This channel provides a framework for using Guix as a West replacement for managing ZephyrRTOS based projects.
Guix provides a complete model of the system and provides an alternative dependency model to the one used by West.
Guix also provides A fully (unprivileged) bootstrapped build environment, including python modules, which results in 100% reproducible builds. The Zephyr project itself takes a lot of care to ensure reproducibility but because they cannot control the universe there are limits to what they can guarantee. Guix can control the universe and so can guarentee reproducibility.
Add the following to your channels.scm
(cons*
(channel
(name 'guix-zephyr)
(url "https://github.com/paperclip4465/guix-zephyr")
;; Enable signature verification:
(introduction
(make-channel-introduction
"a0146bb3d13920074d40ed6d6d53321b17e267fb"
(openpgp-fingerprint
"089F 0E56 0087 9656 C463 691A 3811 C00D C428 5E27"))))
%default-channels)
This channel provides the zephyr-build-system
and zephyr-module-build-system
.
The zephyr-build-system
contains a bootstrapped version of the zephyr sdk.
Currently only arm-zephyr-eabi
sans libstdc++ is supported. (please help!)
Firmware represent the leaf nodes in our deployment graph.
These are the projects which actually provide main
.
Firmware can be defined like so.
(use-modules (guix gexp)
((guix licenses)
#:prefix license:)
(guix packages)
(zephyr build-system zephyr)
(zephyr packages zephyr)
(zephyr packages zephyr-xyz))
(define-public zephyr-hello-world-frdm-k64f
(package
(name "zephyr-hello-world-frdm-k64f")
(version (package-version zephyr-3.5))
(home-page "https://zephyrproject.org")
(source
(file-append (package-source zephyr-3.5) "/samples/hello_world"))
(build-system zephyr-build-system)
(arguments
`(#:configure-flags '("-DBOARD=frdm_k64f")
;; The zephyr-build-system accepts additional arguments
;; such as bin-name and zephyr
;; XXX: bin-name and zephyr should be optional but currently
;; bin-name is required
#:bin-name "hello-world"
#:zephyr ,zephyr-3.5))
(inputs (list zephyr-cmsis zephyr-hal-nxp))
(synopsis "Hello world example from Zephyr Project")
(description "Sample package for zephyr project")
(license license:apsl2)))
Third party modules provide code required to run the system such as
board definitions, drivers, misc libraries, you name it. Anything that
does not provide main
is likely a module.
(use-modules (guix gexp)
(guix git-download)
((guix licenses)
#:prefix license:)
(guix packages)
(zephyr build-system zephyr-module))
(define-public hal-nxp
(let ((module-path "/modules/hal/nxp"))
(package
(name "hal-nxp")
(version "3.5.0")
(home-page "https://nxp.com")
(source
(origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/zephyrproject-rtos/hal_nxp")
(commit "708c95825b0d5279620935a1356299fff5dfbc6e")))
(file-name (git-file-name name version))
(sha256
(base32 "1yb7apbg9hpqz0lvca0r8wzr4zg3fdnzzsahkkx69d64j0vkwkcz"))))
(build-system zephyr-module-build-system)
(arguments
`(#:workspace-path ,module-path))
(synopsis "Zephyr module for NXP Hardware Abstraction Layer")
(description "Provides sources for NXP HAL zephyr module")
(license license:bsd-3))))
The zephyr-module-build-system
is just a specialized
copy-build-system
.
It tries to mimic a West style workspace in the
installation profile and this path is a subdirectory in that
workspace. In this example the NXP HAL ends up in the same spot as is
described in $ZEPHYR_BASE/west.yml
.
Building MCUBoot can be tough. MCUBoot needs to know about the board so it can initialize the hardware and validate/swap images. The board definition provides the parition layout which both MCUBoot and the application must agree on.
MCUBoot also needs to be provided a key so it can validate new images. It also has some dependencies on Zephyr itself being both a module AND an application.
Why is MCUBoot a module? Because the application also needs to know about it so it can work with the images and mark them for upgrade in the first place.
Applications which rely on MCUBoot should include zephyr-mcuboot
in their input list.
MCUBoot is itself a zephyr application.
The procedure make-mcuboot
returns a package which has been
specialized for a given board.
Below is an example bootloader which targets the frdm_k64f
.
(make-mcuboot "frdm_k64f"
;; Use special dev key instead of production
(local-file "ecdsap256-dev.pem")
#:extra-zephyr-modules (list zephyr-cmsis zephyr-hal-nxp)
#:zephyr-base zephyr-3.1
#:extra-configure-flags
'(;; k64 doesn't have fancy crypto hardware
;; so we cannot use RSA keys.
"-DCONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y"
"-DCONFIG_BOOT_SIGNATURE_TYPE_RSA=n"
"-DCONFIG_BOOT_ECDSA_TINYCRYPT=y"))
Guest is a command line utility for working with Guix based Zephyr
projects. Using guix build
in the CI is all well in good but during
development spawning an isolated environment is a bit
cumbersome. Speaking of cumbersome…
Passing $ZEPHYR_MODULES
to CMake when said modules are located in
the store is almost impossible. Zephyr’s CMake scripts call out to
West, when available, to provide the list of locations to include and
that is all Guest does at the moment.
guest list $GUIX_ENVIRONMENT/zephyr-workspace/modules
Unfortunately `guest list` doesn’t mimic the behavior of `west list`. West returns tabular information about the packages described in the manifest including commits and the relative location it resides. CMake (or perhaps python) then crunches through this output to create the `ZEPHYR_MODULES` variable.
Guest just outputs this variable directly by discovering modules in a search path. Some information such as commits and module names are not discoverable by just looking at the store (We hope module names are the same as their directory name but things like HALs break this pattern).
If this information is required Guix can provide it.
Guest can be installed with guix install guest
.