diff options
author | Damien George <damien@micropython.org> | 2025-04-02 12:47:40 +1100 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2025-04-09 22:36:55 +1000 |
commit | 2c0240e068b66b5f7b063125a7977cbca03d9483 (patch) | |
tree | a4faf908cdeb243cfd5e58a9c4c96a901b1dbf10 | |
parent | b078569cffb4b32585806b42ef7a0501bc4d0bca (diff) | |
download | micropython-2c0240e068b66b5f7b063125a7977cbca03d9483.tar.gz micropython-2c0240e068b66b5f7b063125a7977cbca03d9483.zip |
drivers/bus/qspi: Make num_dummy configurable for quad reads.
Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r-- | drivers/bus/qspi.h | 2 | ||||
-rw-r--r-- | drivers/bus/softqspi.c | 6 | ||||
-rw-r--r-- | drivers/memory/spiflash.c | 14 | ||||
-rw-r--r-- | ports/stm32/boards/STM32F769DISC/board_init.c | 4 | ||||
-rw-r--r-- | ports/stm32/octospi.c | 4 | ||||
-rw-r--r-- | ports/stm32/qspi.c | 14 | ||||
-rw-r--r-- | ports/stm32/qspi.h | 2 |
7 files changed, 31 insertions, 15 deletions
diff --git a/drivers/bus/qspi.h b/drivers/bus/qspi.h index 7ba2e75094..32b2890e3f 100644 --- a/drivers/bus/qspi.h +++ b/drivers/bus/qspi.h @@ -45,7 +45,7 @@ typedef struct _mp_qspi_proto_t { 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); int (*read_cmd)(void *self, uint8_t cmd, size_t len, uint32_t *dest); - int (*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, uint8_t num_dummy, 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 5cfc4db5e3..06dcd03b02 100644 --- a/drivers/bus/softqspi.c +++ b/drivers/bus/softqspi.c @@ -189,13 +189,13 @@ static int mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len, uint32_ return 0; } -static int 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, uint8_t num_dummy, 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 cmd_buf[16] = {cmd}; uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr); CS_LOW(self); mp_soft_qspi_transfer(self, 1, cmd_buf, NULL); - 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_qwrite(self, addr_len + 1 + num_dummy, &cmd_buf[1]); // 3/4 addr bytes, 1 extra byte (0), N dummy bytes (2*N dummy cycles) mp_soft_qspi_qread(self, len, dest); CS_HIGH(self); return 0; diff --git a/drivers/memory/spiflash.c b/drivers/memory/spiflash.c index b4133fe2f0..1ae0bbbc67 100644 --- a/drivers/memory/spiflash.c +++ b/drivers/memory/spiflash.c @@ -35,6 +35,14 @@ #error "CHECK_DEVID no longer supported, use MICROPY_HW_SPIFLASH_DETECT_DEVICE instead" #endif +// The default number of dummy bytes for quad-read is 2. This can be changed by enabling +// MICROPY_HW_SPIFLASH_CHIP_PARAMS and configuring the value in mp_spiflash_chip_params_t. +#if MICROPY_HW_SPIFLASH_CHIP_PARAMS +#define MICROPY_HW_SPIFLASH_QREAD_NUM_DUMMY(spiflash) (spiflash->chip_params->qread_num_dummy) +#else +#define MICROPY_HW_SPIFLASH_QREAD_NUM_DUMMY(spiflash) (2) +#endif + #define QSPI_QE_MASK (0x02) #define USE_WR_DELAY (1) @@ -115,7 +123,8 @@ static int 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) { - ret = c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, cmd, addr, len, dest); + uint8_t num_dummy = MICROPY_HW_SPIFLASH_QREAD_NUM_DUMMY(self); + ret = c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, cmd, addr, num_dummy, len, dest); } else { ret = c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src); } @@ -186,7 +195,8 @@ void mp_spiflash_init(mp_spiflash_t *self) { mp_hal_pin_output(self->config->bus.u_spi.cs); self->config->bus.u_spi.proto->ioctl(self->config->bus.u_spi.data, MP_SPI_IOCTL_INIT); } else { - self->config->bus.u_qspi.proto->ioctl(self->config->bus.u_qspi.data, MP_QSPI_IOCTL_INIT, 0); + uint8_t num_dummy = MICROPY_HW_SPIFLASH_QREAD_NUM_DUMMY(self); + self->config->bus.u_qspi.proto->ioctl(self->config->bus.u_qspi.data, MP_QSPI_IOCTL_INIT, num_dummy); } mp_spiflash_acquire_bus(self); diff --git a/ports/stm32/boards/STM32F769DISC/board_init.c b/ports/stm32/boards/STM32F769DISC/board_init.c index 578dc9adb6..001b18bc06 100644 --- a/ports/stm32/boards/STM32F769DISC/board_init.c +++ b/ports/stm32/boards/STM32F769DISC/board_init.c @@ -3,6 +3,8 @@ // This configuration is needed for mboot to be able to write to the external QSPI flash +#define QSPI_QREAD_NUM_DUMMY (2) + #if MICROPY_HW_SPIFLASH_ENABLE_CACHE static mp_spiflash_cache_t spi_bdev_cache; #endif @@ -21,6 +23,6 @@ spi_bdev_t spi_bdev; // This init function is needed to memory map the QSPI flash early in the boot process void board_early_init(void) { - qspi_init(); + qspi_init(QSPI_QREAD_NUM_DUMMY); qspi_memory_map(); } diff --git a/ports/stm32/octospi.c b/ports/stm32/octospi.c index 345c4a2374..861941325c 100644 --- a/ports/stm32/octospi.c +++ b/ports/stm32/octospi.c @@ -283,7 +283,7 @@ static int octospi_read_cmd(void *self_in, uint8_t cmd, size_t len, uint32_t *de return 0; } -static int octospi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) { +static int octospi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, uint8_t num_dummy, size_t len, uint8_t *dest) { (void)self_in; #if defined(MICROPY_HW_OSPIFLASH_IO1) && !defined(MICROPY_HW_OSPIFLASH_IO2) && !defined(MICROPY_HW_OSPIFLASH_IO4) @@ -293,7 +293,7 @@ static int octospi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t add uint32_t adsize = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? 3 : 2; uint32_t dmode = 2; // data on 2-lines uint32_t admode = 2; // address on 2-lines - uint32_t dcyc = 4; // 4 dummy cycles + uint32_t dcyc = 2 * num_dummy; // 2N dummy cycles if (cmd == 0xeb || cmd == 0xec) { // Convert to 2-line command. diff --git a/ports/stm32/qspi.c b/ports/stm32/qspi.c index 7334ece4f2..1360d9b490 100644 --- a/ports/stm32/qspi.c +++ b/ports/stm32/qspi.c @@ -62,6 +62,8 @@ #define QSPI_ADSIZE 2 #endif +static uint8_t qspi_num_dummy; + static inline void qspi_mpu_disable_all(void) { // Configure MPU to disable access to entire QSPI region, to prevent CPU // speculative execution from accessing this region and modifying QSPI registers. @@ -110,7 +112,9 @@ static inline void qspi_mpu_enable_mapped(void) { mpu_config_end(irq_state); } -void qspi_init(void) { +void qspi_init(uint8_t num_dummy) { + qspi_num_dummy = num_dummy; + qspi_mpu_disable_all(); // Configure pins @@ -158,7 +162,7 @@ void qspi_memory_map(void) { | 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction | 3 << QUADSPI_CCR_FMODE_Pos // memory-mapped mode | 3 << QUADSPI_CCR_DMODE_Pos // data on 4 lines - | 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles + | (2 * qspi_num_dummy) << QUADSPI_CCR_DCYC_Pos // 2N dummy cycles | 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte | 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines | QSPI_ADSIZE << QUADSPI_CCR_ADSIZE_Pos @@ -193,7 +197,7 @@ static int qspi_ioctl(void *self_in, uint32_t cmd, uintptr_t arg) { (void)self_in; switch (cmd) { case MP_QSPI_IOCTL_INIT: - qspi_init(); + qspi_init(arg); break; case MP_QSPI_IOCTL_BUS_ACQUIRE: // Disable memory-mapped region during bus access @@ -369,7 +373,7 @@ static int qspi_read_cmd(void *self_in, uint8_t cmd, size_t len, uint32_t *dest) return 0; } -static int 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, uint8_t num_dummy, size_t len, uint8_t *dest) { (void)self_in; uint8_t adsize = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? 3 : 2; @@ -383,7 +387,7 @@ static int qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, | 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction | 1 << QUADSPI_CCR_FMODE_Pos // indirect read mode | 3 << QUADSPI_CCR_DMODE_Pos // data on 4 lines - | 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles + | (2 * num_dummy) << QUADSPI_CCR_DCYC_Pos // 2N dummy cycles | 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte | 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines | adsize << QUADSPI_CCR_ADSIZE_Pos // 32 or 24-bit address size diff --git a/ports/stm32/qspi.h b/ports/stm32/qspi.h index a2d6b9f328..c8a3181653 100644 --- a/ports/stm32/qspi.h +++ b/ports/stm32/qspi.h @@ -33,7 +33,7 @@ extern const mp_qspi_proto_t qspi_proto; -void qspi_init(void); +void qspi_init(uint8_t num_dummy); void qspi_memory_map(void); void qspi_memory_map_exit(void); void qspi_memory_map_restart(void); |