Failure to run generate-lfs-image.py from certificate_provisioning example

Description

Hello,

I am trying to integrate certificate provisioning into the golioth reference template, such that it can use mcumgr to receive the certificate and key.

I can build and run my application just fine without the following in my CMakeLists.txt that creates a littlefs image to be flashed

add_custom_command(
    OUTPUT ${ZEPHYR_BINARY_DIR}/lfs.hex
    COMMAND ${PYTHON_EXECUTABLE}
      ${CMAKE_CURRENT_SOURCE_DIR}/generate-lfs-image.py
      --build-dir ${APPLICATION_BINARY_DIR}
)

add_custom_target(
    lfs ALL
    DEPENDS ${ZEPHYR_BINARY_DIR}/lfs.hex
)

As a result, i get this error message from my device (esp32c6 devkitm in my case):
<err> fs: mount point not found!!

Which makes sense I think, because I didn’t include those cmake instructions for building the initial littlefs image…

However, if I try to incorporate those commands above, I get the following build errors:

[1/548] Generating zephyr/lfs.hex
FAILED: [code=1] zephyr/lfs.hex C:/Users/nicol/radaon-fan-alarm-firmware/app/build/primary/zephyr/lfs.hex
C:\WINDOWS\system32\cmd.exe /C "cd /D C:\Users\nicol\radaon-fan-alarm-firmware\app\build\primary && C:\Users\nicol\.zinstaller\.venv\Scripts\python.exe C:/Users/nicol/radaon-fan-alarm-firmware/app/generate-lfs-image.py --build-dir C:/Users/nicol/radaon-fan-alarm-firmware/app/build/primary"
Traceback (most recent call last):
  File "C:\Users\nicol\radaon-fan-alarm-firmware\app\generate-lfs-image.py", line 18, in <module>
    from devicetree.edtlib import Node
ModuleNotFoundError: No module named 'devicetree'

I made sure I have all the python modules specified by Zephyr by doing the following as directed by Zephyr docs:

west zephyr-export
west packages pip --install

And I can confirm the results:

Requirement already satisfied: pyelftools>=0.29 in c:\users\nicol\.zinstaller\.venv\lib\site-packages (from -r c:\Users\nicol\radaon-fan-alarm-firmware\deps\zephyr\scripts\requirements-base.txt (line 7)) (0.32)
Requirement already satisfied: PyYAML>=6.0 in c:\users\nicol\.zinstaller\.venv\lib\site-packages (from -r c:\Users\nicol\radaon-fan-alarm-firmware\deps\zephyr\scripts\requirements-base.txt (line 11)) (6.0.3)
<REST OF PACKAGES>
Requirement already satisfied: pyparsing<4,>=2.1.0 in c:\users\nicol\.zinstaller\.venv\lib\site-packages (from rdflib->spdx-tools->-r c:\Users\nicol\radaon-fan-alarm-firmware\deps\zephyr\scripts\requirements-run-test.txt (line 22)) (3.2.5)

Can I can see that west is using the correct venv for Python3:

Environment variables and paths loaded from env.yml.
-- west build: making build dir C:\Users\nicol\radaon-fan-alarm-firmware\app\build\primary pristine
-- west build: generating a build system
Loading Zephyr default modules (Zephyr base).
-- Application: C:/Users/nicol/radaon-fan-alarm-firmware/app
-- CMake version: 4.1.2
-- Found Python3: C:/Users/nicol/.zinstaller/.venv/Scripts/python.exe (found suitable version "3.13.5", minimum required is "3.10") found components: Interpreter
-- Cache files will be written to: C:/Users/nicol/radaon-fan-alarm-firmware/deps/zephyr/.cache
-- Zephyr version: 4.2.1 (C:/Users/nicol/radaon-fan-alarm-firmware/deps/zephyr)
-- Found west (found suitable version "1.5.0", minimum required is "0.14.0")
-- Board: esp32c6_devkitc, qualifiers: esp32c6/hpcore
-- Found host-tools: zephyr 0.17.4 (C:/Users/nicol/zephyr-sdk-0.17.4)
-- Found toolchain: zephyr 0.17.4 (C:/Users/nicol/zephyr-sdk-0.17.4)
-- Found Dtc: C:/Users/nicol/.zinstaller/tools/dtc/usr/bin/dtc.exe (found suitable version "1.7.2", minimum required is "1.4.6")
-- Found BOARD.dts: C:/Users/nicol/radaon-fan-alarm-firmware/deps/zephyr/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_hpcore.dts
-- Found devicetree overlay: C:/Users/nicol/radaon-fan-alarm-firmware/app/boards/esp32c6_devkitc_esp32c6_hpcore.overlay
-- Generated zephyr.dts: C:/Users/nicol/radaon-fan-alarm-firmware/app/build/primary/zephyr/zephyr.dts
-- Generated pickled edt: C:/Users/nicol/radaon-fan-alarm-firmware/app/build/primary/zephyr/edt.pickle
-- Generated devicetree_generated.h: C:/Users/nicol/radaon-fan-alarm-firmware/app/build/primary/zephyr/include/generated/zephyr/devicetree_generated.h

