Skip to main content
YShe.1
Associate II
March 19, 2023
Solved

Floating values ​​when writing to memory STM32L422KBT6

  • March 19, 2023
  • 5 replies
  • 2513 views

Hello, well I have some array of uint16_t data with is contains 50 records. If I truing to write it to the flash memory it looks like it have done an then if I write again, the HEX data in debug mode memory is randombly chenging. Ideally Firstly I need read data from flash(after power off) and write to array, on another iteration if data in array != data in flash, then overwrite flash. To put it sumply this is for manage/store a data in flash. Please help me.

  • Function for writing in memory:
#define FLASH_START_ADDRESS 0x08010000
 
static uint32_t GetPage(uint32_t Addr) // Single Bank Device
{
 return ((Addr - FLASH_BASE) / FLASH_PAGE_SIZE);
}
 
// Function to write data to the flash memory
// BYTE pointer, Size in BYTES, put what you want in a STRUCTURE
 
void write_flash(uint8_t *data, uint32_t size)
{
 FLASH_EraseInitTypeDef EraseInitStruct = {0};
 uint32_t addr = FLASH_START_ADDRESS; // 64-bit aligned
 uint64_t value;
 uint32_t PageError;
 
 // Round up size to nearest multiple of 64 bytes
 size = (size + 63) & ~63;
 
 // Calculate number of 64-bit words to write
 uint32_t num_words = size / sizeof(uint64_t);
 
 // Unlock the flash memory for writing
 HAL_FLASH_Unlock();
 
 /* Clear OPTVERR bit set on virgin samples */
 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
 
 /* Fill EraseInit structure, spanning size of write operation */
 EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
 EraseInitStruct.Banks = FLASH_BANK_1;
 EraseInitStruct.Page = GetPage(addr); // Starting Page
 EraseInitStruct.NbPages = GetPage(addr + size) - EraseInitStruct.Page + 1; // Page Count, at least 1
 
 if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
 {
 // Insert code to handle the error here
 
 HAL_FLASH_Lock();
 return;
 }
 
 // Iterate over the array of data and write each element to the flash memory
 for (uint32_t i = 0; i < num_words; i++)
 {
 memcpy(&value, data, sizeof(uint64_t)); // alignment safe copy of byte array into 64-bit value
 
 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, value) != HAL_OK)
 {
 // Insert code to handle the error here
 
 HAL_FLASH_Lock();
 return;
 }
 
 addr += sizeof(uint64_t); // Advance address
 data += sizeof(uint64_t); // Advance byte buffer
 }
 
 // Lock the flash memory after writing is complete
 HAL_FLASH_Lock();
}
 
void read_flash(uint8_t *data, uint32_t size)
{
 memcpy(data, (void*)FLASH_START_ADDRESS, size);
}
 
 
void convert_uint16_to_uint8(uint16_t *src, uint8_t *dst)
{		
		uint32_t size = sizeof(*src);
 for (uint32_t i = 0; i < size; i++)
 {
 *dst++ = (uint8_t)(*src >> 8);
 *dst++ = (uint8_t)(*src & 0xFF);
 src++;
 }
}
 
void convert_uint8_to_uint16(uint8_t *src, uint16_t *dst)
{
		uint32_t size = sizeof(*src);
 for (uint32_t i = 0; i < size; i++)
 {
 *dst++ = (uint16_t)(*src++ << 8) | *src++;
 }
}
  • Function for put data through writing function
void flash_holding_registers()
{
	
	static uint16_t Holding_Registers_Database_test[50]={
		0000, 1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999, // 0-9 40001-40010
		12345, 15432, 15535, 10234, 19876, 13579, 10293, 19827, 13456, 14567, // 10-19 40011-40020
		21345, 22345, 24567, 25678, 26789, 24680, 20394, 29384, 26937, 27654, // 20-29 40021-40030
		31245, 31456, 34567, 35678, 36789, 37890, 30948, 34958, 35867, 36092, // 30-39 40031-40040
		45678, 46789, 47890, 41235, 42356, 43567, 40596, 49586, 48765, 41029, // 40-49 40041-40050
};
	
	// Buffer array with extend from uint16_t to uint8_t
	uint8_t converted_data_uint8_t[sizeof(Holding_Registers_Database_test) * sizeof(uint16_t)]; //2 for uint16_t; 2 for uint32_t
 
	// Buffer array to compare valves RAM and ROM convertation from uint16_t to uint8_t
	uint8_t compare_data_uint8_t[sizeof(Holding_Registers_Database_test) * sizeof(uint16_t)]; //2 for uint16_t; 2 for uint32_t
	
	// Convert Holding_Registers_Database from an array of uint16_t values to an array of uint8_t values
	convert_uint16_to_uint8(Holding_Registers_Database_test, converted_data_uint8_t);
	
	// Read 100 bytes of data from the flash memory
	read_flash(compare_data_uint8_t, sizeof(Holding_Registers_Database_test) * sizeof(uint16_t));
	
 for (uint32_t i = 0; i < sizeof(Holding_Registers_Database_test); i++){
		if (converted_data_uint8_t[i] != compare_data_uint8_t[i]) {
					// Write the converted data to the flash memory
					write_flash(converted_data_uint8_t, sizeof(Holding_Registers_Database_test) * sizeof(uint16_t));
					convert_uint8_to_uint16(converted_data_uint8_t, Holding_Registers_Database_test);
					return;
		}
	}
	
}
  • How the data change if array is constant after iteration:

