建立 F103C8T6 HAL库 Makefile FreeRTOS 工程
F103C8T6 HAL库 Makefile FreeRTOS 工程模板
环境
该工程的开发平台为 ARM-GCC 工具链和 Make
> arm-none-eabi-gcc -v
gcc version 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] (GNU Tools for Arm Embedded Processors 9-2019-q4-major)
> make -v
GNU Make 3.81
下载调试工具为 OpenOCD + CMSIS-DAP
Open On-Chip Debugger 0.10.0 (2020-01-14) [https://github.com/sysprogs/openocd]
固件信息
- 官方 HAL 库版本:
STM32Cube_FW_F1_V1.8.0 - FreeRTOS API :
CMSIS v2 - FreeRTOS version :
10.0.1 - CMSIS-RTOS version :
2.00
- 官方 HAL 库版本:
适配芯片为
STM32F103C8开发环境为
Windows10_64bit+VSCode
资源
BSP_LED -> PB12:板载LED, 指示灯用
USART1:串口,主要调试工具
- TxD -> PA9
- RxD -> PA10
TIM4:HAL 库时基源
SysTick:FreeRTOS 时基源
现象
单片机上电后先通过串口发送一堆测试数据。
BSP_LED 闪烁。
串口每隔一段时间向上位机发送一段测试信息。
- 现象 2 和 3 “同时”进行、互不影响。
目录结构
├─.vscode/ // vscode 配置文件
├─build/ // 编译生成的中间文件
├─DOC/ // 说明文档
├─Drivers/ // ST HAL 库的库文件
├─Inc/ // 用户层的 .h 文件
├─Middlewares/ // 中间件,里面主要包含的是 FreeRTOS 的源码
├─Peripheral/ // 外设。用户层,usart 初始化的 c 和 h 我就写在了这里边
├─Src/ // 用户层的 .c 文件
├─Makefile // 最最重要的 Markfile 文件,工程编译全靠它
├─startup_stm32f103xb.s // 单片机的启动文件,程序其实是从这里开始运行的
├─STM32F103C8Tx_FLASH.ld // 单片机的内存管理相关文件
└─STM32F103xx.svd // 单片机的 svd 文件,大概相当于寄存器的目录吧,调试时使用
工程中的其他注意事项
中断优先级分为4,16级抢占优先级(0~15,越低越优先)无响应优先级。
(HAL_Init() --> HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);)
GCC 中 printf() 底层的实现方式与 Keil 中的不一样,移植工程时须留意。
在 Src 目录下有一个 stm32f1xx_hal_timebase_tim.c 文件,让 TIM 取代 SysTick 就是在这里实现的。(FreeRTOS 的任务调度仍是使用的 SysTick)
因为用到了 TIM4 做 HAL 库时基源 ,所以在 main.c 文件中使用了 HAL_TIM_PeriodElapsedCallback() 函数,以后再使用定时器中断时注意这里 !!!
过程
以完美的 VSCode + GCC工具链 + OpenOCD 的 HAL 库工程为基础再做一个 FreeRTOS 的模板就很简单了。
stm32CubeMX . 用它新建一个工程,配置好 RCC, SYS 和 GPIO , 需要注意的时由于 OS 需要使用 SysTick , 因此将 HAL 库的 时基源调为 TIM1 时基源调为 TIM4 , 因为 TIM1 是高级定时器,高级定时器不多,省着点用。而 TIM4 是 F103C8 的最后一个定时器,后来我又看了几款芯片,发先惯例是每款芯片的最后一个定时器都是那些定时器里最不高级的,因此就用这个吧,免得以后用到什么高级功能麻烦。

在 Middleware 中启用 FreeRTOS (CMSIS_V2) 然后进行一些简单的配置(其实也没什么可配置的)。因为以后我们要自己创建任务所以可以先在这里把总任务堆栈调大一点,其他的配置跟原子推荐的都差不多,用不着动。
可以发现当我们启用 OS 后系统中断发生了一些变化,大概像下图那样。因为 OS 的任务调度跟中断关联很大,所以图上那些灰色不给改的中断配置千万要留意,在 CubeMX 中不能改,在代码中也千万别去改。

