cancel
Showing results for 
Search instead for 
Did you mean: 

WrMulti function ULD for the vl53l5cx running in Zephyr return error on the I2C line

Kuhaku
Associate

I am attempting to write the platform code for the ULD to work with Zephyr. WrByte, RdByte, and RdMulti are running correctly, but the WrMulti function is throwing two types of errors:

<err> i2c_nrfx_twim: Error on I2C line occurred for message 0

<err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0.

The second error appears to be an issue with NACK, but it seems strange that there is no NACK when writing a single byte (WrByte) and NACK is received when attempting to write more (WrMulti). I'm attaching the platform files in case someone could lend me a hand. Thank you in advance.

1 ACCEPTED SOLUTION

Accepted Solutions
John E KVAM
ST Employee

if you look into the Zephyr you will find (I'm guessing) that there is a limit to the length of I2C they can write in one go. And I'm guessing you have exceeded it.

The STM32 is one of the rare chips that can send an I2C write of 0x8000 bytes.

What you have to do is dig in there and break up your I2C writeMulti into chunks suitable to your processor. 

On this forum is the code that someone posted but I cannot find the one I was looking for, but one guy implemented it like this:

uint8_t WrMultiLarge(VL53L5CX_Platform *p_platform,
   uint16_t RegisterAdress,
    uint8_t *p_values,
    uint32_t size) {
   // Solution based on https://forum.arduino.cc/t/stream-large-array-to-i2c-slave/659405/4
  
   // uses raw I2C writes, rather than use the txbuffer
   PERIPH_WIRE.startTransmissionWIRE(((p_platform->address) >> 1) & 0x7F, WIRE_WRITE_FLAG);
 
   // Send address of register
   PERIPH_WIRE.sendDataMasterWIRE((byte)(RegisterAdress >> 8));
   PERIPH_WIRE.sendDataMasterWIRE((byte)(RegisterAdress & 0xFF));
 
   // send one byte at a time from the array to the I2C device
   for (unsigned int i = 0; i < size; i++) {
     if (!PERIPH_WIRE.sendDataMasterWIRE((byte) p_values[i])){ 
      Serial.println("Write error at index "); Serial.println(i); 
    }
   }
  
   // stop sending the data
   PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
 
  return 0;  // No error checking :(
}
 
uint8_t WrMulti(
		VL53L5CX_Platform *p_platform,
		uint16_t RegisterAdress,
		uint8_t *p_values,
		uint32_t size)
{
  // The arduino Wire TX buffer size found in your arduino core's Wire.h
  // For samd21 this is 256, but for other cores it varies widely
  if (size>=256) {  
    return WrMultiLarge(p_platform, RegisterAdress, p_values, size);
  }
 
  Wire.beginTransmission(((uint8_t)(((p_platform->address) >> 1) & 0x7F)));
 
  const uint8_t buffer[2] {RegisterAdress >> 8, RegisterAdress & 0xFF };
  Wire.write(buffer, 2);
  for (uint32_t i = 0 ; i < size ; i++) {
  
    if(Wire.write(p_values[i])==0){ Serial.print("Write error at offset "); Serial.println(i); }
  }
 
  uint8_t code = Wire.endTransmission(true);
  return code;
}

 


If this or any post solves your issue, please mark them as 'Accept as Solution' It really helps. And if you notice anything wrong do not hesitate to 'Report Inappropriate Content'. Someone will review it.

View solution in original post

4 REPLIES 4
John E KVAM
ST Employee

if you look into the Zephyr you will find (I'm guessing) that there is a limit to the length of I2C they can write in one go. And I'm guessing you have exceeded it.

The STM32 is one of the rare chips that can send an I2C write of 0x8000 bytes.

What you have to do is dig in there and break up your I2C writeMulti into chunks suitable to your processor. 

On this forum is the code that someone posted but I cannot find the one I was looking for, but one guy implemented it like this:

uint8_t WrMultiLarge(VL53L5CX_Platform *p_platform,
   uint16_t RegisterAdress,
    uint8_t *p_values,
    uint32_t size) {
   // Solution based on https://forum.arduino.cc/t/stream-large-array-to-i2c-slave/659405/4
  
   // uses raw I2C writes, rather than use the txbuffer
   PERIPH_WIRE.startTransmissionWIRE(((p_platform->address) >> 1) & 0x7F, WIRE_WRITE_FLAG);
 
   // Send address of register
   PERIPH_WIRE.sendDataMasterWIRE((byte)(RegisterAdress >> 8));
   PERIPH_WIRE.sendDataMasterWIRE((byte)(RegisterAdress & 0xFF));
 
   // send one byte at a time from the array to the I2C device
   for (unsigned int i = 0; i < size; i++) {
     if (!PERIPH_WIRE.sendDataMasterWIRE((byte) p_values[i])){ 
      Serial.println("Write error at index "); Serial.println(i); 
    }
   }
  
   // stop sending the data
   PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
 
  return 0;  // No error checking :(
}
 
uint8_t WrMulti(
		VL53L5CX_Platform *p_platform,
		uint16_t RegisterAdress,
		uint8_t *p_values,
		uint32_t size)
{
  // The arduino Wire TX buffer size found in your arduino core's Wire.h
  // For samd21 this is 256, but for other cores it varies widely
  if (size>=256) {  
    return WrMultiLarge(p_platform, RegisterAdress, p_values, size);
  }
 
  Wire.beginTransmission(((uint8_t)(((p_platform->address) >> 1) & 0x7F)));
 
  const uint8_t buffer[2] {RegisterAdress >> 8, RegisterAdress & 0xFF };
  Wire.write(buffer, 2);
  for (uint32_t i = 0 ; i < size ; i++) {
  
    if(Wire.write(p_values[i])==0){ Serial.print("Write error at offset "); Serial.println(i); }
  }
 
  uint8_t code = Wire.endTransmission(true);
  return code;
}

 


If this or any post solves your issue, please mark them as 'Accept as Solution' It really helps. And if you notice anything wrong do not hesitate to 'Report Inappropriate Content'. Someone will review it.

I am having trouble in uploading firmware please see if there is some error i am using DevaSys board and every time getting init failed i am attaching the logs also 

Zhiyuan.Han
ST Employee

Hi

From your log seems IC read write successfully with short data length, like vl53l5cx_is_alive() you have tried to read the device information, and the I2C works well.

The issue happens when you are trying to write big size date to device inside vl53l5cx_is_alive(), which used to download the FW to the device, take below line for example, the data's is 0x8000 bytes long, so my suggestion is to check if your platform supporting such big size data writing.  if not supported by your platform., you can try to split the big size into two 0x4000 .

status |= VL53L8CX_WrMulti(&(p_dev->platform),0,

(uint8_t*)&VL53L8CX_FIRMWARE[0],0x8000);

 

Br

Zhiyaun.Han


In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
tanmaygoyal_26
Associate II

tanmaygoyal_26_1-1759220538994.png

below is when i split the firmware into small chunk 16 bytes i am able to write 

tanmaygoyal_26_0-1759220501717.png

Please check if these two are correct to write the firmware

 

and also my connection 

gnd->gnd

avdd,iovdd,lpn->3v3(high)

scl->scl

sda->sda

i2c_rst->0(gnd)