8000 stm32/main: Allow freezing boot.py and main.py into firmware image by andrewleech · Pull Request #4348 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

stm32/main: Allow freezing boot.py and main.py into firmware image #4348

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

Closed
wants to merge 2 commits into from

Conversation

andrewleech
Copy link
Contributor

If boot.py and/or main.py are in frozen scripts, use them rather than the static copy in code for creating initial files on filesystem.

This was originally inspired by #4248, however taking a different direction.

Currently, the template for main.py and boot.py is just contained in char string in code. When a new filesystem is being created the initial files are created from these templates.

The PR allows a firmware board developer to use their own copies of boot.py or main.py instead of the code templates by putting those files into a separate folder for frozen scripts, eg:

make FROZEN_DIR=src/boot_scripts all

Doing it this way allows the end user to still make modifications to those files during development, etc and the modified copies will be used. However if something goes wrong they can erase the filesystem and go back to the frozen templates.

This PR combined with the existing FROZEN_DIR / FROZEN_MPY_DIR system allows us to have our entire micropython application frozen into the rom dfu image for easy deployment without needing to manually copy any files onto the filesystem afterwards.

Copy link
Contributor
@pfalcon pfalcon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How this can be "stm32/main"? This either works consistently for all ports (including unix), or ... it again works consistently for all ports, like it does now.

@andrewleech
Copy link
Contributor Author

As it stands, all the ports implement boot files (templated or otherwise) separately in their respective main.c files. unix doesn't even have boot files as far as I'm aware.

At this stage I've only updated the stm32 main.c file to look for and handle the frozen template files, if it's an accepted change then the mechanism for handling boot files can (and should) be consolidated into a separate module that can then be shared between most/all of the ports. That's a very different and much larger changeset however.

I'll deal with the build failure shortly.

@pfalcon
Copy link
Contributor
pfalcon commented Dec 13, 2018

Yeah, like that, except the order should be the opposite - first consolidation, then adding new features. And you're pretty right that it's a boring work which falls on the responsibility of maintainers. There're a lot of such things in MicroPython (well, definitely less than in many other projects), which block further progress. But regressing the consolidation work already done (a lot!) by adding port-specific features at the expense of all other ports (which also need the same feature) should not be a way to go.

@dpgeorge
Copy link
Member

I think it would be a lot simple to just allow a given board to specify a custom factory filesystem. In the simplest case main.c could just #include a board-specific file for the content of fresh_boot_py[] and fresh_main_py[]. In a more complicated case a board would specify a manifest with filename and data to populate in a fresh filesystem.

But I agree that something needs to be done about this, there needs to be an efficient way to build and deploy custom applications. (Eg one approach is to build a FAT filesystem image on the PC and copy it to the board, which can be done over DFU. And to protect against corruption the filesystem would need to be mounted read-only.)

@andrewleech
Copy link
Contributor Author

You're right, I did over-complicate this.

@pfalcon I do agree with your sentiments. My back story is I needed this functionality to ship a release of our firmware at work a couple of weeks ago and this is what I came up with quickly, so no it was not thought out as a platform wide improvement. Seeing as it was already done however, I pushed it here for this discussion.

@dpgeorge Yeah a simple #include based scheme would have been much easier, wish I'd thought of that. It doesn't look like it's possible to directly #include a python file into a string literal, but just having a define to point towards a boot.h / main.h or similar for each port would the straightforward.

I do prefer the idea of providing a complete initial filesystem would be much more flexible. I do have a small set of other files I'd like to have included in the image myself, so I think this angle is definitely worth pursuing.
Rather than creating a manifest file I feel it would be far simpler to just have a folder for fs, the contents of which are all included as is. Each port can have a default fs folder that suits its needs and a common library written to include that folders contents in the firmware image.

A boardconfig or make define could point this to a new board or user specific fs folder.

I can think of a couple of options for inclusion methods that would suit different targets better.

