数码之家

 找回密码
 立即注册
搜索
查看: 10237|回复: 71

[ARM] 用C++写单片机程序 STM32F103 + 自建固件库 + FreeRTOS 用gcc编译器和newlib(1篇)

[复制链接]
发表于 2019-8-17 18:22:59 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 freemancn 于 2019-8-17 18:46 编辑

      作为论坛的新人,先自我介绍一下。本人有10年的Win平台开发经验,从VS6.0一直用到VS2019,主要使用C#构建程序。在安徽某大学任教C语言程序设计7年,C语言自然是滚花烂熟。由于工作需要或者说是个人爱好,转战单片机。刚开始学习也是51+Keil用C语言开发,既然是学习实现的功能并不复杂,编写的代码量也不大,但还是体会到什么是一夜回到解放前。Keil的代码自动完成功能太弱鸡,如果做正式的项目效率会非常低。当时也只是想想而已,因为知道自己并不会去做实际的项目。之后当然就是学习STM32了,选择STM32主要是看中了中文资料多,学习人数多学习氛围好。STM32十足让我惊叹,比51复杂N倍的体系架构,超多的片上外设,还有如此低廉的价格。深入学习后发现还是Keil+C语言,至少市面上99%的学习都是基于这一框架的。非常的失望,非常的不适应。因为之前用C#开发Win应用,肯定是面向对象的开发思路,因为.NET Framework(相当于STM32的固件库)就是OO(面相对象)设计的,这么多年用下来,也深深的体会到OO的优势。不光是程序设计思路,还有就是IDE(集成开发环境)对开发者的重要性。我独自开发的Win应用最大的有10万行代码,我可以很轻松的构建,还能很轻松的完成代码维护,这里的代码维护指的是修订BUG,优化功能,增加功能,版本迭代等等。

      STM32F103的主频已有72MHz,复杂的系统架构,超多的片上外设。想要喂饱这个MCU或者说是发挥出它强大的功能,肯定是需要大量代码的。当代码数量达到一定规模,自然要面对代码结构的问题。用Keil+C可以做,完成需要的功能肯定没有问题,而且现在绝大多数人都在这么做。但是C语言是面相过程的语言,对代码结构毫无帮助,毫无益处,因为无计可施。达到一定规模后,代码逻辑估计只有设计者很清楚,别人要想看懂是一件很耗费时间的事情。导致这一结果的原因是有大量的宏,更可怕的是宏嵌套、使用全局变量,这个变量会被多少函数共享,在什么时候会被改变分析起来很头疼、大量的函数,这些函数在语言层面是相互独立的,但逻辑上可能是有联系的,在语言级并没有这种逻辑关系的表达。就像官方的HAL库,我读起来想死的心都有。不是我读不懂而是读懂这些我付出的时间代价太大,要在OO思路下,这个要轻松N倍。时间就是金钱,效率就是生命。官方的HAL库其实就是想实现一个硬件抽象层,让开发者对于不同型号的MCU有一个统一的应用层开发界面,提高代码的移植性,缩短开发周期。想法是好的,做法是失败的,因为HAL库还是再用C语言编写,硬是用C语言套OO思路,代码恶心到极致。这也就是STD库还是有人在用的原因。如果使用真OO就可以把逻辑上有关联的函数组织到一起,将一些全局变量限定在部分函数中共享,其实这就OO中的封装,是语言层面提供的支持。还有要吐槽的地方就是IDE,VS的代码自动完成功能真的很好用,只要你按下任何按键都会出现提示列表,按下空格自动填充你还没有输入的内容,还有参数列表的提示。带来的好处就是,我不需要记住所有函数的名称和参数列表,我只要有一个模糊的映像,输入代码的时候IDE协助我完成。让我专注于逻辑思路,代码只是完成逻辑思路的工具而已。对语言再熟悉,对函数再熟悉,没有一个好的逻辑思路仍然写不出优秀的应用。不光是代码自动完成,还有代码着色,代码折叠,代码重构等等IDE功能,对于开发真的是不可或缺。Keil可能也有这方面的支持,但和其它一些IDE相比真的太弱了。再次重申一遍,时间就是金钱,效率就是生命。Keil+C可以吐槽的地方还有很多很多,我可以给你说一整天,我并不想开吐槽大会,只是想告诉大家其实可以有更好的选择。

     说一下代码效率问题,这可能是大家非常关注的地方。绝大多数人会认为C++的时间效率不如C,但是你要知道C++是C的超集,使用C++开发并不是什么地方都必须C++,你任然可以写C函数,任然可以写嵌入汇编代码。C++的效率损失主要是函数调用,C语言中会将参数压栈,而C++对象函数除了压栈参数以外还要压栈一个this指针,多一个32位的变量而已。表面上看是多了一个参数,但事实上呢?C语言函数可能需要4个参数,而对象函数的这个this指针却能代表这4个参数,因为C++通过这个this指针去访问私有变量,而这些私有变量恰恰是C函数的那4个参数。以上的说明可能过于抽象,你现在未必需要知道细节,你只要明白一点,效率的损失不是绝对的,有时却是一种效率的提升。再高级一点的效率损失来自于多态。在C99里面已有函数参数的多态支持,即使相同函数名但参数不同,调用时根据给定参数自动选择对应的函数。这种多态在C++里面也是存在的,但这种多态是在编译时完成的,对运行效率毫无影响。而虚函数多态的效率损失才是重点,当使用基类指针指向一个子类并调用虚函数,实际运行的时候会确定实际对象的类型去调用不同版本的虚函数,这需要在运行时查找虚函数表来完成,多了一个查找的过程,在内存中多了一份虚函数表。但是这种特性有助于实现一个优秀的代码结构或设计思路,用纯C可能实现不了或者实现了效率也未必比C++来的高效,而代码的逻辑和结构肯定没有C++的优雅,构建的速度也没有C++来的快。对于虚函数的采用是选择性的,没有什么项目在任何位置都需要虚函数。而一些普通的代码,例如:int a, b; a = 10; b = a + 200; if、for......不管是用C还是C++生成的汇编代码都是一致的。第二是空间效率,上面也分析了时间效率,所以空间效率可能有所损失,但也不是绝对的。当你用到一些特性的时候,执行的代码量必然增加,所以固件的体积肯定会有所增加。C++还有个STL库,里面实现了很多基础类,这些基础类可以直接使用或者进行再封装。当你使用这个库时,固件体积会极速增加。对于一些Flash只有64K或更小的MCU,可能有点紧张。但对于更大容量的Flash完全就不是问题了。使用这个库的好处就是,更少的BUG,更快的构建速度。这也是选择性的,你可以根据实际情况自由选择。而C语言中的常用库,例如printf、abs、floor等在C++中也是可以用的,且不会因为你是C++这些库函数就发生变化。总结起来就是可能会带来一些效率的损失,这些损失大部分是选择性的,当你选择牺牲性能的同时会得到C语言无法实现的功能,得到优雅的代码,得到清晰的逻辑,得到快速的构建。对于当今的MCU性能的损失往往都是可以接受的,你能不能喂饱单片机反而是个问题。当你在C++中需要极致性能的时候,你任然可以像C语言一样,该干嘛干嘛。

      互联网上可以找到的资料实在是少之又少,断断续续搞了2年,现在已经完整构建了整个环境,打算写一个连载。这是第一篇,主要是阐述这种开发环境的优势。后面将陆续给大家分享开发环境的搭建,为什么要自建固件库,如何自建固件库,FreeRTOS如何与C++联合使用,newlib中如何实现printf重定向到串口,以及在实践过程中遇到的各种零碎的问题。随着芯片科技的不断进步,MCU性能的进一步加强,我相信这种环境将是未来的主流。也希望一些技术大牛不要再保守秘密了,把真正的技术都分享出来,彻底提升MCU编程。目前我已在用这个环境做实际的项目了,下面给一张开发环境的截图。
