STM32踩坑记录,HAL库无法进中断回调函数

一、使用的软件及版本       

1.STM32单片机,

2.Keil5.0.6版本

二、出现情况

        手上有一个比较大的工程,需要加个旋转编码器的模块,因为这个工程比较庞大还使用了操作系统,直接在这个工程上调试怕因为其他的东西影响,出现其他奇奇怪怪的错误。

        刚好有个f103c6t6的开发板,所以想先在c6t6的开发板编写驱动程序,调试一下软件消抖等,

这里直接编写了中断回调的函数:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{   
    if(HAL_GPIO_ReadPin(EC11_KEY_GPIO_Port, EC11_KEY_Pin) == GPIO_PIN_RESET)                       
        EC11_KEY_Callback();
    if(HAL_GPIO_ReadPin(EC11_S1_GPIO_Port, EC11_S1_Pin) == GPIO_PIN_RESET)     
        EC11_S1_Callback();
    if(HAL_GPIO_ReadPin(EC11_S2_GPIO_Port, EC11_S2_Pin) == GPIO_PIN_RESET)     
        EC11_S2_Callback();
}

       这里使用了PB12-14的引脚,共用了一个中断,所以进中断回调函数时再次判断是哪一个引脚被触发,编译下载调试没有任何反应。

        这里第一反应先检查回调函数是否被调用,打开_it.c文件查看,没有找到外部中断被调用,打开mx发现在配置完GPIO的引脚为外部中断模式后,忘记勾选开启EXTI[15:10]的中断以及生成中断回调函数,这里重新配置后再次生成工程,再次编译下载仍然不可以使用。

 再次检查后,仍然没有什么头绪,所以使用debug进行调试,在中断触发函数处打断点:

        能正常进入中断EXTI15_10_IRQHandler函数,继续在二级函数打断点:

        这里仍能正常进入HAL_GPIO_EXTI_IRQHandler函数,继续在回调函数打断点:

        中断回调函数也能正常触发,于是只能继续进入回调函数测试,右键跳转并没有直接跳转到我之前编写的回调函数,而是直接跳转到系统自动生成的弱定义回调函数:

__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Callback could be implemented in the user file
   */
}

        这里我还没有反应过来,于是自己手动打开自己编写的回调函数,发现没有灰色可打断点的区域,也就是编译器将我编写的代码全部优化掉没有编译进去,这里尝试修改了编译器的优化等级,直接改为不优化,再次编译调试仍然空白无法打断点。

        这里大概是知道是__attribute__((weak))弱定义出问题了,于是查询GNC的手册看到了这样一段话:

        目前我们所看到的对外部目标文件的符号引用在目标文件被最终链接成可执行文件时,它们须要被正确决议,如果没有找到该符号的定义,链接器就会报符号未定义错误,这种被称为强引用(Strong Reference)。与之相对应还有一种弱引用(Weak Reference),在处理弱引用时,如果该符号有定义,则链接器将该符号的引用决议;如果该符号未被定义,则链接器对于该引用不报错。链接器处理强引用和弱引用的过程几乎一样,只是对于未定义的弱引用,链接器不认为它是一个错误。一般对于未定义的弱引用,链接器默认其为0,或者是一个特殊的值,以便于程序代码能够识别。在GCC中,我们可以通过使用"__attribute__((weakref))"这个扩展关键字来声明对一个外部函数的引用为弱引用。

        所以链接器在编译时并没有找到用户重新定义的函数,不理解的是这个函数文件中还有初始化的函数,也就是这个文件已经能被编译器正确的找到并使用,但是同一个文件下面的强定义回调函数并没有被编译器编译。

        这里再一次没有了头绪,于是将这个函数进行声明,仍不行,将函数复制到主函数中,发现能正常使用,更加确定了是函数放在其他文件时编译器没有正确的进行链接,最后想了想是不是因为这是测试的程序没用严谨规范格式添加头文件导致的,随后添加头文件编译运行,代码正确跑起来了。

        所以归根到底就是偷懒导致的,因为只是测试工程,没有去添加头文件,能正常编译不报错,仅会报警告就不在乎不管,但是说来也奇怪,在主函数不添加头文件的情况下,同一个文件中另一个初始化的代码可以正常使用,也就是编译器已经自动帮我们添加了头文件,但是又只链接有被调用的函数,便不会全编译。

三、解决方法

1.首先检查cube是否开启了中断以及是否让cube为你生成回调函数。

2.一定要添加头文件,不要偷懒忽略警告。

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值