Skip to content

Commit 4bd0643

Browse files
andrewleechpi-anl
authored andcommitted
spiflash: Support spi/qspi flash chips over 16MB.
Over 16MB, 32-bit addressing is required rather than the standard 24-bit.
1 parent 3032ae1 commit 4bd0643

File tree

4 files changed

+64
-27
lines changed

4 files changed

+64
-27
lines changed

drivers/bus/qspi.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,22 @@ typedef struct _mp_soft_qspi_obj_t {
5252
mp_hal_pin_obj_t io3;
5353
} mp_soft_qspi_obj_t;
5454

55+
#define MP_SPI_ADDR_32B(addr) (addr & 0xF000)
56+
57+
STATIC inline uint8_t mp_spi_set_addr_buff(uint8_t *buf, uint32_t addr) {
58+
if(MP_SPI_ADDR_32B(addr)) {
59+
buf[0] = addr >> 24;
60+
buf[1] = addr >> 16;
61+
buf[2] = addr >> 8;
62+
buf[3] = addr;
63+
return 4;
64+
} else {
65+
buf[0] = addr >> 16;
66+
buf[1] = addr >> 8;
67+
buf[2] = addr;
68+
return 3;
69+
}
70+
}
5571
extern const mp_qspi_proto_t mp_soft_qspi_proto;
5672

5773
#endif // MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H

drivers/bus/softqspi.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,10 @@ STATIC void mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len,
168168

169169
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) {
170170
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
171-
uint8_t cmd_buf[4] = {cmd, addr >> 16, addr >> 8, addr};
171+
uint8_t cmd_buf[4] = {cmd};
172+
uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr);
172173
CS_LOW(self);
173-
mp_soft_qspi_transfer(self, 4, cmd_buf, NULL);
174+
mp_soft_qspi_transfer(self, addr_len+1, cmd_buf, NULL);
174175
mp_soft_qspi_transfer(self, len, src, NULL);
175176
CS_HIGH(self);
176177
}
@@ -186,10 +187,11 @@ STATIC uint32_t mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) {
186187

187188
STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
188189
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
189-
uint8_t cmd_buf[7] = {cmd, addr >> 16, addr >> 8, addr};
190+
uint8_t cmd_buf[7] = {cmd};
191+
uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr);
190192
CS_LOW(self);
191193
mp_soft_qspi_transfer(self, 1, cmd_buf, NULL);
192-
mp_soft_qspi_qwrite(self, 6, &cmd_buf[1]); // 3 addr bytes, 1 extra byte (0), 2 dummy bytes (4 dummy cycles)
194+
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)
193195
mp_soft_qspi_qread(self, len, dest);
194196
CS_HIGH(self);
195197
}

drivers/memory/spiflash.c

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
#define CMD_RD_DEVID (0x9f)
4545
#define CMD_CHIP_ERASE (0xc7)
4646
#define CMD_C4READ (0xeb)
47+
// 32 bit addressing commands
48+
#define CMD_WRITE_32 (0x12)
49+
#define CMD_READ_32 (0x13)
50+
#define CMD_SEC_ERASE_32 (0x21)
51+
#define CMD_C4READ_32 (0xec)
4752

4853
#define WAIT_SR_TIMEOUT (1000000)
4954

@@ -76,18 +81,26 @@ STATIC void mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t
7681
}
7782
}
7883

79-
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) {
84+
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) {
8085
const mp_spiflash_config_t *c = self->config;
8186
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
82-
uint8_t buf[4] = {cmd, addr >> 16, addr >> 8, addr};
87+
uint8_t buf[5] = {cmd, 0};
88+
uint8_t buff_len = 1 + mp_spi_set_addr_buff(&buf[1], addr);
8389
mp_hal_pin_write(c->bus.u_spi.cs, 0);
84-
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 4, buf, NULL);
85-
if (len) {
90+
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, buff_len, buf, NULL);
91+
if (len && (src != NULL)) {
8692
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, src, NULL);
93+
} else if (len && (dest != NULL)) {
94+
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, dest, dest);
8795
}
96+
8897
mp_hal_pin_write(c->bus.u_spi.cs, 1);
8998
} else {
90-
c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src);
99+
if (dest != NULL) {
100+
c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, cmd, addr, len, dest);
101+
} else {
102+
c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src);
103+
}
91104
}
92105
}
93106

@@ -108,24 +121,16 @@ STATIC uint32_t mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t le
108121
STATIC void mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
109122
const mp_spiflash_config_t *c = self->config;
110123
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
111-
uint8_t buf[4] = {CMD_READ, addr >> 16, addr >> 8, addr};
112-
mp_hal_pin_write(c->bus.u_spi.cs, 0);
113-
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 4, buf, NULL);
114-
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, dest, dest);
115-
mp_hal_pin_write(c->bus.u_spi.cs, 1);
124+
mp_spiflash_transfer_cmd_addr_data(self, MP_SPI_ADDR_32B(addr)?CMD_READ_32:CMD_READ, addr, len, NULL, dest);
116125
} else {
117-
c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, CMD_C4READ, addr, len, dest);
126+
mp_spiflash_transfer_cmd_addr_data(self, MP_SPI_ADDR_32B(addr)?CMD_C4READ_32:CMD_C4READ, addr, len, NULL, dest);
118127
}
119128
}
120129

