-
Notifications
You must be signed in to change notification settings - Fork 8.2k
linker: generate memory regions from devicetree partitions #31077
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
linker: generate memory regions from devicetree partitions #31077
Conversation
Adds a macro that operates on the results of previous evaluations. This is mostly useful for calculating the maximum or minimum of an arbitrary list of integers at compile time. An implementation in a similar style to `Z_FOR_EACH_IDX` was attempted, however macros such as `COND_CODE_1` were not properly being expanded inside nested usage of `UTIL_OBSTRUCT`. Signed-off-by: Jordan Yates <[email protected]>
Add test cases for the `FOR_EACH_NESTED` function. Signed-off-by: Jordan Yates <[email protected]>
Add a new property to the child binding of `fixed-partition` to signify that a memory region in the linker should be generated for this partition. Signed-off-by: Jordan Yates <[email protected]>
Adds two public macros for creating memory regions from devicetree partitions. The `linker-region` property is only considered on partitions under `chosen/zephyr,flash` as this is assumed to be the only flash driver for which memory regions make sense. `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. `DT_PARTITION_REGIONS_START` gets the memory address of the region with the lowest origin address. The FLASH region will be constrained to this address. Signed-off-by: Jordan Yates <[email protected]>
Insert macros for generating memory regions from flash partitions that have set the `linker-region` property. Signed-off-by: Jordan Yates <[email protected]>
Demonstrate how to place variables at constants memory addresses defined by devicetree partitions. Signed-off-by: Jordan Yates <[email protected]>
Enable the `linker-region` property on the NVS partition for a subset of nordic boards to validate CI behaviour. Signed-off-by: Jordan Yates <[email protected]>
|
Added |
Yeap, sorry, I meant the PR, #29794 (not necessarily the exact solution presented there, but rather its generic idea, i.e. using the existing DT/Kconfig infrastructure to limit the code partition to a certain area) |
Sure, this PR makes no statements about the code partition beyond shrinking the default ROM_SIZE so that it doesn't overlay defined |
|
@JordanYates what's the implication if you assumed all partitions had |
|
A limitation that I spot in the current implementation is that all the flash area beyond the storage_partition (or, rather, the first partition with the linker-region property) cannot be used by the Zephyr for the application image. This is problematic for all the boards that define the storage partition right after the boot partition. There has to be found a way to by pass this limitation (alternatively all the boards that not define storage_partition at the end will need to re-adjust their existing flash layout) |
If by all partitions you mean the entire flash space is covered by |
Without changes to this PR, the resolution is simply to not put The special cases/behavior are starting to pile up however, and the solution no longer seems as clean as it did originally. Your |
I believe, this is not ideal, it breaks uniformity across storage partition definitions in the various boards. I would not recommend this way forward; we should be trying to introduce common rules and conventions across definitions.
Unfortunately, this does not always hold - I am sure many they are not (so we're just lucky the samples and tests they run fit in the area preceding the storage partition, or the storage partition is not used in in-tree samples).
Agreed. And that's why I said initially that #31077 is rather a complement for #29794, not an alternative. We need to make it explicit which area can be used by the image code in all cases - not only when we build with boot loader.
The implementation #29794, although it does do the job, as you point out, it is not accepted by @galak @mbolivar-nordic, so we have to look for an alternative.
So you suggest to "do some math" at Kconfig and/or linker stage :) It could theoretically be an alternative. I don't get why this would be a better solution, though. To clarify, my "problem" here is that the logic to decide where to place and how to size the code partition (and other partitions) is split in 3 Zephyr main "components":
IMHO this is far from ideal. The solution is hard to follow and developers have a hard time to learn what is going on. My attempt in #29794 was to move as much as we can at the DeviceTree stage, basically, "doing all the math we need" at DeviceTree partition layout descriptions, and then let Kconfig select the right layouts/partitions and initialize the proper symbols, so the Linker would not have to do anything (just accept the incoming configuration without further "internal" logic to derive region boundaries) If we keep doing "partitioning" calculations at Kconfig/Linker stage, I would argue: why do we, then, need to define partitions in DeviceTree, at all? At Kconfig stage we already know the flash size and start address, so we could even do all the partition layout calculationss there, and remove all stuff from DeviceTree. |
It's not a better long term solution, but I think it would be a less invasive short term one. It doesn't change the current split of information across across devicetree/kconfig/linker, so it doesn't solve your problem, but it does make the error condition in #27471 impossible. Potentially that makes it a more acceptable solution given the The behavior change would be:
The main advantage is that user
I think the primary motivating reason is the |
|
@ioannisg, @JordanYates, let us set the goal of removing everything from Kconfig, and just set everything in the dts: |
I meant if you generated for every partition regardless of |
So this works, even with overlapping memory regions, as long as you don't have multiple variables attempting to be placed at the same address. For example: Trying to place a variable in BOOTLOADER results in an error (overlaps with the application in FLASH) This would not be a solution to the problem without further changes however. The storage partition for example never has any variables in it, so there would still be no errors as FLASH encroaches into it. The linker output is also rather misleading as it implies that there is more flash available than there actually is. The region that the application is put into needs to accurately reflect the space available to it. |
|
If we are willing to live with the misleading linker output, we could:
This approach has much to recommend it IMO. Flash sizes for standalone applications become explicit. A significant chunk of the devicetree Kconfig interaction is reduced to a single symbol with minimal meaning (what partition does the application go into). |
|
@JordanYates, and what if we would generate linker sections only for partitions under the selected code-partition. Flash sizes would become explicit for standalone and bootloader applications, For standalone applications this would fallback to the partitions defined under flash0 (although IMO it would be better to redefine the flash layout in this case). |
I'm not sure what you mean here, it is memory regions we need to generate, not sections.
This would break the ability for the same application to compile as standalone or chain-loaded. The purpose of the Kconfig symbol is to allow |
If the partition it points to has subpartitions it can also point to a collection of partitions.
The proposal would not break this ability. When there are no subpartitions everything would remain as is and A fit for all applications could be defined in one dts-file: compiling for The partitioning could probably be simplified if the is some rule like: "if there is no subpartition labeled "image" then map the flash to the complete partition". |
|
From what I can tell, you are advocating for the solution where the decision to use a bootloader or not happens before either devicetree or Kconfig have run, either in CMake or from the command line (There is no other way to swap around which partition has the "image" label AFAICT). That approach allows Kconfig symbols to be dropped at the cost of adding another configuration layer to the build system. |
No, no, I am not advocating for another solution. The only selection would happen by the setting of OK, it will not be so straightforward because you cannot have multiple partitions with the same label. But by turning the idea around a bit it might even be better: by selecting |
I guess that was what was presented in #29794 (if i understood the comment correctly) |
|
@JordanYates, for some reason your name does not easily pop-up on github. I created a new issue #31487 for image generation. This could be extended with linker memory regions. |
Not quite, your proposal adds one symbol, I am proposing deleting all current symbols except for one. I think I will mock up this solution on a few boards just to see if there are unforeseen problems. |
|
Superseded by #33656 |
Implements a relatively simple mechanism for automatically generating memory regions based devicetree partitions.
For a partition to result in a memory region, it must add the
linker-regionproperty to the appropriate partition.Only partitions under the
chosen/zephyr,flashnode result in memory regions, under the assumption that this points at the onboard ROM, and that memory regions for external flash do not make sense.Regions are named based on the label of the partition.
The primary purpose of this PR is to enable placing constants at absolute addresses in a portable manner.
Naming for
FOR_EACH_NESTEDandlinker-regionis provisional pending feedback.Currently this has only been integrated into the Cortex linker script and enabled on a small subset of nRF hardware.
Implements #31073