MDK 平台下弱声明函数实现后不能被执行的处理

MDK 平台下弱声明函数实现后不能被执行的处理

问题描述

TinyUSB 部分非必要的回调函数采取了弱函数的方式进行声明,这样用户在使用 TinyUSB 的时候,可以仅按照需求实现相应的回调函数,不必将所有的回调函数统统实现,简化了使用 TinyUSB 的方法。

但近日在做 TinyUSB 相关的应用时遇到了一个问题:在 MDK 平台下,那些非必要的回调函数,即使实现了它,也不会去执行,这样让 TinyUSB 相当多的功能都没办法使用了。

为了能够使用到 TinyUSB 提供的回调函数,就需要解决弱函数不能被执行的问题。

原因

经过单步调试发现,当 TinyUSB 去执行弱声明的回调函数时,会先判断该回调函数是否非空,非空则执行。

if (weak_func_cb)
{
    weak_func_cb(...);
}

问题就出在这里,判断这个回调函数依然为空,这个回调函数即使实现了,编译器也依然认为不存在。

两种解法

修改协议栈

修改协议栈是直接粗暴的办法,如果某一个弱函数需要被用到,那让这个弱函数变“强”即可,变成强函数的办法就是跑到协议栈的头文件里面,将弱函数的声明拿掉即可。

当然,这样会让协议栈报 warning,这是由于协议栈内部对弱函数的处理是下面这种方法:

if (weak_func_cb)
{
    weak_func_cb(...);
}

在执行某一个弱函数之前,先判断这个弱函数是否存在,如果存在,则执行这个弱函数,当弱函数修改为强函数后,这个判断逻辑就会变成恒为真,warning 的原因就是如此,因此,需要在协议栈中,移除判断语句,直接执行这个函数。

weak_func_cb(...);

通过这种方法修改协议栈后,所需要执行的回调函数就能够正常执行了。

修改编译选项

修改协议栈是最直接粗暴的方法,但改动协议栈就意味着协议栈不再是原本代码,如果这份协议栈是经过测试认证的代码,修改就意味着测试认证失效,如果协议栈受官方维护,修改协议栈就意味着协议栈不再会受到官方的维护,因此这种直接粗暴的办法,并不适用于所有场合。

弱函数不能被执行,明显是编译器的处理存在问题,协议栈不能改动,则可以改动编译器的编译选项,让弱函数显现出来。

经过多种尝试,发现之所以不执行弱函数的原因,是因为编译器认为该函数没有被用到,因此进行了优化,移除了相关的函数代码,那么解决办法就是让这段函数代码不要被编译器优化掉。

点击 MDK 的魔术棒,点击 Linker 选项,在 Misc controls 框中输入以下内容:

--keep=*_cb

上面那句话的意思是,所有以 “_cb” 结尾的函数,均不允许被优化。“*”是正则表达式中的通配符

如果希望整个工程中所有的代码都不被优化,则可以在 Misc controls 框中输入以下内容:

--keep=*

这样所有的函数都不会被优化,但随之而来的是,编译出来的二进制文件将会变得非常大,因此不推荐使用。

如果指示希望某一个函数不会被优化,则可以在等号后面写上这个函数的名称。

--keep=weak_func_cb

至于 --keep 的具体用法,可参考《Arm Compiler Reference Guide》,点击 MDK Project 右边的 Books 即可找到这份资料。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值