配置一下工程的输出参数,然后生成工程吧。
生成工程后先删掉一些不需要的东西,否则工程文件夹太大了。一般来说删掉 \Drivers\CMSIS 目录下除 Device 和 Include 之外的所有文件就可以了。
将前面制作的 HAL 库工程里的 .vscode 文件夹和 STM32F103xx.svd 文件复制到新工程里。最好测试一下串口,所以把 Peripheral 文件夹和 config.h, syscalls.c 也复制过来,然后去 Makefile 和 stm32f1xx_hal_conf.h 中做相应的修改。如果 vscode 报错就看看 makefile 引用了什么新的头文件,然后包含进 c_cpp_properties.json .

现在编译一次应该能通过的,然后再看着改改试试能不能正常用就行了,应该没什么大问题。
补充
关于新建任务。新建任务其实并不复杂,甚至比原子的方式还要简单。仿照默认任务的创建代定义一个新任务的结构体,然后声明一下任务函数,在 main() 中创建一下任务,最后在找个空白的地方写下这个任务函数的一些实现就 OK 了。
注意!接下来要说的事非常重要!!
在任务函数中无法打印浮点数
这个问题的确出现了而且很令人抓狂,我在第二个任务中放了一个
printf("%f\r\n",3.14)但是程序一旦运行到这里就会死机,陷入到HardFault_Handler()中。使用操作系统时遇到莫名其妙的问题最先想到的可能就是堆栈溢出,但是直到我把运行 printf() 函数的任务堆栈调大到 10kB 后仍没解决问题时我就觉得没那么简单。从网上了找到了修复使用 newlib 库时遇到这个问题的方案,但是我应该没有使用这个东西。查了一晚上的资料(真的是一晚上,我六点才睡觉)也没什么有效的解决方案,但是我隐约明白了这个东西应该跟内存分配有关系。今天下午又修了修也实在是没什么效果,但是果然正当我打算放弃的时候转机就出现了——还记得当初重定向 printf() 函数时用到了一个文件叫 syscalls.c (这个在上文也有提到),重定向 printf() 其实只要用到里面的 _write() 函数就行了,但是我当时的打算是其他函数现在虽然不知道有什么用但难保以后用不着,所以并没有删掉里面的其他函数。今天下午在我放弃之前的最后一刻我突然想到了我的代码中最不可靠的因素——就是那个 syscalls.c 文件,整个工程的核心代码是 STM32CubeMX 根据我的配置自动生成的应该没什么问题,我手动在 main.c 里边写了些东西但那都是我能解释的应该也没什么问题,所以这样说来工程中最可能出问题的就是那个我擅自从 STM32 的 HAL 库例程中复制过来的 syscalls.c 文件了!
果然当我注释掉 syscalls.c 除与 _write() 函数相关的其余所有代码后问题就解决了。事实上后来查明主要原因是因为 syscalls.c 中的 _sbrk() 函数,但是当我查明后还是果断地把除 _write() 之外的所有函数都注释掉了,永绝后患。
这件事告诉我们对于未知的事物一定要时刻保持最大限度的怀疑。你以为 ST 官方的 HAL 库的例程中的文件都是好的、不会坑你?不存在的。
另注:printf() 这种函数还是很耗费内存的,在任务中运行时虽然不用给任务堆栈分配 10kB 那么夸张,但最低给分配 512*4B 还是有必要的。
附录
CubeMX 中关于 FreeRTOS 配置的中文翻译

