Mikrokontrolery STM32 - Bezpieczeństwo i stabilność(1).pdf

(430 KB) Pobierz
652389863 UNPDF
PODZESPOŁY
Mikrokontrolery STM32
Bezpieczeństwo i stabilność
aplikacji
Dodatkowe
materiały na CD
Architektura rdzenia Cortex M3 oferuje wiele udogodnień istotnych
przy tworzeniu wbudowanych systemów operacyjnych. Dzięki
przedstawionym w niniejszym artykule mechanizmom implementacja
RTOS jest znacznie uproszczona w stosunku do mikrokontrolerów
wyposażonych w inne rdzenie. Dodatkowym atutem rdzenia Cortex
M3 jest to, że aktualnie już kilku wiodących producentów ma
w swojej ofercie mikrokontrolery z tym rdzeniem, co znakomicie
poprawia przenośność aplikacji. Podane w artykule informacje
dotyczą mikrokontrolerów STM32.
operacyjnego ( OS – Operating system ). System
operacyjny pracuje w trybie uprzywilejowanym,
natomiast program użytkownika uruchamiany
jest przez OS i wykonywany w trybie o ograni-
czonych możliwościach.
Mikrokontroler obsługując przerwanie za-
wsze pracuje w trybie uprzywilejowanym ( PL )
nawet, jeśli w trakcie normalnego wykonywa-
nia programu ustawiony jest tryb użytkownika
( UL ). Te relacje przedstawiono na rys. 2 , nato-
miast rys. 3 przedstawia pracę mikrokontrolera
z włączonym trybem użytkownika. Z ostatniego
rysunku jasno wynika, że rdzeń Cortex pracując
w trybie UL, w czasie wchodzenia od obsługi
przerwania, przełącza się w tryb PL , natomiast
kończąc obsługę przerwania wraca do poprzed-
niego trybu nieuprzywilejowanego (użytkowni-
ka).
Aplikacje pisane z myślą o wykorzystaniu
w systemie operacyjnym działającym na mikro-
kontrolerze określonego producenta z rdzeniem
Cortex M3, mogą być uruchomione na dowol-
nym innym mikrokontrolerze z tym rdzeniem.
Aplikacja korzysta z API, którego zadaniem jest
należyta komunikacja ze sprzętem, stąd tak
duża przenośność w obrębie mikrokontrolerów
z rdzeniem Cortex. Jest to poważny argument
przemawiający za stosowaniem we własnych
rozwiązaniach układów z tym rdzeniem.
Przedstawiony mechanizm znacznie zwięk-
sza stabilność systemu mikroprocesorowego,
ponieważ aplikacja użytkownika, która ze swej
natury posiada większe prawdopodobieństwo
wygenerowania błędnych zachowań, ma ogra-
niczony dostęp do kluczowych zasobów (np.
NVIC i SysTick), a co za tym idzie, nie może
bezpośrednio zachwiać stabilności pracy całego
układu.
Po uruchomieniu mikrokontroler zawsze
rozpoczyna pracę wtrybie uprzywilejowa-
nym, a zatem do zadań systemu operacyjnego
w pierwszej kolejności należy, jeszcze przed uru-
chomieniem aplikacji użytkownika, włączenie
trybu nieuprzywilejowanego – UL .
Przejście ztrybu użytkownika do trybu
uprzywilejowanego nie jest możliwe bezpo-
średnio. Aplikacja uruchomiona wsystemie
operacyjnym nie ma możliwości wyłączenia
trybu użytkownika, ponieważ nie ma dostępu
do specjalnego rejestru kontrolnego CONTROL.
Zapis do niego z poziomu aplikacji jest ignoro-
wany. Zmiany można dokonać tylko podczas
obsługi przerwania, która jest przeprowadzana
w trybie pełnych uprawnień – PL . Wygląd całego
rejestru CONTROL (z wartościami domyślnymi),
wraz z opisem ważnych bitów, przedstawiono
na rys. 4 .
System operacyjny, który zajmuje się przełą-
czaniem kontekstów zadań i nadzorem nad po-
prawnością pracy całego układu, może zmienić
(pracując w przerwaniach) status uprawnień.
Innymi słowy, aby przejść do trybu uprzywile-
jowanego ( PL ) wykonywania programu należy
Tryby pracy rdzenia Cortex
Z punktu widzenia wykonywanego kodu,
mikrokontroler może pracować wykonując
program normalnie ( Thread mode – TM ), albo
może obsługiwać przerwanie ( Handler mode
HM ). Obie sytuacje przedstawiono na rys. 1 .
Takie rozróżnienie ma kluczowe znaczenie dla
aplikacji opartych o systemy operacyjne, spra-
wa ta poruszona jest w dalszej części tego ar-
tykułu.
Rys. 2.
Dodatkowo rozróżnia się dwa poziomy
o różnych prawach dostępu do kluczowych ob-
szarów w przestrzeni adresowej:
– tryb uprzywilejowany ( Privileged level – PL ),
– tryb użytkownika ( Unprivileged/User level
UL ).
Powyższy podział ma uzasadnienie w apli-
kacjach pracujących pod kontrolą systemu
Rys. 1.
114
ELEKTRONIKA PRAKTYCZNA 4/2009
652389863.045.png 652389863.046.png 652389863.047.png 652389863.048.png 652389863.001.png 652389863.002.png 652389863.003.png 652389863.004.png 652389863.005.png 652389863.006.png 652389863.007.png 652389863.008.png 652389863.009.png 652389863.010.png
 
