cancel
Showing results for 
Search instead for 
Did you mean: 

Data write problem to external EEPROM (or internal flash) in STM32F401RCT6TR when using with Freertos

shydv15
Associate II

Hi, 

I have developed custom PCB board with STM32F401RCT6TR as MCU and there is external EEPROM (connected to I2C2), IMU sensor (connected to I2C1) and display (connected to SPI1). I am reading IMU data and displaying it on the screen. When the sensor data is above critical threshold, I am saving this data to EEPROM, and accessing and showing it on the screen. I have 2 buttons to adjust threshold value and saving this value also to EEPROM. The functions work as expected (read, write, show data).

I then created task to read IMU sensor and save critical IMU data to EEPROM and another task was created to save adjusted threshold value and displaying data on the screen using FREERTOS in CUBE IDE. In this case, I was not able to write anything to EEPROM. (When I try to access EEPROM, I was reading only 255, which is default value if anything is not written to it.) MCU executes the write function but does not write anything to EEPROM. 

I tried to write some random data to EEPROM in FREERTOS and again failed. I also tried to write and read data before Kernel setting and initialization in int main function, again I failed. Sometimes, I am able to write (1 success in 50 - 60 try), but in this case, write time takes too long to execute. (normally write time is 10ms, but in this case it is around 1400ms). I also tried to replace external EEPROM with internal flash (write and read) but again, it only worked without FREERTOS. I changed FREERTOS setting (increased stack size of tasks, increased their priority) to see if it will help but failed again.

I have attached my write code (EEPROM_Write_Num) to this thread. Could you please help me to debug this issue? Thank you

void EEPROM_Write (uint16_t page, uint16_t offset, uint8_t *data, uint16_t size)
{

	int paddrposition = log(PAGE_SIZE)/log(2);
	uint16_t startPage = page;
	uint16_t endPage = page + ((size+offset)/PAGE_SIZE);
	uint16_t numofpages = (endPage-startPage) + 1;
	uint16_t pos=0;
	for (int i=0; i<numofpages; i++)
	{
		/* calculate the address of the memory location
		 */
		uint16_t MemAddress = startPage<<paddrposition | offset;
		uint16_t bytesremaining = bytestowrite(size, offset);  // calculate the remaining bytes to be written
		HAL_I2C_Mem_Write(EEPROM_I2C, EEPROM_ADDR, MemAddress, 2, &data[pos], bytesremaining, 1000);  // write the data to the EEPROM
		startPage += 1;  // increment the page, so that a new page address can be selected for further write
		offset=0;   // since we will be writing to a new page, so offset will be 0
		size = size-bytesremaining;  // reduce the size of the bytes
		pos += bytesremaining;  // update the position for the data buffer
		HAL_Delay (4);  // Write cycle delay (5ms)
	}
}

void float2Bytes(uint8_t * ftoa_bytes_temp,float float_variable)
{
    union {
      float a;
      uint8_t bytes[4];
    } thing;

    thing.a = float_variable;

    for (uint8_t i = 0; i < 4; i++) {
      ftoa_bytes_temp[i] = thing.bytes[i];
    }

}

float Bytes2float(uint8_t * ftoa_bytes_temp)
{
    union {
      float a;
      uint8_t bytes[4];
    } thing;

    for (uint8_t i = 0; i < 4; i++) {
    	thing.bytes[i] = ftoa_bytes_temp[i];
    }

   float float_variable =  thing.a;
   return float_variable;
}

void EEPROM_Write_NUM (uint16_t page, uint16_t offset, float data)
{
	float2Bytes(bytes_temp, data);
	EEPROM_Write(page, offset, bytes_temp, 4);
}

 

1 ACCEPTED SOLUTION

Accepted Solutions
Techn
Senior III

May be you shoud replace hal_delay with osDelay , keep one semaphore to indicate that write is in progress, to be cleared after write is completed. Before next write wait on this semaphore.  You can simplify this code by just one i2c write instead of function call. 

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

2 REPLIES 2
Techn
Senior III

May be you shoud replace hal_delay with osDelay , keep one semaphore to indicate that write is in progress, to be cleared after write is completed. Before next write wait on this semaphore.  You can simplify this code by just one i2c write instead of function call. 

If you feel a post has answered your question, please click "Accept as Solution".

Hi Techn,

I am sorry for my late reply, using binary semaphore solved the issue. Thank you very much.