STM32F2xx: Global Interrupt abfragen

Gast #3335698
Lesenswert?

Hallo!

Ich entwickle gerade FW für einen STM32F2xx von ST unter IAR.
Hier würde ich gerne CriticalSection-Funktionen verwenden.
Bei dem gefundenen Beispielcode wird der Global Interrupt mit
1
asm("CPSID i");
 deaktiviert und mit
1
asm("CPSIE i");
 wieder aktiviert.

Bei einem STM32F0XX sah der Beispielcode anders aus:
1
#define IRQ_FLAG        0x80
2
#define FIQ_FLAG        0x40
3

4
inline __arm uint32 EntrCritSection(void)
5
{
6
unsigned long tmp;
7
  tmp = __get_CPSR();
8
  __set_CPSR(tmp | IRQ_FLAG);
9
  return(tmp);
10
}
11

12
inline __arm void ExtCritSection(uint32 Save)
13
{
14
unsigned long tmp;
15
  tmp = __get_CPSR();
16
  __set_CPSR(tmp & (Save | ~IRQ_FLAG));
17
}
18

19
inline __arm uint32 EntrCritSectionFiq(void)
20
{
21
unsigned long tmp;
22
  tmp = __get_CPSR();
23
  __set_CPSR(tmp | (IRQ_FLAG | FIQ_FLAG));
24
  return(tmp);
25
}
26

27
inline __arm void ExtCritSectionFiq(uint32 Save)
28
{
29
unsigned long tmp;
30
  tmp = __get_CPSR();
31
  __set_CPSR(tmp & (Save | ~(IRQ_FLAG | FIQ_FLAG)));
32
}

Mich interessiert das "__get_CPSR".
Wenn mein Prozessor STM32F2xx gibt es die Befehle __get_CPSR und 
__set_CPSR nicht.

Gibt es eine Alternative zum __get_CPSR?

Danke und Grüß
Michael
#3335756
Lesenswert?

Michael schrieb:
> Das kommt aus einem Code-Beispiel von IAR direkt zu meinem
> STM32F2xx-Prozessor.

Nur ist die Version vom Core in beiden Fällen gleich. Der Kram für die 
Core-Version unterhalb von 7 bezieht sich auf ARM7/ARM9, kann also mit 
dem STM32F0xx eigentlich auch nicht funktioniert haben.

Such mal in der CMSIS, was dort der richtige oder auch nicht richtige 
aber von dir gesuchte Weg ist. Ein sinnvoller Weg geht beispielsweise 
über das BASEPRI/BASEPRI_MAX Register.
Gast #3335794
Lesenswert?

A. K. schrieb:
> Such mal in der CMSIS, ...

Guter Tipp, aber dazu muss ich mich bei ARM registrieren.
und keine Ahnung wie oft ich jetzt da Captcha eingeben habe (Mit 
Großbuchstaben oder Kleinbuchstaben; nur die die Buchstaben ohne Zahlen 
(da characters)) ... Er sagt jedes mal, dass ich das Captcha falsch 
eingegeben habe. Und die Audio-Funktion geht auch nicht!

A. K. schrieb:
> Und was stört dich an den dort enthaltenen Makros?
Also das Makro ist ja nicht das Problem, sondern "die Art" der 
umgesetzten CriticalSections....
Gast #3335822
Lesenswert?

A. K. schrieb:
> Weshalb? Das Include setzt diese Makros für ARMv7 in CPSID/E Befehle um,
> genau wie es sein soll.

Eben! - Die Makros bewirken nur, dass dann das da steht:
1
inline void EntrCritSection(void)
2
{
3
  if(CriticalSecCntr == 0)
4
  {
5
    asm("CPSID i");
6
  }
7
  // avoid lost of one count in case of simultaneously calling from both places
8
  ++CriticalSecCntr;
9
}
bzw.
1
inline void ExtCritSection(void)
2
{
3
  if(--CriticalSecCntr == 0)
4
  {
5
    asm("CPSIE i");
6
  }
7
}

Und da steht auch das in meinem ersten Beitrag erwähnte
1
asm("CPSIE i");
Ich will aber zusätzlich noch wissen, ob das Interrupt Flag beim 
Betreten der Critical Section -also vorher- schon gesetzt war, oder 
nicht.

Ich bräuchte also so was:
#define IRQ_FLAG        0x80
1
uint32 flag = __get_CPSR() & IRQ_FLAG;
Gast #3335963
Lesenswert?