Are the imports inside the generate-lfs-image.py potentially outdated for Zephyr 4.2.1?

It seems that last month west-zephyr.yml in the golioth-firmware-sdk was bumped to pull v4.2.1, but the examples/zephyr/certificate_provisioning/generate-lfs-image.py was last updated 6 months ago… so perhaps these modules have changed?

Expected Behavior

Successful compilation and image generation for lfs.hex

Actual Behavior

Python import errors
ModuleNotFoundError: No module named 'devicetree'

Impact

Cannot use lfs since it needs an initial image to be loaded before mounting

Environment

ESP32C6 DevkitM, Golioth Reference Design Template + certificate_provisioning example

Here is my west.yml

# Copyright (c) 2022-2023 Golioth, Inc.
# SPDX-License-Identifier: Apache-2.0

manifest:
  version: 1.0

  projects:
    - name: golioth
      path: modules/lib/golioth-firmware-sdk
      revision: v0.21.1
      url: https://github.com/golioth/golioth-firmware-sdk.git
      west-commands: scripts/west-commands.yml
      submodules: true
      import:
        file: west-zephyr.yml
        path-prefix: deps
        name-allowlist:
          - nrf
          - zephyr
          - cmsis_6
          - hal_nordic
          - hal_espressif
          - hal_st
          - mbedtls
          - mbedtls-nrf
          - mcuboot
          - net-tools
          - nrfxlib
          - oberon-psa-crypto
          - qcbor
          - segger
          - tfm-mcuboot
          - tinycrypt
          - trusted-firmware-m
          - zcbor
          - littlefs

    - name: zephyr-network-info
      path: deps/modules/lib/network-info
      revision: v1.2.1
      url: https://github.com/golioth/zephyr-network-info

  self:
    path: app

Here is my prj.conf:

# Copyright (c) 2022-2023 Golioth, Inc.
# SPDX-License-Identifier: Apache-2.0

# Enable Golioth Firmware SDK
CONFIG_GOLIOTH_FIRMWARE_SDK=y

# Golioth services used in this app
CONFIG_GOLIOTH_FW_UPDATE=y
CONFIG_GOLIOTH_LIGHTDB_STATE=y
CONFIG_LOG_BACKEND_GOLIOTH=y
CONFIG_GOLIOTH_RPC=y
CONFIG_GOLIOTH_SETTINGS=y
CONFIG_GOLIOTH_STREAM=y

# Enable common sample library
# CONFIG_GOLIOTH_SAMPLE_COMMON=y

# Enable the LittleFS file system
CONFIG_FILE_SYSTEM=y

# init before wifi credentials
CONFIG_FILE_SYSTEM_INIT_PRIORITY=89
CONFIG_FILE_SYSTEM_LITTLEFS=y
CONFIG_FILE_SYSTEM_SHELL=y
CONFIG_HEAP_MEM_POOL_SIZE=4096

# Add 256 bytes to accommodate upload command (lfs_stat overflows)
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2304

# Enable mcumgr
CONFIG_ZCBOR=y
CONFIG_MCUMGR=y

# Enable console with mcumgr pass through
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_UART_CONSOLE_MCUMGR=y

# Configure Golioth SDK dependencies
CONFIG_ZVFS_EVENTFD_MAX=14
CONFIG_ZVFS_OPEN_MAX=23
CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=1536
CONFIG_MBEDTLS_ENABLE_HEAP=y
CONFIG_MBEDTLS_HEAP_SIZE=10240
CONFIG_NETWORKING=y
CONFIG_NET_IPV4=y
CONFIG_COAP_EXTENDED_OPTIONS_LEN=y
CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE=39

# Enable the shell mcumgr transport. This allows SMP messages to pass
# through the shell to the mgmt subsystem.
CONFIG_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_BASE64=y
CONFIG_MCUMGR_TRANSPORT_SHELL=y

# Enable file system commands
CONFIG_MCUMGR_GRP_FS=y

