;;; GNU Guix --- Functional package management for GNU ;;; ;;; Copyright © 2023 Stefan ;;; ;;; This file is not part of GNU Guix. ;;; ;;; GNU Guix is free software; you can redistribute it and/or modify it ;;; under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 3 of the License, or (at ;;; your option) any later version. ;;; ;;; GNU Guix is distributed in the hope that it will be useful, but ;;; WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with GNU Guix. If not, see . (define-module (zephyr apps) #:use-module (embedded) #:use-module (gnu packages) #:use-module (gnu packages python-crypto) #:use-module (gnu packages python-xyz) #:use-module (gnu packages python-web) #:use-module (gnu packages tls) #:use-module (guix build-system cmake) #:use-module (guix build-system python) #:use-module (guix build-system trivial) #:use-module (guix gexp) #:use-module (guix git-download) #:use-module ((guix licenses) #:prefix license:) #:use-module (guix packages) #:use-module (guix utils) #:use-module (ice-9 optargs) #:use-module ((srfi srfi-1) #:select (delete-duplicates second)) #:use-module (zephyr) #:use-module (zephyr modules)) (define-public (complete-zephyr-application zephyr-application zephyr zephyr-build-tools target toolchain c-toolchain directory-to-install-from source-prefix target-prefix) "Complete an incomplete ZEPHYR-APPLICATION package with target specific Zephyr boilerplate." (let ((extended-inputs (modify-inputs (package-inputs zephyr-application) (prepend zephyr zephyr-build-tools))) (cross-compile-prefix (file-append toolchain "/bin/" target "-"))) (package-with-c-toolchain (package (inherit zephyr-application) (build-system cmake-build-system) (arguments (append (substitute-keyword-arguments (package-arguments zephyr-application) ((#:configure-flags configure-flags #~(list)) #~(append #$configure-flags (list "-DZEPHYR_TOOLCHAIN_VARIANT=cross-compile" (string-append "-DCROSS_COMPILE=" #$cross-compile-prefix))))) (list #:tests? #f #:phases #~(modify-phases %standard-phases (add-after 'set-paths 'correct-ZEPHYR_MODULES ;; The search-path-specification is not powerful enough. Zephyr ;; modules contain a zephyr-module//zephyr directory ;; without a common pattern for and the ZEPHYR_MODULES ;; environment variable needs to list the zephyr-module/ ;; directories separated by semicolons. (lambda _ (use-modules (ice-9 regex)) (let ((zephyr-modules (getenv "ZEPHYR_MODULES"))) (when zephyr-modules (setenv "ZEPHYR_MODULES" (string-join (map (lambda (module) (dirname (car (let ((length (string-length module))) (find-files module (lambda (name stat) (string-match "^/[^/]+/zephyr$" (string-drop name length))) #:directories? #t))))) (string-split zephyr-modules #\:)) ";")) (format #t "environment variable `ZEPHYR_MODULES' set to `~a'~%" (getenv "ZEPHYR_MODULES")))))) (replace 'install (lambda _ (let* ((source-prefix #$(string-append directory-to-install-from "/" source-prefix)) (target-prefix #$(string-append directory-to-install-from "/" target-prefix)) (source-prefix-length (string-length source-prefix)) (primary-files-to-install (list (string-append source-prefix ".uf2"))) (files-to-install (map (lambda (suffix) (string-append source-prefix suffix)) '(".bin" ".dts" ".elf" ".hex" ".map" ".stat"))) (source-files (find-files #$directory-to-install-from (lambda (file stat) (member file primary-files-to-install)) #:directories? #f)) (source-files (if (null? source-files) (find-files #$directory-to-install-from (lambda (file stat) (member file files-to-install)) #:directories? #f) source-files)) (target-files (map (lambda (file) (string-replace file target-prefix 0 source-prefix-length)) source-files))) (for-each rename-file source-files target-files) (mkdir #$output) (for-each (lambda (file) (install-file file #$output)) target-files)))))))) (inputs extended-inputs) (license (delete-duplicates (cons (package-license zephyr-application) (map (compose package-license second) (filter package? extended-inputs)))))) c-toolchain))) (define*-public (make-zephyr-application-for-arm zephyr-application #:key (zephyr zephyr) files-to-install (directory-to-install-from "zephyr") (source-prefix "zephyr") target-prefix) "Make a Zephyr application for Arm microcontrollers by completing the incomplete ZEPHYR-APPLICATION package with Arm specific Zephyr boilerplate." (complete-zephyr-application zephyr-application zephyr zephyr-build-tools "arm-none-eabi" gcc12-cross-newlib-arm-none-eabi-toolchain gcc12-cross-newlib-arm-none-eabi-c-toolchain directory-to-install-from source-prefix (or target-prefix (package-name zephyr-application)))) (define-public zephyr-hello-world (make-zephyr-application-for-arm (package (name "zephyr-hello-world") (version (package-version zephyr)) (source (file-append zephyr "/zephyr-base/samples/hello_world")) (build-system #f) (arguments (list #:configure-flags #~(list "-DBOARD=nucleo_wb55rg" "-DCONFIG_BT=y" "-DCONFIG_BT_STM32_IPM=y" "-DCMAKE_C_FLAGS=-DCFG_BLE_LSE_SOURCE=1" "-DCMAKE_BUILD_TYPE=RelMinSize"))) (inputs (list zephyr-module-cmsis zephyr-module-hal-stm32 zephyr-module-tinycrypt)) (home-page (package-home-page zephyr)) (synopsis "Hello-world sample of the Zephyr Project") (description "A simple Zephyr Project sample that prints \"Hello World\" to the console.") (license (package-license zephyr))))) (define*-public (make-zephyr-mcuboot-for-arm board extra-inputs #:key (configure-flags #~(list)) (key (file-append zephyr-module-mcuboot (zephyr-module-installation-target zephyr-module-mcuboot) "/main/root-rsa-2048.pem"))) "Make an MCUboot bootloader package for Zephyr targeting the Arm microcontroller BOARD. Add EXTRA-INPUTS to the build and use the list of optional CONFIGURE-FLAGS. Use the public KEY file for firmware decryption." (make-zephyr-application-for-arm (package/inherit zephyr-module-mcuboot (name (string-append "zephyr-mcuboot-" board)) (source (file-append zephyr-module-mcuboot (zephyr-module-installation-target zephyr-module-mcuboot))) (arguments (list #:configure-flags #~(append #$configure-flags (list "-S../source/boot/zephyr" (string-append "-DBOARD=" #$board) (string-append "-DTINYCRYPT_DIR=PATH:" #$zephyr-module-tinycrypt "/zephyr-module/tinycrypt/lib"))))) (inputs (append extra-inputs (list python-cbor2 python-click python-cryptography python-intelhex zephyr-module-mcuboot zephyr-module-mbedtls zephyr-module-zcbor)))))) (define-public zephyr-mcuboot-nrf52840dongle_nrf52840 (make-zephyr-mcuboot-for-arm "nrf52840dongle_nrf52840" (list zephyr-module-hal-nordic zephyr-module-cmsis) #:configure-flags #~(list "-DMCUBOOT_USE_MBED_TLS=y" "-DCONFIG_LOG=y"))) (define-public imgtool (package (name "imgtool") (version (package-version zephyr-module-mcuboot)) (source (file-append zephyr-module-mcuboot (zephyr-module-installation-target zephyr-module-mcuboot) "mcuboot/scripts")) (build-system python-build-system) (arguments (list #:phases #~(modify-phases %standard-phases (add-after 'unpack 'disable-broken-tests (lambda _ (substitute* "imgtool/keys/ecdsa_test.py" ;; This one is calling _unsupported, which raises an ;; ECDSAUsageError. (("def test_keygen") "def broken_test_keygen") ;; This one is failing with an AttributeError. (("def test_emit_pub") "def broken_test_emit_pub"))))))) (propagated-inputs (list openssl-3.0 python-cbor2 python-click python-cryptography python-intelhex python-pyyaml)) (home-page (package-home-page zephyr-module-mcuboot)) (synopsis "MCUboot's image signing and key management") (description "A tool to securely sign firmware images for booting by MCUboot.") (license (package-license zephyr-module-mcuboot))))