diff --git a/stmhal/Makefile b/stmhal/Makefile index 9a9c50f065..87236068ba 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -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)) diff --git a/stmhal/storage.c b/stmhal/storage.c index 14b504d716..60a7e9f480 100644 --- a/stmhal/storage.c +++ b/stmhal/storage.c @@ -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 } }