# Enable shell commands over SMP
CONFIG_SHELL_BACKEND_DUMMY=y
CONFIG_MCUMGR_GRP_SHELL=y

# Some mgmt command handlers require a large stack.
CONFIG_MAIN_STACK_SIZE=2048

# Enable certificate authentication.
CONFIG_GOLIOTH_AUTH_METHOD_CERT=y

# Enable `log halt` and `log go` commands
CONFIG_LOG_CMDS=y

# If runtime-settings are enabled, use the file storage-backend
CONFIG_SETTINGS_FILE=y
CONFIG_SETTINGS_FILE_PATH="/lfs1/settings"

# Application
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_NET_LOG=y
CONFIG_NET_SHELL=y
CONFIG_REBOOT=y
CONFIG_WIFI_CREDENTIALS=y
# CONFIG_WIFI_CREDENTIALS_BACKEND_PSA=y
CONFIG_WIFI_CREDENTIALS_MAX_ENTRIES=2

# Flash memory (etc.) for firmware upgrade
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_STREAM_FLASH=y
CONFIG_IMG_MANAGER=y
CONFIG_IMG_ERASE_PROGRESSIVELY=y
CONFIG_REBOOT=y

# The rest of the runtime credentials config
CONFIG_SETTINGS=y
CONFIG_SETTINGS_RUNTIME=y
# CONFIG_GOLIOTH_SAMPLE_SETTINGS_AUTOLOAD=y
# CONFIG_GOLIOTH_SAMPLE_SETTINGS_SHELL=y

# Misc.
CONFIG_JSON_LIBRARY=y

# Longer response length needed for network info
CONFIG_GOLIOTH_RPC_MAX_RESPONSE_LEN=512
CONFIG_GPIO=y
CONFIG_I2C=y
CONFIG_SENSOR=y

# Enable floating point support in printf
CONFIG_CBPRINTF_FP_SUPPORT=y

# ESP32C6-specific configurations
CONFIG_WIFI=y
CONFIG_HEAP_MEM_POOL_SIZE=49152
# CONFIG_ESP_HEAP_MEM_POOL_REGION_1_SIZE=32768 (DOESN'T EXIST)

CONFIG_NET_L2_ETHERNET=y

CONFIG_NEWLIB_LIBC=y

CONFIG_NET_DHCPV4=y

# CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y

CONFIG_NET_L2_WIFI_SHELL=y

# CONFIG_GOLIOTH_SAMPLE_WIFI=y

# https://github.com/zephyrproject-rtos/zephyr/issues/63823
# CONFIG_POSIX_FS=n (DOESN'T EXIST)

Logs and Console Output

