Estoy intentando reprogramar el NVM (flash bank 2) mientras ejecuto el código del flash bank 1 en el microcontrolador STM32L071CB.
Como indican AN4808 y AN4767, "la interfaz de memoria es capaz de leer ambos bancos en paralelo, o leer un banco mientras escribe al otro ...", pero estoy experimentando algunos problemas :
- La depuración muestra que el bit FWWERR aumenta en el registro de estado de flash durante la operación de escritura de media página del banco de flash 2. Significa que se ha detenido la escritura del flash bank 2 debido a la obtención de código.
- El borrado del banco 2 por el código del banco 1 funciona correctamente.
- Escribir con el banco 2 de palabras por código en el banco 1 parece funcionar correctamente (pero tengo dudas de que solo sea una coincidencia).
- La escritura de media página termina con el bit FWWERR establecido en FLASH_SR y los ceros en la memoria que estoy intentando escribir.
Sé que me estoy perdiendo algo, pero no puedo descubrir qué es. Tal vez alguien tuvo un problema similar? Estoy empezando a pensar que hay algo mal con el microcontrolador (la hoja de erratas señala algunos problemas con el mecanismo de cambio de banco doble, pero no debería ser un problema en mi caso, porque no estoy cambiando de banco en este momento).
Mi función funciona correctamente cuando se ejecuta desde la memoria RAM, pero prefiero que se ejecute desde el banco flash 1.
La función (1) a continuación es responsable de escribir medias páginas. El código (2) muestra la forma en que estoy llamando (2).
(1)
void nvm_prog_write_halfpages(uint32_t* addr, uint32_t* data, uint32_t length){
// There can't be any previous alignment errors in the flash SR
if ((FLASH->SR & FLASH_SR_PGAERR_Msk) == FLASH_SR_PGAERR){
FLASH->SR = FLASH_SR_PGAERR; // clear any previous alignment errors
}
// Check if any operation was stopped previously due to code fetching
if ((FLASH->SR & FLASH_SR_FWWERR_Msk) == FLASH_SR_FWWERR){
FLASH->SR = FLASH_SR_FWWERR; // clear any previous fetch related errors
}
nvm_prog_unlock();
FLASH->PECR |= FLASH_PECR_PROG | FLASH_PECR_FPRG;
uint32_t cnt = 0;
while (length > 0){
*addr = *data; // Destination address will be increased by the hardware automatically
data++;
cnt++;
// When a half-page has been written
if (cnt == 16){
while ((FLASH->SR & FLASH_SR_BSY_Msk) == FLASH_SR_BSY)
;
cnt = 0;
addr += 16; // Write the next half-page
length--;
}
}
FLASH->PECR &= ~(FLASH_PECR_PROG | FLASH_PECR_FPRG);
nvm_prog_lock();
}
(2)
nvm_prog_erase_page((uint32_t *) 0x08010000); // Erase flash bank 2; it starts at 0x08010000
uint32_t dummydata[32], i;
for (i=0; i<32; i++){
dummydata[i] = i;
}
nvm_prog_write_halfpages((uint32_t *) 0x08010000, &dummydata[0], 2); // Write 2 half-pages at the beginning of flash bank 2