stm32/qspi: Use MPU to allow access to valid memory-mapped QSPI region.
The Cortex-M7 CPU will do speculative loads from any memory location that is not explicitly forbidden. This includes the QSPI memory-mapped region starting at 0x90000000 and with size 256MiB. Speculative loads to this QSPI region may 1) interfere with the QSPI peripheral registers (eg the address register) if the QSPI is not in memory-mapped mode; 2) attempt to access data outside the configured size of the QSPI flash when it is in memory-mapped mode. Both of these scenarios will lead to issues with the QSPI peripheral (eg Cortex bus lock up in scenario 2). To prevent such speculative loads from interfering with the peripheral the MPU is configured in this commit to restrict access to the QSPI mapped region: when not memory mapped the entire region is forbidden; when memory mapped only accesses to the valid flash size are permitted.
This commit is contained in:
parent
eca4115f66
commit
8da39fd182
|
@ -29,6 +29,9 @@
|
||||||
#if defined(STM32F7) || defined(STM32H7)
|
#if defined(STM32F7) || defined(STM32H7)
|
||||||
|
|
||||||
#define MPU_REGION_ETH (MPU_REGION_NUMBER0)
|
#define MPU_REGION_ETH (MPU_REGION_NUMBER0)
|
||||||
|
#define MPU_REGION_QSPI1 (MPU_REGION_NUMBER1)
|
||||||
|
#define MPU_REGION_QSPI2 (MPU_REGION_NUMBER2)
|
||||||
|
#define MPU_REGION_QSPI3 (MPU_REGION_NUMBER3)
|
||||||
#define MPU_REGION_SDRAM1 (MPU_REGION_NUMBER4)
|
#define MPU_REGION_SDRAM1 (MPU_REGION_NUMBER4)
|
||||||
#define MPU_REGION_SDRAM2 (MPU_REGION_NUMBER5)
|
#define MPU_REGION_SDRAM2 (MPU_REGION_NUMBER5)
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,14 @@
|
||||||
|
|
||||||
#include "py/mperrno.h"
|
#include "py/mperrno.h"
|
||||||
#include "py/mphal.h"
|
#include "py/mphal.h"
|
||||||
|
#include "mpu.h"
|
||||||
#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 defined(MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2)
|
||||||
|
|
||||||
|
#define QSPI_MAP_ADDR (0x90000000)
|
||||||
|
|
||||||
#ifndef MICROPY_HW_QSPI_PRESCALER
|
#ifndef MICROPY_HW_QSPI_PRESCALER
|
||||||
#define MICROPY_HW_QSPI_PRESCALER 3 // F_CLK = F_AHB/3 (72MHz when CPU is 216MHz)
|
#define MICROPY_HW_QSPI_PRESCALER 3 // F_CLK = F_AHB/3 (72MHz when CPU is 216MHz)
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,7 +52,31 @@
|
||||||
#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
|
||||||
|
|
||||||
|
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.
|
||||||
|
mpu_config_start();
|
||||||
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x00, MPU_REGION_SIZE_256MB));
|
||||||
|
mpu_config_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
// At the moment this is hard-coded to 2MiB of QSPI address space.
|
||||||
|
mpu_config_start();
|
||||||
|
mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB));
|
||||||
|
mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x0f, MPU_REGION_SIZE_32MB));
|
||||||
|
mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_16MB));
|
||||||
|
mpu_config_end();
|
||||||
|
}
|
||||||
|
|
||||||
void qspi_init(void) {
|
void qspi_init(void) {
|
||||||
|
qspi_mpu_disable_all();
|
||||||
|
|
||||||
// Configure pins
|
// Configure pins
|
||||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_CS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_BK1_NCS);
|
mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_CS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_BK1_NCS);
|
||||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_SCK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_CLK);
|
mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_SCK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_CLK);
|
||||||
|
@ -100,6 +127,8 @@ void qspi_memory_map(void) {
|
||||||
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
|
| 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line
|
||||||
| 0xeb << QUADSPI_CCR_INSTRUCTION_Pos // quad read opcode
|
| 0xeb << QUADSPI_CCR_INSTRUCTION_Pos // quad read opcode
|
||||||
;
|
;
|
||||||
|
|
||||||
|
qspi_mpu_enable_mapped();
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int qspi_ioctl(void *self_in, uint32_t cmd) {
|
STATIC int qspi_ioctl(void *self_in, uint32_t cmd) {
|
||||||
|
|
Loading…
Reference in New Issue