特徴
- 初心者がUCOSIIIを知るのを手伝ってください
- タスクの作成と削除、タスクの一時停止と再開、ソフトウェアタイマー、セマフォと相互排除セマフォ、メッセージ送信など、UCOSIIIの基本的な知識を把握します。
1.はじめに
μC/ OS-IIはMicriumによって提供され、ポータブルで、硬化可能で、調整可能で、プリエンプティブなマルチタスクリアルタイムカーネルです。さまざまなマイクロプロセッサ、マイクロコントローラ、およびデジタル処理チップ(100種類以上に移植されています)に適しています。マイクロプロセッサアプリケーションの)。同時に、システムのソースコードはオープンでクリーンで一貫性があり、詳細なコメントが付いており、システム開発に適しています。μC/ OS-IIは、連邦航空局(FAA)の民間航空機認証に合格し、航空無線技術委員会(RTCA)のDO-178B規格に準拠しています。最新バージョンはμC/ OS-IIIです。
μC/ OS-IIは、コア、タスク処理、時間処理、タスクの同期と通信、CPU移植の5つの部分に大別できます。
- コア部分(OSCore.c)
は、オペレーティングシステムの初期化、オペレーティングシステムの操作、割り込みのリードインとアウト、クロックティック、タスクスケジューリング、イベント処理などを含む、オペレーティングシステムの処理コアです。システムの基本的な作業を維持できる部品はこちらです。 - タスク処理部分(OSTask.c)の内容は、タスク
の操作と密接に関連しています。タスクの作成、削除、一時停止、回復などを含みます。μC/ OS-IIはタスクに基づいてスケジュールされるため、コンテンツのこの部分も非常に重要です。 - クロック部分(OSTime.c)
μC/ OS-IIの最小クロック単位はタイムティック(クロックティック)です。タスク遅延などの操作はここで完了します。 - タスクの同期と通信の部分
は、セマフォ、メールボックス、メールボックスキュー、イベントフラグなどを含むイベント処理部分であり、主にタスク間の相互接続と重要なリソースへのアクセスに使用されます。 - CPU
とのインターフェース部分は、使用するCPUのμC/ OS-IIの移植部分を指します。μC/ OS-IIはユニバーサルオペレーティングシステムであるため、特定のCPUの特定のコンテンツと要件に応じて、重要な問題の実現を移植する必要があります。コンテンツのこの部分にはSPなどのシステムポインタが含まれているため、通常はアセンブリ言語で記述されています。これには主に、割り込みレベルのタスク切り替えの低レベルの実装、タスクレベルのタスク切り替えの最下位の実装、クロックビートの生成と処理、および関連する割り込みの処理が含まれます。
2.基礎知識
1.タスクの作成
①関連するパラメータを定義する
//任务优先级
#define LED1_TASK_PRIO 5
//任务堆栈大小
#define LED1_STK_SIZE 128
//任务控制块
OS_TCB Led1TaskTCB;
//任务堆栈
CPU_STK LED1_TASK_STK[LED1_STK_SIZE];
//任务函数
void led1_task(void *p_arg);
②タスクを作成する
//创建LED1任务
OSTaskCreate((OS_TCB * )&Led1TaskTCB,
(CPU_CHAR * )"led1 task",
(OS_TASK_PTR )led1_task,
(void * )0,
(OS_PRIO )LED1_TASK_PRIO,
(CPU_STK * )&LED1_TASK_STK[0],
(CPU_STK_SIZE)LED1_STK_SIZE/10,
(CPU_STK_SIZE)LED1_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR * )&err);
③タスク機能の書き込み
//led1任务函数
void led1_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
LED1=~LED1;
OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
}
}
2.タスクを一時停止および再開します
在这里插入代码片//task1任务函数
void task1_task(void *p_arg)
{
u8 task1_num=0;
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
POINT_COLOR = BLACK;
OS_CRITICAL_ENTER();
LCD_DrawRectangle(5,110,115,314); //画一个矩形
LCD_DrawLine(5,130,115,130); //画线
POINT_COLOR = BLUE;
LCD_ShowString(6,111,110,16,16,"Task1 Run:000");
OS_CRITICAL_EXIT();
while(1)
{
task1_num++; //任务1执行次数加1 注意task1_num1加到255的时候会清零!!
LED0= ~LED0;
printf("任务1已经执行:%d次\r\n",task1_num);
if(task1_num==5)
{
OSTaskSuspend((OS_TCB*)&Task2_TaskTCB,&err);//任务1执行5次后挂起任务2
printf("任务1挂起了任务2!\r\n");
}
if(task1_num==10)
{
OSTaskResume((OS_TCB*)&Task2_TaskTCB,&err); //任务1运行10次后恢复任务2
printf("任务1恢复了任务2!\r\n");
}
LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充区域
LCD_ShowxNum(86,111,task1_num,3,16,0x80); //显示任务执行次数
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s
}
}
3.タスクの同期
①セマフォを定義する
OS_SEM MY_SEM; //定义一个信号量,用于访问共享资源
②開始タスクでセマフォを作成する
OSSemCreate ((OS_SEM* )&MY_SEM, //创建一个信号量
(CPU_CHAR* )"MY_SEM",
(OS_SEM_CTR)1,
(OS_ERR* )&err);
③セマフォを使う
//led0任务函数
void led0_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
OSSemPend(&MY_SEM,0,OS_OPT_PEND_BLOCKING,0,&err); //请求信号量
LED0=~LED0;
// share_resource=share_resource+1;
// printf("任务1执行次数:%d\r\n",share_resource);
// delay_ms(1000);
// OSSemPost (&MY_SEM,OS_OPT_POST_1,&err); //发送信号量
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
}
}
//led1任务函数
void led1_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
LED1=~LED1;
OSSemPost (&MY_SEM,OS_OPT_POST_1,&err);
// OSSemPend(&MY_SEM,0,OS_OPT_PEND_BLOCKING,0,&err); //请求信号量
// share_resource=share_resource+1;
// printf("任务2执行次数:%d\r\n",share_resource);
//delay_ms(2000);
//发送信号量
OSTimeDlyHMSM(0,0,2,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
}
}
4.メッセージ配信
①メッセージキューを定義する
#define KEYMSG_Q_NUM 1 //按键消息队列的数量
#define DATAMSG_Q_NUM 4 //发送数据的消息队列的数量
OS_Q KEY_Msg; //定义一个消息队列,用于按键消息传递,模拟消息邮箱
OS_Q DATA_Msg; //定义一个消息队列,用于发送数据
②メッセージキューを作成する
//创建消息队列KEY_Msg
OSQCreate ((OS_Q* )&KEY_Msg, //消息队列
(CPU_CHAR* )"KEY Msg", //消息队列名称
(OS_MSG_QTY )KEYMSG_Q_NUM, //消息队列长度,这里设置为1
(OS_ERR* )&err); //错误码
//创建消息队列DATA_Msg
OSQCreate ((OS_Q* )&DATA_Msg,
(CPU_CHAR* )"DATA Msg",
(OS_MSG_QTY )DATAMSG_Q_NUM,
(OS_ERR* )&err);
③タスク機能
//定时器1的回调函数
void tmr1_callback(void *p_tmr,void *p_arg)
{
u8 *pbuf;
static u8 msg_num;
OS_ERR err;
pbuf = mymalloc(SRAMIN,10); //申请10个字节
if(pbuf) //申请内存成功
{
msg_num++;
sprintf((char*)pbuf,"ALIENTEK %d",msg_num);
//发送消息
OSQPost((OS_Q* )&DATA_Msg,
(void* )pbuf,
(OS_MSG_SIZE)10,
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR* )&err);
if(err != OS_ERR_NONE)
{
myfree(SRAMIN,pbuf); //释放内存
OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); //停止定时器1
tmr1sta = !tmr1sta;
LCD_ShowString(10,150,100,16,16,"TMR1 STOP! ");
}
}
}
//主任务的任务函数
void main_task(void *p_arg)
{
u8 key,num;
OS_ERR err;
u8 *p;
while(1)
{
key = KEY_Scan(0); //扫描按键
if(key)
{
//发送消息
OSQPost((OS_Q* )&KEY_Msg,
(void* )&key,
(OS_MSG_SIZE)1,
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR* )&err);
}
num++;
if(num%10==0) check_msg_queue(p);//检查DATA_Msg消息队列的容量
if(num==50)
{
num=0;
LED0 = ~LED0;
}
OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err); //延时10ms
}
}
//按键处理任务的任务函数
void Keyprocess_task(void *p_arg)
{
u8 num;
u8 *key;
OS_MSG_SIZE size;
OS_ERR err;
while(1)
{
//请求消息KEY_Msg
key=OSQPend((OS_Q* )&KEY_Msg,
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(OS_MSG_SIZE* )&size,
(CPU_TS* )0,
(OS_ERR* )&err);
switch(*key)
{
case WKUP_PRES: //KEY_UP控制LED1
LED1 = ~LED1;
break;
case KEY2_PRES: //KEY2控制蜂鸣器
BEEP = ~BEEP;
break;
case KEY0_PRES: //KEY0刷新LCD背景
num++;
LCD_Fill(126,111,233,313,lcd_discolor[num%14]);
break;
case KEY1_PRES: //KEY1控制定时器1
tmr1sta = !tmr1sta;
if(tmr1sta)
{
OSTmrStart(&tmr1,&err);
LCD_ShowString(10,150,100,16,16,"TMR1 START!");
}
else
{
OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); //停止定时器1
LCD_ShowString(10,150,100,16,16,"TMR1 STOP! ");
}
break;
}
}
}
//显示消息队列中的消息
void msgdis_task(void *p_arg)
{
u8 *p;
OS_MSG_SIZE size;
OS_ERR err;
while(1)
{
//请求消息
p=OSQPend((OS_Q* )&DATA_Msg,
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(OS_MSG_SIZE* )&size,
(CPU_TS* )0,
(OS_ERR* )&err);
LCD_ShowString(5,270,100,16,16,p);
myfree(SRAMIN,p); //释放内存
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s
}
}