LiteOS-任务篇-源码分析-系统启动函数
前言
- 20201009
- 移植好内核后,开始实战内核。
- 源码分析一般都在代码注释中。
- 本文LiteOS采用非接管中断方式。
- 本文源码基于 LiteOS 2018 源码,最新官方源码中都有注释,可参考。
- 本文源码与最新官方源码区别
- 原理一样,源码稍有不同,且最新官方源码中带有注释。
链接
- LiteOS源码链接
- 常见问题
- 华为开发者社区
- 华为LiteOS官方教程
- 我的源码
- 包含 裸机源码
- LiteOS 工程模板
- 其它关于 LiteOS 的 demo 及 note
参考
- 上面链接
开启调度
/* 开启调度 */
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;
}
osTickStart
函数源码
- 宏说明
OS_SYS_CLOCK
: 系统时钟频率,单位:Hz (硬系统时钟频率,即是CPU频率)LOSCFG_BASE_CORE_TICK_PER_SECOND
: 每秒心跳次数 (软系统时钟频率,即是RTOS频率)
- 主要内容为:
- 检查参数
- 配置RTOS系统时钟滴答定时器
/*****************************************************************************
Function : osTickStart
Description: Configure Tick Interrupt Start
Input : none
output : none
return : LOS_OK - Success , or LOS_ERRNO_TICK_CFG_INVALID - failed
*****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 osTickStart(VOID)
{
UINT32 uwRet;
if ((0 == OS_SYS_CLOCK)
|| (0 == LOSCFG_BASE_CORE_TICK_PER_SECOND)
|| (LOSCFG_BASE_CORE_TICK_PER_SECOND > OS_SYS_CLOCK))/*lint !e506*/ /* 如果每秒心跳次数设置大于系统时钟频率的设置,则,ERROR */
{
return LOS_ERRNO_TICK_CFG_INVALID;
}
#if (LOSCFG_PLATFORM_HWI == YES) // 开启中断接管
#if (OS_HWI_WITH_ARG == YES) // 参数配置项
osSetVector(SysTick_IRQn, (HWI_PROC_FUNC)osTickHandler, NULL); // 设置中断向量表
#else
osSetVector(SysTick_IRQn, osTickHandler); // 设置中断向量表
#endif
#endif
g_uwCyclesPerTick = OS_SYS_CLOCK / LOSCFG_BASE_CORE_TICK_PER_SECOND; // 算出每个心跳的周期
g_ullTickCount = 0;
uwRet = SysTick_Config(OS_SYS_CLOCK/LOSCFG_BASE_CORE_TICK_PER_SECOND); // 配置滴答定时器。参数为:两个中断之间的节拍数
if (uwRet == 1)
{
return LOS_ERRNO_TICK_PER_SEC_TOO_SMALL;
}
return LOS_OK;
}
LOS_StartToRun
函数源码
- 分析再源码注释中
- 简略步骤
- 将 SysTick 和 PendSVd 优先级设置为最低
- 将 g_bTaskScheduled 至为 1
- 设置控制寄存器为 CONTROL
- 更新当前运行任务
Set g_stLosTask.pstRunTask = g_stLosTask.pstNewTask;
- 更新当前运行任务的任务状态
Set g_stLosTask.pstRunTask->usTaskStatus |= OS_TASK_STATUS_RUNNING;
- 手动更新 PSP 值,恢复到栈顶
- 更新 LR 寄存器
- 开启中断
- 跳转到当前任务的 PC ,教继续运行任务。
- 简略步骤
LOS_StartToRun ;系统启动函数
;; C:*OS_NVIC_SYSPRI2 = OS_NVIC_PENDSV_PRI; // 配置 SysTick 与 PendSVd 的优先级(看图Priority config)
LDR R4, =OS_NVIC_SYSPRI2 ;OS_NVIC_SYSPRI2这个值给 R4
LDR R5, =OS_NVIC_PENDSV_PRI ;OS_NVIC_PENDSV_PRI这个值给 R5
STR R5, [R4] ;把 R5 的值存到 R4指定的地址中
;; C:g_bTaskScheduled = 1;
LDR R0, =g_bTaskScheduled ;; 把变量 g_bTaskScheduled 的地址赋给 R0
MOV R1, #1 ;把 1 赋值给 R1 寄存器
STR R1, [R0]
;; 把 2 赋给 程序状态寄存器 CONTROL
MOV R0, #2
MSR CONTROL, R0
;; C:g_stLosTask.pstRunTask = g_stLosTask.pstNewTask;
LDR R0, =g_stLosTask ;; R2 = g_stLosTask.pstNewTask;
LDR R2, [R0, #4] ;
LDR R0, =g_stLosTask ;; g_stLosTask.pstRunTask = g_stLosTask.pstNewTask;
STR R2, [R0]
;; C:g_stLosTask.pstRunTask->usTaskStatus = g_stLosTask.pstRunTask->usTaskStatus | OS_TASK_STATUS_RUNNING; // 把当前任务状态更新为 OS_TASK_STATUS_RUNNING
LDR R3, =g_stLosTask ;; R0 = g_stLosTask.pstRunTask;
LDR R0, [R3]
LDRH R7, [R0 , #4] ;; R7 = g_stLosTask.pstRunTask->usTaskStatus;;
MOV R8, #OS_TASK_STATUS_RUNNING
ORR R7, R7, R8 ;; R7 = g_stLosTask.pstRunTask->usTaskStatus | OS_TASK_STATUS_RUNNING
STRH R7, [R0 , #4] ;; g_stLosTask.pstRunTask->usTaskStatus = g_stLosTask.pstRunTask->usTaskStatus | OS_TASK_STATUS_RUNNING;
;; C: R12 = *(g_stLosTask.pstRunTask->pStackPointer) + 36; // 先偏移栈指针(手动出栈) (R4-R11, PRIMASK)
LDR R12, [R0] ;; R12 = *(g_stLosTask.pstRunTask->pStackPointer);
ADD R12, R12, #36 ;; R12 = R12 + 36; // 跳过任务中原本属于寄存器 (R4-R11, PRIMASK)的值
;; 把 R12 作为基地址,出栈。LDMFD:先出栈后递增
;; R12 出栈到 R0,R12 递增 4;R12 出栈到 R1,R12 递增 4;......
LDMFD R12!, {R0-R7} ;; 把任务中原本属于寄存器 (R0-R3, R12, LR, PC, xPSR) 中的值分别复制到 (R0-R7)
MSR PSP, R12 ;; 更新 PSP 指针
MOV LR, R5 ;; 任务中的 LR 指针值赋给 LR 寄存器
;MSR xPSR, R7 ;; 任务中的 xPSR 指针值赋给 xPSR 寄存器(屏蔽了)
CPSIE I ;; 开中断
BX R6 ;; 跳转到 当前任务的 PC 指针运行,并切换指令集
图-Priority config
该函数部分变量源码代码(参考)
- 文件 los_dispatch_keil.S 中
OS_NVIC_SYSPRI2 EQU 0xE000ED20
OS_NVIC_PENDSV_PRI EQU 0xF0F00000
- 文件 los_task.c 中
LITE_OS_SEC_BSS BOOL g_bTaskScheduled;
LITE_OS_SEC_BSS ST_LOS_TASK g_stLosTask;
- 文件 los_task.ph 中
- 文件 los_dispatch_keil.S 中
/**
* @ingroup los_task
* Define the task control block structure.
*/
typedef struct tagTaskCB
{
VOID *pStackPointer; /**< Task stack pointer */
UINT16 usTaskStatus;
UINT16 usPriority;
UINT32 uwStackSize; /**< Task stack size */
UINT32 uwTopOfStack; /**< Task stack top */
UINT32 uwTaskID; /**< Task ID */
TSK_ENTRY_FUNC pfnTaskEntry; /**< Task entrance function */
VOID *pTaskSem; /**< Task-held semaphore */
VOID *pTaskMux; /**< Task-held mutex */
UINT32 uwArg; /**< Parameter */
CHAR *pcTaskName; /**< Task name */
LOS_DL_LIST stPendList;
LOS_DL_LIST stTimerList;
UINT32 uwIdxRollNum;
EVENT_CB_S uwEvent;
UINT32 uwEventMask; /**< Event mask */
UINT32 uwEventMode; /**< Event mode */
VOID *puwMsg; /**< Memory allocated to queues */
} LOS_TASK_CB;
LiteOS-任务篇-源码分析-系统启动函数的更多相关文章
- 【LiteOS】LiteOS任务篇-源码分析-创建任务函数
目录 前言 链接 参考 笔录草稿 部分源码分析 源码分析 LOS_TaskCreate函数 LOS_TaskCreateOnly函数 宏 OS_TCB_FROM_PENDLIST 和 宏 LOS_DL ...
- LiteOS-任务篇-源码分析-任务调度函数
目录 前言 笔录草稿 核心源码分析 osTaskSchedule函数源码分析 osPendSV函数源码分析 TaskSwitch函数源码分析 调度上层源码分析 osSchedule函数源码分析 LOS ...
- 性能测试分享: Jmeter的源码分析main函数参数
性能测试分享: Jmeter的源码分析main函数参数 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大 ...
- jQuery源码分析-each函数
本文部分截取自且行且思 jQuery.each方法用于遍历一个数组或对象,并对当前遍历的元素进行处理,在jQuery使用的频率非常大,下面就这个函数做了详细讲解: 复制代码代码 /*! * jQuer ...
- LiteOS-任务篇-源码分析-删除任务函数
目录 前言 笔录草稿 源码分析 LOS_TaskDelete函数源码分析 完整源码 参考 链接 前言 20201009 LiteOS 2018 需要会通用链表 笔录草稿 源码分析 LOS_TaskDe ...
- Memcached源码分析——process_command函数解析
以下为个人笔记 /** * process_command 在memcached中是用来处理用户发送的命令的, * 包括get set,add,delete,replace,stats,flush_a ...
- vue2源码分析:patch函数
目录 1.patch函数的脉络 2.类vnode的设计 3.createPatch函数中的辅助函数和patch函数 4.源码运行展示(DEMO) 一.patch函数的脉络 首先梳理一下patch函数的 ...
- jquery源码分析-工具函数
jQuery的版本一路狂飙啊,现在都到了2.0.X版本了.有空的时候,看看jquery的源码,学习一下别人的编程思路还是不错的. 下面这里是一些jquery的工具函数代码,大家可以看看,实现思路还是很 ...
- 函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例
一.适配器 三种类型的适配器: 容器适配器:用来扩展7种基本容器,利用基本容器扩展形成了栈.队列和优先级队列 迭代器适配器:(反向迭代器.插入迭代器.IO流迭代器) 函数适配器:函数适配器能够将仿函数 ...
随机推荐
- 【Unity C#编程】自定义数据
译林军 灰魅|2014-03-04 10:52|10589次浏览|Unity(315)移动应用(31)技术开发(16)0 在这篇Unity C#的文章中,你将会创建一个简单的数据结构,然后写下它的属性 ...
- A Walk Through the Forest (最短路+记忆化搜索)
Jimmy experiences a lot of stress at work these days, especially since his accident made working dif ...
- Maven 仓库镜像设置
<mirror> <id>alimaven</id> <mirrorOf>central</mirrorOf> <name>al ...
- 小程序开发-小程序tabBar不显示的原因分析
在尝试小程序开发时,tabBar这个是个非常常见的组件,但是今天在进行开发时,设置了TabBarb并没有显示,被这个问题困扰了近半小时,现在将排查问题后所得到的经验记录下来. 首先 如果tabBar不 ...
- Q200510-02-02: 重复的DNA序列 SQL解法
重复的DNA序列所有 DNA 都由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”.在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助. 编写一个函数来 ...
- Zookeeper高级
1.1. 一致性协议概述 前面已经讨论过,在分布式环境下,有很多不确定性因素,故障随时都回发生,也讲了CAP理论,BASE理论 我们希望达到,在分布式环境下能搭建一个高可用的,且数据高一致性的服务,目 ...
- Windows安装tensorflow教程 GPU版
PS:这是GPU版本,CPU版会用笔记本环境另写一篇博客. 前置准备 查看GPU型号 电脑桌面->右键我的电脑->选择管理->点击设备管理器 如下图: 如果不是英伟达显卡,那么不用 ...
- JDK1.7之前的Bug之静态代码块
程序的主入口是main方法,但是在jdk1.7之前,可以没有main方法也一样能运行,很是不可思议,到底是什么原因呢?,大家都知道在类中定义了静态代码块的话,是首先执行代码块里的语句的,如果把静态代码 ...
- vue项目前端导出word文件(bug解决)
摘要:之前项目中导出价格表是由后端实现,前端只需要调用接口下载word即可,后来业务改变比较大,word模版需要一直改动,后端改起来相对麻烦,后来直接前端自己定义模版,实现下载word文档. 一.需要 ...
- jmeter服务器监控磁盘IO、网络-PerfMon Metrics Collector
1.jmeetr客户端安装jp@gc - PerfMon Metrics Collector 先安装jmeter-plugins 启动jmeter ——> 客户端选项 ——> jmeter ...