ISIX-RTOS – przykład 1 – sterowanie LED w wątkach
| Opis systemu ISIX-RTOS i jego funkcji opublikowaliśmy w artykule „Mini system operacyjny dla STM32 – wprowadzenie”, który można przeczytać tu. |
Pokażemy w jaki sposób stworzyć kod startowy dla systemu oraz dwa nowe zadania (wątki). Prezentowany program umożliwia sterowanie diodami LED zamontowanymi w zestawie STM32Butterflyw następujący sposób: dioda LED1 miga cyklicznie, natomiast dioda LED2 jest włączana i wyłączana po wciśnięciu manipulatora joysticka.
Start systemu zrealizowany jest w bibliotece lib-stm32, odpowiedzialnej za inicjalizację systemu zgodnie z wymogami ANSI C/C++. Przed wywołaniem globalnych konstruktorów obiektów wywoływana jest funkcja __external_startup() następnie funkcja główna main().
Kod funkcji __external_startup pokazano na list. 1.
List. 1. Kod funkcji __external_startup
void __external_startup(void)
{
//Initialize system perhipheral
uc_periph_setup();
//1 bit for preemtion priority
nvic_priority_group(NVIC_PriorityGroup_1);
//System priorities
nvic_set_priority(PendSV_IRQn,1,0x7);
//System priorities
nvic_set_priority(SVCall_IRQn,1,0x7);
//Set timer priority
nvic_set_priority(SysTick_IRQn,1,0x7);
//Initialize isix
isix::isix_init(ISIX_NUM_PRIORITIES);
//Setup the systick timer
timer_setup();
}
Funkcja uc_periph_setup() jest odpowiedzialna za konfigurację kontrolera pamięci oraz ustawienie pętli PLL mikrokontrolera tak, aby rdzeń był taktowany z maksymalną dozwoloną częstotliwością (72 MHz). Następnie konfigurowany jest kontroler przerwań NVIC, w trybie jeden bit priorytetu przerwania oraz trzy bity podpriorytetu. Dodatkowo ustalono priorytet przerwań używanych przez system ISIX-RTOS (PENDSV, SVC, SYSTICK) na najniższy możliwy. Kolejna wywoływana funkcja isix_init jest odpowiedzialna za inicjalizacje systemu, jako argument przyjmuję ona liczbę priorytetów wykorzystywanych przez scheduler. Liczba dostępnych priorytetów jest dowolna (ograniczona wielkością dostępnej pamięci), w praktyce wystarcza najczęściej kilkanaście priorytetów. Następnie wywoływana jest funkcjatimer_setup(), która jest odpowiedzialna za konfigurację przerwania zegarowego SYSTICK, tak aby było ono generowane z częstotliwością ISIX_HZ. Wartość tej częstotliwości w przykładzie ustalono na 1000 Hz. Po wykonaniu funkcji startowej oraz wywołaniu konstruktorów globalnych, wykonywana jest funkcja główna main() (list. 2).
List. 2. Główna funkcja main()
//App main entry point
int main()
{
//The blinker class
static app::ledblink led_blinker;
//The ledkey class
static app::ledkey led_key;
//Start the isix scheduler
isix::isix_start_scheduler();
}
Najpierw jest tworzony obiekt klasy ledblink, której zadaniem jest cykliczne miganie diodą LED1 (patrz dokumentacja zestawu STM32Butterfly), następnie obiekt klasy ledkey, której zadaniem jest cykliczna zmiana stanu diody LED2 w wyniku naciśnięcia manipulatora joysticka. Następnie jest wywoływana funkcja isix_start_scheduler(), która powoduje uruchomienie szeregowania zadań przez system ISIX-RTOS. Obie klasy (ledblink, ledkey) dziedziczą z klasy bazowej isix::task_base. Każda klasa dziedzicząca z klasy task_base musi implementować metodę wirtualną main(), która jest wykonywana w oddzielnym wątku tworzonym przez konstruktor klasy task_base. Implementację klasy blinker odpowiedzialnej za cykliczne miganie diodą LED1 przedstawiono na list. 3.
List. 3. Implementacja klasy blinker
/* ------------------------------- */
//Default constructor, construct base object
ledblink::ledblink():task_base( STACK_SIZE, TASK_PRIO)
{
//Enable PE in APB2
RCC->APB2ENR |= RCC_APB2Periph_GPIOE;
io_config(LED_PORT,LED_PIN, GPIO_MODE_10MHZ, GPIO_CNF_GPIO_PP);
}
/* ---------------------------- */
//Main task/thread function
void ledblink::main()
{
while(true)
{
//Enable LED
io_clr( LED_PORT, LED_PIN );
//Wait time
isix::isix_wait( isix::isix_ms2tick( BLINK_TIME) );
//Disable LED
io_set( LED_PORT, LED_PIN );
//Wait time
isix::isix_wait( isix::isix_ms2tick( BLINK_TIME) );
}
}
W liście inicjalizacyjnej konstruktora wywoływany jest konstruktor klasy bazowej task_base(), który jest odpowiedzialny za tworzenie nowego zadania (wątku). Jako argumenty przyjmuje on rozmiar stosu zadania oraz jego priorytet. W konstruktorze jest także konfigurowany port GPIO PE.14, do którego w zestawie STM32Butterfly podłączono diodę LED1. Wątek realizowany jest w pętli nieskończonej metody wirtualnej main(). Wątek zmienia stan LED, a następnie wywołuje funkcję isix_wait(), której zadaniem jest uśpienie wątku na czas określony przez stałą BLINK_TIME.
Najistotniejsze fragmenty implementacji klasyledkey przedstawiono na list. 4.
List. 4. Fragmenty implementacji klasyledkey
/Default constructor initialize GPIO and var
ledkey::ledkey():task_base( STACK_SIZE,TASK_PRIO), is_enabled(false)
{
//Enable PE in APB2
RCC->APB2ENR |= RCC_APB2Periph_GPIOE;
io_config(LED_PORT,LED_PIN, GPIO_MODE_10MHZ, GPIO_CNF_GPIO_PP);
}
/* ------------------------------------ */
void ledkey::main()
{
//Last key state
bool p_state = true;
//Task/thread main loop
while(true)
{
//Change state on rising edge
if(io_get(KEY_PORT, KEY_PIN) && !p_state)
{
is_enabled = !is_enabled;
}
//Get previous state
p_state = io_get(KEY_PORT, KEY_PIN);
//If enabled change state
if(is_enabled) io_clr( LED_PORT, LED_PIN );
else io_set( LED_PORT, LED_PIN );
//Wait short time
isix::isix_wait( isix::isix_ms2tick( DELAY_TIME) );
}
}
Podobnie jak poprzednio w liście inicjalizacyjnej jest wywoływany konstruktor klasy bazowej oraz inicjalizowane są porty GPIO. Wątek odpowiedzialny za wspomniane wcześniej zadanie zrealizowany jest przez metodę wirtualną main() w pętli nieskończonej. Zmiana stanu diody LED2 następuje w momencie puszczenia manipulatora joysticka (zbocze narastające na wejściu mikrokontrolera). Detekcję zrealizowano w sposób klasyczny przez porównanie bieżącego stanu klawisza ze stanem poprzednim. W momencie, gdy wykryjemy zbocze jest zmieniany stan zmiennej 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 usypia bieżący wątek na krótki czas, tak aby wyeliminować drgania zestyków.

Mikrochip zmniejsza o połowę moc potrzebną do pomiaru zużycia energii przez urządzenia przenośne
NCS-PX215P-J2-I
Złącza przewód-płytka z serii MAS-CON od firmy Pancon 



