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) {