LiteOS內(nèi)核的任務(wù)管理
Huawei LiteOS 任務(wù)管理模塊提供任務(wù)創(chuàng)建、任務(wù)刪除、任務(wù)延時、任務(wù)掛起和任務(wù)恢復(fù)、更改任務(wù)優(yōu)先級、鎖任務(wù)調(diào)度和解鎖任務(wù)調(diào)度、根據(jù)任務(wù)控制塊查詢?nèi)蝿?wù) ID、根據(jù) ID 查詢?nèi)蝿?wù)控制塊信息功能。
1、任務(wù)的創(chuàng)建和管理
要求:本實驗中將創(chuàng)建兩個任務(wù),一個低優(yōu)先級任務(wù)task1,一個高優(yōu)先級任務(wù)task2,兩個任務(wù)都會每隔2s在串口打印自己的任務(wù)id號,在串口終端中觀察兩個任務(wù)的運行情況。
基于HELLO工程,進(jìn)行創(chuàng)建,在demo文件夾下創(chuàng)建oasl_kernel_demo文件存放內(nèi)核

接下來在此osal_kernel_demo文件夾中新建第一個實驗文件osal_task_demo.c文件,開始編寫代碼:
/* 使用osal接口需要包含該頭文件 */
#include <osal.h>
/* 任務(wù)優(yōu)先級宏定義(shell任務(wù)的優(yōu)先級為10) */
#define USER_TASK1_PRI 12 //低優(yōu)先級
#define USER_TASK2_PRI 11 //高優(yōu)先級
/* 任務(wù)ID */
uint32_t user_task1_id = 0;
uint32_t user_task2_id = 0;
/* 任務(wù)task1入口函數(shù) */
static int user_task1_entry()
{
int n = 0;
/* 每隔2s在串口打印一次,打印5次后主動結(jié)束 */
for(n = 0; n < 5; n++)
{
printf("task1: my task id is %ld, n = %d!\r\n", user_task1_id, n);
/* 任務(wù)主動掛起2s */
osal_task_sleep(2*1000);
}
printf("user task 1 exit!\r\n");
/* 任務(wù)結(jié)束 */
return 0;
}
/* 任務(wù)task2入口函數(shù) */
static int user_task2_entry()
{
/* 每隔2s在串口打印一次,不結(jié)束 */
while (1)
{
printf("task 2: my task id is %ld!\r\n", user_task2_id);
/* 任務(wù)主動掛起2s */
osal_task_sleep(2*1000);
}
}
/* 標(biāo)準(zhǔn)demo啟動函數(shù),函數(shù)名不要修改,否則會影響下一步實驗 */
int standard_app_demo_main()
{
/* 創(chuàng)建任務(wù)task1 */
user_task1_id = osal_task_create("user_task1",user_task1_entry,NULL,0x400,NULL,USER_TASK1_PRI);
/* 創(chuàng)建任務(wù)task2 */
user_task2_id = osal_task_create("user_task2",user_task2_entry,NULL,0x400,NULL,USER_TASK2_PRI);
return 0;

編寫完成之后,要將我們編寫的osal_task_demo.c文件添加到makefile中,加入整個工程的編譯:直接在直接修改Demo文件夾下的user_demo.mk配置文件,添加如下代碼:
#example for osal_task_demo
ifeq ($(CONFIG_USER_DEMO), "osal_task_demo")
user_demo_src = ${wildcard $(TOP_DIR)/targets/STM32L431_BearPi/Demos/osal_kernel_demo/osal_task_demo.c}
user_demo_defs = -D CONFIG_OSAL_TASK_DEMO_ENABLE=1
endif

接下來將osal_task_demo.c文件加入到makefile中進(jìn)行編譯。在工程根目錄下的.sdkconfig文件中的末尾即可配置:
CONFIG_USER_DEMO = "osal_task_demo"

因為我們修改了mk配置文件,所以點擊重新編譯按鈕進(jìn)行編譯,編譯完成后點擊下載按鈕燒錄程序。

燒錄過后,將串口打開,方法如下:


實驗現(xiàn)象:

總結(jié):可以看到,系統(tǒng)啟動后,首先打印版本號,串口shell的優(yōu)先級為10,最先打印shell信息,接下來task1先創(chuàng)建,但是優(yōu)先級為12,小于task2優(yōu)先級11,所以后創(chuàng)建的task2搶占執(zhí)行,task2輸出后主動掛起2s,這時低優(yōu)先級task1開始執(zhí)行,依次執(zhí)行5次后task1結(jié)束,task2一直保持運行。
2、LiteOS的互斥鎖
要求:本實驗中將創(chuàng)建兩個任務(wù),一個低優(yōu)先級任務(wù)task1,一個高優(yōu)先級任務(wù)task2,兩個任務(wù)之間依次對共享資源上鎖、操作、解鎖,在串口終端中觀察兩個任務(wù)的運行情況
實驗過程如下:
首先打開上一篇使用的 HelloWorld 工程,基于此工程進(jìn)行實驗。
在Demo文件夾右擊,新建文件夾osal_kernel_demo用于存放內(nèi)核的實驗文件,接下來在此文件夾中新建一個實驗文件 osal_mutex_demo.c

添加代碼如下:
/* 使用osal接口需要包含該頭文件 */
#include <osal.h>
/* 任務(wù)優(yōu)先級宏定義(shell任務(wù)的優(yōu)先級為10) */
#define USER_TASK1_PRI 12 //低優(yōu)先級
#define USER_TASK2_PRI 11 //高優(yōu)先級
/* 共享資源 */
uint32_t public_value = 0;
/* 互斥鎖索引ID */
osal_mutex_t public_value_mutex;
/* 任務(wù)task1入口函數(shù) */
static int user_task1_entry()
{
while(1)
{
/* 嘗試獲取互斥鎖 */
if(true == osal_mutex_lock(public_value_mutex))
{
/* 獲取到互斥鎖,對共享資源進(jìn)行操作 */
printf("\r\ntask1: lock a mutex.\r\n");
public_value += 10;
printf("task1: public_value = %ld.\r\n", public_value);
/* 對共享資源操作完畢,釋放互斥鎖 */
printf("task1: unlock a mutex.\r\n\r\n");
osal_mutex_unlock(public_value_mutex);
/* 滿足條件則結(jié)束任務(wù) */
if(public_value > 100)
break;
}
}
/* while(1)會執(zhí)行結(jié)束,所以需要返回值 */
return 0;
}
/* 任務(wù)task2入口函數(shù) */
static int user_task2_entry()
{
while (1)
{
/* 嘗試獲取互斥鎖 */
if(true == osal_mutex_lock(public_value_mutex))
{
/* 獲取到互斥鎖,對共享資源進(jìn)行操作 */
printf("\r\ntask2: lock a mutex.\r\n");
public_value += 5;
printf("task2: public_value = %ld.\r\n", public_value);
/* 對共享資源操作完畢,釋放互斥鎖 */
printf("task2: unlock a mutex.\r\n\r\n");
osal_mutex_unlock(public_value_mutex);
/* 滿足條件則結(jié)束任務(wù) */
if(public_value > 90)
break;
/* 優(yōu)先級較高,需要掛起一下,讓task1獲取到互斥鎖,否則task2再次上鎖,形成死鎖 */
osal_task_sleep(10);
}
}
/* while(1)會執(zhí)行結(jié)束,所以需要返回值 */
return 0;
}
/* 標(biāo)準(zhǔn)demo啟動函數(shù),函數(shù)名不要修改,否則會影響下一步實驗 */
int standard_app_demo_main()
{
/* 創(chuàng)建互斥鎖public_value_mutex */
osal_mutex_create(&public_value_mutex);
/* 創(chuàng)建任務(wù)task1 */
osal_task_create("user_task1",user_task1_entry,NULL,0x400,NULL,USER_TASK1_PRI);
/* 創(chuàng)建任務(wù)task2 */
osal_task_create("user_task2",user_task2_entry,NULL,0x400,NULL,USER_TASK2_PRI);
return 0;
編寫完成之后,要將我們編寫的 osal_mutex_demo.c文件添加到makefile中,加入整個工程的編譯:直接修改Demo文件夾下的user_demo.mk配置文件,添加如下代碼(跟上一個任務(wù)添加方式一樣,所以不再演示細(xì)節(jié))截圖如下:
#example for osal_mutex_demo
ifeq ($(CONFIG_USER_DEMO), "osal_mutex_demo")
user_demo_src = ${wildcard $(TOP_DIR)/targets/STM32L431_BearPi/Demos/osal_kernel_demo/osal_mutex_demo.c}
endif

將osal_mutex_demo.c文件加入到makefile中進(jìn)行編譯。在.sdkconfig中修改即可

重新編譯按鈕進(jìn)行編譯,編譯完成后點擊下載按鈕燒錄程序。
實驗現(xiàn)象如下:

總結(jié):可以看到,系統(tǒng)啟動后,首先打印版本號,串口shell的優(yōu)先級為10,最先打印shell信息,接下來優(yōu)先級高的task2執(zhí)行,獲得資源共享,執(zhí)行過后進(jìn)入鎖定狀態(tài),然后就是優(yōu)先級低的task1執(zhí)行,當(dāng)task1執(zhí)行過程中,task2是不能執(zhí)行的,必須有task1執(zhí)行完過后,解鎖完了,task2才能再次執(zhí)行。
3、LiteOS內(nèi)核的內(nèi)存管理
要求:本實驗中將創(chuàng)建一個任務(wù),從最小字節(jié)開始,不停的申請分配內(nèi)存,釋放分配的內(nèi)存,直到申請失敗,串口終端中觀察可以申請到的最大字節(jié)。
流程:
首先打開上一篇使用的 HelloWorld 工程,基于此工程進(jìn)行實驗。
在Demo文件夾右擊,新建文件夾osal_kernel_demo用于存放內(nèi)核的實驗文件
接下來在此文件夾中新建一個實驗文件 osal_mem_demo.c,開始編寫代碼:

代碼如下:
/* 使用osal接口需要包含該頭文件 */
#include <osal.h>
/* 任務(wù)入口函數(shù) */
static int mem_access_task_entry()
{
uint32_t i = 0; //循環(huán)變量
size_t mem_size; //申請的內(nèi)存塊大小
uint8_t* mem_ptr = NULL; //內(nèi)存塊指針
while (1)
{
/* 每次循環(huán)將申請內(nèi)存的大小擴大一倍 */
mem_size = 1 << i++;
/* 嘗試申請分配內(nèi)存 */
mem_ptr = osal_malloc(mem_size);
/* 判斷是否申請成功 */
if(mem_ptr != NULL)
{
/* 申請成功,打印信息 */
printf("access %d bytes memory success!\r\n", mem_size);
/* 釋放申請的內(nèi)存,便于下次申請 */
osal_free(mem_ptr);
/* 將內(nèi)存塊指針置為NULL,避免稱為野指針 */
mem_ptr = NULL;
printf("free memory success!\r\n");
}
else
{
/* 申請失敗,打印信息,任務(wù)結(jié)束 */
printf("access %d bytes memory failed!\r\n", mem_size);
return 0;
}
}
}
/* 標(biāo)準(zhǔn)demo啟動函數(shù),函數(shù)名不要修改,否則會影響下一步實驗 */
int standard_app_demo_main()
{
/* 創(chuàng)建任務(wù),任務(wù)優(yōu)先級為11,shell任務(wù)的優(yōu)先級為10 */
osal_task_create("mem_access_task",mem_access_task_entry,NULL,0x400,NULL,11);
return 0;
}
編寫完成之后,要將我們編寫的 osal_mem_demo.c文件添加到makefile中,加入整個工程的編譯直接修改Demo文件夾下的user_demo.mk配置文件,代碼如下:
#example for osal_mem_demo
ifeq ($(CONFIG_USER_DEMO), "osal_mem_demo")
user_demo_src = ${wildcard $(TOP_DIR)/targets/STM32L431_BearPi/Demos/osal_kernel_demo/osal_mem_demo.c}
endif

講osal_mem_demo.c文件加入到makefile中進(jìn)行編譯。
那么,如何配置 CONFIG_USER_DEMO 宏定義呢?在工程根目錄下的.sdkconfig文件中的末尾即可配置,操作如下:

重新編譯按鈕進(jìn)行編譯,編譯完成后點擊下載按鈕燒錄程序。
實驗現(xiàn)象:

總結(jié):可以看到,系統(tǒng)啟動后,首先打印版本號,串口shell的優(yōu)先級為10,最先打印shell信息,接下來內(nèi)存申請任務(wù)創(chuàng)建開始執(zhí)行,在該芯片上最大能申請的空間為 16384 字節(jié)。