On SDK16.0.0 + Mesh SDK 4.1.0
I am getting random softdevice asserts when running our application with TWI accessing a temperature/humidity sensor (HTU21D/HPP845). Sometimes within a few minutes and sometimes it takes hours.
<t: 16498108>, app_error_weak.c, 96, Softdevice assert: 154516:0
I tried both blocking and non-blocking with a handler. I set .interrupt_priority = APP_IRQ_PRIORITY_LOW.
static void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context) { //Not really being used } static void twi_init(void) { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "twi_init()\n"); ret_code_t err_code; const nrf_drv_twi_config_t twi_config = { .scl = I2C_SCL_PIN, .sda = I2C_SDA_PIN, .frequency = NRF_DRV_TWI_FREQ_400K, .interrupt_priority = APP_IRQ_PRIORITY_LOW, .clear_bus_init = false }; err_code = nrf_drv_twi_init(&m_twi, &twi_config, twi_handler, NULL); //event handler, non-blocking mode //err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL); //no event handler, blocking mode ERROR_CHECK(err_code); nrf_drv_twi_enable(&m_twi); } static void read_hpp845(void) { ret_code_t ret_code = 0; uint8_t command_address; uint16_t rawHumidity; uint16_t rawTemperature; static uint8_t hpp845_stage = 0; switch(hpp845_stage) { case 0: //start_hpp845_humidity command_address = HPP845_START_HUMIDITY_ADDR; ret_code = nrf_drv_twi_tx(&m_twi, HPP845_ADDR, &command_address, 1, false); break; case 1: //fetch_hpp845_humidity memset(i2cBuffer_RX, 0, sizeof(i2cBuffer_RX)); ret_code = nrf_drv_twi_rx(&m_twi, HPP845_ADDR, i2cBuffer_RX, 3); //Get raw humidity data break; case 2: //continue fetch_hpp845_humidity rawHumidity = ((unsigned int)i2cBuffer_RX[0] << 8) | ((unsigned int)i2cBuffer_RX[1]); float tempRH = rawHumidity / (float)65536; float rh = -6 + (125 * tempRH); if(rh < 0.0) { rh = 0.0; } else if(rh > 100.0) { rh = 100.0; } hpp845_humidity = (uint8_t)rh; __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "HPP845 Humidity: %u\n", hpp845_humidity); break; case 3: //start_hpp845_temperature command_address = HPP845_START_TEMPERATURE_ADDR; ret_code = nrf_drv_twi_tx(&m_twi, HPP845_ADDR, &command_address, 1, false); break; case 4: //fetch_hpp845_temperature memset(i2cBuffer_RX, 0, sizeof(i2cBuffer_RX)); ret_code = nrf_drv_twi_rx(&m_twi, HPP845_ADDR, i2cBuffer_RX, 3); //Get raw temperature data break; case 5: //continue fetch_hpp845_temperature rawTemperature = ((unsigned int)i2cBuffer_RX[0] << 8) | ((unsigned int)i2cBuffer_RX[1]); float tempTemperature = (float)rawTemperature / (float)65536; float temperatureC = (float)-46.85 + ((float)175.72 *(float)tempTemperature); //set range limits if(temperatureC < -40.0) { temperatureC = -40.0; } else if(temperatureC > 125.0) { temperatureC = 125.0; } hpp845_temperature = (uint16_t)((temperatureC*3.0) + 120.0); //in one-third degC and offset by 120 to work in uint16_t __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "HPP845 Temperature: %u in one-third degC (offset +120)\n", hpp845_temperature); break; default: __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "ERROR: hpp845_stage out-of-range: %u\n", hpp845_stage); hpp845_stage = 0; //reset, should never get here break; } if((ret_code == 0) && (hpp845_stage != 5)) { hpp845_stage++; } else if(ret_code != 0) { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "ERROR: hpp845_stage: %u, ret_code: %u\n", hpp845_stage, ret_code); hpp845_stage = 0; //reset, something went wrong } else { hpp845_stage = 0; //reset, need to cycle back to start } }
I am calling read_hpp845() from an app_timer and I am only running one TWI instruction per app_timer cycle. If I comment out the call, the application works fine. The app_timer is set at 100ms and so I am not even using the twi event handler to check that it was successful, for now I am just assuming that it was.
How do I figure out what is causing the assert?
Thanks.