能回复的回复一下啊,让我有写完整篇的动力。
IED.jpg


打赏

参与人数 17家元 +337 收起 理由
新wx鑫 + 2
缘起缘灭123 + 15 安徽那个大学 我是合肥滴
smfox10 + 40 行动支持!拜读大作
invent + 3 優秀文章
cala4a5a7a0a + 30 good morning teacher freeman
待定d + 20 精彩回帖
wenxueroom + 20 虽然看不懂
飞向狙沙 + 20 優秀文章
jxcnj + 3 優秀文章牛人,希望能出成果
jpdd521 + 20 一直没有研究单片机代码,就是因为环境不好.

查看全部打赏

发表于 2019-8-17 18:49:45 | 显示全部楼层
太高大上了,太高深了,只能路过。

打赏

参与人数 2家元 +11 收起 理由
锰子 + 10 我很贊同
freemancn + 1

查看全部打赏

回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-17 19:17:50 | 显示全部楼层

后续会逐步介绍环境搭建、设计思路、代码也会贴出来一部分的,都是关键性代码。至于开不开源我认为不重要。
回复 支持 反对

使用道具 举报

发表于 2019-8-17 19:18:59 | 显示全部楼层
如何搭建VS开发调试STM32的环境?

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1 工具是这样,但不是我的核心思想。核心是想.

