¿Funciona correctamente la lectura durante la escritura de doble banco en STM32L071?

Estoy tratando de reprogramar el NVM (banco de flash 2) mientras ejecuto el código del banco de flash 1 en el microcontrolador STM32L071CB.

Como dice AN4808 y AN4767, "la interfaz de memoria es capaz de leer ambos bancos en paralelo, o leer un banco mientras escribe en el otro ...", pero estoy experimentando algunos problemas:

  1. La depuración muestra que el bit FWWERR sube en el registro de estado de flash durante la operación de escritura de media página del banco flash 2. Significa que se ha detenido la escritura del banco flash 2 debido a la obtención del código.
  2. Borrar el banco 2 por código en el banco 1 funciona correctamente.
  3. Escribir por palabras banco 2 por código en banco 1 parece funcionar correctamente (pero tengo dudas si es solo una coincidencia).
  4. La escritura de media página termina con el bit FWWERR establecido en FLASH_SR y ceros en la memoria que estoy tratando de escribir.

Sé que me estoy perdiendo algo, pero no puedo encontrar lo que 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 dual, 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
Asegúrese de que el depurador no lea el contenido flash durante la programación. No escalone la secuencia de programación, use puntos de interrupción.

Respuestas (1)

Lectura-mientras-escritura tiene algunas limitaciones en el caso de la operación de programación múltiple. Ver RM0377 § 3.3.4 Escritura/borrado de la MVN - Media página del programa en la memoria de programa Flash página 82:

Cuando se inicia una operación de media página, la interfaz de memoria espera 16 direcciones/datos, abortando (con una falla grave) todos los accesos de lectura que no son de recuperación (consulte Recuperación y captación previa). Una búsqueda detiene la operación de media página. El contenido de la memoria permanece sin cambios, el error FWWERR se establece en el registro FLASH_SR.

Esto significa que no se permiten operaciones de búsqueda en la memoria flash mientras se alimenta la interfaz de memoria con las 16 palabras (cualquiera que sea el código que se ejecuta en el banco 1 y la programación de media página se realiza en el banco 2). Una vez que las 16 palabras se han enviado a la interfaz de memoria, puede reanudar la ejecución desde flash, es decir, durante la escritura física de los datos dentro del banco flash (suponiendo que su código se esté ejecutando en el otro banco).

En pocas palabras, debe ejecutar desde SRAM la alimentación de la interfaz de memoria con las 16 palabras y asegurarse de que las interrupciones no causen recuperación en la memoria flash (o enmascare todas las interrupciones o reubique los controladores de interrupciones y el vector de interrupciones en SRAM).

Nota: no existe tal limitación en el caso de la operación de programación única.