I feel that the flash examples on the sdk are not so informative as how and why do things to beginners, so I'm gonna try to show the basics of operating with the flash.
Storing data
To store data, you need to choose a flash memory region to do so. I think it's safe to assume you can choose right after your program (it lives at the beginning of the flash), but even with this simple idea you should plan for it to grow over time. I'm trying to leave 512K for the program (which is a lot! even with a lot of libraries) on the example. The raspberry pico has 2MB of flash, so there is plenty of room.
The code is not tested, it should be viewed as a general idea. Please note that the examples assume your user data lives as a global variable to simplify things.
As you're gonna see, we need to erase the whole area we need to write to, and after that we can write the data: it's a flash memory related behaviour. The sdk allows us to erase in flash sectors size multiples and write in flash page size multiples.
Code: Select all
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/flash.h" // for the flash erasing and writing
#include "hardware/sync.h" // for the interrupts
#define FLASH_TARGET_OFFSET (512 * 1024) // choosing to start at 512K
struct MyData {
int some_int;
char some_string[40];
long some_long_int;
};
MyData myData;
void saveMyData() {
uint8_t* myDataAsBytes = (uint8_t*) &myData;
int myDataSize = sizeof(myData);
int writeSize = (myDataSize / FLASH_PAGE_SIZE) + 1; // how many flash pages we're gonna need to write
int sectorCount = ((writeSize * FLASH_PAGE_SIZE) / FLASH_SECTOR_SIZE) + 1; // how many flash sectors we're gonna need to erase
printf("Programming flash target region...\n");
uint32_t interrupts = save_and_disable_interrupts();
flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE * sectorCount);
flash_range_program(FLASH_TARGET_OFFSET, myDataAsBytes, FLASH_PAGE_SIZE * writeSize);
restore_interrupts(interrupts);
printf("Done.\n");
}
Reading back data
This is easy peasy. The data is simply available at a memory region for us to read, even right after writing to the flash. So let's be happy.
Code: Select all
void readBackMyData() {
const uint8_t* flash_target_contents = (const uint8_t *) (XIP_BASE + FLASH_TARGET_OFFSET);
memcpy(&myData, flash_target_contents + FLASH_PAGE_SIZE, sizeof(myData));
}
Please feel free to correct or add to it. I hope you enjoy it.
Roberto Buaiz