121130
STATIC void mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) {
122131
mp_spiflash_write_cmd_data(self, cmd, 0, 0);
123132
}
124133

125-
STATIC void mp_spiflash_write_cmd_addr(mp_spiflash_t *self, uint8_t cmd, uint32_t addr) {
126-
mp_spiflash_write_cmd_addr_data(self, cmd, addr, 0, NULL);
127-
}
128-
129134
STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) {
130135
uint8_t sr;
131136
do {
@@ -210,7 +215,7 @@ STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr)
210215
}
211216

212217
// erase the sector
213-
mp_spiflash_write_cmd_addr(self, CMD_SEC_ERASE, addr);
218+
mp_spiflash_transfer_cmd_addr_data(self, MP_SPI_ADDR_32B(addr)?CMD_SEC_ERASE_32:CMD_SEC_ERASE, addr, 0, NULL, NULL);
214219

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

229234
// write the page
230-
mp_spiflash_write_cmd_addr_data(self, CMD_WRITE, addr, len, src);
235+
mp_spiflash_transfer_cmd_addr_data(self, MP_SPI_ADDR_32B(addr)?CMD_WRITE_32:CMD_WRITE, addr, len, src, NULL);
231236

232237
// wait WIP=0
233238
return mp_spiflash_wait_wip0(self);

ports/stm32/qspi.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@
5252
#define MICROPY_HW_QSPI_CS_HIGH_CYCLES 2 // nCS stays high for 2 cycles
5353
#endif
5454

55+
#if (MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 -3 -1) >= 24
56+
#define QSPI_CMD 0xec
57+
#define QSPI_ADSIZE 3
58+
#else
59+
#define QSPI_CMD 0xeb
60+
#define QSPI_ADSIZE 2
61+
#endif
62+
5563
static inline void qspi_mpu_disable_all(void) {
5664
// Configure MPU to disable access to entire QSPI region, to prevent CPU
5765
// speculative execution from accessing this region and modifying QSPI registers.
@@ -112,10 +120,11 @@ void qspi_init(void) {
112120
;
113121
}
114122

115-
void qspi_memory_map(void) {
123+
void qspi_memory_map() {
116124
// Enable memory-mapped mode
117125

118126
QUADSPI->ABR = 0; // disable continuous read mode
127+
119128
QUADSPI->CCR =
120129
0 << QUADSPI_CCR_DDRM_Pos // DDR mode disabled
121130
| 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction
@@ -124,10 +133,10 @@ void qspi_memory_map(void) {
124133
| 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles
125134
| 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte
126135
| 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines
127-
| 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size
136+
| QSPI_ADSIZE << QUADSPI_CCR_ADSIZE_Pos
128137
| 3 << QUADSPI_CCR_ADMODE_Pos // address on 4 lines
129138
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
130-
| 0xeb << QUADSPI_CCR_INSTRUCTION_Pos // quad read opcode
139+
| QSPI_CMD << QUADSPI_CCR_INSTRUCTION_Pos
131140
;
132141

133142
qspi_mpu_enable_mapped();
@@ -203,6 +212,8 @@ STATIC void qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t
203212
STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
204213
(void)self_in;
205214

215+
uint8_t adsize = MP_SPI_ADDR_32B(addr)? 3:2;
216+
206217
QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag
207218

208219
if (len == 0) {
@@ -213,7 +224,7 @@ STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr,
213224
| 0 << QUADSPI_CCR_DMODE_Pos // no data
214225
| 0 << QUADSPI_CCR_DCYC_Pos // 0 dummy cycles
215226
| 0 << QUADSPI_CCR_ABMODE_Pos // no alternate byte
216-
| 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size
227+
| adsize << QUADSPI_CCR_ADSIZE_Pos // 32/24-bit address size
217228
| 1 << QUADSPI_CCR_ADMODE_Pos // address on 1 line
218229
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
219230
| cmd << QUADSPI_CCR_INSTRUCTION_Pos // write opcode
@@ -230,7 +241,7 @@ STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr,
230241
| 1 << QUADSPI_CCR_DMODE_Pos // data on 1 line
231242
| 0 << QUADSPI_CCR_DCYC_Pos // 0 dummy cycles
232243
| 0 << QUADSPI_CCR_ABMODE_Pos // no alternate byte
233-
| 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size
244+
| adsize << QUADSPI_CCR_ADSIZE_Pos // 32/24-bit address size
234245
| 1 << QUADSPI_CCR_ADMODE_Pos // address on 1 line
235246
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
236247
| cmd << QUADSPI_CCR_INSTRUCTION_Pos // write opcode
@@ -285,6 +296,9 @@ STATIC uint32_t qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) {
285296

286297
STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
287298
(void)self_in;
299+
300+
uint8_t adsize = MP_SPI_ADDR_32B(addr)? 3:2;
301+
288302
QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag
289303

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

0 commit comments

Comments
 (0)
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