diff --git a/ports/stm32/flashbdev.c b/ports/stm32/flashbdev.c index 2b633cf16b..395662c8be 100644 --- a/ports/stm32/flashbdev.c +++ b/ports/stm32/flashbdev.c @@ -143,14 +143,17 @@ int32_t flash_bdev_ioctl(uint32_t op, uint32_t arg) { flash_bdev_irq_handler(); return 0; - case BDEV_IOCTL_SYNC: + case BDEV_IOCTL_SYNC: { + uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access if (flash_flags & FLASH_FLAG_DIRTY) { flash_flags |= FLASH_FLAG_FORCE_WRITE; while (flash_flags & FLASH_FLAG_DIRTY) { - NVIC->STIR = FLASH_IRQn; + flash_bdev_irq_handler(); } } + restore_irq_pri(basepri); return 0; + } } return -MP_EINVAL; } diff --git a/ports/stm32/irq.h b/ports/stm32/irq.h index 3fe20867fe..9919013f89 100644 --- a/ports/stm32/irq.h +++ b/ports/stm32/irq.h @@ -106,9 +106,9 @@ MP_DECLARE_CONST_FUN_OBJ_0(pyb_irq_stats_obj); //#def IRQ_PRI_SYSTICK 0 #define IRQ_PRI_UART 1 -#define IRQ_PRI_FLASH 1 #define IRQ_PRI_SDIO 1 #define IRQ_PRI_DMA 1 +#define IRQ_PRI_FLASH 2 #define IRQ_PRI_OTG_FS 2 #define IRQ_PRI_OTG_HS 2 #define IRQ_PRI_TIM5 2 @@ -126,10 +126,6 @@ MP_DECLARE_CONST_FUN_OBJ_0(pyb_irq_stats_obj); // get dropped. The handling for each character only consumes about 0.5 usec #define IRQ_PRI_UART NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 1, 0) -// Flash IRQ must be higher priority than interrupts of all those components -// that rely on the flash storage. -#define IRQ_PRI_FLASH NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 2, 0) - // SDIO must be higher priority than DMA for SDIO DMA transfers to work. #define IRQ_PRI_SDIO NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 4, 0) @@ -137,6 +133,11 @@ MP_DECLARE_CONST_FUN_OBJ_0(pyb_irq_stats_obj); // into the sdcard driver which waits for the DMA to complete. #define IRQ_PRI_DMA NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 5, 0) +// Flash IRQ (used for flushing storage cache) must be at the same priority as +// the USB IRQs, so that the IRQ priority can be raised to this level to disable +// both the USB and cache flushing, when storage transfers are in progress. +#define IRQ_PRI_FLASH NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) + #define IRQ_PRI_OTG_FS NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) #define IRQ_PRI_OTG_HS NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) #define IRQ_PRI_TIM5 NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) diff --git a/ports/stm32/spibdev.c b/ports/stm32/spibdev.c index 368e639665..9b5a10b400 100644 --- a/ports/stm32/spibdev.c +++ b/ports/stm32/spibdev.c @@ -49,8 +49,7 @@ int32_t spi_bdev_ioctl(spi_bdev_t *bdev, uint32_t op, uint32_t arg) { case BDEV_IOCTL_SYNC: if (bdev->spiflash.flags & 1) { - // we must disable USB irqs to prevent MSC contention with SPI flash - uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); + uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access mp_spiflash_cache_flush(&bdev->spiflash); led_state(PYB_LED_RED, 0); // indicate a clean cache with LED off restore_irq_pri(basepri); @@ -61,8 +60,7 @@ int32_t spi_bdev_ioctl(spi_bdev_t *bdev, uint32_t op, uint32_t arg) { } int spi_bdev_readblocks(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { - // we must disable USB irqs to prevent MSC contention with SPI flash - uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); + uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access mp_spiflash_cached_read(&bdev->spiflash, block_num * FLASH_BLOCK_SIZE, num_blocks * FLASH_BLOCK_SIZE, dest); restore_irq_pri(basepri); @@ -70,8 +68,7 @@ int spi_bdev_readblocks(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uin } int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { - // we must disable USB irqs to prevent MSC contention with SPI flash - uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); + uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access int ret = mp_spiflash_cached_write(&bdev->spiflash, block_num * FLASH_BLOCK_SIZE, num_blocks * FLASH_BLOCK_SIZE, src); if (bdev->spiflash.flags & 1) { led_state(PYB_LED_RED, 1); // indicate a dirty cache with LED on diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index b0b607deff..7724ae0f42 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -55,8 +55,7 @@ void storage_init(void) { #endif // Enable the flash IRQ, which is used to also call our storage IRQ handler - // It needs to go at a higher priority than all those components that rely on - // the flash storage (eg higher than USB MSC). + // It must go at the same priority as USB (see comment in irq.h). NVIC_SetPriority(FLASH_IRQn, IRQ_PRI_FLASH); HAL_NVIC_EnableIRQ(FLASH_IRQn); }