You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by vi...@apache.org on 2018/10/25 03:00:54 UTC
[mynewt-core] 03/06: fixes
This is an automated email from the ASF dual-hosted git repository.
vipulrahane pushed a commit to branch dma_i2c
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 1f81ac8d930c6f6acc3500cd578382c1fab86869
Author: Vipul Rahane <vi...@runtime.io>
AuthorDate: Mon Oct 22 13:36:03 2018 -0700
fixes
---
hw/drivers/bq27z561/src/bq27z561.c | 8 +-
hw/drivers/sensors/lis2dw12/src/lis2dw12.c | 14 ++--
hw/hal/include/hal/hal_i2c.h | 26 +++++--
hw/mcu/nordic/nrf52xxx/src/hal_i2c.c | 116 +++++++++++++++++------------
hw/mcu/nordic/nrf52xxx/syscfg.yml | 4 +
5 files changed, 100 insertions(+), 68 deletions(-)
diff --git a/hw/drivers/bq27z561/src/bq27z561.c b/hw/drivers/bq27z561/src/bq27z561.c
index 2ab06dd..9494d3b 100644
--- a/hw/drivers/bq27z561/src/bq27z561.c
+++ b/hw/drivers/bq27z561/src/bq27z561.c
@@ -142,7 +142,7 @@ bq27z561_rd_std_reg_byte(struct bq27z561 *dev, uint8_t reg, uint8_t *val)
}
- rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
+ rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 1,
MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
if (rc != 0) {
BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
@@ -178,7 +178,7 @@ bq27z561_rd_std_reg_word(struct bq27z561 *dev, uint8_t reg, uint16_t *val)
return rc;
}
- rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
+ rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 1,
MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
if (rc != 0) {
BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
@@ -353,7 +353,7 @@ bq27x561_rd_alt_mfg_cmd(struct bq27z561 *dev, uint16_t cmd, uint8_t *val,
i2c.len = 1;
i2c.buffer = tmpbuf;
- rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
+ rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 1,
MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
if (rc != 0) {
BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", tmpbuf[0]);
@@ -459,7 +459,7 @@ bq27x561_rd_flash(struct bq27z561 *dev, uint16_t addr, uint8_t *buf, int buflen)
i2c.len = 1;
i2c.buffer = tmpbuf;
- rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
+ rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 1,
MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
if (rc != 0) {
BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", tmpbuf[0]);
diff --git a/hw/drivers/sensors/lis2dw12/src/lis2dw12.c b/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
index bee8cf6..02deaab 100644
--- a/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
+++ b/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
@@ -235,8 +235,8 @@ lis2dw12_i2c_writelen(struct sensor_itf *itf, uint8_t addr, uint8_t *buffer,
rc = i2cn_master_write(itf->si_num, &data_struct, MYNEWT_VAL(LIS2DW12_I2C_TIMEOUT_TICKS), 1,
MYNEWT_VAL(LIS2DW12_I2C_RETRIES));
if (rc) {
- LIS2DW12_LOG(ERROR, "I2C access failed at address 0x%02X\n",
- data_struct.address);
+ LIS2DW12_LOG(ERROR, "I2C write failed err=%d at addr:0x%02X:0x%02X\n",
+ rc, data_struct.address, payload[0]);
STATS_INC(g_lis2dw12stats, write_errors);
goto err;
}
@@ -290,7 +290,7 @@ lis2dw12_spi_writelen(struct sensor_itf *itf, uint8_t addr, uint8_t *payload,
rc = hal_spi_tx_val(itf->si_num, payload[i]);
if (rc == 0xFFFF) {
rc = SYS_EINVAL;
- LIS2DW12_LOG(ERROR, "SPI_%u write failed addr:0x%02X:0x%02X\n",
+ LIS2DW12_LOG(ERROR, "SPI_%u write failed addr:0x%02X\n",
itf->si_num, addr);
STATS_INC(g_lis2dw12stats, write_errors);
goto err;
@@ -365,8 +365,8 @@ lis2dw12_i2c_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t *buffer,
rc = i2cn_master_write(itf->si_num, &data_struct, MYNEWT_VAL(LIS2DW12_I2C_TIMEOUT_TICKS), 1,
MYNEWT_VAL(LIS2DW12_I2C_RETRIES));
if (rc) {
- LIS2DW12_LOG(ERROR, "I2C access failed at address 0x%02X\n",
- itf->si_addr);
+ LIS2DW12_LOG(ERROR, "I2C %u write failed at address 0x%02X:0x%02X\n",
+ itf->si_num, itf->si_addr, reg);
STATS_INC(g_lis2dw12stats, write_errors);
return rc;
}
@@ -378,8 +378,8 @@ lis2dw12_i2c_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t *buffer,
MYNEWT_VAL(LIS2DW12_I2C_RETRIES));
if (rc) {
- LIS2DW12_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
- itf->si_addr, reg);
+ LIS2DW12_LOG(ERROR, "I2C %u read failed at address 0x%02X:0x%02X\n",
+ itf->si_num, itf->si_addr, reg);
STATS_INC(g_lis2dw12stats, read_errors);
}
diff --git a/hw/hal/include/hal/hal_i2c.h b/hw/hal/include/hal/hal_i2c.h
index 50fd1df..0d1173e 100644
--- a/hw/hal/include/hal/hal_i2c.h
+++ b/hw/hal/include/hal/hal_i2c.h
@@ -64,30 +64,40 @@ extern "C" {
/*** I2C status codes (0=success). */
-/** Unknown error. */
+/* Unknown error. */
#define HAL_I2C_ERR_UNKNOWN 1
-/** Invalid argument. */
+/* Invalid argument. */
#define HAL_I2C_ERR_INVAL 2
-/** MCU failed to report result of I2C operation. */
+/* MCU failed to report result of I2C operation. */
#define HAL_I2C_ERR_TIMEOUT 3
-/** Slave responded to address with NACK. */
+/* Slave responded to address with NACK. */
#define HAL_I2C_ERR_ADDR_NACK 4
-/** Slave responded to data byte with NACK. */
+/* Slave responded to data byte with NACK. */
#define HAL_I2C_ERR_DATA_NACK 5
-/** Overrun error */
+/* Overrun error */
#define HAL_I2C_ERR_OVERRUN 6
-/** I2C bus in suspended state, but last op was 0 */
+/* I2C bus in suspended state, but last op was 0 */
#define HAL_I2C_ERR_SUSPEND 7
-/** I2C bus in stopped state, but last op was 1 */
+/* I2C bus in stopped state, but last op was 1 */
#define HAL_I2C_ERR_STOP 8
+/* At boot up or on facing an error I2C bus in
+ * suspended state
+ */
+#define HAL_I2C_ERR_INIT_SUSPEND 9
+
+/* At boot up or on facing an error I2C bus in
+ * suspended state
+ */
+#define HAL_I2C_ERR_INIT_STOP 10
+
/**
* When sending a packet, use this structure to pass the arguments.
*/
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
index 10e59d7..133e330 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
@@ -33,18 +33,6 @@
#define I2C_WRITE 0
#define I2C_READ 1
-#define WAIT_FOR_EVT(__r, __e, __op)\
- while (!(__r)->EVENTS_####__e) {\
- console_printf("while op: %u macro: STOPPED: %lu SUSPENDED: %lu LASTTX: %lu LASTRX: %lu\n",\
- __op, regs->EVENTS_STOPPED, regs->EVENTS_SUSPENDED, regs->EVENTS_LASTTX,\
- regs->EVENTS_LASTRX);\
- now = os_time_get();\
- if (OS_TIME_TICK_GT(now, abs_timo)) {\
- rc = HAL_I2C_ERR_TIMEOUT;\
- goto err;\
- }\
- }
-
#define NRF52_HAL_I2C_MAX (2)
#define NRF52_SCL_PIN_CONF \
@@ -70,6 +58,7 @@ struct nrf52_hal_i2c {
* transaction actually put the I2C bus in the suspended state
*/
int nhi_prev_last_op;
+ uint32_t nhi_freq;
};
#if MYNEWT_VAL(I2C_0)
@@ -322,7 +311,13 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
regs->PSEL.SCL = cfg->scl_pin;
regs->PSEL.SDA = cfg->sda_pin;
+#if MYNEWT_VAL(NRF52_HANDLE_ANOMALY_109)
+ i2c->nhi_freq = freq;
+ regs->FREQUENCY = 0;
+#else
regs->FREQUENCY = freq;
+#endif
+ regs->ADDRESS = 0;
regs->ENABLE = TWIM_ENABLE_ENABLE_Enabled;
i2c->nhi_prev_last_op = -1;
@@ -331,64 +326,79 @@ err:
return (rc);
}
+static void
+hal_i2c_handle_anomaly_109(NRF_TWIM_Type *regs, uint32_t prev_freq, uint8_t address)
+{
+ if (regs->FREQUENCY == 0) {
+ regs->ENABLE = TWIM_ENABLE_ENABLE_Disabled;
+ regs->ENABLE = TWIM_ENABLE_ENABLE_Enabled;
+ regs->ADDRESS = address;
+ regs->FREQUENCY = prev_freq;
+ regs->TASKS_STARTTX = 1;
+ }
+}
+
/*
* Starts an I2C transaction either read or write using EasyDMA/TWIM
*/
static int
hal_i2c_handle_transact_start(struct nrf52_hal_i2c *i2c, uint8_t op,
- uint32_t abs_timo)
+ os_time_t abs_timo, uint8_t address)
{
NRF_TWIM_Type *regs;
- uint32_t now;
+ os_time_t now;
int rc;
regs = i2c->nhi_regs;
regs->EVENTS_ERROR = 0;
+ regs->EVENTS_STOPPED = 0;
/* If a transaction was previously suspended, resume it */
if (regs->EVENTS_SUSPENDED) {
regs->TASKS_RESUME = 1;
+ regs->EVENTS_SUSPENDED = 0;
+ return 0;
}
- regs->EVENTS_STOPPED = 0;
- regs->EVENTS_SUSPENDED = 0;
if (op == I2C_WRITE) {
/* Start an I2C transmit transaction */
regs->TASKS_STARTTX = 1;
- WAIT_FOR_EVT(regs, TXSTARTED, op);
+
+#if MYNEWT_VAL(NRF52_HANDLE_ANOMALY_109)
+ while (!regs->EVENTS_TXSTARTED) {
+ now = os_time_get();
+ if (OS_TIME_TICK_GT(now, abs_timo)) {
+ rc = HAL_I2C_ERR_TIMEOUT;
+ return rc;
+ }
+ }
+
regs->EVENTS_TXSTARTED = 0;
+ if (!regs->FREQUENCY) {
+ hal_i2c_handle_anomaly_109(regs, i2c->nhi_freq, address);
+ regs->EVENTS_TXSTARTED = 0;
+ }
+#endif
} else {
+ if (!regs->FREQUENCY) {
+ regs->FREQUENCY = i2c->nhi_freq;
+ }
/* Start an I2C receive transaction */
regs->TASKS_STARTRX = 1;
- WAIT_FOR_EVT(regs, RXSTARTED, op);
- regs->EVENTS_RXSTARTED = 0;
}
return 0;
-err:
- return rc;
}
static int
hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint8_t op, uint32_t start,
- uint32_t abs_timo, uint8_t last_op)
+ os_time_t abs_timo, uint8_t last_op)
{
int rc;
uint32_t evt;
os_time_t now;
- if (last_op) {
- /* this is to take care of clock stretches as per the datasheet */
- if (regs->EVENTS_SUSPENDED) {
- /* If there is a clock stretch, the event would be suspended for
- * that TWIM interface, it would need to be resumed to finish the
- * transaction
- */
- regs->TASKS_RESUME = 1;
- }
- }
-
while(1) {
/*
* Use last_op as the determining factor for the type of event to be
@@ -402,8 +412,11 @@ hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint8_t op, uint32_t start,
if (evt) {
if (&evt == ®s->EVENTS_STOPPED) {
- regs->EVENTS_LASTTX = 0;
- regs->EVENTS_LASTRX = 0;
+#if MYNEWT_VAL(NRF52_HANDLE_ANOMALY_109)
+ if (regs->FREQUENCY) {
+ regs->FREQUENCY = 0;
+ }
+#endif
}
break;
}
@@ -412,11 +425,6 @@ hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint8_t op, uint32_t start,
goto err;
}
- console_printf("while end: last_op: %u STOPPED: %lu SUSPENDED: %lu"
- "LASTTX: %lu LASTRX: %lu\n", last_op, regs->EVENTS_STOPPED,
- regs->EVENTS_SUSPENDED, regs->EVENTS_LASTTX,
- regs->EVENTS_LASTRX);
-
now = os_time_get();
if (OS_TIME_TICK_GT(now, abs_timo)) {
rc = HAL_I2C_ERR_TIMEOUT;
@@ -445,8 +453,7 @@ hal_i2c_bus_error_detect(struct nrf52_hal_i2c *i2c)
rc = HAL_I2C_ERR_SUSPEND;
goto err;
} else if ((i2c->nhi_prev_last_op == 1 &&
- !regs->EVENTS_STOPPED) && regs->EVENTS_SUSPENDED) {
-
+ (!regs->EVENTS_STOPPED || regs->EVENTS_SUSPENDED))) {
/*
* return HAL_I2C_ERR_STOP if previous last_op was 1 and
* the bus is not in the stopped state or in initial state
@@ -454,20 +461,29 @@ hal_i2c_bus_error_detect(struct nrf52_hal_i2c *i2c)
*/
rc = HAL_I2C_ERR_STOP;
goto err;
+ } else if (i2c->nhi_prev_last_op == -1 &&
+ (regs->EVENTS_STOPPED || regs->EVENTS_SUSPENDED)) {
+ if (regs->EVENTS_STOPPED) {
+ rc = HAL_I2C_ERR_INIT_STOP;
+ } else {
+ rc = HAL_I2C_ERR_INIT_SUSPEND;
+ }
+ goto err;
}
return 0;
err:
- console_printf("i2c failure: rc:%u evt_stopped: %lu evt_suspended: %lu\n",
- rc, regs->EVENTS_STOPPED, regs->EVENTS_SUSPENDED);
return rc;
}
/* Handle errors returned from the TWIM peripheral along with timeouts */
static int
-hal_i2c_handle_errors(NRF_TWIM_Type *regs, int rc)
+hal_i2c_handle_errors(struct nrf52_hal_i2c *i2c, int rc, os_time_t abs_timo)
{
int nrf_status;
+ NRF_TWIM_Type *regs;
+
+ regs = i2c->nhi_regs;
regs->TASKS_RESUME = 1;
regs->TASKS_STOP = 1;
@@ -487,6 +503,8 @@ hal_i2c_handle_errors(NRF_TWIM_Type *regs, int rc)
regs->ENABLE = TWIM_ENABLE_ENABLE_Disabled;
hal_i2c_clear_bus(regs->PSEL.SCL, regs->PSEL.SDA);
regs->ENABLE = TWIM_ENABLE_ENABLE_Enabled;
+ i2c->nhi_prev_last_op = -1;
+ regs->EVENTS_STOPPED = 0;
}
return rc;
@@ -548,7 +566,7 @@ hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
}
/* Starts an I2C transaction using TWIM/EasyDMA */
- rc = hal_i2c_handle_transact_start(i2c, I2C_WRITE, start + timo);
+ rc = hal_i2c_handle_transact_start(i2c, I2C_WRITE, start + timo, pdata->address);
if (rc) {
goto err;
}
@@ -564,7 +582,7 @@ hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
return 0;
err:
- return hal_i2c_handle_errors(regs, rc);
+ return hal_i2c_handle_errors(i2c, rc, start + timo);
}
int
@@ -613,7 +631,7 @@ hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
}
/* Starts an I2C transaction using TWIM/EasyDMA */
- rc = hal_i2c_handle_transact_start(i2c, I2C_READ, start + timo);
+ rc = hal_i2c_handle_transact_start(i2c, I2C_READ, start + timo, pdata->address);
if (rc) {
goto err;
}
@@ -629,7 +647,7 @@ hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
return 0;
err:
- return hal_i2c_handle_errors(regs, rc);
+ return hal_i2c_handle_errors(i2c, rc, start + timo);
}
int
diff --git a/hw/mcu/nordic/nrf52xxx/syscfg.yml b/hw/mcu/nordic/nrf52xxx/syscfg.yml
index 2028a3c..f90c32c 100644
--- a/hw/mcu/nordic/nrf52xxx/syscfg.yml
+++ b/hw/mcu/nordic/nrf52xxx/syscfg.yml
@@ -394,6 +394,10 @@ syscfg.defs:
- "!XTAL_RC"
- "!XTAL_32768"
+ NRF52_HANDLE_ANOMALY_109:
+ description: 'TWIM NRF52XXX anomaly 109 fix'
+ value: 1
+
syscfg.restrictions:
- "MCU_NRF52832 ^^ MCU_NRF52840"
- "!I2C_0 || (I2C_0_PIN_SCL && I2C_0_PIN_SDA)"