2011
12.27

V předchozím článku byl ve stručnosti popsán vývojový kit PIC32 Ethernet Starter Kit (dále jen PIC32 ESK) a uveřejněn jednoduchý projekt s blikáním LED diod. Nyní Vám představíme projekt se stejnou funkcí provedenou ale tentokrát operačním systémem reálného času FreeRTOS.

1. Proč operační systém

Existují dvě řešení jak navrhnout softwarovou strukturu požadovaného zařízení. Tedy s operačním systémem, nebo bez něj. Implementace zařízení bez operačního systému má své výhody, jako například cena, nebo menší náročnost na výpočetní výkon, ale u složitějších úloh převažují jeho nevýhody. To může být například nízká variabilita a špatná přenositelnost kódu. Často navíc sama řízená úloha přímo vybízí k použití více-vláknového zpracování, což je jasný signál pro použití operačního sytému. Ulehčíme si tak práci využitím předem připravených synchronizačních nástrojů pro synchronizaci úloh a hardwarových přerušení. Využití operačního systému dává smysl u složitějších úloh, kde předpokládáme častou modifikaci programu.

Použití operačního systému nám tedy umožňuje zavedení multitaskingu. Multitasking je schopnost operačního systému provádět zdánlivě  několik úloh (vláken) současně. Jádro operačního systému velmi rychle střídá na mikrokontroléru běžící vlákna (tzv. změna kontextu), takže uživatel má dojem, že běží současně. O přidělování výpočetního času mikrokontroléru jednotlivým vláknům se stará tzv. scheduler neboli plánovač. Ten na základě priorit přidělených jednotlivým vláknům přepíná kontext a tím spouští a pozastavuje běh jednotlivých vláken.

2. Proč operační systém reálného času

Definic pro operační systém reálného času je několik – zde odkazuji na článek na wikipedii - Operační systém reálného času. Pro lehčí pochopení stručně uvedu, že operační systém reálného času (dále jen RTOS) je například takový, který se snaží dodržet minimální latence při reakci na událost.

3. Proč FreeRTOS

Operační systém FreeRTOS je v současnosti nejuniverzálnějším embedded RTOS systémem podporujícím až 30 různých architektur procesorů. Téměř celý operační systém je napsán v programovacím jazyce C, pouze několik funkcí je vytvořeno v assembleru. Podporuje jak plně preemptivní tak kooperativní zpracován vláken.

  • Dostupné demonstrační aplikace pro různé architektury
  • Je šířen pod GNU licencí (nemusí se publikovat zdrojové kódy)
  • Je zdarma, volně stažitelný
  • Nízké nároky na výpočetní výkon, dá se aplikovat i na 8bitové mikroprocesory.
  • Podpora až 30 různých architektur

Pro komunikaci mezi vlákny, nebo mezi přerušeními a vlákny poskytuje komunikační a synchronizační nástroje typu fronta zpráv, (binární) semafor a mutex. Více na stránkách FreeRTOS.

4. Vzorová aplikace

V předchozím článku PIC32 Ethernet Starter Kit – PIC32 ESK (DM320004) jsme si ukázali jednoduchou aplikaci pro blikání LED diod. Zde si ukážeme aplikaci se stejnou funkčností realizovanou vlákny ve FreeRTOS. Do projektu byly přidány soubory s jádrem FreeRTOS. Pro hlubší pochopení opět doporučuji stránky FreeRTOS, kde je také podrobný help k jednotlivým funkcím FreeRTOS spolu s ukázkami kódu.

Základní nastavení FreeRTOS jádra se provádí v souboru FreeRTOSConfig.h, popis a význam jednotlivých definic opět naleznete na stránkách výrobce FreeRTOS.

Nejprve je nutné zadeklarovat jednotlivá vlákna. Vlákna jsou v podstatě funkce tak, jak je vidíme na následujícím textu:

/* Deklarace vlaken */
static void vLed1Task( void *pvParameters );
static void vLed2Task( void *pvParameters );
static void vLed3Task( void *pvParameters );
txt

Po deklaraci vláken následuje definice priorit pro jednotlivá vlákna:

/* Nastaveni priorit vytvarenych vlaken */
#define LED1priority			(tskIDLE_PRIORITY + 2)
#define LED2priority			(tskIDLE_PRIORITY + 2)
#define LED3priority			(tskIDLE_PRIORITY + 1)

