LiteOS-任务篇
前言
移植好内核后,开始实战内核。
链接
参考
- 野火
- 上面链接
笔录草稿
基本概念
- 任务是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源,并独立于其它任务运行
- 任务与线程
- 在 LiteOS 中,一个任务可以表示一条线程。
- Huawei LiteOS的任务一共有 32 个优先级(0-31),最高优先级为0,最低优先级为31。
任务相关概念
任务状态
- 就绪 (Ready)
- 运行(Running)
- 运行(Running)
- 退出态(Dead)
任务ID
- 可通过 任务ID 获取 任务句柄
***任务句柄*** = (((LOS_TASK_CB *)g_pstTaskCBArray) + (TaskID))
- 可通过 任务ID 获取 任务句柄
任务控制块TCB
- TCB 包含了任务上下文栈指针(stack pointer)、任务状态、任务优先级、任务ID、任务名、任务栈大小等信息。TCB 可以反映出每个任务运行情况。(TCB 其实就是一个袜子)
任务栈
- 每一个任务都拥有一个独立的栈空间,称为任务栈。
任务上下文切换 (个人把上下文分开理解)
- ** Huawei LiteOS** 在任务由运行态转为其它状态时会将本任务的上文信息,保存在自己的任务栈里面,也称压栈或入栈;
- 当任务切换到运行态时,把保存到任务栈中的上文信息加载到CPU寄存器中,即可恢复该任务的运行,称为出栈。新的任务信息也就是下文。
- 以上流程就是 上文压栈 --> 下文出栈。
LiteOS 任务运作机制
- Huawei LiteOS 任务管理模块提供
- 任务创建
- 任务删除
- 任务延时
- 任务挂起
- 任务恢复
- 更改任务优先级
- 锁定任务调度
- 解锁任务调度
- 根据任务控制块查询任务ID
- 根据ID查询任务查询任务控制块信息功能。
- 任务创建时,如果 OS 的系统可用空间少于任务,则创建失败,反之亦然。
- 用户创建任务时,系统会将任务栈进行初始化,预置上下文。
- 任务入口函数 也放到了相应的位置,在任务第一次执行时便可执行 任务入口函数。
内核初始化
一般的 RTOS 启动流程:MCU进入 main 函数 --> 创建任务 --> 启动 RTOS。
- 当然,在启动的过程中可以插入一些操作,如板级初始化
bspInit();等等
- 当然,在启动的过程中可以插入一些操作,如板级初始化
而 Huawei LiteOS 的启动流程则要多一步:MCU进入 main 函数 --> LiteOS内核初始化 --> 创建任务 --> 启动 RTOS。
- 在操作 LiteOS 必须先初始化其内核。
- 函数
LOS_KernelInit();(带返回值)。
内核初始化主要工作
- 配置任务数量上限
- 内存起始地址
- 初始化动态内存池(如果内存溢出,则内核初始化失败)
- 接管中断处理(非接管中断跳过)
- 任务初始化
- 先创建一个空闲任务
- 任务监视初始化
- CPU利用率初始化
- IPC通信初始化:信号量、互斥量、消息队列等等。
- 软件定时器初始化
- 该函数内会创建一个队列 和 一个定时任务
- 后续会在软件定时器相关篇章分析源码
- 该函数内会创建一个队列 和 一个定时任务
创建任务
创建任务有两种方案
- 方案一:
- 先创建所有任务
- 再启动调度
- 方案二:
- 先创建一个创建任务
- 然后启动调度
- 在创建任务里面创建所有任务
- 然后删除创建任务
本章实操的是方案二。
任务相关函数
| 接口名 | 描述 |
|---|---|
| LOS_TaskCreateOnly | 创建任务,并使该任务进入suspend状态,并不调度 |
| LOS_TaskCreate | 创建任务,并使该任务进入ready状态,并调度 |
| LOS_TaskDelete | 删除指定的任务 |
| LOS_TaskResume | 恢复挂起的任务 |
| LOS_TaskSuspend | 挂起指定的任务 |
| LOS_TaskDelay | 任务延时等待 |
| LOS_TaskYield | 显式放权,调整指定优先级的任务调度顺序 |
| LOS_TaskLock | 锁任务调度 |
| LOS_TaskUnlock | 解锁任务调度 |
| LOS_CurTaskPriSet | 设置当前任务的优先级 |
| LOS_TaskPriSet | 设置指定任务的优先级 |
| LOS_TaskPriGet | 获取指定任务的优先级 |
| LOS_CurTaskIDGet | 获取当前任务的ID |
| LOS_TaskInfoGet | 获取指定任务的信息 |
| LOS_TaskStatusGet | 获取指定任务的状态 |
| LOS_TaskNameGet | 获取指定任务的名称 |
| LOS_TaskInfoMonitor | 监控所有任务,获取所有任务的信息 |
| LOS_NextTaskIDGet | 获取即将被调度的任务的ID |
各函数使用可以看源码或者例程
任务开发流程
- 配置任务块
- 锁任务(防止高优先级任务调度)
- 创建任务
- 解锁任务
创建创建任务
部分源码
- 使用
LOS_TaskCreate函数- 需要一个 任务初始化参数结构体
TSK_INIT_PARAM_S和 一个任务句柄。
- 需要一个 任务初始化参数结构体
- TSK_INIT_PARAM_S 源码
/**
* @ingroup los_task
* Define the structure of the parameters used for task creation.
*
* Information of specified parameters passed in during task creation.
*/
typedef struct tagTskInitParam
{
TSK_ENTRY_FUNC pfnTaskEntry; /**< Task entrance function */
UINT16 usTaskPrio; /**< Task priority */
UINT32 uwArg; /**< Task parameters */
UINT32 uwStackSize; /**< Task stack size */
CHAR *pcName; /**< Task name */
UINT32 uwResved; /**< Reserved */
} TSK_INIT_PARAM_S;
例子
- 把创建创建任务的工作放到一个函数里
- 这里使用宏,是因为方便管理,框架是基于本人编写的框架。需要移植的可以直接填写数值。
lssConfigvStartTaskPRIO一个数值,表示优先级。lssConfigvStartTaskSIZE一个数值,表示堆空间字节数。- 注意:这里表示的是字节数,其它 RTOS 可能会表示 字数
- 如:FreeRTOS 中任务堆空间赋值就是以 字数 为单位。
- 一个 字数 表示多个 字节,看CPU架构是多少位的
- 如:32位CPU,一个字 = 四个字节 / word = 4byte
- 注意:这里表示的是字节数,其它 RTOS 可能会表示 字数
- 这里使用宏,是因为方便管理,框架是基于本人编写的框架。需要移植的可以直接填写数值。
/**
* @brief 创建一个LED任务
* @param
* @retval
* @author lzm
*/
static UINT32 Creat_vStartTask_Task()
{
UINT32 uwRet = LOS_OK;// 定义一个返回值变量
TSK_INIT_PARAM_S task_init_param;// 定义一个任务参数结构体
task_init_param.usTaskPrio = lssConfigvStartTaskPRIO; /* 任务优先级,值越少,优先级越高 */
task_init_param.pcName = "Start_Task"; /* 任务名 */
task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)vStartTask; /* 回调函数 */
task_init_param.uwStackSize = lssConfigvStartTaskSIZE; /* 任务堆空间 */
uwRet = LOS_TaskCreate(&StartTask_Handle, &task_init_param); /* 创建任务 */
return uwRet;
}
创建任务的任务回调函数 vStartTask
/**
* @brief 创建任务
* @param
* @retval
* @author lzm
*/
void vStartTask (void )
{
UINT32 uwRet = LOS_OK;
UINTPTR uvIntSave;
/* 进入临界 */
uvIntSave = LOS_IntLock();
uwRet = Creat_vLedTask_Task();
if (uwRet != LOS_OK)
{
; // 创建失败
}
/* 删除创建任务 */
LOS_TaskDelete(StartTask_Handle);
/* 退出临界 */
(VOID)LOS_IntRestore(uvIntSave);
}
Led任务创建函数 Creat_vLedTask_Task
/**
* @brief Led任务
* @param
* @retval
* @author lzm
*/
static UINT32 Creat_vLedTask_Task()
{
UINT32 uwRet = LOS_OK;
TSK_INIT_PARAM_S task_init_param;
task_init_param.usTaskPrio = lssConfigvLedTaskPRIO;
task_init_param.pcName = "Led Task";
task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)vLedTask;
task_init_param.uwStackSize = lssConfigvLedTaskSIZE;
uwRet = LOS_TaskCreate(&LedTask_Handle, &task_init_param);
return uwRet;
}
Led任务回调函数 vLedTask
- 该函数在
LedTask.c文件中
/**
******************************************************************************
* @file LedTask.c
* @author lzm
* @version V1.0
* @date 2020-xx-xx
* @brief
* @attention
* 实验平台:LZM
******************************************************************************
*/
#include "LedTask.h"
void vLedTask( void )
{
/* 设备初始化 */
LSS_LED_Init();
/* 进入死循环 */
while(1)
{
LSS_LED_Flash(&LedA, LedA.cycle); // 设备业务
LOS_TaskDelay( 10 ); // 进入阻塞态
}
}
开启调度
/* 开启调度 */
LOS_Start();
LOS_Start 函数源码
- 具体的源码分析可看源码篇
- 主要内容
- 配置RTOS的节拍定时器
- 启动调度
/*****************************************************************************
Function : LOS_Start
Description : Task start function
Input : None
Output : None
Return : LOS_OK on success or error code on failure
*****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_Start(VOID)
{
UINT32 uwRet;
/* 判断是否使用专用定时器 */
#if (LOSCFG_BASE_CORE_TICK_HW_TIME == NO) // 不使用专门的定时器
uwRet = osTickStart(); // 开启调度
if (uwRet != LOS_OK)
{
PRINT_ERR("osTickStart error\n");
return uwRet;
}
#else // 使用专门的定时器
extern int os_timer_init(void);
uwRet = os_timer_init(); // RTOS 配置的专用定时器
if (uwRet != LOS_OK)
{
PRINT_ERR("os_timer_init error\n");
return uwRet;
}
#endif
LOS_StartToRun(); // 启动调度,汇编
return uwRet;
}
附件
任务错误码列表
| 序号 | 定义 | 实际数值 | 描述 | 参考解决方案 |
|---|---|---|---|---|
| 1 | LOS_ERRNO_TSK_NO_MEMORY | 0x03000200 | 内存空间不足 | 分配更大的内存分区 |
| 2 | LOS_ERRNO_TSK_PTR_NULL | 0x02000201 | 任务参数为空 | 检查任务参数 |
| 3 | LOS_ERRNO_TSK_STKSZ_NOT_ALIGN | 0x02000202 | 任务栈大小未对齐 | 对齐任务栈 |
| 4 | LOS_ERRNO_TSK_PRIOR_ERROR | 0x02000203 | 不正确的任务优先级 | 检查任务优先级 |
| 5 | LOS_ERRNO_TSK_ENTRY_NULL | 0x02000204 | 务入口函数为空 | 定义任务入口函数 |
| 6 | LOS_ERRNO_TSK_NAME_EMPTY | 0x02000205 | 任务名为空 | 设置任务名 |
| 7 | LOS_ERRNO_TSK_STKSZ_TOO_SMALL | 0x02000206 | 任务栈太小 | 扩大任务栈 |
| 8 | LOS_ERRNO_TSK_ID_INVALID | 0x02000207 | 无效的任务ID | 检查任务ID |
| 9 | LOS_ERRNO_TSK_ALREADY_SUSPENDED | 0x02000208 | 任务已经被挂起 | 等待这个任务被恢复后,再去尝试挂起这个任务 |
| 10 | LOS_ERRNO_TSK_NOT_SUSPENDED | 0x02000209 | 任务未被挂起 | 挂起这个任务 |
| 11 | LOS_ERRNO_TSK_NOT_CREATED | 0x0200020a | 任务未被创建 | 创建这个任务 |
| 12 | LOS_ERRNO_TSK_OPERATE_SWTMR | 0x02000222 | 不允许操作软件定时器任务 | 用户不要试图去操作软件定时器任务的设置 |
| 13 | LOS_ERRNO_TSK_MSG_NONZERO | 0x0200020c | 任务信息非零 | 暂不使用该错误码 |
| 14 | LOS_ERRNO_TSK_DELAY_IN_INT | 0x0300020d | 中断期间,进行任务延时 | 等待退出中断后再进行延时操作 |
| 15 | LOS_ERRNO_TSK_DELAY_IN_LOCK | 0x0200020e | 任务被锁的状态下,进行延时 | 等待解锁任务之后再进行延时操作 |
| 16 | LOS_ERRNO_TSK_YIELD_INVALID_TASK | 0x0200020f | 将被排入行程的任务是无效的 | 检查这个任务 |
| 17 | LOS_ERRNO_TSK_YIELD_NOT_ENOUGH_TASK | 0x02000210 | 没有或者仅有一个可用任务能进行行程安排 | 增加任务数 |
| 18 | LOS_ERRNO_TSK_TCB_UNAVAILABLE | 0x02000211 | 没有空闲的任务控制块可用 | 增加任务控制块数量 |
| 19 | LOS_ERRNO_TSK_HOOK_NOT_MATCH | 0x02000212 | 任务的钩子函数不匹配 | 暂不使用该错误码 |
| 20 | LOS_ERRNO_TSK_HOOK_IS_FULL | 0x02000213 | 任务的钩子函数数量超过界限 | 暂不使用该错误码 |
| 21 | LOS_ERRNO_TSK_OPERATE_IDLE | 0x02000214 | 这是个IDLE任务 | 检查任务ID,不要试图操作IDLE任务 |
| 22 | LOS_ERRNO_TSK_SUSPEND_LOCKED | 0x03000215 | 将被挂起的任务处于被锁状态 | 等待任务解锁后再尝试挂起任务 |
| 23 | LOS_ERRNO_TSK_FREE_STACK_FAILED | 0x02000217 | 任务栈free失败 | 该错误码暂不使用 |
| 24 | LOS_ERRNO_TSK_STKAREA_TOO_SMALL | 0x02000218 | 任务栈区域太小 | 该错误码暂不使用 |
| 25 | LOS_ERRNO_TSK_ACTIVE_FAILED | 0x03000219 | 任务触发失败 | 创建一个IDLE任务后执行任务转换 |
| 26 | LOS_ERRNO_TSK_CONFIG_TOO_MANY | 0x0200021a | 过多的任务配置项 | 该错误码暂不使用 |
| 27 | LOS_ERRNO_TSK_CP_SAVE_AREA_NOT_ALIGN | 0x0200021b | 暂无 | 该错误码暂不使用 |
| 28 | LOS_ERRNO_TSK_MSG_Q_TOO_MANY | 0x0200021d | 暂无 | 该错误码暂不使用 |
| 29 | LOS_ERRNO_TSK_CP_SAVE_AREA_NULL | 0x0200021e | 暂无 | 该错误码暂不使用 |
| 30 | LOS_ERRNO_TSK_SELF_DELETE_ERR | 0x0200021f | 暂无 | 该错误码暂不使用 |
| 31 | LOS_ERRNO_TSK_STKSZ_TOO_LARGE | 0x02000220 | 任务栈大小设置过大 | 减小任务栈大小 |
| 32 | LOS_ERRNO_TSK_SUSPEND_SWTMR_NOT_ALLOWED | 0x02000221 | 不允许挂起软件定时器任务 | 检查任务ID, 不要试图挂起软件定时器任务 |
LiteOS-任务篇的更多相关文章
- 【LiteOS】LiteOS任务篇-源码分析-创建任务函数
目录 前言 链接 参考 笔录草稿 部分源码分析 源码分析 LOS_TaskCreate函数 LOS_TaskCreateOnly函数 宏 OS_TCB_FROM_PENDLIST 和 宏 LOS_DL ...
- 【LiteOS】Liteos移植篇
目录 前言 链接 参考 笔录草稿 移植(2018) 移植获取 (Cortex-M 内核) 主要文件夹分析 移植过程 1. 拷贝文件 2. 创建工程分组 3. 添加头文件路径 4. 兼容 C99 模式 ...
- TGL站长关于常见问题的回复
问题地址: http://www.thegrouplet.com/thread-112923-1-1.html 问题: 网站配有太多的模板是否影响网站加载速度 月光答复: wp不需要删除其他的模板,不 ...
- 华为LiteOS系统使用-任务调度函数-第一篇
1.最近项目遇到华为的LiteOS小型操作系统,使用学习 2. 先打开一个工程LiteOS_Kernel-master\projects\LPC824_LITE_KEIL 3. main.c里面2个关 ...
- 【LiteOS】STM32F103-LiteOS移植教程(详细篇)【华为云技术分享】
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...
- 【LiteOS】STM32F103-LiteOS移植教程(详细篇)
总览 本文基于STM32F103C8T6,详细讲述华为LiteOS的移植过程.开发工具是MDK5.LiteOS官方已经适配过cortex M系列内核的单片机,因此移植过程非常简单. LiteOS有两种 ...
- 在秉火STM32F429挑战者开发板上移植Huawei LiteOS指南
昨天在B站上突然看到了一个短视频,是在正点原子的战舰V3开发板上移植华为的Huawei LiteOS操作系统,就是这个视频:看完鸿蒙OS发布会,试用华为的物联网操作系统Lite OS(B站),于是呢, ...
- LiteOS-任务篇-源码分析-系统启动函数
目录 前言 链接 参考 开启调度 LOS_Start 函数源码 osTickStart 函数源码 LOS_StartToRun 函数源码 前言 20201009 移植好内核后,开始实战内核. 源码分析 ...
- 鸿蒙内核源码分析(根文件系统) | 先挂到`/`上的文件系统 | 百篇博客分析OpenHarmony源码 | v66.01
百篇博客系列篇.本篇为: v66.xx 鸿蒙内核源码分析(根文件系统) | 先挂到/上的文件系统 | 51.c.h.o 文件系统相关篇为: v62.xx 鸿蒙内核源码分析(文件概念篇) | 为什么说一 ...
随机推荐
- UI 科学
以简书为案例讲述「尼尔森十大可用性原则」 http://www.jianshu.com/p/a45e4ad68e20 你真的懂得尼尔森的十大可用性原则么? http://jy.sccnn.com/po ...
- Mono嵌入C++
http://docs.go-mono.com/index.aspx?link=xhtml%3Adeploy%2Fmono-api-embedding.html https://www.mono-pr ...
- [BUUOJ记录] [BJDCTF2020]EasySearch
前面的突破点考察swp泄露以及md5截断认证,最后一步考察ssi注入 进入题目是一个登陆页面什么提示都没有,工具扫了一下发现swp泄露,得到登录验证页面的源码: <?php ob_start() ...
- Java的枚举简单应用
/** * 请用枚举方式实现如下应用: * 客户去旅店住房, * 客户分普通客户,和vip客户,vip分白金和钻石客户 * 不同的客户有不同的折扣 * 入住的房间分单人房,双人房和套房 * 不同的房间 ...
- 备忘录:SQL SERVER2014 出现:“Cannot find one or more components”
目录 1. 起因 2. 解决方案 3. 备注 4. 参考 2020年9月13日 00:40:09-shanzm 1. 起因 因为卸载vs2015的时候,使用了一个VS2013/2015卸载工具Tota ...
- spring cloud微服务快速教程之(十二) 分布式ID解决方案(mybatis-plus篇)
0-前言 分布式系统中,分布式ID是个必须解决的问题点: 雪花算法是个好方式,不过不能直接使用,因为如果直接使用的话,需要配置每个实例workerId和datacenterId,在微服务中,实例一般动 ...
- Ansible剧本介绍及使用演示(3)
Ansible剧本编写说明 一. 缩进 yaml 的缩进要求比较严格.一定不能使用tab键 注意:编写yaml文件,就忘掉shell的tab吧. 二. 冒号 每个冒号后面一定要有一个空格 注意:1. ...
- 原生post请求
ajax: function(opt) { opt = opt || {}; opt.method = opt.method.toUpperCase() || 'POST'; opt.url = op ...
- CPF 入门教程 - 绘图(四)
CPF NetCore跨平台UI框架,增加了Vlc支持跨平台播放视频. 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) CPF 入门教程 - 样式和动画(三) CPF ...
- python安装scrapy库失败
解决方法: 首先,下载Twisted.cp后数字为python版本,例如cp36为python3.6:amd则表示系统位数,例如amd64为64位.下载对应版本即可.点击打开链接 找到Twisted, ...