FreeRTOS STM32: co wywołuje przerwanie xPortPendSVHandler, kontekst, PendSV, scheduler

Pytanie

co powoduje przerwanie xPortPendSVHandler w freertos na stm32

Odpowiedź Sztucznej Inteligencji


Bezpośrednia odpowiedź na pytanie

• 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().

Szczegółowa analiza problemu

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.

Aktualne informacje i trendy

– 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.

Wspierające wyjaśnienia i detale

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.

Aspekty etyczne i prawne

– 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.

Praktyczne wskazówki

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.

Ewentualne zastrzeżenia lub uwagi dodatkowe

– 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.

Sugestie dalszych badań

– 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”.

Krótkie podsumowanie

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.

Oceń odpowiedź:
Zastrzeżenie: Odpowiedzi udzielone przez sztuczną inteligencję (model językowy) mogą być niedokładne i wprowadzające w błąd. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi powinny być zweryfikowane przez użytkownika.