co robi przerwanie xPortPendSVHandler w freertos stm32
xPortPendSVHandler
to procedura obsługi przerwania PendSV wykorzystywana przez FreeRTOS na STM32 do przełączania kontekstu zadań. Kluczowe punkty
• Najniższy priorytet – nie blokuje krytycznych przerwań.
• Wyzwalane programowo – bit PENDSVSET w SCB->ICSR.
• Obsługuje również rejestry FPU (M4F/M7/M33).
Teoretyczne podstawy
• ARM Cortex‑M sprzętowo zapisuje na stos zadania rejestry R0‑R3, R12, LR, PC, xPSR.
• xPortPendSVHandler
w asemblerze dopisuje brakujące R4‑R11 (i S0‑S15 przy włączonym FPU), aktualizuje wskaźnik stosu w TCB oraz wybiera nowe zadanie (makro portSWITCH_CONTEXT()
).
Przełączanie krok‑po‑kroku
a) Scheduler ustawia SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
b) Po wyjściu z bieżących ISR CPU wejdzie w PendSV:
– PUSH R4‑R11 ( + FPU S16‑S31 gdy aktywne).
– ldr r0, =pxCurrentTCB / str sp, [r0]
– zapisz SP.
– Wywołanie vTaskSwitchContext()
(C) lub makra w asm – wybór zadania.
– ldr sp, [r0] / pop R4‑R11
– przywrócenie nowego SP i rejestrów.
– bx lr
– powrót już w kontekście nowego zadania.
Integracja ze STM32
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
Makra łączą nazwy FreeRTOS z wektorami w startup_stm32*.s
. Domyślne tusze HAL‑a należy usunąć lub przekierować.
FPU i TrustZone
• Gdy configENABLE_FPU
= 1, port zapisuje/odtwarza 32 rejestry S0–S31 (lub do S15 przy lazy stacking).
• Dla MCU z TrustZone (Cortex‑M33) są dwa dodatkowe kroki: zapamiętanie strefy secur./non‑secur. i opcjonalne zapisywanie rejestrów SAU podczas przełączania.
Praktyczne zastosowania
• Preempcja (wypieranie) – zadanie o wyższym priorytecie może przerwać niższe.
• Tryb tick‑less – PendSV działa tak samo, tylko mniej wywołań SysTick.
• FreeRTOS 2024‑LTS optymalizuje kod xPortPendSVHandler
dla Armv8‑M i usprawnia obsługę FPU lazy‑save przy TrustZone.
• Coraz częściej używa się trace hooków (portSWITCHED_OUT_HOOK
, portSWITCHED_IN_HOOK
) do profilowania czasu przełączania bez modyfikacji samego handlera.
• Vendorzy (ST, NXP) dodają akceleratory RTOS‑owe (np. ST H7 ART) – zmniejsza to ilość cykli PendSV.
• PendSV musi mieć NAJNIŻSZY możliwy priorytet (np. 15 przy 4‑bit NVIC), inaczej może dojść do UsageFault po kolizji z innymi ISR.
• Stos zadania powinien mieć zapas (co najmniej +128 B względem obliczonego) – kontekst + wywołania funkcji w przerwaniu.
Przykład – pomiar czasu przełączania:
configUSE_TRACE_FACILITY 1
void portSWITCHED_OUT_HOOK( void )
{
GPIOB->BSRR = GPIO_PIN_0; // Set
}
void portSWITCHED_IN_HOOK( void )
{
GPIOB->BRR = GPIO_PIN_0; // Clear
}
Oscyloskop pokaże szerokość impulsu ~x μs = czas PendSV.
• FreeRTOS pod MIT – obowiązek zachowania licencji w kodzie.
• Błędna konfiguracja stosów/przerwań może skutkować nie‑deterministycznym działaniem urządzenia krytycznego (np. medycznego) – należy przeprowadzać testy jednostkowe i analiza FMEA.
• Ustaw configMAX_SYSCALL_INTERRUPT_PRIORITY
< NVIC priorytet PendSV.
• Dla M4F: jeśli używasz FPU w zadaniu, koniecznie portENABLE_FPU()
lub configENABLE_FPU 1
.
• W diagnostyce HardFaultów sprawdzaj wartość LR = 0xFFFFFFFD lub ‑FE – jeśli przychodzą z PendSV, prawdopodobnie przepełniasz stos.
• Lazy stacking FPU przy intensywnym użyciu zmiennoprzecinkowym może generować nieoczekiwane opóźnienia.
• W portach SMP (np. ESP32) PendSV nie istnieje – tam context switch przebiega inaczej; nie mylić.
• Analiza wpływu różnych algorytmów schedulera (EDF, RBED) na liczbę wywołań PendSV.
• Porównanie czasu przełączania między FreeRTOS a Zephyr‑RTOS na tym samym STM32.
• Eksperyment z Security Extension (ARMv8‑M) – minimalizacja czasu przełączania między strefami.
xPortPendSVHandler
jest „sercem” wielozadaniowości FreeRTOS na STM32. Dzięki najniższemu priorytetowi i programowemu wyzwalaniu gwarantuje bezpieczne, deterministyczne oraz szybkie przełączanie kontekstu zadań. Poprawna konfiguracja priorytetów, rozmiarów stosów i opcji FPU jest krytyczna dla stabilności systemu.