load:0x40800000,len:0x10480
load:0x40810490,len:0x6064
SHA-256 comparison failed:
Calculated: 3e73a891cee7f0da4d1c2352b4ec0d4e60ea77500aa5bbfd5f727f75140809da
Expected: 00000000e09a0000000000000000000000000000000000000000000000000000
Attempting to boot anyway...
entry 0x40804c9e
I (69) soc_init: ESP Simple boot
I (69) soc_init: compile time Nov 22 2025 11:40:11
I (70) soc_init: chip revision: v0.2
I (70) flash_init: SPI Speed      : 80MHz
I (72) flash_init: SPI Mode       : DIO
I (76) flash_init: SPI Flash Size : 8MB
I (80) boot: DRAM: lma 0x00000020 vma 0x40800000 len 0x10480  (66688)
I (86) boot: DRAM: lma 0x000104a8 vma 0x40810490 len 0x6064   (24676)
I (92) boot: IRAM: lma 0x00016518 vma 0x00000000 len 0x9ae0   (39648)
I (98) boot: IMAP: lma 0x00020000 vma 0x42800000 len 0x24d68  (150888)
I (104) boot: IRAM: lma 0x00044d70 vma 0x00000000 len 0xb288   (45704)
I (111) boot: IMAP: lma 0x00050000 vma 0x42000000 len 0xaeec0  (716480)
I (117) boot: Image with 6 segments
I (120) boot: IROM segment: paddr=00050000h, vaddr=42000000h, size=AEEBEh (716478) map
I (128) boot: DROM segment: paddr=00020000h, vaddr=42800000h, size=24D70h (150896) map
I (147) boot: libc heap size 252 kB.
I (147) spi_flash: detected chip: gd
I (147) spi_flash: flash io: dio
{Esc}[m
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J[00:00:00.005,000] {Esc}[0m<inf> wifi_init: rx ba win: 6{Esc}[0m
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J[00:00:00.015,000] {Esc}[1;31m<err> fs: mount point not found!!{Esc}[0m
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J[00:00:00.016,000] {Esc}[1;31m<err> fs: mount point not found!!{Esc}[0m
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J[00:00:00.016,000] {Esc}[1;31m<err> wifi_credentials_backend: Initializing settings subsystem failed: -2{Esc}[0m
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J[00:00:00.016,000] {Esc}[1;31m<err> wifi_credentials: Initializing WiFi credentials storage backend failed, err: -2{Esc}[0m
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J*** Booting Zephyr OS build v4.2.1 ***
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J*** Golioth Firmware SDK v0.21.0 ***
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J[00:00:00.016,000] {Esc}[0m<dbg> golioth_rd_template: main: Start Reference Design Template sample{Esc}[0m
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J[00:00:00.016,000] {Esc}[0m<inf> golioth_rd_template: Firmware version: 2.8.0{Esc}[0m
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J[00:00:00.016,000] {Esc}[1;31m<err> fs: mount point not found!!{Esc}[0m
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J[00:00:00.016,000] {Esc}[1;33m<wrn> golioth_rd_template: Could not stat /lfs1/credentials/crt.der, err: -2{Esc}[0m
{Esc}[1;32muart:~$ {Esc}[m{Esc}[8D{Esc}[J{Esc}[1;32muart:~$ {Esc}[m

Attempts to Resolve

Tried looking for similar build errors, but couldn’t find anything helpful on why those modules wouldn’t be included already…

Hey @nicolas,

In the Reference Design Template, Zephyr lives under the deps folder. The generate-lfs-image.py script imports devicetree and runners from the Zephyr tree (scripts/dts/python-devicetree/src and scripts/west_commands). The devicetree import error wasn’t about missing pip packages as that module comes directly from the Zephyr repo.

You can see the assumption in the script here:

WEST_TOPDIR = Path(west.configuration.west_dir()).parent

sys.path.insert(0, str(WEST_TOPDIR / 'zephyr' / 'scripts' / 'dts' / 'python-devicetree' / 'src'))
sys.path.insert(0, str(WEST_TOPDIR / 'zephyr' / 'scripts' / 'west_commands'))

from devicetree.edtlib import Node
from runners.core import BuildConfiguration

This assumes zephyr/ is at the repo top level. In the RD template it’s actually under deps/zephyr, so the paths don’t exist. The quick fix is to add the extra deps segment:

sys.path.insert(0, str(WEST_TOPDIR / 'deps' / 'zephyr' / 'scripts' / 'dts' / 'python-devicetree' / 'src'))
sys.path.insert(0, str(WEST_TOPDIR / 'deps' / 'zephyr' / 'scripts' / 'west_commands'))

The fs: mount point not found!! messages are a side effect of the LittleFS partition not being initialized the way this sample expects. The certificate_provisioning example relies on the CMake rule running generate-lfs-image.py to generate and flash an image that overwrites the first erase blocks of the LFS partition. LittleFS itself doesn’t require a prebuilt image, but this helper makes sure the partition starts from a known, clean state. Once the Python import issue is fixed, the mount error should go away and you can then use mcumgr to upload the cert/key files onto the filesystem.

Thank you Mark! That definitely helped!

I was running into some other issues stating it couldn’t find lfs1, but then I realized the certificate_provisioning example had some soc overlays that enabled this alias under the fstabstructure, so I did this and it worked, so i add the following to my overlay for my board file and it was able to compile:

/*
 * Copyright (c) 2025
 * SPDX-License-Identifier: Apache-2.0
 */

/ {

	fstab {
		compatible = "zephyr,fstab";

		lfs1: lfs1 {
			compatible = "zephyr,fstab,littlefs";
			mount-point = "/lfs1";
			partition = <&storage_partition>;
			automount;
			read-size = <16>;
			prog-size = <16>;
			cache-size = <64>;
			lookahead-size = <32>;
			block-cycles = <512>;
		};
	};
};


&wifi {
	status = "okay";
};

&storage_partition {
	reg = <0x00250000 0x00008000>;
};

Now it builds just fine and I can flash it, but I am getting some runtime errors that seem to be related to an incorrect flash size… so i need to do some digging on what value the reg should be for

&storage_partition {
	reg = <0x00250000 0x00008000>;
};

As I am unsure if that is correct and how to come up with that value… (that was provided as an example for the esp32s3, but I am using the esp32c6, with 4 MB of flash)

1 Like