I have an nRF5340 with an AT24CM01 EEPROM on an I2C bus (SDA = P0.16, SDL = P0.17). My devicetree looks like so:
&i2c3 { compatible = "nordic,nrf-twim"; status = "okay"; clock-frequency = <I2C_BITRATE_FAST>; pinctrl-0 = <&i2c3_default>; pinctrl-1 = <&i2c3_sleep>; pinctrl-names = "default", "sleep"; // EEPROM at24cm01: at24cm01@50 { compatible = "atmel,at24"; reg = <0x50>; size = <131072>; pagesize = <256>; address-width = <16>; timeout = <5>; status = "okay"; }; };
I'm having troubles when writing and reading in rapid succession. If I do this, it throws a bunch of errors:
#include <zephyr/drivers/eeprom.h> int test() { uint8_t readdata; for(uint32_t addr = 0; addr < 131072; addr++) { uint8_t data = addr % 255; LOG_INF("Writing..."); err = eeprom_write(dev, addr, &data, sizeof(data)); if(err) { LOG_ERR("EEPROM write failed at address %d, err: %d", addr, err); return false; } LOG_INF("Written! Reading..."); err = eeprom_read(dev, addr, &readdata, sizeof(readdata)); if(err) { LOG_ERR("EEPROM read failed at address %d, err: %d", addr, err); return false; } LOG_INF("Read!"); if(readdata != data) { LOG_ERR("EEPROM failed at address %d (expected %d, got %d)", addr, data, readdata); return false; } k_msleep(500); } return 0; }
[00:00:05.435,577] <inf> myapp: Writing... [00:00:05.435,791] <inf> myapp: Written! Reading... [00:00:05.435,882] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0 [00:00:05.437,042] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0 [00:00:05.438,201] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0 [00:00:05.439,514] <inf> myapp: Read! [00:00:05.939,575] <inf> myapp: Writing... [00:00:05.939,758] <inf> myapp: Written! Reading... [00:00:05.939,849] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0 [00:00:05.940,979] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0 [00:00:05.942,169] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0 [00:00:05.943,450] <inf> myapp: Read!
From other forum posts, this error appears to be a NACK. If I put a delay in between the write and read though:
#include <zephyr/drivers/eeprom.h> int test() { uint8_t readdata; for(uint32_t addr = 0; addr < 131072; addr++) { uint8_t data = addr % 255; LOG_INF("Writing..."); err = eeprom_write(dev, addr, &data, sizeof(data)); if(err) { LOG_ERR("EEPROM write failed at address %d, err: %d", addr, err); return false; } k_msleep(5); LOG_INF("Written! Reading..."); err = eeprom_read(dev, addr, &readdata, sizeof(readdata)); if(err) { LOG_ERR("EEPROM read failed at address %d, err: %d", addr, err); return false; } LOG_INF("Read!"); if(readdata != data) { LOG_ERR("EEPROM failed at address %d (expected %d, got %d)", addr, data, readdata); return false; } k_msleep(500); } return 0; }
Then it works fine:
[00:00:05.739,227] <inf> myapp: Writing... [00:00:05.749,511] <inf> myapp: Written! Reading... [00:00:05.749,755] <inf> myapp: Read! [00:00:06.249,816] <inf> myapp: Writing... [00:00:06.260,070] <inf> myapp: Written! Reading... [00:00:06.260,284] <inf> myapp: Read!
Is this expected behaviour? I'm surprised that the Zephyr library doesn't wait for the operation to be complete before returning. Is there a recommended approach to dealing with this, other than putting a (likely unnecessary) sleep after each operation?