Koncepcja systemu operacyjnego czasu rzeczywistego (RTOS) jest dla większości programistów znana. Istotnym aspektem wykorzystywania go jest tzw. przełączanie kontekstu. Może realizować tę procedurę ręcznie, przeskakując z jednego wątku do drugiego. W poniższym artykule przyjrzymy się, jak zbudować własny minimalny system operacyjny czasu rzeczywistego (MiROS), w którym przełączanie kontekstu można zautomatyzować.
Zaczynamy od dodania nowej grupy do projektu z nagłówkiem i plikami źródłowymi. Następnie stopniowo uzupełniamy szczegóły, przede wszystkim kopiując, wklejając i modyfikując fragmenty kodu, które już posiadamy. Konsekwentnie mając dwa widoki obok siebie, możemy łatwiej zrozumieć interfejs API jądra (interfejs programowania aplikacji) w jednym podglądzie, jednocześnie próbując natychmiast użyć interfejsu API w drugim. W ten sposób łatwiej jest nauczyć się czegoś przydatnego.
Wyjątek PendSV
Przełącznik kontekstu RTOS przechwytuje mechanizm obsługi przerwań, który jest już dostępny w CPU. Konkretnie mówiąc, pod koniec obsługi ISR (takiego jak np. SysTick_Handler pokazanego w filmie powyżej), oszukuje on procesor, aby powrócił do innego wątku niż ten, który został wywłaszczony na początku obchodzenia się z przerwaniem. W tym celu trzeba dodać kod przełączania kontekstu do każdego ISR, co jest niewygodne.
W ARM Cortex-M ISR mogą również zagnieżdżać się (wywłaszczać się nawzajem). Stąd tylko powrót z ostatniego zagnieżdżonego przerwania (do poziomu wątku) powinien przeprowadzić przełączenie kontekstu. Trudność polega na tym, że kolejność wywłaszczania ISR zmienia się dynamicznie w czasie wykonywania, więc generalnie nie wiadomo, który z nich będzie finalny.
Eleganckim rozwiązaniem zastosowanym w praktycznie wszystkich systemach RTOS dla procesorów z rdzeniem ARM Cortex-M jest wykorzystanie tego samego mechanizmu zagnieżdżania przerwań, który stworzył problem. W szczególności Cortex-M zapewnia wyjątek PendSV (Pend Service Call), który można zaprogramować do przeprowadzania przełączania kontekstu i skonfigurować z najniższym priorytetem przerwania (0xFF). Gdy system RTOS wykryje potrzebę zmiany kontekstu, może wstrzymać wyjątek PendSV. Priorytetyzacja przerwań gwarantuje, że PendSV będzie ostatnim ISR uruchomionym tuż przed powrotem do poziomu wątków. Co więcej, NVIC w ARM Cortex-M ma wbudowaną optymalizację sprzętową zwaną: „łańcuchem końcowym”, która eliminuje narzut związany z wychodzeniem z jednego przerwania.
Kodowanie przełącznika kontekstu w assemblerze
Przełącznika kontekstu w PendSV_Handler() nie można zakodować w standardowym C, ponieważ musi on manipulować wskaźnikiem stosu (SP), a także rejestrami procesora push i pop. Jednakże nadal uda się spożytkować do tego klasyczny kompilator C, aby zapewnić dobry punkt wyjścia do programowania w asemblerze. Film powyżej pokazuje, jak zakodować: „przybliżony” algorytm w C, a następnie wykorzystać wygenerowany kod maszynowy w widoku deasemblera.
Jądro MiROS zaczyna po powyższych zmianach nabierać kształtu, ale planowanie jest wciąż wykonywane ręcznie. Kolejne modyfikacje w omawianym oprogramowaniu dotyczyć mają rozszerzenia MiROS RTOS o prostą politykę planowania zwaną round-robin. W ten sposób zaimplementowany zostanie system podziału czasu.
Źródło: https://www.embedded.com/programming-embedded-systems-rtos-automating-the-context-switch/
Zaczynamy od dodania nowej grupy do projektu z nagłówkiem i plikami źródłowymi. Następnie stopniowo uzupełniamy szczegóły, przede wszystkim kopiując, wklejając i modyfikując fragmenty kodu, które już posiadamy. Konsekwentnie mając dwa widoki obok siebie, możemy łatwiej zrozumieć interfejs API jądra (interfejs programowania aplikacji) w jednym podglądzie, jednocześnie próbując natychmiast użyć interfejsu API w drugim. W ten sposób łatwiej jest nauczyć się czegoś przydatnego.
Wyjątek PendSV
Przełącznik kontekstu RTOS przechwytuje mechanizm obsługi przerwań, który jest już dostępny w CPU. Konkretnie mówiąc, pod koniec obsługi ISR (takiego jak np. SysTick_Handler pokazanego w filmie powyżej), oszukuje on procesor, aby powrócił do innego wątku niż ten, który został wywłaszczony na początku obchodzenia się z przerwaniem. W tym celu trzeba dodać kod przełączania kontekstu do każdego ISR, co jest niewygodne.
W ARM Cortex-M ISR mogą również zagnieżdżać się (wywłaszczać się nawzajem). Stąd tylko powrót z ostatniego zagnieżdżonego przerwania (do poziomu wątku) powinien przeprowadzić przełączenie kontekstu. Trudność polega na tym, że kolejność wywłaszczania ISR zmienia się dynamicznie w czasie wykonywania, więc generalnie nie wiadomo, który z nich będzie finalny.
Eleganckim rozwiązaniem zastosowanym w praktycznie wszystkich systemach RTOS dla procesorów z rdzeniem ARM Cortex-M jest wykorzystanie tego samego mechanizmu zagnieżdżania przerwań, który stworzył problem. W szczególności Cortex-M zapewnia wyjątek PendSV (Pend Service Call), który można zaprogramować do przeprowadzania przełączania kontekstu i skonfigurować z najniższym priorytetem przerwania (0xFF). Gdy system RTOS wykryje potrzebę zmiany kontekstu, może wstrzymać wyjątek PendSV. Priorytetyzacja przerwań gwarantuje, że PendSV będzie ostatnim ISR uruchomionym tuż przed powrotem do poziomu wątków. Co więcej, NVIC w ARM Cortex-M ma wbudowaną optymalizację sprzętową zwaną: „łańcuchem końcowym”, która eliminuje narzut związany z wychodzeniem z jednego przerwania.
Kodowanie przełącznika kontekstu w assemblerze
Przełącznika kontekstu w PendSV_Handler() nie można zakodować w standardowym C, ponieważ musi on manipulować wskaźnikiem stosu (SP), a także rejestrami procesora push i pop. Jednakże nadal uda się spożytkować do tego klasyczny kompilator C, aby zapewnić dobry punkt wyjścia do programowania w asemblerze. Film powyżej pokazuje, jak zakodować: „przybliżony” algorytm w C, a następnie wykorzystać wygenerowany kod maszynowy w widoku deasemblera.
Jądro MiROS zaczyna po powyższych zmianach nabierać kształtu, ale planowanie jest wciąż wykonywane ręcznie. Kolejne modyfikacje w omawianym oprogramowaniu dotyczyć mają rozszerzenia MiROS RTOS o prostą politykę planowania zwaną round-robin. W ten sposób zaimplementowany zostanie system podziału czasu.
Źródło: https://www.embedded.com/programming-embedded-systems-rtos-automating-the-context-switch/
Fajne? Ranking DIY
