任務一 體驗任務的創(chuàng)建與切換
實驗內(nèi)容
本實驗中將創(chuàng)建兩個任務,一個低優(yōu)先級任務task1,一個高優(yōu)先級任務task2,兩個任務都會每隔2s在串口打印自己的任務id號,在串口終端中觀察兩個任務的運行情況。
實驗代碼
首先打開之前創(chuàng)建的 HelloWorld 工程,基于此工程進行實驗。



/* 使用osal接口需要包含該頭文件 */
#include <osal.h>
/* 任務優(yōu)先級宏定義(shell任務的優(yōu)先級為10) */
#define USER_TASK1_PRI 12 //低優(yōu)先級
#define USER_TASK2_PRI 11 //高優(yōu)先級
/* 任務ID */
uint32_t user_task1_id = 0;
uint32_t user_task2_id = 0;
/* 任務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);
/* 任務主動掛起2s */
osal_task_sleep(2*1000);
}
printf("user task 1 exit!\r\n");
/* 任務結(jié)束 */
return 0;
}
/* 任務task2入口函數(shù) */
static int user_task2_entry()
{
/* 每隔2s在串口打印一次,不結(jié)束 */
while (1)
{
printf("task 2: my task id is %ld!\r\n", user_task2_id);
/* 任務主動掛起2s */
osal_task_sleep(2*1000);
}
}
/* 標準demo啟動函數(shù),函數(shù)名不要修改,否則會影響下一步實驗 */
int standard_app_demo_main()
{
/* 創(chuàng)建任務task1 */
user_task1_id = osal_task_create("user_task1",user_task1_entry,NULL,0x400,NULL,USER_TASK1_PRI);
/* 創(chuàng)建任務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
添加位置如圖:



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

可以看到,系統(tǒng)啟動后,首先打印版本號,串口shell的優(yōu)先級為10,最先打印shell信息,接下來task1先創(chuàng)建,但是優(yōu)先級較低,所以后創(chuàng)建的task2搶占執(zhí)行,task2打印后主動掛起2s,這時task1開始執(zhí)行,依次執(zhí)行5次后task1結(jié)束,task2一直保持運行。

任務二 LiteOS的互斥鎖
實驗內(nèi)容
本實驗中將創(chuàng)建兩個任務,一個低優(yōu)先級任務task1,一個高優(yōu)先級任務task2,兩個任務之間依次對共享資源上鎖、操作、解鎖,在串口終端中觀察兩個任務的運行情況。
實驗代碼
首先打開上一篇使用的 HelloWorld 工程,基于此工程進行實驗。
在Demo文件夾右擊,新建文件夾osal_kernel_demo用于存放內(nèi)核的實驗文件(如果已有請忽略這一步)。
接下來在此文件夾中新建一個實驗文件 osal_mutex_demo.c,開始編寫代碼:
/* 使用osal接口需要包含該頭文件 */
#include <osal.h>
/* 任務優(yōu)先級宏定義(shell任務的優(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;
/* 任務task1入口函數(shù) */
static int user_task1_entry()
{
while(1)
{
/* 嘗試獲取互斥鎖 */
if(true == osal_mutex_lock(public_value_mutex))
{
/* 獲取到互斥鎖,對共享資源進行操作 */
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é)束任務 */
if(public_value > 100)
break;
}
}
/* while(1)會執(zhí)行結(jié)束,所以需要返回值 */
return 0;
}
/* 任務task2入口函數(shù) */
static int user_task2_entry()
{
while (1)
{
/* 嘗試獲取互斥鎖 */
if(true == osal_mutex_lock(public_value_mutex))
{
/* 獲取到互斥鎖,對共享資源進行操作 */
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é)束任務 */
if(public_value > 90)
break;
/* 優(yōu)先級較高,需要掛起一下,讓task1獲取到互斥鎖,否則task2再次上鎖,形成死鎖 */
osal_task_sleep(10);
}
}
/* while(1)會執(zhí)行結(jié)束,所以需要返回值 */
return 0;
}
/* 標準demo啟動函數(shù),函數(shù)名不要修改,否則會影響下一步實驗 */
int standard_app_demo_main()
{
/* 創(chuàng)建互斥鎖public_value_mutex */
osal_mutex_create(&public_value_mutex);
/* 創(chuàng)建任務task1 */
osal_task_create("user_task1",user_task1_entry,NULL,0x400,NULL,USER_TASK1_PRI);
/* 創(chuàng)建任務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配置文件,添加如下代碼:
#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
添加位置如圖:

這段代碼的意思是:
如果 CONFIG_USER_DEMO 宏定義的值是osal_mutex_demo,則將osal_mutex_demo.c文件加入到makefile中進行編譯。
那么,如何配置 CONFIG_USER_DEMO 宏定義呢?在工程根目錄下的.sdkconfig文件中的末尾即可配置:
因為我們修改了mk配置文件,所以點擊重新編譯按鈕進行編譯,編譯完成后點擊下載按鈕燒錄程序。
實驗現(xiàn)象

可以看到,系統(tǒng)啟動后,首先打印版本號,串口shell的優(yōu)先級為10,最先打印shell信息,接下來task1先創(chuàng)建,但是優(yōu)先級較低,所以后創(chuàng)建的task2搶占執(zhí)行,task2獲取到互斥鎖,對共享資源進行操作,操作完畢解鎖,然后主動掛起,task1獲取到互斥鎖,對共享資源進行另一個操作,操作完畢解鎖,在task1操作的時候,task2早已掛起完畢,但是獲取不到互斥鎖,所以掛起等待,在task1解鎖后,堵塞的task2被喚醒開始執(zhí)行。
- 任務三 測試動態(tài)內(nèi)存分配的最大字節(jié)
實驗內(nèi)容
本實驗中將創(chuàng)建一個任務,從最小字節(jié)開始,不停的申請分配內(nèi)存,釋放分配的內(nèi)存,直到申請失敗,串口終端中觀察可以申請到的最大字節(jié)。
實驗代碼
首先打開上一篇使用的 HelloWorld 工程,基于此工程進行實驗。
在Demo文件夾右擊,新建文件夾osal_kernel_demo用于存放內(nèi)核的實驗文件(如果已有請忽略這一步)。
接下來在此文件夾中新建一個實驗文件 osal_mem_demo.c,開始編寫代碼:

/* 使用osal接口需要包含該頭文件 */
#include <osal.h>
/* 任務入口函數(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
{
/* 申請失敗,打印信息,任務結(jié)束 */
printf("access %d bytes memory failed!\r\n", mem_size);
return 0;
}
}
}
/* 標準demo啟動函數(shù),函數(shù)名不要修改,否則會影響下一步實驗 */
int standard_app_demo_main()
{
/* 創(chuàng)建任務,任務優(yōu)先級為11,shell任務的優(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
添加位置如圖:
這段代碼的意思是:
如果 CONFIG_USER_DEMO 宏定義的值是osal_mem_demo,則將osal_mem_demo.c文件加入到makefile中進行編譯。
那么,如何配置 CONFIG_USER_DEMO 宏定義呢?在工程根目錄下的.sdkconfig文件中的末尾即可配置:
因為我們修改了mk配置文件,所以點擊重新編譯按鈕進行編譯,編譯完成后點擊下載按鈕燒錄程序。
實驗現(xiàn)象
程序燒錄之后,即可看到程序已經(jīng)開始運行,在串口終端中可看到實驗的輸出內(nèi)容:![{[1_AY6Q$I)RWZ{~WF97_1.png
可以看到,系統(tǒng)啟動后,首先打印版本號,串口shell的優(yōu)先級為10,最先打印shell信息,接下來內(nèi)存申請任務創(chuàng)建開始執(zhí)行,在該芯片上最大能申請的空間為 16384 字節(jié)。