Skip to content

Commit a4456ee

Browse files
author
Andrew Leech
committed
stm32/qspi: Use the flash size configured in spiflash init.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
1 parent 1d48ff5 commit a4456ee

File tree

7 files changed

+139
-56
lines changed

7 files changed

+139
-56
lines changed

drivers/bus/qspi.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ enum {
3737
MP_QSPI_IOCTL_DEINIT,
3838
MP_QSPI_IOCTL_BUS_ACQUIRE,
3939
MP_QSPI_IOCTL_BUS_RELEASE,
40+
MP_QSPI_IOCTL_FLASH_SIZE,
4041
};
4142

4243
enum qspi_tranfer_mode {
@@ -45,7 +46,7 @@ enum qspi_tranfer_mode {
4546
};
4647

4748
typedef struct _mp_qspi_proto_t {
48-
int (*ioctl)(void *self, uint32_t cmd);
49+
int (*ioctl)(void *self, uint32_t cmd, uint32_t arg);
4950
int (*write_cmd_data)(void *self, uint8_t cmd, size_t len, uint32_t data);
5051
int (*write_cmd_addr_data)(void *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src);
5152
int (*read_cmd)(void *self, uint8_t cmd, size_t len, uint32_t *dest);

drivers/bus/softqspi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ STATIC void nibble_write(mp_soft_qspi_obj_t *self, uint8_t v) {
5656
mp_hal_pin_write(self->io3, (v >> 3) & 1);
5757
}
5858

59-
STATIC int mp_soft_qspi_ioctl(void *self_in, uint32_t cmd) {
59+
STATIC int mp_soft_qspi_ioctl(void *self_in, uint32_t cmd, uint32_t arg) {
6060
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
6161

6262
switch (cmd) {

drivers/memory/spiflash.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@ static external_flash_device generic_config = GENERIC;
8080
STATIC void mp_spiflash_acquire_bus(mp_spiflash_t *self) {
8181
const mp_spiflash_config_t *c = self->config;
8282
if (c->bus_kind == MP_SPIFLASH_BUS_QSPI) {
83-
c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_ACQUIRE);
83+
c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_ACQUIRE, 0);
8484
}
8585
}
8686

8787
STATIC void mp_spiflash_release_bus(mp_spiflash_t *self) {
8888
const mp_spiflash_config_t *c = self->config;
8989
if (c->bus_kind == MP_SPIFLASH_BUS_QSPI) {
90-
c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_RELEASE);
90+
c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_RELEASE, 0);
9191
}
9292
}
9393

@@ -198,7 +198,7 @@ int mp_spiflash_init(mp_spiflash_t *self) {
198198
mp_hal_pin_output(self->config->bus.u_spi.cs);
199199
self->config->bus.u_spi.proto->ioctl(self->config->bus.u_spi.data, MP_SPI_IOCTL_INIT);
200200
} else {
201-
self->config->bus.u_qspi.proto->ioctl(self->config->bus.u_qspi.data, MP_QSPI_IOCTL_INIT);
201+
self->config->bus.u_qspi.proto->ioctl(self->config->bus.u_qspi.data, MP_QSPI_IOCTL_INIT, 0);
202202
}
203203

204204
mp_spiflash_acquire_bus(self);
@@ -327,6 +327,10 @@ int mp_spiflash_init(mp_spiflash_t *self) {
327327
}
328328
}
329329

330+
if (self->config->bus_kind == MP_SPIFLASH_BUS_QSPI) {
331+
self->config->bus.u_qspi.proto->ioctl(self->config->bus.u_qspi.data, MP_QSPI_IOCTL_FLASH_SIZE, self->device->total_size);
332+
}
333+
330334
mp_spiflash_release_bus(self);
331335
return ret;
332336
}

ports/stm32/boards/STM32F769DISC/board_init.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "storage.h"
22
#include "qspi.h"
3+
#include "mpconfigboard.h"
34

45
// This configuration is needed for mboot to be able to write to the external QSPI flash
56

@@ -21,6 +22,6 @@ spi_bdev_t spi_bdev;
2122
// This init function is needed to memory map the QSPI flash early in the boot process
2223

