浅析LiteOS启动过程(基于STM32L431)-0x01
摘要:本文简要的分析了基于STM32L431的智慧农业案例程序中的LiteOS的启动过程。从经典的main函数开始,到LiteOS正常启动,实现任务的调度。通过这种分析,可以很好的理解LiteOS的一些运行原理过程,有助于LiteOS移植过程中的问题排查,有助于在其他芯片上顺利移植LiteOS。
1.从主函数main()进入
在嵌入式C语言程序中,程序通常从main函数开始执行。在没有操作系统的时候,通常在主程序中会有一个无限循环。例如下面的这一段程序。
在无限循环中,不断控制两个LED灯的亮灭控制。但是,当程序有了操作系统后,这个主函数还有吗?这个无限循环还会有吗,它的运行逻辑是什么?
下面是智慧农业的程序的main函数
在这个main函数中
62行,调用Hardware_Init进行硬件初始化。主要是时钟、GPIO、UART、LCD等的初始配置。
63行,调用LOS_Kernelinit( )对Lite OS的内核进行初始化。
70行,调用create_work_tasks(void) 创建了一个工作任务。
77行,调用LOS_Start( )启动LiteOS系统。
可以看出,在上面的程序中,没有出现while(1)这样的无限循环。那么77行,调用LOS_Start()后,接下来的要执行的程序代码去哪里了?难道就这样return0了吗?不应该。
从哪里消失,从哪里找起。从LOS_Start( )“消失”,继续从LOS_Start( )看起。
2. 进入LOS_Start( )
LOS_Start( )函数在los_init.c文件中,代码如下
在99行,调用osTickStart(); 配置Lite OS系统的时钟。Lite OS系统的时钟配置和刚开始的时钟的初始化配置不同。刚开始的时钟配置是基于STM32L431的系统进行的时钟配置。这里的时钟配置,是Lite OS系统中时钟配置。这里Lite OS系统时钟,类似于大家常用的桌面操作系统的时钟概念。
在121行,调用LOS_StartToRun( );启动Lite OS 运行。 LOS_StartToRun()函数,在Keil 环境中,通过右键->转到定义 的方法,找不到函数的实现文件。通过在整个项目中,查找LOS_StartToRun发现LOS原来的los_dispatch_keil.S文件中。
3. 进入los_dispatch_keil.S
los_dispatch_keil.S使用汇编语言编写的,主要实现了下面几个重要的函数及全局变量。
其中有LOS_StartToRun 函数。这个LOS_StartToRun函数就应该是在LOS_Start()函数最后调用的那个LOS_StartToRun( )。 LOS_StartToRun函数代码如下
这个代码用汇编语言写的。很难看懂,但是76-80行的注释,简要的说明了这个函数的调用形式以及功能:这个函数是没有返回值,没有参数的,它主要实现了 启动第一个任务,这个任务具有最高的优先级。其他的任务都是由任务调度来启动。任务调度在哪里?下面一会会说。
这个函数中最后一行 BX R6 上面的注释说,直接跳转到了g_stLosTask.pstRunTask中存储的PC指针处了,这样main函数的相关新就丢失了,程序就不会返回到main函数中了。
通常在嵌入式汇编程序中,调用子程序时,通常会保存号当前函数相关的信息,等调用完后,在恢复到调用的函数中。而这里的 BX R6 并没有让LOS_StartToRun函数返回到调用它的函数中,这样程序就不会在返回到main函数中了。至此,main函数结束了。整个系统的运行就全部依靠Lite OS系统了。
不返回main函数了,那么程序从哪里开始执行了?从 PC of g_stLosTask.pstRunTask,开始执行了。这里的PC是程序计数器,里面存储着CPU下一次要执行的程序指令的地址。执行完BX R6后,CPU就取到了g_stLosTask.pstRunTask地址中存储的指令,开始执行了。这个g_stLosTask.pstRunTask里面存储的是什么?在整个项目中查找g_stLosTask.pstRunTask,发现有如下代码
在osTaskInit()函数中,对g_stLosTask.pstRunTask进行了赋值。从分析赋值过程语句,可发现在g_stLosTask.pstRunTask中存储了要执行的任务相关的信息存储在里面了,即任务控制块(task control block structure即LOS_TASK_CB中的内容)的内容存储在g_stLosTask.pstRunTask中了。
在汇编语言中,将g_stLosTask.pstRunTask中的相关信息存储到STM32L431的相关的工作寄存器中,例如R6 工作寄存器。这样程序就可以执行任务了。而任务的相关信息、入口函数等都可以用C语言来编写。至此,程序可以绕道执行任务相关的代码了。“绕道”,这里绕道可以理解为,终于绕开了那个main函数了,可以执行操作系统中的多个任务了!
多个任务的调度,主要由LOS_IntLock,LOS_IntUnlock,LOS_IntRestore,osTaskScheldule,PendSV_Handler这些函数实现。这些函数也是用汇编语言写的。那么这里可以看出,针对不同芯片移植LiteOS的时候,由于不同的汇编语言可能需要不同的类似los_dipatch_keil.S这样的汇编语言编写程序文件。
4.综述
通过以上的分析,可以看出,在Lite OS在启动的时候,是从main函数中被调用开始,而在被调用的过程中,没有让PC指针再次跳转回main函数中,而是直接跳转到执行任务的命令的地址上去,从而开启了具有多任务执行能力的操作系统功能。
- 点赞
- 收藏
- 关注作者
评论(0)