Bezpieczeństwo i stabilność aplikacji
Rys. 6.
Rys. 3.
Rys. 4.
również wskaźnik stosu R13 wskazuje na stos
systemowy MSP tuż po uruchomieniu się mikro-
kontrolera.
Wykorzystanie dwóch stosów dodatkowo
zwiększa odporność całego systemu na błędy,
ponieważ jeśli aplikacja użytkownika zacznie
wykonywać na stosie nieprawidłowe operacje,
to nie wpłynie to negatywnie na stabilność dzia-
łania układu. System operacyjny (jeżeli pracuje
wykorzystując przerwania) ma swój, oddzielny
stos MSP.
Mikrokontroler rozpoczynając obsługę prze-
rwania umieszcza zawartość kluczowych reje-
strów systemowych na stosie, natomiast powra-
cając z obsługi przerwania zdejmuje te wartości,
na powrót zapisując je do rejestrów. Dzięki temu
przerwany proces nie traci informacji i może być
dalej wykonywany bez przeszkód.
Jeśli wykorzystywany jest tylko stos MSP,
to sprawa jest oczywista i mikrokontroler za-
chowuje się tak, jak to opisano powyżej. Wąt-
pliwości rodzą się dopiero w przypadku, gdy
wykorzystywane są oba stosy. W takiej sytuacji,
do przechowywania informacji o przerywanym
procesie wykorzystywany jest stos użytkownika
PSP, natomiast MSP wykorzystywany jest tylko
wewnątrz obsługi przerwania. Zachowanie takie
przedstawiono na rys. 7 .
Gdy mikrokontroler pracuje w trybie uprzy-
wilejowanym, to dostęp (lub zapis) do obydwu
stosów jest możliwy bezpośrednio, za pomocą
instrukcji odczytu (MRS) lub zapisu (MSR) reje-
stru specjalnego. Odczyt i zapis stosu MSP i PSP
w asemblerze może wyglądać następująco:
MRS r0, PSP ; Odczyt PSP do R0
MSR PSP, r0 ; Zapis R0 do PSP
MRS r0, MSP ; Odczyt MSP do R0
MSR MSP, r0 ; Zapis R0 do MSP
Powyższe instrukcje można, rzecz jasna,
zapisać przy użyciu zdefiniowanych przez fir-
mę ST funkcji, które zadeklarowano jako makra
asemblerowe. W takiej sytuacji, odczyt stosu
użytkownika realizowany jest za pomocą nastę-
pującego fragmentu kodu:
Wartość_PSP = __MRS_PSP();
Procedura zapisu na stos PSP natomiast po-
lega na wywołaniu odpowiedniego fragmentu
kodu asemblera:
__MSR_PSP( (u32)NOWA_WARTOSC );
Analogicznie zapis i odczyt stosu MSP:
Rys. 5.
zmienić w funkcji obsługi przerwania ustawie-
nia specjalnego rejestru kontrolnego CONTROL,
czyli wyzerować najmłodszy bit.
tację rejestru wskaźnika stosu. Mikrokontrolery
STM32 są 32–bitowe, a więc stos jest inkremen-
towany (lub dekrementowany) zawsze o 4.
Stos
Stos jest elementem systemu mikroproceso-
rowego, który pozwala przechowywać kluczowe
informacje. Fizycznie jest to obszar w pamięci,
który współpracuje ze specjalnym rejestrem
wskaźnikowym. Na stosie informacje wpisywane
są w sposób liniowy, co oznacza, że aby odczy-
tać zagrzebane dane, należy najpierw ściągnąć
ze stosu dane nowsze ( rys. 5 ).
Z perspektywy programisty, dostęp do stosu
realizowany jest przez użycie polecenia zdejmo-
wania (POP) i wkładania (PUSH) na stos. Po każ-
dej operacji PUSH rejestr wskaźnikowy (w przy-
padku rdzenia Cortex jest to rejestr R13) jest
dekrementowany, czyli wskazuje młodszy adres.
Analogicznie operacja POP powoduje inkremen-
Dwa stosy, MSP i PSP
Rejestr R13 jest wskaźnikiem stosu – ściślej
są to dwa bankowane wskaźniki stosu. W zależ-
ności od ustawienia drugiego bitu w specjalnym
rejestrze kontrolnym CONTROL ( rys. 4 ), może on
wskazywać na stos systemowy MSP ( Main Stack
Pointer ) lub na stos użytkownika PSP ( Process
Stack Pointer ). Skoro wskaźnik stosu jest banko-
wany, to w danej chwili R13 może wskazywać
tylko jeden stos (MSP lub PSP). Przedstawiono
to na rys. 6 . Ponadto, obsługując przerwanie
mikrokontroler zawsze korzysta ze stosu MSP.
Przy okazji opisu trybów pracy mikrokontro-
lerów STM32 pojawiła się wzmianka o tym, że
po uruchomieniu układ zawsze pracuje w trybie
uprzywilejowanym. Konsekwencją tego jest, że
ELEKTRONIKA PRAKTYCZNA 4/2009
115
652389863.011.png 652389863.012.png 652389863.013.png 652389863.014.png 652389863.015.png 652389863.016.png 652389863.017.png 652389863.018.png 652389863.019.png 652389863.020.png
PODZESPOŁY
Wartość_MSP = __MRS_MSP();
__MSR_MSP( (u32)NOWA_WARTOSC );
Zastosowanie powyższych instrukcji umoż-
liwia systemowi operacyjnemu dostęp do stosu
aplikacji (PSP), a więc pełną kontrolę nad pro-
gramem użytkownika.
Tryb użytkownika i PSP
Oddzielne wykorzystanie mechanizmu
poziomów uprzywilejowania i modelu dwóch
stosów jest oczywiście użyteczne, ale znacz-
ne zwiększenie możliwości uzyskuje się przez
połączenie obydwu. Na list. 1 przedstawiono
fragment programu, który jest odpowiedzialny
za włączenie trybu użytkownika i obsługi sto-
su PSP. Gdy te operacje zostaną zrealizowane,
to następuje wywołanie przerwania od wyjątku
systemowego SVC (omówiony w dalszej części
artykułu). Funkcja obsługi przerwania SVC wy-
łącza tryb użytkownika. Wywołanie przerwania
jest zabiegiem koniecznym do zmiany poziomu
uprzywilejowania. Jak było to już napisane, jego
zmiana z trybu użytkownika do trybu uprzywile-
jowanego jest możliwa tylko w funkcji obsługi
przerwania. Ilustruje to przykład funkcji obsługi
przerwania SVC umieszczony poniżej:
void SVCHandler(void)
{
__MSR_CONTROL(0);
}
Instrukcja wewnątrz ciała funkcji ma za za-
danie wpisać do specjalnego rejestru kontrolne-
go wartość 0, co odpowiada wyzerowaniu bitów
CONTROL[0] i CONTROL[1], które odpowiedzial-
ne są za aktualny poziom uprzywilejowania oraz
wykorzystywany stos.
Omawiane możliwości zwiększenia stabil-
ności pracy systemu zaimplementowano przede
wszystkim z myślą o systemach operacyjnych,
jednak nic nie stoi na przeszkodzie, aby wyko-
rzystać je w aplikacjach nie pracujących pod
kontrolą OS.
Rys. 7.
List. 1.
// Inicjalizacja PSP
for(Index = 0; Index < 0x200; Index++)
PSPMem[Index] = 0x00;
__MSR_PSP((u32)PSPMem + 0x200);
// Wybor PSP i trybu uzytkownika
__MSR_CONTROL(0x03);
// Wygenerowanie SVC, powrot to trybu uprzywilejowanego
__SVC();
poprawności przenoszenia aplikacji pomiędzy
rdzeniami ARM7 i Cortex M3.
Wyjątek SVC (System service call)
W dobrze zaprojektowanym systemie ope-
racyjnym, uruchomiona w nim aplikacja nie
może bezpośrednio odwołać się do sprzętu.
Odnosząc to zdanie do konkretnego przypad-
ku można powiedzieć, że aplikacja użytkowni-
ka nie ma możliwości operowania na portach
wejścia/wyjścia inaczej, niż za pośrednictwem
systemu operacyjnego. Takie ograniczenia
w stosunku do aplikacji uruchamianych w sys-
temie operacyjnym mają bardzo istotne zna-
czenie ze względu na ograniczone zaufanie dla
programów użytkownika. W związku z powyż-
szym musi istnieć mechanizm pozwalający na
bezpieczne korzystanie ze sprzętu przez uru-
chomiony w systemie operacyjnym program
użytkownika. Do realizacji tego zadania prze-
znaczono wyjątek SVC.
Wyjątki systemowe
Kontrolę wykonywanych przez STM32 za-
dań znacznie ułatwiają trzy wyjątki systemowe,
dostępne w architekturze Cortex. Docelowym
ich zadaniem jest praca pod kontrolą systemu
operacyjnego, aczkolwiek w aplikacjach bez
OS również można je z doskonałym Skutkiem
wykorzystać do zapewnienia większej kontroli
i stabilności pracy.
Do cyklicznego przełączania kontekstu za-
dań stworzono systemowy, 24–bitowy, timer Sy-
sTick. Jego zadaniem jest generowanie w okre-
ślonych odstępach czasu przerwania, a funkcja
jego obsługi może zajmować się właśnie przełą-
czaniem kontekstu zadań. Bardziej szczegółowo
zasadę działania i sposób konfiguracji timera
SysTick omówiono w EP12/08 .
Pozostałe dwa wyjątki systemowe, to SVC
i PendSV. Pierwsza instrukcja przerwania jest
analogiczna do instrukcji przerwania SWI, którą
miały mikrokontrolery z rdzeniem ARM7. Zmia-
na nazwy wynika z potrzeby zabezpieczenia
Rys. 8.
Rys. 9.
116
ELEKTRONIKA PRAKTYCZNA 4/2009
652389863.021.png 652389863.022.png 652389863.023.png 652389863.024.png 652389863.025.png 652389863.026.png 652389863.027.png 652389863.028.png 652389863.029.png 652389863.030.png 652389863.031.png 652389863.032.png 652389863.033.png 652389863.034.png
Bezpieczeństwo i stabilność aplikacji
Rys. 10.
czenia kontekstu zadań i wywołanie przerwania
PendSV. Dopiero to ostatnie przerwanie wykonu-
je właściwe przełączenie kontekstów tak, że gdy
mikrokontroler powraca do normalnego wyko-
nywania programu, to wówczas podejmowane
już jest wykonywanie następnego zadania.
Jeśli wtrakcie przełączania kontekstów
zadań w funkcji obsługi przerwania PendSV
system zarejestruje inne przerwanie, to przełą-
czanie kontekstów zostaje wstrzymane przez
wywłaszczenie PendSV (pamiętajmy, że jego
priorytet jest najniższy). Cały omawiany proces
przedstawiono na rys. 9 .
PendSV i SysTick
Podobnie ma się sprawa wtedy, gdy system
operacyjny przygotowuje przełączanie konteks-
tów zadań przy pomocy przerwania od timera Sy-
sTick. W takiej sytuacji, zakładając, że przerwanie
od SysTick ma wysoki priorytet, a chwilę wcześ-
niej był obsługiwany jakiś inny wyjątek, nastąpi
wywłaszczenie tego ostatniego na rzecz SysTick.
W związku z tym, że obsługa wywłaszczo-
nego przerwania jest zdecydowanie ważniejsza
od wykonywania uruchomionych w systemie
zadań, to funkcja obsługi przerwania od timera
SysTick (podobnie jak SVC) tylko przygotowuje
system do przełączenia kontekstu zadań i ge-
neruje wyjątek PendSV. Teraz, skoro PendSV ma
najniższy priorytet, mikrokontroler wraca do
obsługi wywłaszczonego wcześniej przerwania.
Gdy czynności z tą obsługą zostaną zakończone,
to oczekujący wyjątek PendSV zaczyna być reali-
zowany, konsekwencją czego jest przełączenie
kontekstu i rozpoczęcie obsługi kolejnego uru-
chomionego w systemie zadania, patrz rys. 10 .
Krzysztof Paprocki
paprocki.krzysztof@gmail.com
Jeśli program użytkownika chce skorzy-
stać ze sprzętu, to musi wywołać funkcję SVC,
a dopiero ta realizuje zadanie z użyciem wyma-
ganego sprzętu. W dużym uproszczeniu przed-
stawiono to na rys. 8 . Dzięki temu wszystkie
operacje z użyciem np. urządzeń peryferyjnych
są pod kontrolą systemu operacyjnego.
Wyjątek PendSV
Jak napisano wcześniej, w najprostszym sys-
temie operacyjnym, za przełączanie kontekstów
uruchomionych zadań odpowiada timer SysTick.
Podczas pracy takiego systemu może powstać
prosty, choć nie zawsze oczywisty problem.
Podczas realizacji zadanie (program użyt-
kownika) może zostać zgłoszone przerwanie,
które wywłaszczy dotychczasowy proces. Jeśli
teraz, czyli w trakcie obsługi zgłoszonego prze-
rwania, timer SysTick przerwie je i system ope-
racyjny rozpocznie przełączanie kontekstów za-
dań, to wychodząc z funkcji obsługi przerwania
od timera SysTick, OS będzie próbował zmusić
mikrokontroler do rozpoczęcia realizacji nowe-
go zadania. Jest to rzecz jasna zachowanie błęd-
ne, ponieważ obsługa pierwszego przerwania
zostanie znacznie opóźniona. Poza tym, może
zostać wygenerowany błąd.
Rozwiązaniem powyższego problemu jest
zastosowanie wyjątku PendSV. Jego progra-
mowalny priorytet jest ustawiany na najniższy
możliwy, dzięki czemu przerwanie to nigdy nie
wywłaszczy innych obsługiwanych przerwań.
Przeanalizujmy teraz zachowanie systemu
z zaimplementowaną obsługą PendSV. Załóżmy,
że zadanie realizowane w systemie nie ma ak-
tualnie nic do zrobienia. Generuje wyjątek SVC,
którego zadaniem jest przygotowanie do przełą-
R
E
K
L
A
M
A
ELEKTRONIKA PRAKTYCZNA 4/2009
117
652389863.035.png 652389863.036.png 652389863.037.png 652389863.038.png 652389863.039.png 652389863.040.png 652389863.041.png 652389863.042.png 652389863.043.png 652389863.044.png
Zgłoś jeśli naruszono regulamin