earlephilhower / arduino-pico

Raspberry Pi Pico Arduino core, for all RP2040 and RP2350 boards
GNU Lesser General Public License v2.1
1.97k stars 410 forks source link

#define PICO_FLASH_SIZE_BYTES #1399

Closed Ing-Dom closed 1 year ago

Ing-Dom commented 1 year ago

I'm not sure what is the best solution, but I found the value of PICO_FLASH_SIZE_BYTES missleading, because it is set to 2MB regardless of the board configuration: https://github.com/raspberrypi/pico-sdk/blob/master/src/boards/include/boards/pico.h#L73-L75

Maybe it would be good to set it in the core according to the user's selection of HW and flash configuration.

open for discussion...

traxanos commented 1 year ago

My expectation would be, that the parameter "board_build.flash_size" would be used for this.

maxgerhardt commented 1 year ago

Technically, the linker script provides the symbol _EEPROM_start per

https://github.com/earlephilhower/arduino-pico/blob/f33dfd2313de853af8f50650fd2f6dabf788130d/lib/memmap_default.ld#L24-L31

and since the EEPROM always starts 4096 bytes before the end of flash, and the start of flash is at the known address 0x10000000, I think one could calculate it as something like

extern uint32_t _EEPROM_start;
uint32_t flash_size_bytes = (uint32_t)(&_EEPROM_start) - 0x10000000lu + 4096lu;

On the other hand, best to set the PICO_FLASH_SIZE_BYTES macro properly (though changing this macro at Arduino-Pico build time would not affect the precompiled pico-sdk library if it was being used in there).

earlephilhower commented 1 year ago

That's a fair request, I'd say. You have to be aware, though, that the SDK is compiled with a fixed 16MB size since OTW I'd need a whole new libpico.a for every board memory size. (The SDK only uses it to check you don't write past the end of flash, and to store the Bluetooth paining info in the last sector...which is overridden here to store in the app itself since the last sector for us is EEPROM).

Ing-Dom commented 1 year ago

that are very usefull information. I wasn't aware that the SDK is precompiled.

Do you think it would be good to have some defines or symbols defined by the core so the user can easily access this flash layout information? Or should we go for an own solution?

The reason I'm asking is that for OpenKNX we have a advanced usage of the flash, not only programm code and littleFS but also some areas where we directly want to read / write flash. Obviously, we want to make sure that there are no collisions. Also for users (developers) which do not dive deep into flash adresses...

And here we are getting to the next question: is there a good way to have a flash layout not following the scheme "flash / littlefs / eeprom" ? By specifying board_upload.maximum_size = 16777216; board_build.filesystem_size = 8388608; I can change maximum size and the share for flash and littlefs, but I cannot define gaps...

is there a way to do that without messing with the boards.txt ?

maxgerhardt commented 1 year ago

The boards.txt has explicit start addresses defined for LittleFS and EEPROM, so you can have a layout with

sketck | [empty space] | littlefs | [empty space] | eeprom

The makeboards.py just calculates these start values to have no gaps.

https://github.com/earlephilhower/arduino-pico/blob/f33dfd2313de853af8f50650fd2f6dabf788130d/tools/makeboards.py#L15-L20

Same as I do in platfom-raspberrypi

https://github.com/maxgerhardt/platform-raspberrypi/blob/9dc638d6bad895b294db28e91dbdd6d89843f40f/builder/main.py#L71-L73

So yes if you modify the boards.txt or the PlatformIO logic (or an add an extra script that overwrites `env["__fetch_fs_size"] I guess) you can do that.

earlephilhower commented 1 year ago

Do you think it would be good to have some defines or symbols defined by the core so the user can easily access this flash layout information? Or should we go for an own solution?

No, that would be a bad idea. The Arduino user should not be messing around with raw flash, that's what the helper libs are for (EEPROM, LittleFS, Bluetooth). You're welcome to write whatever you want in your code, of course, but it's on you if you overwrite some of your code or critical filesystem structures.

Ing-Dom commented 1 year ago

ok, do I get it right when I say your core is designed for only libs in your core using raw flash. All others should not use raw flash but littlefs as a HAL ?

While I perfectly understand this approach because it is reducing complexity, it is giving me a little headache how to fit that with my needs to have raw flash access due to performance...

Do you think that the core could provide an option to have a raw flash section free for the application/3rd party libs to use?

traxanos commented 1 year ago

i think it would be enough if i could check in the program code how much flash is occupied in the front by the sketch. so i can validate overlappingg in our lib.

earlephilhower commented 1 year ago

my needs to have raw flash access due to performance...

FWIW, If you are writing to flash, the overhead from LittleFS should be insignificant compared to the erase/write cycles in these QSPI tiny, cheap flash chips. And don't forget that if you're doing 2 core operation, you need to stop the 2nd core from running code from flash during the flash operations.

@traxanos 's suggestion makes sense. You have from end of app to the beginning of FS or EEPROM to do with as you wish (modulo 4K, of course). Adding an unused area explicitly would not be of use to other users, IMHO, so I'm quite against adding another menu option for that.

Another thing, if you have a limited amount of flash needed, why not use the trick I used for the Bluetooth Pairing(TLV) stack? Allocate it in your code on 4K boundaries and work w/it as you want. See https://github.com/earlephilhower/arduino-pico/blob/master/cores/rp2040/sdkoverride/btstack_flash_bank.cpp

Ing-Dom commented 1 year ago

for your understanding why we need direct access - we need to save values into flash at power loss. There we have on some ms to store the data until the cap runs out of energy. Every ms counts and so we just are optimizing in the way we always have a freshly erased sector ready to be written, squezing out as much as possible.

Well, we find a working solution (we have one), for sure, but I consider using a flash area that is not meant to be used for that somehow a little bit of a dirty hack.. I would have prefered an "official" solution. But I can live with that.. Especially cause we have plenty of flash unused anyway.

earlephilhower commented 1 year ago

Ah, got it. Erase is the really slow operation so pre-erasing on startup should give you a fighting chance.

The option I suggested from the Bluetooth code is not too ugly a hack, IMHO, and will let you erase on startup and write on power fail pretty simply. You also get to define exactly how much space you need up front and the link will fail if there's not enough space for your flash data and code. You can also read data out just as if it were a global const variable (because, well, it is...)