Für mich gibt es nicht nur einen Typus "sicheren Bereich", sondern drei:
1. Innerhalb des sicheren Bereiches sind Globale Interrupts nicht 
erlaubt => Critical Section
2. Innerhalb des sicheren Bereiches in dem Globale Interrupts aktiv sein 
müssen => Mutex
Für das Betreten und Verlassen einer Mutex ist ein Sicherer Bereich von 
Typ 1 = Critical Section von Nöten, in der das jeweilige 
Mutex-Locked-Flag gesetzt wird.
3. Innerhalb des sicheren Bereiches sind Globale Interrupts nur 
zugelassen, wenn sie es vorher auch waren
Gast #3335969
Lesenswert?

Typ 3 wird durch die Critical Section auch erfüllt.

Was nicht geklärt ist:
Was ist, wenn innerhalb eines sicheren Bereichs von Typ 1 einer von Typ 
2 aufgerufen wird.
Dann passt es beim nächsten Aufruf einer Typ 3 Zone nicht mehr!
#3336185
Lesenswert?

Wenn ausschliesslich der obige Code im Include für Critical Sections 
genutzt wird, dann dürfen die Critical Sections auch schachteln, da der 
Code einen Level-Counter mitführt.

EntrCritSection => CriticalSecCntr==1 / CPSID I
EntrCritSection => CriticalSecCntr==2 / nix
ExtCritSection  => CriticalSecCntr==1 / nix
ExtCritSection  => CriticalSecCntr==0 / CPSIE I
#3336198
Lesenswert?

Michael schrieb:
> Für das Betreten und Verlassen einer Mutex ist ein Sicherer Bereich von
> Typ 1 = Critical Section von Nöten

Das ist ein Weg. Und zwar der bei den Cortex M schlechtere.

Der bessere trennt die Interrupt-Prioritäten in zwei Bereiche, 
unterschieden durch die RTOS-Priorität N. Interrupts, die RTOS nutzen, 
erhalten eine geringere Priorität als das RTOS in seinen kritischen 
Bereichen. Interrupts ohne RTOS Nutzung können einen höhere Priorität 
haben (funktionell betrachtet, nicht numerisch).

Eine kritische Sektion, die alle funktional geringeren Interrupts als K 
ausschliesst, kann man völlig ohne CPSID/E so definieren:
  enter: var old = BASEPRI
         BASEPRI_MAX = K
  ...
  exit:  BASEPRI = old
Eine Zuweisung an BASEPRI_MAX hat die Eigenheit, die Priorität nie zu 
verschlechtern, daher ist dieses Prinzip risikofrei anwendbar.

Für RTOS-Lockouts, wie beispielsweise für eine Mutex, lässt sich die 
kritische Sektion also mit ebendieser BASEPRI Aktion implementieren, mit 
K=N.

Vorteil: Zeitkritische Interrupts, die keine RTOS APIs verwenden, werden 
vom RTOS nicht blockiert, also auch nicht verzögert.
Gast #3336987
Lesenswert?

Sagen wir es mal so. Ich weiß, dass der Cortex Priolevels hat.
Aber die benötige mich nicht und deswegen weiß ich darüber auch nicht 
viel, weil ich mich damit nicht befasst habe.
Der Grund ist, dass die FW parallel auch auf einem Prozessor läuft, der 
wesentlich schwächer als ein Cortex ist und diese Funktionen nicht hat.
Deswegen muss ich bei einer portierbaren Holzhammer-'Methode bleiben.

Mit RTOS, insbesondere OS, hat das alles recht wenig zu tun, aber mit 
Nested Interrupts.
#3337019
Lesenswert?

Michael schrieb:
> Mit RTOS, insbesondere OS, hat das alles recht wenig zu tun, aber mit
> Nested Interrupts.

In welcher Umgebung gibt es Mutexe? In Interrupts ist eine Mutex 
ziemlich sinnarm und eine kritische Sektion zum Schutz vor Interrupts 
ist keine Mutex. Und die Mutext hattest du eingeführt.

Also: Wo hast du ein Problem? Die Makros/Funktionen im Include 
jedenfalls führen - richtig eingesetzt - nicht zu einem Problem.
Gast #3338822
Lesenswert?

Entweder hat er ein Problem mit seinem eigentlichen Systementwurf (weil 
er seine Algorithmen so organisiert hat, daß mehrere Instanzen zugleich 
schreibend auf Daten zugreifen) oder er hat Spaß daran, etwas zu 
verwenden, was er an anderer Stelle schon mal benutzt hatte:

Michael schrieb:
> Hier würde ich gerne CriticalSection-Funktionen verwenden.

Gerne! Und wozu genau? Ich würde die Sache so aufbauen, daß man 
derartiges überhaupt nicht benötigt. Wer das nicht kann oder will, 
stolpert später drüber.

W.S.

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