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

TWI write: unable to write without a repeat start

Hello,

We are in the process of migrating to the nrf52840 and as such have decided to use the latest SDK (15.2). 

As part of the migration we are trying to do a TWI write without a stop or repeated start condition using the nrf twi manager (by dividing it into two transfers, one with the register address and one with the data to write that has variable length). Basically the following: 

We are able to send a write command followed by no stop and a repeated start with the data but our slave device does not respond to this command. We are able to go around the issue by sending a single transfer packet with the register address in the first byte of the buffer but not all of our drivers will be easy to modify with this change. Is there a way to do this using the nrf_twi_mngr OR the driver directly? After perusing the documentation and the source code, we were not able to find a solution that did not require modification of the SDK. 

There is an old thread with a similar question that has gone un-answered so any help will be greatly appreciated. 

Thanks, 

JP

Parents
  • long time ago I tested that the TWIS module responds to continuous writes (no stop bits in between) upto 255 bytes. I am not sure how you have configured the receiver of TWIS when the master is writing to it. Could you attach some code snippets on your configuration and the code where you are configuring TWIS to receive commands.

  • Hello, 

    Thanks for the quick reply,

    As for the slave response, we are not setting up the slaves, these are sensors we need to communicate with which drivers use the format:

    CHIP ADDRESS
    REGISTER ADDRESS
    BUFFER
    BUFFER LENGTH

    to send a twi command, and we are trying to preserve this when passing it to either the twi driver or the twi manager (which we have currently set up for this). We are able to communicate with the sensors if we do: 

    CHIP ADDRESS
    BUFFER[0]=REGISTER ADDRESS
    BUFFER[1..n]= data to write
    BUFFER LENGTH

    however, this is not always possible with the way that our drivers were written in the past. Basically, we are trying to avoid having to allocate memory for every call where all we do is copy the register address to mem[0] and the data to mem[1..n] in order to use a single call of the driver/manager.

    This is the way its being used at the moment:

    twi_write( const uint8_t slave_chip_address, uint8_t slave_reg_address, void* data_buffer, const uint8_t data_length )
    {
      static nrf_twi_mngr_transfer_t addr_packet;
      static nrf_twi_mngr_transfer_t wr_packet;
     
      // initialize packet transfer descriptors
      // address packet (always write on first packet)
      addr_packet.operation = slave_chip_addr; // already formatted to read/write
      addr_packet.p_data = &slave_reg_address;
      addr_packet.length = 1;
      addr_packet.flags = NRF_TWI_MNGR_NO_STOP; // is there a way to NO_RESTART?
      // data/register to read/write packet
      wr_packet.operation = slave_chip_address; // already formatted to read/write
      wr_packet.p_data = data_buffer;
      wr_packet.length = data_length;
      wr_packet.flags = NULL;
     
      // prepare "whole" packet for sending
      nrf_twi_mngr_transfer_t twi_wr_packets[] =
      {
        addr_packet,
        wr_packet
      };

      nrf_twi_mngr_perform( &nrf_twi0_mngr, NULL, twi_wr_packets, 2, NULL );

    }

    But as said before the only way to make it work as we need it to (image in original post) is to prepare a single transfer and pass it to twi_mngr_perform as such.

    Hope this clarifies the issues we are having, let me know if I can provide more information/clarification.

Reply
  • Hello, 

    Thanks for the quick reply,

    As for the slave response, we are not setting up the slaves, these are sensors we need to communicate with which drivers use the format:

    CHIP ADDRESS
    REGISTER ADDRESS
    BUFFER
    BUFFER LENGTH

    to send a twi command, and we are trying to preserve this when passing it to either the twi driver or the twi manager (which we have currently set up for this). We are able to communicate with the sensors if we do: 

    CHIP ADDRESS
    BUFFER[0]=REGISTER ADDRESS
    BUFFER[1..n]= data to write
    BUFFER LENGTH

    however, this is not always possible with the way that our drivers were written in the past. Basically, we are trying to avoid having to allocate memory for every call where all we do is copy the register address to mem[0] and the data to mem[1..n] in order to use a single call of the driver/manager.

    This is the way its being used at the moment:

    twi_write( const uint8_t slave_chip_address, uint8_t slave_reg_address, void* data_buffer, const uint8_t data_length )
    {
      static nrf_twi_mngr_transfer_t addr_packet;
      static nrf_twi_mngr_transfer_t wr_packet;
     
      // initialize packet transfer descriptors
      // address packet (always write on first packet)
      addr_packet.operation = slave_chip_addr; // already formatted to read/write
      addr_packet.p_data = &slave_reg_address;
      addr_packet.length = 1;
      addr_packet.flags = NRF_TWI_MNGR_NO_STOP; // is there a way to NO_RESTART?
      // data/register to read/write packet
      wr_packet.operation = slave_chip_address; // already formatted to read/write
      wr_packet.p_data = data_buffer;
      wr_packet.length = data_length;
      wr_packet.flags = NULL;
     
      // prepare "whole" packet for sending
      nrf_twi_mngr_transfer_t twi_wr_packets[] =
      {
        addr_packet,
        wr_packet
      };

      nrf_twi_mngr_perform( &nrf_twi0_mngr, NULL, twi_wr_packets, 2, NULL );

    }

    But as said before the only way to make it work as we need it to (image in original post) is to prepare a single transfer and pass it to twi_mngr_perform as such.

    Hope this clarifies the issues we are having, let me know if I can provide more information/clarification.

Children
  • Hi,

    I am sorry, I totally misunderstood your initial question and thought that nRF is on the slave side. 

    Now back to your question, I think the source of your problem is that there is no configuration in twi_manager that gives you a sequential operation without a repeated start. The flag is only to omit a stop but there is nothing to omit a repeated start. I see that there is no easy solution for this without changing too much of twi_manager and risking untested changes.

    Let me have a look at nRFX drivers to see if we can manage to do this in easier way.

    For now it looks to me that your way of packing slave address and register address seems to be the simplest way without changing any SDK library or driver code.

    I will be back to you once I experiment a bit with nrfx drivers

  • OK actually digging around I see that it is not possible to omit start sequence between two separate TX transactions. Normally the driver is able to omit a stop condition between two transaction by using the short available in the hardware LASTTX_SUSPEND. But I am pretty sure that your sensors get confused here.

    in your workaround you avoid a stop and repeated start by keeping all of them in the same transaction. I think that is the best way to do it.

  • Alright, thanks for the help. We will use it in that way then.

Related