IOT联接管理作业
一、动手实验 —— 体验任务的创建与切换
实验内容
本实验中将创建两个任务,一个低优先级任务task1,一个高优先级任务task2,两个任务都会每隔2s在串口打印自己的任务id号,在串口终端中观察两个任务的运行情况。
实验代码
首先打开之前创建的 HelloWorld 工程,基于此工程进行实验。
在Demo
文件夹右击,选择新建文件夹:
新建osal_kernel_demo
文件夹,用于存放内核的实验文件:
接下来在此osal_kernel_demo
文件夹中新建第一个实验文件osal_task_demo.c
文件,开始编写代码:
/* 使用osal接口需要包含该头文件 */
#include
/* 任务优先级宏定义(shell任务的优先级为10) */
#define USER_TASK1_PRI 12 //低优先级
#define USER_TASK2_PRI 11 //高优先级
/* 任务ID */
uint32_t user_task1_id = 0;
uint32_t user_task2_id = 0;
/* 任务task1入口函数 */
static int user_task1_entry()
{
int n = 0;
/* 每隔2s在串口打印一次,打印5次后主动结束 */
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");
/* 任务结束 */
return 0;
}
/* 任务task2入口函数 */
static int user_task2_entry()
{
/* 每隔2s在串口打印一次,不结束 */
while (1)
{
printf("task 2: my task id is %ld!\r\n", user_task2_id);
/* 任务主动挂起2s */
osal_task_sleep(2*1000);
}
}
/* 标准demo启动函数,函数名不要修改,否则会影响下一步实验 */
int standard_app_demo_main()
{
/* 创建任务task1 */
user_task1_id = osal_task_create("user_task1",user_task1_entry,NULL,0x400,NULL,USER_TASK1_PRI);
/* 创建任务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
添加位置如图:
这段代码的意思是:
如果 CONFIG_USER_DEMO 宏定义的值是osal_task_demo
,则将osal_task_demo.c
文件加入到makefile中进行编译。
那么,如何配置 CONFIG_USER_DEMO 宏定义呢?在工程根目录下的.sdkconfig
文件中的末尾即可配置:
因为我们修改了mk配置文件,所以点击重新编译按钮
进行编译,编译完成后点击下载按钮烧录程序。
实验现象
程序烧录之后,即可看到程序已经开始运行,在串口终端中可看到实验的输出内容:
linkmain:V1.2.1 AT 11:30:59 ON Nov 28 2019
WELCOME TO IOT_LINK SHELL
LiteOS:/>task 2: my task id is 5!
task1: my task id is 4, n = 0!
task 2: my task id is 5!
task1: my task id is 4, n = 1!
task 2: my task id is 5!
task1: my task id is 4, n = 2!
task 2: my task id is 5!
task1: my task id is 4, n = 3!
task 2: my task id is 5!
task1: my task id is 4, n = 4!
task 2: my task id is 5!
user task 1 exit!
task 2: my task id is 5!
……
总结
系统启动后,首先打印版本号,串口shell的优先级为10,最先打印shell信息,接下来task1先创建,但是优先级较低,所以后创建的task2抢占执行,task2打印后主动挂起2s,这时task1开始执行,依次执行5次后task1结束,task2一直保持运行。
二、动手实验 —— 使用互斥锁进行资源保护
实验内容
本实验中将创建两个任务,一个低优先级任务task1,一个高优先级任务task2,两个任务之间依次对共享资源上锁、操作、解锁,在串口终端中观察两个任务的运行情况。
实验代码
首先打开上一篇使用的 HelloWorld 工程,基于此工程进行实验。
在Demo文件夹右击,新建文件夹osal_kernel_demo
用于存放内核的实验文件
接下来在此文件夹中新建一个实验文件 osal_mutex_demo.c
,开始编写代码:
/* 使用osal接口需要包含该头文件 */
#include
/* 任务优先级宏定义(shell任务的优先级为10) */
#define USER_TASK1_PRI 12 //低优先级
#define USER_TASK2_PRI 11 //高优先级
/* 共享资源 */
uint32_t public_value = 0;
/* 互斥锁索引ID */
osal_mutex_t public_value_mutex;
/* 任务task1入口函数 */
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);
/* 满足条件则结束任务 */
if(public_value > 100)
break;
}
}
/* while(1)会执行结束,所以需要返回值 */
return 0;
}
/* 任务task2入口函数 */
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);
/* 满足条件则结束任务 */
if(public_value > 90)
break;
/* 优先级较高,需要挂起一下,让task1获取到互斥锁,否则task2再次上锁,形成死锁 */
osal_task_sleep(10);
}
}
/* while(1)会执行结束,所以需要返回值 */
return 0;
}
/* 标准demo启动函数,函数名不要修改,否则会影响下一步实验 */
int standard_app_demo_main()
{
/* 创建互斥锁public_value_mutex */
osal_mutex_create(&public_value_mutex);
/* 创建任务task1 */
osal_task_create("user_task1",user_task1_entry,NULL,0x400,NULL,USER_TASK1_PRI);
/* 创建任务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配置文件,所以点击重新编译按钮进行编译,编译完成后点击下载按钮烧录程序。
实验现象
程序烧录之后,即可看到程序已经开始运行,在串口终端中可看到实验的输出内容:
linkmain:V1.2.1 AT 11:30:59 ON Nov 28 2019
WELCOME TO IOT_LINK SHELL
LiteOS:/>
task2: lock a mutex.
task2: public_value = 5.
task2: unlock a mutex.
task1: lock a mutex.
task1: public_value = 15.
task1: unlock a mutex.
task1: lock a mutex.
task1: public_value = 25.
task1: unlock a mutex.
task2: lock a mutex.
task2: public_value = 30.
task2: unlock a mutex.
task1: lock a mutex.
task1: public_value = 40.
task1: unlock a mutex.
task1: lock a mutex.
task1: public_value = 50.
task1: unlock a mutex.
task2: lock a mutex.
task2: public_value = 55.
task2: unlock a mutex.
task1: lock a mutex.
task1: public_value = 65.
task1: unlock a mutex.
task1: lock a mutex.
task1: public_value = 75.
task1: unlock a mutex.
task2: lock a mutex.
task2: public_value = 80.
task2: unlock a mutex.
task1: lock a mutex.
task1: public_value = 90.
task1: unlock a mutex.
task1: lock a mutex.
task1: public_value = 100.
task1: unlock a mutex.
task2: lock a mutex.
task2: public_value = 105.
task2: unlock a mutex.
总结
首先打印版本号,串口shell的优先级为10,最先打印shell信息,接下来task1先创建,但是优先级较低,所以后创建的task2抢占执行,task2获取到互斥锁,对共享资源进行操作,操作完毕解锁,然后主动挂起,task1获取到互斥锁,对共享资源进行另一个操作,操作完毕解锁,在task1操作的时候,task2早已挂起完毕,但是获取不到互斥锁,所以挂起等待,在task1解锁后,堵塞的task2被唤醒开始执行。
三、动手实验 —— 测试动态内存分配的最大字节
实验内容
本实验中将创建一个任务,从最小字节开始,不停的申请分配内存,释放分配的内存,直到申请失败,串口终端中观察可以申请到的最大字节。
实验代码
首先打开上一篇使用的 HelloWorld 工程,基于此工程进行实验。
在Demo文件夹右击,新建文件夹osal_kernel_demo
用于存放内核的实验文件
接下来在此文件夹中新建一个实验文件 osal_mem_demo.c
,开始编写代码:
/* 使用osal接口需要包含该头文件 */
#include
/* 任务入口函数 */
static int mem_access_task_entry()
{
uint32_t i = 0; //循环变量
size_t mem_size; //申请的内存块大小
uint8_t* mem_ptr = NULL; //内存块指针
while (1)
{
/* 每次循环将申请内存的大小扩大一倍 */
mem_size = 1 << i++;
/* 尝试申请分配内存 */
mem_ptr = osal_malloc(mem_size);
/* 判断是否申请成功 */
if(mem_ptr != NULL)
{
/* 申请成功,打印信息 */
printf("access %d bytes memory success!\r\n", mem_size);
/* 释放申请的内存,便于下次申请 */
osal_free(mem_ptr);
/* 将内存块指针置为NULL,避免称为野指针 */
mem_ptr = NULL;
printf("free memory success!\r\n");
}
else
{
/* 申请失败,打印信息,任务结束 */
printf("access %d bytes memory failed!\r\n", mem_size);
return 0;
}
}
}
/* 标准demo启动函数,函数名不要修改,否则会影响下一步实验 */
int standard_app_demo_main()
{
/* 创建任务,任务优先级为11,shell任务的优先级为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配置文件,所以点击重新编译按钮进行编译,编译完成后点击下载按钮烧录程序。
实验现象
程序烧录之后,即可看到程序已经开始运行,在串口终端中可看到实验的输出内容:
linkmain:V1.2.1 AT 11:30:59 ON Nov 28 2019
WELCOME TO IOT_LINK SHELL
LiteOS:/>access 1 bytes memory success!
free memory success!
access 2 bytes memory success!
free memory success!
access 4 bytes memory success!
free memory success!
access 8 bytes memory success!
free memory success!
access 16 bytes memory success!
free memory success!
access 32 bytes memory success!
free memory success!
access 64 bytes memory success!
free memory success!
access 128 bytes memory success!
free memory success!
access 256 bytes memory success!
free memory success!
access 512 bytes memory success!
free memory success!
access 1024 bytes memory success!
free memory success!
access 2048 bytes memory success!
free memory success!
access 4096 bytes memory success!
free memory success!
access 8192 bytes memory success!
free memory success!
access 16384 bytes memory success!
free memory success!
access 32768 bytes memory failed!
总结:
可系统启动后,首先打印版本号,串口shell的优先级为10,最先打印shell信息,接下来内存申请任务创建开始执行,在该芯片上最大能申请的空间为 16384
字节。