-
Notifications
You must be signed in to change notification settings - Fork 6.9k
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
RFC: memory regions from devicetree & explicit code locations #33656
RFC: memory regions from devicetree & explicit code locations #33656
Conversation
Add a second modifier to the board string that allows for specifying a code layout. Both board revision and board layout can be specified independently, or together. If specified together, the layout must follow the revision. A board indicates that it supports multiple code layouts by the presence of the `layouts` folder in the board folder. If this folder exists and no layout is specified, the `default` layout is selected. The selected layout must exactly match an overlay file in that folder. An optional Kconfig configuration file may also exist. For example, for a layout of `mcuboot` on board `test`: ``` test - layouts - default.overlay - mcuboot.overlay - mcuboot.conf -test.dts -... ``` The valid board specifiers are now: `board` `board@revision` `board%layout` `board@revision%layout` Signed-off-by: Jordan Yates <[email protected]>
Apply board dts overlays and kconfig configurations when `BOARD_LAYOUT` is specified. Fixes #31487. Signed-off-by: Jordan Yates <[email protected]>
Convert the nrf52840dk_nrf52840 board to use the new board layouts as a demonstration of the changes required. Signed-off-by: Jordan Yates <[email protected]>
Adds a public macro for creating memory regions from devicetree partitions. All partitions under `chosen/zephyr,flash` result in an output region. `DT_PARTITION_REGIONS` declares the memory regions for consumption by ld. While macro limitations mean that region names are quoted and there are no seperators between regions, ld appears to handle this fine. Signed-off-by: Jordan Yates <[email protected]>
Generate linker memory regions from flash partitions that exist under the chosen node `zephyr,flash`. This makes the linker aware of the various flash memory regions. If code overflows from one region to another, the linker will complain. This additionally enables variables to be placed at absolute memory addresses by placing sections inside the generated memory regions. Fixes #31073, #27471. Signed-off-by: Jordan Yates <[email protected]>
Simplify bespoke memory region definitions by declaring the regions directly from devicetree nodes. Signed-off-by: Jordan Yates <[email protected]>
A highly level comment is I think it would be good to split this PR in two. One is the linker.ld changes and use of devicetree and the other PR the introduction of the layout concept. |
@JordanYates The zephyrproject-rtos/example-application repository scope includes demonstrating how to configure application repositories so the build system sees DTS overlays from the application repository tree. Can these be used to solve your problem? If not, what is lacking? |
This is not sufficient as the core functionality that this PR enables is dynamically generating the "correct" flash partitions depending on what type of application is being built. These flash partitions are then used to generate the memory regions supplied to the linker. |
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.
The first step is to extend the board revision syntax board@revision to support different code layouts board%layout/board@revision%layout.
This really don't belong with the BOARD
argument.
Flash layout is a (user) configuration that is depending directly on the sample you are building and for which we have DTC_OVERLAY_FILE
and CONFIG_FILE
/ OVERLAY_CONFIG
.
Note, if we have a <board>_mcuboot.overlay
, users can easily copy that file to their sample, for example:
cp nrf52840dk_nrf52840.overlay <sample>/boards/nrf52840dk_nrf52840.overlay
This extension is proposed as manually specifying devicetree overlays on the command line is verbose and error prone (-- -DDTC_OVERLAY_FILE=zephyr/boards/arm/board/board_mcuboot.overlay).
If this is not sufficient and Zephyr would benefit from an enhanced way of looking up files, I think a dedicated issue should be raised for further discussions.
https://docs.zephyrproject.org/latest/guides/dts/howtos.html#set-devicetree-overlays
@@ -162,7 +147,7 @@ SECTIONS | |||
|
|||
GROUP_START(ROMABLE_REGION) | |||
|
|||
_image_rom_start = ROM_ADDR; | |||
_image_rom_start = .; |
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.
This is changing the value of _image_rom_start
from a calculated address to 0x0
.
This means that code that refers to _image_rom_start
might get a wrong value.
This also results in:
_flash_used = LOADADDR(.last_section) - _image_rom_start; |
being calculated wrongly.
As example, building hello world for cc3235sf_launchxl
with CONFIG_XIP=n
on master gives me:
$ objdump -x zephyr/zephyr.elf |grep _image_rom_start
20000000 g *ABS* 00000000 _image_rom_start
$ objdump -x build_xip_ref/zephyr/zephyr.elf |grep _flash_used
00004158 g *ABS* 00000000 _flash_used
but with this PR:
$ objdump -x build_xip/zephyr/zephyr.elf |grep _image_rom_start
00000000 g rom_start 00000000 _image_rom_start
$ objdump -x build_xip/zephyr/zephyr.elf |grep _flash_used
20004158 g *ABS* 00000000 _flash_used
so any code relying on those two symbols will fail.
#define CCFG_SIZE 88 | ||
#define ROM_SIZE (CONFIG_FLASH_SIZE*1K - CONFIG_FLASH_LOAD_OFFSET - \ | ||
CCFG_SIZE) | ||
#define CCFG_ADDR (ROM_ADDR + ROM_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.
CCFG_ADDR
is still being used in the code below:
#ifdef CONFIG_HAS_TI_CCFG
FLASH_CCFG (rwx): ORIGIN = CCFG_ADDR, LENGTH = CCFG_SIZE
#endif
causing:
invalid origin for memory region FLASH_CCFG
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
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.
Removing dev-review as this was already discussed there; please add the label again if there's more to discuss at the meeting. |
I am not in favor of adding the % thing,, so I let myself drop some thoughts on alternative I have been considering. I think the Instead we should introduce compatible that will be set to entire partitioning schema, for example Having the But getting back to the partitioning: we can attach any number of
withing single DTS configuration. This means that at compilation time Several partitioning schema should be able to co-exist (@galak ?) We could probably provide more independent configurations for other bootloaders without no need for overlays or switching layouts. After DTS processing phase all listed schema are available, if provided, for board, at the same time and we can decide which will be picked basing on Kconfig options, for example: now we can even decide, basing on existence of Having spaces for Zephyr app images with compatible set should also allow to, while processing DTS file, warn user that for example images have different sizes or warn that the smallest size defined by User does not have to overlay both schema, for example if only single is used then user removes the single one and provides own configuration, same with mcuboot schema. What do you think about such approach @JordanYates , @mrrosen ? |
This has been soundly rejected at this point, but it was never the important part of the proposal, simply a shorthand to specify a devicetree overlay.
This is only problematic if we have no simple way of applying common devicetree overlays from the command line.
You therefore setup
This is possible, but I don't believe this is the correct path forward. IMO I am not convinced by the proposed compatibles and keeping the existing devicetree/Kconfig dance to configure the linker. Under my preferred scenario (where |
I agree with @JordanYates that limiting the devicetree to only include the set of partitions actually used by the application is the right approach and that by using overlays, a user can select the desired set of partitions from a few commons ones provided by the board or provide their own in their application. But @de-nordic does raise a good issue that I also ran into in my own project: once you have a nice way of creating the desired partitions in devicetree and provide this information to the linker in the form of memory regions (addressed in this MR and discussed more generally in #34167), how do you instruct Zephyr on how to link all the unspecified code/data and what artifacts do you want out of the build. The current solution for the first part is to use chosen DT nodes ( Another somewhat related issue is that for certain partitions/memory regions, it would be good to generate separate binaries for them instead of a single monolithic hex/binary at the end (for example, you have a separate flash in your system that needs separate binaries to program but needs to be linked with the application); this is a problem I ran into recently and had to somewhat hack a solution using a second configuration file parsed by CMake. In both cases, while devicetree is providing the build system and code with what memories are available in the hardware and how they are partitioned (ie, spelling out all the linkable memory in the system), Im not sure its the right place to actually instruct the build system where the link the code and data and what artifacts to generate during the build (I dont think Kconfig is the right place either as it runs into the same issues as devicetree in terms of rebuilding unnecessarily and isnt as flexible). Im sure this is a much larger discussion than just this MR but I did want to raise it in response to @de-nordic 's comments on Direct-XIP; while devicetree can solve that problem (somewhat), Im not sure its the right strategy moving forward. |
There is actually is good argument for having mcuboot layout as separate layout overlay, so that user could include it into own dts of own board to bootstrap work: we support mcuboot so having basic description of fixed partition layout that gives support to mcuboot is desired as a working base, cut for a specific chip (or a family); although the user may finally even override that when it would seem that the app would not required that much flash yet storage or other flash area would be desired. The dev-boards, that are "known" by the Zephyr code are different case, as they serve different purpose. Heaving all configurations in one file allows you to switch, with the same DTS, without re-parsing it, to build mcuboot and single app conf just by adding or removing CONFIG_MCUBOOT to config overlay. The existence of all layouts supported out-of-tree for a board in single DTS is just demonstratpion that these are alternatives you may choose from, user may remove or replace any of them with overlays. as it may do with any other dev board peripheral. We provide generic configurations for dev boards to make them work with samples and tests, although sometimes overlays are required, adding all partitions' layouts that are supported at once would be in line with that approach. The nrf52840dk_nrf52840, as an example, gives configuration arduino header and mx25 in board dts, even though neither of these may be in use by an application or a sample. The provided DTS may only support what we know is possible and that is limited to layout of dev board and samples that run on them.
I have used that approach, although I do not like it because it basically means that I had to change hardware description to move software to address, and restart built from the bottom (Direct-XIP scripts that builds "other-slot" application #29974). Shouldn't that be done by compiler and linker basing on decision by user where to put the application? I know that "fixed-partition" definitions can not be strictly affiliated with either software or hardware configuration: they usually describe constrains for the application (software) placement in regard of a given board (hardware), but also may gather different flash devices into single map of storage devices.
Yes, that would probably be desired, this is "move problem to linker" approach. When this would be supported you could pre-build app and then decide which image you want to link it to: that would be very nice because moving app from single/no-mcuboot to slot1 or slot2 (or other) would be just a matter of re-linking it.
I agree that both the |
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |
@JordanYates Why are you closing the issue? |
I've closed the PR because every aspect of the approach has changed in response to feedback. |
Thanks for explaining. I hope that the idea on switching layout via command line will come back at some time. |
** Update **
Please refer to #34167 for a walkthrough of the issue reasoning. This PR may reasonably be closed in favor of following the more independent steps outlined there.
** Original**
This patch series is prototyping a solution to several problems related to the linker and memory layout. A minimal solution is developed and applied to the
nrf52840dk_nrf52840
board to demonstrate its use.The primary problem can be stated as:
The biggest problem that appears as a result is that for standard applications, the linker makes the assumption that the entirety of flash is available for code (unless Kconfig options are set separately). This results in problems like #27471.
The assumption underlying this solution is that different code layouts of applications running on a board (standalone, chain-loadable, etc) is roughly analogous to minor hardware revisions (https://docs.zephyrproject.org/latest/guides/porting/board_porting.html#multiple-board-revisions).
The broad idea is to describe different code layouts in devicetree overlay files in the board directory. Partitions are then instantiated as linker memory regions, which lets the linker place code at defined locations, and detect when partitions have been overrun.
The first step is to extend the board revision syntax
board@revision
to support different code layoutsboard%layout
/board@revision%layout
. This extension is proposed as manually specifying devicetree overlays on the command line is verbose and error prone (-- -DDTC_OVERLAY_FILE=zephyr/boards/arm/board/board_mcuboot.overlay
). If a layout is not specified, thedefault
layout is selected.The second step automatically adds the layout overlay (and an optional Kconfig settings file). The Kconfig file is to allow for configurations such as
board%mcuboot
to automatically enable relevant symbols likeCONFIG_BOOTLOADER_MCUBOOT
.The final step automatically creates a linker memory region for all partitions under the devicetree chosen node
zephyr,flash
.The partition pointed to by the chosen node
zephyr,code-partition
is used as the output memory region for TEXT/DATA.Additional memory regions can be created by pointing the linker directly at a devicetree node, which can clean up the linker scripts considerably.
Example outputs