co powoduje przerwanie xPortPendSVHandler w freertos na stm32
• xPortPendSVHandler
jest wywoływany zawsze wtedy, gdy jądro FreeRTOS potrzebuje przełączyć kontekst zadań.
• Przerwanie to nie jest generowane przez peryferia STM32, lecz programowo – poprzez ustawienie bitu PENDSVSET w rejestrze ICSR (SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
).
• Powodem ustawienia tego bitu może być:
– upłynięcie kwantu czasu w przerwaniu SysTick (xTaskIncrementTick()
),
– odblokowanie zadania o wyższym priorytecie (kolejki, semafory, event‑groups),
– jawne wywołanie taskYIELD()
lub portYIELD()
,
– zakończenie ISR‑a, który wywołał portYIELD_FROM_ISR()
/ vPortYieldFromISR()
.
1. Architektura Cortex‑M i wyjątek PendSV
• PendSV (Pendable Service Call, wektor 14) ma z definicji najniższy priorytet; wykonuje się dopiero, gdy NVIC obsłuży wszystkie przerwania o wyższym priorytecie.
• W FreeRTOS PendSV służy wyłącznie do zmiany kontekstu – dzięki temu sama operacja jest odroczona i atomowa względem innych ISR‑ów.
2. Droga wykonania – krok po kroku
1. Zdarzenie (SysTick, API, ISR) powoduje, że scheduler uznaje potrzebę przełączenia zadania.
2. Makro/asembler w portYIELD()
zapisuje do SCB‑ICSR bit PENDSVSET.
3. Po zakończeniu bieżącego przerwania procesor wejdzie do wektora PendSV → xPortPendSVHandler
.
4. Handler w asemblerze:
a) zapisuje rejestry R4‑R11 oraz LR zadania bieżącego na jego stos,
b) zapisuje wskaźnik stosu do TCB,
c) wywołuje vTaskSwitchContext()
(C) wybierając kolejne zadanie,
d) pobiera SP nowego zadania z jego TCB, przywraca R4‑R11, LR,
e) BX LR
wraca z wyjątku – procesor kontynuuje w nowym zadaniu.
3. Typowe miejsca zgłoszenia PendSV
• xTaskIncrementTick()
(wywoływane z SysTick)
• vTaskSwitchContext()
(wywoływane po zmianie list zadań gotowych)
• taskYIELD()
(wywołane przez aplikację)
• portYIELD_FROM_ISR()
(z poziomu ISR‑a peryferyjnego)
4. Powody, dla których FreeRTOS używa PendSV zamiast natychmiastowego skoku
• Spójność: przełączanie nigdy nie przedziela ISR‑ów „ważniejszych” niż RTOS.
• Deterministyczne latencje: czas obsługi kluczowych przerwań nie wydłuża się o kod schedulera.
• Prostota portu: cały kod kontekstu jest w jednym wyjątku, niezależnie od miejsca zgłoszenia.
– W nowych rdzeniach ARM Cortex‑M33/M35P (STM32U5, STM32H5) mechanizm pozostaje identyczny, choć pojawia się podział na domenę Secure/Non‑Secure – PendSV występuje w obu światach, co wymaga zdublowanych handlerów.
– FreeRTOS V11.0.0 (2024 r.) dodał opcjonalne „direct to task notifications 2.0” – również one mogą kończyć się pended‑yield i wyzwoleniem PendSV.
– ST w pakietach CubeFW od 2023 r. włącza domyślnie ochronę przepełnienia stosu (configCHECK_FOR_STACK_OVERFLOW = 2) – jej detekcja następuje właśnie w xPortPendSVHandler
.
Przykładowy kod makra yield (Cortex‑M, plik port.c):
#define portYIELD() __asm volatile ( "dsb" ::: "memory" ); \
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; \
__asm volatile ( "isb" );
Rejestr ICSR
(bit 28 – PENDSVSET) pozwala „zapendować” wyjątek w pełni programowo.
– FreeRTOS jest rozpowszechniany w licencji MIT; modyfikując port lub xPortPendSVHandler
trzeba zachować nagłówki licencyjne.
– W aplikacjach safety‑critical (IEC 61508, ISO 26262) należy udokumentować czasy opóźnień PendSV i poprawną konfigurację priorytetów.
– Błędna konfiguracja priorytetów może prowadzić do dead‑locków ‑ istotne z punktu widzenia certyfikacji funkcjonalnego bezpieczeństwa.
1. Priorytety przerwań
• PendSV
– najniższy (np. 15 w 4‑bitowej implementacji).
• SysTick
– tuż nad PendSV
.
• ISR‑y korzystające z FromISR()
muszą mieć priorytet ≥ configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
.
2. Debugowanie HardFaultów w PendSV
• Włącz uxTaskGetStackHighWaterMark()
na wszystkich zadaniach.
• Sprawdź SCB->CFSR
– często wskazuje na STKERR
(stack error).
3. Trace
• MCU STLink v3 wspiera ETM; z SEGGER SystemView można obserwować dokładne momenty PendSV.
– Brak blokady FPU: jeśli używasz FPU, upewnij się, że port FreeRTOS zapisuje/odtwarza rejestry S0‑S31; w przeciwnym razie PendSV może uszkodzić kontekst.
– Jeżeli kod w ISR‑ach wywołuje długotrwałe funkcje C, zwiększ kwant SysTick lub wyłącz preempcję – zminimalizujesz liczbę wejść do PendSV.
– Dokument ARM® DDI 0403E.B (ARMv7‑M Architecture Reference Manual) – rozdział „Exception model”.
– FreeRTOS Kernel v11 – plik portable/GCC/ARM_CM?.S
.
– ST Application Note AN5324 „Using FreeRTOS on STM32 MCUs” – sekcja dotycząca priorytetów NVIC.
– Blog FreeRTOS: „Understanding PendSV and Context Switching”.
xPortPendSVHandler
jest sercem mechanizmu wielozadaniowości FreeRTOS na STM32. Zgłaszany programowo (PENDSVSET) po każdym zdarzeniu wymagającym zmiany zadania, wykonuje zapis kontekstu, wywołuje scheduler i przywraca kontekst nowego wątku. Dzięki najniższemu priorytetowi gwarantuje spójność i deterministyczne opóźnienia ISR‑ów o wyższym priorytecie. Poprawna konfiguracja priorytetów, wielkości stosów i użycia API ISR jest kluczowa dla stabilności aplikacji.