Repository: incubator-mynewt-core Updated Branches: refs/heads/sterly_refactor 30da46584 -> e22285ca8
add I2C HAL. Update I2C HAL to remove vestigates of system_device_id, and convert docs to doxygen format. Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/e22285ca Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/e22285ca Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/e22285ca Branch: refs/heads/sterly_refactor Commit: e22285ca8e12ec9c0a31689729f5c2b4d6f384a1 Parents: 30da465 Author: Sterling Hughes <[email protected]> Authored: Thu Aug 4 14:14:32 2016 -0700 Committer: Sterling Hughes <[email protected]> Committed: Thu Aug 4 14:14:32 2016 -0700 ---------------------------------------------------------------------- hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h | 2 +- hw/hal/include/hal/hal_i2c.h | 92 +++++++---- hw/hal/include/hal/hal_spi.h | 6 +- hw/mcu/nordic/nrf52xxx/src/hal_i2c.c | 188 +++++++++++++++++++++++ 4 files changed, 252 insertions(+), 36 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e22285ca/hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h ---------------------------------------------------------------------- diff --git a/hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h b/hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h index 320dd87..d90fc99 100644 --- a/hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h +++ b/hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h @@ -314,7 +314,7 @@ #define TWI0_INSTANCE_INDEX 0 #endif -#define TWI1_ENABLED 0 +#define TWI1_ENABLED 1 #if (TWI1_ENABLED == 1) #define TWI1_USE_EASY_DMA 0 http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e22285ca/hw/hal/include/hal/hal_i2c.h ---------------------------------------------------------------------- diff --git a/hw/hal/include/hal/hal_i2c.h b/hw/hal/include/hal/hal_i2c.h index 876e287..e8c02db 100644 --- a/hw/hal/include/hal/hal_i2c.h +++ b/hw/hal/include/hal/hal_i2c.h @@ -27,7 +27,8 @@ extern "C" { #endif -/* This is the API for an i2c bus. Currently, this is a master API +/** + * This is the API for an i2c bus. Currently, this is a master API * allowing the mynewt device to function as an I2C master. * * A slave API is pending for future release @@ -47,9 +48,9 @@ extern "C" { * hal_i2c_end(); */ -struct hal_i2c; - -/* when sending a packet, use this structure to pass the arguments */ +/** + * when sending a packet, use this structure to pass the arguments. + */ struct hal_i2c_master_data { uint8_t address; /* destination address */ /* a I2C address has 7 bits. In the protocol these @@ -64,53 +65,82 @@ struct hal_i2c_master_data { uint8_t *buffer; /* buffer space to hold the transmit or receive */ }; -/* Initialize a new i2c device with the I2C number. - * Returns a pointer to the i2c device or NULL on error +/** + * Initialize a new i2c device with the I2C number. + * + * @param i2c_num The number of the I2C device being initialized + * @param scl_pin The GPIO pin to use for clock + * @param sda_pin The GPIO pin to use for data + * @param i2c_frequency The I2C frequency to use, in KHz + * + * @return 0 on success, and non-zero error code on failure */ -struct hal_i2c *hal_i2c_init(uint8_t i2c_num); +int hal_i2c_init(uint8_t i2c_num, int scl_pin, int sda_pin, + uint32_t i2c_frequency); -/* Sends a start condition and writes <len> bytes of data on the i2c. +/** + * Sends a start condition and writes <len> bytes of data on the i2c. * This API assumes that you have already called hal_i2c_master_begin - * It will fail if you have not. This API does NOT issue a stop condition. + * It will fail if you have not. This API does NOT issue a stop condition. * You must stop the bus after successful or unsuccessful write attempts. * This API is blocking until an error or NaK occurs. Timeout is platform - * dependent - * Returns 0 on success, negative on failure + * dependent. + * + * @param i2c_num The number of the I2C device being written to + * @param pdata The data to write to the I2C bus + * + * @return 0 on success, and non-zero error code on failure */ -int -hal_i2c_master_write(struct hal_i2c *, struct hal_i2c_master_data *pdata); +int hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata); -/* Sends a start condition and reads <len> bytes of data on the i2c. +/** + * Sends a start condition and reads <len> bytes of data on the i2c. * This API assumes that you have already called hal_i2c_master_begin - * It will fail if you have not. This API does NOT issue a stop condition. + * It will fail if you have not. This API does NOT issue a stop condition. * You must stop the bus after successful or unsuccessful write attempts. * This API is blocking until an error or NaK occurs. Timeout is platform - * dependent - * Returns 0 on success, negative on failure + * dependent. + * + * @param i2c_num The number of the I2C device being written to + * @param pdata The location to place read data + * + * @return 0 on success, and non-zero error code on failure */ -int -hal_i2c_master_read(struct hal_i2c *, struct hal_i2c_master_data *pdata); +int hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata); -/* +/** * Starts an I2C transaction with the driver. This API does not send - * anything over the bus itself + * anything over the bus itself. + * + * @param i2c_num The number of the I2C to begin a transaction on + * + * @return 0 on success, non-zero error code on failure */ -int -hal_i2c_master_begin(struct hal_i2c *); +int hal_i2c_master_begin(uint8_t i2c_num); -/* issues a stop condition on the bus and ends the I2C transaction. +/** + * Issues a stop condition on the bus and ends the I2C transaction. * You must call i2c_master_end for every hal_i2c_master_begin - * API call that succeeds */ -int -hal_i2c_master_end(struct hal_i2c *); + * API call that succeeds. + * + * @param i2c_num The number of the I2C to end a transaction on + * + * @return 0 on success, non-zero error code on failure + */ +int hal_i2c_master_end(uint8_t i2c_num); -/* Probes the i2c bus for a device with this address. THIS API +/** + * Probes the i2c bus for a device with this address. THIS API * issues a start condition, probes the address using a read * command and issues a stop condition. There is no need to call - * hal_i2c_master_begin/end with this method + * hal_i2c_master_begin/end with this method. + * + * @param i2c_num The number of the I2C to probe + * @param address The address to probe for + * + * @return 0 on success, non-zero error code on failure */ -int -hal_i2c_master_probe(struct hal_i2c *, uint8_t address); +int hal_i2c_master_probe(uint8_t i2c_num, uint8_t address); #ifdef __cplusplus } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e22285ca/hw/hal/include/hal/hal_spi.h ---------------------------------------------------------------------- diff --git a/hw/hal/include/hal/hal_spi.h b/hw/hal/include/hal/hal_spi.h index 4ed5aa6..19219a4 100644 --- a/hw/hal/include/hal/hal_spi.h +++ b/hw/hal/include/hal/hal_spi.h @@ -65,8 +65,7 @@ struct hal_spi_settings { struct hal_spi *hal_spi_init(uint8_t spi_num); /* configure the spi., Reutrns 0 on success, negative on error */ -int -hal_spi_config(struct hal_spi *pspi, struct hal_spi_settings *psettings); +int hal_spi_config(struct hal_spi *pspi, struct hal_spi_settings *psettings); /* Do a blocking master spi transfer of one SPI data word. * The data to send is an 8 or 9-bit pattern (depending on configuration) @@ -74,8 +73,7 @@ hal_spi_config(struct hal_spi *pspi, struct hal_spi_settings *psettings); * a 16-bit number to allow up to 9-bit SPI data words. * Returns the data received from the remote device or negative on error. */ -int -hal_spi_master_transfer(struct hal_spi *psdi, uint16_t tx); +int hal_spi_master_transfer(struct hal_spi *psdi, uint16_t tx); #ifdef __cplusplus http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e22285ca/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c ---------------------------------------------------------------------- diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c new file mode 100644 index 0000000..17b841d --- /dev/null +++ b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c @@ -0,0 +1,188 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <hal/hal_i2c.h> + +#include <string.h> +#include <errno.h> + +#include <nrf.h> +#include <nrf_drv_twi.h> + +struct nrf52_hal_i2c { + nrf_drv_twi_t nhi_nrf_master; +}; + +#define NRF52_HAL_I2C_MAX (2) + +#if TWI0_ENABLED +struct nrf52_hal_i2c hal_twi_i2c0; +#endif +#if TWI1_ENABLED +struct nrf52_hal_i2c hal_twi_i2c1; +#endif + +struct nrf52_hal_i2c *nrf52_hal_i2cs[NRF52_HAL_I2C_MAX] = { +#if TWI0_ENABLED + &hal_twi_i2c0, +#else + NULL, +#endif +#if TWI1_ENABLED + &hal_twi_i2c1 +#else + NULL +#endif +}; + +#define NRF52_HAL_I2C_RESOLVE(__n, __v) \ + if ((__n) >= NRF52_HAL_I2C_MAX) { \ + rc = EINVAL; \ + goto err; \ + } \ + (__v) = nrf52_hal_i2cs[(__n)]; \ + if ((__v) == NULL) { \ + rc = EINVAL; \ + goto err; \ + } + +int +hal_i2c_init(uint8_t i2c_num, int scl_pin, int sda_pin, + uint32_t i2c_frequency) +{ + struct nrf52_hal_i2c *i2c; + nrf_drv_twi_config_t cfg; + int rc; + + NRF52_HAL_I2C_RESOLVE(i2c_num, i2c); + + cfg.scl = scl_pin; + cfg.sda = sda_pin; + switch (i2c_frequency) { + case 100: + cfg.frequency = NRF_TWI_FREQ_100K; + break; + case 250: + cfg.frequency = NRF_TWI_FREQ_250K; + break; + case 400: + cfg.frequency = NRF_TWI_FREQ_400K; + break; + default: + rc = EINVAL; + goto err; + } + + rc = nrf_drv_twi_init(&i2c->nhi_nrf_master, &cfg, NULL, NULL); + if (rc != 0) { + goto err; + } + + nrf_drv_twi_enable(&i2c->nhi_nrf_master); + + return (0); +err: + return (rc); +} + +int +hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata) +{ + struct nrf52_hal_i2c *i2c; + int rc; + + NRF52_HAL_I2C_RESOLVE(i2c_num, i2c); + + rc = nrf_drv_twi_tx(&i2c->nhi_nrf_master, pdata->address, pdata->buffer, + pdata->len, true); + if (rc != 0) { + goto err; + } + + return (0); +err: + return (rc); +} + +int +hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata) +{ + struct nrf52_hal_i2c *i2c; + int rc; + + NRF52_HAL_I2C_RESOLVE(i2c_num, i2c); + + rc = nrf_drv_twi_rx(&i2c->nhi_nrf_master, pdata->address, pdata->buffer, + pdata->len); + if (rc != 0) { + goto err; + } + + return (0); +err: + return (rc); +} + +int +hal_i2c_master_begin(uint8_t i2c_num) +{ + return (0); +} + +int +hal_i2c_master_end(uint8_t i2c_num) +{ + struct nrf52_hal_i2c *i2c; + int rc; + + NRF52_HAL_I2C_RESOLVE(i2c_num, i2c); + + /** + * XXX: Nordic doesn't provide a function for generating the stop + * character, and I don't trust issue'ing nrf_drv_twi_tx() with NULL + * data, and 0 length, so directly use the stop task in HAL driver. + * This is subject to break as NRF SDK is updated, as reg.p_twi is + * private, however, seems like it will be reasonably easy to spot. + * Famous last words. + */ + nrf_twi_task_trigger(i2c->nhi_nrf_master.reg.p_twi, NRF_TWI_TASK_STOP); + + return (0); +err: + return (rc); +} + +int +hal_i2c_master_probe(uint8_t i2c_num, uint8_t address) +{ + struct nrf52_hal_i2c *i2c; + uint8_t buf; + int rc; + + NRF52_HAL_I2C_RESOLVE(i2c_num, i2c); + + rc = nrf_drv_twi_rx(&i2c->nhi_nrf_master, address, &buf, 1); + if (rc != 0) { + goto err; + } + + return (0); +err: + return (rc); +}