Definice tskIDLE_PRIORITY nám určuje referenční hodnotu priority tzv. IDLE vlákna. IDLE vlákno je voláno tehdy, pokud není připraveno žádné jiné vlákno s větší prioritou než má právě IDLE vlákno. Naše vlákna mají všechny větší prioritu než IDLE a dále vidíme, že vlákno s LED1 a LED2 má větší prioritu než vlákno s LED3. Proč tomu tak je pochopíme později.

Následuje samotná funkce main, která vypadá takto:

/* Main application entry point */
int main(void) {

  /* Inicializace Hardware */
  HardwareSetup();

  /* Vytvoreni vlaken. */
  xTaskCreate(vLed1Task,"led1",configMINIMAL_STACK_SIZE,NULL,LED1priority...
  xTaskCreate(vLed2Task,"led2",configMINIMAL_STACK_SIZE,NULL,LED2priority...
  xTaskCreate(vLed3Task,"led3",configMINIMAL_STACK_SIZE,NULL,LED3priority...

  /* Start scheduleru */
  vTaskStartScheduler();
  /* Will only reach here if there is insufficient heap available to start the scheduler. */
}
txt

A teď samotná vlákna. První vlákno je vlákno s LED1:

// ------------- Vlakno s Led1 ------------ //
static void vLed1Task( void *pvParameters ){
  for( ;; ){
    LED1 = ~LED1;
    vTaskDelay(500 / portTICK_RATE_MS);
  }
}
/*------------------------------------------*/
txt

Druhé vlákno s LED2:

// ------------- Vlakno s Led2 ------------ //
static void vLed2Task( void *pvParameters ){
  for( ;; ){
    LED2 = ~LED2;
    vTaskDelay(50 / portTICK_RATE_MS);
  }
}
/*------------------------------------------*/
txt

A nakonec třetí vlákno s LED3:

// ------------- Vlakno s Led3 ------------- //
static void vLed3Task( void *pvParameters ){
  for( ;; ){
    LED3 = !BUTTON3;
  }
}
/*------------------------------------------*/
txt

Z uvedeného vyplývá, že z vláken se nikdy „nevyskočí“, neboť jsou v nekonečné smyčce for( ;; ). Dále vidíme, že ve vlákně LED1 a LED2 je použita funkce vTaskDelay(timeValue). Tato funkce má za úkol uspat vlákno a znovu jej probudit až za čas určený parametrem timeValue. Hodnota (50 / portTICK_RATE_MS) tedy znamená, že vlákno se probudí a bude pokračovat v běhu až za dalších 50 ms (perioda 10 Hz). Obdobně tomu bude i ve vlákně LED1, kde je doba „spánku“ nastavena na 500 ms (perioda 1 Hz). V době, kdy tedy vlákna LED1 a LED2 spí, se vykonává třetí vlákno LED3. Vidíme, že vykonávání není blokováno žádným zpožděním, ale v tomto případě je blokováno nastavením priority vlákna LED3priority. Jinak řečeno, pokud se přihlásí o běh vlákna LED1 nebo LED2, vlákno LED3 bude pozastaveno na dobu, dokud se vykonávání LED1 nebo LED2 opět neuspí.

Pokud bychom chtěli libovolné vlákno zakázat a tím pozastavit jeho běh, stačí zakomentovat příslušný řádek xTaskCreate(…

5. Závěr

Článek popisuje implementaci FreeRTOS embedded operačního systému reálného času a jeho názorné použití v jednoduché aplikaci blikání LED diod. Z pohledu programátora se jeví zdrojový kód rozdělený do tří vláken lépe čitelný, neboť každá z LED diod má své vlastní vlákno a tyto vlákna jsou mezi sebou navzájem nezávislé.

Tak, jak je již na našich stránkách zvykem, poskytujeme registrovaným uživatelům možnost stáhnout si tento vzorový projekt se všemi potřebnými zdrojovými soubory a vyzkoušet si tak FreeRTOS na svém vývojovém kitu.

  FirstFreeRTOSProjectPIC32.zip (362,1 KiB, 45 hits)

Zatím pouze 1 komentář

Přidej komentář.
  1. avatar

    Test

Musíte být přihlášen pro vkládání příspěvků.