2

I want to write the contents of a struct to flash memory in my C program for STM32F4 Discovery board using HAL libraries. This is my struct:

typedef struct
{
    RTC_TimeTypeDef time;
    RTC_DateTypeDef date;
    float Data;
} DataLogTypeDef;

I have the option to write Byte, Half-Word, Word and Double-Word to each memory address at a time using the stm32f4xx_hal_flash.c library function:

HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data);

My struct contains various data types but I'm not sure how to write the contents using only Byte, Half-Word, Word and Double-Word commands at a time?

b7031719
  • 120
  • 1
  • 2
  • 8
  • You should be able to write it using any one of those methods as long as you write out at least `sizeof(DataLogTypeDef)` bytes of information, and you read it back into a struct in the same way you wrote it and on the same platform (to avoid portability issues). In other words, treat it as a simple block of data. – lurker Jan 11 '19 at 15:55
  • Thanks for the reply. I am not sure how to arrange the data in order for it to be transferred to memory. I am sure it will take several write operations but how do I instruct the program to perform several write operations each with different parts of the overall struct? – b7031719 Jan 11 '19 at 16:02
  • You don't have to arrange it. If your data is declared as `DataLogTypeDef my_data;` then you would write a block of memory to flash from address `&my_data` and that block would be `sizeof(DataLogTypeDef)` bytes long. Read it back the same way on the same platform and you should be fine. – lurker Jan 11 '19 at 16:06
  • Thanks for replying. I can kind of follow what you are describing but I am not sure how to code this. Do you have any examples of how to do this kind of write operation? Thanks again – b7031719 Jan 11 '19 at 16:14
  • I'm not sure what the arguments in your flash programming function mean, but suppose you had a function `write_flash(from_address, to_address, number_of_bytes)` you would just call, `write_flash(&my_data, flash_address, sizeof(DataLogTypeDef))`. – lurker Jan 11 '19 at 16:24
  • OK I understand the confusion now, the write function is something like `write_flash(data_type, to_address, my_data);` where data_type and my_data are the same size. – b7031719 Jan 11 '19 at 16:30
  • But `my_data` is what? A pointer to the data? Or are you passing the entire block of data on the stack? And what does the `read_flash` look like? – lurker Jan 11 '19 at 16:43
  • Thanks again. `my_data` is the actual data to be stored in flash memory using this library function. `read_flash` looks like this
    `uint32_t Flash_Read(uint32_t Flash_Address) { uint32_t* Flash_Data = (uint32_t*) Flash_Address; return *Flash_Data; }`
    – b7031719 Jan 11 '19 at 16:49
  • So you are passing the entire contents of the structure of data on the stack to the flash writing function? – lurker Jan 11 '19 at 18:09
  • OK I'm not 100% certain what you are asking because I am not completely sure about stack / heap memory management in C. From what I understand the answer is yes in this case unless there is an alternative way. Thanks – b7031719 Jan 11 '19 at 18:32
  • If `my_data` is a structure and you pass `my_data` as a C function parameter, most C compilers (with some embedded system C compiler exceptions) will push the entire contents of `my_data` onto the stack before the function call. – lurker Jan 11 '19 at 19:54
  • Is `data_type` what defines byte, word, or double word? – lurker Jan 11 '19 at 19:55
  • Thanks again. Yes data_type is what defines byte, word or double-word. – b7031719 Jan 11 '19 at 20:08

2 Answers2

3

What you have is a flash writing function that will write a byte, word, or double word.

If you want to write your structure to flash the simplest way is to view it as a buffer of bytes or words as long as you read it back the same way on the same platform (and with the same C compiler and compile options). Why the same platform? Because different computer platforms can have a different byte ordering for multi-byte values. Why the same compiler and compiler options? Because a different compiler or different options might pack the data in a struct differently.

So with that in mind, and keeping in mind there's a lot of details you haven't provided regarding how your flash writer should be called, your code might look like this to copy the structure to flash:

DataLogTypeDef my_data;

...

int i;
uint8_t *data_p = &my_data;
flash_address = //put first flash address here

for ( i = 0; i < sizeof(DataLogTypeDef); i++, data_p++, flash_address++ )
    HAL_FLASH_Program(type_byte, flash_address, *data_p);

I don't know what the values are for the first two arguments, so I just put type_byte and flash_address. I'm also assuming flash address is an integer form and is a byte address.

If you want to read the structure back, it might look something like this:

// Initialize i, data_p, and flash_address first

for ( i = 0; i < sizeof(DataLogTypeDef); i++, data_p++, flash_address++ )
    *data_p = Flash_read(flash_address);
lurker
  • 56,987
  • 9
  • 69
  • 103
1

Unfortunately flash lib stm32f4xx_hal_flash.c only can write:

  • half word (two bytes)
  • word
  • double word

And can not write record byte for byte.

I write two methods for read and write struct:

void ReadRecord(SensorData *pSD, uint32_t flash_address)
{
    uint32_t *ptr = (uint32_t* )pSD;

  for (int i = 0; i < sizeof(SensorData); i+=4, ptr++, flash_address+=4 )   
     *ptr = FlashRead(flash_address);
}

void WriteRecord(SensorData *pSD, uint32_t address)
{
    int i;
    uint32_t *pRecord = (uint32_t* )pSD;  
    uint32_t flash_address = address;

    HAL_FLASH_Unlock();
    for(i=0; i<sizeof(SensorData); i+=4, pRecord++, flash_address+=4)
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, flash_address,*pRecord);
    HAL_FLASH_Lock();       
}

They was check in debugger. Type int read and write good, but float read back with little error in last one or two digit after coma.