给大家讲解下在使用ARM Cortex-M内核的下载/调试接口JTAG和SWD引脚如何作为普通GPIO的使用方法。
一、准备工作
1、32F103xx系列单片机的用户手册和数据手册【我这边以国产GD32系列单片机为例】
二、JTAG|SWD调试仿真接口讲解
1、前言:在产品的软件开发阶段,单片机的调试是一个很关键的步骤,然而很多山寨的程序在开发中,甚至都没有调试的概念,而只是把程序生成的映像文件hex或bin,通过串口直接烧入片子,再根据错误症状来判断问题,然后修改程序重新烧,周而复始,直到问题解决或放弃为止。在开发比较大的应用程序时,强劲的调试手段是非常重要的。当 bug 复杂到无法分析时,只能用调试来追踪它。如果没有调试手段,简直就束手无策。正因为此,在 CM3 中,调试机能突然在一夜之间,就从丑小鸭变成了白天鹅,得到了登峰造极般的,令人非常惊艳的强化。CM3 提供了多种多样的调试模型和调试组件,其中我们使用做多的莫过于JTAG和SWD的调试仿真接口了。
2、接口定义
在用户手册的调试章节中,我们会看到如下的介绍:
可以看到这里讲解的是ARM Cortex-M3内核,并不是某一款单片机的型号,所以在使用ARM Cortex-M3内核单片机时都有相同且标准的调试接口,大家可以以一举三,适用于任何CM3的内核MCU;
关于具体引脚的定义如下:
需要注意的是,下面红色框框中的引脚在MCU上电复位后的功能是调试模式,具体引脚定义和引脚功能描述可以在数据手册中进行查看(PA13/PA14/PA15/PB3/PB4):
简单总结JTAG|SWD调试仿真接口引脚定义如下:
那么如何把引脚作为普通的GPIO使用呢?
下面图中给出了我们禁止JTAG|SWD调试仿真接口寄存器设置方法:
三、JTAG|SWD调试仿真接口作为GPIO口使用的具体方法:
如果仅仅是把调试接口作为普通的GPIO口,根据上图可知:我们可以通过配置SWJ_CFG[2:0]寄存器的这三个bit位即可(可以看出默认000的情况下,MCU的PA13/PA14/PA15/PB3/PB4引脚都是作为了调试接口),当然如果采用库函数进行开发的话,也可以通过相应的API函数进行配置;
gpio_pin_remap_config(uint32_t gpio_remap, ControlStatus newvalue);
//其中参数uint32_t gpio_remap有以下几种选择:
GPIO_SWJ_NONJTRST_REMAP // full SWJ(JTAG-DP + SW-DP),but without NJTRST,对应寄存器SWJ_CFG[2:0]的001;注明:这种方式下可以使用JTAG和SWD的接口进行程序下载;
GPIO_SWJ_SWDPENABLE_REMAP //JTAG-DP disabled and SW-DP enabled,对应寄存器SWJ_CFG[2:0]的010;注明:这种方式下可以使用SWD接口进行程序的下载;JTAG接口已经不能在使用了,此种方式使用最为广泛;
GPIO_SWJ_DISABLE_REMAP //JTAG-DP disabled and SW-DP disabled,对应寄存器SWJ_CFG[2:0]的100;注明:仿真调试接口被全部禁止,所以引脚都作为了GPIO口进行使用,除非GPIO引脚十分紧张的情况下,否则不推荐采用此种设置方法,会造成使用SWD时程序下载和仿真都失效的情况;当然在实际的使用过程中,还是需要根据自己项目的真实情况进行相关引脚的配置。
针对GD系列的单片机,可以参考以下的代码(GD32F103RCT6为例):
void LED_Flash_Init(void)
{
//Enable the peripherals clock
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
/* configure led GPIO port */
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_15);
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_3|GPIO_PIN_4);
//设置初始化后的引脚电平状态
gpio_bit_set(GPIOA,GPIO_PIN_15);
gpio_bit_set(GPIOB,GPIO_PIN_3|GPIO_PIN_4);
}
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
//For use the delay function
systick_config();
//For use the Printf function
USART_Init();
rcu_periph_clock_enable(RCU_AF);
// gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP,ENABLE); //full SWJ(JTAG-DP + SW-DP),but without NJTRST
gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP,ENABLE); //JTAG-DP disabled and SW-DP enabled
// gpio_pin_remap_config(GPIO_SWJ_DISABLE_REMAP,ENABLE); //JTAG-DP disabled and SW-DP disabled
printf("JTAG-DP disabled and SW-DP enabled demo code\r\n");
printf("PA13/PA14 USE SW-DP, PA15/PB3/PB4 USE GPIO\r\n");
//For use the GPIO function
LED_Flash_Init();
while(1)
{
//Led light on
gpio_bit_set(GPIOA,GPIO_PIN_15);
gpio_bit_set(GPIOB,GPIO_PIN_3|GPIO_PIN_4);
delay_1ms(500);
//Led light off
gpio_bit_reset(GPIOA,GPIO_PIN_15);
gpio_bit_reset(GPIOB,GPIO_PIN_3|GPIO_PIN_4);
delay_1ms(500);
}
}
需要特别说明,因为此功能涉及到了复用功能,有操作AFIO_PCF0的寄存器,所以同样需要打开AF时钟,库函数操作如下:
rcu_periph_clock_enable(RCU_AF);
四、如何恢复SWD的功能:
如果在使用的过程中配置为了GPIO_SWJ_DISABLE_REMAP,SWD的功能都禁止了,那么单片机是不是就废了,这颗MCU就不能再进行仿真的操作了呢?答案是否定的,首先是需要把代码中的GPIO_SWJ_DISABLE_REMAP替换为GPIO_SWJ_SWDPENABLE_REMAP ,替换后重新去编译工程文件,生成最新的Hex文件;然后可以通过以下两种方案进行解决:
1、在复位引脚上下功夫,操作相对简单,但是有一定的技巧性:
如果MCU的复位操作是通过外部物理按键实现的话,可以按住复位按键,再点击download程序下载按钮,此时再同步松开MCU的复位按键,特别注意复位按键松开的时间和点击下载按钮的时间需要保持一定的同步,所以说有一定的技巧性;如果设备没有复位按键,同样可以采用镊子短路复位引脚上的电容进行实现;
2、采用MCU的ISP方式进行程序的再次下载,这个需要硬件上修改BOOT的上下拉电平配置,操作上相对复杂一些:
因为MCU在出厂前都有一段固定在Flash内部的BootLoader,通过串口可以进行程序的下载;但需要通过修改Boot的连接方式,具体Boot的配置如下第②中方式:
然后通过MCU原厂的ISP上位机即可实现单片机的ISP程序下载,UART的配置一般为115200-8-1-N,如果你恰巧使用的是GD的MCU,可以通过搜索“GigaDevice_MCU_ISP_Programmer_V3.0.2.5782”进行免费获取。
以上就是针对Cortex-M内核MCU中JTAG|SWD调试仿真接口做为普通GPIO使用的简单说明,希望可以帮助到正在不断调试的你。
------------------------------------------------------------------------------------------------------------------------------------------
因为小编自己能力水平有限,文中难免有错误或表达不到的信息,还望广大阅读者留言批评指正,谢谢。
|