microSD for FMFU, flash_driver_api

Hello. I want to use microSD card mounted in my device tree overlay on SPI3 as "zephyr,mmc-spi-slot" instead of onboard NOR flash for full modem firmware update. Hovewer, during FMFU initialization in function call tree:

dfu_target_full_modem_cfg => dfu_target_stream_init => stream_flash_init => flash_get_write_block_size
there is:
api->get_parameters(dev)->write_block_size;
How to implement flash_driver_api for "zephyr,mmc-spi-slot" characteristic? Or can I add some additional "zephyr,..." characteristics to "compatible" property in device tree to enable this feature?
I also need to use FAT filesystem to make SD card acceptable by PC usb-microsd card reader.
Thanks.
  • Hi,

    Do you plan to download the new modem images via the nRF9160, or is the idea that the user will place the image on the SD card themselves?

    I don't think you can use the SD card directly with the dfu_target or fmfu_fdev libraries, as they assume you can access a random part of the flash directly, rather than having to read it in blocks. The libraries also don't account for any file system, so that might also cause problems.

    However, you should be able to use the full modem update API directly from the modem library, where the application handles reading (and writing if necessary) from the SD card itself.

    See the documentation here for how to perform a full modem update.

    Best regards,

    Didrik

  • Idea in that there is no spi NOR flash on my board, but it is only on nRF9160DK board. On my board there is only SD card. The aim is to make Zephyr consider a single file on sd card as an external flash where it can write/read FMFU binary file, using as buffer. 

    Now I written a driver code with implemented flash_driver_api functionality. This driver writes and read in a single opened file on FAT formatted SD card. However, my driver is not initialized by Zephyr, I dont know how exactly to add it to device tree overlay file. To spi3? Or to sdhc0: sdhc@0, which I put to spi3? How to make Zephyr see and initialize my driver?

    #define DT_DRV_COMPAT my_file_flash_drive
    ....some code...
    and at the end of a file:
    DEVICE_DT_INST_DEFINE(0, &file_flash_drive_init, NULL, &file_flash_drive_data, &file_flash_drive_config_0, POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY, &file_flash_drive_api);
    In application I try to get device instance by:
    dev = device_get_binding(DT_LABEL(DT_INST(0, my_file_flash_drive)));
    In .overlay file I have:
    &spi3 {
        compatible = "nordic,nrf-spim";
        status = "okay";
        sck-pin = <21>;
        mosi-pin = <24>;
        miso-pin = <22>;

        cs-gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;

        sdhc0: sdhc@0 {
            compatible = "zephyr,mmc-spi-slot";
            reg = <0>;
            status = "okay";
            label = "SDHC0";
            spi-max-frequency = <24000000>;
        };
    };
    In top project CMakeLists.txt I put:
    add_subdirectory_ifdef(CONFIG_FILE_FLASH_DRIVE src/file_flash_drive)
    In driver directory's CMakeLists.txt I put:
    zephyr_library()
    zephyr_library_include_directories($ENV{ZEPHYR_BASE}/../modules/fs/fatfs/include)
    zephyr_library_sources(file_flash_drive.c)
    During build I get error:
    error: 'DT_N_INST_0_file_flash_drive_P_label' undeclared (first use in this function)
  • You will probably have to write a bindings file, so that you can define your own device tree node.

    That way, the device tree node can be tied to your flash driver, so that Zephyr knows that it should initialize it.

    You can read more about how it is done here:

    https://iwasz.pl/electronics/2021-06-18-out-of-tree-zephyr-module.md/

    https://github.com/martelmy/NCS_examples/tree/main/devicetree/devicetree_custom_device

  • Yes, I just created it "my,file-flash-drive.yaml" , but how to tell build system where to search for this file?

    description: |
      Raw flash storage emulation based on a single file in FAT-FS formatted SD card
    
    compatible: "my,file-flash-drive"
    include: ["base.yaml"]
    To help build system find it I added to the top of my project's CMakeLists:
    list(APPEND DTS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/src/file_flash_drive)
    list(APPEND EXTRA_ZEPHYR_MODULES ${CMAKE_CURRENT_SOURCE_DIR}/src/file_flash_drive)
    My yaml file is located in file_flash_drive folder. This folder structure is:
    Now the project builds successfully, but in runtime only NULL is returned when I ask for the device:
    dev = device_get_binding(DT_LABEL(DT_INST(0, my_file_flash_drive)));
    The addition to device tree overlay file is:
    / {
        file-flash-drive {
            compatible = "my,file-flash-drive";
            status = "okay";
        };
    };
  • UPD: I make it recognizable by Zephyr, however, I found that fatfs is initialized later than my driver. My driver has priority

    CONFIG_APPLICATION_INIT_PRIORITY

    But fs system is defined inside of SDK as

    SYS_INIT(fs_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
    How to tell it that fs should be initialized before my device? Is it possible?
Related