Constant’s value cannot be changed so it’s rational to store it in the FLASH memory rather than in the SRAM. The modifier const tells the compiler that a name represents a constant and it shall be stored in the FLASH memory (in contrary to for example Arduino). As far as I know we cannot change that behaviour of the ARM compiler. Then we can access constants in the code without any additional provisions. We don’t have to specify that they should be read from FLASH (in contrary to for example Arduino).
If your question was how to create a variable (especially an array) in the FLASH memory and access it from the code then one way is to utilize Mbed’s Flash IAP API. But be aware of increased FLASH memory wear out and quite slow write speed (in comparison to using SRAM)!
An example is below:
#include "mbed.h"
FlashIAP flash;
int main() {
printf("Starting...\r\n");
flash.init();
const uint32_t flash_start = flash.get_flash_start();
const uint32_t flash_size = flash.get_flash_size();
const uint32_t flash_end = flash_start + flash_size;
const uint32_t page_size = flash.get_page_size(); // in bytes
uint32_t sector_size = flash.get_sector_size(flash_end - 1); // in bytes
uint32_t addr = flash_end - sector_size; // address of first byte in the last sector
printf("flash_start = 0x%.8x\r\n", flash_start);
printf("flash_size = 0x%.8x\r\n", flash_size);
printf("flash_end = 0x%.8x\r\n", flash_end);
printf("page_size = 0x%.8x\r\n", page_size);
printf("sector_size = 0x%.8x\r\n", sector_size);
printf("addr = 0x%.8x\r\n", addr);
printf("----------------------\r\n");
// Create an array in SRAM (later on to be stored in the first page of last sector in FLASH)
uint32_t data_len = page_size/sizeof(uint32_t); // calculate available space
uint32_t* data = new uint32_t[data_len] {1, 2, 3}; // create an array in SRAM and initialize the first three elements
data[11] = 572; // set element 11 to 572
// Print the first 15 elements
for (int i = 0; i < 15; i++) {
printf("data[%d] = %d\r\n", i, data[i]);
}
// Store the array 'data' in FLASH
flash.erase(addr, sector_size); // erase needs sector_size (not page size)
flash.program(data, addr, page_size); // write needs page_size
printf("----------------------\r\n");
// Clear the first 15 elements in SRAM (to see whether they are going to be updated with values stored in FLASH)
for (int i = 0; i < 15; i++) {
data[i] = 0;
printf("data[%d] = %d\r\n", i, data[i]);
}
printf("----------------------\r\n");
// Update the SRAM array with values stored in FLASH
flash.read(data, addr, page_size); // read needs page_size
// Print the first 15 elements
for (int i = 0; i < 15; i++) {
printf("data[%d] = %d\r\n", i, data[i]);
}
delete[] data;
flash.deinit();
printf("----------------------\r\n");
printf("Done.\r\n");
}
This is helpful, but not quite what I am looking for.
I have a large data structure on the order of 132K uint_32t, or 512K bytes.
If I declare this array const, the compiler allocates it in flash, which is what I want.
If I am not mistaken, the code that accesses this array in flash is identical to the code that accesses the same array in sram if it were not compiled with the const modifier. The arm must have some way to map the memory accesses to flash.
If I write the data to flash and use the flash API to read it into sram, then I have to pay the price of the storage twice – once in flash, and again in sram – if it will even fit in sram.
What I am looking for is a way to provision the data in flash with one app and then access the data from another app as if it were a compiled const array.
Is this possible?
The example you gave me is very useful for a different purpose – for storing a small amount of persistent configuration data. I have one question about this: how do I know it will not be overwritten by compiler const data?
I think the first part (provision the data in flash with one app) is feasible. But I don’t know how to access the data from another app as if it were a compiled const array. The problem is when a const is declared it also must be initialized with data. And that would overwrite the existing data in FLASH.
Get the flash_start and addr as indicated in the example above and make sure that flash_start + Total flash memory used by the program (as reported by the compiler) < addr.
I am currently trying to make a simple project for saving an array in Flash memory and I found your code great for starting with.
I tried using your code in this post but I am getting an Error: Identifier “FlashIAP” is undefined in “main.cpp”, Line: 4, Col: 2
Although FlashIAP belongs to mbed API official library the programm does not even compile. I am posting here in order to check maybe you have come accross with the same problem.
I am using mbed online compiler and Nucleo F334R8 as a target.
I’m sorry, I don’t have good news for your. The FlashIAP is available only in Mbed OS 5. But unfortunately the NUCLEO-F334R8 board does not seem to be supported by Mbed OS 5. I’ve got the following error when trying to compile:
Could not compile for NUCLEO_F334R8: Target does not support mbed OS 5
Are you sure?
I can not test it because I do not have this board but both tools (Online compiler and Mbed Studio) can successfully compile program for this board, with bare metal profile.
And the FlashIAP can be probably added via Mbed_app.json file.