This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

TWI Switch between easyDMA and normal read

Hi,

I am reading a BMX055 via I2C which consists of three sensors with three addresses. I got the easyDMA running to read 10 times the gyro using the PPI and the data ready interrupt. Now after 10 readings I want to read once the accelerometer and the magnetometer. But if I try to read with

nrf_drv_twi_tx(&m_twi_instance, address, &reg, 1, false); nrf_drv_twi_rx(&m_twi_instance, address, p_data, length);

I get the NRF_ERROR_BUSY which means that the TWIM is still in use. So here is my question how can I switch from easyDMA reading to normal reading.

Thanks and kind regards,

C.

Parents
  • No it is the following problem: I start a easydma transfer for 10 gyro samples with:

    // Disable the TWIM module while we reconfigure it
    NRF_TWIM0->ENABLE = TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos;
    NRF_TWIM0->SHORTS = 0;
    NVIC_DisableIRQ(SPI0_TWI0_IRQn);
    NVIC_ClearPendingIRQ(SPI0_TWI0_IRQn);
    
    // Configure a gpiote channel to generate an event on a polarity change from
    // low to high generated the BMX interrupt pin.
    uint8_t gpiote_ch_bmx_int_event = 0;
    NRF_GPIOTE->CONFIG[gpiote_ch_bmx_int_event] = ( (GPIOTE_CONFIG_MODE_Event   << GPIOTE_CONFIG_MODE_Pos) |
                                                    (BMX_INT_PIN                << GPIOTE_CONFIG_PSEL_Pos) |
                                                    (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos));
    
    NRF_TWIM0->PSEL.SCL = BMX_TWI_SCL_PIN;
    NRF_TWIM0->PSEL.SDA = BMX_TWI_SDA_PIN;
    NRF_TWIM0->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K400;
    
    // Load TWI TX buffer into TWI module. Set number of bytes to write pr transfer, max count, to one.
    // Disable the EasyDMA list functionality for TWI TX.
    NRF_TWIM0->TXD.PTR = (uint32_t)&p_tx_gyro_buffer;
    NRF_TWIM0->TXD.MAXCNT = 1;
    NRF_TWIM0->TXD.LIST = TWIM_TXD_LIST_LIST_Disabled << TWIM_TXD_LIST_LIST_Pos;
    
    // Point to TWI RX buffer. Set number of bytes to read pr transfer, max count, to TWIM_RX_BUF_WIDTH.
    // Disable the EasyDMA list functionality for TWI TX
    NRF_TWIM0->RXD.PTR = (uint32_t)&p_rx_gyro_buffer;
    NRF_TWIM0->RXD.MAXCNT = TWIM_RX_BUF_WIDTH_GYRO_ONLY;
    NRF_TWIM0->RXD.LIST = TWIM_RXD_LIST_LIST_ArrayList << TWIM_RXD_LIST_LIST_Pos;
    
    // Make sure that BMX address is set
    NRF_TWIM0->ADDRESS = BMX055_GYRO_ADDRESS;
    // Enable shortcuts that starts a read right after a write and sends a stop condition after last TWI read
    NRF_TWIM0->SHORTS = (TWIM_SHORTS_LASTTX_STARTRX_Enabled << TWIM_SHORTS_LASTTX_STARTRX_Pos) |
                        (TWIM_SHORTS_LASTRX_STOP_Enabled << TWIM_SHORTS_LASTRX_STOP_Pos);
    
    // Configure PPI channel
    // Use BMX interrupt pin as event
    // Start timer 0 on event to count number of transfers
    // Also start TWI transfers on event
    // Enable PPI channel
    NRF_PPI->CH[0].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[gpiote_ch_bmx_int_event];
    NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TIMER0->TASKS_COUNT;
    NRF_PPI->FORK[0].TEP = (uint32_t)&NRF_TWIM0->TASKS_STARTTX;
    
    // Enable the TWIM module
    NRF_TWIM0->ENABLE = TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos;
    

    then when I get the interrupt of the timer I do the following:

    // Clear timer event
    NRF_TIMER0->EVENTS_COMPARE[0] = 0;
    // Reset the TWIM RX pointer to initial address of RX buffer
    NRF_TWIM0->RXD.PTR = (uint32_t)&p_rx_gyro_buffer;
    // Toggle a LED for show
    nrf_gpio_pin_toggle(LED_1);
    // Set flag to notify main context of the new data available
    twi_gyro_transfers_complete = true;
    

    Now I want at the same interrupt read the accelerometer and magnetometer only once and then return with the gyro reading. But if I try either reading or writing during the interrupt routine or in the main after reading the flag I get NRF_ERROR_BUSY.

