kopia lustrzana https://github.com/micropython/micropython
stm32/qspi: Use the flash size configured in spiflash init.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>pull/12722/head
rodzic
475c040dc4
commit
36bf7e9263
|
@ -37,6 +37,7 @@ enum {
|
||||||
MP_QSPI_IOCTL_DEINIT,
|
MP_QSPI_IOCTL_DEINIT,
|
||||||
MP_QSPI_IOCTL_BUS_ACQUIRE,
|
MP_QSPI_IOCTL_BUS_ACQUIRE,
|
||||||
MP_QSPI_IOCTL_BUS_RELEASE,
|
MP_QSPI_IOCTL_BUS_RELEASE,
|
||||||
|
MP_QSPI_IOCTL_FLASH_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum qspi_tranfer_mode {
|
enum qspi_tranfer_mode {
|
||||||
|
@ -45,7 +46,7 @@ enum qspi_tranfer_mode {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _mp_qspi_proto_t {
|
typedef struct _mp_qspi_proto_t {
|
||||||
int (*ioctl)(void *self, uint32_t cmd);
|
int (*ioctl)(void *self, uint32_t cmd, uint32_t arg);
|
||||||
int (*write_cmd_data)(void *self, uint8_t cmd, size_t len, uint32_t data);
|
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 (*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)(void *self, uint8_t cmd, size_t len, uint32_t *dest);
|
||||||
|
|
|
@ -56,7 +56,7 @@ static void nibble_write(mp_soft_qspi_obj_t *self, uint8_t v) {
|
||||||
mp_hal_pin_write(self->io3, (v >> 3) & 1);
|
mp_hal_pin_write(self->io3, (v >> 3) & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mp_soft_qspi_ioctl(void *self_in, uint32_t cmd) {
|
static int mp_soft_qspi_ioctl(void *self_in, uint32_t cmd, uint32_t arg) {
|
||||||
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
|
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
|
|
@ -80,14 +80,14 @@ static external_flash_device generic_config = GENERIC;
|
||||||
static void mp_spiflash_acquire_bus(mp_spiflash_t *self) {
|
static void mp_spiflash_acquire_bus(mp_spiflash_t *self) {
|
||||||
const mp_spiflash_config_t *c = self->config;
|
const mp_spiflash_config_t *c = self->config;
|
||||||
if (c->bus_kind == MP_SPIFLASH_BUS_QSPI) {
|
if (c->bus_kind == MP_SPIFLASH_BUS_QSPI) {
|
||||||
c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_ACQUIRE);
|
c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_ACQUIRE, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mp_spiflash_release_bus(mp_spiflash_t *self) {
|
static void mp_spiflash_release_bus(mp_spiflash_t *self) {
|
||||||
const mp_spiflash_config_t *c = self->config;
|
const mp_spiflash_config_t *c = self->config;
|
||||||
if (c->bus_kind == MP_SPIFLASH_BUS_QSPI) {
|
if (c->bus_kind == MP_SPIFLASH_BUS_QSPI) {
|
||||||
c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_RELEASE);
|
c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_RELEASE, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ int mp_spiflash_init(mp_spiflash_t *self) {
|
||||||
mp_hal_pin_output(self->config->bus.u_spi.cs);
|
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);
|
self->config->bus.u_spi.proto->ioctl(self->config->bus.u_spi.data, MP_SPI_IOCTL_INIT);
|
||||||
} else {
|
} else {
|
||||||
self->config->bus.u_qspi.proto->ioctl(self->config->bus.u_qspi.data, MP_QSPI_IOCTL_INIT);
|
self->config->bus.u_qspi.proto->ioctl(self->config->bus.u_qspi.data, MP_QSPI_IOCTL_INIT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_spiflash_acquire_bus(self);
|
mp_spiflash_acquire_bus(self);
|
||||||
|
@ -327,6 +327,10 @@ int mp_spiflash_init(mp_spiflash_t *self) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->config->bus_kind == MP_SPIFLASH_BUS_QSPI) {
|
||||||
|
self->config->bus.u_qspi.proto->ioctl(self->config->bus.u_qspi.data, MP_QSPI_IOCTL_FLASH_SIZE, self->device->total_size);
|
||||||
|
}
|
||||||
|
|
||||||
mp_spiflash_release_bus(self);
|
mp_spiflash_release_bus(self);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
#include "qspi.h"
|
#include "qspi.h"
|
||||||
|
#include "mpconfigboard.h"
|
||||||
|
|
||||||
// This configuration is needed for mboot to be able to write to the external QSPI flash
|
// This configuration is needed for mboot to be able to write to the external QSPI flash
|
||||||
|
|
||||||
|
@ -21,6 +22,6 @@ spi_bdev_t spi_bdev;
|
||||||
// This init function is needed to memory map the QSPI flash early in the boot process
|
// This init function is needed to memory map the QSPI flash early in the boot process
|
||||||
|
|
||||||
void board_early_init(void) {
|
void board_early_init(void) {
|
||||||
qspi_init();
|
qspi_init(MICROPY_HW_BDEV_SPIFLASH_SIZE_BYTES);
|
||||||
qspi_memory_map();
|
qspi_memory_map();
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ void octospi_init(void) {
|
||||||
OCTOSPI1->CR |= OCTOSPI_CR_EN;
|
OCTOSPI1->CR |= OCTOSPI_CR_EN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int octospi_ioctl(void *self_in, uint32_t cmd) {
|
static int octospi_ioctl(void *self_in, uint32_t cmd, uint32_t arg) {
|
||||||
(void)self_in;
|
(void)self_in;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case MP_QSPI_IOCTL_INIT:
|
case MP_QSPI_IOCTL_INIT:
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include "qspi.h"
|
#include "qspi.h"
|
||||||
#include "pin_static_af.h"
|
#include "pin_static_af.h"
|
||||||
|
|
||||||
#if defined(MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2)
|
#if MICROPY_HW_ENABLE_QSPI || defined(MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2)
|
||||||
|
|
||||||
#define QSPI_MAP_ADDR (0x90000000)
|
#define QSPI_MAP_ADDR (0x90000000)
|
||||||
|
|
||||||
|
@ -52,17 +52,18 @@
|
||||||
#define MICROPY_HW_QSPI_CS_HIGH_CYCLES 2 // nCS stays high for 2 cycles
|
#define MICROPY_HW_QSPI_CS_HIGH_CYCLES 2 // nCS stays high for 2 cycles
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MICROPY_HW_QSPI_MPU_REGION_SIZE
|
#ifndef MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2
|
||||||
#define MICROPY_HW_QSPI_MPU_REGION_SIZE ((1 << (MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 - 3)) >> 20)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 - 3 - 1) >= 24
|
// Fast Read command in 32bit and 24bit addressing.
|
||||||
#define QSPI_CMD 0xec
|
#define QSPI_FAST_READ_A4_CMD 0xec
|
||||||
#define QSPI_ADSIZE 3
|
#define QSPI_FAST_READ_A3_CMD 0xeb
|
||||||
#else
|
|
||||||
#define QSPI_CMD 0xeb
|
// this formula computes the log2 of "m"
|
||||||
#define QSPI_ADSIZE 2
|
#define BITS_TO_LOG2(m) ((m) - 1) / (((m) - 1) % 255 + 1) / 255 % 255 * 8 + 7 - 86 / (((m) - 1) % 255 + 12)
|
||||||
#endif
|
|
||||||
|
#define MBytes (1024 * 1024)
|
||||||
|
static size_t qspi_memory_size_bytes = 0;
|
||||||
|
|
||||||
static inline void qspi_mpu_disable_all(void) {
|
static inline void qspi_mpu_disable_all(void) {
|
||||||
// Configure MPU to disable access to entire QSPI region, to prevent CPU
|
// Configure MPU to disable access to entire QSPI region, to prevent CPU
|
||||||
|
@ -72,6 +73,8 @@ static inline void qspi_mpu_disable_all(void) {
|
||||||
mpu_config_end(irq_state);
|
mpu_config_end(irq_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
|
||||||
static inline void qspi_mpu_enable_mapped(void) {
|
static inline void qspi_mpu_enable_mapped(void) {
|
||||||
// Configure MPU to allow access to only the valid part of external SPI flash.
|
// Configure MPU to allow access to only the valid part of external SPI flash.
|
||||||
// The memory accesses to the mapped QSPI are faster if the MPU is not used
|
// The memory accesses to the mapped QSPI are faster if the MPU is not used
|
||||||
|
@ -83,36 +86,106 @@ static inline void qspi_mpu_enable_mapped(void) {
|
||||||
// other enabled region overlaps the disabled subregion, and the access is
|
// other enabled region overlaps the disabled subregion, and the access is
|
||||||
// unprivileged or the background region is disabled, the MPU issues a fault.
|
// unprivileged or the background region is disabled, the MPU issues a fault.
|
||||||
uint32_t irq_state = mpu_config_start();
|
uint32_t irq_state = mpu_config_start();
|
||||||
#if MICROPY_HW_QSPI_MPU_REGION_SIZE > 128
|
|
||||||
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0xFF, MPU_REGION_SIZE_256MB));
|
if (qspi_memory_size_bytes > (128 * MBytes)) {
|
||||||
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 64
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0xFF, MPU_REGION_SIZE_256MB));
|
||||||
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x0F, MPU_REGION_SIZE_256MB));
|
} else if (qspi_memory_size_bytes > (64 * MBytes)) {
|
||||||
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 32
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x0F, MPU_REGION_SIZE_256MB));
|
||||||
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x03, MPU_REGION_SIZE_256MB));
|
} else if (qspi_memory_size_bytes > (32 * MBytes)) {
|
||||||
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 16
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x03, MPU_REGION_SIZE_256MB));
|
||||||
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
} else if (qspi_memory_size_bytes > (16 * MBytes)) {
|
||||||
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 8
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
||||||
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
} else if (qspi_memory_size_bytes > (8 * MBytes)) {
|
||||||
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x0F, MPU_REGION_SIZE_32MB));
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
||||||
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 4
|
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x0F, MPU_REGION_SIZE_32MB));
|
||||||
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
} else if (qspi_memory_size_bytes > (4 * MBytes)) {
|
||||||
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x03, MPU_REGION_SIZE_32MB));
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
||||||
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 2
|
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x03, MPU_REGION_SIZE_32MB));
|
||||||
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
} else if (qspi_memory_size_bytes > (2 * MBytes)) {
|
||||||
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_32MB));
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
||||||
#elif MICROPY_HW_QSPI_MPU_REGION_SIZE > 1
|
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_32MB));
|
||||||
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
} else if (qspi_memory_size_bytes > (1 * MBytes)) {
|
||||||
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x0F, MPU_REGION_SIZE_32MB));
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
||||||
mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_16MB));
|
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x0F, MPU_REGION_SIZE_32MB));
|
||||||
#else
|
mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_16MB));
|
||||||
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
} else {
|
||||||
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_32MB));
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_256MB));
|
||||||
mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x03, MPU_REGION_SIZE_4MB));
|
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x01, MPU_REGION_SIZE_32MB));
|
||||||
#endif
|
mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_NOACCESS(0x03, MPU_REGION_SIZE_4MB));
|
||||||
|
}
|
||||||
mpu_config_end(irq_state);
|
mpu_config_end(irq_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qspi_init(void) {
|
#else
|
||||||
|
|
||||||
|
// This variant of the function is harder to read, but 76 bytes smaller.
|
||||||
|
|
||||||
|
static inline void qspi_mpu_enable_mapped(void) {
|
||||||
|
// Configure MPU to allow access to only the valid part of external SPI flash.
|
||||||
|
// The memory accesses to the mapped QSPI are faster if the MPU is not used
|
||||||
|
// for the memory-mapped region, so 3 MPU regions are used to disable access
|
||||||
|
// to everything except the valid address space, using holes in the bottom
|
||||||
|
// of the regions and nesting them.
|
||||||
|
// Note: Disabling a subregion (by setting its corresponding SRD bit to 1)
|
||||||
|
// means another region overlapping the disabled range matches instead. If no
|
||||||
|
// other enabled region overlaps the disabled subregion, and the access is
|
||||||
|
// unprivileged or the background region is disabled, the MPU issues a fault.
|
||||||
|
uint32_t irq_state = mpu_config_start();
|
||||||
|
|
||||||
|
static const uint8_t region_definitions[][7] = {
|
||||||
|
// Each row per MB region total size, specifying region srd and size for MPU_REGION_QSPI1, 2 and 3.
|
||||||
|
{128, 0xFF, MPU_REGION_SIZE_256MB, 0, 0, 0, 0},
|
||||||
|
{ 64, 0x0F, MPU_REGION_SIZE_256MB, 0, 0, 0, 0},
|
||||||
|
{ 32, 0x03, MPU_REGION_SIZE_256MB, 0, 0, 0, 0},
|
||||||
|
{ 16, 0x01, MPU_REGION_SIZE_256MB, 0, 0, 0, 0},
|
||||||
|
{ 8, 0x01, MPU_REGION_SIZE_256MB,
|
||||||
|
0x0F, MPU_REGION_SIZE_32MB, 0, 0},
|
||||||
|
{ 4, 0x01, MPU_REGION_SIZE_256MB,
|
||||||
|
0x03, MPU_REGION_SIZE_32MB, 0, 0},
|
||||||
|
{ 2, 0x01, MPU_REGION_SIZE_256MB,
|
||||||
|
0x01, MPU_REGION_SIZE_32MB, 0, 0},
|
||||||
|
{ 1, 0x01, MPU_REGION_SIZE_256MB,
|
||||||
|
0x0F, MPU_REGION_SIZE_32MB,
|
||||||
|
0x01, MPU_REGION_SIZE_16MB},
|
||||||
|
{ 0, 0x01, MPU_REGION_SIZE_256MB,
|
||||||
|
0x01, MPU_REGION_SIZE_32MB,
|
||||||
|
0x03, MPU_REGION_SIZE_4MB},
|
||||||
|
};
|
||||||
|
size_t qspi_memory_size_mbytes = qspi_memory_size_bytes / 1024 / 1024;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 9; ++i) {
|
||||||
|
if (qspi_memory_size_mbytes > region_definitions[i][0]) {
|
||||||
|
uint32_t attr_size_1 = MPU_CONFIG_NOACCESS(region_definitions[i][1], region_definitions[i][2]);
|
||||||
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, attr_size_1);
|
||||||
|
if (region_definitions[i][3] > 0) {
|
||||||
|
uint32_t attr_size_2 = MPU_CONFIG_NOACCESS(region_definitions[i][3], region_definitions[i][4]);
|
||||||
|
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, attr_size_2);
|
||||||
|
}
|
||||||
|
if (region_definitions[i][5] > 0) {
|
||||||
|
uint32_t attr_size_3 = MPU_CONFIG_NOACCESS(region_definitions[i][5], region_definitions[i][6]);
|
||||||
|
mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, attr_size_3);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mpu_config_end(irq_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void qspi_set_memory_size(size_t memory_size_bytes) {
|
||||||
|
qspi_memory_size_bytes = memory_size_bytes;
|
||||||
|
size_t QSPIFLASH_SIZE_BITS_LOG2 = BITS_TO_LOG2(qspi_memory_size_bytes * 8);
|
||||||
|
QUADSPI->DCR =
|
||||||
|
(QSPIFLASH_SIZE_BITS_LOG2 - 3 - 1) << QUADSPI_DCR_FSIZE_Pos
|
||||||
|
| (MICROPY_HW_QSPI_CS_HIGH_CYCLES - 1) << QUADSPI_DCR_CSHT_Pos
|
||||||
|
| 0 << QUADSPI_DCR_CKMODE_Pos // CLK idles at low state
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qspi_init(size_t memory_size_bytes) {
|
||||||
|
qspi_memory_size_bytes = memory_size_bytes;
|
||||||
|
|
||||||
qspi_mpu_disable_all();
|
qspi_mpu_disable_all();
|
||||||
|
|
||||||
// Configure pins
|
// Configure pins
|
||||||
|
@ -143,15 +216,20 @@ void qspi_init(void) {
|
||||||
| 1 << QUADSPI_CR_EN_Pos // enable the peripheral
|
| 1 << QUADSPI_CR_EN_Pos // enable the peripheral
|
||||||
;
|
;
|
||||||
|
|
||||||
QUADSPI->DCR =
|
if (qspi_memory_size_bytes) {
|
||||||
(MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 - 3 - 1) << QUADSPI_DCR_FSIZE_Pos
|
qspi_set_memory_size(qspi_memory_size_bytes);
|
||||||
| (MICROPY_HW_QSPI_CS_HIGH_CYCLES - 1) << QUADSPI_DCR_CSHT_Pos
|
}
|
||||||
| 0 << QUADSPI_DCR_CKMODE_Pos // CLK idles at low state
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qspi_memory_map(void) {
|
void qspi_memory_map() {
|
||||||
// Enable memory-mapped mode
|
// Enable memory-mapped mode
|
||||||
|
uint8_t cmd = QSPI_FAST_READ_A3_CMD;
|
||||||
|
uint8_t adsize = 2;
|
||||||
|
if (qspi_memory_size_bytes > (16 * MBytes)) {
|
||||||
|
// Flash chips over 16MB require 32bit addressing.
|
||||||
|
cmd = QSPI_FAST_READ_A4_CMD;
|
||||||
|
adsize = 3;
|
||||||
|
}
|
||||||
|
|
||||||
QUADSPI->ABR = 0; // disable continuous read mode
|
QUADSPI->ABR = 0; // disable continuous read mode
|
||||||
|
|
||||||
|
@ -163,20 +241,20 @@ void qspi_memory_map(void) {
|
||||||
| 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles
|
| 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles
|
||||||
| 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte
|
| 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte
|
||||||
| 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines
|
| 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines
|
||||||
| QSPI_ADSIZE << QUADSPI_CCR_ADSIZE_Pos
|
| adsize << QUADSPI_CCR_ADSIZE_Pos
|
||||||
| 3 << QUADSPI_CCR_ADMODE_Pos // address on 4 lines
|
| 3 << QUADSPI_CCR_ADMODE_Pos // address on 4 lines
|
||||||
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
|
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
|
||||||
| QSPI_CMD << QUADSPI_CCR_INSTRUCTION_Pos
|
| cmd << QUADSPI_CCR_INSTRUCTION_Pos
|
||||||
;
|
;
|
||||||
|
|
||||||
qspi_mpu_enable_mapped();
|
qspi_mpu_enable_mapped();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qspi_ioctl(void *self_in, uint32_t cmd) {
|
static int qspi_ioctl(void *self_in, uint32_t cmd, uint32_t arg) {
|
||||||
(void)self_in;
|
(void)self_in;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case MP_QSPI_IOCTL_INIT:
|
case MP_QSPI_IOCTL_INIT:
|
||||||
qspi_init();
|
qspi_init(0);
|
||||||
break;
|
break;
|
||||||
case MP_QSPI_IOCTL_BUS_ACQUIRE:
|
case MP_QSPI_IOCTL_BUS_ACQUIRE:
|
||||||
// Disable memory-mapped region during bus access
|
// Disable memory-mapped region during bus access
|
||||||
|
@ -192,6 +270,11 @@ static int qspi_ioctl(void *self_in, uint32_t cmd) {
|
||||||
// Switch to memory-map mode when bus is idle
|
// Switch to memory-map mode when bus is idle
|
||||||
qspi_memory_map();
|
qspi_memory_map();
|
||||||
break;
|
break;
|
||||||
|
case MP_QSPI_IOCTL_FLASH_SIZE:
|
||||||
|
if (arg > 0) {
|
||||||
|
qspi_set_memory_size(arg);
|
||||||
|
}
|
||||||
|
return qspi_memory_size_bytes;
|
||||||
}
|
}
|
||||||
return 0; // success
|
return 0; // success
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
extern const mp_qspi_proto_t qspi_proto;
|
extern const mp_qspi_proto_t qspi_proto;
|
||||||
|
|
||||||
void qspi_init(void);
|
void qspi_init(size_t memory_size_bytes);
|
||||||
void qspi_memory_map(void);
|
void qspi_memory_map(void);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_STM32_QSPI_H
|
#endif // MICROPY_INCLUDED_STM32_QSPI_H
|
||||||
|
|
Ładowanie…
Reference in New Issue