summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal/storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'stmhal/storage.c')
-rw-r--r--stmhal/storage.c116
1 files changed, 107 insertions, 9 deletions
diff --git a/stmhal/storage.c b/stmhal/storage.c
index 14b504d716..d0f2782856 100644
--- a/stmhal/storage.c
+++ b/stmhal/storage.c
@@ -29,8 +29,8 @@
#include "py/obj.h"
#include "py/runtime.h"
-#include "lib/fatfs/ff.h"
-#include "extmod/fsusermount.h"
+#include "lib/oofatfs/ff.h"
+#include "extmod/vfs_fat.h"
#include "systick.h"
#include "led.h"
@@ -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
@@ -141,7 +149,7 @@ static uint8_t *flash_cache_get_addr_for_write(uint32_t flash_addr) {
flash_cache_sector_size = flash_sector_size;
}
flash_flags |= FLASH_FLAG_DIRTY;
- led_state(PYB_LED_R1, 1); // indicate a dirty cache with LED on
+ led_state(PYB_LED_RED, 1); // indicate a dirty cache with LED on
flash_tick_counter_last_write = HAL_GetTick();
return (uint8_t*)CACHE_MEM_START_ADDR + flash_addr - flash_sector_start;
}
@@ -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;
}
@@ -220,12 +261,16 @@ void storage_irq_handler(void) {
// clear the flash flags now that we have a clean cache
flash_flags = 0;
// indicate a clean cache with LED off
- led_state(PYB_LED_R1, 0);
+ led_state(PYB_LED_RED, 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
}
}
@@ -393,10 +488,10 @@ STATIC mp_obj_t pyb_flash_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in)
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_ioctl_obj, pyb_flash_ioctl);
-STATIC const mp_map_elem_t pyb_flash_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_readblocks), (mp_obj_t)&pyb_flash_readblocks_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_writeblocks), (mp_obj_t)&pyb_flash_writeblocks_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&pyb_flash_ioctl_obj },
+STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&pyb_flash_readblocks_obj) },
+ { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&pyb_flash_writeblocks_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&pyb_flash_ioctl_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table);
@@ -405,11 +500,14 @@ const mp_obj_type_t pyb_flash_type = {
{ &mp_type_type },
.name = MP_QSTR_Flash,
.make_new = pyb_flash_make_new,
- .locals_dict = (mp_obj_t)&pyb_flash_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_flash_locals_dict,
};
void pyb_flash_init_vfs(fs_user_mount_t *vfs) {
+ vfs->base.type = &mp_fat_vfs_type;
vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL;
+ vfs->fatfs.drv = vfs;
+ vfs->fatfs.part = 1; // flash filesystem lives on first partition
vfs->readblocks[0] = (mp_obj_t)&pyb_flash_readblocks_obj;
vfs->readblocks[1] = (mp_obj_t)&pyb_flash_obj;
vfs->readblocks[2] = (mp_obj_t)storage_read_blocks; // native version