mbed RTOS の メモ&Tips
mbed RTOS の メモ&Tips
Information
<mbed OS 2 向け>
本ページは私家版のため、誤り等あればご指摘ください。
なるべく更新を心がけていますが、最新の情報に追従していないことがあります。
mbed RTOS 特有の情報です。 その他の情報はメモ&Tipsへ
あなたのプロジェクトに mbed RTOS をインクルードするだけで、main() が一つ目のスレッドとして動き出します。
Import librarymbed-rtos
Official mbed Real Time Operating System based on the RTX implementation of the CMSIS-RTOS API open standard.
mbed RTOS は CMSIS RTOS をベースにしています。
- mbed RTOS
- mbed RTOS 日本語 (by takashikojo)
- CMSIS - Cortexマイクロコントローラ ソフトウェア インタフェース規格 (ARM)
Memory Model - メモリーモデル
ユーザータスクのスタックは、ヒープ領域に確保される。
MemoryModel
+-------------------+ +-------------------+ Last Address of RAM | Scheduler Stack | | Scheduler Stack | +-------------------+ +-------------------+ | Main Thread Stack | | Main Thread Stack | | | | | | | | v | | v | +-------------------+ +-------------------+ | | | | | | | | | | +-------------------+ RAM | | | ^ | | | | | | | | | Heap | | | +-------------------+ | | | User Thread Stack | }-- DEFAULT_STACK_SIZE +-------------------+ +-------------------+ | ^ | | User Thread Stack | }-- DEFAULT_STACK_SIZE | | | +-------------------+ | Heap | | Heap | +-------------------+ +-------------------+ | ZI: Idle Stack | | ZI: Idle Stack | +-------------------+ +-------------------+ | ZI: Timer Stack | | ZI: Timer Stack | +-------------------+ +-------------------+ | RW | | RW | +===================+ +===================+ First Address of RAM | | | | Flash | | | |
参照: http://mbed.org/handbook/RTOS-Memory-Model
Thread - スレッド
メモリー
スレッド内でのmallocやnewは、スタック(User Thread Stack)からメモリーが確保される。
つまり、ローカル変数も含めてスタックにまとめられる。
DEFAULT_STACK_SIZE は2048バイトのようだ。
mbed-rtos/rtx/TARGET_CORTEX_A/cmsis_os.h
#if defined(TOOLCHAIN_GCC) || defined(TOOLCHAIN_ARM_STD) # define WORDS_STACK_SIZE 512 #elif defined(TOOLCHAIN_ARM_MICRO) # define WORDS_STACK_SIZE 128 #endif #define DEFAULT_STACK_SIZE (WORDS_STACK_SIZE*4)
※メインスレッドだけはRTOSを使わないときと同様に、ローカル変数はスタック、mallocやnewはヒープから確保される。
タスク切り替えを停止する
RTOSは SVCall, PendSV, SysTick 割込みを使用している。(プライオリティは最低の 31, 31, 30)
__disable_irq() __enable_irq()
を使いたくない場面で、
RTOSのタスク切り替えの割り込みが起きてほしくないときに。。。
(SPIやI2C通信中などに、タスク切り替えが起きると Hard Fault してしまう?ため)
CMSIS RTOS にある関数を直接コールする。
extern "C" { #include "rt_TypeDef.h" #include "rt_System.h" } : rt_tsk_lock(); : rt_tsk_unlock(); :
ISR - 割込み
stdio (printf, putc, getc, etc), malloc & new in ISR
割り込み処理中のStream(printf等)、malloc(new)はできません。
Stream
割込みルーチン内でMutex等の待ちが発生する処理は使えない。
このため、内部的にMutexを使っているSerial(putc, getc, printf等)は割込みルーチン内で使えない。
Serial の定義を RawSerial とすれば putc, getc は使えるようになる。
#include "RawSerial.h" RawSerial pc(USBTX, USBRX);
※ mbedライブラリの Rev.68 以降にアップデートすること。
メモリー
割込みルーチン内のローカル変数は、メインスレッドのスタック(Main Thread Stack)からメモリーが確保される。
割込みルーチン内でmallocやnewでヒープ領域のメモリーを確保することはできない。
Class
Class中でスレッドを生成したいとき。
スレッドの関数は static で宣言する。
class MyClass { static void threadStarter(void const *p); void threadWorker(); Thread *_thread; };
staticな関数内からは、クラス内変数や関数へアクセスできないので、 スレッドの引数としてthisインスタンスのポインタを渡し、ポインタ経由でアクセスする。
MyClass::MyClass(...args...) { _thread = new Thread(&MyClass::threadStarter, this); } void MyClass::threadStarter(void const *p) { MyClass *instance = (MyClass*)p; instance->threadWorker(); } void MyClass::threadWorker() { while (1) { // do stuff } }
参考: https://developer.mbed.org/forum/mbed/topic/4388/
Power Management - 省電力
Sleep
タスク管理で1msごとに割り込みが発生しているため、単純にスリープしてもすぐに眠りから覚めてしまう。
RTOSライブラリのアイドル処理に追記すれば、スリープすることができる。
RTX_Conf_CM.c
extern void sleep(void); void os_idle_demon (void) { for (;;) { //Go to sleep sleep(); } }
参照: http://mbed.org/questions/2201/mbed-sleep-problem-with-RTOS/
CPU負荷率
上記のアイドル処理を利用して、CPUの負荷率(使用率)を計るプログラムを作ってみた。
もとは、EthernetInterfaceを使って、不正なパケットなどでどれくらい負荷がかかるか知りたいがために作ったもの。 参考になるものがあったわけではないので、こんなプログラムでいいかはよくわからない。
Import programeth_load_testing
load testing EthernetInterface
File System - ファイルシステム
スレッドの中でファイルシステム関数(fopen等)を使う場合は、デフォルトのままではスタックの容量が足りない。
スレッドを生成する際に、スタックのサイズを2.25倍以上に指定するとよい。
Thread t(sd_thread, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 2.25));
※ DEFAULT_STACK_SIZE は (512 * 4) と定義されている。
参照: http://mbed.org/forum/bugs-suggestions/topic/3288/
EthernetInterface - イーサーネット
複数コネクション
EthernetInterface のサンプルをそのまま使うと、1コネクションしか使えなくて悲しい。
acceptした後にスレッドを生成してforkすれば、複数コネクションを受付けられるようになる。
Import programTCPEchoServer_with_fork
EthernetInterface, TCP Echo Server, support multi session
メモ
SVC_Handler (31)
PendSV_Handler (31)
SysTick_Handler (30)
1 comment on mbed RTOS の メモ&Tips:
Please log in to post comments.
この表現は現在推奨されていません。関数の呼び出しにはcallbackを用いてください。 また、動的なメモリ確保を用いた記法も現在推奨されていないようです。(←まだよく調べていない)