Reading initialization data (in flash) for variables

bullit
Posts: 3
Joined: Mon Apr 18, 2022 5:15 am

Reading initialization data (in flash) for variables

Postby bullit » Mon Apr 18, 2022 5:39 am

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

ESP_Sprite
Posts: 9746
Joined: Thu Nov 26, 2015 4:08 am

Re: Reading initialization data (in flash) for variables

Postby ESP_Sprite » Mon Apr 18, 2022 7:15 am

I'd simply use a define to do this, e.g.

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");
}
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.

bullit
Posts: 3
Joined: Mon Apr 18, 2022 5:15 am

Re: Reading initialization data (in flash) for variables

Postby bullit » Mon Apr 18, 2022 7:36 am

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.

bullit
Posts: 3
Joined: Mon Apr 18, 2022 5:15 am

Re: Reading initialization data (in flash) for variables

Postby bullit » Mon Apr 18, 2022 7:52 am

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?

ESP_Sprite
Posts: 9746
Joined: Thu Nov 26, 2015 4:08 am

Re: Reading initialization data (in flash) for variables

Postby ESP_Sprite » Mon Apr 18, 2022 7:58 am

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.

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");
}

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.

oedipus
Posts: 3
Joined: Mon Apr 18, 2022 9:05 am

Re: Reading initialization data (in flash) for variables

Postby oedipus » Mon Apr 18, 2022 9:55 am

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.
  1. uint32_t magic_word = 0xDEADBEEF;
  2. uint32_t* pmagic_word = &magic_word;
  3.  
  4. void example_function(void *data){
  5.     esp_partition_t *partition = esp_ota_get_running_partition();
  6.     uint32_t *flash_magic;
  7.     spi_flash_mmap_handle_t map_handle;
  8.  
  9.     // Map the partition to data memory
  10.     esp_partition_mmap(partition, 0, partition->size, SPI_FLASH_MMAP_DATA, (void *)&flash_magic, &map_handle));
  11.     ESP_LOGE("MMAP", "Mapped partition to data memory address %p", flash_magic);
  12.     assert(partition != NULL);
  13.  
  14.     ESP_LOGE("MAGIC IN FLASH", "Searching for magic word %08X in flash", magic_word);
  15.     while ((*flash_magic) != magic_word){
  16.       flash_magic++;
  17.     }
  18.     ESP_LOGE("MAGIC IN FLASH", "Found magic in flash at address %p, value = %08x", (void *)flash_magic, *flash_magic);
  19.    
  20.     //offset in RAM
  21.     int32_t offset = (pmagic_word - (uint32_t *)data);
  22.    
  23.  
  24.     res = (memcmp (data, (void*) ((uint32_t) flash_magic - offset), size) == 0 ? false : true);
  25.  
  26.     ESP_LOGE("OUTPUT", "address in FLASH %p", (void*) ((uint32_t) flash_magic - offset);
  27.     ESP_LOGE("OUTPUT", "value in FLASH %08x", *(uint32_t *)((uint32_t) flash_magic - offset);
  28.     ESP_LOGE("OUTPUT", "value in RAM %08x", *(uint32_t *)data);
  29.     ESP_LOGE("OUTPUT", "res is %d", res);
  30. }

ESP_Sprite
Posts: 9746
Joined: Thu Nov 26, 2015 4:08 am

Re: Reading initialization data (in flash) for variables

Postby ESP_Sprite » Tue Apr 19, 2022 3:42 am

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: Bing [Bot] and 81 guests