STM32F031 Wann blockiert CPU beim Flash programmieren/löschen

Gast #5348676
Lesenswert?

Guten Tag,

ich besitze einen STM32F031 und möchte zur Laufzeit in eine freie 
Flashseite etwas programmieren bzw. diese löschen. Aufgrund der 
Löschzeit von max. 40ms möchte ich aber parallel weiter meine 
Main-Funktion / andere Funktionen und Interrupts abarbeiten und auf ein 
Flash-Interrupt warten, also kein Busywait.

Meine Frage: Ist das so direkt umsetzbar, dass gelöscht/programmiert 
wird und ich parallel andere Programmteile ausführen kann (inkl. 
Interruptroutinen)?

Die Frage stelle ich, weil ich Zweifel aufgrund folgender Textzeilen im 
Datenblatt habe:
1
during a program/erase operation to the Flash memory, any attempt to read the Flash memory will stall the bus. The read operation will proceed correctly once the program/erase operation has completed. This means that code or data fetches cannot be made while a program/erase operation is ongoing.

Ich verstehe darunter, dass ich KEIN Code (Code fetch) aus dem Flash 
holen und ausführen darf, während Löschen/Programmieren. Ist es dann 
notwendig, dass ich mein Linkerfile anpassen muss um den Code in den 
SRAM zu bekommen?

Mein Linkerfile:
1
.isr_vector :
2
  {
3
    . = ALIGN(4);
4
    KEEP(*(.isr_vector)) /* Startup code */
5
    . = ALIGN(4);
6
  } >FLASH
7

8
  /* The program code and other data goes into FLASH */
9
  .text :
10
  {
11
    . = ALIGN(4);
12
    *(.text)           /* .text sections (code) */
13
    *(.text*)          /* .text* sections (code) */
14
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
15
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
16
    *(.glue_7)         /* glue arm to thumb code */
17
    *(.glue_7t)        /* glue thumb to arm code */
18
  *(.eh_frame)
19

20
    KEEP (*(.init))
21
    KEEP (*(.fini))
22

23
    . = ALIGN(4);
24
    _etext = .;        /* define a global symbols at end of code */
25
  } >FLASH




-------------------------------
In diesem Beitrag ist das Problem auch schon geschildert worden:

STM32 : internen Flash löschen/schreiben - CPU stall mit STLINK 
detektieren?
Beitrag "STM32 : internen Flash löschen/schreiben - CPU stall mit STLINK detektieren?"

In diesem Beitrag
https://stackoverflow.com/questions/36244319/why-cant-write-internal-flash-of-same-address-twice

heisst es auch in einem Kommentar:
1
normally you can read one page while writing/erasing another, but in STM32 the entire flash bus stalls, so no no code in flash runs - stalling execution for significant periods (tens of milliseconds)
Gast #5348718
Lesenswert?

Mir gefällt die Speicheraufteilung der STM32 für nichtflüchtige Daten 
generell nicht - der wohl größte Minuspunkt an diesen Controllern. Ich 
verwende daher immer ein externes EEPROM, auch wenn das etwas mehr Platz 
und Geld kostet.

Ansonsten ist das wichtigste gesagt. Aufpassen, dass dein Code keinen 
Flashzugriff benötigt. Mit einem SPI EEPROM passiert mir sowas aber 
nicht ;).
Gast #5348726
Lesenswert?

Eine Ergänzung von mir die meine Zweifel bestärkt, scheint als ob der 
ganze Controller ausser Gefecht gesetzt wird:
https://community.st.com/thread/30821

>wirst Du wie ein Fuchs darauf aufpassen
>muessen , dass Dein Code im Ram nicht irgendetwas aus dem Flash braucht

Sprich: Mit meinem aktuellen Linkerfile (ganzer Code im Flash) kann ich 
mein Vorhaben in die Tonne kloppen?

Ich hab > 5k Code im Flash, aber nur ein 4k RAM. Damit ist also dieses 
"Parallele abarbeiten der main / andere Unterfunktionen" wohl 
Wunschdenken und verdammt kompliziert.


Ich muss also mit sowas arbeiten, richtig?
1
__attribute__( ( section(".data") ) ) void 
2
TIM3_IRQHandler .....


1
Dann hol Dir einen dicken µC
Ich kann die Hardware nicht wechseln.
Gast #5348789
Lesenswert?

Ich hab kurz in die Headerfiles geschaut und konnte nichts finden beim 
M0.

core_cm0.h:
1
typedef struct
2
{
3
  __I  uint32_t CPUID;                   /*!< Offset: 0x000 (R/ )  CPUID Base Register                                   */
4
  __IO uint32_t ICSR;                    /*!< Offset: 0x004 (R/W)  Interrupt Control and State Register                  */
5
       uint32_t RESERVED0;
6
  __IO uint32_t AIRCR;                   /*!< Offset: 0x00C (R/W)  Application Interrupt and Reset Control Register      */
7
  __IO uint32_t SCR;                     /*!< Offset: 0x010 (R/W)  System Control Register                               */
8
  __IO uint32_t CCR;                     /*!< Offset: 0x014 (R/W)  Configuration Control Register                        */
9
       uint32_t RESERVED1;
10
  __IO uint32_t SHP[2];                  /*!< Offset: 0x01C (R/W)  System Handlers Priority Registers. [0] is RESERVED   */
11
  __IO uint32_t SHCSR;                   /*!< Offset: 0x024 (R/W)  System Handler Control and State Register             */
12
} SCB_Type;


core_cm4.h:
1
typedef struct
2
{
3
  __I  uint32_t CPUID;                   /*!< Offset: 0x000 (R/ )  CPUID Base Register                                   */
4
  __IO uint32_t ICSR;                    /*!< Offset: 0x004 (R/W)  Interrupt Control and State Register                  */
5
  __IO uint32_t VTOR;                    /*!< Offset: 0x008 (R/W)  Vector Table Offset Register                          */
6
  __IO uint32_t AIRCR;                   /*!< Offset: 0x00C (R/W)  Application Interrupt and Reset Control Register      */
7
  __IO uint32_t SCR;                     /*!< Offset: 0x010 (R/W)  System Control Register                               */
8
  __IO uint32_t CCR;                     /*!< Offset: 0x014 (R/W)  Configuration Control Register                        */
9
  __IO uint8_t  SHP[12];                 /*!< Offset: 0x018 (R/W)  System Handlers Priority Registers (4-7, 8-11, 12-15) */
10
  __IO uint32_t SHCSR;                   /*!< Offset: 0x024 (R/W)  System Handler Control and State Register             */
11
  __IO uint32_t CFSR;                    /*!< Offset: 0x028 (R/W)  Configurable Fault Status Register                    */
12
  __IO uint32_t HFSR;                    /*!< Offset: 0x02C (R/W)  HardFault Status Register                             */
13
  __IO uint32_t DFSR;                    /*!< Offset: 0x030 (R/W)  Debug Fault Status Register                           */
14
  __IO uint32_t MMFAR;                   /*!< Offset: 0x034 (R/W)  MemManage Fault Address Register                      */
15
  __IO uint32_t BFAR;                    /*!< Offset: 0x038 (R/W)  BusFault Address Register                             */
16
  __IO uint32_t AFSR;                    /*!< Offset: 0x03C (R/W)  Auxiliary Fault Status Register                       */
17
  __I  uint32_t PFR[2];                  /*!< Offset: 0x040 (R/ )  Processor Feature Register                            */
18
  __I  uint32_t DFR;                     /*!< Offset: 0x048 (R/ )  Debug Feature Register                                */
19
  __I  uint32_t ADR;                     /*!< Offset: 0x04C (R/ )  Auxiliary Feature Register                            */
20
  __I  uint32_t MMFR[4];                 /*!< Offset: 0x050 (R/ )  Memory Model Feature Register                         */
21
  __I  uint32_t ISAR[5];                 /*!< Offset: 0x060 (R/ )  Instruction Set Attributes Register                   */
22
       uint32_t RESERVED0[5];
23
  __IO uint32_t CPACR;                   /*!< Offset: 0x088 (R/W)  Coprocessor Access Control Register                   */
24
} SCB_Type;

