-
Notifications
You must be signed in to change notification settings - Fork 0
FreeRTOS blink example
Ha sikeresen feltelepítettük a fejlesztőkörnyezetet, és le tudtuk fordítani az üres projektet, akkor nekiláthatunk tartalommal megtölteni. Először egy egyszerű led-villogtató alkalmazást mutatunk be UART kommunikációval, majd kiegészítjük PMW generálással, amivel később a quadcopter motorjait tudjuk vezérleni. A projekt konfigurálása során beállítottuk, hogy a konfigurátor állítsa be nekünk a FreeRTOS-t. Ez egy ingyenes, beágyazott rendszerekben előszeretettel használt operációs rendszer. Segítségével task-okat hozhatunk létre, akár csak a tanfolyamon használt NXT-n, és ezeket az operációs rendszer felváltva, kvázi párhuzamosan futtatja, vagy a megadott időzítésekkel ütemezi. Az operációs rendszer tehát megkönnyíti a programozás menetét, illetve biztonságosabbá teszi programunkat. A FreeRTOS-nek saját függvénykönyvtára van, melyek segítségével létrehozhatunk a task-okokat, ütemezhetjük, vagy kinyírhatjuk azokat. A példák során megismerkedünk ezen függvények használatával. Ezen kívül szükségünk van az STM HAL (Hardware Abstraction Layer) ismeretére. Ez szintén egy függvénykönyvtár mellyel a mikrokontroller perifériáit (GPIO, UART, PWM, I2C, TIMER) kezelhetjük. Kezdetben bonyolultnak tűnhetnek, de ha az alapokkal megismerkedtünk később sokkal könnyebb a fejlesztés menete.
A Cube legenerálta nekünk a beállításainknak megfelelő kezdeti kódot. Ez remélhetőleg mindenkinek úgy néz ki, mint itt a repo-ban. Minket most főleg az Src/main.c file fog érdekelni. Mint láthatjuk egy elég terjedelmes kódot generált le a program. Ebben főként a perifériákat inicializálja, valamint felkonfigurálja az OS-t. Minden perifériának külön inicializáló függvénye van, melyeknek az implementációja a kód végén található. Ami most számunkra érdekes, az az operációs rendszer függvényei. A kód futása a megszokott main()-ben kezdődik. Itt találhatjuk a példa task inicializáló sorait:
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
Ez inicializál egy task-ot defaultTask
néven, Normál prioritással. A task-ot egy függvény fogja megvalósítani, amit StartDefaultTask
néven implementálunk (ahhoz hogy itt ne kapjunk hibát, a függvényt korábban dekraláni kell).
Ezután elindítja az ütemezőt osKernelStart();
, ami vált a task-ok között. Most csak egy task-unk lesz, így az ütemező valójában nem fog váltogatni, de ettől még el kell indítani, hogy működjönk a program.
Ettől a ponttól fogva az ütemező dönti el, hogy mi fusson, és soha nem tér vissza a fent meghívott függvény.
Már csak implementálunk kell a task-ot jelentő függvényt. Ezt már a kód végén el is kezdte nekünk a Cube. Keressük meg a következő részt:
void StartDefaultTask(void const * argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for(;;)
{
osDelay(1);
}
/* USER CODE END 5 */
}
A task-oknak mindig végtelen ciklust kell tartalmazniuk, magától az ütemező nem ciklikusan hajtja végre a programot. Itt megírhatjuk a villogtató programot. Most lesz szükségünk a korábban említett HAL könyvtárra. Ennek a megfelelő elemei már include-olva vannak, ha az eddigiek alapján készítettük el a projektet. A GPIO (digitális ki/bement) kezelésére az alábbi függvényeink vannak:
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
Nekünk most a HAL_GPIO_TogglePin
függvényre lesz szükségünk. A teljes dokumentációt itt találjuk. Így a villogtató ciklus így néz ki (a define-okat is a Cube hozta létre):
for(;;)
{
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
osDelay(500);
}