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

1 REPLY 1
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.