2324
void board_early_init(void) {
24-
qspi_init();
25+
qspi_init(MICROPY_HW_BDEV_SPIFLASH_SIZE_BYTES);
2526
qspi_memory_map();
2627
}

ports/stm32/octospi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ void octospi_init(void) {
9292
OCTOSPI1->CR |= OCTOSPI_CR_EN;
9393
}
9494

95-
STATIC int octospi_ioctl(void *self_in, uint32_t cmd) {
95+
STATIC int octospi_ioctl(void *self_in, uint32_t cmd, uint32_t arg) {
9696
(void)self_in;
9797
switch (cmd) {
9898
case MP_QSPI_IOCTL_INIT:

ports/stm32/qspi.c

Lines changed: 125 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
#include "qspi.h"
3333
#include "pin_static_af.h"
3434

35-
#if defined(MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2)
35+
#if MICROPY_HW_ENABLE_QSPI || defined(MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2)
3636

3737
#define QSPI_MAP_ADDR (0x90000000)
3838

@@ -52,17 +52,18 @@
5252
#define MICROPY_HW_QSPI_CS_HIGH_CYCLES 2 // nCS stays high for 2 cycles
5353
#endif
5454

55-
#ifndef MICROPY_HW_QSPI_MPU_REGION_SIZE
56-
#define MICROPY_HW_QSPI_MPU_REGION_SIZE ((1 << (MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 - 3)) >> 20)
55+
#ifndef MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2
5756
#endif
5857

59-
#if (MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 - 3 - 1) >= 24
60-
#define QSPI_CMD 0xec
61-
#define QSPI_ADSIZE 3
62-
#else
63-
#define QSPI_CMD 0xeb
64-
#define QSPI_ADSIZE 2
65-
#endif
58+
// Fast Read command in 32bit and 24bit addressing.
59+
#define QSPI_FAST_READ_A4_CMD 0xec
60+
#define QSPI_FAST_READ_A3_CMD 0xeb
61+
62+
// this formula computes the log2 of "m"
63+
#define BITS_TO_LOG2(m) ((m) - 1) / (((m) - 1) % 255 + 1) / 255 % 255 * 8 + 7 - 86 / (((m) - 1) % 255 + 12)
64+
65+
#define MBytes (1024 * 1024)
66+
static size_t qspi_memory_size_bytes = 0;
6667

6768
static inline void qspi_mpu_disable_all(void) {
6869
// Configure MPU to disable access to entire QSPI region, to prevent CPU
@@ -72,7 +73,48 @@ static inline void qspi_mpu_disable_all(void) {
7273
mpu_config_end(irq_state);
7374
}
7475

75-
static inline void qspi_mpu_enable_mapped(void) {
76+
#if 1
77+
78+
static inline void qspi_mpu_enable_mapped() {
79+
// Configure MPU to allow access to only the valid part of external SPI flash.
80+
// The memory accesses to the mapped QSPI are faster if the MPU is not used
81+
// unprivileged or the background region is disabled, the MPU issues a fault.
82+
uint32_t irq_state = mpu_config_start();
83+
84+
if (qspi_memory_size_bytes > (128 * MBytes)) {
85+
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0xFF, MPU_REGION_SIZE_256MB));
86+
} else if (qspi_memory_size_bytes > (64 * MBytes)) {
87+
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x0F, MPU_REGION_SIZE_256MB));
88+
} else if (qspi_memory_size_bytes > (32 * MBytes)) {
89+
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x03, MPU_REGION_SIZE_256MB));
90+
} else if (qspi_memory_size_bytes > (16 * MBytes)) {
91+
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
92+
} else if (qspi_memory_size_bytes > (8 * MBytes)) {
93+
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
94+
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x0F, MPU_REGION_SIZE_32MB));
95+
} else if (qspi_memory_size_bytes > (4 * MBytes)) {
96+
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
97+
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x03, MPU_REGION_SIZE_32MB));
98+
} else if (qspi_memory_size_bytes > (2 * MBytes)) {
99+
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
100+
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_32MB));
101+
} else if (qspi_memory_size_bytes > (1 * MBytes)) {
102+
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
103+
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x0F, MPU_REGION_SIZE_32MB));
104+
mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_16MB));
105+
} else {
106+
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
107+
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_32MB));
108+
mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x03, MPU_REGION_SIZE_4MB));
109+
}
110+
mpu_config_end(irq_state);
111+
}
112+
113+
#else
114+
115+
// This variant of the function is harder to read, but 76 bytes smaller.
116+
117+
static inline void qspi_mpu_enable_mapped() {
76118
// Configure MPU to allow access to only the valid part of external SPI flash.
77119
// The memory accesses to the mapped QSPI are faster if the MPU is not used
78120
// for the memory-mapped region, so 3 MPU regions are used to disable access
@@ -83,36 +125,61 @@ static inline void qspi_mpu_enable_mapped(void) {
83125
// other enabled region overlaps the disabled subregion, and the access is
84126
// unprivileged or the background region is disabled, the MPU issues a fault.
85127
uint32_t irq_state = mpu_config_start();
86-
#if MICROPY_HW_QSPI_MPU_REGION_SIZE > 128
87-
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0xFF, MPU_REGION_SIZE_256MB));
88-
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 64
89-
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x0F, MPU_REGION_SIZE_256MB));
90-
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 32
91-
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x03, MPU_REGION_SIZE_256MB));
92-
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 16
93-
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
94-
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 8
95-
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
96-
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x0F, MPU_REGION_SIZE_32MB));
97-
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 4
98-
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
99-
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x03, MPU_REGION_SIZE_32MB));
100-
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 2
101-
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
102-
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_32MB));
103-
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 1
104-
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
105-
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x0F, MPU_REGION_SIZE_32MB));
106-
mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_16MB));
107-
#else
108-
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
109-
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_32MB));
110-
mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x03, MPU_REGION_SIZE_4MB));
111-
#endif
128+
129+
static const uint8_t region_definitions[][7] = {
130+
// Each row per MB region total size, specifying region srd and size for MPU_REGION_QSPI1, 2 and 3.
131+
{128, 0xFF, MPU_REGION_SIZE_256MB, 0, 0, 0, 0},
132+
{ 64, 0x0F, MPU_REGION_SIZE_256MB, 0, 0, 0, 0},
133+
{ 32, 0x03, MPU_REGION_SIZE_256MB, 0, 0, 0, 0},
134+
{ 16, 0x01, MPU_REGION_SIZE_256MB, 0, 0, 0, 0},
135+
{ 8, 0x01, MPU_REGION_SIZE_256MB,
136+
0x0F, MPU_REGION_SIZE_32MB, 0, 0},
137+
{ 4, 0x01, MPU_REGION_SIZE_256MB,
138+
0x03, MPU_REGION_SIZE_32MB, 0, 0},
139+
{ 2, 0x01, MPU_REGION_SIZE_256MB,
140+
0x01, MPU_REGION_SIZE_32MB, 0, 0},
141+
{ 1, 0x01, MPU_REGION_SIZE_256MB,
142+
0x0F, MPU_REGION_SIZE_32MB,
143+
0x01, MPU_REGION_SIZE_16MB},
144+
{ 0, 0x01, MPU_REGION_SIZE_256MB,
145+
0x01, MPU_REGION_SIZE_32MB,
146+
0x03, MPU_REGION_SIZE_4MB},
147+
};
148+
size_t qspi_memory_size_mbytes = qspi_memory_size_bytes / 1024 / 1024;
149+
150+
for (uint8_t i = 0; i < 9; ++i) {
151+
if (qspi_memory_size_mbytes > region_definitions[i][0]) {
152+
uint32_t attr_size_1 = MPU_CONFIG_DISABLE(region_definitions[i][1], region_definitions[i][2]);
153+
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, attr_size_1);
154+
if (region_definitions[i][3] > 0) {
155+
uint32_t attr_size_2 = MPU_CONFIG_DISABLE(region_definitions[i][3], region_definitions[i][4]);
156+
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, attr_size_2);
157+
}
158+
if (region_definitions[i][5] > 0) {
159+
uint32_t attr_size_3 = MPU_CONFIG_DISABLE(region_definitions[i][5], region_definitions[i][6]);
160+
mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, attr_size_3);
161+
}
162+
break;
163+
}
164+
}
112165
mpu_config_end(irq_state);
113166
}
114167