查看全部打赏

回复 支持 1 反对 0

使用道具 举报

发表于 2019-8-17 19:25:00 | 显示全部楼层
我喜欢极致效率,所以我只用ASM,至少现在为止。
连FFT都能用ASM写出来,当然不是我,我还不知道有什么是ASM做不了的。
加油,LZ,高层艺术一样美丽。:titter:

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-17 19:31:10 | 显示全部楼层
la45088d1 发表于 2019-8-17 19:25
我喜欢极致效率,所以我只用ASM,至少现在为止。
连FFT都能用ASM写出来,当然不是我,我还不知道有什么是AS ...

任何语言都会转换到ASM,在硬件如此强大的今天如何快速构建应用是我追求的目标。软件应该从2个方面衡量效率,一就是代码自身的执行效率,二是构建效率。
回复 支持 反对

使用道具 举报

发表于 2019-8-17 22:15:10 | 显示全部楼层
咋看有些道理,但是实际……不知楼主能否听的进去?
任何技术都要先谈定位。系统、OO、数据库、框架……对这些有需要的,会选ARM9,A8等直接跑linux,啥都有了;而选小MCU的,注定功能不会太复杂,要DIY要简便有Arduino,要可靠当然还是固件库+C+Keil/IAR。
当然对于个人出于爱好折腾来说,什么样奇怪的要求都不算奇怪。但想个人出一整套开发系统就难了,推广更难。

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 2019-8-17 22:18:32 | 显示全部楼层
至于楼主说的C的局限,这个可能只是楼主见识的局限……linux内核源码、MTK手机源码、各种SOC源码都是很好的参考

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 1 反对 0

使用道具 举报

发表于 2019-8-17 22:24:59 | 显示全部楼层
高手,对编程语言的理解非常地深入,
楼主可以看看Arduino,我觉得是一个很好的趋势,已经支持部分stm32了

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-17 23:09:03 | 显示全部楼层
amo73 发表于 2019-8-17 22:15
咋看有些道理,但是实际……不知楼主能否听的进去?
任何技术都要先谈定位。系统、OO、数据库、框架……对 ...

      这些道理不用你说我也很明白的。世界上也存在大量的C语言应用案例,而且是非常成功的应用案例。我并不是整出一整套开发系统,而是如何更好的利用现有的开发环境与思路。你即使要我整我也整不出来。我是从OO思路转到MCU的,进入这个领域后各种的不适应。在Keil+C的环境下我失去的太多了,反观OO我对其有了更为深刻的理解,我是想找回我失去的哪些便利,哪些不能在MCU中使用的设计模式,不能在MCU中实现的代码构建方法。我相信从事过OO开发的人与我有同样的想法。在我将要介绍的开发环境下,即使不用OO思路也比Keil方便N倍。况且整套方案中的核心gcc编译器用的可是ARM的亲儿子,是ARM自己干的。GCC编译器的地址是这个https://developer.arm.com/tools- ... nu-toolchain/gnu-rm    有这样的思路并不是想比C语言作出更多的功能,而是利用新的IDE和设计思路提高生产效率。结合C++ C和汇编的所有优势,有的放矢,而不是一根筋的为OO而OO。在国内的论坛,提出这样的思路往往都会遭到大量的质疑与反驳,这我也早有心里准备,但我希望大家能放下偏见与思维定式。反观国外,这样的话题大家聊得都非常开心。而且很多IDE中都带有OO的例程,其实就连Keil也是支持C++开发的,况且现在的MCU性能足够支撑OO开发,那何必不做一次有益的尝试呢?
