@ -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
}
}