How to read initialization data values for variables? I want to know if the value of a variable has changed, compared to the initialization value.
Global var:
int abc = 124;
In stm32:
address VAR in data (flash) = "start section of data in flash" + ("address VAR in ram" - "start data section in ram") =>
* "address VAR in data (flash)" = 124
Reading initialization data (in flash) for variables
-
- Posts: 9746
- Joined: Thu Nov 26, 2015 4:08 am
Re: Reading initialization data (in flash) for variables
I'd simply use a define to do this, e.g.
There's ways to find the variable in the data section of the app in flash, for sure, but those are really dependent on the partition scheme, OTA setup, linker script stuff etc. It's possible to handle all that, but it's a fragile setup, so I'd advise you not to go that route.
Code: Select all
#define MY_VAR_INIT_VAL 123
int my_var=MY_VAR_INIT_VAL;
void check() {
if (my_var!=MY_VAR_INIT_VAL) printf("Changed!\n");
}
Re: Reading initialization data (in flash) for variables
Thanks for reply!
I have a lot of variables. Lots of code from code generator. This may increase read-only data and searches are needed!
Would like to be able to access the data section in flash.
I have a lot of variables. Lots of code from code generator. This may increase read-only data and searches are needed!
Would like to be able to access the data section in flash.
Re: Reading initialization data (in flash) for variables
And if you declare a section in an ld script, and declare variables in this section. Is there an example of a section declaration and how to declare variables?
-
- Posts: 9746
- Joined: Thu Nov 26, 2015 4:08 am
Re: Reading initialization data (in flash) for variables
Well, another non-hacky way you could do this for multiple variables is to put all variables in a struct, define a variable according to this struct with the initial values in it as const so it's put in RO memory, then manually memcpy those values into a 2nd variable in RAM. This also has the advantage of namespacing all those 'special' variables into a struct.
If you still insist on doing it by digging through the app code manually, it's really a lot more difficult than on the STM32, as the flash doesn't contain exactly what's mapped in memory, to make things like OTA easier. The steps would roughly be:
- Find out which application partition in flash you're running from.
- Read the application header and parse it.
- Read out and parse the chunks the application consists of. Find the chunk that contains the address of your variable.
- Read out the chunk at the correct offset
- Compare with the variable.
Note that as the flash sections containing all of this by default are not memory mapped, you'd either have to manually memory map them or read the data using the spiflash api.
Code: Select all
typedef struct my_variables_t {
int var1;
int var2;
};
const my_variables_t initial_values={ //will live in flash because 'const'
.var1=123,
.var2=456,
};
my_variables_t values;
void on_startup() {
memcpy(&values, &initial_values, sizeof(my_variables_t));
}
void check_same() {
if (values.var1!=initial_values.var1) printf("Changed var1!\n");
if (values.var2!=initial_values.var2) printf("Changed var2!\n");
}
- Find out which application partition in flash you're running from.
- Read the application header and parse it.
- Read out and parse the chunks the application consists of. Find the chunk that contains the address of your variable.
- Read out the chunk at the correct offset
- Compare with the variable.
Note that as the flash sections containing all of this by default are not memory mapped, you'd either have to manually memory map them or read the data using the spiflash api.
Re: Reading initialization data (in flash) for variables
I have memory mapped running partition, but depending on where I defined magic_word variable I get different results.
For example, when I define magic_word in main.c I get incorrect results.
But when I define it elsewhere this code seems to work.
I search entire partition without parsing headers. Address where I find magic_word is in data section.
For example, when I define magic_word in main.c I get incorrect results.
But when I define it elsewhere this code seems to work.
I search entire partition without parsing headers. Address where I find magic_word is in data section.
- uint32_t magic_word = 0xDEADBEEF;
- uint32_t* pmagic_word = &magic_word;
- void example_function(void *data){
- esp_partition_t *partition = esp_ota_get_running_partition();
- uint32_t *flash_magic;
- spi_flash_mmap_handle_t map_handle;
- // Map the partition to data memory
- esp_partition_mmap(partition, 0, partition->size, SPI_FLASH_MMAP_DATA, (void *)&flash_magic, &map_handle));
- ESP_LOGE("MMAP", "Mapped partition to data memory address %p", flash_magic);
- assert(partition != NULL);
- ESP_LOGE("MAGIC IN FLASH", "Searching for magic word %08X in flash", magic_word);
- while ((*flash_magic) != magic_word){
- flash_magic++;
- }
- ESP_LOGE("MAGIC IN FLASH", "Found magic in flash at address %p, value = %08x", (void *)flash_magic, *flash_magic);
- //offset in RAM
- int32_t offset = (pmagic_word - (uint32_t *)data);
- res = (memcmp (data, (void*) ((uint32_t) flash_magic - offset), size) == 0 ? false : true);
- ESP_LOGE("OUTPUT", "address in FLASH %p", (void*) ((uint32_t) flash_magic - offset);
- ESP_LOGE("OUTPUT", "value in FLASH %08x", *(uint32_t *)((uint32_t) flash_magic - offset);
- ESP_LOGE("OUTPUT", "value in RAM %08x", *(uint32_t *)data);
- ESP_LOGE("OUTPUT", "res is %d", res);
- }
-
- Posts: 9746
- Joined: Thu Nov 26, 2015 4:08 am
Re: Reading initialization data (in flash) for variables
I can't help you aside from saying this is a really brittle solution. You're assuming that the C compiler and linker do things (like allocate sequential variables in sequential addresses, or even allocate variables at all, and the linker not splitting up memory ranges into different appfile chunks) that aren't by any means guaranteed, as you noticed.
Who is online
Users browsing this forum: Google [Bot] and 100 guests