Forum: Mikrocontroller und Digitale Elektronik CPU operating modes auf dem STM32


von leo (Gast)


Lesenswert?

Hallo, ich habe derzeit eine Applikation auf dem STM32 am Laufen.
Nun möchte ich wenn ein Interrupt ausgelöst wird, die anderen Interrupt 
sperren und kurz vor dem Verlassen des Interrupts sollen alle Interrupts 
wieder freigegeben werden. Ein RTOS verwende ich nicht.
1
__istate_t get_int_state = __get_interrupt_state();
2
3
__istate_t get_primask = __get_PRIMASK();

Wenn ich diese beiden Codezeilen in meiner Applikation (in der while(1)) 
ausführe, dann erhalte ich immer den Wert 0.
Muss ich womöglich den STM32 in einem anderen Modus bringen ? Wenn ja, 
was müsste ich da genau tun ?

von (prx) A. K. (prx)


Lesenswert?

Komplett falscher Ansatz. Dass Cortex-M Cores bereits über ein voll 
entwickeltes Prioritäts-Management verfügen ist dir entgangen?

Du musst lediglich den exklusiven Interrupts eine höhere Priorität als 
den anderen zuweisen und schon kommt während der Ausführung des Handlers 
kein anderer Interrupt mehr durch.

von leo (Gast)


Lesenswert?

Vielen Dank für deinen Beitrag. Ich habe auf meinem System mehrere 
Interrupts: Can, Usart, Ethernet, Systick.

Müsste ich dann für jeden Interrupt in der NVIC_InitStructure die 
Priorität festlegen ?
1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

von leo (Gast)


Lesenswert?

Folgende Prioritäten habe ich vergeben:

Usart:
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1

Can:
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2

Ethernet:
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3

Es ändert sich nichts. get_int_state ist immer 0.

von (prx) A. K. (prx)


Lesenswert?

PRIMASK hat nichts mit Interrupt-Prioritäten zu tun, sondern ist ein 
globales Interrupt-Enable-Flag. Genau das benötigst du bei einem korrekt 
konfigurierten Prioritätsschema jedoch nicht.

von leo (Gast)


Lesenswert?

Guten Morgen,

danke für deinen Post. Wie konnte so ein Prioritätsschema 
sinnvollerweise aussehen ?
Ich habe mir vlgendes überlegt. Dem SysTick würde ich die Priorität 0 in 
der Prioritätsgruppe 0 vergeben.
Die anderen Interrupts würde ich der Prioritätsgruppe 1 zuordnen. Die 
USART bekäme die Priorität 0, CAN die Priorität 1 sowie ETHERNET die 
Priorität 2.

Die Intrinsics Funktionen __get_interrupt_state, __set_interrupt_state, 
__enable_interrupt und __disable_interrupt werden überhaupt nicht mehr 
benötigt ?

von (prx) A. K. (prx)


Lesenswert?

Ja, sie werden im laufenden System typischerweise nicht benötigt.

Bei den Prioritäten drauf achten dass hier - wie auch sonst oft in der 
Branche - die kleinere Zahl der höheren Priorität entspricht. Dem 
Systick als System-Timer maximale Priorität zuzuordnen ist etwas 
ungewöhnlich.

von leo (Gast)


Lesenswert?

Der SysTick hat die Priorität 15.
1
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
2
{
3
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
4
5
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
6
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
7
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
8
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
9
                   SysTick_CTRL_TICKINT_Msk   |
10
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
11
  return (0);                                                  /* Function successful */
12
}

Das ist aber eine niedrige Priorität. Macht es nicht Sinn die Priorität 
für den SysTick auf 0 zu setzen ?

Würdest du alle Interrupts in eine Gruppe packen ?

von leo (Gast)


Lesenswert?

Folgendes Prioritätsschema ist auf meiner Applikation vorhanden:

SysTick -> Priorität=15 Prioritätsgruppe=0
USART2 -> Priorität=0  Prioritätsgruppe=5
CAN1 -> Priorität=0  Prioritätsgruppe=5
Ethernet Link Ext. Interrupt -> Priorität=0 Prioritätsgruppe=5

Diese Werte habe ich mit folgenden Funktionen aushgelesen:

GetPriority = NVIC_GetPriority(InterruptNummer);
GetPriorityGrouping = NVIC_GetPriorityGrouping();

Wenn ich die Prioritäten und die Prioritätsgruppen ändern will, müsste 
ich folgende Funktionen verwenden:
NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
NVIC_SetPriorityGrouping(uint32_t PriorityGroup)

Mir ist noch folgendes unklar. In der Interruptinitialisierung der 
USART2 wird keine Prioritätsgruppe gesetzt. Warum lese ich den Wert 5 
mit der Funktion NVIC_GetPriorityGrouping aus ?
1
/* Enable the USART2 Interrupt */
2
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
3
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
4
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
5
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
6
NVIC_Init(&NVIC_InitStructure);

von (prx) A. K. (prx)


Lesenswert?

leo schrieb:
> SysTick -> Priorität=15 Prioritätsgruppe=0
> USART2 -> Priorität=0  Prioritätsgruppe=5
> CAN1 -> Priorität=0  Prioritätsgruppe=5

Da im CM3 nur 4 Bits für Prio+Gruppe zur Verfügung stehen wird das 
schwierig.

> Würdest du alle Interrupts in eine Gruppe packen ?

Es ergibt Sinn, Interrupts die sich gegenseitig ausschliessen sollen, in 
eine Gruppe zu packen. Andernfalls ergibt das meist wenig Sinn.

> Macht es nicht Sinn die Priorität für den SysTick auf 0 zu setzen ?

Weshalb? Für welche Rolle hast du den Systick vorgesehen?

von leo (Gast)


Lesenswert?

Der SysTick wird für den Scheduler eingesetzt. Wie kannst du dir das 
erklären, warum für die USART2, CAN, ETHERNET die Prioritätsgruppe 5 
verwendet wird ? Ich kann nirgends eine Zuweisung finden.

von (prx) A. K. (prx)


Lesenswert?

leo schrieb:
> NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1

Du solltest für einen aktuellen Einstieg für die NVIC-Steuerung die 
CMSIS-Funktionen verwenden, nicht die steinalten NVIC-Funktionen der 
ST-Library, die seit CMSIS obsolet sind.

von leo (Gast)


Lesenswert?

Mit den folgenden beiden Funktionen, können die Einstellungen 
vorgenommen werden.
1
  
2
NVIC_SetPriority(USART2_IRQn,1);  // Priorität=1
3
NVIC_SetPriorityGrouping(0);      // Prioritätsgruppe=0

Benötigt man prinzipiell die Funktion NVIC_EncodePriority(0, 1, 0); ?

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?


von (prx) A. K. (prx)


Lesenswert?

leo schrieb:
> Benötigt man prinzipiell die Funktion NVIC_EncodePriority(0, 1, 0); ?

Ansichtssache. Einer mags so, der andere anders:
Beitrag "CMSIS und die Interrupt-Prioritäten"

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.