LEDチカチカ(RTOS)
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#analog
#norelated
#contents
* LEDチカチカ(RTOS) [#i310dd56]
** RTOS [#u1ca3865]
RTOSとはなんぞやというのは、なかなか説明が難しいものでは...
[[Wikipedia:http://ja.wikipedia.org/wiki/%E3%83%AA%E3%82%...
書籍では、[[リアルタイムOSと組み込み技術の基礎:http://www...
μITRONなんかは、非常に有名ですね。~
今回使用するFreeRTOSは、サイズが小さくシンプルで、色々な...
FreeRTOSのリファレンスマニュアルやチュートリアルは、[[公...
が、APIリファレンスくらいであれば、[[公式サイト:http://ww...
私はまだ買ってませんけどw~
** 構成 [#gb2699d7]
構成は、[[LEDチカチカ(RTOS)]]の方と変わりません。~
基板上のLEDを、FreeRTOSを使用して点滅させます。~
** プロジェクト [#oee75559]
まずは、新規プロジェクトを作りますが、前回とは選ぶプロジ...
QuickStartPanelのNew projectから、LPC176Xの「FreeRTOS Pro...
ここでは、「ledtest02」としました。~
MCUはLPC1769を選び、途中Advanced OptionでFreeRTOSのrootを...
すると、以下の様な構成で、プロジェクトが出来上がります。~
#ref(ledtest02.png,left,nowrap,プロジェクト構成)
FreeRTOS_なんとかというフォルダは、FreeRTOS用のファイルで...
自分でいじるのは、srcフォルダにある、cr_startup_lpc17.c、...
ざっと、デフォルトで作られたmain.cを見てみると、2つのタス...
それぞれに関連性はないので協調して動くものではないですが...
main関数は、これらのタスクを生成して、スタートさせている...
RTOSのイメージが、なんとなく掴めるでしょうか。~
次にFreeRTOSConfig.hを見てみましょう。~
この中身をいじることにより、FreeRTOSの機能をカスタマイズ...
とりあえず直しておく必要があるのは、configCPU_CLOCK_HZで...
これは、CPUクロックを設定する必要があるので、ledtest01で...
#define configCPU_CLOCK_HZ ( ( unsigned long )SystemCo...
ただし、実はこれではビルドが通りません。~
SystemCoreClockというのは、元々CMSISライブラリのsystem_LP...
このため、CMSISライブラリを参照する必要がありますが、ledt...
FreeRTOSを選んだ時には、FreeRTOSのソースが組み入れられる...
ledtest01の時と同じように、CMSISv2p00_LPC17xxと、DriverLi...
ledtest02のプロジェクトを、右クリックからプロパティを開き...
まず、「Project References」で、CMSISv2p00_LPC17xxと、Dri...
#ref(prjref.png,left,nowrap,プロジェクト参照)
次に、「C/C++ General」の「Paths and Symbols」を開いて、i...
IncludesタブのLanguagesがGNU Cのところを選択し、/CMSISv2p...
#ref(includes.png,left,nowrap,Includeパス設定)
そして、Librariesタブに、CMSISv2p00_LPC17xxと、DriverLib...
#ref(libraries.png,left,nowrap,ライブラリ設定)
最後に、Library Pathsタブに、/CMSISv2p00_LPC17xx/Debugと...
#ref(librarypaths.png,left,nowrap,ライブラリパス設定)
これでヘッダファイルを参照出来るようになったので、FreeRTO...
#include "LPC17xx.h"
ビルドを行い、ledtest02.axfが出来上がればOKです。~
ビルドは通りましたが、実はまだ、ledtest01とはプロジェクト...
プロジェクトのプロパティに、Symbolsというタブがあり、色々...
Show built-in valuesというチェックを外すと、このプロジェ...
ledtest01とledtest02の定義を比べてみましょう。~
|ledtest01のみ|ledtest02のみ|h
|__REDLIB__|__NEWLIB__|
|__USE_CMSIS||
||GCC_ARMCM3|
||PACK_STRUCT_END|
まず、__REDLIB__と__NEWLIB__の定義ですが、これはどのCライ...
[[CodeRedのサポートページ:http://support.code-red-tech.co...
RedLibの特徴としては、C90準拠でサイズが小さいため、メモリ...
C++を使わない限りは、RedLibを使用するのがいいと思いますの...
使用ライブラリの切り替えは、QuickStartPanelのQuick Settin...
すると、シンボル定義や、リンクするライブラリの切り替えを...
nohostやSemihostについては、デバッグ用だったりするので、...
#ref(sellib.png,left,nowrap,ライブラリ選択)
次にledtest01のみで定義されていた__USE_CMSISですが、これ...
この定義があると、cr_startup_lpc17.cの中で、CMSISライブラ...
やっておいた方がいいと思うので、ledtest02にもこの定義を追...
SymbolsタブでAddボタンを押し、以下のように入れておきます。~
#ref(usecmsis.png,left,nowrap,定義追加)
ledtest02で定義されているGCC_ARMCM3は、FreeRTOSが適切な設...
もう一つのPACK_STRUCT_ENDですが、これは現状、どこでも使用...
ただ、FreeRTOSのサンプルプログラムで、構造体定義のパディ...
現状あってもなくても影響はないはずですが、とりあえずはそ...
FreeRTOSConfig.hの他の設定については、今のところはいじり...
基本的なプロジェクトの設定はこんなところかと思いますが、...
内容としては、ledtest01の方が新しいようなのですが、ledtes...
以下の3関数が、g_pfnVectorsという割り込み関数テーブルの中...
extern void xPortSysTickHandler(void);
extern void xPortPendSVHandler(void);
extern void vPortSVCHandler( void );
これは、FreeRTOSがタスクスケジューリングをするために使う...
SysTick handlerはledtest01で使用しましたが、FreeRTOSで使...
ただし、FreeRTOSにタスクを一定時間休止するような機能や、...
** ソースコード [#d48a41c4]
まずはざっくり全部消してしまって、ledtest01の最初の部分だ...
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif
#include <cr_section_macros.h>
#include <NXP/crp.h>
// Variable to store CRP value in. Will be placed automa...
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP;
// TODO: insert other include files here
#include "lpc17xx_pinsel.h"
#include "lpc17xx_gpio.h"
次に、FreeRTOSを使うためのヘッダをincludeします。~
基本のヘッダと、今回はタスクを使うので、タスクのヘッダを...
#include "FreeRTOS.h"
#include "task.h"
タスクで使うスタック領域のサイズとプライオリティを定義し...
#define LED_STACK_SIZE 64
#define LED_TASK_PRIO tskIDLE_PRIORITY + 1
先にタスクの処理を書いてしまいます。~
void LedTask(void *param) {
uint32_t state = 0;
while (1) {
vTaskDelay(500);
state = GPIO_ReadValue(PINSEL_PORT_0);
GPIO_ClearValue(PINSEL_PORT_0, state & (1 << PINSEL_PI...
GPIO_SetValue(PINSEL_PORT_0, ~state & (1 << PINSEL_PIN...
}
}
そして、メイン関数は以下のようになります。~
int main(void) {
// TODO: insert code here
PINSEL_CFG_Type pincfg; // ピン設定構造体
// LED初期化
pincfg.Funcnum = PINSEL_FUNC_0;
pincfg.OpenDrain = PINSEL_PINMODE_NORMAL;
pincfg.Pinmode = PINSEL_PINMODE_PULLUP;
pincfg.Portnum = PINSEL_PORT_0;
pincfg.Pinnum = PINSEL_PIN_22;
PINSEL_ConfigPin(&pincfg);
GPIO_SetDir(PINSEL_PORT_0, (1 << PINSEL_PIN_22), 1 );
GPIO_SetValue(PINSEL_PORT_0, (1 << PINSEL_PIN_22));
xTaskCreate( LedTask, ( signed portCHAR * ) "LedTask", L...
vTaskStartScheduler();
return 0;
}
** ソースコード解説 [#g9c0489b]
まず、メイン関数ですが、LEDがつながっているポート0の22番...
その後、LEDタスクを生成して、タスク動作をスタートさせると...
xTaskCreateはタスクの生成を行うマクロですが、第1引数にタ...
第1引数のタスク関数は、戻り値なし(void)でvoid*型の関数を...
また、この関数はreturnしてはいけません。~
無限ループ等で関数から抜けないようにしておく必要がありま...
LedTask関数も、そのように作っています。~
第2引数のタスク名は、FreeRTOSConfig.h内のconfigMAX_TASK_N...
デフォルトでは12文字までですね。~
終端文字を入れて12文字なので、実質11文字になります。~
#define configMAX_TASK_NAME_LEN ( 12 )
第3引数のスタックサイズには、そのタスクで使用するスタック...
スタックとは、ローカル変数や関数コール時の引数等を一時的...
本当に必要なサイズが、実際にどれくらいかというのを厳密に...
今回はひとまず、64を指定します。~
実際のメモリサイズとしては、ここで指定した値に4をかけたも...
つまり、64*4で256バイトのスタックが確保されます。~
第4引数のパラメータですが、今回はタスクに何も渡すものがな...
第5引数のタスク優先度ですが、0からFreeRTOSConfig.h内のcon...
デフォルトでは5なので、0(低優先度)〜4(高優先度)の優先度が...
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE...
ただし、CPUが何も実行するタスクがない場合、FreeRTOSが自動...
このため、優先度0はアイドルタスク専用としておき、1〜4まで...
今回、LEDタスクとしての優先度は、アイドルタスクの次に低い...
今後、優先度の高い他のタスクを動作させるようになり、その...
第6引数のタスクハンドルですが、タスクハンドルを後で使用す...
例えば、別のタスクからLEDタスクを削除したり、サスペンドし...
vTaskStartSchedulerは、アイドルタスクを作成して、各タスク...
アイドルタスクとLEDタスクが開始され、優先度の高いLEDタス...
----
最後に、タスク関数の中身ですが、基本的にはledtest01の無限...
一つ違うのは、500ms待つための関数が、タスクを待ち状態にさ...
vTaskDelayは、指定されたtick数分、タスクを待ち状態にする...
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
今回は、LEDタスク以外にはアイドルタスクしかないので、vTas...
** 実行・デバッグ [#t028524b]
ビルドして実行してみます。~
当然ながら、見た目はledtest01の時と変わりません。~
ただ、タスクという概念で動作するようになったので、今後色...
タスクのデバッグも、普通にブレークポイントをはるだけで可...
** スタックサイズ [#ueae9e98]
今回、スタックサイズに64(*4=128バイト)を指定しましたが、...
FreeRTOSは、xTaskCreateでタスクを生成する時に、指定された...
そして、スタックという特性上、確保されたメモリの後ろ側か...
スタック領域が使用された場合、基本的にはそこのメモリアド...
タスク処理中に任意のタイミングで、uxTaskGetStackHighWater...
LedTask関数を、以下のように書き換えてみましょう。~
void LedTask(void *param) {
uint32_t state = 0;
unsigned portBASE_TYPE freesize = 0;
while (1) {
vTaskDelay(500);
state = GPIO_ReadValue(PINSEL_PORT_0);
GPIO_ClearValue(PINSEL_PORT_0, state & (1 << PINSEL_PI...
GPIO_SetValue(PINSEL_PORT_0, ~state & (1 << PINSEL_PIN...
freesize = uxTaskGetStackHighWaterMark(NULL);
}
}
uxTaskGetStackHighWaterMarkをコールする箇所にブレークポイ...
今回は、35という値が帰って来ました。~
ということは、35(140バイト)/64(256バイト)で、140バイトが...
もちろん、これは実際に動作した結果そうなっているというだ...
今回はたまたま、深い関数コールのネストが行われずにスタッ...
自分でタスクのプログラムを書く場合、どこが一番深いネスト...
メモリの容量制限の厳しいマイコンでは、特に意識しないとな...
また、これ以外にも、スタックオーバーフローを検知してフッ...
使う機会があれば、そのうち書いてみたいと思います。~
終了行:
#analog
#norelated
#contents
* LEDチカチカ(RTOS) [#i310dd56]
** RTOS [#u1ca3865]
RTOSとはなんぞやというのは、なかなか説明が難しいものでは...
[[Wikipedia:http://ja.wikipedia.org/wiki/%E3%83%AA%E3%82%...
書籍では、[[リアルタイムOSと組み込み技術の基礎:http://www...
μITRONなんかは、非常に有名ですね。~
今回使用するFreeRTOSは、サイズが小さくシンプルで、色々な...
FreeRTOSのリファレンスマニュアルやチュートリアルは、[[公...
が、APIリファレンスくらいであれば、[[公式サイト:http://ww...
私はまだ買ってませんけどw~
** 構成 [#gb2699d7]
構成は、[[LEDチカチカ(RTOS)]]の方と変わりません。~
基板上のLEDを、FreeRTOSを使用して点滅させます。~
** プロジェクト [#oee75559]
まずは、新規プロジェクトを作りますが、前回とは選ぶプロジ...
QuickStartPanelのNew projectから、LPC176Xの「FreeRTOS Pro...
ここでは、「ledtest02」としました。~
MCUはLPC1769を選び、途中Advanced OptionでFreeRTOSのrootを...
すると、以下の様な構成で、プロジェクトが出来上がります。~
#ref(ledtest02.png,left,nowrap,プロジェクト構成)
FreeRTOS_なんとかというフォルダは、FreeRTOS用のファイルで...
自分でいじるのは、srcフォルダにある、cr_startup_lpc17.c、...
ざっと、デフォルトで作られたmain.cを見てみると、2つのタス...
それぞれに関連性はないので協調して動くものではないですが...
main関数は、これらのタスクを生成して、スタートさせている...
RTOSのイメージが、なんとなく掴めるでしょうか。~
次にFreeRTOSConfig.hを見てみましょう。~
この中身をいじることにより、FreeRTOSの機能をカスタマイズ...
とりあえず直しておく必要があるのは、configCPU_CLOCK_HZで...
これは、CPUクロックを設定する必要があるので、ledtest01で...
#define configCPU_CLOCK_HZ ( ( unsigned long )SystemCo...
ただし、実はこれではビルドが通りません。~
SystemCoreClockというのは、元々CMSISライブラリのsystem_LP...
このため、CMSISライブラリを参照する必要がありますが、ledt...
FreeRTOSを選んだ時には、FreeRTOSのソースが組み入れられる...
ledtest01の時と同じように、CMSISv2p00_LPC17xxと、DriverLi...
ledtest02のプロジェクトを、右クリックからプロパティを開き...
まず、「Project References」で、CMSISv2p00_LPC17xxと、Dri...
#ref(prjref.png,left,nowrap,プロジェクト参照)
次に、「C/C++ General」の「Paths and Symbols」を開いて、i...
IncludesタブのLanguagesがGNU Cのところを選択し、/CMSISv2p...
#ref(includes.png,left,nowrap,Includeパス設定)
そして、Librariesタブに、CMSISv2p00_LPC17xxと、DriverLib...
#ref(libraries.png,left,nowrap,ライブラリ設定)
最後に、Library Pathsタブに、/CMSISv2p00_LPC17xx/Debugと...
#ref(librarypaths.png,left,nowrap,ライブラリパス設定)
これでヘッダファイルを参照出来るようになったので、FreeRTO...
#include "LPC17xx.h"
ビルドを行い、ledtest02.axfが出来上がればOKです。~
ビルドは通りましたが、実はまだ、ledtest01とはプロジェクト...
プロジェクトのプロパティに、Symbolsというタブがあり、色々...
Show built-in valuesというチェックを外すと、このプロジェ...
ledtest01とledtest02の定義を比べてみましょう。~
|ledtest01のみ|ledtest02のみ|h
|__REDLIB__|__NEWLIB__|
|__USE_CMSIS||
||GCC_ARMCM3|
||PACK_STRUCT_END|
まず、__REDLIB__と__NEWLIB__の定義ですが、これはどのCライ...
[[CodeRedのサポートページ:http://support.code-red-tech.co...
RedLibの特徴としては、C90準拠でサイズが小さいため、メモリ...
C++を使わない限りは、RedLibを使用するのがいいと思いますの...
使用ライブラリの切り替えは、QuickStartPanelのQuick Settin...
すると、シンボル定義や、リンクするライブラリの切り替えを...
nohostやSemihostについては、デバッグ用だったりするので、...
#ref(sellib.png,left,nowrap,ライブラリ選択)
次にledtest01のみで定義されていた__USE_CMSISですが、これ...
この定義があると、cr_startup_lpc17.cの中で、CMSISライブラ...
やっておいた方がいいと思うので、ledtest02にもこの定義を追...
SymbolsタブでAddボタンを押し、以下のように入れておきます。~
#ref(usecmsis.png,left,nowrap,定義追加)
ledtest02で定義されているGCC_ARMCM3は、FreeRTOSが適切な設...
もう一つのPACK_STRUCT_ENDですが、これは現状、どこでも使用...
ただ、FreeRTOSのサンプルプログラムで、構造体定義のパディ...
現状あってもなくても影響はないはずですが、とりあえずはそ...
FreeRTOSConfig.hの他の設定については、今のところはいじり...
基本的なプロジェクトの設定はこんなところかと思いますが、...
内容としては、ledtest01の方が新しいようなのですが、ledtes...
以下の3関数が、g_pfnVectorsという割り込み関数テーブルの中...
extern void xPortSysTickHandler(void);
extern void xPortPendSVHandler(void);
extern void vPortSVCHandler( void );
これは、FreeRTOSがタスクスケジューリングをするために使う...
SysTick handlerはledtest01で使用しましたが、FreeRTOSで使...
ただし、FreeRTOSにタスクを一定時間休止するような機能や、...
** ソースコード [#d48a41c4]
まずはざっくり全部消してしまって、ledtest01の最初の部分だ...
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif
#include <cr_section_macros.h>
#include <NXP/crp.h>
// Variable to store CRP value in. Will be placed automa...
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP;
// TODO: insert other include files here
#include "lpc17xx_pinsel.h"
#include "lpc17xx_gpio.h"
次に、FreeRTOSを使うためのヘッダをincludeします。~
基本のヘッダと、今回はタスクを使うので、タスクのヘッダを...
#include "FreeRTOS.h"
#include "task.h"
タスクで使うスタック領域のサイズとプライオリティを定義し...
#define LED_STACK_SIZE 64
#define LED_TASK_PRIO tskIDLE_PRIORITY + 1
先にタスクの処理を書いてしまいます。~
void LedTask(void *param) {
uint32_t state = 0;
while (1) {
vTaskDelay(500);
state = GPIO_ReadValue(PINSEL_PORT_0);
GPIO_ClearValue(PINSEL_PORT_0, state & (1 << PINSEL_PI...
GPIO_SetValue(PINSEL_PORT_0, ~state & (1 << PINSEL_PIN...
}
}
そして、メイン関数は以下のようになります。~
int main(void) {
// TODO: insert code here
PINSEL_CFG_Type pincfg; // ピン設定構造体
// LED初期化
pincfg.Funcnum = PINSEL_FUNC_0;
pincfg.OpenDrain = PINSEL_PINMODE_NORMAL;
pincfg.Pinmode = PINSEL_PINMODE_PULLUP;
pincfg.Portnum = PINSEL_PORT_0;
pincfg.Pinnum = PINSEL_PIN_22;
PINSEL_ConfigPin(&pincfg);
GPIO_SetDir(PINSEL_PORT_0, (1 << PINSEL_PIN_22), 1 );
GPIO_SetValue(PINSEL_PORT_0, (1 << PINSEL_PIN_22));
xTaskCreate( LedTask, ( signed portCHAR * ) "LedTask", L...
vTaskStartScheduler();
return 0;
}
** ソースコード解説 [#g9c0489b]
まず、メイン関数ですが、LEDがつながっているポート0の22番...
その後、LEDタスクを生成して、タスク動作をスタートさせると...
xTaskCreateはタスクの生成を行うマクロですが、第1引数にタ...
第1引数のタスク関数は、戻り値なし(void)でvoid*型の関数を...
また、この関数はreturnしてはいけません。~
無限ループ等で関数から抜けないようにしておく必要がありま...
LedTask関数も、そのように作っています。~
第2引数のタスク名は、FreeRTOSConfig.h内のconfigMAX_TASK_N...
デフォルトでは12文字までですね。~
終端文字を入れて12文字なので、実質11文字になります。~
#define configMAX_TASK_NAME_LEN ( 12 )
第3引数のスタックサイズには、そのタスクで使用するスタック...
スタックとは、ローカル変数や関数コール時の引数等を一時的...
本当に必要なサイズが、実際にどれくらいかというのを厳密に...
今回はひとまず、64を指定します。~
実際のメモリサイズとしては、ここで指定した値に4をかけたも...
つまり、64*4で256バイトのスタックが確保されます。~
第4引数のパラメータですが、今回はタスクに何も渡すものがな...
第5引数のタスク優先度ですが、0からFreeRTOSConfig.h内のcon...
デフォルトでは5なので、0(低優先度)〜4(高優先度)の優先度が...
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE...
ただし、CPUが何も実行するタスクがない場合、FreeRTOSが自動...
このため、優先度0はアイドルタスク専用としておき、1〜4まで...
今回、LEDタスクとしての優先度は、アイドルタスクの次に低い...
今後、優先度の高い他のタスクを動作させるようになり、その...
第6引数のタスクハンドルですが、タスクハンドルを後で使用す...
例えば、別のタスクからLEDタスクを削除したり、サスペンドし...
vTaskStartSchedulerは、アイドルタスクを作成して、各タスク...
アイドルタスクとLEDタスクが開始され、優先度の高いLEDタス...
----
最後に、タスク関数の中身ですが、基本的にはledtest01の無限...
一つ違うのは、500ms待つための関数が、タスクを待ち状態にさ...
vTaskDelayは、指定されたtick数分、タスクを待ち状態にする...
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
今回は、LEDタスク以外にはアイドルタスクしかないので、vTas...
** 実行・デバッグ [#t028524b]
ビルドして実行してみます。~
当然ながら、見た目はledtest01の時と変わりません。~
ただ、タスクという概念で動作するようになったので、今後色...
タスクのデバッグも、普通にブレークポイントをはるだけで可...
** スタックサイズ [#ueae9e98]
今回、スタックサイズに64(*4=128バイト)を指定しましたが、...
FreeRTOSは、xTaskCreateでタスクを生成する時に、指定された...
そして、スタックという特性上、確保されたメモリの後ろ側か...
スタック領域が使用された場合、基本的にはそこのメモリアド...
タスク処理中に任意のタイミングで、uxTaskGetStackHighWater...
LedTask関数を、以下のように書き換えてみましょう。~
void LedTask(void *param) {
uint32_t state = 0;
unsigned portBASE_TYPE freesize = 0;
while (1) {
vTaskDelay(500);
state = GPIO_ReadValue(PINSEL_PORT_0);
GPIO_ClearValue(PINSEL_PORT_0, state & (1 << PINSEL_PI...
GPIO_SetValue(PINSEL_PORT_0, ~state & (1 << PINSEL_PIN...
freesize = uxTaskGetStackHighWaterMark(NULL);
}
}
uxTaskGetStackHighWaterMarkをコールする箇所にブレークポイ...
今回は、35という値が帰って来ました。~
ということは、35(140バイト)/64(256バイト)で、140バイトが...
もちろん、これは実際に動作した結果そうなっているというだ...
今回はたまたま、深い関数コールのネストが行われずにスタッ...
自分でタスクのプログラムを書く場合、どこが一番深いネスト...
メモリの容量制限の厳しいマイコンでは、特に意識しないとな...
また、これ以外にも、スタックオーバーフローを検知してフッ...
使う機会があれば、そのうち書いてみたいと思います。~
ページ名: