Skip to content

Commit 736a637

Browse files
committed
Add sector flash erase to STM32F4xx
When small binary file is loaded, only part of flash could be erased. This feature speed up flash time. It is added only for files smaller than 512 kb, because this doesn't add much of complexity to erase routine.
1 parent fe7d723 commit 736a637

File tree

2 files changed

+87
-6
lines changed

2 files changed

+87
-6
lines changed

Inc/cortexm/stm32/stm32f4.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define STM32F4_FLASH_CR_PG (1 << 0)
1414
#define STM32F4_FLASH_CR_SER (1 << 1)
1515
#define STM32F4_FLASH_CR_MER (1 << 2)
16+
#define STM32F4_FLASH_CR_SNB_SHIFT (3)
1617
#define STM32F4_FLASH_CR_PSIZE8 (0 << 8)
1718
#define STM32F4_FLASH_CR_PSIZE16 (1 << 8)
1819
#define STM32F4_FLASH_CR_PSIZE32 (2 << 8)

Src/cortexm/stm32/stm32f4.c

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
101178
static 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

Comments
 (0)