逼疯我的AFIO,STM32的JTAG调试接口作为GPIO用

不知是心境不佳还是时运不佳,不好的情绪造成了消极待事还是不好的境遇导致了消极情绪?连STM32的GPIO都要耍十里,还好十里最终破解了AFIO的把戏,没有过不去的坎,对不对!

现象

最近在玩带按钮的旋转编码器,旋转编码器用到了 stm32f103c8t6 的3个GPIO作为输入,分别是:

  • PB4 -> A相
  • PB3 -> B相
  • PA15 -> 按钮

这里就不介绍旋转编码器了,因为这里只需要知道是作为输入管脚使用就可以了。

出现了很奇怪的现象,PB3的管脚不能正常采集外部输入,造成了驱动异常,十里一度怀疑管脚坏了,但是十里使用STM32CubeMX生成了新的工程,测试管脚正常采集高低电平,简直了!此时此刻脑袋中有一万头羊驼奔过。。。

分析

管脚配置问题

十里曾经怀疑是不是STM32CubeMX生成的的初始化代码有问题,但是十里在调试过程中查看了管脚配置,与手册对照配置是正确的。

管脚坏了

现象中已经提到,新的工程中PB3作为输入是正常的,所以原因排除。

外部电路干扰

直连编码器和单片机,管脚仍然配置为上拉输入,依旧存在问题,说明肯定还有其他原因才对!开始怀疑人生。。。

难道管脚有什么特殊之处

查看芯片手册,最终发现原来真的是有猫腻,PB3管脚复位后的主功能原来不是GPIO,而是JTDO(JTAG接口的数据输出),原来是管脚复用(AFIO)的问题,网上查找资料,果然被十里找到一篇文章,问题出错原理一模一样:

查看STM32F1参考手册可以发现PB4及PA13\PA14\PA15\PB3等5个脚在芯片复位后默认的就是专用的调试口,非通用GPIO。现在客户工程师虽然用SWD接口,只用到PA13\PA14两根线,但PB4及PA15、PB3三根线的属性没变,还是专用调试口。如果要把不用的PB4等三根线作为GPIO,还得额外做些相关寄存器配置,即操作AFIO_MAPR寄存器中的SWJ_CFG【2:0】三个位。

如果使用ST公司的STM32CubeMx图形化配置工具来做管脚安排及时钟初始化等就可以避免很多类似上面谈到的繁琐或麻烦。利用STM32CubeMx配置工具,很多初始化的东西都可以依据你的管脚和时钟安排、外设功能的使能等而生成出相应的配置代码,不必手动二次添加配置,让你去专注你的用户应用代码设计与调试。

取自:一个关于STM32 GPIO管脚复用冲突的话题

解决

依照找到的原因查看程序,调试过程中发现AFIO->MAPR并不是期望值2,也就是说复位保持了PB3的复用功能JTDO,所以导致PB3作为输入无法正常工作。那么为什么我也采用了STM32CubeMX生成的代码,却没有屏蔽调试接口的处理呢?查看代码找到文件stm32f1xx_hal_msp.c中的 HAL_Msp_init 函数,发现里面有屏蔽调试接口的操作:

__HAL_AFIO_REMAP_SWJ_NOJTAG();

但是为什么没有生效呢?gdb一步步调试程序,发现执行HAL_Msp_Init函数时跳到了其他文件,这个文件中这个函数为弱函数定义,其中没有任何操作,说明文件stm32f1xx_hal_msp.c没有被编译进程序,最后查找Makefile发现,果真没有加入这个文件的编译,加入后,编译运行,一切OK!!!

这也就解释了为什么其他用STM32CubeMX配置工具生成的工程可以正常操作PB3。

总结

没有总结,只有安利,gdb真的很好用,对于stm32芯片可以使用arm-none-eabi-gdb进行调试,nice!比IDE中的调试功能强大且灵活。。。