以前PSoC5LPとPSoC Creater4.2にFreeRTOSを実装した記事「FreeRTOSをPSoC5LPで使う」と同様に、MPLAB XでdsPIC33CK256MP503にFreeRTOSを実装した覚書です。
使用アイテムは現時点で最新版、FreeRTOSV202012.00(カーネルはV10.4.3)、MPLAB X5.45です。
目次
- RTOSソースとプロジェクト&ソースを一つのフォルダにまとめる
- port.cなど一部MicrochipのDemoを利用
- フォルダ構成とプロジェクトのファイルツリー
- FreeRTOSConfig.hを編集
- タスクスイッチャのタイマーはT1。現行ソースと被るのでソースを変更
- 動作確認Lチカソース
- ワーニングが1つでる・・・このままでも良いようだ
- 最後にヒープ残量確認
RTOSソースとプロジェクト&ソースを一つのフォルダにまとめる
PSoC5LPでは、DemoにならってRTOSカーネルを「Source」という共通フォルダを用意しプロジェクトと別の場所に格納し、各プロジェクトから参照する方式で、プロジェクト毎に格納し編集するのはFreeRTOSConfig.hのみでした。このためフォルダ位置関係が変わるとコンパイラエラーとなります。またカーネルのバージョンアップでは古いプロジェクトも影響を受けてしまうリスクがあります。
RTOS本体の容量はさほど大きくないので、今回は1つのフォルダにプロジェクトとカーネルソース/dsPIC関数をまとめて格納してみました。デメリットはプロジェクトごとにカーネルソースが存在することで容量が少し増えることです。
これにより、フォルダ依存関係が全部相対とできるため、上位フォルダごと移動・コピーすることで再利用性を犠牲にしても可搬性は良くなる、と思います。
port.cなど一部MicrochipのDemoを利用
AWSのFreeRTOS本体では、最新版でもport.cなどハードウエア依存モジュールがdsPIC33Cに対応していないので(33Eや33Fは対応)、Microchipで用意されたデモからいただきました。DLはこのページから”FreeRTOS”のリンクを経てGitHubから「freeRTOS-PIC24-dsPIC-PIC32MM-master.zip」を入手しました。カーネルは最新ではなくV9.0.0です。
フォルダ構成とプロジェクトのファイルツリー
\SourceフォルダはRTOS本体です。コルーチンなど今回の用途で不要なファイルは削除してシェイプしました。この段階で\Sourceフォルダサイズは約1.2MBです。
続いて、MPLAB X内でのファイル関係。自分のソースはモザイクにしてあります。
プロジェクト内のファイルパスも設定しておく → 結構重要
FreeRTOSConfig.hを編集
各パラメータを編集します。主な編集は、コルーチン廃止、タスクスイッチ周期を合わせたことです。設定項目のみ抜粋します。なお、Demoにあったスタックオーバーフローチェックはうまくコンパイラできなかったので削除しました。
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include "xc.h"
#define configUSE_PREEMPTION 1 // プリエンプティブマルチタスク
#define configUSE_IDLE_HOOK 0 // IdleHook no use
#define configUSE_TICK_HOOK 0
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configCPU_CLOCK_HZ ( ( unsigned long ) 50000000 ) /* Fosc / 2 */
#define configMAX_PRIORITIES ( 4 )
#define configMINIMAL_STACK_SIZE ( 105 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) 5120 )
#define configMAX_TASK_NAME_LEN ( 4 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 1
#define configIDLE_SHOULD_YIELD 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
#define configUSE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 0
#define configUSE_ALTERNATIVE_API 0
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_RECURSIVE_MUTEXES 0
#define configQUEUE_REGISTRY_SIZE 0
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_MALLOC_FAILED_HOOK 0
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 0
#define INCLUDE_vTaskDelay 1
#define configKERNEL_INTERRUPT_PRIORITY 0x01
#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t) ( ( ( TickType_t) ( xTimeInMs ) )) * ((( TickType_t) configTICK_RATE_HZ ) / ( TickType_t) 1000 ))
#endif /* FREERTOS_CONFIG_H */
タスクスイッチャのタイマーはT1。現行ソースと被るのでソースを変更
dsPIC33CのFreeRTOSはT1を使用しています。今回用いた自分のソースもT1を周期割り込みとしていました。カーネルを変更するよりは、無用なトラブルを避けるためにも、自分のソースを変更しました。
dsPIC33CKは汎用タイマはT1しかありませんが、CCP1,2も汎用タイマとして使えます(T2,T3と同様に使用できる)。CCP1CON1Lを設定し、割り込みハンドラ名を
_T1Interrupt から _CCT1Interruptへ変更し、フラグクリアもT1IF を CCT1IFとします。
動作確認Lチカソース
定番の1秒点滅のLチカで、スイッチャ周期など確認
// for RTOS
void vTask1(); //タスク関数1
void vTask2(); //タスク関数2
void vTask3(); //タスク関数3
xTaskHandle xTask1;
xTaskHandle xTask2;
xTaskHandle xTask3;
・
・
・
int main(void) {
・
初期化ルーチン
・
//タスクを生成
xTaskCreate(vTask1,"task_main",100,NULL,3,&xTask1);
xTaskCreate(vTask2,"task_setting",100,NULL,3,&xTask2);
xTaskCreate(vTask3,"task_buzzer",100,NULL,3,&xTask3);
//スケジューラを起動
vTaskStartScheduler();
for(;;);
}
//メインタスク
void vTask1(){
for(;;) mloop();
}
// サブタスク1
void vTask2(){
for(;;);
}
// サブタスク2(PILOTタスク)
void vTask3() {
// vTaskSuspend(xTask3); // start後はサスペンドにしておく(電源投入時に鳴らせない)
for(;;) {
int i;
for(i=0;i<3;i++) {
PILOT = 1;
vTaskDelay(1000);
PILOT = 0;
vTaskDelay(1000);
}
// vTaskSuspend(xTask3);
}
}
タスクスイッチャ周期の確認はタスクディレイ関数で簡単に確認できます。vTaskDelay()に1000を指定しているのでスイッチタイム1msでLED点滅は2秒周期となるはずなのでカウンタ等で確認(私はストップウォッチでしたが・・・(^^;))し、違えばFreeRTOSConfig.hを変更します。
ワーニングが1つでる・・・このままでも良いようだ
キャストするポインタサイズが違う、というワーニングが消えません。フォーラムなど調べたところとりあえずはこのままでも良いらしい。
最後にヒープ残量確認
FreeRTOSConfig.hでヒープサイズをMicrochipのDemoのまま”5120”にしていました。余裕度を見てみます。以下のようなコードを追加し、ブレークしてhsize変数をウォッチするだけです
size_t hsize; // 最適化で見失わないようにGlobal変数として宣言。 ・ ・ hsize = xPortGetFreeHeapSize(); // メインタスクループの中で
結果は、
“4140”
となりました。実際この程度のタスクでは5120-4140=980しか使用していないことがわかりました。
dsPIC33CK256MP503にはまだまだ余裕があります。