ISIX RTOS EP 06 2010


programy
Dodatkowe materiały
ISIX-RTOS
na CD i FTP
Podstawy obsługi wątków
Dodatkowe informacje na temat systemu ISIX-RTOS oraz
Artykuł poświęcony prostemu systemowi
prezentacje multimedialne są dostępne na stronie www.stm32.eu
operacyjnemu ISIX-RTOS, jaki opublikowaliśmy
w EP3/2010, zainteresował wielu Czytelników.
Wracamy więc do tego tematu, pokazując przykład
jego praktycznego wykorzystania z zestawem
STM32Butterfly  popularną platformą sprzętową
propagowaną przez firmę STMIcroelectronics
podczas warsztatów STM32TechDays. Pokażemy
sposób przygotowania kodu startowego dla
mikrokontrolera oraz dwa wątki, które będą
wykorzystane do sterowania diodami LED.
Start systemu zrealizowany jest w bibliotece lib-stm32, odpo-
wiedzialnej za inicjalizację systemu zgodnie z wymogami ANSI C/
C++. Przed wywołaniem globalnych konstruktorów obiektów wy- używanych przez system ISIX-RTOS (PENDSV, SVC, SYSTICK) na
woływana jest funkcja __external_startup(), następnie funkcja głów- najniższy możliwy. Kolejna wywoływana funkcja isix_init jest od-
na main(). powiedzialna za inicjalizację systemu, jako argument przyjmuję
ona liczbę priorytetów wykorzystywanych przez scheduler. Licz-
List. 1. Kod funkcji __external_startup
ba dostępnych priorytetów jest dowolna (ograniczona wielkością
void __external_startup(void)
dostępnej pamięci), w praktyce wystarcza najczęściej kilkanaście
{
priorytetów. Następnie wywoływana jest funkcja timer_setup(),
//Initialize system perhipheral
która jest odpowiedzialna za konfigurację przerwania zegarowego
uc_periph_setup();
SYSTICK, tak aby było ono generowane z częstotliwością ISIX_HZ.
//1 bit for preemtion priority
Wartość tej częstotliwości w przykładzie ustalono na 1000 Hz. Po
nvic_priority_group(NVIC_PriorityGroup_1);
wykonaniu funkcji startowej oraz wywołaniu konstruktorów glo-
//System priorities
balnych, wykonywana jest funkcja główna main() (list. 2).
nvic_set_priority(PendSV_IRQn,1,0x7);
Najpierw jest tworzony obiekt klasy ledblink, której zadaniem
//System priorities
jest cykliczne miganie diodą LED1 (patrz dokumentacja zestawu
nvic_set_priority(SVCall_IRQn,1,0x7);
STM32Butterfly), następnie obiekt klasy ledkey, której zadaniem
//Set timer priority
jest cykliczna zmiana stanu diody LED2 w wyniku naciśnię-
nvic_set_priority(SysTick_IRQn,1,0x7);
cia manipulatora joysticka. Następnie jest wywoływana funkcja
//Initialize isix
isix::isix_init(ISIX_NUM_PRIORITIES);
List. 3. Implementacja klasy blinker
//Setup the systick timer
/* ------------------------------------------------------
timer_setup();
------------ */
}
//Default constructor, construct base object
ledblink::ledblink():task_base(STACK_SIZE,TASK_PRIO)
{
//Enable PE in APB2
Kod funkcji __external_startup pokazano na list. 1.
RCC->APB2ENR |= RCC_APB2Periph_GPIOE;
Funkcja uc_periph_setup() jest też odpowiedzialna za konfi- io_config(LED_PORT,LED_PIN,GPIO_MODE_10MHZ,GPIO_
CNF_GPIO_PP);
gurację kontrolera pamięci oraz ustawienie pętli PLL mikrokon-
}
trolera tak, aby rdzeń był taktowany z maksymalną dozwoloną
częstotliwością (72 MHz). Następnie konfigurowany jest kontro-
/* ------------------------------------------------------
------------ */
ler przerwań NVIC, w trybie jeden bit priorytetu przerwania oraz
//Main task/thread function
trzy bity podpriorytetu. Dodatkowo ustalono priorytet przerwań
void ledblink::main()
{
while(true)
List. 2. główna funkcja main() {
//Enable LED
//App main entry point
io_clr( LED_PORT, LED_PIN );
int main()
//Wait time
{
isix::isix_wait( isix::isix_
//The blinker class
ms2tick(BLINK_TIME) );
static app::ledblink led_blinker;
//Disable LED
//The ledkey class
io_set( LED_PORT, LED_PIN );
static app::ledkey led_key;
//Wait time
isix::isix_wait( isix::isix_
//Start the isix scheduler
ms2tick(BLINK_TIME) );
isix::isix_start_scheduler();
}
} }
86 ELEKTRONIKA PRAKTYCZNA 6/2010
Podstawy obsługi wątków
List. 4. Fragmenty implementacji klasy ledkey
odpowiedzialnej za cykliczne miganie diodą LED1 przedstawiono
/Default constructor initialize GPIO and var
na list. 3.
ledkey::ledkey():task_base(STACK_SIZE,TASK_PRIO),is_
enabled(false)
W liście inicjalizacyjnej konstruktora wywoływany jest kon-
{
//Enable PE in APB2 struktor klasy bazowej task_base(), który jest odpowiedzialny za
RCC->APB2ENR |= RCC_APB2Periph_GPIOE;
tworzenie nowego zadania (wątku). Jako argumenty przyjmuje on
io_config(LED_PORT,LED_PIN,GPIO_MODE_10MHZ,GPIO_
CNF_GPIO_PP);
rozmiar stosu zadania oraz jego priorytet. W konstruktorze jest
}
także konfigurowany port GPIO PE.14, do którego w zestawie STM-
/* ------------------------------------------------------
32Butterfly podłączono diodę LED1. Wątek realizowany jest w pę-
------------ */
tli nieskończonej metody wirtualnej main(). Wątek zmienia stan
void ledkey::main()
{
LED, a następnie wywołuje funkcję isix_wait(), której zadaniem
//Last key state
bool p_state = true; jest uśpienie wątku na czas określony przez stałą BLINK_TIME.
//Task/thread main loop
Najistotniejsze fragmenty implementacji klasy ledkey przed-
while(true)
{
stawiono na list. 4.
//Change state on rising edge
Podobnie jak poprzednio w liście inicjalizacyjnej jest wywo-
if(io_get(KEY_PORT, KEY_PIN) && !p_
state)
ływany konstruktor klasy bazowej oraz inicjalizowane są porty
{
GPIO. Wątek odpowiedzialny za wspomniane wcześniej zadanie
is_enabled = !is_enabled;
}
zrealizowany jest przez metodę wirtualną main() w pętli nieskoń-
//Get previous state
p_state = io_get(KEY_PORT, KEY_PIN); czonej. Zmiana stanu diody LED2 następuje w momencie pusz-
//If enabled change state
czenia manipulatora joysticka (zbocze narastające na wejściu mi-
if(is_enabled) io_clr( LED_PORT, LED_PIN
);
krokontrolera). Detekcję zrealizowano w sposób klasyczny przez
else io_set( LED_PORT, LED_PIN );
porównanie bieżącego stanu klawisza ze stanem poprzednim.
//Wait short time
isix::isix_wait( isix::isix_
W momencie, gdy wykryjemy zbocze, jest zmieniany stan zmien-
ms2tick(DELAY_TIME) );
nej is_enabled, następnie na podstawie stanu zmiennej dioda
}
}
LED2 jest włączana lub wyłączana. Na koniec cyklu wywoływana
jest funkcja isix_wait() z argumentem DELAY_TIME (25 ms), która
isix_start_scheduler(), która powoduje uruchomienie szeregowa- usypia bieżący wątek na krótki czas, tak aby wyeliminować drga-
nia zadań przez system ISIX-RTOS. Obie klasy (ledblink, ledkey) nia zestyków.
dziedziczą z klasy bazowej isix::task_base. Każda klasa dziedzi- Lucjan Bryndza, Ep
cząca z klasy task_base musi implementować metodę wirtualną lucck@boff.pl
main(), która jest wykonywana w oddzielnym wątku tworzonym
przez konstruktor klasy task_base. Implementację klasy blinker
R E K L A M A
ELEKTRONIKA PRAKTYCZNA 6/2010 87


Wyszukiwarka