Multiple Flash Chips

Using NCS 1.8 and NRF5340

Right now I’m able to use the MX25U external flash that we have attached to the nRF5340, We are planning to ship our board with MCUBoot and application loaded on the device, but we’re not necessarily going to use the MX25U.  In all likelihood we will have 3-4 different flash chips that could be soldered to the board.

                Is there a way to build a single application that can work with multiple varieties of flash chip?  The pinout will remain the same, but the flash chip itself will be different.  Notably, this will mean different “jedec-id” values, and potentially different settings for fields like “quad-enable-requirements” or even “sck-frequency”

                Is this possible?

  • Hi,

    Are you planning on using the external flash for secondary image slot for MCUboot?

    You can probably read the JEDEC of the devices using (Q)SPI and do initialization of the external flash in the application, but this may not with MCUboot and the devicetree configuration in Zephyr.

    If you can elaborate a bit on how the flash will be used, I can check the alternatives with our developers.

    Best regards,
    Jørgen

  • The intent is to use this external memory as the secondary image slot for MCUBoot.

  • Hi,

    Multiple flash variants are currently not supported, as the HW configuration is done statically.

    This solution to the same problem was proposed by my colleague in another ticket:

    On the MCUboot side:

    To swap the images, the MCUboot will run the function swap_run(), and then it will flash_area_open() for both the primary slot as well as the secondary slot, which will get the flash_area struct for both slots, including the flash device name set by CONFIG_PM_EXTERNAL_FLASH_DEV_NAME.

    Right after flash_area_open(FLASH_AREA_IMAGE_SECONDARY..) do the following (pseudocode):

    /*
        In prj.conf: CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="FIRST_FLASH_DEV"
        
        In overlay file:
        
        &spi0 {
            flashdev1@{
                ...
                label="FIRST_FLASH_DEV";
            };
            flashdev2@{
                ...
                label="SECOND_FLASH_DEV";
            };
        }
    
    */
    
    // In bootloader\mcuboot\boot\bootutil\src\swap_move.c-->swap_run(),after call to flash_area_open(FLASH_AREA_IMAGE_SECONDARY..)
    if(fap_sec->fa_dev_name=="FIRST_FLASH_DEV"){ // This check is probably not necessary, but will make it possible to use the same code e.g. if internal flash is used
        if(!device_get_binding(fap_sec->fa_dev_name)){
            // Change name of fap_sec->fa_dev_name to "SECOND_FLASH_DEV"
            // or you may have to create a new one, since the struct is of type const
        }
    }

    If the first flash device is not connected, the call to device_get_binding("FIRST_FLASH_DEV") will then fail, and you will modify the flash_area structure to use the label of the second flash device. Then flash area struct will then get passed down to lower layers and device_get_binding("x_FLASH_DEV") will eventually get called and get the spi/flash-specific functions.

    You should be able to follow this suggestions to add support for multiple flash chip variants. If you are receiving the DFU updates through the applications, you need to add a similar approach there in order to place the image in the correct flash chip variant.
    Let me know if you are facing any issues with this approach.
    Best regards,
    Jørgen
  • So the customer has been trying to implement the suggestion.

    his overlay looks like this

    / {
                    chosen {
                                    zephyr,code-partition = &boot_partition;
                                    nordic,pm-ext-flash = &mx25u;
                    };
    };
    
    &qspi {
                    compatible = "nordic,qspi-nor";
                    status = "okay";
                    sck-pin = <19>;
                    io-pins = <20>, <21>, <22>, <23>;
                    csn-pins = <17>;
                    flashsearch: flashsearch@0{
                                    compatible = "jedec,flashsearch";
                                    status = "okay";
                                    reg = <0>;
                                    sck-frequency = <32000000>;
                                    jedec-id = [ 00 00 00 ];
                                    label = "FLASHSEARCH";
                                    size = <16777216>;
                    };
                    mx25u: mx25u1633fm2i@1{
                                    compatible = "mxicy,mx25u1633fm2i";
                                    status = "okay";
                                    reg = <1>;
                                    quad-enable-requirements = "S1B6";
                                    writeoc = "pp4io";
                                    readoc = "read4io";
                                    sck-frequency = <32000000>;
                                    jedec-id = [ c2 25 35 ];
                                    label = "MX25U";
                                    size = <16777216>;
                                    has-dpd;
                                    t-enter-dpd = <10000>;
                                    t-exit-dpd = <35000>;
                    };
    };
    

    when he sets

    CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="FLASHSEARCH"

    it throws a warning

    warning for “attempt to assign the value '"FLASHSEARCH"' to the undefined symbol PM_EXTERNAL_FLASH_DEV_NAME”

    he has laid out the multiple spi device structures per your email, but the system doesn’t seem to include anything but the first device in the list. if he debugs into the “z_impl_device_get_binding” function (zephyr/kernel/device.c), and examines the __device_start to __device_end entries, He can see that the last one is “FLASHSEARCH” and there isn’t an “MX25U”.  So it fails. 

    He did initially modify swap_run(), but without success.  The original solution mentioned passing the different string to device_get_binding.  That part was failing, and debugged into it to discover that the devices listed between __device_start and __device_end do not contain my “MX25U”.  It also seems like that’s where I want to actually make the change, since that should propagate to the application as well.

Related