Reply
  • No it is the following problem: I start a easydma transfer for 10 gyro samples with:

    // Disable the TWIM module while we reconfigure it
    NRF_TWIM0->ENABLE = TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos;
    NRF_TWIM0->SHORTS = 0;
    NVIC_DisableIRQ(SPI0_TWI0_IRQn);
    NVIC_ClearPendingIRQ(SPI0_TWI0_IRQn);
    
    // Configure a gpiote channel to generate an event on a polarity change from
    // low to high generated the BMX interrupt pin.
    uint8_t gpiote_ch_bmx_int_event = 0;
    NRF_GPIOTE->CONFIG[gpiote_ch_bmx_int_event] = ( (GPIOTE_CONFIG_MODE_Event   << GPIOTE_CONFIG_MODE_Pos) |
                                                    (BMX_INT_PIN                << GPIOTE_CONFIG_PSEL_Pos) |
                                                    (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos));
    
    NRF_TWIM0->PSEL.SCL = BMX_TWI_SCL_PIN;
    NRF_TWIM0->PSEL.SDA = BMX_TWI_SDA_PIN;
    NRF_TWIM0->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K400;
    
    // Load TWI TX buffer into TWI module. Set number of bytes to write pr transfer, max count, to one.
    // Disable the EasyDMA list functionality for TWI TX.
    NRF_TWIM0->TXD.PTR = (uint32_t)&p_tx_gyro_buffer;
    NRF_TWIM0->TXD.MAXCNT = 1;
    NRF_TWIM0->TXD.LIST = TWIM_TXD_LIST_LIST_Disabled << TWIM_TXD_LIST_LIST_Pos;
    
    // Point to TWI RX buffer. Set number of bytes to read pr transfer, max count, to TWIM_RX_BUF_WIDTH.
    // Disable the EasyDMA list functionality for TWI TX
    NRF_TWIM0->RXD.PTR = (uint32_t)&p_rx_gyro_buffer;
    NRF_TWIM0->RXD.MAXCNT = TWIM_RX_BUF_WIDTH_GYRO_ONLY;
    NRF_TWIM0->RXD.LIST = TWIM_RXD_LIST_LIST_ArrayList << TWIM_RXD_LIST_LIST_Pos;
    
    // Make sure that BMX address is set
    NRF_TWIM0->ADDRESS = BMX055_GYRO_ADDRESS;
    // Enable shortcuts that starts a read right after a write and sends a stop condition after last TWI read
    NRF_TWIM0->SHORTS = (TWIM_SHORTS_LASTTX_STARTRX_Enabled << TWIM_SHORTS_LASTTX_STARTRX_Pos) |
                        (TWIM_SHORTS_LASTRX_STOP_Enabled << TWIM_SHORTS_LASTRX_STOP_Pos);
    
    // Configure PPI channel
    // Use BMX interrupt pin as event
    // Start timer 0 on event to count number of transfers
    // Also start TWI transfers on event
    // Enable PPI channel
    NRF_PPI->CH[0].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[gpiote_ch_bmx_int_event];
    NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TIMER0->TASKS_COUNT;
    NRF_PPI->FORK[0].TEP = (uint32_t)&NRF_TWIM0->TASKS_STARTTX;
    
    // Enable the TWIM module
    NRF_TWIM0->ENABLE = TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos;
    

    then when I get the interrupt of the timer I do the following:

    // Clear timer event
    NRF_TIMER0->EVENTS_COMPARE[0] = 0;
    // Reset the TWIM RX pointer to initial address of RX buffer
    NRF_TWIM0->RXD.PTR = (uint32_t)&p_rx_gyro_buffer;
    // Toggle a LED for show
    nrf_gpio_pin_toggle(LED_1);
    // Set flag to notify main context of the new data available
    twi_gyro_transfers_complete = true;
    

    Now I want at the same interrupt read the accelerometer and magnetometer only once and then return with the gyro reading. But if I try either reading or writing during the interrupt routine or in the main after reading the flag I get NRF_ERROR_BUSY.

Children
No Data
Related