How to write a variable to a specific address in Keil

Occasionally, the task arises to save a checksum, a picture, a line of text, a setting in flash memory. Sometimes the task arises to save not just in RAM, but in a certain area, for example, to enable / disable DCACHE for this area. Or, for example, have a function executed from RAM so that you can send it via UART and immediately execute a new function code.

Let’s consider the problem with examples. The test subject will be the folk stm32f401ret6 with the following flash memory addressing (page 51 datasheet):

#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) //Sector 0, 16 Kbytes
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) //Sector 1, 16 Kbytes
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) //Sector 2, 16 Kbytes
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) //Sector 3, 16 Kbytes
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) //Sector 4, 64 Kbytes
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) //Sector 5, 128 Kbytes

In Keil, this can be done in different ways. Zero path – via GUI by editing project options – very limited, we will not consider.

The first way is manual:
uint32_t keyFlash __attribute__((at(0x08004000))) = 0xAABBCCDD;
Here we have written the 32-bit number 0xAABBCCDD at address 0x08004000.

Another way is to use a scatter file. The theory can be read here. It is also desirable to understand what an object file is. Quite in a nutshell, after the work of the preprocessor-> compiler, a set of
*.o files
where the asterisk means any name. For example, from main.c you get the file main.o

Consider an example of a scatter file. This file was obtained from the default scatter file that Keil itself generates. Then an execution region was added to it, which I decided to call MYREGION. This region has a section called mysection, which is searched for in all object files. If the linker finds a syntactic unit (read variable) from this section, then this syntactic unit will fall into the MYREGION region.
LR_IROM1 0x08000000 0x08001000 { ; load region size_region
ER_IROM1 0x08000000 0x00080000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}

RW_IRAM1 0x20000000 0x00000900 { ; RW data
.ANY (+RW+ZI)
}

MYREGION 0x0800C000 FIXED {
*.o (mysection)
}
}

And now, in the main.c file, we will get our syntactic unit for storage in the region:
const uint16_t ADC_Buf[7] __attribute__((section("mysection"))) = {0xDDDD, 0xDDDD, 0xDDDD, 0xDDDD, 0xDDDD, 0xDDDD, 0xDDDD};

And here we have a trap. We love a high-level language for its optimization. We include -O3 and our unused constant in the program disappears. Here is a case when you can say “too smart” about a toolchain. To explain that in the mysection section we have everything we need, let’s go to the Linker tab in Misc controls and write
–keep=”main.o(mysection)”

Keil project properties
Keil project properties

Occasionally there is a situation when we want to limit the distribution of the region only to syntactic units from a certain file, let main.c then instead of
MYREGION 0x0800C000 FIXED {
*.o (mysection)
}

write
MYREGION 0x0800C000 FIXED {
main.o (mysection)
}

And you can, for example, make all the variables from the file main.c live in your section like this
MYREGION 0x0800C000 FIXED {
main.o(+RW +ZI)
}

When testing, do not forget to do Full chip erase to accurately clean all flash:

Source.

For those who are interested in the topic of scatter files, I suggest an exercise. You must have written the program blinking LED. I suggest that you write one program that works correctly: turns on and off the LED, And the second program will turn on and turn on the LED:

void blink(){
  while(1){
    on();
    delay();
    on();
    delay();
  }
}

After that, I suggest that you look at the contents of the memory and find the difference with your eyes. Next, place blink() using the scatter file in RAM, let it run from there. Then, before calling the blink() function in main() , try writing code to fix blink() so that it turns on and off. Write about your (un)successes in pm or comments, maybe you will get another note.

Also might be helpful
https://radiohlam.ru/stm32_1/

Additional materials:
How do not initialize variables in kayla?
About the word FIXED

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *