因为最近比较有时间,而且发现自己对于STM上可以跑的操作系统相对陌生。所以选择几个操作系统进行移植和玩几个DEMO理解一下。虽然理解的不是很深入,但是如果项目需要的话,只是移植,进行多任务的操作。应付一下还是绰绰有余的。之前移植了uCosII.后续有需要会总结一下。这里先对FreeRTOS相关的问题进行总结。因为个人能力有限。有什么不对的地方请大家批评,写这个主要是为了记录一下自己的移植过程。
1、第一步肯定是先到官网去下载关于FreeRTOS的源码
下面的网址是官方最新源码的下载地址:
https://sourceforge.net/projects/freertos/files/latest/download?source=files
目前官方提供的最新版本是v9.0.0, FreeRTOS源码在解压目录下的路径为
FreeRTOS_V9.0.0rc2\FreeRTOS\Source
2、下载完,进行安装。安装完你会得到如下目录的文件
我们需要的是FreeRTOS这个目录的文件。而关于-Plus的使用,目前小弟并没有试过。大家可以试试,好玩记得推荐哦。
3、进入FreeRTOS目录,你会发现里面有三个文件夹,分别是Demo,License,Source。在Demo中,我们能看到很多不同平台的移植例程,这个很好的,有相关不懂的平台,完全可以用来参考使用。因为我们是在MDK下移植。所以选择CORTEX_STM32F103_Keil这个文件夹的内容进行参考,其实这个Demo还是很有帮助的,后续你在移植的时候,会发现缺少的文件都可以在这个Demo中进行直接拿来使用。选择介绍另一个文件夹的主要用途。
另一个文件夹是Source.这个目录下的文件主要有
include这个目录,我建议大家如果不是很清楚哪些要用,哪些不用的要,都可以添加进工程中。重点是这个portable文件夹,里面的东西比较多。而我们主要用到的目录有下面几个。关于不同的平台,大家可以自己选择哦。
其实你会发现,你进入Keil中,其实没有东西,就是告诉你,这个目录和RVDS中的是一样的操作。所以你需要进入RVDS中。把关于你平台内核的文件拷贝过来。小弟这边使用的M3内核,所以拷贝后如下。还有这个MemMang一定要记得拿过来,很重要哦。因为关于内存的管理都是在这里面呢。
接下来介绍下根目录下的这个几个源文件,我们需要用到的就只有几个,如果只是移植看一下加入操作系统后的运行情况。
现在,我们需要移植的文件大概就只有这些哦。现在就可以建立一个简单的工程了。关于工程建立,这边就不多说啦。大家不会的话,可以自己参考网上的例程或者正点原子中不完全手册上的教程哦。现在小弟创建工程并添加进相关文件如下:
其中port.c就是在ARM_CM3中找。heap_4.c就是在MenMang中找。里面有不同的内存管理方案,大家可以根据需要选择自己想要的方案,小弟这边选的是heap_4.c.现在要说一个最最骚的问题了,就是你添加完这些文件。然后点击编译,如果你默认的是选择系统的启动文件,就会报出很多错误。还有就是会缺少一个文件叫做FreeRTOSConfig.h,你会发现这个文件在源码中并找不到。所以刚才说了哦,Demo很重要呢。就是要到Demo中去找到这个文件,并且添加进去。还有就是启动文件,如果你看不出那些错误怎么改,也拿Demo中的启动文件啦。有时候,我们需要的是应用,如果你有时间并且很多兴趣,你就可以一步步进行理解操作哦。小弟这边是试验。所以直接拿了STM32F10x.s这个启动文件,后续的话,应该会进行对比分析,再跟大家分享。
最后就是跟你的需要添加一些文件进去哦,如果你用的是库函数开发,记得关于stm32f10x_conf.h、#include "stm32f10x.h"这些文件很重要哦。记得去Demo中找,如果丢失会很麻烦呢,很多地方编译都不会通过。还有就是库函数开发的话,这边一个地方要设置,不然也编译不过呢
现在看一下main.c函数的主要操作
#include "led.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x.h"
#include "misc.h"
#include "FreeRTOS.h"
#include "task.h"
#include "usart.h"
void LedTask1(void *pvParameters )
{
while(1)
{
printf("i am LedTask1\r\n");
//vTaskDelay(100 / portTICK_RATE_MS);
LED0_OFF;
vTaskDelay(500 / portTICK_RATE_MS);
LED0_ON;
vTaskDelay(500 / portTICK_RATE_MS);
}
}
void LedTask2(void *pvParameters )
{
while(1)
{
printf("i am LedTask2\r\n");
vTaskDelay(10 / portTICK_RATE_MS);
// LED1_OFF;
// vTaskDelay(500 / portTICK_RATE_MS);
// LED1_ON;
// vTaskDelay(500 / portTICK_RATE_MS);
}
}
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
uart_init(9600);
LED_Init();
printf("init sucess\r\n");
//堆栈深度(字) //任务参数 //任务优先级 //任务句柄
xTaskCreate(LedTask1,"LED_TASK1",40,NULL,1,NULL);
xTaskCreate(LedTask2,"LED_TASK2",40,NULL,2,NULL);
vTaskStartScheduler(); //启动任务调度器
return 0;
}
根据需求添加哦。我这边是用LED灯和串口进行验证是否移植成功。所以添加了关于LED和USART的模块代码。这边有个注意的地方是。你的创建的任务一定记得在后面加上一点延迟。不然的话,很容易出错,你想看到的效果,就看不到啦。像小弟这个Demo,效果就是LED灯5秒闪烁一次。然后串口交替打印信息。
好了。目前简单的移植就这些啦,是不是觉得很简单呢。因为现在很多物联网小模块,可能只需要接收和处理数据。然后上传之类的。用上一个操作系统,可能会比较好哦,毕竟简单的处理。