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 をベースにしています。

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)


戻る (back)


1 comment on mbed RTOS の メモ&Tips:

17 Mar 2019

_thread = new Thread(&MyClass::threadStarter, this);

この表現は現在推奨されていません。関数の呼び出しにはcallbackを用いてください。 また、動的なメモリ確保を用いた記法も現在推奨されていないようです。(←まだよく調べていない)

_thread.start(callback(&MyClass::threadStarter, this));

Please log in to post comments.