Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nrf_blk_dev_read_req is called from critical region in the SDK

Hello,

I'm using SDK nrf5_17.0.2 on nrf52840

I'm implementing a custom nrf block device for a spi nand flash, and I'm getting trouble with the calling site of the nrf_blk_dev_read_req call from the usb msc (app_usbd_msc).

nrf_blk_dev_read_req could be called either by app_usbd_msc.c::cmd_read_start or by app_usbd_msc.c:msc::msc_blockdev_ev_handler as shown in the following screenshot:

The call stack from the cmd_read_start is "the normal path" and this path works. The callstack from the msc_blockdev_ev_handler comes from my block device where I have to notify the usb msc stack the status of the block device request (for the example at the end of the read request):


const nrf_block_dev_event_t ev = {
        .ev_type = NRF_BLOCK_DEV_EVT_BLK_READ_DONE,
        .result = NRF_BLOCK_DEV_RESULT_SUCCESS,
        .p_context = p_work->p_context,
        .p_blk_req = p_blk,
};

p_work->ev_handler(p_blk_dev, &ev);

The problem is in the ev_handler (pointing to msc_blockdev_ev_handler) implementation where the _BLK_READ_DONE command is handled like the following:

 case NRF_BLOCK_DEV_EVT_BLK_READ_DONE:
    CRITICAL_REGION_ENTER();
    msc_blockdev_read_done_handler(p_blk_dev, p_event);
    CRITICAL_REGION_EXIT();
    break;

msc_blockdev_read_done_handler is called in a critical region. So following the call stack from this point leads to app_usbd_msc.c::read_block_mem_processor:L950 where nrf_blk_dev_read_req is called if there is still some bytes to process.

The problem is that I currently reading page size (4096 bytes) in the external memory by SPI in a asynchronous way so I'm using SPIM with EasyDMA. And the SPI irq is never called because NVIC->ICER has been clear in CRITICAL_REGION_ENTER.

Why msc_blockdev_read_done_handler has to be called in a critical region ? How can I fix this issue ?

Best

Joël

Parents
  • joel-sc said:
    But the issue with this was the nrfx_spim_xfer was interrupted by some irq and my SPI transfers was corrupted/invalid. My assumption is the flash doesn't seem support these bus interruptions.

     Are you able to find out what IRQ this is? Is it the external NAND chip you're suspecting that does not support bus interruptions? The asserts you mention does indeed seem to be timing related, so that's a good call I think.

    Can you check whether you have this SOFTDEVICE_PRESENT macro for entering a critical region enabled. See snippet below. The event shouldn't be erased when you enter/exit this CRITICAL_REGION, and should be trigged once you enable interrupts again after the CRITICAL tasks has been completed.

    Best regards,

    Simon

  • Hello,

     Are you able to find out what IRQ this is?

    Unfortunately, no...

    Is it the external NAND chip you're suspecting that does not support bus interruptions?

    That is not explicitly indicated in the datasheet... The flash is a NAND MT29F8G01, but you won't be able to find the datasheet on the internet.

    Can you check whether you have this SOFTDEVICE_PRESENT macro for entering a critical region enabled.

    Yes , it's defined.

    See snippet below

    I think you forgot to paste this snippet ?

    The implementation of the sd_nvic_critical_region_enter write ~0 to the NVIC->ICER which disable all external irq. So I don't get how pending interrupt will be raised once sd_nvic_critical_region_exit is called.

    Best,

Reply
  • Hello,

     Are you able to find out what IRQ this is?

    Unfortunately, no...

    Is it the external NAND chip you're suspecting that does not support bus interruptions?

    That is not explicitly indicated in the datasheet... The flash is a NAND MT29F8G01, but you won't be able to find the datasheet on the internet.

    Can you check whether you have this SOFTDEVICE_PRESENT macro for entering a critical region enabled.

    Yes , it's defined.

    See snippet below

    I think you forgot to paste this snippet ?

    The implementation of the sd_nvic_critical_region_enter write ~0 to the NVIC->ICER which disable all external irq. So I don't get how pending interrupt will be raised once sd_nvic_critical_region_exit is called.

    Best,

Children
No Data
Related