From 7ee5afe8d16e4b53a2468df097e6e1a91b8127ce Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Fri, 5 Mar 2021 10:15:29 +1100 Subject: [PATCH] drivers/bus: Detect QSPI transfer errors and pass up to spiflash driver. This changes the signatures of QSPI write_cmd_data, write_cmd_addr_data and read_cmd_qaddr_qdata so they return an error code. The softqspi and stm32 hardware qspi driver are updated to follow this new signature. Also the spiflash driver is updated to use these new return values. Signed-off-by: Damien George --- drivers/bus/qspi.h | 6 +-- drivers/bus/softqspi.c | 9 ++-- drivers/memory/spiflash.c | 94 ++++++++++++++++++++++++++------------- drivers/memory/spiflash.h | 6 +-- ports/stm32/qspi.c | 31 +++++++++++-- ports/stm32/spibdev.c | 24 +++++----- 6 files changed, 117 insertions(+), 53 deletions(-) diff --git a/drivers/bus/qspi.h b/drivers/bus/qspi.h index 7dfaaf3d40..33f482127d 100644 --- a/drivers/bus/qspi.h +++ b/drivers/bus/qspi.h @@ -41,10 +41,10 @@ enum { typedef struct _mp_qspi_proto_t { int (*ioctl)(void *self, uint32_t cmd); - void (*write_cmd_data)(void *self, uint8_t cmd, size_t len, uint32_t data); - void (*write_cmd_addr_data)(void *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src); + int (*write_cmd_data)(void *self, uint8_t cmd, size_t len, uint32_t data); + int (*write_cmd_addr_data)(void *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src); uint32_t (*read_cmd)(void *self, uint8_t cmd, size_t len); - void (*read_cmd_qaddr_qdata)(void *self, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest); + int (*read_cmd_qaddr_qdata)(void *self, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest); } mp_qspi_proto_t; typedef struct _mp_soft_qspi_obj_t { diff --git a/drivers/bus/softqspi.c b/drivers/bus/softqspi.c index 71ab559768..6ede29dcd7 100644 --- a/drivers/bus/softqspi.c +++ b/drivers/bus/softqspi.c @@ -158,15 +158,16 @@ STATIC void mp_soft_qspi_qwrite(mp_soft_qspi_obj_t *self, size_t len, const uint //mp_hal_pin_input(self->io1); } -STATIC void mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) { +STATIC int mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) { mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in; uint32_t cmd_buf = cmd | data << 8; CS_LOW(self); mp_soft_qspi_transfer(self, 1 + len, (uint8_t*)&cmd_buf, NULL); CS_HIGH(self); + return 0; } -STATIC void mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) { +STATIC int mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) { mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in; uint8_t cmd_buf[5] = {cmd}; uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr); @@ -174,6 +175,7 @@ STATIC void mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_ mp_soft_qspi_transfer(self, addr_len + 1, cmd_buf, NULL); mp_soft_qspi_transfer(self, len, src, NULL); CS_HIGH(self); + return 0; } STATIC uint32_t mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) { @@ -185,7 +187,7 @@ STATIC uint32_t mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) { return cmd_buf >> 8; } -STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) { +STATIC int mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) { mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in; uint8_t cmd_buf[7] = {cmd}; uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr); @@ -194,6 +196,7 @@ STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32 mp_soft_qspi_qwrite(self, addr_len + 3, &cmd_buf[1]); // 3/4 addr bytes, 1 extra byte (0), 2 dummy bytes (4 dummy cycles) mp_soft_qspi_qread(self, len, dest); CS_HIGH(self); + return 0; } const mp_qspi_proto_t mp_soft_qspi_proto = { diff --git a/drivers/memory/spiflash.c b/drivers/memory/spiflash.c index 9f8dc29a73..a71ef41f46 100644 --- a/drivers/memory/spiflash.c +++ b/drivers/memory/spiflash.c @@ -70,7 +70,8 @@ STATIC void mp_spiflash_release_bus(mp_spiflash_t *self) { } } -STATIC void mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t data) { +STATIC int mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t data) { + int ret = 0; const mp_spiflash_config_t *c = self->config; if (c->bus_kind == MP_SPIFLASH_BUS_SPI) { // Note: len/data are unused for standard SPI @@ -78,11 +79,13 @@ STATIC void mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 1, &cmd, NULL); mp_hal_pin_write(c->bus.u_spi.cs, 1); } else { - c->bus.u_qspi.proto->write_cmd_data(c->bus.u_qspi.data, cmd, len, data); + ret = c->bus.u_qspi.proto->write_cmd_data(c->bus.u_qspi.data, cmd, len, data); } + return ret; } -STATIC void mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src, uint8_t *dest) { +STATIC int mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src, uint8_t *dest) { + int ret = 0; const mp_spiflash_config_t *c = self->config; if (c->bus_kind == MP_SPIFLASH_BUS_SPI) { uint8_t buf[5] = {cmd, 0}; @@ -98,11 +101,12 @@ STATIC void mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, mp_hal_pin_write(c->bus.u_spi.cs, 1); } else { if (dest != NULL) { - c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, cmd, addr, len, dest); + ret = c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, cmd, addr, len, dest); } else { - c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src); + ret = c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src); } } + return ret; } STATIC uint32_t mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t len) { @@ -119,7 +123,7 @@ STATIC uint32_t mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t le } } -STATIC void mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { +STATIC int mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { const mp_spiflash_config_t *c = self->config; uint8_t cmd; if (c->bus_kind == MP_SPIFLASH_BUS_SPI) { @@ -127,11 +131,11 @@ STATIC void mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len } else { cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_C4READ_32 : CMD_C4READ; } - mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, NULL, dest); + return mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, NULL, dest); } -STATIC void mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) { - mp_spiflash_write_cmd_data(self, cmd, 0, 0); +STATIC int mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) { + return mp_spiflash_write_cmd_data(self, cmd, 0, 0); } STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) { @@ -208,36 +212,50 @@ void mp_spiflash_deepsleep(mp_spiflash_t *self, int value) { } STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr) { + int ret = 0; // enable writes - mp_spiflash_write_cmd(self, CMD_WREN); + ret = mp_spiflash_write_cmd(self, CMD_WREN); + if (ret != 0) { + return ret; + } // wait WEL=1 - int ret = mp_spiflash_wait_wel1(self); + ret = mp_spiflash_wait_wel1(self); if (ret != 0) { return ret; } // erase the sector uint8_t cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_SEC_ERASE_32 : CMD_SEC_ERASE; - mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, 0, NULL, NULL); + ret = mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, 0, NULL, NULL); + if (ret != 0) { + return ret; + } // wait WIP=0 return mp_spiflash_wait_wip0(self); } STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) { + int ret = 0; // enable writes - mp_spiflash_write_cmd(self, CMD_WREN); + ret = mp_spiflash_write_cmd(self, CMD_WREN); + if (ret != 0) { + return ret; + } // wait WEL=1 - int ret = mp_spiflash_wait_wel1(self); + ret = mp_spiflash_wait_wel1(self); if (ret != 0) { return ret; } // write the page uint8_t cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_WRITE_32 : CMD_WRITE; - mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, src, NULL); + ret = mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, src, NULL); + if (ret != 0) { + return ret; + } // wait WIP=0 return mp_spiflash_wait_wip0(self); @@ -253,13 +271,14 @@ int mp_spiflash_erase_block(mp_spiflash_t *self, uint32_t addr) { return ret; } -void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { +int mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { if (len == 0) { - return; + return 0; } mp_spiflash_acquire_bus(self); - mp_spiflash_read_data(self, addr, len, dest); + int ret = mp_spiflash_read_data(self, addr, len, dest); mp_spiflash_release_bus(self); + return ret; } int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) { @@ -289,9 +308,9 @@ int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint #if MICROPY_HW_SPIFLASH_ENABLE_CACHE -void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { +int mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { if (len == 0) { - return; + return 0; } mp_spiflash_acquire_bus(self); mp_spiflash_cache_t *cache = self->config->cache; @@ -304,7 +323,11 @@ void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uin if (bis < cache->block) { // Read direct from flash for first part rest = cache->block * SECTOR_SIZE - addr; - mp_spiflash_read_data(self, addr, rest, dest); + int ret = mp_spiflash_read_data(self, addr, rest, dest); + if (ret != 0) { + mp_spiflash_release_bus(self); + return ret; + } len -= rest; dest += rest; addr += rest; @@ -318,21 +341,22 @@ void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uin len -= rest; if (len == 0) { mp_spiflash_release_bus(self); - return; + return 0; } dest += rest; addr += rest; } } // Read rest direct from flash - mp_spiflash_read_data(self, addr, len, dest); + int ret = mp_spiflash_read_data(self, addr, len, dest); mp_spiflash_release_bus(self); + return ret; } -STATIC void mp_spiflash_cache_flush_internal(mp_spiflash_t *self) { +STATIC int mp_spiflash_cache_flush_internal(mp_spiflash_t *self) { #if USE_WR_DELAY if (!(self->flags & 1)) { - return; + return 0; } self->flags &= ~1; @@ -342,7 +366,7 @@ STATIC void mp_spiflash_cache_flush_internal(mp_spiflash_t *self) { // Erase sector int ret = mp_spiflash_erase_block_internal(self, cache->block * SECTOR_SIZE); if (ret != 0) { - return; + return ret; } // Write @@ -350,16 +374,18 @@ STATIC void mp_spiflash_cache_flush_internal(mp_spiflash_t *self) { uint32_t addr = cache->block * SECTOR_SIZE + i * PAGE_SIZE; int ret = mp_spiflash_write_page(self, addr, PAGE_SIZE, cache->buf + i * PAGE_SIZE); if (ret != 0) { - return; + return ret; } } #endif + return 0; } -void mp_spiflash_cache_flush(mp_spiflash_t *self) { +int mp_spiflash_cache_flush(mp_spiflash_t *self) { mp_spiflash_acquire_bus(self); - mp_spiflash_cache_flush_internal(self); + int ret = mp_spiflash_cache_flush_internal(self); mp_spiflash_release_bus(self); + return ret; } STATIC int mp_spiflash_cached_write_part(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) { @@ -389,10 +415,16 @@ STATIC int mp_spiflash_cached_write_part(mp_spiflash_t *self, uint32_t addr, siz // Read sector #if USE_WR_DELAY if (cache->block != 0xffffffff) { - mp_spiflash_cache_flush_internal(self); + int ret = mp_spiflash_cache_flush_internal(self); + if (ret != 0) { + return ret; + } } #endif - mp_spiflash_read_data(self, addr, SECTOR_SIZE, cache->buf); + int ret = mp_spiflash_read_data(self, addr, SECTOR_SIZE, cache->buf); + if (ret != 0) { + return ret; + } } #if USE_WR_DELAY diff --git a/drivers/memory/spiflash.h b/drivers/memory/spiflash.h index c4162ff21c..5ccf7d44c9 100644 --- a/drivers/memory/spiflash.h +++ b/drivers/memory/spiflash.h @@ -76,13 +76,13 @@ void mp_spiflash_deepsleep(mp_spiflash_t *self, int value); // These functions go direct to the SPI flash device int mp_spiflash_erase_block(mp_spiflash_t *self, uint32_t addr); -void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest); +int mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest); int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src); #if MICROPY_HW_SPIFLASH_ENABLE_CACHE // These functions use the cache (which must already be configured) -void mp_spiflash_cache_flush(mp_spiflash_t *self); -void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest); +int mp_spiflash_cache_flush(mp_spiflash_t *self); +int mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest); int mp_spiflash_cached_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src); #endif diff --git a/ports/stm32/qspi.c b/ports/stm32/qspi.c index 04e226697e..3036f6f384 100644 --- a/ports/stm32/qspi.c +++ b/ports/stm32/qspi.c @@ -196,7 +196,7 @@ STATIC int qspi_ioctl(void *self_in, uint32_t cmd) { return 0; // success } -STATIC void qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) { +STATIC int qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) { (void)self_in; QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag @@ -238,12 +238,17 @@ STATIC void qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t // Wait for write to finish while (!(QUADSPI->SR & QUADSPI_SR_TCF)) { + if (QUADSPI->SR & QUADSPI_SR_TEF) { + return -MP_EIO; + } } QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag + + return 0; } -STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) { +STATIC int qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) { (void)self_in; uint8_t adsize = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? 3 : 2; @@ -286,6 +291,9 @@ STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, // Write out the data 1 byte at a time while (len) { while (!(QUADSPI->SR & QUADSPI_SR_FTF)) { + if (QUADSPI->SR & QUADSPI_SR_TEF) { + return -MP_EIO; + } } *(volatile uint8_t *)&QUADSPI->DR = *src++; --len; @@ -294,9 +302,14 @@ STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, // Wait for write to finish while (!(QUADSPI->SR & QUADSPI_SR_TCF)) { + if (QUADSPI->SR & QUADSPI_SR_TEF) { + return -MP_EIO; + } } QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag + + return 0; } STATIC uint32_t qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) { @@ -320,6 +333,10 @@ STATIC uint32_t qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) { // Wait for read to finish while (!(QUADSPI->SR & QUADSPI_SR_TCF)) { + if (QUADSPI->SR & QUADSPI_SR_TEF) { + // Not sure that calling functions will deal with this appropriately + return -MP_EIO; + } } QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag @@ -328,7 +345,7 @@ STATIC uint32_t qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) { return QUADSPI->DR; } -STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) { +STATIC int qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) { (void)self_in; uint8_t adsize = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? 3 : 2; @@ -366,6 +383,9 @@ STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, if (((uintptr_t)dest & 3) == 0) { while (len >= 4) { while (!(QUADSPI->SR & QUADSPI_SR_FTF)) { + if (QUADSPI->SR & QUADSPI_SR_TEF) { + return -MP_EIO; + } } *(uint32_t *)dest = QUADSPI->DR; dest += 4; @@ -376,12 +396,17 @@ STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, // Read in remaining data 1 byte at a time while (len) { while (!((QUADSPI->SR >> QUADSPI_SR_FLEVEL_Pos) & 0x3f)) { + if (QUADSPI->SR & QUADSPI_SR_TEF) { + return -MP_EIO; + } } *dest++ = *(volatile uint8_t *)&QUADSPI->DR; --len; } QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag + + return 0; } const mp_qspi_proto_t qspi_proto = { diff --git a/ports/stm32/spibdev.c b/ports/stm32/spibdev.c index afa6f4ecdc..fecd4a9915 100644 --- a/ports/stm32/spibdev.c +++ b/ports/stm32/spibdev.c @@ -40,25 +40,29 @@ int32_t spi_bdev_ioctl(spi_bdev_t *bdev, uint32_t op, uint32_t arg) { bdev->flash_tick_counter_last_write = 0; return 0; - case BDEV_IOCTL_IRQ_HANDLER: + case BDEV_IOCTL_IRQ_HANDLER: { + int ret = 0; #if MICROPY_HW_SPIFLASH_ENABLE_CACHE if ((bdev->spiflash.flags & 1) && HAL_GetTick() - bdev->flash_tick_counter_last_write >= 1000) { - mp_spiflash_cache_flush(&bdev->spiflash); + ret = mp_spiflash_cache_flush(&bdev->spiflash); led_state(PYB_LED_RED, 0); // indicate a clean cache with LED off } #endif - return 0; + return ret; + } - case BDEV_IOCTL_SYNC: + case BDEV_IOCTL_SYNC: { + int ret = 0; #if MICROPY_HW_SPIFLASH_ENABLE_CACHE if (bdev->spiflash.flags & 1) { uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access - mp_spiflash_cache_flush(&bdev->spiflash); + ret = mp_spiflash_cache_flush(&bdev->spiflash); led_state(PYB_LED_RED, 0); // indicate a clean cache with LED off restore_irq_pri(basepri); } #endif - return 0; + return ret; + } } return -MP_EINVAL; } @@ -66,10 +70,10 @@ int32_t spi_bdev_ioctl(spi_bdev_t *bdev, uint32_t op, uint32_t arg) { #if MICROPY_HW_SPIFLASH_ENABLE_CACHE int spi_bdev_readblocks(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { 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); + int ret = mp_spiflash_cached_read(&bdev->spiflash, block_num * FLASH_BLOCK_SIZE, num_blocks * FLASH_BLOCK_SIZE, dest); restore_irq_pri(basepri); - return 0; + return ret; } int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { @@ -87,10 +91,10 @@ int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_nu int spi_bdev_readblocks_raw(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes) { uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access - mp_spiflash_read(&bdev->spiflash, block_num * MP_SPIFLASH_ERASE_BLOCK_SIZE + block_offset, num_bytes, dest); + int ret = mp_spiflash_read(&bdev->spiflash, block_num * MP_SPIFLASH_ERASE_BLOCK_SIZE + block_offset, num_bytes, dest); restore_irq_pri(basepri); - return 0; + return ret; } int spi_bdev_writeblocks_raw(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes) {