MCU

小さなRTOSみたいなものを動かす

MCUの場合、OSなしで動かす事も多い筈です*1
なんかLinux動かすのも、ちょっとしんどいかなぁ、とか思ったりしてたり・・・
それで、本当に基本的な機能だけのRTOSもどきを作った事があったので、紹介してみます。
なを、このRTOSもどきは、1プライオリティ=1タスクです。

対象MCUは、H8/3052、言語はアセンブラ、cygwin+gccです。
プログラム・サイズは8KB程度、使用RAMは1タスク40バイト程度で動いています。
もっとも、Cで使うとスタックが大量消費されるので、なんともいえませんが、実際には、AKI-H8/3052 LAN開発ボードで自作TCP/IPスタックなんぞを動かした事があります。

基本的に、ソースを貼り付けて、それなりに説明を加えるという感じで、後は、ソースを読む人におまかせという事にします。

その前に…

こんな感じでCで動かします。

1) kernel.h --- タスク数・セマフォ数の定義とプロトタイプ宣言

00001 /*------------------------------------------------------------------------------
00002  H8/300H用マイクロRTOS Ver1.0.0
00003 
00004  2007.03.25 新規作成
00005 
00006                                            Copyright(C) by MCM Co.,Ltd
00007 -TAB=4------------------------------------------------------------------------*/
00008 #ifndef _KERNEL_H_
00009 #define _KERNEL_H_
00010 
00011 /******************************************************************************/
00012 /*                                                                            */
00013 /*  このシステムのタスク数とセマフォ数の定義(ユーザー設定)                   */
00014 /*                                                                            */
00015 /******************************************************************************/
00016 #define  TSK_NUMBER   (5)               /* このシステムのタスク数             */
00017 #define  SEM_NUMBER   (5)               /* このシステムのタスク数             */
00018 
00019 /******************************************************************************/
00020 /*                                                                            */
00021 /*                                                                            */
00022 /*                                                                            */
00023 /******************************************************************************/
00024 struct TSK_INF {
00025     long max_task_number;               /* タスク数                           */
00026     struct tcbs {                       /* TCBを作成する情報               */
00027         void  (*func)(void);            /* タスクエントリーアドレス           */
00028         long  *stack_top;               /* タスクで使用するスタック領域先頭   */
00029         long stack_size;                /* スタック領域のサイズ               */
00030     } tcbs[TSK_NUMBER];                 /* タスク数分用意する                 */
00031 };
00032 
00033 struct SEM_INF {
00034     unsigned char max_sem_num;          /* セマフォ数                         */
00035     unsigned char sem_num[SEM_NUMBER];  /* セマフォ資源数                     */
00036 };
00037 
00038 /******************************************************************************/
00039 /*                                                                            */
00040 /*  システムコール・プロトタイプ                                              */
00041 /*                                                                            */
00042 /******************************************************************************/
00043 void reg_tsk(struct TSK_INF *);         /* タスク登録                         */
00044 void reg_sem(struct SEM_INF *);         /* セマフォ登録                       */
00045 void dis_int(void);                     /* 割り込み禁止                       */
00046 void ena_int(void);                     /* 割り込み許可                       */
00047 void dis_dsp(void);                     /* ディスパッチ禁止                   */
00048 void ena_dsp(void);                     /* ディスパッチ許可                   */
00049 void INT_ENT(void);                     /* 割り込み処理開始                   */
00050 void RET_INT(void);                     /* 割り込み処理終了                   */
00051 void set_tim(long time);                /* 時間セット                         */
00052 long get_tim(void);                     /* 時間取得                           */
00053 long get_tid(void);                     /* 自タスクID取得                   */
00054 void wup_tsk(short id);                 /* 他タスク起床                       */
00055 void slp_tsk(void);                     /* 自タスク起床待ち                   */
00056 void dly_tsk(long time);                /* 自タスク時間経過待ち               */
00057 void wai_sem(short id);                 /* 資源取得                           */
00058 void sig_sem(short id);                 /* 資源解放                           */
00059 
00060 #endif /* defined(_KERNEL_H_) */



2) sysarea.h --- システムで使う領域と、タスク定義データ・セマフォ定義データ