Anscheinend hat M0 im Vergleich zu M4 die Funktion nicht.



Was ist eigentlich mit diesem Codeausschnitt von ST aus der StdLib?
1
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout)
2
{ 
3
  FLASH_Status status = FLASH_COMPLETE;
4
   
5
  /* Check for the FLASH Status */
6
  status = FLASH_GetStatus();
7
  
8
  /* Wait for a FLASH operation to complete or a TIMEOUT to occur */
9
  while((status == FLASH_BUSY) && (Timeout != 0x00))
10
  {
11
    status = FLASH_GetStatus();
12
    Timeout--;
13
  }
14
  
15
  if(Timeout == 0x00 )
16
  {
17
    status = FLASH_TIMEOUT;
18
  }
19
  /* Return the operation status */
20
  return status;
21
}

Wird die while-Schleife ueberhaupt ausgefuehrt waehrend des Loeschens 
einer Seite und wie?
(Firma: TU Darmstadt) #5348878
Lesenswert?

Jim M. schrieb:
> Du musst aber auch zwingend die Vektor-Tabelle ins RAM schieben, und ich
> weiss grade nicht ob der Cortex-M0 überhaupt das dafür notwendige VTOR
> Register kennt. War das nicht ein optionales Feature...?

Die STM32F0 Serie hat kein VTOR. Um das zu umgehen mappe ich mit SYSCFG 
das Ram an Adresse 0. Dann ist die Interrupttabelle im Ram aktiv.
Gast #5348926
Lesenswert?

stm32user schrieb:
> Ich hab > 5k Code im Flash, aber nur ein 4k RAM.

Kannst du den Code, der parallel zum schreiben läuft, nicht eingrenzen 
sodass nur ein "Notprogramm" in den RAM passen muss? Kannst du einfach 
nach dem Abschalten des Geräts schreiben indem du einen Kondensator als 
Puffer verbaust? Reduziert auch die Flash Abnutzung.
Gast #5349158
Lesenswert?

Danke, für die Antworten.

Ich wünschte ich hätte dieses Dokument früher gefunden und mir die 
Sucharbeit erspart:

AN4808

Writing to non-volatile memory without disrupting code execution
 on microcontrollers of the STM32L0 and STM32L1 Series

http://www.st.com/content/ccc/resource/technical/document/application_note/group0/7c/6a/88/d1/27/04/46/2f/DM00260799/files/DM00260799.pdf/jcr:content/translations/en.DM00260799.pdf

Schade das im Reference Manual dieser ganze Sachverhalt nur in paar 
Sätzen kurz nebenbei erläutert wird.

>Kannst du den Code, der parallel zum schreiben läuft,
>nicht eingrenzen sodass nur ein "Notprogramm" in den RAM passen muss

Das werd ich wohl machen müssen, da ich heute rausgefunden habe, dass 
sogar (hochpriorisierte) Interrupts nicht bearbeitet werden während 
dieser Zeit - was fatal ist ... sogar Watchdogs.

>Wäre es denn in der Zeit möglich auf die Ereignisse mit DMA zu
reagieren?

Ich hatte eher die Idee an eine komplette quasi-Multitaskanwendung 
gedacht, also mit mehreren Tasks ...


Kann mir jemand noch vielleicht verraten, was der Sinn hinter der 
Funktion ist, die ja im Flash ausgefuehrt wird:
1
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout)
Gast #5349295
Lesenswert?

>Wenn ein Not-Programm aus dem RAM ausgeführt wird

Diese ganzen Funktionen wie EraseFlash, ProgramHalfWord, .. SOLLTEN also 
aus dem RAM aufgerufen werden. Weil ja sonst die nächste Programmzeile 
nach dem Funktionsaufruf die CPU Blockade hervorrufen würde.

Schade das diese Empfehlung mit der Auslagerung in den RAM gar nicht im 
Code/StdLib dokumentiert ist. Wenn ich mich irre, bitte Bescheid sagen. 
Alles sehr mager beschrieben

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren