1616#define FLASH_PART1_NUM_BLOCKS (224) // 16k+16k+16k+64k=112k
1717#define FLASH_MEM_START_ADDR (0x08004000) // sector 1, 16k
1818
19+ #define FLASH_FLAG_DIRTY (1)
20+ #define FLASH_FLAG_FORCE_WRITE (2)
21+ #define FLASH_FLAG_ERASED (4)
1922static bool flash_is_initialised = false;
20- static bool flash_cache_dirty ;
23+ static __IO uint8_t flash_flags = 0 ;
2124static uint32_t flash_cache_sector_id ;
2225static uint32_t flash_cache_sector_start ;
2326static uint32_t flash_cache_sector_size ;
2427static uint32_t flash_tick_counter_last_write ;
2528
2629static void flash_cache_flush (void ) {
27- if (flash_cache_dirty ) {
28- // sync the cache RAM buffer by writing it to the flash page
29- flash_write (flash_cache_sector_start , (const uint32_t * )CACHE_MEM_START_ADDR , flash_cache_sector_size / 4 );
30- flash_cache_dirty = false;
31- // indicate a clean cache with LED off
32- led_state (PYB_LED_R1 , 0 );
30+ if (flash_flags & FLASH_FLAG_DIRTY ) {
31+ flash_flags |= FLASH_FLAG_FORCE_WRITE ;
32+ while (flash_flags & FLASH_FLAG_DIRTY ) {
33+ NVIC -> STIR = FLASH_IRQn ;
34+ }
3335 }
3436}
3537
@@ -44,9 +46,9 @@ static uint8_t *flash_cache_get_addr_for_write(uint32_t flash_addr) {
4446 flash_cache_sector_start = flash_sector_start ;
4547 flash_cache_sector_size = flash_sector_size ;
4648 }
47- flash_cache_dirty = true ;
48- // indicate a dirty cache with LED on
49- led_state ( PYB_LED_R1 , 1 );
49+ flash_flags |= FLASH_FLAG_DIRTY ;
50+ led_state ( PYB_LED_R1 , 1 ); // indicate a dirty cache with LED on
51+ flash_tick_counter_last_write = HAL_GetTick ( );
5052 return (uint8_t * )CACHE_MEM_START_ADDR + flash_addr - flash_sector_start ;
5153}
5254
@@ -64,11 +66,17 @@ static uint8_t *flash_cache_get_addr_for_read(uint32_t flash_addr) {
6466
6567void storage_init (void ) {
6668 if (!flash_is_initialised ) {
67- flash_cache_dirty = false ;
69+ flash_flags = 0 ;
6870 flash_cache_sector_id = 0 ;
69- flash_is_initialised = true;
7071 flash_tick_counter_last_write = 0 ;
72+ flash_is_initialised = true;
7173 }
74+
75+ // Enable the flash IRQ, which is used to also call our storage IRQ handler
76+ // It needs to go at a higher priority than all those components that rely on
77+ // the flash storage (eg higher than USB MSC).
78+ HAL_NVIC_SetPriority (FLASH_IRQn , 1 , 1 );
79+ HAL_NVIC_EnableIRQ (FLASH_IRQn );
7280}
7381
7482uint32_t storage_get_block_size (void ) {
@@ -79,9 +87,47 @@ uint32_t storage_get_block_count(void) {
7987 return FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS ;
8088}
8189
82- bool storage_needs_flush (void ) {
83- // wait 2 seconds after last write to flush
84- return flash_cache_dirty && sys_tick_has_passed (flash_tick_counter_last_write , 2000 );
90+ void storage_irq_handler (void ) {
91+ if (!(flash_flags & FLASH_FLAG_DIRTY )) {
92+ return ;
93+ }
94+
95+ // This code uses interrupts to erase the flash
96+ /*
97+ if (flash_erase_state == 0) {
98+ flash_erase_it(flash_cache_sector_start, (const uint32_t*)CACHE_MEM_START_ADDR, flash_cache_sector_size / 4);
99+ flash_erase_state = 1;
100+ return;
101+ }
102+
103+ if (flash_erase_state == 1) {
104+ // wait for erase
105+ // TODO add timeout
106+ #define flash_erase_done() (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) == RESET)
107+ if (!flash_erase_done()) {
108+ return;
109+ }
110+ flash_erase_state = 2;
111+ }
112+ */
113+
114+ // This code erases the flash directly, waiting for it to finish
115+ if (!(flash_flags & FLASH_FLAG_ERASED )) {
116+ flash_erase (flash_cache_sector_start , (const uint32_t * )CACHE_MEM_START_ADDR , flash_cache_sector_size / 4 );
117+ flash_flags |= FLASH_FLAG_ERASED ;
118+ return ;
119+ }
120+
121+ // If not a forced write, wait at least 5 seconds after last write to flush
122+ // On file close and flash unmount we get a forced write, so we can afford to wait a while
123+ if ((flash_flags & FLASH_FLAG_FORCE_WRITE ) || sys_tick_has_passed (flash_tick_counter_last_write , 5000 )) {
124+ // sync the cache RAM buffer by writing it to the flash page
125+ flash_write (flash_cache_sector_start , (const uint32_t * )CACHE_MEM_START_ADDR , flash_cache_sector_size / 4 );
126+ // clear the flash flags now that we have a clean cache
127+ flash_flags = 0 ;
128+ // indicate a clean cache with LED off
129+ led_state (PYB_LED_R1 , 0 );
130+ }
85131}
86132
87133void storage_flush (void ) {
@@ -167,7 +213,6 @@ bool storage_write_block(const uint8_t *src, uint32_t block) {
167213 uint32_t flash_addr = FLASH_MEM_START_ADDR + (block - FLASH_PART1_START_BLOCK ) * FLASH_BLOCK_SIZE ;
168214 uint8_t * dest = flash_cache_get_addr_for_write (flash_addr );
169215 memcpy (dest , src , FLASH_BLOCK_SIZE );
170- flash_tick_counter_last_write = HAL_GetTick ();
171216 return true;
172217
173218 } else {
0 commit comments