建议使用以下浏览器,以获得最佳体验。 IE 9.0+以上版本 Chrome 31+ 谷歌浏览器 Firefox 30+ 火狐浏览器
请选择 进入手机版 | 继续访问电脑版
设置昵称

在此一键设置昵称,即可参与社区互动!

确定
我再想想
选择版块

星辰27

发帖: 21粉丝: 1

级别 : 版主

Rank: 7Rank: 7Rank: 7

发消息 + 关注

发表于2019-12-2 10:31:59 523 1 楼主 显示全部楼层
[技术干货] 漫谈LiteOS-启动流程

启动流程

摘要:本文通过对代码的解析对LiteOS的启动流程做了一个较为详细的介绍,希望对你有所帮助。

启动方式

目前对于多任务的实时操作系统中有两种比较流行的启动方式,一种是在main函数中进行硬件初始化以及系统初始化之后先将所有任务创建完成之后,一起启动,如移植代码中的主函数图1所示。

图1 启动方式1.png

图1 启动方式一

另一种方式是在main函数中进行硬件初始化以及系统初始化之后创建任务之后直接启动调度器,然后在启动任务中创建各种应用任务,当所有任务创建成功后启动任务再把自己删除。具体如图2所示。

图2 启动方式2.png

启动方式二

启动流程

2.1 Reset_Handler函数

一般在程序下载到开发板之后,我们首先会按一下Reset按键进行开发板的启动,因此在开发板上电后第一个执行的就是Reset_Handler函数,其位于los_startup_gcc.s文件中,该文件可以在LiteOS源码中的targets示例工程中找到。该函数主要进行了以下工作。

1)初始化栈指针;

2)初始化 PC 指针;

3)初始化中断向量表;

4)配置系统时钟;

5)调用 C 库函数_main。

具体如图3所示,位于los_startup_keil.s中。

图3 keil.png

3 los_startup_keil.s

  汇编程序如图4所示

图4.png

汇编程序

2.2 LiteOS的初始化

进入主函数之后首先进行的是LiteOS的初始化。LOS_KernelInit函数,其具体如下代码所示。

LITE_OS_SEC_TEXT_INIT UINT32 LOS_KernelInit(VOID)
{
  UINT32 uwRet;
 
  osRegister();
 
  m_aucSysMem0 = OS_SYS_MEM_ADDR;
  uwRet = osMemSystemInit();
  if (uwRet != LOS_OK)
  {
    PRINT_ERR("osMemSystemInit error %d\n", uwRet);/*lint !e515*/
      return uwRet;
  }
  
#if (LOSCFG_PLATFORM_HWI == YES)
    {
      sHwiInit();
    }
#endif
 
#if (LOSCFG_PLATFORM_EXC == YES)
  {
    osexcInit(MAX_EXC_MEM_SIZE);
  }
#endif
     
  uwRet =osTaskInit();
  if (uwRet != LOS_OK)
  {
    PRINT_ERR("osTaskInit error\n");
    return uwRet;
  }
     
#if (LOSCFG_BASE_CORE_TSK_MONITOR == YES)
  {
    osTaskMonInit();
  }
#endif
     
#if (LOSCFG_BASE_CORE_CPUP == YES)
  {
    uwRet = osCpupInit();
    if (uwRet != LOS_OK)
    {
      PRINT_ERR("osCpupInit error\n");
      return uwRet;
    }
  }
#endif
     
#if (LOSCFG_BASE_IPC_SEM == YES)
  {
    uwRet = osSemInit();
    if (uwRet != LOS_OK)
    {
      return uwRet;
    }
  }
#endif
     
#if (LOSCFG_BASE_IPC_MUX == YES)
  {
    uwRet = osMuxInit();
    if (uwRet != LOS_OK)
    {
      return uwRet;
    }
  }
#endif
     
#if (LOSCFG_BASE_IPC_QUEUE == YES)
  {
    uwRet = osQueueInit();
    if (uwRet != LOS_OK)
    {
      PRINT_ERR("osQueueInit error\n");
      return uwRet;
    }
  }
#endif
     
#if (LOSCFG_BASE_CORE_SWTMR == YES)
  {
    uwRet = osSwTmrInit();
    if (uwRet != LOS_OK)
    {
      PRINT_ERR("osSwTmrInit error\n");
      return uwRet;
    }
  }
#endif
     
#if(LOSCFG_BASE_CORE_TIMESLICE == YES)
  osTimesliceInit();
#endif
     
  uwRet = osIdleTaskCreate();
  if (uwRet != LOS_OK)
  {
    return uwRet;
  }
     
#if (LOSCFG_TEST == YES)
  uwRet = los_TestInit();

  if (uwRet != LOS_OK)
  {
    PRINT_ERR("los_TestInit error\n");
    return uwRet;
  }
#endif
     
  return LOS_OK;
}
     
#ifdef __cplusplus
#if __cplusplus
    }
#endif /* __cpluscplus */
#endif /* __cpluscplus */

具体说明如图5所示。

图5.png

图5 内核函数示意图

下面对上图其中的几个宏以及函数(1、2、3、4、10)做一个较为详细的介绍:

1:根据 target_config.h 中的 LOSCFG_BASE_CORE_TSK_LIMIT 来配置最大支持的任务个数,默认为 LOSCFG_BASE_CORE_TSK_LIMIT+1,包括空闲任务IDLE

2:初始化 LiteOS 管理的内存模块,系统管理的内存大小为OS_SYS_MEM_SIZE

:如果在 target_config.h 中使用了 LOSCFG_PLATFORM_HWI 这个宏定义,则进行硬件中断模块的初始化。则表示 LiteOS 接管了系统的中断,使用时需要注册中断,否则无法响应中断,而如果不使用 LOSCFG_PLATFORM_HWI 这个宏定义,系中断将由硬件响应,系统不接管中断的操作与裸机基本是差不多的。

:初始化任务模块相关的函数,进行分配任务内存,初始化相关链表,为后面创建任务做准备。

10:在 target_config.h 中使用 LOSCFG_BASE_CORE_SWTMR 软件定时器的宏,所以,需要对软件定时器的使用进行相关初始化,当使用软件定时器的时候,系统还会创建一个软件定时器任务,并且必须使用消息队列。

之后直接开启任务调度,配置SysTick,以及配置 SysTick  PendSVd 的优先级即可,通过上述步骤即完成了LiteOS的启动流程。

目录主博文https://bbs.huaweicloud.com/blogs/124244


举报
分享

分享文章到朋友圈

分享文章到微博

EnyaSeven

发帖: 60粉丝: 12

级别 : 版主

Rank: 7Rank: 7Rank: 7

发消息 + 关注

发表于2019-12-2 10:44:37 沙发 显示全部楼层
点赞 评论 引用 举报

游客

富文本
Markdown
您需要登录后才可以回帖 登录 | 立即注册