前言

  • 20201009
  • 移植好内核后,开始实战内核。
  • 源码分析一般都在代码注释中
  • 本文LiteOS采用非接管中断方式。
  • 本文源码基于 LiteOS 2018 源码,最新官方源码中都有注释,可参考
  • 本文源码与最新官方源码区别
    • 原理一样,源码稍有不同,且最新官方源码中带有注释。

链接

参考

  • 上面链接

开启调度

  /* 开启调度 */
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 函数源码

  • 分析再源码注释中

    • 简略步骤

      1. SysTickPendSVd 优先级设置为最低
      2. g_bTaskScheduled 至为 1
      3. 设置控制寄存器为 CONTROL
      4. 更新当前运行任务 Set g_stLosTask.pstRunTask = g_stLosTask.pstNewTask;
      5. 更新当前运行任务的任务状态 Set g_stLosTask.pstRunTask->usTaskStatus |= OS_TASK_STATUS_RUNNING;
      6. 手动更新 PSP 值,恢复到栈顶
      7. 更新 LR 寄存器
      8. 开启中断
      9. 跳转到当前任务的 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
/**
* @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-任务篇-源码分析-系统启动函数的更多相关文章

  1. 【LiteOS】LiteOS任务篇-源码分析-创建任务函数

    目录 前言 链接 参考 笔录草稿 部分源码分析 源码分析 LOS_TaskCreate函数 LOS_TaskCreateOnly函数 宏 OS_TCB_FROM_PENDLIST 和 宏 LOS_DL ...

  2. LiteOS-任务篇-源码分析-任务调度函数

    目录 前言 笔录草稿 核心源码分析 osTaskSchedule函数源码分析 osPendSV函数源码分析 TaskSwitch函数源码分析 调度上层源码分析 osSchedule函数源码分析 LOS ...

  3. 性能测试分享: Jmeter的源码分析main函数参数

    性能测试分享: Jmeter的源码分析main函数参数   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大 ...

  4. jQuery源码分析-each函数

    本文部分截取自且行且思 jQuery.each方法用于遍历一个数组或对象,并对当前遍历的元素进行处理,在jQuery使用的频率非常大,下面就这个函数做了详细讲解: 复制代码代码 /*! * jQuer ...

  5. LiteOS-任务篇-源码分析-删除任务函数

    目录 前言 笔录草稿 源码分析 LOS_TaskDelete函数源码分析 完整源码 参考 链接 前言 20201009 LiteOS 2018 需要会通用链表 笔录草稿 源码分析 LOS_TaskDe ...

  6. Memcached源码分析——process_command函数解析

    以下为个人笔记 /** * process_command 在memcached中是用来处理用户发送的命令的, * 包括get set,add,delete,replace,stats,flush_a ...

  7. vue2源码分析:patch函数

    目录 1.patch函数的脉络 2.类vnode的设计 3.createPatch函数中的辅助函数和patch函数 4.源码运行展示(DEMO) 一.patch函数的脉络 首先梳理一下patch函数的 ...

  8. jquery源码分析-工具函数

    jQuery的版本一路狂飙啊,现在都到了2.0.X版本了.有空的时候,看看jquery的源码,学习一下别人的编程思路还是不错的. 下面这里是一些jquery的工具函数代码,大家可以看看,实现思路还是很 ...

  9. 函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例

    一.适配器 三种类型的适配器: 容器适配器:用来扩展7种基本容器,利用基本容器扩展形成了栈.队列和优先级队列 迭代器适配器:(反向迭代器.插入迭代器.IO流迭代器) 函数适配器:函数适配器能够将仿函数 ...

随机推荐

  1. POJ-3255-Roadblocks(次短路的另一种求法)

    Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. Sh ...

  2. FZU - 2037 -Maximum Value Problem(规律题)

    Let’s start with a very classical problem. Given an array a[1…n] of positive numbers, if the value o ...

  3. 9.深入k8s:调度器及其源码分析

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 源码版本是1.19 这次讲解的是k8s的调度器部分的代码,相对来说比较复杂,慢慢的梳理清 ...

  4. 【python】迭代器与生成器到底是什么?看完你就知道

    迭代器跟生成器,与上篇文章讲的装饰器一样,都是属于我的一个老大难问题. 通常就是遇到的时候就去搜一下,结果在一大坨各种介绍博客中看了看,回头又忘记了. 你是不是也是这样呢? 俗话说:好记性不如烂笔头, ...

  5. Oracle 11G R2安装说明 -九五小庞

    教程版本Oracle 11.2.0.1.0

  6. Beware of the encrypted VM

    A friend of mine Megan told me that she got an error message as below screenshot when trying to open ...

  7. Zookeeper高级

    1.1. 一致性协议概述 前面已经讨论过,在分布式环境下,有很多不确定性因素,故障随时都回发生,也讲了CAP理论,BASE理论 我们希望达到,在分布式环境下能搭建一个高可用的,且数据高一致性的服务,目 ...

  8. python之读取yaml数据

    一.yaml简介 yaml:一种标记语言,专门用来写配置文件. 二.yaml基础语法 区分大小写: 使用缩进表示层级关系: 使用空格键缩进,而非Tab键缩进 缩进的空格数目不固定,只需要相同层级的元素 ...

  9. 二、loadrunner参数化连接数据库

    2.连接sqlserver数据库.oracle数据库或mysql数据库(只有mysql数据库驱动需要先手动安装) 2.1.新建一个参数,随便设置file还是table类型之类的 2.2.点击Data ...

  10. $\TeX$ Gyre 字体安装过程与问题解决

    目录 安装过程 1. 下载字体包 2. 安装字体 3. 测试范例文件 本文地址 https://www.cnblogs.com/oberon-zjt0806/p/13672426.html 本文只是一 ...