-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
ports/rp2: Per-board linker scripts to avoid producing self-corrupting builds. #8761
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Note; I have created custom linker scripts for PICO and our boards which I know the flash sizes of. If this stands a chance of being merged before the next release I could try and find the time to update the other boards. Right now this is a very us-packing-everything-and-the-kitchen-sink-into-MicroPython problem, but I think having linker scripts that correctly reflect the actual FLASH available (and not allocated to the user filesystem) makes sense generally. |
It's definitely not ideal. Would be best to try and eliminate duplication. Linker scripts can include other linker script files, see eg You can also inject variables into linker scripts, see eg |
Aha, thank you for the examples, I shall look into those when I have time and see if I can make this workable. |
3e8580a
to
c564fe5
Compare
Updated to a much cleaner solution. The In lieu of this I have detected It feels a bit icky that we're defining both TODO
|
In stm32 the flash layout (what's for the bootloader, the app firmware, the filesystem etc) is done in the linker script. And then those values are passed up to C. I think it makes good sense to do a similar thing for the rp2 port, define everything at the linker level. In stm32 an example is:
Sometimes I think we should use similar names for rp2, eg
I agree. So we would remove |
@@ -0,0 +1,4 @@ | |||
_user_fs_size = 1408 * 1024; | |||
_flash_size = (2 * 1024 * 1024) - _user_fs_size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to define _flash_size
as the total size of the flash, and then _flash_fs_size
as the filesystem size. Also _flash_app_size
as the difference. Only two of those need to be specified by the board.
Your suggested approach has the consequence of making it easier to locate objects in the filesystem - ie an initialized filesystem image - at compile time. That could prove a handy jumping off point for some other ideas floating around. I like it! |
c564fe5
to
dbaee83
Compare
I'm not totally sure Similarly The latter might be fixable with some not-insignificant refactoring, but the former is likely to be tricky. I ended up with a per-board configuration in set(MICROPY_HW_FLASH_SIZE_BYTES "2 * 1024 * 1024")
set(MICROPY_HW_APP_SIZE_BYTES "640 * 1024") Which is a hack around the fact that But with no way to pass these values into the Linker script, it's all academic. The linker script now looks something like this: _flash_start = 0x10000000;
_flash_size = DEFINED(MICROPY_HW_FLASH_SIZE_BYTES) ? MICROPY_HW_FLASH_SIZE_BYTES : 2 * 1024 * 1024;
_flash_app_size = DEFINED(MICROPY_HW_APP_SIZE_BYTES) ? MICROPY_HW_APP_SIZE_BYTES : 640 * 1024;
_flash_fs_size = _flash_size - _flash_app_size;
_flash_fs_start = _flash_start + _flash_app_size;
MEMORY
{
FLASH(rx) : ORIGIN = _flash_start, LENGTH = _flash_size
APP(rx) : ORIGIN = _flash_start, LENGTH = _flash_app_size
FILESYSTEM(r) : ORIGIN = _flash_fs_start, LENGTH = _flash_fs_size
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
} And in CMakeLists.txt I am attempting to do something like this: # supply user-configurable app size and Pico board size to the linker script
target_link_options(pico_standard_link INTERFACE "-Wl,--defsym,MICROPY_HW_FLASH_SIZE_BYTES=${MICROPY_HW_FLASH_SIZE_BYTES}")
target_link_options(pico_standard_link INTERFACE "-Wl,--defsym,MICROPY_HW_APP_SIZE_BYTES=${MICROPY_HW_APP_SIZE_BYTES}") But symbols passed in this way neither qualify as in static_assert(PICO_FLASH_SIZE_BYTES == MICROPY_HW_FLASH_SIZE_BYTES, "MICROPY_HW_FLASH_SIZE_BYTES does not match PICO_FLASH_SIZE_BYTES"); I feel like I've painted myself into a corner here, but there may be light at the end of the tunnel, It seems that the mimxrt port actually runs the C preprocessor over its $(Q)$(CC) -E -x c $(LDDEFINES) $(LD_FILES) | grep -v '^#' > $(BUILD)/link.ld I have...borrowed.. this and hung a custom command off the Issues:
|
dbaee83
to
412d7cd
Compare
Okay I have replaced the ugly preprocessor hack with CMake's I still don't like the duplication of On the upside, having both these vars configured by MicroPython's board config means they're right there under your nose if you ever want to tweak the app sizes for existing boards. |
Would it help to adjust the code in |
The main issue with adjusting rp2_flash is the inability to use the “dynamic” linker symbols in the “bi_decl” macro. I don’t see an obvious way around this, though that may be a lack of knowledge or imagination on my part. |
412d7cd
to
c7b8241
Compare
Apart from this not being marked "Ready for review" is there anything that needs to be addressed? Getting input is tricky here because I'm probably the only person screaming out for this 😆 |
It looks like this commit c80e7c1 takes another step toward relying on As I mentioned in the comment there, this causes some difficulty with modules that - up until now - have been able to safely assume that some C++ heap is available for general use. This is no longer generally the case. Of course I'm always going to err on the side of not wanting to update our few dozen modules and expect push-back, but I think th is is another potential argument for this per-board It's going to take some amount of effort to rebase this PR, so before I go launching into it-
|
It isn't init yet. Fixes micropython#8761
It should be noted that I've switched away from trying to wrangle linker scripts and have instead written a pure Python tool to analyze the .uf2 output files and check the binary metadata doesn't describe a filesystem that overlaps the flash binary. That tool lives here: https://github.com/gadgetoid/py_decl Is invoked in our CI like so:
And will produce an error like:
|
c7b8241
to
8f8ac1c
Compare
Add per-board flash config to avoid silently overwriting user code on vfs init. Make linker FLASH section reflect board size. Add linker APP section for user code. Add linker FILESYSTEM section for vfs. Add per-board config for FLASH + APP sizes: * MICROPY_HW_FLASH_SIZE_BYTES * MICROPY_HW_APP_SIZE_BYTES CMake "configure_file" memmap_mp.ld.in. Signed-off-by: Phil Howard <github@gadgetoid.com>
Add --print-memory-usage to print memory usage at the end of a build. Shows used/remaining app storage. Signed-off-by: Phil Howard <github@gadgetoid.com>
bd57969
to
780ac22
Compare
It's still not ideal and I'm not dealing with romfs well, but I've rebased this PR so we can better see how feasible this is and what the challenges might be. The issues with Note: should probably have a TODOAssuming we move forward with this, we need to:
|
Code size report:
|
Add per-board linker scripts to avoid silently overflowing flash.
Excludes region allocated to user filesystem from FLASH section.
Rationale explained in #8680
TLDR: Prevents the accidental generation of MicroPython builds which self-destruct on first run by overwriting themselves with the configured LittleFS filesystem.
I'm not super happy about copying memmap_mp.ld for every board, but I don't really see a better way to do this and preprocessing is non-trivial CMake spaghetti.