0693W00000aJH4vQAG.png

This topic has been closed for replies.
Best answer by Tesla DeLorean

Pretty sure the sizeof() here doesn't know the array size

  1. void convert_uint16_to_uint8(uint16_t *src, uint8_t *dst)
  2. {
  3. uint32_t size = sizeof(*src);
  4. for (uint32_t i = 0; i < size; i++)

Couldn't you just cast the array directly?

5 replies

Tesla DeLorean
Guru
March 19, 2023

sizeof() is the size in bytes, if you multiply it and do a byte copy you will overflow the buffer.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
YShe.1
YShe.1Author
Associate II
March 19, 2023

Yes, thank you for your yesterday code. Even your original code:

/**
 * @brief Gets the page of a given address
 * @param Addr: Address of the FLASH Memory
 * @retval The page of a given address
 */
static uint32_t GetPage(uint32_t Addr) // Single Bank Device
{
 return((Addr - FLASH_BASE) / FLASH_PAGE_SIZE);
}
 
// Function to write data to the flash memory
// BYTE pointer, Size in BYTES, put what you want in a STRUCTURE
 
void write_flash(uint8_t *data, uint32_t size)
{
 FLASH_EraseInitTypeDef EraseInitStruct = {0};
 uint32_t addr = FLASH_START_ADDRESS; // 64-bit aligned 
 uint64_t value;
 uint32_t PageError;
 
 size = (size + 7) & ~7; // Round to 64-bit words
 
 // Unlock the flash memory for writing
 HAL_FLASH_Unlock();
 
 /* Clear OPTVERR bit set on virgin samples */
 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
 
 /* Fill EraseInit structure, spanning size of write operation */
 EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
 EraseInitStruct.Banks = FLASH_BANK_1;
 EraseInitStruct.Page = GetPage(addr); // Starting Page
 EraseInitStruct.NbPages = GetPage(addr + size) - EraseInitStruct.Page + 1; // Page Count, at least 1 
 
 if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
 {
 // Insert code to handle the error here
 
 HAL_FLASH_Lock();
 return;
 }
	
 size /= sizeof(uint64_t); // Byte count to 64-bit word count
 
 // Iterate over the array of data and write each element to the flash memory
 while(size--)
 {
 memcpy(&value, data, sizeof(uint64_t)); // alignment safe copy of byte array into 64-bit value
 
 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, value) != HAL_OK)
 {
 // Insert code to handle the error here
 
 HAL_FLASH_Lock();
 return;
 }
 
 
 addr += sizeof(uint64_t); // Advance address
 data += sizeof(uint64_t); // Advance byte buffer
 }
 
 // Lock the flash memory after writing is complete
 HAL_FLASH_Lock();
}

With:

size = (size + 7) & ~7; // Round to 64-bit words

Got simular result for me. Any ideas please?

Tesla DeLorean
Guru
March 19, 2023

No, this reads 200 bytes, and overflows

  1. // Read 100 bytes of data from the flash memory
  2. read_flash(compare_data_uint8_t, sizeof(Holding_Registers_Database_test) * sizeof(uint16_t));

printf("%d\n", sizeof(Holding_Registers_Database_test) * sizeof(uint16_t) );

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
March 19, 2023

Also, if you use a structure/pointer you can read the values directly from the flash

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Tesla DeLoreanBest answer
Guru
March 19, 2023

Pretty sure the sizeof() here doesn't know the array size

  1. void convert_uint16_to_uint8(uint16_t *src, uint8_t *dst)
  2. {
  3. uint32_t size = sizeof(*src);
  4. for (uint32_t i = 0; i < size; i++)

Couldn't you just cast the array directly?

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..