cancel
Showing results for 
Search instead for 
Did you mean: 

Floating values ​​when writing to memory STM32L422KBT6

YShe.1
Associate II

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

1 ACCEPTED SOLUTION

Accepted Solutions

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
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

5 REPLIES 5

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
Up vote any posts that you find helpful, it shows what's working..

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?

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
Up vote any posts that you find helpful, it shows what's working..

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
Up vote any posts that you find helpful, it shows what's working..

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
Up vote any posts that you find helpful, it shows what's working..