2023-11-16 02:12 AM
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.
Solved! Go to Solution.
2023-11-16 07:59 AM
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;
}
2023-11-16 07:59 AM
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;
}