2023-03-19 05:20 AM
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.
#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++;
}
}
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;
}
}
}
Solved! Go to Solution.
2023-03-19 06:20 AM
Pretty sure the sizeof() here doesn't know the array size
Couldn't you just cast the array directly?
2023-03-19 05:50 AM
sizeof() is the size in bytes, if you multiply it and do a byte copy you will overflow the buffer.
2023-03-19 06:04 AM
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?
2023-03-19 06:13 AM
No, this reads 200 bytes, and overflows
printf("%d\n", sizeof(Holding_Registers_Database_test) * sizeof(uint16_t) );
2023-03-19 06:15 AM
Also, if you use a structure/pointer you can read the values directly from the flash
2023-03-19 06:20 AM
Pretty sure the sizeof() here doesn't know the array size
Couldn't you just cast the array directly?