MCUBoot: adding custom serial flash driver as secondary partition

We use spi flash with custom driver and goal is to set it to act as secondary partition for MCUBoot.

The question is how to adapt driver to be accepted by MCUBoot, maybe there is an example on how driver should look like?

As far as I understand Nordic supports mx25r64, what files have to be produced and where to place them to enable custom driver to be accepted by MCUBoot?

Parents
  • The nRF91 DK which contains an mx25r64, and it will use the spi nor driver to communicate with it:

    https://github.com/nrfconnect/sdk-zephyr/blob/v3.0.99-ncs1/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_common_0_14_0.dtsi#L66

    https://github.com/nrfconnect/sdk-zephyr/blob/v3.0.99-ncs1/drivers/flash/spi_nor.c#L10

    As you can see, the spi_nor.c is located inside zephyr/drivers/flashIf you do it this way, you will be able to write/read to the spi flash using the flash API.

    After adding your spi flash driver and adding your flash device to the device tree you can put the secondary partition in your external flash by doing the following:

    Best regards,

    Simon

  • Thank you for clarification, Simon.

    At the moment I am struggling with this error: "zephyr\include\generated\devicetree_unfixed.h:6002:34: error: 'DT_N_S_soc_S_spi_40023000_S_at25xe081_0_P_size' undeclared here (not in a function); did you mean 'DT_N_S_soc_S_spi_40023000_S_at25xe081_0_P_reg".

    I added this to my_board.dts file:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    &spi2 {
    status = "okay";
    at25xe081: at25xe081@0 {
    compatible = "at25xe081";
    reg = <0>;
    label = "AT25XE081";
    size = <67108864>;
    };
    };
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    And in my driver wrapper I added #define DT_DRV_COMPAT at25xe081. However it seems that size property is not found when I am doing: flash_size = DT_INST_PROP(0, size) / 8. What I am missing here?

  • Is it possible to run debugger in bootloader (using VS Code) ?

    I managed to build the project, however get the following error from the bootloader:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    *** Booting Zephyr OS build v2.7.0-ncs1 ***
    00> I: Starting bootloader
    00> W: Failed reading sectors; BOOT_MAX_IMG_SECTORS=128 - too small?
    00> E: ***** MPU FAULT *****
    00> E: Instruction Access Violation
    00> E: r0/a1: 0x00000000 r1/a2: 0x00000000 r2/a3: 0x20000284
    00> E: r3/a4: 0x00000020 r12/ip: 0xe6f7fbb5 r14/lr: 0x00000e4f
    00> E: xpsr: 0x61000000
    00> E: Faulting instruction address (r15/pc): 0xe6f7fbb4
    00> E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
    00> E: Current thread: 0x20000128 (unknown)
    00> E: Resetting system
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    And this is my pm_static.yml:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    external_flash:
    address: 0x0
    region: external_flash
    size: 0x800000
    app:
    address: 0xc200
    end_address: 0x6DC80
    region: flash_primary
    size: 0x61A80
    mcuboot:
    address: 0x0
    end_address: 0xc000
    placement:
    before:
    - mcuboot_primary
    region: flash_primary
    size: 0xc000
    mcuboot_pad:
    address: 0xc000
    end_address: 0xc200
    placement:
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • I just talked to a colleague familiar with this stuff, and asked if at25xe081 was supported by the spi_nor driver. He said as far as he knew, most of the NOR chips should be supported by the spi_nor driver, and most of the commands from the data sheets seems to be generic, so it should not be a problem as far as he knew.

    To get more details, and a more certain answer, try to ask the Zephyr experts on Zephyr Discord, if at25xe081 is supported by the spi_nor driver (Maybe add a link to the data sheet). If that is the case, you may save a lot of time.

    Best regards,

    Simon

  • Thank you for information, Simon.

    Maybe you can also provide a hint on how to debug the bootloader?

  • mesh777 said:
    Maybe you can also provide a hint on how to debug the bootloader?

    Ah, yes. Of course. If you debug through VS Code GDB it should be quite straightforward. See the following video: https://youtu.be/MGsZJpdLtco?list=PLx_tBuQ_KSqEt7NK-H7Lu78lT2OijwIMl&t=30 

    Then set a break point in <ncs location>/bootloader/mcuboot/boot/zephyr/main.c-->main() and you can start to debug.

    Let me know if you don't get it to work.

  • I use VS Code and GDB.

    Can you share working launch.json, as I am not able to manage to reach that breakpoint.

    EDIT: I enabled debugging by unchecking Debug Options in build configuration.

    Now I have problem with device_get_binding, it returns Null for my driver. Although MCUBoot uses the same dts file when building. What else could be possibly wrong?

