我都二手程序员好几个礼拜了!想给我的STM32来点“中国风”,装个华为LiteOS操作系统。
在此之前,我也试过STM32CubeMX自带的FreeRTOS操作系统,不知是何缘故,用F103c8t6芯片时,FreeRTOS里的一个断言过不去。出师不利,决定换LiteOS试试,尽管移植LiteOS有些麻烦,不如STM32CubeMX生成的方便,但是,移植成功后,编译没有问题、运行也没有问题,这让我这个初学者增添了不少信心。
FreeRTOS与LiteOS孰优孰劣,我真的不知道,不过,我知道我喜欢CubeMX,Keil也算凑活,所以,想用大白话说说,如何给STM32CubeMX创建的MDK-ARM工程移植LiteOS。如果,你也想用华为LiteOS操作系统,可以继续往下看,若是内行高手,“要是你拿正眼多看我一眼,那你就输了”。
一、 准备一个STM32CubeMX工程
没什么特殊要求,注意以下两点:一、SYS 时钟源不要用SysTick。二、项目管理中Toolchain选择MDK-ARM。
二、 LiteOS源码去那里找
上面给的链接不是最新发行版,新版本增加了些芯片架构的支持,暂时还不会用。先来个打了标签LiteOSV200R001C50B038
的版本。下图中红框标注的4个目录是我们需要的。
三、 把LiteOS源码拷贝到咱的Keil工程目录下
LiteOS源码下载好了吧?我们开始给Keil工程添加LiteOS源码。
-
先在Keil工程根目录下,建一个目录
LiteOS
,用来放置LiteOS的源码,(其实目录名叫什么不重要,看你高兴)。 -
在新建的LiteOS目录下,再整4个子目录,分别叫它们
Kernel
、Arch
、CMSIS
、Config
。看看它们的名字,想必您已经猜到了,我想在里面放些什么了,对喽,就是图1中那4个目录所对应的内容。 -
怎么复制源码呢?是不是这个姿势...
不必这样,按照下面的图片复制就好。
-
首先,Kernel目录:
把LiteOS源码中
kernel
目录下的内容全部复制到工程里的.\LiteOS\Kernel
目录下,然后再把.\LiteOS\Kernel\base\mem
目录下的两个子目录bestfit
、tlsf
删除。 -
接下来是Arch目录:
从LiteOS源码arch\arm\arm-m
中复制两个目录src
、include
到工程.\LiteOS\Arch
目录下。
然后,根据你的STM32芯片的具体架构(cortex-m3或cortex-m4 ??),选择复制arch\arm\arm-m\contex-m?\keil\los_dispatch_keil.S
到工程.\LiteOS\Arch
目录下。下图,我的芯片是Cortex-m3的。
复制好以后,Arch目录长这样。
- 现在是,CMSIS目录:
这个目录下是与操作系统供应商无关的抽象层,复制LiteOS源码osdepends\liteos\cmsis
目录中的文件到工程目录.\LiteOS\CMSIS
目录下。
- 最后,复制Config目录:
这个目录下应放置和你芯片相匹配的配置文件,咱们先去LiteOS源码的targets
目录下找一个合适的,然后把它里面OS_Config
目录下的头文件(.h 文件),复制到工程的.\LiteOS\Config
目录下。
复制好以后,我的Config目录是这个样子的。
四、 在Keil工程中添加分组(Groups)
在Keil的IDE环境中,分别添加以下4个分组:
- LiteOS/Kernel
- LiteOS/Arch
- LiteOS/CMSIS
- LiteOS/Config
在LiteOS/Kernel分组下,我们添加上面复制在..\LiteOS\Kernel
目录下(包含子目录下)的所有.c
的源文件。
在LiteOS/Arch分组下,添加..\LiteOS\Arch
目录下(包含子目录下)所有.c
的源文件,还不够,还有那个名为los_dispatch_keil.S
的汇编源文件也得添加。
在LiteOS/CMSIS分组下,添加..\LiteOS\CMSIS
目录下的cmsis_liteos.c
。
在LiteOS/Config分组下,添加..LiteOS\Config
目录下的所有.h
的头文件,其实,这个分组不建,程序照样能跑,但是,为了以后修改参数方便,我们还是先安排上吧。
五、 给Keil工程添加头文件引用路径
添加内容如下:
../LiteOS/Arch/include
../LiteOS/Kernel/include
../LiteOS/Kernel/base/include
../LiteOS/Kernel/extended/include
../LiteOS/Config
../LiteOS/CMSIS
六、 注释掉STM32生成的两个中断处理函数(PendSV_Handler、SysTick_Handler)
它们俩藏在一个叫stm32f?xx_it.c
的文件中, 注释掉就好。
七、 修改配置
记得前面创建的Keil工程分组LiteOS/Config
分组吗?配置参数就藏在这儿。
分组中有个叫target_config.c
文件,你可以根据使用的芯片,在这修改一下#define BOARD_SRAM_SIZE_KB 40
参数,据说,该值应该比芯片实际的SRAM略小。
其它的参数,在实际开发过程中,慢慢研究调整吧。我读书少,更多的内容也搞不清楚。
到这里,LiteOS的移植工作算是差不多了,接下来,点一盏灯,验证一下"来时的路"。
八、 一灯大师,发功了
-
在main.c 引入头文件
#include "cmsis_os.h"
-
在main.c 申明俩个变量
/* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ osThreadId_t default_taskHandle; const osThreadAttr_t default_task_attributes = { .name = "default_task", .stack_size = 512 * 4, .priority = (osPriority_t) osPriorityNormal, }; /* USER CODE END PV */
-
在main.c 申明两个函数
/* USER CODE BEGIN PFP */ /* LITEOS BEGIN PFP */ void StartDefaultTask(void *argument); void LiteOS_Init(void); /* LITEOS END PFP */ /* USER CODE END PFP */
-
在main.c中,实现上面的函数
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ void LiteOS_Init(void) { osKernelInitialize(); default_taskHandle = osThreadNew(StartDefaultTask, NULL, &default_task_attributes); } void StartDefaultTask(void *argument) { while(1) { /* 一灯大师,请试试在这里点一盏灯。 */ HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_13); osDelay(200); } } /* USER CODE END 0 */
-
在main.c中,
int main(void)
函数体里调用/* USER CODE BEGIN 2 */ LiteOS_Init(); osKernelStart(); //注意,这东西要在main的while之前 /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
灯亮了吗?祝您成功!
九、 手搓 LiteOS移植工具
写到这儿,不知道我讲清除了没有。还不行的话,我准备了一个手搓移植工具,要不您也试试。
我把它放这儿了,Python实现,有源码,改改给Makefile工程移植应该也行。它长下面这副德行:
-
LiteOS移植完成后,如果再次点击STM32CubeMX中的
GENERATE CODE
按钮,会把工具注释掉的两个中断处理函数恢复出来,这时需要您手工注释掉它们。PendSV_Handler
、SysTick_Handler
他们在..\Core\Src\stm32f?xx_it.c
文件中。或者,也可以再次点击工具中的开始移植
按钮,也能注释掉它们。 -
根据实际情况设置LiteOS的
BOARD_SRAM_SIZE_KB
参数, 这个值应略小于芯片的SRAM,LiteOS配置文件位于LiteOS\Config
分组下的target_config.h
文件中,约在283行处#define BOARD_SRAM_SIZE_KB 40
。 本工具定义了一些芯片的SRAM设置尺寸,由于个人能力问题,它们既不全面,也不准确。(工具中关于芯片配置定义,见stm32.py中的枚举类class STM32
)