nrf52840 spim, external flash W25Q32JV read/write failed, mcuboot failed

We are using the external flash w25q32jv via SPIM connection. the configuration as below.


arduino_spi: &spi3 {
status = "okay";
compatible = "nordic,nrf-spim";
cs-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;

pinctrl-0 = <&spi3_default>;
pinctrl-1 = <&spi3_sleep>;
pinctrl-names = "default", "sleep";
w25q32jv: w25q32jv@0 {
compatible = "jedec,spi-nor";
reg = < 0 >;
spi-max-frequency = < 8000000 >;
size = < 0x2000000 >;
has-dpd;
t-enter-dpd = < 3000 >;
t-exit-dpd = < 30000 >;
jedec-id = [ ef 40 16 ];
};
};
When performing write/read with only configuration SPI nor flash, it passed. But when integrating into the system with USB_CDC_ACM, PDMIC, zephyr threads. It's very easy to fail write/read flash and mcuboot from external flash. We investigate that the f/w sending the wrong op-code for reading/writing. If we use irq_lock/unlock before flash_area_write(), flash_area_read() in zephyr library. The flash operation is successful and DFU with mcumgr will pass.
But this solution needs to modify the zephyr library (flash_map.c), not easy to commit and apply to our firmware. What should be appropriate solution in this case?
  • Update:

    spi3_default: spi3_default {
    group1 {
    psels = <NRF_PSEL(SPIM_SCK, 1, 10)>, <NRF_PSEL(SPIM_MOSI, 1, 13)>;
    nordic,drive-mode = <NRF_DRIVE_H0H1>;
    };
    group2 {
    psels = <NRF_PSEL(SPIM_MISO, 0, 3)>;
    };
    };

    spi3_sleep: spi3_sleep {
    group1 {
    psels = <NRF_PSEL(SPIM_SCK, 1, 10)>, <NRF_PSEL(SPIM_MOSI, 1, 13)>;
    nordic,drive-mode = <NRF_DRIVE_H0H1>;
    low-power-enable;
    };
    group2 {
    psels = <NRF_PSEL(SPIM_MISO, 0, 3)>;
    low-power-enable;
    };
    };
  • Hi,

    We investigate that the f/w sending the wrong op-code for reading/writing. If we use irq_lock/unlock before flash_area_write(), flash_area_read() in zephyr library. The flash operation is successful and DFU with mcumgr will pass.

    It looks like there is some race condition in your application that is seems solved when you apply this critical section locks in the lower layers of the zephyr library. But applications should apply critical section (lock/unlock of schedulers) not in lower levels but in the app level.

    Based on your explanation, it sounds very much like you managed to solve an application race condition by applying critical sections on lower levels.

    You need to figure out why this workaround (irq_lock/unlock) worked for you. This can be due to any race condition in your application not visible to us.

  • Hi,
    We are using mcuboot and mcumgr feature for updating F/W and mcuboot and mcumgr will use zephyr library to write/read to ext-flash without our control. We need to enable USB, PDM for application while DFU (device firmware update).
    If we can not apply workaround (irq_lock/unlock) the MCU boot will be failed. We want to know why USB, PDM module can affect to SPI NOR flash? with our application, it's easy to apply irq_lock, but mcuboot and mcumgr belong to nrf SDK, we can not change! Is there any way that we can avoid it without changing low layer levels?

  • Hi Susheel,
    we've found this problem in Errata, could you confirm this, and should we move to use SPIM2 instead of SPIM3?

    [198] SPIM: SPIM3 transmit data might be corrupted

    https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF52840_Rev2%2FERR%2FnRF52840%2FRev2%2Flatest%2Fanomaly_840_198.html

  • Hi

    Sorry about the late reply, but Susheel is out of office for the time being so I have taken over and I needed a while to get into your case before getting back to you. Since you're not using the QSPI peripheral that can only be used by the SPIM3, it should be fine to move to SPIM2. Although it should also be perfectly fine using the SPIM3 as long as you take into account and implement the workaround:

    Reserve dedicated RAM AHB slave for the SPIM3 transmit buffer, not overlapping with application data used by the CPU. In addition, synchronize so that the CPU is not writing data to the transmit buffer while SPIM is transmitting data.

    Best regards,

    Simon

Related