移植freertos到stm32 f103 的基本流程和总结
为什么要在stm32 f103上面移植freertos
stm32 f103 以他的全面的文档,亲民的价格,强大的功能。成为无数微设备的方案首选。在市场上有极大的使用量。市场占有率也是非常的高。freertos作为一个开源的微型操作系统,凭借着它的资源占用小,功能强大,文档齐全,成为各大芯片公司都支持的操作系统,也是程序员操作系统学习的不二首选。所以,把这两者结合起来,除了能给我们的产品提供强大的支撑之外,还积累的很多基础技术。笔者花了不少心思才把这个移植好,在这里做个记录。希望能给你一些启发。
基本介绍
我这里使用的是freertos的版本是9.0。移动植入之前,先看一下freertos的文件目录:
├── croutine.c
├── event_groups.c
├── include
│ ├── FreeRTOS.h
│ ├── StackMacros.h
│ ├── croutine.h
│ ├── deprecated_definitions.h
│ ├── event_groups.h
│ ├── list.h
│ ├── mpu_prototypes.h
│ ├── mpu_wrappers.h
│ ├── portable.h
│ ├── projdefs.h
│ ├── queue.h
│ ├── semphr.h
│ ├── stdint.readme
│ ├── task.h
│ └── timers.h
├── list.c
├── portable
│ ├── GCC
│ │ └── ARM_CM3
│ │ ├── port.c
│ │ └── portmacro.h
│ ├── MemMang
│ │ ├── heap_1.c
│ │ ├── heap_2.c
│ │ ├── heap_2.lst
│ │ ├── heap_2.o
│ │ ├── heap_3.c
│ │ ├── heap_4.c
│ │ └── heap_5.c
│ └── readme.txt
├── queue.c
├── readme.txt
├── tasks.c
└── timers.c
大致一看,这个操作系统是非常简洁的。从文件名字就可以看出:
queue.c 这个文件是队列,负责线程之间的通信和数据传输的。
task.c 就是线程及任务模块,线程相关的都在这个文件里面。
list.c 就是一个链表,用来实现可变数据的存放和操作。
根目录下的和具体的芯片没关系,和芯片的接口及相关的元素主要在两个函数里面。
一个是portable文件下的port.c 这个里面要注意下,在stm32 f103中,这里最重要的就是这里的中断处理函数的匹配了。在无操作系统的stm32 f103中,systick, SVC 和 PendSV 这三个中断的处理函数 这三个函数一般在start.s文件或中断向量表中vector.c 中。基本额写法如下所示:
void SVC_Handler (void) attribute((weak));
void PendSV_Handler (void) attribute((weak));
void SysTick_Handler (void) attribute((weak));
在freertos中,需要替换成port.c 里面的另外三个中断处理函数:
voidxPortPendSVHandler( void ) attribute (( naked ));
voidxPortSysTickHandler( void );
voidvPortSVCHandler( void ) attribute (( naked ));
另外一个就是heap,heap主要是系统的内存管理单元。heap_1.c, heap_2.c and heap_3.c属于三个基本的样例子,用户也可以根据自己的实际情况做修改。这里的的heap虽然很多,但是每个系统只会使用一个,具体使用哪一个要看你的芯片平台的属性,stm32 f103 使用的是heap_2.c
移植流程
第一步就是把代码拷贝到目标文件中,编译通过。这里属于一些基本功夫,详细的步骤我就不多说了,谨记中断处理函数的处理,这里非常容易出问题。再者就是FreeRTOSconfig.h文件中的heap_size大小,不能太大,太大了这个芯片的资源不够的。建议一般不要10k左右就行了吧。
第二步就是FreeRTOSConfig.h文件的配置选择,这里面的是非常关键的,最容易出错。下面是我的这个文件的配置:
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )
#define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ / 8 ) /* fix for vTaskDelay() */
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
这里要注意几点: configCPU_CLOCK_HZ 就是CPU的的时钟,系统的时钟和CPU的时钟是不同的,这里做一个8分频:#define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ / 8 )
还有就是后面的heap大小和stack大小,要根据实际的产品情况进行调整的。这个调整好了,可以让你的小芯片发挥出极大的威力。
第三点,应用部分:
这里手先看一下主函数:
int main()
{
RCC_Configuration();
GPIO_Configuration();
usart1_init();
printf("start main sdf \n\r");
usart1_puts(" 512k flash, 64k ram ..........\n\r");
xTaskCreate(tadventure,"game",configMINIMAL_STACK_SIZE,NULL,configMAX_PRIORITIES-1,NULL);
xTaskCreate(flasher,"flash",configMINIMAL_STACK_SIZE,NULL,configMAX_PRIORITIES-1,NULL);
xTaskCreate(vT_usart, (const char*) "USART Task", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
vTaskStartScheduler();
while (1);
return 0;
}
三个task的处理函数:
static void flasher(void *arg __attribute__((unused))) {
for (;;) {
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
vTaskDelay(pdMS_TO_TICKS(400));
GPIO_SetBits(GPIOA, GPIO_Pin_1);
vTaskDelay(pdMS_TO_TICKS(400));
}
}
static void tadventure(void *arg __attribute__((unused))) {
{
for (;;) {
GPIO_ResetBits(GPIOA, GPIO_Pin_0);
vTaskDelay(pdMS_TO_TICKS(1000));
GPIO_SetBits(GPIOA, GPIO_Pin_0);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
static void vT_usart(void *p)
{
// Block for 500ms.
const portTickType xDelay = 500 / portTICK_RATE_MS;
for(;;) {
usart1_puts("FreeRTOS V9.0.0 demo on STM32F103c8t6\r\n");
usart1_puts(" 64k flash, 20k ram ..........\r\n");
vTaskDelay(xDelay);
}
}
这里的结果如下所示:

问题备忘
最大的问题就是一个是FreertosConfig.h文件设置错误导致的系统timer不对。
另外就是中断的服务处理函数了,一定要换成自己的。
移植freertos到stm32 f103 的基本流程和总结的更多相关文章
- FreeRTOS学习及移植笔记之二:在IAR和STM32F103VET上移植FreeRTOS
上一次,我们简单的测试了FreeRTOS的基于IAR EWARM v6.4和STM32F103VET6平台的Demo,对其有了一个基本认识.接下来我们开始自己移植FreeRTOS的过程. 1.创建一个 ...
- Bootloader 跳转到 RT-Thread 或 FreeRTOS(基于 STM32)
Bootloader 跳转到 RT-Thread 或 FreeRTOS(基于 STM32) 作者:猾蚁 QQ:7376220一.Bootloader 程序1. 准备好升级程序项目,可以使用 STM32 ...
- STM32移植FreeRTOS(1)
"STM32F103VET6<_>FreeRTOS" 1.项目功能实现 1)LED灯定时闪烁 2)KEY按键检测 3)FreeRTOS任务创建 4)串口输出程序运行状态 ...
- 移植FreeModbus+ModbusMaster+STM32至RT-Thread(3、4阶段)
一.简介及进展 经过一个多月的努力,目前项目开发已进入最后阶段.虽然比预期时间有些延迟,但也收获不少,边工作边开源的效率确实还有待提高. 简单说下目前的进展吧 1.目前项目已经在Github中开源,大 ...
- 基于keil平台下STM32L系列移植FreeRTOS操作系统
1,下载FreeRTOS https://www.freertos.org/a00104.html 点击下载后,会进入如下界面 之后会弹出下载界面,格式为.EXE,不用怀疑.不是木马. 等待下载完成, ...
- LWIP network interface 即 LWIP 的 硬件 数据 接口 移植 详解 STM32 以太网数据 到达 的第二站: void ethernetif_input( void * pvParameters )
根据 上一篇 文章 , ETH DMA 数据中断 会 发送 一个信号量 ,我使用 全局 搜索 这个信号量 s_xSemaphore 得到 一下 几个 值 根据 这个 分析 我们找到了 数据 的 ...
- 移植mavlink到stm32详细教程,后面附快速移植方法
一:准备材料: mavlink源码 stm32串口程序 1.mavlink源码: a.进入mavlink官网(http://qgroundcontrol.org/mavlink/s ...
- 移植FreeModbus+ModbusMaster+STM32至RT-Thread(初步)
一.项目描述 目前操作系统在嵌入式软件行业非常流行,在工控组网方面,以后可能会经常使用到Modbus主机+操作系统.Modbus从机+操作系统甚至Modbus主机+Modbus从机+操作系统.但是操作 ...
- 学习使用Free RTOS ,移植最新的STM32 v3.5固件库
最近拿到了一块万利的EK-STM32F的学习板,打算先用它来熟悉下STM32的编程环境,不过在这过程中和一个同事聊的时候觉得如果只调用STM32的库写程序,可能在芯片资源的利用上面可能就会差一点,在这 ...
随机推荐
- 基于JGraphT实现的路径探寻
基于JGraphT实现的路径探寻 业务中提出基于内存,探寻的两点间的有向以及无向路径,多点间的最小子图等需求,以下记录使用JGraphT的实现过程. GraphT是免费的Java类库,提供数学图论对象 ...
- MySQL 基础 SQL 操作
MySQL 用户 --登录 mysql -u<用户名> -p[密码] --修改密码 mysqladmin -u<用户名> -p[密码] password <new_pas ...
- linux修改环境变量的三种方法【转】
[环境变量配置的三个方法] 如想将一个路径加入到$PATH中,可以像下面这样做: 1. 控制台中,不赞成使用这种方法,因为换个shell,你的设置就无效了,因此这种方法仅仅是临时使用,以后要使用的时 ...
- vue状态管理vuex从浅入深详细讲解
1.vuex简介以及创建一个简单的仓库 vuex是专门为vue框架而设计出的一个公共数据管理框架,任何组件都可以通过状态管理仓库数据沟通,也可以统一从仓库获取数据,在比较大型的应用中,数据交互庞大的情 ...
- 2018 Multi-University Training Contest 10
Recently, TeaTree acquire new knoledge gcd (Greatest Common Divisor), now she want to test you. As ...
- Splash简单应用
jd->iphone import requests from lxml import etree # search_key = 'iphone' jd_url = "https:// ...
- VSCode前端 插件
https://www.cnblogs.com/karthuslorin/p/8577224.html
- 8.Java的特性和优势
简单性:可以说Java是C++语法的纯净版,没有头文件,没有指针运算,也不用分配内存. 面向对象:是一种程序设计技术,它将重点放在对象以及对象的接口上,模拟人的思维写程序,所以人去学习非常快.因此,J ...
- Unity3d游戏角色描边
本文发布于游戏程序员刘宇的个人博客,欢迎转载,请注明来源https://www.cnblogs.com/xiaohutu/p/10834491.html 游戏里经常需要在角色上做描边,这里总结一下平时 ...
- Android的学习之路一
在Android的道路上越走越远==,本着一颗童心去学习,没想到最后会成为自己的职业.看到过知乎上写的,并不是兴趣使比尔盖茨以及乔布斯他们成就斐然,而是他们真正的牛逼使得即使买大饼也能成为世界首富.然 ...