For read only filesystems (teensy is always hardcoded / RO isn't is? and could be an option on other platforms/boards for deployment) the approach of pre-generating the fat fs is pretty clean, then it can be just linked into the appropriate location. That way there's no duplication of template/filesystem using extra flash.
If this was made RW though then you lose the ability to reset the filesystem back to original format.

Actually for RO use it would probably make more sense to use the memzip (#147) or finish the ZipFile (#1797) support and use that, though I guess that's a cpu+ram vs flash tradeoff, probably best to support both zip and fat as the image format.

In the case of RW filesystems, either a prebuilt FAT image or a zip image could still be included in the image and used as the template to install onto the formatted fs on initial install / erase. Using zip probably makes a lot more sense as it'll reduce flash usage, at the expense of a one-off cpu+ram when extracting it into a new fs.

@dpgeorge
Copy link
Member

Rather than creating a manifest file I feel it would be far simpler to just have a folder for fs, the contents of which are all included as is.

Yes that would be much simpler (but I'd want to keep away from symlinks in the repo).

For read only filesystems ... the approach of pre-generating the fat fs is pretty clean, then it can be just linked into the appropriate location. That way there's no duplication of template/filesystem using extra flash.

FAT FS has a lot of overhead, its minimum size is about 20k (see eg #4305), excluding actual file data. So implementing a very simple linear RO filesystem structure, and using that instead of FAT for RO filesystems, would more than pay for that 20k.

There are a few different classes of filesystems which would be good to support:

  • RO linear filesystem, with possibility to memory map the data (eg for execution)
  • RO zipped FS (no possibility to memory map the data inplace since it must be uncompressed first)
  • initial data to populate a "factory fresh" RW filesystem (data could be compressed, could be a list of files and their data, or could be a compressed binary image of the full filesystem) (this could actually be the same as / be sourced by the above 2 items, or it could be different)
  • general RW filesystem

@dhylands
Copy link
Contributor

You can also use zip files which contain uncompressed files (which is what memzip did)

@dhylands
Copy link
Contributor

Allowing non- .py/.mpy files to be frozen would be pretty close to using memzip with uncompressed files.

pi-anl added 2 commits April 29, 2019 11:59
…O_FS_TEMPLATE is defined and set.

These files are often undesirable in a production setting and take up code space.
@pi-anl pi-anl force-pushed the frozen_boot_main branch from 6700ccc to 94acf41 Compare April 29, 2019 02:06
@andrewleech
Copy link
Contributor Author

FWIW I've just pushed the much simpler version of this I've been running for some time now (still stm32 only), albeit just updated to suit latest master.

Two commits; the first gives a define option MICROPY_HW_NO_FS_TEMPLATE which if set, removes all the initial/template file blocks from main.c for projects where you don't want the generic files written to flash.

The second updates utils/pyexec: pyexec_file_if_exists() to look for and run frozen modules in preference to vfs ones.

This means you can put your main.py and boot.py in a folder boot then compile mpy with

make -C micropython/ports/stm32 FROZEN_DIR=boot

and it'll always use your frozen boot/main files.

As an interim solution for production use I'm finding it quite stable and effective, secure against users being able to inject their own boot/main files, and consistent in behavior even when the fat filesystem gets corrupted and you lose your runtime files.

@dpgeorge
Copy link
Member

Thanks @andrewleech for the update. I like the pyexec_file_if_exists() update and think it's a good solution to execute frozen boot.py and/or main.py, because:

  • it's a small change that works for all baremetal ports in the same way
  • fills out the current behaviour of boot.py/main.py so that they can be optionally frozen, and frozen exactly the same way that other scripts are frozen
  • works for scripts frozen as mpy, frozen as strings, and even frozen native code

So I'd be happy to merge that commit. The other (disable initial files) would need separate consideration.


This means you can put your main.py and boot.py in a folder boot then compile mpy with

make -C micropython/ports/stm32 FROZEN_DIR=boot

It also works with make FROZEN_MPY_DIR=frozendir and boot.py in frozendir/, ie with precompiled .mpy files (which are more efficient than scripts frozen with FROZEN_DIR).

@rolandvs
Copy link
Contributor

👍 +

@dpgeorge
Copy link
Member
dpgeorge commented May 1, 2019

I merged support for frozen boot/main scripts in 859596c

There's still the remaining commit here regarding not including the default files for stm32.

@dpgeorge
Copy link
Member
dpgeorge commented May 6, 2019

See #4752 for an alternative proposal to make default files configurable.

@dpgeorge
Copy link
Member
dpgeorge commented Jul 9, 2019

Default files were made configurable in 97753a1

@dpgeorge dpgeorge closed this Jul 9, 2019
kamtom480 pushed a commit to kamtom480/micropython that referenced this pull request Mar 11, 2021
…I_wrover

Franzininho wifi ESP32-S2 Wrover
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants
0