115-
void qspi_init(void) {
168+
#endif
169+
170+
void qspi_set_memory_size(size_t memory_size_bytes) {
171+
qspi_memory_size_bytes = memory_size_bytes;
172+
size_t QSPIFLASH_SIZE_BITS_LOG2 = BITS_TO_LOG2(qspi_memory_size_bytes * 8);
173+
QUADSPI->DCR =
174+
(QSPIFLASH_SIZE_BITS_LOG2 - 3 - 1) << QUADSPI_DCR_FSIZE_Pos
175+
| (MICROPY_HW_QSPI_CS_HIGH_CYCLES - 1) << QUADSPI_DCR_CSHT_Pos
176+
| 0 << QUADSPI_DCR_CKMODE_Pos // CLK idles at low state
177+
;
178+
}
179+
180+
void qspi_init(size_t memory_size_bytes) {
181+
qspi_memory_size_bytes = memory_size_bytes;
182+
116183
qspi_mpu_disable_all();
117184

118185
// Configure pins
@@ -143,15 +210,20 @@ void qspi_init(void) {
143210
| 1 << QUADSPI_CR_EN_Pos // enable the peripheral
144211
;
145212

146-
QUADSPI->DCR =
147-
(MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 - 3 - 1) << QUADSPI_DCR_FSIZE_Pos
148-
| (MICROPY_HW_QSPI_CS_HIGH_CYCLES - 1) << QUADSPI_DCR_CSHT_Pos
149-
| 0 << QUADSPI_DCR_CKMODE_Pos // CLK idles at low state
150-
;
213+
if (qspi_memory_size_bytes) {
214+
qspi_set_memory_size(qspi_memory_size_bytes);
215+
}
151216
}
152217

153-
void qspi_memory_map(void) {
218+
void qspi_memory_map() {
154219
// Enable memory-mapped mode
220+
uint8_t cmd = QSPI_FAST_READ_A3_CMD;
221+
uint8_t adsize = 2;
222+
if (qspi_memory_size_bytes > (16 * MBytes)) {
223+
// Flash chips over 16MB require 32bit addressing.
224+
cmd = QSPI_FAST_READ_A4_CMD;
225+
adsize = 3;
226+
}
155227

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

@@ -163,20 +235,20 @@ void qspi_memory_map(void) {
163235
| 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles
164236
| 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte
165237
| 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines
166-
| QSPI_ADSIZE << QUADSPI_CCR_ADSIZE_Pos
238+
| adsize << QUADSPI_CCR_ADSIZE_Pos
167239
| 3 << QUADSPI_CCR_ADMODE_Pos // address on 4 lines
168240
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
169-
| QSPI_CMD << QUADSPI_CCR_INSTRUCTION_Pos
241+
| cmd << QUADSPI_CCR_INSTRUCTION_Pos
170242
;
171243

172244
qspi_mpu_enable_mapped();
173245
}
174246

175-
STATIC int qspi_ioctl(void *self_in, uint32_t cmd) {
247+
STATIC int qspi_ioctl(void *self_in, uint32_t cmd, uint32_t arg) {
176248
(void)self_in;
177249
switch (cmd) {
178250
case MP_QSPI_IOCTL_INIT:
179-
qspi_init();
251+
qspi_init(0);
180252
break;
181253
case MP_QSPI_IOCTL_BUS_ACQUIRE:
182254
// Disable memory-mapped region during bus access
@@ -192,6 +264,11 @@ STATIC int qspi_ioctl(void *self_in, uint32_t cmd) {
192264
// Switch to memory-map mode when bus is idle
193265
qspi_memory_map();
194266
break;
267+
case MP_QSPI_IOCTL_FLASH_SIZE:
268+
if (arg > 0) {
269+
qspi_set_memory_size(arg);
270+
}
271+
return qspi_memory_size_bytes;
195272
}
196273
return 0; // success
197274
}

ports/stm32/qspi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
extern const mp_qspi_proto_t qspi_proto;
3232

33-
void qspi_init(void);
33+
void qspi_init(size_t memory_size_bytes);
3434
void qspi_memory_map(void);
3535

3636
#endif // MICROPY_INCLUDED_STM32_QSPI_H

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