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.