ここでは、FreeRTOSの簡単な例であるmicrochip\harmony\v1_04_02\apps\rtos\freertos\basicと同じものをMHC(Microchip Harmony Configurator)で作成します。
使用する回路は、PIC32MX230F064B (HARMONY)の章に書かれてあるものと同じです。PICをPIC32MX270F256としただけです。
MPLAB X IDE MPLAB X IDE v3.00-betaをインストールした後、MPLAB XC32 Compiler v1.34とMPLAB XC32 Compiler Part-Support v1.34をインストールしておきます。 さらに、MPLAB Harmony Integrated Software Framework v1.04.02をインストールし、そのあと、MPLAB Harmony Confugulator(MHC)をプラグインとして、MPLAB X IDEに組み込みます。組み込み方法は、MPLAB Harmonyをインストールした時に、最後に表示されます。Webを検索をすれば、日本語での解説もありますので、そちらを参考にしてください。
次に、MHC環境を整えます。その前に
フォルダーmicrochip\harmony\v1_04_02\bsp\config
ファイルmicrochip\harmony\v1_04_02\utilities\mhc\config\PIC32MX230F064B.hconfig
ファイルmicrochip\harmony\v1_04_02\utilities\mhc\config\PIC32MX270F256B.hconfig
のバックアップを取っておきます。
引き続き、config.zipを解凍すると、configフォルダーの中に、bspフォルダーとutilitiesフォルダーが出てきますので。これらbspフォルダーとutilitiesフォルダーをmicrochip\harmony\v1_04_02フォルダーの中に上書きします。これで、PIC32MX270F256Bを用いたPIC回路用のMHC環境が整います。
ところで、上記MHC環境を用いると、以下のピン配置となります。なお、SWITCH_1、SWITCH_2、SWITCH_3ともに弱くプルアップするよう、設定しています。
PICに書き込むファームウェアはM270_rtosです。M270_rtos.zipを解凍して出てくるM270_rtosフォルダーをmicrochip\harmony\v1_04_02\appsフォルダーの中に入れます。
ファームウェアの概略です。SYS_Taskタスクを別にすると、4つのタスクがあります。優先順が高い方から、APP2_Tasks、APP1_Tasks、APP_Tasks、APP3_Tasksです。基本的に優先度が高いタスクが実行されます。ただ、優先度が高いタスクがブロック状態になれば、より下位の(そのうちでも、最も優先度が高い)タスクが実行されます。最下位のタスクは、その他の優先度が高いタスクが、すべてブロック状態になった時だけ実行されます。なお、蛇足ですが、以下に出てくる秒数は、きっちりとした値ではなく、きっちりとした値より、ほんの僅かですが長くなります。
APP2_Tasks
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY )関数のため、キューに数値が入らない間は、自分自身をブロックしますので、より優先度が低い関数が実行可能となります。キューに数値100が入るたびに、LED1が点灯したり消灯したりを繰り返します。その後、vTaskDelay((TickType_t)ulReceivedValue)関数で、自分自身を100ミリ秒間ブロックしますので(ulReceivedValueは100)、その間にAPP1_Tasksタスクが実行可能となります。
APP1_Tasks
キューに数値が入らない間は、自分自身をブロックしますので、より優先度が低い関数が実行可能となります。キューに数値1000が入るたびに、LED2が点灯したり消灯したりを繰り返します。
APP_Tasks
このタスクで、キューに数値を入れない限り、APP2_TasksタスクもAPP1_Tasksタスクもブロック状態にありますので、このタスクが実行されます。このタスクでは、まずキューに数値100を入れます。すると、APP_Tasksタスクはブロック状態になり、いままで、ブロックされていた、一番優先度が高いAPP2_Tasksタスクが実行されます。APP2_Tasksタスクは、自分自身を100ミリ秒間ブロックします。このとき、キューに数値がないので(すでにAPP2_Tasksタスクにより数値が取り出されてしまている)、APP1_Tasksタスクはブロックされたままとなります。このため、APP_Tasksタスクが再度実行されます。APP_Tasksタスクはキューに数値1000を入れます。すると、APP_Tasksタスクはブロック状態になり、またAPP2_Tasksタスクは、自分自身を100ミリ秒間ブロックしていますので、二番目に優先度が高いAPP1_Tasksタスクが実行されます。これで、また、キューに数値がないの状態になるので(すでにAPP1_Tasksタスクにより数値が取り出されてしまている)、APP_Tasksタスクが再度実行されます。すなわち、vTaskDelay(QUEUE_SEND_FREQUENCY_MS )関数が実行されて、自分自身を200ミリ秒間ブロックします。200ミリ秒後にAPP_Tasksは、ブロック状態から抜け、再び実行されるようになります。
結局、APP2_TasksタスクとAPP1_Tasksタスクは、このAPP_Tasksタスクで支配されていて、約200ミリ秒間隔でしかLED1もLED2も点灯したり消灯したりを繰り返しません。
APP3_Tasks
このタスクは、上記のタスクとは独立で、優先度が最下位のタスクです。APP2_Tasks、APP1_Tasks、_APP_Tasksのすべてのタスクがブロック状態にある200ミリ秒間の間隙を見て実行されます。このタスクは50ミリ秒間、自分自身をブロックしますので、50ミリ間隔でLED3が点灯したり消灯したりを繰り返します。
1.Terget DeviceとしてPIC32MX270F256Bを選択し、プロジェクト名をM270_rtosとして新規プロジェクトを作成します。
2.作成すると、MHCが立ち上がりますので、まずRTOS環境を以下の様に設定します。MHCでは、背景色が薄紫になっている箇所が、デフォルト値から変えてある所です。それ以外はデフォルト値のままとなっている箇所です。
3.以下の様に、BSPとしてPIC32MX230F064Bを選択します。このBSPはPIC32MX270F256Bでも用いることができます。両PICのピン配置が同じからです。
4.Application Configurationを以下の様に設定します。4つのタスクを作ります。
5.Interruptsを以下の様に設定します(下から2行目のチェック)。
6.Harmony Clock Configulationタブを選択し、以下の図のように、クロックを4,000,000Hzとして、一度Auto-Calculateボタンを押します。
7.Harmony Configulatorタブを選択して、Generateボタンを押します。あとは、出てくるダイアログの指示にしたがって操作すると、MHCでコードが生成されます。
8.microchip\harmony\v1_04_02\apps\rtos\freertos\basic\firmware\srcフォルダーにある8個のファイル(app.c、app.h、app1.c、app1.h、app2.c、app2.h、app3.c、app3.h)をmicrochip\harmony\v1_04_02\apps\M270_rtos\firmware\srcフォルダーの中に上書き保存します。もちろん、後者のフォルダーの中の8個のファイルを、前者のフォルダーの8個のファイルとそれそれ比較して、直接ファイルの中身を編集してもかまいません。
9.microchip\harmony\v1_04_02\apps\M270_rtos\firmware\src\system_config\default\rtos-hooks.cの中のvApplicationMallocFailedHook( void )関数の後に、次の3つの関数を追加します。
void vApplicationIdleHook( void )
{
/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
task. It is essential that code added to this hook function never attempts
to block in any way (for example, call xQueueReceive() with a block time
specified, or call vTaskDelay()). If the application makes use of the
vTaskDelete() API function then it is also
important that vApplicationIdleHook() is permitted to return to its calling
function, because it is the responsibility of the idle task to clean up
memory allocated by the kernel to any task that has since been deleted. */
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
void vApplicationTickHook( void )
{
/* This function will be called by each tick interrupt if
configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be
added here, but the tick hook is called from an interrupt context, so
code must not attempt to block, and only the interrupt safe FreeRTOS API
functions can be used (those that end in FromISR()). */
}
/*-----------------------------------------------------------*/
/* Error Handler */
void vAssertCalled( const char * pcFile, unsigned long ulLine )
{
volatile unsigned long ul = 0;
( void ) pcFile;
( void ) ulLine;
taskENTER_CRITICAL();
{
/* Set ul to a non-zero value using the debugger to step out of this
function. */
while( ul == 0 )
{
portNOP();
}
}
taskEXIT_CRITICAL();
}
以上。