建立 F103C8T6 HAL库 Makefile FreeRTOS 工程的更多相关文章
- STM32,下载HAL库写的代码后J-Link识别不到芯片,必须要按住复位才能下载?
问题描述:最近在学STM32的HAL库,据说可以统一STM32江湖,前途无量.最近一段时间参照STM32CubeMX和原子的资料自己学着建了两个HAL库的工程模板,F4的还好说,F1的出现了一个玄学问 ...
- 新建基于STM32F103ZET6的工程-HAL库版本
1.STM32F103ZET6简介 STM32F103ZET6的FLASH容量为512K,64K的SRAM.按照STM32芯片的容量产品划分,STM32F103ZET6属于大容量的芯片. 2.下载HA ...
- 【GMT43智能液晶模块】基于HAL库的SDRAM和LCD驱动例程(MDK工程&CubeMX工程)
说明: 1.该工程基于HAL库实现动态存储器SDRAM驱动以及液晶控制器LCD驱动. 2.工程通过STM32CubeMX(Version 4.22.0)配置生成,可直接打开进行配置. 3.KEIL M ...
- STM32F072从零配置工程-基于HAL库的串口UART中断配置
先上一个采用串口直接传输的Demo: 此处的思路是完全采用HAL库来实现的,核心是运用HAL_UART_Transmit_IT和HAL_UART_Receive_IT两个函数来实现的,可以作为一个De ...
- STM32 HAL库利用DMA实现串口不定长度接收方法
参考:https://blog.csdn.net/u014470361/article/details/79206352 我这里使用的芯片是 F1 系列的,主要是利用 DMA 数据传输方式实现的,在配 ...
- 【STM32H7教程】第32章 STM32H7的TIM定时器基础知识和HAL库API
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第32章 STM32H7的TIM定时器基础知识和H ...
- 【STM32H7教程】第29章 STM32H7的USART串口基础知识和HAL库API
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第29章 STM32H7的USART串口基础知识和 ...
- 如何使用keil5将stm32的hal库编译成lib文件——F1版本
hal库中keil5中编译的速度是比较慢的,相同情况下,每次都要编译的时候,比标准库是要慢很多的,因此就hal库编译成lib文件是一种加快编译速度的方法,当然也有其自身的缺点.一.步骤1.使用cube ...
- 【STM32H7教程】第59章 STM32H7的DAC基础知识和HAL库API
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第59章 STM32H7的DAC基础知识和HAL库 ...
随机推荐
- Docker部署Zookeeper部署实践(1)
Zookeeper可提供的服务主要有:配置服务.名字服务.分布式同步.组服务等 1. 抓取Zookeeper镜像 命令:docker pull zookeeper 2. 将Zookeeper镜像保存为 ...
- Dired Mode in Emacs
Start up Dired mode: C-x d; (List dirs: C-x C-d) Hide Dired mode window: q; Mark Mark (for group man ...
- MySQL-11-存储引擎
存储引擎简单介绍 存储引擎:相当于Linux文件系统,只不过比文件系统强大 功能 数据读写 数据安全和一致性 提高性能 热备份 自动故障恢复 高可用方面支持 存储引擎种类 InnoDB MyISAM ...
- 【笔记】SVM思想解决回归问题
使用svm思想解决回归问题 使用svm思想解决是如何解决回归问题,其中回归问题的本质就是找一条线,能够最好的拟合数据点 怎么定义拟合就是回归算法的关键,线性回归算法就是让预测的直线的MSE的值最小,对 ...
- DVWA-全等级文件包含
DVWA简介 DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用,旨在为安全专业人员测试自己的专业技能和工具提供合法 ...
- Docker源码安装附内网镜像安装演示
Docker源码安装附内网镜像安装演示 系统版本要求 当前系统版本:CentOS Linux release 7.9.2009 (Core) 内核版本:3.10.0-1160.el7.x86_64 注 ...
- bootstrap导航条报错 Uncaught TypeError: Cannot convert object to primitive value
原文: https://feiffy.cc/uncaught-typeerror-cannot-convert-object-to-primitive-value 最近发现我的博客页面移动端上下拉菜单 ...
- UWP App Data存储和获取
这篇博客介绍如何在UWP开发时,如何存储App Data和获取. App Data是指用户的一些设定,偏好等.例如,App的主题,是否接收推送,离线接收消息等.需要区分下App Data和User D ...
- 简单实现 nodejs koa2 mysql 增删改查 制作接口
1.首先 在电脑上安装 nodejs (此处略过) 2.全局安装 koa2 (这里使用的淘宝镜像cnpm,有兴趣的同学可以自行搜索下) cnpm install koa-generator -g 3. ...
- jvm系列(六):jvm调优-工具篇
## jdk自带的工具### jconsole Jconsole(Java Monitoring and Management Console)是从java5开始,在JDK中自带的java监控和管理控 ...