summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--stmhal/Makefile5
-rw-r--r--stmhal/storage.c95
2 files changed, 100 insertions, 0 deletions
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
}
}