IAR平台下移植FreeRTOS,切换C++语言的编译问题分析

IAR平台下移植FreeRTOS,切换C++语言的编译问题分析,第1张

IAR平台下移植FreeRTOS,切换C++语言的编译问题分析

用IAR开发时,在STM32F4上面移植FreeRTOS时发现,添加完成包含C++源文件时,将IAR语言切换到C++时,编译报错特别多,常见的之类类型转换都好处理,直接强制转换就好了。但是还有一些函数未定义的问题,比较难处理,尤其是有些文件引用了“portasm.s”这个汇编文件里面的函数,在工程编译最后的链接阶段,总会报错某某函数未定义。这篇文章记录一下处理流程,仅供参考。

情况介绍:

一开始在IAR上面移植,切换C++报错时,以为自己移植的过程有问题,所以直接将FreeRTOS里面的F407 Demo工程拿过来测试
项目路径为:FreeRTOSv202107.00FreeRTOSDemoCORTEX_M4F_STM32F407ZG-SK

测试工程是近期直接在FreeRTOS官网上下载的。


问题描述:

官方工程使用IAR8.20打开后,直接编译,没有任何问题

Total number of errors: 0 
Total number of warnings: 0 

切换语言为C++,重新编译

报错,现阶段主要是指针类型转换的问题

找到报错点,一个个改完即可,如下




有“=”号进行赋值的语句直接强制类型转换就可以了,里面还有几处是宏定义里面报错的,如


直接修改宏定义即可

类型转换问题修改完成之后,重新编译此时的报错主要是引用的函数未定义

Error[Li005]: no definition for “vPortEnableVFP()”
Error[Li005]: no definition for “vPortStartFirstTask()”
Error[Li005]: no definition for “vRegTestClearFlopRegistersToParameterValue(unsigned long)”
Error[Li005]: no definition for “ulRegTestCheckFlopRegistersContainParameterValue(unsigned long)”
Error[Li005]: no definition for “vRegTest2Task(void *)”
Error[Li005]: no definition for “vRegTest1Task(void *)”
主要是上述几个函数,在链接的时候报错未定义,处理既然是链接阶段,那就直接看下.map文件。这是前两个报错的函数,后面几个可以在map文件里找到,主要在portasm.s 和RegTest.s这两个汇编文件里面。可以判断map文件里面都有相关的函数生成了,只是在连接的时候没有被正确识别。


问题分析:

既然知道问题在哪里,那一般怎么 *** 作呢,Google一下,百度一下,基本上也就处理好了,但是不太好找到一些有效的处理办法。

比如这篇文章《IAR报错处理》,里面提到了函数vPortEnableVFP()和vPortStartFirstTask()未定义,是因为portasm.s文件没有添加到工程里面,上述问题显然不是这个原因。

或者这篇文章Creating a FreeRTOS Static Library,面提到了在C++环境下,C风格的文件在引用时需要做好声明,以便编译器在编译的过程中自动切换。

其他相关度较高的文章就不再列举了,所描述的问题处理方式不太适用当前情况,可以自行查阅。

解决方式:

问题主要是在切换了C++语言之后出现的,按照上述第二篇文章里面说的,C++环境下C风格的文件需要做好声明,一般也就是头文件里面加上extern “C”{ },但是对于上述两个汇编文件portasm.s 和RegTest.s,这两货和port.c没有头文件,报错信息中port.c和main.c这两个文件里面,引用了汇编中的函数导致链接无法成功,那咋办呢。既然头文件里面处理不了,那就哪里声明引用的,哪里处理。找到port.c文件中声明外部函数的地方,如下

给他两加上C的编译限制,方式和头文件里面的写法一致。

同样,对main.c中做一样的处理,此时编译通过,不再报错。

虽然这样 *** 作可以避开报错,因为只是处理里链接的问题。但是函数调用的过程还是按照C++的编译规范处理的,是有可能会引起软件运行时的未知BUG,最好用extern “C”{ }将port.c整个源码段全部包含,避免在出现其他未知问题。同样main.c也做同样处理。

题外话:

现在问题是处理好了,但是具体原因是啥,还没有做分析。以本人愚见,认为是C++的函数重载机制引入的问题。C中对于函数名是禁止重名的,因为在链接的时候链接文件中的函数名和声明的函数名时保持一致的;而C++中为了支持函数的重载,链接文件中的函数名和你声明的并不完全一致,以便在链接的时候实现函数重载的功能。打开IAR中输出C++编译过程的链接文件输出选项,分析下port.c文件的链接文件。

在没有加extern “C”{ }限定声明引用的函数时,port.c的链接文件中对报错函数vPortEnableVFP()的链接名进行了修改,仅仅是为了支持重载,如下

当加了extern “C”{ }限定之后,变成了如下


上述的两个函数的实现实在汇编文件portasm.s中实现的,汇编是不管重载的事的,所以输出链接文件和声明的函数名时一致的,所以在没有限定C的条件下,导致C++ 函数重载时生产的函数链接名,和汇编中的链接名无法匹配,所以才报错Error[Li005], 某某函数 no definition。。。。。这个问题可能在其他条件下也会出现,与君共勉,后面再遇到类似问题,多一个思考方向。

至此,欢迎各位大佬交流分享。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5116101.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-17
下一篇2022-11-17

发表评论

登录后才能评论

评论列表(0条)

    保存