Hallo Mikrocontroller- Gemeinde,
ich habe eine Frage zu den Prioritäten des STM32F103.
Irgendwie ist das nämlich net so ganz sauber dokumentiert, wie ich
finde.
Hier mal so, wie ich das Ganze verstehe:
- Die Prioritäten sind in Haupt- und Unterpriorität unterteilbar
- es werden hierfür 4 Bits verwendet
- es gibt 5 Gruppen, die diese 4 Bits für die Unterteilung in Haupt und
Unterpriorität nutzten (z.B. 1 Bit für Haupt, 3 Bit für Unterprio.
usw.).
- ein Interrupt mit einer höheren Priorität darf eine niedrigere
Unterbrechen --> die höhere wird dann zunächst abgearbeitet, bevor in
die niedrige zurück gekehrt wird. Hier eine frage: Wie schaut's da mit
der Verwaltung des Stack's aus? Normal muss ich mich ja nich darum
kümmern, weil der CORTEX M3 das selbst erledigt (Hardware) - aber bei
Unterbrechung einer ISR auch?
- kann ich dem Systick die oberste Priorität zuordnen, so dass diese
alle
anderen ISR's unterbrechen darf? Ich hab's nämlich noch
nicht hnbekommen :) Verwendet habe ich hierfür:
NVIC_SetPriority(SysTick_IRQn,
NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
Vielleicht findet sich ja ein STM - Erfahrener, der da behilflich sein
kann ;)
Danke & viele Grüße
Ich selbst versuche nested Interrupts zu vermeiden, wann immer möglich,
aber ich glaube, dieser Abschnitt aus dem Programmers Manual könnte Dir
weiterhelfen:
---
To increase priority control in systems with interrupts, the NVIC
supports priority grouping.
This divides each interrupt priority register entry into two fields:
● An upper field that defines the group priority
● A lower field that defines a subpriority within the group.
Only the group priority determines preemption of interrupt exceptions.
When the processor is executing an interrupt exception handler, another
interrupt with the same group priority as the interrupt being handled
does not preempt the handler.
---
Folglich müsste der Systick in Deinem Fall denn eben der einzige sein,
der eine höhere group priority besitzt.
Und um den Stack musst Du Dich nur insofern kümmern, dass da genügend
vorhanden ist...
Gruß,
Hannes
Eigentlich möchte ich auch keine Nested Interrupts verwenden.
Möchte aber eigentlich den Systick nutzen, um zu bestimmten Zeiten (jede
ms) einen Wert über SPI auszugeben. Daher sollte dieser in der Lage
sein, ggf. auch andere Interrupts zu unterbrechen... Na mal schauen, wie
ich das hingekomme :)
Dank Dir' auf jeden Fall für die Antwort!
Michael schrieb:> - ein Interrupt mit einer höheren Priorität darf eine niedrigere> Unterbrechen --> die höhere wird dann zunächst abgearbeitet, bevor in> die niedrige zurück gekehrt wird. Hier eine frage: Wie schaut's da mit> der Verwaltung des Stack's aus?
Nicht deine Sorge, der Stack muss nur gross genug sein.
Grad beim CM3 spricht rein garnix gegen IRQ-Nesting, der ist ja
regelrecht dafür gebaut.
> - kann ich dem Systick die oberste Priorität zuordnen, so dass diese> alle anderen ISR's unterbrechen darf?
Ja. Die Prio der System Exceptions, wozu auch der Systick zählt, ist
übrigens von Haus aus schon 0, also maximal.
Allerdings fehlt mit in deinem Posting irgendwie eine konkrete Frage,
eine die sich beantworten liesse ohne dabei ganze Bücher zu schreiben.
Du schreibst ja nicht einmal, was funktioniert oder nicht funktioniert
hat und wo dein Problem liegt.
Das Thema Gruppierung von Interrupts würde ich erst einmal grosszügig
ignorieren.
Michael schrieb:> Irgendwie ist das nämlich net so ganz sauber dokumentiert, wie ich> finde.
Was hast du denn an Doku bisher aufgetrieben?
Bischen was steht im "Insiders Guide" drin, aber m.E. zu knapp. Deutlich
mehr steht im "The Definitive Guide to the ARM Cortex-M3" von Joseph
Yiu. Eine sinnvolle Lektüre wie ich meine.
ST reicht im Cortex-M3 Programming Manual effektiv nur die Core-Doku von
ARM durch, die haben den CM3 ja nicht selbst erfunden. Und diese Doku
ist nicht wirklich als Anleitung geschrieben.
Ohne grouping wird's nicht gehen - nur ein Interrupt mit höherer group
priority (in der Lib "preemption priority" genannt) kann einen anderen
Interrupt unterbrechen.
Habe gerade mal meinen Code modifiziert und bin jetzt auch mit dem
Systick etwas ratlos - mit RTC hingegen funktioniert es. Hier meine NVIC
Config:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_SetPriority(SysTick_IRQn,
NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
In den TIM2 Irq Handler habe ich ein while(1); eingebaut. Der RTC
interrupt unterbricht dieses und wird ausgeführt, der Systick hingegen
nicht... strange... irgendwelche Ideen?
Hannes S. schrieb:> Ohne grouping wird's nicht gehen - nur ein Interrupt mit höherer group> priority (in der Lib "preemption priority" genannt) kann einen anderen> Interrupt unterbrechen.
Was andersrum gemeint. Wenn nichts konkret dagegen spricht, dann kann
man alle 4 Bits als preeption priority konfigurieren - ist wohl auch
default.
Zu dem CMSIS Kram kann ich nicht viel sagen, der ist mir zu umständlich.
Ist der Systick Interrupt überhaupt eingeschaltet? Die bisherigen
Schnipsel enthalten dazu nichts.
Hab's gerade rausgefunden, woran es lag: Der Aufruf von SysTick_Config()
ist der übeltäter, denn hier wird offensichtlich nochmal in der Lib an
der Priotrity gedreht. Wenn man DANACH NVIC_SetPriority() aufruft, dann
tut es wie es soll. Also in meinem Fall:
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
SysTick_Config(0x9000);
NVIC_SetPriority(SysTick_IRQn,
NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
Jau, und die Frage was der Default-Mode ist: Meiner Meinung nach ist
nach dem Reset kein Grouping aktiviert also NVIC_PriorityGroup_0.
Allerdings hatte ich das in meinem Code auch immer explizit drinstehen.
Aber Dein Vorschlag alle Bits zur preemption zu nutzen sollte natürlich
auch gangbar sein (NVIC_PriorityGroup_4).
Hannes S. schrieb:> Jau, und die Frage was der Default-Mode ist: Meiner Meinung nach ist> nach dem Reset kein Grouping aktiviert also NVIC_PriorityGroup_0.
Das Feld im Register SCB_AIRCR ist ab Reset 0, ein Wert der für 7
Preemption-Bits und ein Subprio-Bit steht und bei 4 Prio-Bits daher
überhaupt nicht definiert ist ;-).
Faktisch heisst das wahrscheinlich, dass ab Reset alle 4 Bits als
Preemption-Bits verstanden werden, man aber saubererweise was anderes
(z.B. 3) reinschreiben sollte. Man aber jedenfalls aber nicht das
reinschreiben sollte, was vorher drinstand.
Die Priorität für den Systick auf 15 gesetzt. Also die niedrigste!
Wenn die Systick Priorität verändert werden soll, muss dies also nach
dem SysTick_Config() Aufruf erfolgen!
Michael schrieb:> Beim Aufruf der Funktion SysTick_Config() wird ...Die Priorität für den> Systick auf 15 gesetzt. Also die niedrigste!
Na ob das wohl so von den Erschaffern gewollt ist ...
Der eine oder andere von Euch kennt vielleicht diesen Thread?
Beitrag "CMSIS und die Interrupt-Prioritäten"
Lutz schrieb:> Na ob das wohl so von den Erschaffern gewollt ist ...
Anscheinend. Ich habe dieses Verhalten vor etwa zwei Jahren bei Keil
bemängelt und bekam die Antwort, dass man in den meisten RTOS
Situationen den SysTick mit niedrigster Priorität belegen möchte. CMSIS
bediene hier den wahrscheinlichsten Fall.
Wenn es denn wenigstens dokumentiert wäre...
Gruß
Marcus