STM32 Probleme durch Flash-Latency?

Gast #4874079
Lesenswert?

Hallo zusammen,
ich betreibe einen STM32F446 bei 180 MHz und hab die Flash-Latency auf 5 
laut Reference-Manual gestellt.

Ich hatte folgendes Problem:
Ich hatte eine Code-Sektion in der ein IRQ deaktiviert sein musste um 
Anomalien zu vermeiden. Während dieser Code ausgeführt wurde, ist ein 
IRQ-Event aufgetreten, also nach enable des entsprechenden IRQs ist 
dieser sofort nach Aktivierung in die entsprechende IRQ gesprungen 
(siehe Pseudo-Code).
In der IRQ wurde das IRQ-enable-Bit deaktiviert (wird durch eine 
Variablen-Abfrage nur einmal ausgeführt und kann danach nicht mehr 
wiederholt deaktiviert werden).

Falls ich nun im normalen Programmablauf direkt nach der 
IRQ-Aktivierung-Befehlszeile eine Zeile eingefügt habe, in welcher auf 
dasselbe Register zugegriffen wird, wurde der IRQ einfach wieder 
aktiviert (scheinbar wurde einfach der alte Registerwert vorher vom 
Prefetch-Controller gesichert und hergenommen) und der IRQ in einer 
Dauerschleife ausgeführt:

1
Regulärer Programmablauf:
2

3
irgendein Code;
4
Register = enable-IRQ;
5
              <----------|
6
Register = enable-IRQ;   |
7
                         |
8
                         |
9
                hier tritt IRQ auf

Fehlt die zweite Zeile mit enable-IRQ funktioniert alles ohne Probleme.
Hattet ihr schonmal ähnliche Probleme?
Gast #4874094
Lesenswert?

Noch eine Ergänzung...
Es ist egal was man bei der zweiten Registeroperation macht.
Mit "Register" ist hier das selbe Register gemeint.
1
Regulärer Programmablauf in welcher IRQ-Event auftritt;
2

3
Register = enable-IRQ;
4
              <---------------|
5
Register = Registerzugriff;   |
6
                              |
7
                              |
8
                    hier tritt IRQ auf
#4874421
Lesenswert?

STM32-Programmierer schrieb im Beitrag #4874079:
> dasselbe Register zugegriffen wird, wurde der IRQ einfach wieder
> aktiviert (scheinbar wurde einfach der alte Registerwert vorher vom
> Prefetch-Controller gesichert und hergenommen) und der IRQ in einer
> Dauerschleife ausgeführt:

Klingt komisch. Zeig mal den Source Code, und eventuell auch den 
Assembler der vom Compiler erzeugt wurde.

Normales Read-Modify-Write hat genau Deine beobachteten Probleme,
eventuell können LDREX/STREX oder Bitband Zugriffe das auflösen.

Falls die Latenz nicht zu wichtig ist, könnte man auch einfach ein paar 
Takte lang die Interrupts global sperren.
#4874434
Lesenswert?

Keine Ahnung ob das hier der Fall ist (zu viel Beschreibung von 
Pseudocode statt echtem Code!), aber:
Wenn der Interrupt von irgendeiner Peripherie ausgelöst wird, ist darauf 
zu achten, daß der entsprechende Interrupt-Request nicht gerade als 
allerletztes vor dem Return aus der Interruptroutine zurückgesetzt wird!
Wegen des geringeren Taktes der Peripherie ist das nämlich nach dem 
Rücksprung evtl. noch gar nicht wirksam, so daß derselbe Interrupt 
nochmal ausgelöst wird.
Gast #4881532
Lesenswert?

Hallo zusammen,

erstmal Danke für die Antworten!
Hab das Problem inzwischen entdeckt...
Es war in der Tat ein Read-Modify-Write-Problem.
Dieses wird leider nicht atomar ausgeführt (waren 5 Assembler-Befehle) 
und es kam zu den oben genannten Problemen.
Gast #4882461
Lesenswert?

Interrupts beim Cortex global zu sperren ist sofort wirksam. Interrupts 
über die Enablefunktion der Perpherie zu sperren braucht ein besonders 
Vorgehen, da im NCVIC der Interrupt schon gesetzt sein kann. Wie man da 
richtig vorgeht,  musst Du nachlesen....
(Firma: keine) #4883398
Lesenswert?

STM32-Programmierer schrieb im Beitrag #4881532:
> Hallo zusammen,
>
> erstmal Danke für die Antworten!
> Hab das Problem inzwischen entdeckt...
> Es war in der Tat ein Read-Modify-Write-Problem.
> Dieses wird leider nicht atomar ausgeführt (waren 5 Assembler-Befehle)
> und es kam zu den oben genannten Problemen.

Zwei mögliche Lösungsansätze:

1. Wenn es bei dem R-M-W Problem darum geht, dass verschiedene bits in 
demselben byte durch Racekonditionen nicht synchron gehalten werden, 
hilft bit banding (da kannst Du atomar Operationen auf einzelnen bits 
ausführen, ohne die Anderen Bits im selben byte mit zu beeinträchtigen).

2. Möglicherweise kommst du mit einer ISB weiter (wenn ein 
Interruptrequest bereits einen prefetch cycle in die Pipeline abgelegt 
hat, bevor das Unterdrücken gesetzt worden ist).

Details findest Du in Kapiteln 2 bzw. 6 meines Buches, oder natürlich 
direkt in der ARM Doku.

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