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

nrf52840 twim: how to write multiple buffers without repeated start condition?

The TWIM peripheral allows you to tx multiple buffers back-to-back like this:

- Set buffer 1 in TXD.PTR, TXD.AMOUNT
- Trigger TASKS_STARTTX
- Wait for EVENTS_TXSTARTED
- Set buffer 2 in TXD.PTR, TXD.AMOUNT
- Wait for EVENTS_LASTTX
- Trigger TASKS_STARTTX
- Wait for EVENTS_LASTTX
- Trigger TASKS_STOP

(This is what nrfx NRFX_TWIM_XFER_TXTX does, for instance)

However, this will send this on the bus:

- Start condition
- Address + write bit
- Data from buffer 1
- REPEATED start condition <-- I don't want this
- Address + write bit <-- I don't want this
- Data from buffer 2
- Stop condition

Is it possible to NOT send the repeated start condition, sending the data from the 2 buffers back-to-back instead? like this:

- Start condition
- Address + write bit
- Data from buffer 1
- Data from buffer 2
- Stop condition

To be clear, I'm not asking if the Nordic's C software (nrf5 SDK, nrfx) supports it (I already know it doesn't).

I'm asking if the actual hardware supports it. I'm writing my own driver, directly touching the TWIM registers, events and tasks.

Parents Reply
  • When writing data to a chip, you usually send a few command/address bytes, followed by many data bytes. My TWI code gets the data in a buffer, and since sending many buffers is not supported it has to copy the data to a second buffer to prefix it with the command/address bytes and send this second buffer.

    This means it ends up using double the RAM and an extra data copy. I was hoping the hardware had a way to avoid that.

Children
  • Hi,

    The twim peripheral doesn't support it no, it may be possible by using the legacy twi peripheral that is also present in hardware. However the legacy twi require you to write one byte at a time (e.g. there will be a twi interrupt for each byte written/read), so in terms of resources and speed I don't think it is worth looking into this option.

    Best regards,
    Kenneth

  • I realize this was long enough ago that it might not be relevant anymore, but if you know how many buffers you have and/or how long they are, couldn't you allocate your buffers so that they occupy a contiguous region to begin with? Maybe an array of buffers, or just a long buffer and an offset index to use as the original buffer location/partioning? Then you could effectively run a long I2C transfer of both buffers without allocating a separate double-length buffer.

    Something like this, as a toy example

    static uint8_t buffers[BUFFER_LENGTH * NUM_BUFFERS] = {0}
    
    void get_data_for_i2c_tx(uint8_t buffer_idx)
    {
        // Get your data and put it in
        // buffers[buffer_idx * BUFFER_LENGTH]
    }
    
    void send_data_over_i2c(void)
    {
        // Send "BUFFER_LENGTH * NUM_BUFFERS" bytes starting at buffers (or &buffers[0])
    }

Related