インターフェース2021年4月号で特集されているFreeRTOSをPSoC4で使ってみたので備忘録として投稿します。
デモとして赤・緑・青色LEDをそれぞれ1,3,5Hzにて点滅させるタスクを動作させます。
確認環境 | バージョン |
FreeRTOS | v202012.00 |
PSoC Creator | 4.4 (4.4.0.80) |
ARM GCC | 5.4-2016-q2-update |
作業手順
1.FreeRTOSのダウンロード
FreeRTOSより、[Download FreeRTOS]を選択します。
Download FreeRTOS画面で、FreeRTOSの[Download]を行います。
ダウンロードしたZIPファイルを適当な場所に解凍します。(解凍したファイルをコピーして使用するので、保存場所は任意)
2.プロジェクトの新規作成
PSoC Creatorで、PSOC4の新規プロジェクトを生成します。赤・緑・青色LEDの駆動端子も設定して、一旦、プロジェクトを終了します。
3.プロジェクトフォルダ内にFreeRTOSのソースファイルをコピーします。
プロジェクトフォルダ(main.cファイルがあるフォルダ)内に、FreeRTOSソースファイル収納用”FreeRTOS”フォルダを作成し、その下に、”include”フォルダと”source”フォルダを作成します。
“include”フォルダ内には、ダウンロードしたFreeRTOSより以下をコピーします。
“ダウンロードフォルダ\FreeRTOSv202012.00\FreeRTOS\Source\include”フォルダ内のすべてのヘッダファイル
“ダウンロードフォルダ\FreeRTOSv202012.00\FreeRTOS\Source\portable\GCC\ARM_CM0″フォルダ内のすべてのヘッダファイル
“source”フォルダ内には、ダウンロードしたFreeRTOSより以下をコピーします。
“ダウンロードフォルダ\FreeRTOSv202012.00\FreeRTOS\Source”フォルダ内のすべてのcファイル
“ダウンロードフォルダ\FreeRTOSv202012.00\FreeRTOS\Source\portable\Common”フォルダ内のすべてのcファイル
“ダウンロードフォルダ\FreeRTOSv202012.00\FreeRTOS\Source\portable\GCC\ARM_CM0″フォルダ内のすべてのcファイル
“ダウンロードフォルダ\FreeRTOSv202012.00\FreeRTOS\Source\portable\MemMang”フォルダ内のいずれか1つのcファイル(今回はheap_1.cを選択、どのファイルを選択するかは同フォルダ内のReadMeを参照)
4.プロジェクトフォルダ内にFreeRTOSConfig.hの作成
ダウンロードしたFreeRTOS内には、PSoC5(ARM Cortex-M3)のデモフォルダがあるので、PSoC4(ARM Cortex-M0)用に一部を編集して下記を使用しました。
//
// for PSoC4
//
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include "project.h"
#define configUSE_PREEMPTION 1 // プリエンプティブ RTOS スケジューラを使用する
#define configCPU_CLOCK_HZ CYDEV_BCLK__HFCLK__HZ // 内部クロック周波数
#define configTICK_RATE_HZ 1000 // RTOS ティック割り込み周波数
#define configMAX_PRIORITIES 5 // アプリケーション タスクで使用できる優先度の数
#define configMINIMAL_STACK_SIZE 100 // スタックサイズ(ワード数)
#define configMAX_TASK_NAME_LEN 12 // タスク名の最大文字列長
#define configUSE_16_BIT_TICKS 0 // ティック割り込み実行回数を使用しない
#define configIDLE_SHOULD_YIELD 0 // アイドル優先度を使用しない
#define configUSE_MUTEXES 1 // ミューテックス機能を使用する
#define configUSE_RECURSIVE_MUTEXES 1 // 再帰ミューテックス機能を使用する
#define configUSE_COUNTING_SEMAPHORES 1 // カウンティングセマフォ機能を使用する
#define configUSE_ALTERNATIVE_API 0 // オルタナティブAPIを使用しない
#define configQUEUE_REGISTRY_SIZE 10 // キューレジストリの容量
// メモリ割り当て関連の定義
#define configTOTAL_HEAP_SIZE 2048 // ヒープで使用可能容量
// フック機能関連の定義
#define configUSE_IDLE_HOOK 0 // アイドルフックを省略
#define configUSE_TICK_HOOK 0 // ティックフックを省略
#define configCHECK_FOR_STACK_OVERFLOW 2 // スタックオーバーフローフック関数を使用する
#define configUSE_MALLOC_FAILED_HOOK 1 // ヒープ領域獲得失敗フック関数を使用する
// 実行時タスク状態の情報
#define configGENERATE_RUN_TIME_STATS 0 // 実行状態の情報を使用しない
#define configUSE_TRACE_FACILITY 0 // トレースを支援機能を使用しない
// コルーチン関連の定義
#define configUSE_CO_ROUTINES 0 // コルーチン機能を使用しない
#define configMAX_CO_ROUTINE_PRIORITIES 2 // コルーチンで使用できる優先順位数
// 割込み動作構成(Cortex-M0)
#define configPRIO_BITS __NVIC_PRIO_BITS // 4 priority levels
#define MIN_PRIORITY ((1 << configPRIO_BITS) - 1)
#define configKERNEL_INTERRUPT_PRIORITY ( MIN_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( 2 << (8 - configPRIO_BITS) )
// オプション関数
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_eTaskGetState 1
#endif /* FREERTOS_CONFIG_H */
各設定の詳細は、FreeRTOSConfig.hを参照下さい
5.ビルド設定でインクルード・パスを設定します。
Psoc Creatorで、先ほど生成したプロジェクトを立ち上げ、[Project] > [Build Settings]より、ARM GCCコンパイラに、先ほどヘッダファイルをコピーしたフォルダをインクルード・ディレクトリに追加します。
6.デモ用のメイン・プログラムを編集します。
//
// FreeRTOS demo for PSoC4
//
#include
#include "project.h"
#include
#include
#define CORTEX_INTERRUPT_BASE (16)
#define BLUE_LED_BLINK_FREQ_HZ (5)
#define GREEN_LED_BLINK_FREQ_HZ (3)
#define RED_LED_BLINK_FREQ_HZ (1)
// 青色LEDタスク
void vBlinkTaskBlue(void *pvParameters) {
while (1) {
Pin_Blue_LED_Write(~Pin_Blue_LED_Read());
vTaskDelay(configTICK_RATE_HZ / (BLUE_LED_BLINK_FREQ_HZ * 2));
}
}
// 緑色LEDタスク
void vBlinkTaskGreen(void *pvParameters) {
while (1) {
Pin_Green_LED_Write(~Pin_Green_LED_Read());
vTaskDelay(configTICK_RATE_HZ / (GREEN_LED_BLINK_FREQ_HZ * 2));
}
}
// 赤色LEDタスク
void vBlinkTaskRed(void *pvParameters) {
while (1) {
Pin_Red_LED_Write(~Pin_Red_LED_Read());
vTaskDelay(configTICK_RATE_HZ / (RED_LED_BLINK_FREQ_HZ * 2));
}
}
// FreeRTOSセットアップ
void setupFreeRTOS(void)
{
// ベクターテーブルにコピーする必要のあるポートレイヤー関数
extern void vPortSVCHandler(void); // address 11 - Supervisor Call (SVC, formerly SWI)
extern void xPortPendSVHandler(void); // address 14 - PendSV Call
extern void xPortSysTickHandler(void); // address 15 - SYSTICK
CyIntSetSysVector(CORTEX_INTERRUPT_BASE + SVCall_IRQn, (cyisraddress)vPortSVCHandler);
CyIntSetSysVector(CORTEX_INTERRUPT_BASE + PendSV_IRQn, (cyisraddress)xPortPendSVHandler);
CyIntSetSysVector(CORTEX_INTERRUPT_BASE + SysTick_IRQn, (cyisraddress)xPortSysTickHandler);
}
// メイン
int main(void)
{
setupFreeRTOS();
xTaskCreate(vBlinkTaskBlue, "BlinkBlue", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
xTaskCreate(vBlinkTaskGreen, "BlinkGreen", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL);
xTaskCreate(vBlinkTaskRed, "BlinkRed", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 3, NULL);
CyGlobalIntEnable;
vTaskStartScheduler();
while (1);
return 1;
}
// スタックオーバーフローフック関数
void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName)
{
taskDISABLE_INTERRUPTS();
while (1);
}
// ヒープ領域獲得失敗フック関数
void vApplicationMallocFailedHook(void)
{
taskDISABLE_INTERRUPTS();
while (1);
}
/* [] END OF FILE */
ベクターテーブルにポートレイヤ関数を登録する方法は、FreeRTOS内のPSoC5デモでは、ベクターテーブルに直接書き込んでいますが、専用の関数が用意されていますので、今回はこの関数を使用しました。
7.ビルドして実行してみます。
おおよそ1,3,5Hzで点滅していることが確認できました。