回复 支持 反对

使用道具 举报

发表于 2019-8-17 23:57:48 | 显示全部楼层
不如直接搞类似arduino一类的,搞个Python或者JAVA的那才叫牛逼,那才叫高效,否则就只能自己一个人玩玩,就当学习提高自己了。

另外一点也不喜欢GCC:lol:

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-18 00:06:41 | 显示全部楼层
40560335 发表于 2019-8-17 23:57
不如直接搞类似arduino一类的,搞个Python或者JAVA的那才叫牛逼,那才叫高效,否则就只能自己一个人玩玩, ...

大哥做不到啊。当我写完整后,你或许会发现GCC还是很友好的。
回复 支持 反对

使用道具 举报

发表于 2019-8-18 00:56:19 来自手机浏览器 | 显示全部楼层
用iar硬啃stm8的路过…c语言学的比较烂,状态机现在都撸不转…

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 2019-8-18 10:31:01 | 显示全部楼层
大牛啊,写过一些小的C程序,还没到LZ这种境界,希望可以向LZ学习,提高自己软件水平。

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 2019-8-18 14:50:21 | 显示全部楼层
有想法就去实现,支持实干家!!!

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 1 反对 0

使用道具 举报

发表于 2019-8-18 15:49:01 | 显示全部楼层
首先楼主牛人,点个赞。
不过话说回来。
很多做硬件C编程的不是从OO阶段过来的,喜欢直来直去。赋值过程不要超过3个包含文件才好。
对于像windows这样的环境,内存够不够用一般都不考虑,但如果在103这样单片机里,CreateObject,我还是有点心惊肉跳,不跟踪到寄存器级我都不会放心。如果新的架构不能增加开发效率反而降低了,我觉得是不是有更好的方法呢。比如不动现有的标准库,光是改进IDE,原有的源码直接拿来就可以用,相当于兼容KEIL ,然后支持中文,免费,各种插件可以付费到支付宝,收费的是纯本土公司,不断促进国内IDE行业的发展。
其实作为一个程序员,我真的愿意支持本土企业,奈何不争气啊。
有远大目标和理想也要有接地气,实用的产品啊,你说是不是。

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 2019-8-18 17:01:11 | 显示全部楼层
支持楼主!!
官方的HAL库可能是从商业角度考虑,因为很多硬件工程师都在用C。
CubeMX的出现也许就是要解决这些问题。
C++的学习曲线太陡峭。

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 2019-8-19 00:49:03 | 显示全部楼层
很好的东西 确实不错

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 2019-8-19 01:08:25 | 显示全部楼层
STM32有支持C++的编译器吗?至少我记得keil mdk是不支持的。
想使用C++编程的话,必然是需要使用GCC,看题主这个界面应该是用Vc++的。
如果可以的话,个人认为GCC+VSCODE+JLINK应该是不错的选择。不过这个一定是够折腾的了。以前试过用keil调用GCC编译,没成功就被再折腾过了。

打赏

参与人数 1家元 +1 收起 理由
freemancn + 1

查看全部打赏

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-3-29 13:39 , Processed in 0.171600 second(s), 15 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

快速回复 返回顶部 返回列表