PSoC5LPでFreeRTOSv10.2.1を使ってLチカ


環境

プロジェクトを作る

PSoC Creatorを立ち上げ、File->New->Projectよりプロジェクトを作る。
デバイスは今回用いるCY8C5888LTI-LP097を選択。

テンプレートは空っぽのemptyを選択。

わかりやすい名前とディレクトリを指定してFinishする。

FreeRTOSを導入する

ダウンロード

FreeRTOSよりダウンロードできる。
2019/6/10時点で最新verは10.2.1。
zipとexeがあるが今回はzipを選択。

導入

zipを解凍すると、いくつかのフォルダが生成される。このうち、Demoフォルダは各マイコン用のデモフォルダ、Licenseはライセンスが入っている。今回使用するSourceだけをプロジェクトのディレクトリへコピーする。

PSoC Creatorへリンク

まずわかりやすいように、デザイン内にFreeRTOS用のフォルダを生成する。
コピーしたファイルをこのフォルダ内にリンクしていく。

必要なものを列挙すると、

  • FreeRTOS/Source/下の.Cソースファイル
  • FreeRTOS/include下のヘッダーファイル
  • FreeRTOS/portable/MemMangのheap.cファイルどれかひとつ
  • FreeRTOS/portable/GCC/ARM_CM3のソースファイル・ヘッダーファイル

をそれぞれHeader FilesSource Filesにドラッグアンドドロップでリンクする。

FreeRTOSコンフィグファイルの作成

FreeRTOSの設定用ヘッダファイルを作成する。
解凍してできたFreeRTOS/Demo/CORTEX_CY8C5588_PSoC_Creator_GCC/FreeRTOS_Demo.cydsnディレクトリの、FreeRTOSConfig.hdevice.hをコピーして持ってくるのが早い。
FreeRTOSConfig.hはFreeRTOSの設定ファイル、device.hはproject.hのラッパーになっている。筆者の場合めんどくさかったのでdevice.hはコピーしてこないでFreeRTOSConfig.h内の記述をいじって直接project.hをインクルードする形にした。

コピーしてきたら忘れずにPSoC Creatorにリンクしておく。

PSoC Creatorにインクルードパスを指定する

PSoC CreatorメニューバーのProject->Build SettingよりARM_GCC~->Compiler->GeneralAdditional Include DirectoriesにFreeRTOSのヘッダファイルが存在するディレクトリを指定してやる。
portable/GCC/ARM_CM3が忘れやすいので注意すること。
以上でFreeRTOSの最低限の導入はおしまい。

Lチカする

Top Design/Pinアサイン

今回はただのLチカなのでDigital Outputピンを一つ置くだけ。
ピンアサインは開発ボードのユーザーLEDとつながっている2.1ピンを指定する。

プログラム

プログラムは以下のようになる。

main.c
#include "project.h"
#include "FreeRTOS.h"
#include "task.h"

void vTestTask1();//タスクとして走らせる関数
void vTestTask2();
int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */

    //FreeRTOS用の割り込み周りの初期設定。この処理をしないと動かない。
    extern void xPortPendSVHandler( void );
    extern void xPortSysTickHandler( void );
    extern void vPortSVCHandler( void );
    extern cyisraddress CyRamVectors[];

    CyRamVectors[ 11 ] = ( cyisraddress ) vPortSVCHandler;
    CyRamVectors[ 14 ] = ( cyisraddress ) xPortPendSVHandler;
    CyRamVectors[ 15 ] = ( cyisraddress ) xPortSysTickHandler;

    //タスクを生成
    xTaskCreate(vTestTask1,"test1",100,NULL,3,NULL);
    xTaskCreate(vTestTask2,"test2",100,NULL,3,NULL);
    //スケジューラを起動
    vTaskStartScheduler();

    for(;;)
    {
        /* Place your application code here. */
    }
}

//LEDを点灯させるタスク
void vTestTask1(){
    for(;;){
        vTaskDelay(1000);
        LED_1_Write(1);        
    }    
}
//LEDを消灯させるタスク
void vTestTask2(){
    vTaskDelay(500);
    for(;;){
        vTaskDelay(1000);
        LED_1_Write(0);        
    }    
}
//オーバーフローが起こった際のハンドラ
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
    /* The stack space has been execeeded for a task, considering allocating more. */
    taskDISABLE_INTERRUPTS();
}/*---------------------------------------------------------------------------*/

//メモリの確保に失敗したときのハンドラ
void vApplicationMallocFailedHook( void )
{
    /* The heap space has been execeeded. */
    taskDISABLE_INTERRUPTS();
}

FreeRTOSは、タスクとして走らせる関数を、xTaskCreate();関数で指定してタスクを生成し、vTaskStartScheduler();関数でスケジューラを起動することによって、生成されたタスクを走らせることができる。

xTaskCreate();関数の引数は1項目から、走らせる関数、タスク名、スタックサイズ、タスクに渡す引数、優先度、タスクのIDになっている。
今回はtestTask1でLEDを点灯させ、testTask2で消灯させるようなプログラムにした。testTask2の方は500msのディレイを入れているので、1HzのLチカになっているはずだが、同期をとっていないのでズレる可能性もある。

無事コンパイルが通り書き込みに成功すれば、0.5秒ごとにLEDがチカチカするはず。
このLチカはFreeRTOSの(たぶん)最小構成なので、他の機能を試したい場合はデモが参考になる。