Reply
  • I use VS Code and GDB.

    Can you share working launch.json, as I am not able to manage to reach that breakpoint.

    EDIT: I enabled debugging by unchecking Debug Options in build configuration.

    Now I have problem with device_get_binding, it returns Null for my driver. Although MCUBoot uses the same dts file when building. What else could be possibly wrong?

Children
  • mesh777 said:
    Now I have problem with device_get_binding, it returns Null for my driver. Although MCUBoot uses the same dts file when building. What else could be possibly wrong?

    There may be different reasons for the failure of device_get_binding(). I can see in the overlay you provider earlier that label="AT25XE081", so maybe you could start by putting a break point in mcuboot when device_get_binding() is called and check that it evaluates to device_get_binding("AT25XE081").

    Maybe also check the file build/mcuboot/zephyr/zephyr.dts (notice that this is a different path than build/zephyr/zephyr.dts), and check if you find the at25x node, and that it is enabled. If not, you probably need to enable it following the approaches explained in https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/nrf/ug_multi_image.html#image-specific-variables.

    If the init function of you driver fails (the function that is passed into DEVICE_DT_INST_DEFINE, like done here), the call to device_get_binding will also fail.

    In this reply I give some detailed explanations about why init function need to be successful for device_get_binding() to succeed, if you're interested. It may be a bit outdated due to an older NCS version.

    Best regards,

    Simon

  • I checked build/mcuboot/zephyr/zephyr.dts, at25x appears in spi2 node. Also device_get_binding is called with correct label.

    However init function is not called. In driver file the following macro is added at the end of file:

    DEVICE_DT_INST_DEFINE(0, &spi_flash_init, NULL,
             &spi_flash_data_0, &spi_flash_config_0,
             POST_KERNEL, 80,
             &spi_flash_api);
    And spi_flash_init is not called. What I am still missing?
  • mesh777 said:
    However init function is not called. In driver file the following macro is added at the end of file:

    If your custom init function is not called, maybe it is because the custom driver file is not seen by the build system and added to the executable? Have you modified the CMakeLists.txt to include the source file? Like done for spi_nor.c for example here: https://github.com/nrfconnect/sdk-zephyr/blob/v2.7.0-ncs1/drivers/flash/CMakeLists.txt#L6 (try adding your driver in-tree first, just to make sure it works). You can check that the source file is included by looking in /<sample>/build/mcuboot/zephyr/drivers/flash/CMakeFiles/drivers__flash.dir I think (or just open build folder in vscode, click ctrl+P and search for the source (.c) file).

    Again, I do think the spi_nor.c driver might support the at25x, at least it's worth checking out.

    mesh777 said:
    And spi_flash_init is not called. What I am still missing?

    Where did you find this function? I search through the whole NCS v1.8.0 (based on earlier logs, it seems like you're using this version).

  • This is my own static function which resides in the driver.

    I need to make it out-of-tree anyway, could you please check how to proceed with that.

    Thank you again.

  • mesh777 said:
    I need to make it out-of-tree anyway, could you please check how to proceed with that.

    Yes, of course I can look into that. I'll do it tomorrow.

    However, I think it is smart to try to resolve one issue at the time. So I would recommend this approach:

    1. Add your driver in-tree and make sure it works
    2. Add your fully working driver out-of-tree