SWD调试在STM32中REMAP调试的深入探究

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/baidu_25505611/article/details/79456251
首先说一下问题的现象,如果有这种现象的同学可以看看博主的这篇博文
程序download一次后,第二次download就提示no target connect,除非长按reset键才能继续下载程序

首先上一组stm32的TIM2的端口使用组合有下面四种:

1.当不重映射时,默认TIM2四个的IO口是PA0、PA1、PA2、PA3

开启重映射__HAL_AFIO_REMAP_TIM2_ENABLE()

2.要使用PA15、PB3、PA2、PA3的端口组合,要调用下面的语句进行部分重映射:


__HAL_AFIO_REMAP_TIM2_PARTIAL_1()


3.要使用PA0、PA1、PB10、PB11的端口组合,要调用下面的语句进行部分重映射:

__HAL_AFIO_REMAP_TIM2_PARTIAL_2()


4.要使用PA15、PB3、PB10、PB11的端口组合,要调用下面的语句进行完全重映射:

__HAL_AFIO_REMAP_TIM2_ENABLE()

同时还要禁用JTAG功能,PA15、PB3、PB10、PB11才会正常输出。

那么使用了重映射之后会导致一个问题,程序download一次后,第二次download就提示no target connect,除非长按reset键才能继续下载程序。

该问题讨论可在此问答中找到答案

https://electronics.stackexchange.com/questions/260757/timer1-remap-cause-debug-crash-on-stm32f103
从该帖子找到的精辟回答如下

The problem is that the STM32F1 series has one register AFIO_MAPR which contains thesettings for remapping various peripherals and for enabling/disabling the JTAG/SWD connectionto your debugger. And to makethis more complicated, the bits in that register which enable/disable theJTAG/SWD settings (bits 24-26) arewrite-only so their existing state cannot be read.

See this extract from the STM32F1Reference Manual:

This means that any attempt to change the settings of thevarious "peripheral remap" bits, by doing a read-modify-writesequence to this register, could read differentvalues instead of the real current valuesin the JTAG/SWD bits. Then, when the write to the register is done, your debugger access stopsbecause whatever was read from those JTAG/SWD bits, is written back to them.(Other effects have also been reported, but I won't go into that now).

From what I could find without installing the HAL, the macrosused are:

#define __HAL_AFIO_REMAP_TIM1_ENABLE()
MODIFY_REG(AFIO->MAPR, AFIO_MAPR_TIM1_REMAP, AFIO_MAPR_TIM1_REMAP_FULLREMAP)

and MODIFY_REG is:

#define MODIFY_REG(REG, CLEARMASK, SETMASK)
WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))

So as you see, MODIFY_REG isdoing a read-modify-write and you don't know what values it will read fromJTAG/SWD bits 24-26 andhence what values it will write back to there! The values read from those bitsare "undefined" (to quote ST) and I know I have read different valuesfrom the same STM32F1 at different times.

The "fix" I have used with the SPL, is to change anyremapping code to specifically set the JTAG/SWD bits which you want, wheneveryou write to the AFIO_MAPRregister. You will need to figure out how you want to do the same with the HALcode. One way is to use a temporary variable so, from memory, the sequencebecomes:

·        Read AFIO_MAPR register intotemp variable

·        Change desired peripheralremap bits in the temp variable

·        Mask out bits 24-26 in thetemp variable

·        Set bits 24-26 in the tempvariable to whatever I wanted (therefore ignoring whatever their, likelyincorrect, "read" value was)

·        Write temp variable toAFIO_MAPR


基本上导致这个问题的原因在于SWJ_CFG[2]位是Write Only的,
__HAL_AFIO_REMAP_I2C1_ENABLE()中会执行类似reg |= xxx_enable的操作
该操作会读寄存器,然后或上某个使能位
然而由于SWJ_CFG[2]位的Write Only特性,导致寄存器读出来后不是实际的值

解决方法:在使用了引脚复用的宏之后需要调用一次__HAL_AFIO_REMAP_SWJ_NOJTAG(),该宏的解释如下:

/**

 * @brief Enable the Serial wire JTAG configuration

 * @note  NOJTAG: JTAG-DP Disabledand SW-DP Enabled

 * @retval None

 */

#define__HAL_AFIO_REMAP_SWJ_NOJTAG()   do{CLEAR_BIT(AFIO->MAPR, AFIO_MAPR_SWJ_CFG);           \

                                           SET_BIT(AFIO->MAPR, AFIO_MAPR_SWJ_CFG_JTAGDISABLE); \

                                         }while(0U)

我们追一下CLEAR_BIT(AFIO->MAPR,AFIO_MAPR_SWJ_CFG); 

可以发现#defineCLEAR_BIT(REG, BIT)   ((REG) &=~(BIT))

继续追该宏使用的参数AFIO->MAPR,AFIO_MAPR_SWJ_CFG,其中MAPR为复用寄存器,而AFIO_MAPR_SWJ_CFG追到最后为0x07000000(过程比较多,就不赘述了),再通过&= ~(BIT)操作,得出&=~(0111000000000000000000000000)

最后结果为&=11111000111111111111111111111111

这个时候可以看出来在CLEAR_BIT(AFIO->MAPR,AFIO_MAPR_SWJ_CFG);宏的作用是使得MAPR寄存器的Bits 26:24重置为0。

这个时候博主把MAPR寄存器放出来


可以发现是重新复位了SWJ,也就是重置了JTAG位的功能。

 

 

接下来我们再看SET_BIT(AFIO->MAPR,AFIO_MAPR_SWJ_CFG_JTAGDISABLE);

功能函数#defineSET_BIT(REG, BIT)     ((REG) |= (BIT))

直接追AFIO_MAPR_SWJ_CFG_JTAGDISABLE,最后得出该值是0x02000000

所以该值操作为|=02000000,即|=00000 010 000000000000000000000000

重新看该值010在寄存器的作用,可以发现现在使能了SWD的调试功能了。
 ———————————————— 
版权声明:本文为CSDN博主「Blucher_Ce」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/baidu_25505611/article/details/79456251

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值