stmhal: Add ability to have filesystem stored on external SPI flash.
To use this feature a port should define MICROPY_HW_SPIFLASH_SIZE_BITS along with x_CS, x_SCK, x_MOSI, x_MISO (x=MICROPY_HW_SPIFLASH). This will then use external SPI flash on those pins instead of the internal flash. The SPI is done using the software implementation. There is currently only support for standard SPI (ie not dual or quad mode).
This commit is contained in:
parent
784e023a26
commit
d6a2d00167
|
@ -117,6 +117,10 @@ SRC_LIB = $(addprefix lib/,\
|
|||
utils/pyexec.c \
|
||||
)
|
||||
|
||||
DRIVERS_SRC_C = $(addprefix drivers/,\
|
||||
memory/spiflash.c \
|
||||
)
|
||||
|
||||
SRC_C = \
|
||||
main.c \
|
||||
system_stm32.c \
|
||||
|
@ -256,6 +260,7 @@ endif
|
|||
OBJ =
|
||||
OBJ += $(PY_O)
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_O))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_HAL:.c=.o))
|
||||
|
|
|
@ -38,6 +38,14 @@
|
|||
#include "storage.h"
|
||||
#include "irq.h"
|
||||
|
||||
#if defined(MICROPY_HW_SPIFLASH_SIZE_BITS)
|
||||
#define USE_INTERNAL (0)
|
||||
#else
|
||||
#define USE_INTERNAL (1)
|
||||
#endif
|
||||
|
||||
#if USE_INTERNAL
|
||||
|
||||
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)
|
||||
|
||||
#define CACHE_MEM_START_ADDR (0x10000000) // CCM data RAM, 64k
|
||||
|
@ -158,19 +166,50 @@ static uint8_t *flash_cache_get_addr_for_read(uint32_t flash_addr) {
|
|||
return (uint8_t*)flash_addr;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "drivers/memory/spiflash.h"
|
||||
#include "genhdr/pins.h"
|
||||
|
||||
#define FLASH_PART1_START_BLOCK (0x100)
|
||||
#define FLASH_PART1_NUM_BLOCKS (MICROPY_HW_SPIFLASH_SIZE_BITS / 8 / FLASH_BLOCK_SIZE)
|
||||
|
||||
static bool flash_is_initialised = false;
|
||||
|
||||
STATIC const mp_spiflash_t spiflash = {
|
||||
.cs = &MICROPY_HW_SPIFLASH_CS,
|
||||
.spi = {
|
||||
.base = {&mp_machine_soft_spi_type},
|
||||
.delay_half = MICROPY_PY_MACHINE_SPI_MIN_DELAY,
|
||||
.polarity = 0,
|
||||
.phase = 0,
|
||||
.sck = &MICROPY_HW_SPIFLASH_SCK,
|
||||
.mosi = &MICROPY_HW_SPIFLASH_MOSI,
|
||||
.miso = &MICROPY_HW_SPIFLASH_MISO,
|
||||
},
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void storage_init(void) {
|
||||
if (!flash_is_initialised) {
|
||||
#if USE_INTERNAL
|
||||
flash_flags = 0;
|
||||
flash_cache_sector_id = 0;
|
||||
flash_tick_counter_last_write = 0;
|
||||
#else
|
||||
mp_spiflash_init((mp_spiflash_t*)&spiflash);
|
||||
#endif
|
||||
flash_is_initialised = true;
|
||||
}
|
||||
|
||||
#if USE_INTERNAL
|
||||
// Enable the flash IRQ, which is used to also call our storage IRQ handler
|
||||
// It needs to go at a higher priority than all those components that rely on
|
||||
// the flash storage (eg higher than USB MSC).
|
||||
HAL_NVIC_SetPriority(FLASH_IRQn, IRQ_PRI_FLASH, IRQ_SUBPRI_FLASH);
|
||||
HAL_NVIC_EnableIRQ(FLASH_IRQn);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t storage_get_block_size(void) {
|
||||
|
@ -182,6 +221,8 @@ uint32_t storage_get_block_count(void) {
|
|||
}
|
||||
|
||||
void storage_irq_handler(void) {
|
||||
#if USE_INTERNAL
|
||||
|
||||
if (!(flash_flags & FLASH_FLAG_DIRTY)) {
|
||||
return;
|
||||
}
|
||||
|
@ -222,10 +263,14 @@ void storage_irq_handler(void) {
|
|||
// indicate a clean cache with LED off
|
||||
led_state(PYB_LED_R1, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void storage_flush(void) {
|
||||
#if USE_INTERNAL
|
||||
flash_cache_flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_block, uint32_t num_blocks) {
|
||||
|
@ -264,6 +309,8 @@ static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_blo
|
|||
buf[15] = num_blocks >> 24;
|
||||
}
|
||||
|
||||
#if USE_INTERNAL
|
||||
|
||||
static uint32_t convert_block_to_flash_addr(uint32_t block) {
|
||||
if (FLASH_PART1_START_BLOCK <= block && block < FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS) {
|
||||
// a block in partition 1
|
||||
|
@ -279,6 +326,8 @@ static uint32_t convert_block_to_flash_addr(uint32_t block) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool storage_read_block(uint8_t *dest, uint32_t block) {
|
||||
//printf("RD %u\n", block);
|
||||
if (block == 0) {
|
||||
|
@ -299,6 +348,8 @@ bool storage_read_block(uint8_t *dest, uint32_t block) {
|
|||
return true;
|
||||
|
||||
} else {
|
||||
#if USE_INTERNAL
|
||||
|
||||
// non-MBR block, get data from flash memory, possibly via cache
|
||||
uint32_t flash_addr = convert_block_to_flash_addr(block);
|
||||
if (flash_addr == -1) {
|
||||
|
@ -308,6 +359,27 @@ bool storage_read_block(uint8_t *dest, uint32_t block) {
|
|||
uint8_t *src = flash_cache_get_addr_for_read(flash_addr);
|
||||
memcpy(dest, src, FLASH_BLOCK_SIZE);
|
||||
return true;
|
||||
|
||||
#else
|
||||
|
||||
// non-MBR block, get data from SPI flash
|
||||
|
||||
if (block < FLASH_PART1_START_BLOCK || block >= FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS) {
|
||||
// bad block number
|
||||
return false;
|
||||
}
|
||||
|
||||
// we must disable USB irqs to prevent MSC contention with SPI flash
|
||||
uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS);
|
||||
|
||||
mp_spiflash_read((mp_spiflash_t*)&spiflash,
|
||||
(block - FLASH_PART1_START_BLOCK) * FLASH_BLOCK_SIZE, FLASH_BLOCK_SIZE, dest);
|
||||
|
||||
restore_irq_pri(basepri);
|
||||
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,6 +390,8 @@ bool storage_write_block(const uint8_t *src, uint32_t block) {
|
|||
return true;
|
||||
|
||||
} else {
|
||||
#if USE_INTERNAL
|
||||
|
||||
// non-MBR block, copy to cache
|
||||
uint32_t flash_addr = convert_block_to_flash_addr(block);
|
||||
if (flash_addr == -1) {
|
||||
|
@ -327,6 +401,27 @@ bool storage_write_block(const uint8_t *src, uint32_t block) {
|
|||
uint8_t *dest = flash_cache_get_addr_for_write(flash_addr);
|
||||
memcpy(dest, src, FLASH_BLOCK_SIZE);
|
||||
return true;
|
||||
|
||||
#else
|
||||
|
||||
// non-MBR block, write to SPI flash
|
||||
|
||||
if (block < FLASH_PART1_START_BLOCK || block >= FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS) {
|
||||
// bad block number
|
||||
return false;
|
||||
}
|
||||
|
||||
// we must disable USB irqs to prevent MSC contention with SPI flash
|
||||
uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS);
|
||||
|
||||
int ret = mp_spiflash_write((mp_spiflash_t*)&spiflash,
|
||||
(block - FLASH_PART1_START_BLOCK) * FLASH_BLOCK_SIZE, FLASH_BLOCK_SIZE, src);
|
||||
|
||||
restore_irq_pri(basepri);
|
||||
|
||||
return ret == 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue