0

I am trying to store data in flash memory on a STM32F411VET6. I want the memory to store and stay there even after rebooting the MC. I have looked at this, this, this and this examples but I am still not sure that I am doing this correctly. I was able to create a location in memory (I checked in the map file) with this as my scatter file:

LR_IROM1 0x08000000 0x00080000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00060000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  USER_CONFIG 0x08060000 0x0001FFFF  {
   userConfig.o (+RW)
  }
  RW_IRAM1 0x20000000 0x00020000  {  ; RW data
   .ANY (+RW +ZI)
  }
}

and this for my code (adapted from this example):

__attribute__((__section__("USER_CONFIG"))) const char userValues[64];

void Write_Flash(uint32_t data[], uint8_t flashTypeProgram)
{
  uint8_t addressGap;
  HAL_FLASH_Unlock();
  __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR);
  FLASH_Erase_Sector(FLASH_SECTOR_7, VOLTAGE_RANGE_3);
  int ii = 0;
  for (ii = 0; ii < 64 / pow(2, flashTypeProgram); ii++)
  {
    addressGap = pow(2, flashTypeProgram) * ii;
    HAL_FLASH_Program(flashTypeProgram, userValues[0] + addressGap, data[ii]);
  }
  HAL_FLASH_Lock();
}

but whenever I build the code I get an error that "No section matches pattern userConfig.o".

Is there anything that I am setting up incorrectly or why if I am missing a call somewhere?

glts
  • 21,808
  • 12
  • 73
  • 94
Nibble
  • 33
  • 1
  • 5
  • `userValues[0] + addressGap` this should be `&userValues[0] + addressGap` or better `$userValues[addressGap]`.... The linker file is not really needed for anything. What is `userConfig.o` supposed to be? What is that `section` gcc specifier for? `pow(2, flashTypeProgram)` - this is bad, I know the compiler may optimize it, however it casts the arguments to float, which is unneded here. Also why `64/` ? – KamilCuk Feb 20 '19 at 15:53
  • From what I understood it is an object file. I was under the impression that I needed this in order to be able to access (sorry I am not sure if that is the correct term) the location in memory. I tried adding the "&" in from of userValues[0] but I get an error saying "incompatible pointer to integer conversion..." – Nibble Feb 20 '19 at 15:55
  • If you use `HAL_FLASH_Program` you don't need linker for anything - you can write to any location in memory. And the linker can't stop you. `incompatible pointer to integer conversion...` - 1. Post full error message, 2. `HAL_FLASH_Program` takes `uin32_t` argument - you need to cast your pointer. – KamilCuk Feb 20 '19 at 15:56
  • Oops, somehow casting completely slipped my mind :). Thanks for that. On another note, since HAL_FLASH_Program doesn't need a linker, would I need to put any information into the linker file? – Nibble Feb 20 '19 at 16:02
  • No? The only use case I would see, if you want the `USER_CONFIG` section to start at a specified location in the memory. But I don't think you care about the exact location, just only so it is there and is not used. – KamilCuk Feb 20 '19 at 16:03

1 Answers1

1

I was able to get the solution with some help from Kamil Cuk that helped me solve some issues. One of the problems I was experiencing with the scatter file was that my load and execution addresses were not the same causing linker to not work as intended (very well explained in this link). I modified my .sct file to the following:

LR_IROM1 0x08000000 0x00060000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00060000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  RW_IRAM1 0x20000000 0x00020000  {  ; RW data
   .ANY (+RW +ZI)
  }
}

LR_IROM2 0x08060000 0x00020000 {  ; load region size_region
  USER_CONFIG 0x08060000 0x00020000  {
   *(.user_data)
  }
}

This implementation where an additional load region was created would cause my load address and exception address to be the same.

Then, in case someone comes here looking for help as well, here is my code for the flashing:

__attribute__((section(".user_data"))) const char userConfig[64];

[...]

void Write_Flash(uint32_t data[], uint8_t flashTypeProgram)
{
  uint8_t addressGap;
  HAL_FLASH_Unlock();
  __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR);
  FLASH_Erase_Sector(FLASH_SECTOR_7, VOLTAGE_RANGE_3);
  int ii = 0;
  for (ii = 0; ii < 64 / pow(2, flashTypeProgram); ii++)
  {
    addressGap = pow(2, flashTypeProgram) * ii;
    HAL_FLASH_Program(flashTypeProgram, (uint32_t) &userConfig[0] + addressGap, data[ii]);
  }
  HAL_FLASH_Lock();
}

This program allowed me to store data in internal flash which would remain stored even after a hard reboot where all power was disconnected and then reconnected to the board.

Nibble
  • 33
  • 1
  • 5