Funktioniert Dual-Bank-Read-While-Write in STM32L071 ordnungsgemäß?

Ich versuche, den NVM (Flash-Bank 2) neu zu programmieren, während Code von Flash-Bank 1 im STM32L071CB-Mikrocontroller ausgeführt wird.

Wie AN4808 und AN4767 angeben, "ist die Speicherschnittstelle in der Lage, beide Bänke parallel zu lesen oder eine Bank zu lesen, während in die andere geschrieben wird ...", aber ich habe einige Probleme:

  1. Das Debuggen zeigt, dass das FWWERR-Bit im Flash-Statusregister während des Halbseiten-Schreibvorgangs der Flash-Bank 2 hoch geht. Dies bedeutet, dass das Schreiben der Flash-Bank 2 wegen Code-Abrufen gestoppt wurde.
  2. Das Löschen von Bank 2 per Code in Bank 1 funktioniert einwandfrei.
  3. Das Schreiben von Wörtern Bank 2 durch Code in Bank 1 scheint richtig zu funktionieren (aber ich habe Zweifel, ob es nur ein Zufall ist).
  4. Das Schreiben einer halben Seite endet mit dem in FLASH_SR gesetzten FWWERR-Bit und Nullen im Speicher, den ich zu schreiben versuche.

Ich weiß, dass mir etwas fehlt, aber ich kann nicht herausfinden, was es ist. Hatte vielleicht jemand ähnliche Probleme? Ich fange an zu glauben, dass etwas mit dem Mikrocontroller nicht stimmt (Errata-Blatt weist auf einige Probleme mit dem Dual-Bank-Umschaltmechanismus hin, aber das sollte in meinem Fall kein Problem sein, da ich gerade keine Bank wechsle).

Meine Funktion funktioniert ordnungsgemäß, wenn sie vom RAM-Speicher ausgeführt wird, aber ich möchte lieber, dass sie von der Flash-Bank 1 ausgeführt wird.

Die folgende Funktion (1) ist für das Schreiben von halben Seiten zuständig. Code (2) zeigt den Weg, den ich anrufe (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
Stellen Sie sicher, dass der Debugger während der Programmierung nicht den Flash-Inhalt liest. Gehen Sie nicht schrittweise in die Programmiersequenz, sondern verwenden Sie Haltepunkte.

Antworten (1)

Read-While-Write hat einige Einschränkungen im Falle eines Mehrfachprogrammiervorgangs. Siehe RM0377 § 3.3.4 Schreiben/Löschen der NVM - Programmhalbseite im Flash-Programmspeicher Seite 82:

Wenn eine Halbseitenoperation beginnt, wartet die Speicherschnittstelle auf 16 Adressen/Daten und bricht (mit einem harten Fehler) alle Lesezugriffe ab, die kein Abruf sind (siehe Abrufen und Vorabrufen). Ein Abruf stoppt die Halbseitenoperation. Der Speicherinhalt bleibt unverändert, der Fehler FWWERR wird im Register FLASH_SR gesetzt.

Dies bedeutet, dass im Flash keine Abrufoperation erlaubt ist, während die Speicherschnittstelle mit den 16 Wörtern gespeist wird (was auch immer der Code in Bank 1 läuft und die Halbseitenprogrammierung in Bank 2 durchgeführt wird). Sobald die 16 Wörter an die Speicherschnittstelle gesendet wurden, können Sie die Ausführung vom Flash aus fortsetzen, dh während des physischen Schreibens der Daten in die Flash-Bank (vorausgesetzt, Ihr Code läuft in der anderen Bank).

Kurz gesagt, Sie müssen vom SRAM aus die Speisung der Speicherschnittstelle mit den 16 Wörtern ausführen und sicherstellen, dass die Interrupts keinen Abruf im Flash-Speicher verursachen (entweder alle Interrupts maskieren oder Interrupt-Handler und Interrupt-Vektor im SRAM verschieben).

Hinweis: Bei der Einzelprogrammierung gibt es diese Einschränkung nicht.