dffzh 发表于 2025-8-1 14:35

MCU引脚不够用,那就把烧录脚也用上吧!

本帖最后由 dffzh 于 2025-8-1 14:38 编辑

之前做过一个项目,因为是降本方案,所以对芯片选型要求比较高,特别是其中的MCU主控,综合评估后,最后选了STM32G431KBU3,一款带26个GPIO引脚的M4核芯片。可是让我没有想到的是,最后这个芯片的普通GPIO引脚居然不够用,没办法,只能把烧录脚SWCLK和SWDIO也用上了,主控原理图如下图所示:其中烧录脚SWCLK和SWDIO用作模拟I2C功能,读写外部EEPROIM芯片。那这样在代码仿真调试I2C功能时就会比较麻烦了,因为如果烧录脚SWCLK和SWDIO配置为普通GPIO模式后,就无法正常仿真了,只能下载程序到板子上实际运行看结果了。因此为了调试方便一些,代码上就最后再调试I2C了,并加上一个宏定义来使能或禁止烧录脚SWCLK和SWDIO的GPIO配置,如下图所示:需要仿真的时候,就手动把I2C_ENABLE的定义屏蔽掉;需要实测I2C功能时,就手动把I2C_ENABLE的定义打开。这里还有个问题需要注意,就是如果配置为GPIO模式后,如果烧录信号线不接RESET脚,是无法正常下载程序的,不知道其他MCU是不是也是如此。像这种GPIO复用的设计,其实不是很好,后面有时候因为出现Bug需要仿真时,操作半天进不了仿真,以为代码有问题,结果排查后才发现,原来是没有关闭I2C配置,因为时间长了,容易忘记;还有就是修改Bug后生成固件,结果测试发现参数无法掉电保存,结果是生成固件时没有使能I2C配置。反正就是这种复用操作,很可能会遇到意想不到的问题,结果我们还认为是不可思议的。因此,除非真的没有办法了,类似这种用烧录脚来做普通GPIO功能的设计,看上去似乎很高端很优秀,其实稍微不小心,就容易出问题,而且可能会影响芯片的二次烧录。大家有木有做过类似的开发设计?欢迎分享一下心得~~。

丙丁先生 发表于 2025-8-1 22:16

那怎么烧录啊?

大大财迷 发表于 2025-8-4 08:09

建议:芯片在上电开机后,时钟初始化之后,要延时3S左右,再将SWD设置为GPIO,否则,量产时将引起程序无法烧录的问题。

大大财迷 发表于 2025-8-4 08:11

还有一个办法:将SWD的RST引出来,烧录时接到烧录器,下载时烧录器强制复位MCU,也可以实现烧录口占用暂时解除。

hp860629 发表于 2025-8-4 09:02

可以的

xch 发表于 2025-8-4 09:25

我不用宏定义。自动切换调试模式和运行模式。
几行代码的工作。

zjk103 发表于 2025-8-4 09:55

能不用最好不要用,后面烧录很麻烦

dukedz 发表于 2025-8-4 10:05

串口打印调试啊

xch 发表于 2025-8-4 14:23

/********************************
在初始化时检测一下SWD 仿真器是否接入;
复位后先按照SWD 功能配置 PA13,14。
检测SWD 接口函数也增加了启动的延时。
*****************************/
uint8_t JlinkOnline(void)
{
uint16_t cnt =0;
uint16_t tmp =PinInput(SWCLK);
do{
    if( tmp != PinInput(SWCLK)) //读IO电平函数,检测SWCLK 是否翻转
    {
      return 1; //发现仿真器
    }
}while(++cnt<60000);
return 0; //未接入仿真器返回0.
}

int main()
{
;;;;;;;
if(0 == JlinkOnline () )
{
    ConfigSwdPinFucntionRatherThanSwd();
   // DisableWatchDog();
//DisableDeepSleepMode();
}
;;;;;;;;;;
while(1)
{
;;;;;;;;;;;;
}
}

xch 发表于 2025-8-4 14:27

其实,还有其他功能没有一一列出。比如加密功能。未连接仿真器就把MCU 加密。
下次调试下载时会自动全片擦除。免得忘记加密就出货了。

xch 发表于 2025-8-4 14:51

#define PA(x) P(A,x)
#define P(GpioName,PinNum) (tPin){GPIO##GpioName,PinNum}

typedef struct{
    GPIO_TypeDef *GPIO;
    const uint8_t PinNum;
}tPin;

#define SWDIO   PA(13)
#define SWCLK   PA(14)

uint16_t PinInput (tPin pin)
{
//return(pin.GPIO->IDR )& (1<<pin.PinNum);
return(pin.GPIO->IDR >>pin.PinNum)& 1;
}

页: [1]
查看完整版本: MCU引脚不够用,那就把烧录脚也用上吧!