nRF5: add lightweight XIP demo [FIRM-198] #142
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
In FIRM-198, we planned to introduce a simple XIP "hello world" demo, with "concepts of a plan" for how to make the core of it mergeable, but in a form that is not necessarily mergeable in and of itself; this is that demo. This demo shows that XIP of C compiled code is possible at least once on Asterix hardware, using the
xip hello worldcommand that gets the in-flash address of a precompiled XIP stub, turns on the QSPI hardware, jumps to the stub, and then turns off the hardware after the stub is done. The expected output is approximately as follows:To enable this, we add support for the
MAPPABLE_FLASHcapability on nRF5 / Asterix. Unfortunately, nRF52840's QSPI controller is pretty broken -- it has a brutal erratum that means that it is not safe to actually use QSPI mapped memory when executing from microflash or SRAM. In fact, this happens to come up in our use: whenupngtries to decode memory-mapped PNGs, depending on the alignment of the upng code, it will either succeed or fail, claiming that the PNG in question is unsupported (!). In this PR, I show two ways to permute this outcome (whenMAPPABLE_FLASH_IS_FOR_CODE_ONLYis not enabled): if you remove theusleep(0)inflash_impl_use, then upng will fail to decode a system PNG and the system will assert on boot. But if you remove the+ 1incommand_xip_hello_worldafter that, then upng will happily decode the PNG again! (Of course, `command_xip_hello_world will not work anymore if you do that.)However, Nordic hints that it is legal to (or maybe, it happens to work to?) execute code from QSPI flash -- just as long as you don't hand any pointers in QSPI flash back to the system that runs in microflash. So we introduce CAPABILITY_MAPPABLE_FLASH_IS_FOR_CODE_ONLY, as a pinky-swear that you definitely are only going to execute that thing that you just mapped in, and you promise not to read from it without branching to it. (A dark irony is that this xip stub actually does hand a pointer back to the system illegally! But it doesn't seem to have any of the instruction sequence that causes this particular catastrophe.)
Although the final state of this particular thing works well -- well enough for me to consider FIRM-198 to be complete, anyway -- the bad news is that there are a bunch of extremely careful things done in this demo to make it work -- and solving each of these for something more "industrial-strength" might be nontrivial. Accordingly, I'll file Linear tickets for each of these.