00001 /*------------------------------------------------------------------------------
00002  H8/300H用マイクロRTOS Ver1.0.0
00003 
00004  2007.03.25 新規作成
00005 
00006                                            Copyright(C) by MCM Co.,Ltd
00007 ------------------------------------------------------------------------------*/
00008 #ifndef _SYSAREA_H_
00009 #define _SYSAREA_H_
00010 
00011 #include "kernel.h"
00012 
00013 
00014 /******************************************************************************/
00015 /*                                                                            */
00016 /*  スタック領域の確保                                                        */
00017 /*                                                                            */
00018 /******************************************************************************/
00019 long task1_stack[48];  /* RAM領域 */
00020 long task2_stack[48];  /* RAM領域 */
00021 long task3_stack[48];  /* RAM領域 */
00022 long task4_stack[48];  /* RAM領域 */
00023 long task5_stack[48];  /* RAM領域 */
00024 
00025 
00026 /******************************************************************************/
00027 /*                                                                            */
00028 /*  TCB領域の確保とタスク情報テーブル                                      */
00029 /*                                                                            */
00030 /******************************************************************************/
00031 unsigned char TCB_TOP[TSK_NUMBER * 12];     /* RAM領域 */
00032 
00033 const struct  TSK_INF TSK_INF = {           /* ROM領域 */
00034     TSK_NUMBER,
00035     /* TSK_NUMBER分、以下を記述する */
00036     task1, task1_stack, sizeof(task1_stack),
00037     task2, task2_stack, sizeof(task2_stack),
00038     task3, task3_stack, sizeof(task3_stack),
00039     task4, task4_stack, sizeof(task4_stack),
00040     task5, task5_stack, sizeof(task5_stack)
00041 };
00042 
00043 
00044 /******************************************************************************/
00045 /*                                                                            */
00046 /* セマフォ領域の確保                                                         */
00047 /*                                                                            */
00048 /******************************************************************************/
00049 unsigned char SEM_TOP[SEM_NUMBER * 2];      /* RAM領域 */
00050 
00051 const struct  SEM_INF SEM_INF = {           /* ROM領域 */
00052     SEM_NUMBER,                             /* セマフォの総数 */
00053 
00054     /* SEM_NUMBER分、以下を記述する */
00055     5,                                      /* セマフォ00の資源数 */
00056     4,
00057     3,
00058     2,
00059     1
00060 };
00061 
00062 #endif /* defined(_SYSAREA_H_)  */



3) main.c --- こんな感じでタスクとセマフォを登録して、タスク起動します。

00001 /*--------------------------------------------------------------------
00002  H8/300H用マイクロRTOS Ver1.0.0
00003 
00004  2007.03.08 新規作成
00005 
00006                                            Copyright(C) by MCM Co.,Ltd
00007 --------------------------------------------------------------------*/
00008 
00009 /* タスクのプロトタイプ */
00010 void task1(void);
00011 void task2(void);
00012 void task3(void);
00013 void task4(void);
00014 void task5(void);
00015 
00016 #include "kernel.h"
00017 #include "sysarea.h"            /* タスクのプロトタイプ決定後に読む */
00018 
00019 /* I/Oポートアドレス */
00020 #define IO_PA_DAT (*(volatile unsigned char *)0xFFFFD3)
00021 #define IO_PB_DAT (*(volatile unsigned char *)0xFFFFD6)
00022 
00023 /********************************************************************/
00024 /*                                                                  */
00025 /* システム初期化処理                                               */
00026 /*                                                                  */
00027 /********************************************************************/
00028 int main(void)
00029 {
00030 extern void sock_init();
00031 
00032     /* ここでタスクを生成します */
00033     reg_tsk((struct TSK_INF *)&TSK_INF);
00034 
00035     /* ここでセマフォを生成します */
00036     reg_sem((struct SEM_INF *)&SEM_INF);
00037 
00038     /* 必要なタスクを起動します */
00039     wup_tsk(0);
00040     wup_tsk(1);
00041     wup_tsk(3); // ボタン入力処理
00042     wup_tsk(4); // 受信監視タスクの起動
00043 
00044 
00045     /* リターンする事により各タスクへ制御が移ります */
00046     return 0;
00047 }
00048 
00049 
00050 /********************************************************************/
00051 /*                                                                  */
00052 /*                                                                  */
00053 /*                                                                  */
00054 /********************************************************************/
00055 void task1()
00056 {
00057     while(1) {
00058         IO_PB_DAT ^= 0x01;
00059         dly_tsk(30);
00060         IO_PB_DAT ^= 0x01;
00061         dly_tsk(1234);
00062     }
00063 }
00064 
00065 
00066 /********************************************************************/
00067 /*                                                                  */
00068 /*                                                                  */
00069 /*                                                                  */
00070 /********************************************************************/
00071 void task2()
00072 {
00073     while(1) {
00074         IO_PB_DAT ^= 0x02;
00075         wai_sem(0);
00076         sig_sem(0);
00077         dly_tsk(876);
00078     }
00079 }

以下、ソース割愛

とりあえず、タスクが切り替わり、時間待ちや、他タスク起動とかはできます。
本当は、プライオリティ・インヘリタンスとか色々な技があるのですが、基礎中の基礎という感じで、以降のソース類は参考までに:-b

小さなRTOSみたいなものを動かす/1 システム初期化
小さなRTOSみたいなものを動かす/2 ディスパッチ処理
小さなRTOSみたいなものを動かす/3 タイマー割り込み
小さなRTOSみたいなものを動かす/4 システムコール(1)
小さなRTOSみたいなものを動かす/5 システムコール(2)
小さなRTOSみたいなものを動かす/6 システムコール(3)
小さなRTOSみたいなものを動かす/7 システムコール(4)
小さなRTOSみたいなものを動かす/8 インクルード・ファイル

*1 単なるコントローラ的なものなら、わざわざOSなくてもね。
最終更新のRSS
Last-modified: 2010-07-14 (水) 13:01:21 2779日前
HTML convert time: 0.051 sec.