@@ -61,7 +61,6 @@ static int stm32f4_erase_all_flash(STM32F4_PRIV_t *priv, int *progress, int prog
6161 int time = 0 ;
6262 int progress_step = progress_end /10 ;
6363
64- printf ("Erase Flash\n" );
6564 /* Flash mass erase start instruction */
6665 priv -> cortex -> ops -> write_word (priv -> cortex -> priv , STM32F4_FLASH_CR , STM32F4_FLASH_CR_MER );
6766 priv -> cortex -> ops -> write_word (priv -> cortex -> priv , STM32F4_FLASH_CR , STM32F4_FLASH_CR_STRT | STM32F4_FLASH_CR_MER | STM32F4_FLASH_CR_EOPIE );
@@ -73,7 +72,7 @@ static int stm32f4_erase_all_flash(STM32F4_PRIV_t *priv, int *progress, int prog
7372 printf ("Error while waiting for erase end\n" );
7473 return STM32F4_ERASE_NEVER_END ;
7574 }
76- osDelay (1 );
75+ osDelay (10 );
7776 time ++ ;
7877 // after each 100 loops add one to progress, we asume that whole erase will take 1000 loops
7978 if (time > 100 ) {
@@ -98,6 +97,84 @@ static int stm32f4_erase_all_flash(STM32F4_PRIV_t *priv, int *progress, int prog
9897 return 0 ;
9998}
10099
100+ // This function return how many sectors is needed in bank 1 of flash
101+ // to save len bytes. If len is bigger then 7 sectors, return bigger number than number of sectors
102+ static uint8_t stm32f4_sectors_in_bank1 (int len )
103+ {
104+ uint8_t sector = 0 ;
105+ while (len > 0 ) {
106+ /*
107+ * Secotr sizes from:
108+ * RM0090 -- STM32F4xx reference manual, chapter 3.3
109+ */
110+ switch (sector ) {
111+ case 0 :
112+ case 1 :
113+ case 2 :
114+ case 3 :
115+ len -= 0x4000 ;
116+ break ;
117+ case 4 :
118+ len -= 0x10000 ;
119+ break ;
120+ case 5 :
121+ case 6 :
122+ case 7 :
123+ len -= 0x20000 ;
124+ break ;
125+ case 8 :
126+ return 255 ;
127+ }
128+ sector ++ ;
129+ }
130+ return sector ;
131+ }
132+
133+ static int stm32f4_erase_flash (STM32F4_PRIV_t * priv , int len , int * progress , int progress_end )
134+ {
135+ uint16_t sr ;
136+ uint32_t cr ;
137+ uint8_t last_sector_to_flash = stm32f4_sectors_in_bank1 (len );
138+ int progress_step = (progress_end + 31 )/32 ;
139+
140+ printf ("Erase Flash\n" );
141+ // TODO: For simplicity only when writing less than 512KB optimal sector erase
142+ // algorithm is used. First 7 sectors are the same size which is independent
143+ // of single and dual bank mode and size of flash memory.
144+ if (last_sector_to_flash > 7 ) {
145+ return stm32f4_erase_all_flash (priv , progress , progress_end );
146+ }
147+
148+ for (uint8_t sector = 0 ; sector <= last_sector_to_flash ; sector ++ ) {
149+ cr = STM32F4_FLASH_CR_EOPIE | STM32F4_FLASH_CR_ERRIE | STM32F4_FLASH_CR_SER ;
150+ cr |= sector << STM32F4_FLASH_CR_SNB_SHIFT ;
151+ /* Flash page erase instruction */
152+ priv -> cortex -> ops -> write_word (priv -> cortex -> priv , STM32F4_FLASH_CR , cr );
153+ /* write address to FMA */
154+ priv -> cortex -> ops -> write_word (priv -> cortex -> priv , STM32F4_FLASH_CR , cr | STM32F4_FLASH_CR_STRT );
155+ /* Read FLASH_SR to poll for BSY bit */
156+ while (priv -> cortex -> ops -> read_word (priv -> cortex -> priv , STM32F4_FLASH_SR ) & STM32F4_FLASH_SR_BSY ) {
157+ if (priv -> cortex -> ops -> check_error (priv -> cortex -> priv )) {
158+ // TODO: handle error
159+ printf ("Error while waiting for erase end\n" );
160+ return STM32F4_ERASE_NEVER_END ;
161+ }
162+ }
163+ * progress += progress_step ;
164+ printf ("Flash progress %d\n" , * progress );
165+ }
166+
167+ /* Check for error */
168+ sr = priv -> cortex -> ops -> read_word (priv -> cortex -> priv , STM32F4_FLASH_SR );
169+ if ((sr & STM32F4_SR_ERROR_MASK ) || !(sr & STM32F4_SR_EOP )) {
170+ // TODO: handle error
171+ printf ("Error after erase 0x%x\n" , sr );
172+ return sr | STM32F4_ERASE_ERROR_BIT ;
173+ }
174+
175+ return 0 ;
176+ }
177+
101178static int stm32f4_flash_write (STM32F4_PRIV_t * priv , uint32_t dest , const uint32_t * src , int len )
102179{
103180 uint32_t start_of_ram = 0x20000000 ;
@@ -144,22 +221,25 @@ static int stm32f4_program(void *priv_void, FIL *file, int *progress)
144221 uint32_t * data = pvPortMalloc (STM32F4_SIZE_OF_ONE_WRITE /sizeof (uint32_t ));
145222 STM32F4_PRIV_t * priv = priv_void ;
146223 uint16_t result ;
224+ uint32_t file_len = f_size (file );
147225
148226 // these variables are only needed to show progress
149- int number_of_writes = (f_size ( file ) + STM32F4_SIZE_OF_ONE_WRITE - 1 )/STM32F4_SIZE_OF_ONE_WRITE + STM32F4_ERASE_TIME_IN_WRITES ;
150- float progress_as_float = 100 * STM32F4_ERASE_TIME_IN_WRITES /number_of_writes ;
151- float progress_on_one_write = 100.0 / number_of_writes ;
227+ int number_of_writes = (file_len + STM32F4_SIZE_OF_ONE_WRITE - 1 )/STM32F4_SIZE_OF_ONE_WRITE ;
228+ float progress_as_float = 100 * STM32F4_ERASE_TIME_IN_WRITES /( number_of_writes + STM32F4_ERASE_TIME_IN_WRITES ) ;
229+ float progress_on_one_write ;
152230
153231 printf ("Start flashing STM32F4x\n" );
154232
155233 priv -> cortex -> ops -> halt_request (priv -> cortex -> priv );
156234 stm32f4_flash_unlock (priv );
157- result = stm32f4_erase_all_flash (priv , progress , progress_as_float );
235+ result = stm32f4_erase_flash (priv , file_len , progress , progress_as_float );
158236 if (result ) {
159237 vPortFree (data );
160238 return result ;
161239 }
162240
241+ progress_as_float = * progress ;
242+ progress_on_one_write = (100 - * progress )/number_of_writes ;
163243
164244 do {
165245 f_read (file , data , STM32F4_SIZE_OF_ONE_WRITE , & br );
0 commit comments