cancel
Showing results for 
Search instead for 
Did you mean: 

Executing code in external OCTO SPI-flash for H7-device?

Southbranch
Senior II

 

Hi!

I have a TouchGFX project based on a H725-device with a large display 1024x600 having a fair amount of graphic components. It is a custom board but I am using STM32H735G-DK as a reference.

I have two related questions before moving onwards:

1. Application updates. From a customer’s perspective, is there a easy way to do updates via let say UART with just ONE application package (.BIN file) eventhough images are stored in the external flash?

2. Executing code in external flash.  Placing BOTH app code and images in the external flash could be an alternative, however, from documentation it is not entirely clear to me if the H7-series actually supports this for a OCTO SPI?

Many thanks in advance

1 ACCEPTED SOLUTION

Accepted Solutions

NOR Flash devices in general are not multi-mode, the erase/write are significantly asymmetrical in access size and speed. The reads are designed to be at MCU operational speeds, but the writes and erase can take thousands or millions of cycles, and thus best not to stall by stuffing wait-states at the bus.

The QUAD/OCTO SPI on the STM32 is further complicated by Command Mode and Memory Mapped can't operate concurrently.

You can store apps at different addresses, the vector tables however contain absolute addresses. There are techniques to make them relocatable by placing a fixed-up copy in RAM and pointing to that instead. With external memory there isn't the concept of bank-swapping (flipping) or any virtual memory type remapping.

App code can also be unpacked or copied to a fixed RAM address, and executed there.

Probably needs a boot loader to check and arbitrate which image gets run, and a way to determine which image is newer, say a date code or sequence number in some unused vector table position. Generally you want some integrity checking function so you can determine if an image is complete (end-to-end) and valid.

Your application could also check for other images and transfer control to them.

These could be a "loader" or simply a common piece of code in the front of each that basically fork()'s.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

9 REPLIES 9
Pavel A.
Evangelist III

This depends... is the code binary much smaller than the GUI resources? Do you want to update everything at once or selective?

We have a similar app but it is connected to cloud, so we use the same cloud to detect and install updates. User only has to set the time of day (or night) for updates. If you don't have network connectivity, update over UART is possible but you need to think of a good connector (robust, f00l-proof). Consider also SD card or USB. SD or USB drive with files allows your app to update only changed components, saving time. Packing everything into one .bin file is possible only if everything is in external flash. 

For more details on OSPI capabilities see https://www.st.com/resource/en/application_note/dm00407776-octospi-interface-on-stm32-microcontrollers-stmicroelectronics.pdf

 

 

Andreas Bolsch
Lead II

Re. 1: Yes, but you have to write your own bootloader located in internal flash only (protected!) which handles receiving the file and programming it into internal flash and external one based on target address. This means that it can't be a flat binary file, but it must contain some sort of address or partitioning information, so that the bootloader knows where the parts have to go (address space of internal and external flash are not contiguous). And, as Pavel already mentioned, it must be bullet-proof or you need some reliable recovery mechanism, i.e. in case of a failed update, the booloader must be able to detect this (e.g. by CRC check) and allow a second attempt.

Re. 2:  Regarding the bootloader mechanism, the application's memory layout (only resources in external flash or code, too) doesn't matter at all.  The bootloader must be contained entirely in internal flash, as external one is completely inaccessible during its erase/program cycles. Code for *application* may be placed in external flash (OCTOSPI supports memory mapped read), but this gives some (slight?!) performance penalty due to slower access. So time-critical routines, interrupt handlers etc. should reside in internal flash.

Yes, can XIP, should be examples in the trees. Problem is to doing that concurrently with erasing/writing to pull down the new code, and have rich user interface.

Per Pavel, ability to stage in another device preferable. Perhaps a simpler GUI you can boot into to do updates, either splash screen or some progress / wait dialog.

I would tend to package into a single 'binary' or object file, and unpack to memory. For standards look at .DFU format. Would tend to want to compress, crypt and sign in current environment. But start simple, get the mechanics down, and then pivot.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Pavel A.
Evangelist III

Configuration: Configure the boot settings of the H725 to recognize the external SPI flash as a bootable device.

*bleeping* Chatgpt, *bleep* go away! 

 

Southbranch
Senior II

 

Many thanks for all your comments, highly appreciated!

I believe pack into a single bin file is a must, so is having a “bullet proof” mechanism with a version-fallback. Forgive me, I said UART but my real vision is a full OTA-service like this:

  1. Keep current and previous app versions in two separate flash banks/blocks, one is executed obviously.
  2. The current app version checks for latest version in cloud and prompts user for downloading/flashing into SD or possible a third memory block (Tesla pointed out responsive GUI challenge, splash screen etc)
  3. Implement logic for flashing and revert-back-functionality
  4. If no connectivity is available use UART/SD-card

In 2), would it be possible by the App itself (after flashing) to change vector table and call JumpToApplication() to the newer version? I think in that case the separate bootloader would be used in 4) only.

Where the update image comes from is rather irrelevant, be it network, SD-card, UART, ...

But 1. with 3. is not possible as soon as parts of your application reside in the external flash. To emphasize it again: During *any* program or erase operation of an SPI flash, the *whole* SPI flash is inaccessible (except for reading status register). Your application could only operate in sort of "degraded" mode where it does not access the extenal flash, e.g. if only some bitmaps, images etc. are located there. But whether you call this "degraded" or "bootloader" mode is rather splitting hairs. There is nothing like "banks" in usual SPI flashes. The only option would be to attach two flashes in parallel (that's *NOT* dual mode of OCTOSPI) and use two different NCS pins, so that only one is selected at any time.

Ah.. of course, that makes sense about inaccessible SPIs.

So I guess the App then needs to somehow notify the Bootloader when a new version is available for download. Alternatively if the App itself first download the new version to e.g. a SD and therafter notify the bootloader so it can flash the new version.

But I still wonder if two App versions in flash can "jump-start" each other as a version rollback or does this also need to be handled by the Bootloader?

NOR Flash devices in general are not multi-mode, the erase/write are significantly asymmetrical in access size and speed. The reads are designed to be at MCU operational speeds, but the writes and erase can take thousands or millions of cycles, and thus best not to stall by stuffing wait-states at the bus.

The QUAD/OCTO SPI on the STM32 is further complicated by Command Mode and Memory Mapped can't operate concurrently.

You can store apps at different addresses, the vector tables however contain absolute addresses. There are techniques to make them relocatable by placing a fixed-up copy in RAM and pointing to that instead. With external memory there isn't the concept of bank-swapping (flipping) or any virtual memory type remapping.

App code can also be unpacked or copied to a fixed RAM address, and executed there.

Probably needs a boot loader to check and arbitrate which image gets run, and a way to determine which image is newer, say a date code or sequence number in some unused vector table position. Generally you want some integrity checking function so you can determine if an image is complete (end-to-end) and valid.

Your application could also check for other images and transfer control to them.

These could be a "loader" or simply a common piece of code in the front of each that basically fork()'s.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Southbranch
Senior II

Thank you all for commenting on this thread!