STM32 HAL_I2C_Mem_Write/Read Errors In Quick Sequential Operations
Hi, I am working on a project using the STM32H730 with the M24C64 I2C EEPROM chip.
In my project I am using the HAL_I2C_Mem_Write functions to load and save values from the EEPROM. I'm running into an issue where the wrong value gets read if there are sequential calls to HAL_I2C_Mem_Write or HAL_I2C_Mem_Read functions. I already have a short delay of 1ms after the reads and writes, but it seems longer is necessary, more in the realm of 10ms, which is a major drag on performance. I discovered this when debugging because I do not get read/write errors when stepping through slowly with a debugger, as this adds a time delay between the I2C functions being called.
Here are my I2C read / write functions:
/**
* @brief Erases the entire i2c_eeprom memory
*/
void persistent_memory_i2c_eeprom::erase_all(void) {
clear_block(0, mem_size);
}
/**
* @brief Writes a byte to i2c_eeprom memory
*/
void persistent_memory_i2c_eeprom::write_val(uint32_t offset, uint8_t val) {
HAL_StatusTypeDef res = HAL_I2C_Mem_Write(hi2c, DevAddress, mem_base_address + offset, I2C_MEMADD_SIZE_16BIT, &val, 1, 100);
HAL_Delay(1);
}
/**
* @brief Reads a byte from i2c_eeprom memory
*/
uint8_t persistent_memory_i2c_eeprom::read_val(uint32_t offset) {
uint8_t data;
HAL_StatusTypeDef res = HAL_I2C_Mem_Read(hi2c, DevAddress, mem_base_address + offset, I2C_MEMADD_SIZE_16BIT, &data, 1, 100);
HAL_Delay(1);
return data;
}
/**
* @brief Writes a block of data to i2c_eeprom memory
*/
void persistent_memory_i2c_eeprom::write_block(uint32_t offset, uint8_t * vals, uint32_t size) {
uint32_t write_remaining = size;
uint32_t mem_addr = mem_base_address + offset;
uint32_t incr = 0;
while(write_remaining > 0){
uint16_t block_portion = 32 - (mem_addr % 32);
if(block_portion > write_remaining){
block_portion = write_remaining;
}
HAL_StatusTypeDef res = HAL_I2C_Mem_Write(hi2c, DevAddress, mem_addr, I2C_MEMADD_SIZE_16BIT, &vals[incr], block_portion, 100);
mem_addr += block_portion;
write_remaining -= block_portion;
incr += block_portion;
HAL_Delay(1);
}
}
/**
* @brief Reads a block of data from i2c_eeprom memory
*/
void persistent_memory_i2c_eeprom::read_block(uint32_t offset, uint8_t * vals, uint32_t size) {
HAL_StatusTypeDef res = HAL_I2C_Mem_Read(hi2c, DevAddress, mem_base_address + offset, I2C_MEMADD_SIZE_16BIT, vals, size, 100);
HAL_Delay(1);
}
void persistent_memory_i2c_eeprom::clear_block( uint32_t offset, uint32_t size ) {
uint8_t vals[32] = {};
uint32_t write_remaining = size;
uint32_t mem_addr = mem_base_address + offset;
uint32_t incr = 0;
while(write_remaining > 0){
uint16_t block_portion = 32 - (mem_addr % 32);
if(block_portion > write_remaining){
block_portion = write_remaining;
}
HAL_StatusTypeDef res = HAL_I2C_Mem_Write(hi2c, DevAddress, mem_addr, I2C_MEMADD_SIZE_16BIT, &vals[incr], block_portion, 100);
mem_addr += block_portion;
write_remaining -= block_portion;
incr += block_portion;
HAL_Delay(1);
}
}
Here is an example of a call that leads to an error unless I insert an artificial delay:
/* Write each preset to memory */
clear_block(mem_offset, 1);
write_block(mem_offset, &temp[i], 1);
Is there a reason this is happening? Currently the weird thing is that all the read / write functions are returning HAL_OK, even when they're reading / writing the incorrect values. Is there a different function I can call to wait until the EEPROM is actually ready to accept new messages?
