Skip to content

Support spi/qspi flash chips over 16MB. #5166

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions drivers/bus/qspi.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@ typedef struct _mp_soft_qspi_obj_t {
mp_hal_pin_obj_t io3;
} mp_soft_qspi_obj_t;

#define MP_SPI_ADDR_32B(addr) (addr & 0xff000000)

STATIC inline uint8_t mp_spi_set_addr_buff(uint8_t *buf, uint32_t addr) {
if(MP_SPI_ADDR_32B(addr)) {
buf[0] = addr >> 24;
buf[1] = addr >> 16;
buf[2] = addr >> 8;
buf[3] = addr;
return 4;
} else {
buf[0] = addr >> 16;
buf[1] = addr >> 8;
buf[2] = addr;
return 3;
}
}
extern const mp_qspi_proto_t mp_soft_qspi_proto;

#endif // MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H
10 changes: 6 additions & 4 deletions drivers/bus/softqspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,10 @@ STATIC void mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len,

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) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
uint8_t cmd_buf[4] = {cmd, addr >> 16, addr >> 8, addr};
uint8_t cmd_buf[5] = {cmd};
uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr);
CS_LOW(self);
mp_soft_qspi_transfer(self, 4, cmd_buf, NULL);
mp_soft_qspi_transfer(self, addr_len+1, cmd_buf, NULL);
mp_soft_qspi_transfer(self, len, src, NULL);
CS_HIGH(self);
}
Expand All @@ -186,10 +187,11 @@ STATIC uint32_t mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) {

STATIC void 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, addr >> 16, addr >> 8, addr};
uint8_t cmd_buf[7] = {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, 6, &cmd_buf[1]); // 3 addr bytes, 1 extra byte (0), 2 dummy bytes (4 dummy cycles)
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);
}
Expand Down
39 changes: 22 additions & 17 deletions drivers/memory/spiflash.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
#define CMD_RD_DEVID (0x9f)
#define CMD_CHIP_ERASE (0xc7)
#define CMD_C4READ (0xeb)
// 32 bit addressing commands
#define CMD_WRITE_32 (0x12)
#define CMD_READ_32 (0x13)
#define CMD_SEC_ERASE_32 (0x21)
#define CMD_C4READ_32 (0xec)

#define WAIT_SR_TIMEOUT (1000000)

Expand Down Expand Up @@ -76,18 +81,26 @@ STATIC void mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t
}
}

STATIC void mp_spiflash_write_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
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) {
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
uint8_t buf[4] = {cmd, addr >> 16, addr >> 8, addr};
uint8_t buf[5] = {cmd, 0};
uint8_t buff_len = 1 + mp_spi_set_addr_buff(&buf[1], addr);
mp_hal_pin_write(c->bus.u_spi.cs, 0);
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 4, buf, NULL);
if (len) {
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, buff_len, buf, NULL);
if (len && (src != NULL)) {
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, src, NULL);
} else if (len && (dest != NULL)) {
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, dest, dest);
}

mp_hal_pin_write(c->bus.u_spi.cs, 1);
} else {
c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src);
if (dest != NULL) {
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);
}
}
}

Expand All @@ -108,24 +121,16 @@ 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) {
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
uint8_t buf[4] = {CMD_READ, addr >> 16, addr >> 8, addr};
mp_hal_pin_write(c->bus.u_spi.cs, 0);
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 4, buf, NULL);
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, dest, dest);
mp_hal_pin_write(c->bus.u_spi.cs, 1);
mp_spiflash_transfer_cmd_addr_data(self, MP_SPI_ADDR_32B(addr)?CMD_READ_32:CMD_READ, addr, len, NULL, dest);
} else {
c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, CMD_C4READ, addr, len, dest);
mp_spiflash_transfer_cmd_addr_data(self, MP_SPI_ADDR_32B(addr)?CMD_C4READ_32:CMD_C4READ, 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 void mp_spiflash_write_cmd_addr(mp_spiflash_t *self, uint8_t cmd, uint32_t addr) {
mp_spiflash_write_cmd_addr_data(self, cmd, addr, 0, NULL);
}

STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) {
uint8_t sr;
do {
Expand Down Expand Up @@ -210,7 +215,7 @@ STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr)
}

