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

TWI - Reading more that 255 packet size

Hi All,

I have looked through the devzone and cannot find a solution to this. I am using the nRF52832 SDK 15.2. Working with a BNO080 IMU over TWI.

I need to read more than 255 byte packet size (276 bytes) in one pass from the sensor upon power up. The BNO080 must upload all of this data before sending IMU data.

when i try reading one byte at a time in a loop, it does not work.

Is there any way to do this?

Regards,

Zoran

Parents Reply Children
  • Hello Dmitry,
    Thank you for the feedback. I was wondering if you could please help me to figure out how to implement this on the twi_receive_byte function? I have tried but without any success that i can see on the logic analyzer.

    Once this is implemented, do i need to send 2 consecutive reads as my packetLength is 276?

    err_code = nrf_drv_twi_rx(&p_twi_instance, deviceAddress, shtpTemp, packetLength);
    APP_ERROR_CHECK(err_code);

    Below is what Daniel Veilleux implemented for the twi_send_byte:

    static bool m_suspended = false;

    static bool twi_send_byte(NRF_TWI_Type * p_twi,
    uint8_t const * p_data,
    uint8_t length,
    uint8_t * p_bytes_transferred,
    bool no_stop)
    {
    if (*p_bytes_transferred < length)
    {
    nrf_twi_txd_set(p_twi, p_data[*p_bytes_transferred]);
    ++(*p_bytes_transferred);
    }
    else
    {
    if (no_stop)
    {
    m_suspended = true;
    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_SUSPEND);
    return false;
    }
    else
    {
    m_suspended = false;
    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
    }
    }
    return true;
    }

    static nrfx_err_t twi_tx_start_transfer(twi_control_block_t * p_cb,
    NRF_TWI_Type * p_twi,
    uint8_t const * p_data,
    uint8_t length,
    bool no_stop)
    {
    nrfx_err_t ret_code = NRFX_SUCCESS;
    volatile int32_t hw_timeout;

    hw_timeout = HW_TIMEOUT;

    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
    nrf_twi_shorts_set(p_twi, 0);

    p_cb->bytes_transferred = 0;
    p_cb->error = false;

    // In case TWI is suspended resume its operation.
    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);

    if (!m_suspended)
    {
    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTTX);
    }

    (void)twi_send_byte(p_twi, p_data, length, &p_cb->bytes_transferred, no_stop);

    if (p_cb->handler)
    {
    p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK |
    NRF_TWI_INT_ERROR_MASK |
    NRF_TWI_INT_TXDSENT_MASK |
    NRF_TWI_INT_RXDREADY_MASK;
    nrf_twi_int_enable(p_twi, p_cb->int_mask);
    }
    else
    {
    while ((hw_timeout > 0) &&
    twi_transfer(p_twi,
    &p_cb->error,
    &p_cb->bytes_transferred,
    (uint8_t *)p_data,
    length,
    no_stop))
    {
    hw_timeout--;
    }

    if (p_cb->error)
    {
    uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi);

    if (errorsrc)
    {
    ret_code = twi_process_error(errorsrc);
    }
    }

    if (hw_timeout <= 0)
    {
    nrf_twi_disable(p_twi);
    nrf_twi_enable(p_twi);
    ret_code = NRFX_ERROR_INTERNAL;
    }

    }
    return ret_code;
    }

    Here is the receive_byte function:

    static void twi_receive_byte(NRF_TWI_Type * p_twi,
    uint8_t * p_data,
    size_t length,
    size_t * p_bytes_transferred)
    {
    if (*p_bytes_transferred < length)
    {
    p_data[*p_bytes_transferred] = nrf_twi_rxd_get(p_twi);

    ++(*p_bytes_transferred);

    if (*p_bytes_transferred == length - 1)
    {
    nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK);
    }
    else if (*p_bytes_transferred == length)
    {
    return;
    }

    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
    }
    }

    static nrfx_err_t twi_rx_start_transfer(twi_control_block_t * p_cb,
    NRF_TWI_Type * p_twi,
    uint8_t const * p_data,
    size_t length)
    {
    nrfx_err_t ret_code = NRFX_SUCCESS;
    volatile int32_t hw_timeout;

    hw_timeout = HW_TIMEOUT;

    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);

    p_cb->bytes_transferred = 0;
    p_cb->error = false;

    if (length == 1)
    {
    nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK);
    }
    else
    {
    nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_SUSPEND_MASK);
    }
    // In case TWI is suspended resume its operation.
    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTRX);

    if (p_cb->handler)
    {
    p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK |
    NRF_TWI_INT_ERROR_MASK |
    NRF_TWI_INT_TXDSENT_MASK |
    NRF_TWI_INT_RXDREADY_MASK;
    nrf_twi_int_enable(p_twi, p_cb->int_mask);
    }
    else
    {
    while ((hw_timeout > 0) &&
    twi_transfer(p_twi,
    &p_cb->error,
    &p_cb->bytes_transferred,
    (uint8_t*)p_data,
    length,
    false))
    {
    hw_timeout--;
    }

    if (p_cb->error)
    {
    uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi);

    if (errorsrc)
    {
    ret_code = twi_process_error(errorsrc);
    }
    }
    if (hw_timeout <= 0)
    {
    nrf_twi_disable(p_twi);
    nrf_twi_enable(p_twi);
    ret_code = NRFX_ERROR_INTERNAL;
    }
    }
    return ret_code;
    }

  • Hi,

    please use "Insert code" menu to post code snippets, it's hard to read it without indentations.

    Thank you for the feedback. I was wondering if you could please help me to figure out how to implement this on the twi_receive_byte function? I have tried but without any success that i can see on the logic analyzer.

    Did you try the code proposed by Daniel, or made changes for RX code?

    I looked at that code once more - it is based on nrfx_twi module (that's without EDMA). As I understand, with nrfx_twi there is no 255-byte limitation, because transfer is done one byte at a time in interrupt mode. Did you try it? If it works, you can then implement switching from twi to twim to use interrupt mode for first long sequence and EDMA for IMU data transfers.

  • Hi Dmitry,

    i didnt realise about the posting as code snippets.

    I tried to implement Daniel's approach but for the RX code but my logic analyzer shows a stop command at the 255th byte. then it restarts the read for the remaining 21 bytes. This wont work for this IMU.

    I have used the simple sensor example to implement this. 

    It would be great to implement a read one byte at a time. Is there an example of the interrupt mode implementation? 

  • i didnt realise about the posting as code snippets.

    This menu:

    It would be great to implement a read one byte at a time. Is there an example of the interrupt mode implementation?

    Yes, just use nrfx_twi instead of nrfx_twim.

  • Thanks for that. How can I enable EDMA in code after the first long sequence of data from the IMU? I thought this was just enabled in the config file?

Related