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

Unable to write 8210 bytes on I2c bus

Hi,

I am facing the issue of sending 8210 bytes of data to my slave device.

I am using NRF52840 interfaced with the MAX32664 maxim sensor hub.

I tried both approaches to transmit data with a legacy as well as easyDMA enabled case.

On the forum, I found a similar case on this link "i2c message max buffer size - Nordic Q&A - Nordic DevZone - Nordic DevZone (nordicsemi.com)" however could not resolve the issue.

observation made on the saleae logic analyzer:

when tried to transmit 

1)8210 bytes - it sends the first 18 bytes data + write address

2)8192 bytes - it sends the 0 bytes of data + write address (code gets stuck)

3)8191 bytes - it sends the first 255 bytes of data + write address 

4)8190 bytes - it sends the first 254 bytes of data + write address 

5) 7936 BYTES - it sends the 0 bytes of data + write address (code gets stuck)

I am failing to understand this buffer overflow at multiples of 256(case 2 and case 5).....

I did try sending the data into chunks of 200 without issuing stop byte and at the end of 8210th byte sent the stop bit, but the slave responds with an illegal command sequence error.

Info:

NRF52840 custom board 

NRF SDK17 is used

18 bytes + write address

255 bytes +write address

Parents Reply Children
  • Hi Jorgen,

    I have migrated the code from nrf_drv_twi  to nrfx_twi where API uses size_t  as the length parameter.

    Now when I am trying to write the bytes it sends 1380 bytes and sends error code 3.

    what does error code 3 means?

  • Error code 3 means NRF_ERROR_INTERNAL. Which function is returning this error?

    Can you post your code for initializing of TWI and how you do the transfers?

  • Information: all other reads/writes commands are working this happens just when the buffer size is 8210 bytes

    nrfx_twi_tx function call gives error code 3 only when I write 1st page of 8210 bytes for all other small transaction it is working.

    Initialization in main:

    //initialization:
    ret_code_t err_code;
    const nrfx_twi_config_t twi_max32664_config = {
    .scl = ARDUINO_SCL_PIN,
    .sda = ARDUINO_SDA_PIN,
    .frequency = NRF_TWI_FREQ_100K,
    .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
    .hold_bus_uninit = false
    };
    
    err_code = nrfx_twi_init(&m_twi, &twi_max32664_config, NULL, NULL);
    APP_ERROR_CHECK(err_code);
    nrfx_twi_enable(&m_twi);

    write cmd function :

        //write command function definition
        SS_STATUS write_cmd(uint8_t *tx_buf, int tx_len, int sleep_ms) {
    
    	me11_i2c_wakeup_call();
    	ret_code_t err_code = me11_write(tx_buf, tx_len, false);
    
    	int retries = 4;
    	while (err_code != NRF_SUCCESS && retries-- > 0) {
    		NRF_LOG_INFO("i2c wr retry = %d" , err_code);
    		NRF_LOG_FLUSH();
    		i_mxc_delay(1000);
    		me11_i2c_wakeup_call();
    		err_code = me11_write(tx_buf, tx_len, false);
    	}
    
    	if (err_code != 0) {
    		NRF_LOG_INFO("write_cmd error SS_ERR_UNAVAILABLE = %d" , err_code);
    		NRF_LOG_FLUSH();
    		return SS_ERR_UNAVAILABLE;
    	}
    
    	nrf_delay_ms(sleep_ms);
    	uint8_t status_byte;
    
    	me11_i2c_wakeup_call();
    	err_code = me11_read( &status_byte, 1, false);
    
    #if 1	//optional
    	bool try_again = (status_byte == SS_ERR_TRY_AGAIN);
    	while ((err_code != NRF_SUCCESS || try_again) && retries-- > 0) {
    		i_mxc_delay(sleep_ms * 1000);
    		me11_i2c_wakeup_call();
    		err_code = me11_read( &status_byte, 1, false);
    		try_again = (status_byte == SS_ERR_TRY_AGAIN);
    	}
    #endif
    
    	return (SS_STATUS)status_byte;
    
    }
    
    void me11_i2c_wakeup_call(void){
    
    #if 1
    	uint8_t tx_buf[1];
    	tx_buf[0] = 0x00;
    
    
    	nrfx_twi_tx(&m_twi,0x00,&tx_buf[0],1,false); //GD
    
    	i_mxc_delay(200); //GD might need calibration
    
    	tx_buf[0] = 0xD3;
    	tx_buf[0] = 0x00;
    
    	nrfx_twi_tx(&m_twi,0x00,&tx_buf[0],1,false); //GD
    	i_mxc_delay(150);
    
    
    
    
    #else
    
    	
    	uint8_t tx_buf[1] = {0xFF};
    	nrfx_twi_tx(&m_twi,I2C_SLAVE_ADDR,&tx_buf[0],1,FALSE);
    	nrfx_twi_tx(&m_twi,I2C_SLAVE_ADDR,&tx_buf[0],1,FALSE);
    	nrfx_twi_tx(&m_twi,I2C_SLAVE_ADDR,&tx_buf[0],1,FALSE);
    	nrfx_twi_tx(&m_twi,I2C_SLAVE_ADDR,&tx_buf[0],1,FALSE);
    	 */
    
    #endif
    
    }
    
    int me11_write( const uint8_t *data, int length, bool repeated){
    	ret_code_t err_code;
    	
    	err_code = nrfx_twi_tx(&m_twi,I2C_SLAVE_ADDR,(uint8_t *)data, length,repeated);
    	if(err_code != NRF_SUCCESS)
    	{
    		NRF_LOG_INFO("mel1_write err_code= %d", err_code);
    //		APP_ERROR_CHECK(err_code);
    	}
    
    	return err_code;
    }
    
    int me11_read( uint8_t *data, int length, bool repeated){
    	ret_code_t err_code;
    	
    	err_code = nrfx_twi_rx(&m_twi,I2C_SLAVE_ADDR,(uint8_t *)data, length);
    	if(err_code != NRF_SUCCESS)
    	{
    		NRF_LOG_INFO("mel1_read err_code= %d", err_code);
    //		APP_ERROR_CHECK(err_code);
    	}
    	return err_code;
    }

    calling write_cmd:

    //Function call:
    
    status = write_cmd(cmd_bytes_4c_to_205b, sizeof(cmd_bytes_4c_to_205b),340); 
    
    //size of cmd_bytes_4c_to_205b = 8210 bytes
    
    if(status!=SS_SUCCESS)
    {
    NRF_LOG_INFO("FAILED to send page bytes 0x4C to 0x205B from the .msbl file SIZE:%d status byte:0x%x",sizeof(cmd_bytes_4c_to_205b),status);
    NRF_LOG_FLUSH();
    }
    else
    {
    NRF_LOG_INFO("SUCCESFULL to send page bytes 0x4C to 0x205B from the .msbl file SIZE:%d",sizeof(cmd_bytes_4c_to_205b));
    NRF_LOG_FLUSH();
    }

  • I believe you get this error because the function uses too long time to transfer the data when you are using the nrfx_twi driver in blocking mode, leading to a HW timeout in the driver.

    I would highly recommend you to switch to using the nrfx_twim driver, as this handles the long transfers in HW, by fetching the data directly from RAM. In nrfx_twi, only one byte is provided to the peripheral by the CPU at a time, leading to much interrupt/event overhead and CPU usage. It would also be beneficial if you add an event handler in your application, to run in non-blocking mode. This would eliminate the HW timeout used in blocking mode.

  • Hi Jorgen,

    I migrated from code nrfx_twi to nrfx_twim successfully.

    I want to write 28 pages  (28 x 8210bytes) 1 page at a time.

    for the same, I have made 28 static buffers in the code containing 8210 bytes in a sequence.  

    Now with your suggestions, I have written 13 pages successfully out of 28 but as soon as it tries to write the 14th page the function returns error code 16.

    what error code 16 refers to?

    how do I resolve it?

    Thank you 

    -Gaurav

Related