FreeRTOSをVScode環境で動かす①環境構築 の続きです。
概要
以前紹介した記事でFreeRTOSを用いてWindowsPC上で2つのタスクを実行する環境を作成しました。
もともとやりたかった事として、ARMマイコン用ファームの予備検証環境をWindowsで構築する という前提があります。
具体的に何のARMマイコンなの?
STマイクロ製 の ARM cortexF7 シリーズをターゲットとしています。
ここで、
STマイクロのマイコンでRTOSを動かしたい場合は APIを CMSIS_RTOS に合わせておく という制約があります。
今回はCMSIS_RTOSのラッパーを被せていく作業を紹介します。
(CMSIS_RTOSが何者なのかは他のが詳しく紹介記事を書かれているので割愛します)
使用する機能
CMSISの全ての機能を使用するとエラー等が出てきたりして、初心者には苦しい状況になるかと思います。。。
今回は最低限の機能だけ使用して、動作する状況を作っていきたいと思います。
有効にする構造体など
- enum
- osPriority
- osStatus
- typedef
- os_pthread
- TaskHandle_t
- struct
- osThreadDef_t
使用するカーネルコントロール関数
CMSIS_RTOS関数名 | 機能 |
---|---|
osKernelInitialize | スケジューラーの初期化 |
osKernelStart | スケジューラーの起動 |
osKernelRunning | スケジューラーが動作中か否かの判定 |
使用するスレッドマネージメント関数
CMSIS_RTOS関数名 | 機能 |
---|---|
osThreadCreate | スレッドをスケジューラーに登録 |
osThreadGetId | 実行中のスレッドIDの取得 |
osThreadTerminate | スレッドの停止 |
使用するウェイト関連関数
CMSIS_RTOS関数名 | 機能 |
---|---|
osDelay | 指定時間だけ待つ |
osDelayUntil | 基準時刻から指定した時間だけ待つ |
コンフィグヘッダの設定
プライオリティの設定を7にします
# define configMAX_PRIORITIES (7)
理由は cmsis_os.h の中でプライオリティの設定が↓の通り、7段階定義されているため、これに合わせる必要があります。
typedef enum {
osPriorityIdle = -3, ///< priority: idle (lowest)
osPriorityLow = -2, ///< priority: low
osPriorityBelowNormal = -1, ///< priority: below normal
osPriorityNormal = 0, ///< priority: normal (default)
osPriorityAboveNormal = +1, ///< priority: above normal
osPriorityHigh = +2, ///< priority: high
osPriorityRealtime = +3, ///< priority: realtime (highest)
osPriorityError = 0x84 ///< system cannot determine priority or thread has illegal priority
} osPriority;
ユーザー関数
参考までに私の作った関数を紹介します。
- タスクは2つ
- task1は1秒周期でprint
- task1は2秒周期でprint
- 5週したらtask停止
# include "UserTaskDef.h"
# include <stdio.h>
//===================================================================
//
//===================================================================
int main(){
if( 0 == TaskInit() ){
printf("task initialize OK\n");
}else{
printf("task initialize ON!!!!!!\n");
};
/* Start scheduler */
UserTaskStart();
while (1)
{
}
}
# ifndef _DUMMY_TASK_H_
# define _DUMMY_TASK_H_
int TaskInit(void);
void UserTaskStart();
# endif // include gurde
# include "cmsis_os.h"
# include "UserTaskDef.h"
# include <stdio.h>
//--------------------------------------------------------
// static functions
//--------------------------------------------------------
static void dummyTask1Func(void const *arg);
static void dummyTask2Func(void const *arg);
static osThreadId taskHandle1;
static osThreadId taskHandle2;
//--------------------------------------------------------
// task Definition
//--------------------------------------------------------
// Task Name Entry Function Priority instance Stack Size
osThreadDef(dummyTask1 ,dummyTask1Func ,osPriorityHigh , 0 , 0x800);
osThreadDef(dummyTask2 ,dummyTask2Func ,osPriorityHigh , 0 , 0x800);
//--------------------------------------------------------
// task Registration
//--------------------------------------------------------
int TaskInit(void){
if( 1 == osKernelRunning() ){
return 1;//error
}
taskHandle1 = osThreadCreate(osThread(dummyTask1), NULL);
taskHandle2 = osThreadCreate(osThread(dummyTask2), NULL);
return 0;//
}
//--------------------------------------------------------
// task Start
//--------------------------------------------------------
void UserTaskStart(){
if( 0 == osKernelRunning() ){
osKernelStart();
}
}
//--------------------------------------------------------
// task1
//--------------------------------------------------------
static void dummyTask1Func(void const *arg){
uint32_t PreviousWakeTime;
for(int i=0; i<5; i++){
printf("dummy_task1\n");
osDelayUntil(&PreviousWakeTime , 1000);//1秒周期
}
osThreadTerminate(taskHandle1);//タスク停止
}
//--------------------------------------------------------
// task2
//--------------------------------------------------------
static void dummyTask2Func(void const *arg){
uint32_t PreviousWakeTime;
for(int i=0; i<5; i++){
printf(" dummy_task2\n");
osDelayUntil(&PreviousWakeTime , 2000);//2秒周期
}
osThreadTerminate(taskHandle2);
}
//--------------------------------------------------------
//
//--------------------------------------------------------
void vApplicationMallocFailedHook( void ){
/* vApplicationMallocFailedHook() will only be called if
configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
function that will get called if a call to pvPortMalloc() fails.
pvPortMalloc() is called internally by the kernel whenever a task, queue,
timer or semaphore is created. It is also called by various parts of the
demo application. If heap_1.c, heap_2.c or heap_4.c is being used, then the
size of the heap available to pvPortMalloc() is defined by
configTOTAL_HEAP_SIZE in FreeRTOSConfig.h, and the xPortGetFreeHeapSize()
API function can be used to query the size of free heap space that remains
(although it does not provide information on how the remaining heap might be
fragmented). See http://www.freertos.org/a00111.html for more
information. */
vAssertCalled( __LINE__, __FILE__ );
}
動作結果
- 2つのタスクが平行して走っていることが確認できました。
- task1の終了と同時にプログラム全体が停止しました。
- task1の終了後もtask2が5回呼ばれてからプログラム全体が終了を期待していたのですが。。。
今後の課題
ここまでで windowsPC上でFreeRTOSにCMSIS_OSラッパーを被せて動作確認ができました。
次はARMマイコンとのクロスコンパイル環境の構築を目指てみます。