// erase the sector
mp_spiflash_write_cmd_addr(self, CMD_SEC_ERASE, addr);
mp_spiflash_transfer_cmd_addr_data(self, MP_SPI_ADDR_32B(addr)?CMD_SEC_ERASE_32:CMD_SEC_ERASE, addr, 0, NULL, NULL);

// wait WIP=0
return mp_spiflash_wait_wip0(self);
Expand All @@ -227,7 +232,7 @@ STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, size_t len
}

// write the page
mp_spiflash_write_cmd_addr_data(self, CMD_WRITE, addr, len, src);
mp_spiflash_transfer_cmd_addr_data(self, MP_SPI_ADDR_32B(addr)?CMD_WRITE_32:CMD_WRITE, addr, len, src, NULL);

// wait WIP=0
return mp_spiflash_wait_wip0(self);
Expand Down
26 changes: 20 additions & 6 deletions ports/stm32/qspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@
#define MICROPY_HW_QSPI_CS_HIGH_CYCLES 2 // nCS stays high for 2 cycles
#endif

#if (MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 -3 -1) >= 24
#define QSPI_CMD 0xec
#define QSPI_ADSIZE 3
#else
#define QSPI_CMD 0xeb
#define QSPI_ADSIZE 2
#endif

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.
Expand Down Expand Up @@ -112,10 +120,11 @@ void qspi_init(void) {
;
}

void qspi_memory_map(void) {
void qspi_memory_map() {
// Enable memory-mapped mode

QUADSPI->ABR = 0; // disable continuous read mode

QUADSPI->CCR =
0 << QUADSPI_CCR_DDRM_Pos // DDR mode disabled
| 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction
Expand All @@ -124,10 +133,10 @@ void qspi_memory_map(void) {
| 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles
| 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte
| 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines
| 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size
| QSPI_ADSIZE << QUADSPI_CCR_ADSIZE_Pos
| 3 << QUADSPI_CCR_ADMODE_Pos // address on 4 lines
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
| 0xeb << QUADSPI_CCR_INSTRUCTION_Pos // quad read opcode
| QSPI_CMD << QUADSPI_CCR_INSTRUCTION_Pos
;

qspi_mpu_enable_mapped();
Expand Down Expand Up @@ -203,6 +212,8 @@ STATIC void qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t
STATIC void 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 = MP_SPI_ADDR_32B(addr)? 3:2;

QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag

if (len == 0) {
Expand All @@ -213,7 +224,7 @@ STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr,
| 0 << QUADSPI_CCR_DMODE_Pos // no data
| 0 << QUADSPI_CCR_DCYC_Pos // 0 dummy cycles
| 0 << QUADSPI_CCR_ABMODE_Pos // no alternate byte
| 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size
| adsize << QUADSPI_CCR_ADSIZE_Pos // 32/24-bit address size
| 1 << QUADSPI_CCR_ADMODE_Pos // address on 1 line
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
| cmd << QUADSPI_CCR_INSTRUCTION_Pos // write opcode
Expand All @@ -230,7 +241,7 @@ STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr,
| 1 << QUADSPI_CCR_DMODE_Pos // data on 1 line
| 0 << QUADSPI_CCR_DCYC_Pos // 0 dummy cycles
| 0 << QUADSPI_CCR_ABMODE_Pos // no alternate byte
| 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size
| adsize << QUADSPI_CCR_ADSIZE_Pos // 32/24-bit address size
| 1 << QUADSPI_CCR_ADMODE_Pos // address on 1 line
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
| cmd << QUADSPI_CCR_INSTRUCTION_Pos // write opcode
Expand Down Expand Up @@ -285,6 +296,9 @@ STATIC uint32_t qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) {

STATIC void 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 = MP_SPI_ADDR_32B(addr)? 3:2;

QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag

QUADSPI->DLR = len - 1; // number of bytes to read
Expand All @@ -297,7 +311,7 @@ STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr,
| 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles
| 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte
| 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines
| 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size
| adsize << QUADSPI_CCR_ADSIZE_Pos // 32 or 24-bit address size
| 3 << QUADSPI_CCR_ADMODE_Pos // address on 4 lines
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
| cmd << QUADSPI_CCR_INSTRUCTION_Pos // quad read opcode
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy