I am in the initial phases of porting an arduino project using the NRF52832 to the Nordic SDK (14.2 for the moment) and am running into issues when using TWIM and an event handler. This stage of my port effort is based on the twi_sensor example and I have made the necessary changes to my sensor library to successfully read values from my accelerometer in blocking mode. I am now trying to implement the non-blocking operation and am having difficulty with the TWI event handler running to completion.
If I place a breakpoint in the event handler on NRF_DRV_TWI_EVT_DONE and the function I have initiating the TWI RX/TX operations and step through them I have noticed the following:
- The library function call to read from the sensor (consisting of both a TX and RX operation) first initiates a NRF_DRV_TWI_XFER_TX event xfer type and passes through the handler. This is expected.
- The subsequent RX operation to read the selected register from above is called, passes through the event handler, calls the data handler to output to the console, and returns. What I am seeing at this point of stepping through however is that I am not receiving values from the sensor. This process does run through the event handler though.
I have tried changing the event handler to handle RX and TX event separately and changed the interrupt priority in the TWI config to no avail. I suppose it is worth mentioning that I am using an Adafruit NRF52 board and Visual Studio + VisualGDB. As I mentioned before, I do have TWI working in blocking mode and have been getting expected readings from my sensor so I am hesitant to blame the board or the dev environment. I am planning to move to SDK15 as soon as a BSP is created for VisualGDB but I do not think that has any bearing on the issue I am facing. Relevant code is included below.
main.cpp
#include <stdio.h> #include "boards.h" #include "app_util_platform.h" #include "app_error.h" #include "nrf_delay.h" #include "nrf_drv_twi.h" #include "H3LIS331DL.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" /* TWI instance ID. */ #define TWI_INSTANCE_ID 0 /* TWI instance. */ static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID); static volatile bool m_xfer_rx_done = false; int16_t x, y, z; static H3LIS331DL h3lis; __STATIC_INLINE void accel_data_handler(int16_t x, int16_t y, int16_t z) { NRF_LOG_INFO("X: %d \t Y: %d \t Z: %d \n", x, y, z); } static void read_sensor_data() { m_xfer_rx_done = false; h3lis.readXYZ(&x, &y, &z); // accel_data_handler(x, y, z); } void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context) { switch (p_event->type) { case NRF_DRV_TWI_EVT_DONE: if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX) { accel_data_handler(x, y, z); } m_xfer_rx_done = true; break; case NRF_DRV_TWI_EVT_ADDRESS_NACK: break; case NRF_DRV_TWI_EVT_DATA_NACK: break; default: break; } } /** * @brief TWI initialization. */ void twi_init(void) { ret_code_t err_code; const nrf_drv_twi_config_t twi_config = { .scl = ARDUINO_SCL_PIN, .sda = ARDUINO_SDA_PIN, .frequency = NRF_TWI_FREQ_100K, .interrupt_priority = APP_IRQ_PRIORITY_LOW, .clear_bus_init = false }; err_code = nrf_drv_twi_init(&m_twi, &twi_config, twi_handler, NULL); APP_ERROR_CHECK(err_code); nrf_drv_twi_enable(&m_twi); } /** * @brief Function for main application entry. */ int main(void) { ret_code_t err_code; APP_ERROR_CHECK(NRF_LOG_INIT(NULL)); NRF_LOG_DEFAULT_BACKENDS_INIT(); NRF_LOG_FLUSH(); twi_init(); h3lis.init(&m_twi, H3LIS331DL_ODR_100Hz, H3LIS331DL_NORMAL, H3LIS331DL_FULLSCALE_2); //int16_t x, y, z; while(true) { nrf_delay_ms(500); do { __WFE(); } while (m_xfer_rx_done == false); read_sensor_data(); NRF_LOG_FLUSH(); } }
H3LIS331DL.cpp read and write functions. _twi_inst passed from main.
uint8_t H3LIS331DL::readReg(uint8_t deviceAddr, uint8_t Reg, uint8_t* Data, uint8_t len) { ret_code_t err_code; err_code = nrf_drv_twi_tx(_twi_inst, deviceAddr, &Reg, 1, true); if (err_code == NRF_SUCCESS) { nrf_drv_twi_rx(_twi_inst, deviceAddr, Data, len); } else { return MEMS_ERROR; } return MEMS_SUCCESS; } // ///******************************************************************************* //* Function Name : writeReg //* Description : Generic Writing function. It must be full filled with either //* : I2C or SPI writing function //* Input : Register Address, Data to be written //* Output : None //* Return : Status [MEMS_ERROR, MEMS_SUCCESS] //*******************************************************************************/ uint8_t H3LIS331DL::writeReg(uint8_t deviceAddr, uint8_t WriteAddr, uint8_t Data) { ret_code_t err_code; uint8_t dat[2]; dat[0] = WriteAddr; dat[1] = Data; err_code = nrf_drv_twi_tx(_twi_inst, deviceAddr, dat, sizeof(dat), true); if (err_code != NRF_SUCCESS) { return MEMS_ERROR; } return MEMS_SUCCESS; }