背景故事

STM32主控板(STM32F103RCT6)预留了SWD接口用于调试,但JTAG的其他引脚PA15 PB3、PB4又有了其他用途,需要关闭JTAG部分功能,但保留SWD功能,按照常规方式配置后,依然SWD无法使用。

常规方式

先附上正常配置方式如下:

GPIO_InitTypeDef GPIO_InitStructure;
 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //打开复用时钟,注意此处时钟要先与从映射开启
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //调用重映射函数
 
 // 释放普通IO
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_15 ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
 
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3 ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
 
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4 ;
GPIO_Init(GPIOB, &GPIO_InitStructure);

问题描述

按照上述配置,我的主控板,依然出现无法使用SWD的情况,查了很多资料依然无法解决。

问题解决

  1. 首先想办法排除硬件问题,这个主要靠经验,我这边用万用表测了swd接口电压,Jlink的地与主控的地的连通性,单片机SWDIO和CLK引脚与jlink的连通性,并且检查了MDK软件读取jlink是否正常;
  2. 然后查资料排除自己软件的问题;
  3. 后来只能怀疑到库函数上。考虑直接用寄存器操作;说干就干,翻出STM32F103中文参考手册,

由上述可查询到 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE) 该功能的寄存器实现方式为 AFIO->MAPR |= 0x02000000
修改代码如下:

GPIO_InitTypeDef GPIO_InitStructure;
 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //打开复用时钟,注意此处时钟要先与从映射开启
// GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //调用重映射函数
GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE);			// 先使能全功能的JTAG,再复用其他引脚
AFIO->MAPR |= 0x02000000 //调用重映射函数
 
 // 释放普通IO
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_15 ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
 
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3 ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
 
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4 ;
GPIO_Init(GPIOB, &GPIO_InitStructure);

最终测试通过。

注意事项

  1. 在上述代码中遇到一个容易忽略的坑点:

所以要注意 AFIO时钟需要先打开,再进行引脚从映射才能生效。
2.单单使用AFIO->MAPR |= 0x02000000 还不够,需要先开启全功能的JTAG功能,GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE);具体原因暂时不知道,这个是经验试出来的。

总结

不能全信库函数,硬件还是容易遇到问题,可能是我的库没有更新到最新,也有可能是个库函数的bug,暂时没时间研究,就先这样吧。
对于该功能我研究的也不深,希望懂的朋友能进一步解惑。

欢迎各位老铁一键三连,本号后续会不断更新树莓派、人工智能、STM32、ROS小车相关文章和知识。

大家对感兴趣的知识点可以在文章下面留言,我可以优先帮大家讲解哦

欢迎大家光临我的淘宝小店,会定期推出教程中使用的物美价优的硬件,你的光临就是对我的支持

原创不易,转载请说明出处。