SWO引脚配置覆盖, 导致ITM信息打印失效

试验原因

在STM32F407上作SPI方式的SD卡试验, 因为手头没有产品板子,就找了一个开发板作试验。
SD卡驱动库在其他开发板上验证过了好使。
但是在这个板子上SD卡初始化失败。

看现在接上这块SD卡模块,上面有稳压芯片。标着电源是5V的。板子上接过来的是3.3V, 估计是SD卡模块电压不足引起SD卡不能正常操作。

手头还有几块以前屯的SD卡模块,有2块是没有稳压芯片的, 只有SD卡插座,上拉电阻,SPI方式的连线(VDD/GND/SWCLK/SWDIO/SWO),如果接上这个SD卡模块,相当于接上了和产品板子一样的SD卡电路。

接上后SD卡还是初始化失败…, 哪出问题了?
SD卡驱动库是正常的(在上一个开发板上验证过).
开始找问题

为了调试方便,打印了ITM信息。
发现程序入口处是可以打印出ITM信息的。等程序跑起来,ITM信息就看不到了。
根据经验,程序中如果发现了一个小问题,那么隐藏的问题可能不止这一个点,一定要先将发现的任何已知问题先搞定(解决或定位),再去查其他问题。

先缩小问题范围,加了更多的ITM打印信息。程序跑起来后,发现进了SD卡的GPIO初始化后,ITM信息就没了。

开始单步GPIO初始化代码。在单步之前,在GPIO初始化函数中,加了更多的ITM信息。
开始单步,看看到哪里ITM信息没了。这下找到问题了, 因为SPI管脚在2块开发板上不一样,改程序的时候,由于手误, 将PB13写成了PB3, 将SWO引脚占住了。MCU复位时,调试用的SWO引脚默认就是PB3. 只要系统时钟设置完了,printf打印的ITM信息就能被MDK收到。当设置PB3为其他功能(e.g. SPI1_CLK)后, SWO功能就没了,ITM信息就打印不出来了。

试验

\bsp\sd\bsp_spi_sdcard.c

static void GPIO_Configuration(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
  SPI_InitTypeDef   SPI_InitStructure;

  /*!< SD_SPI_CS_GPIO, SD_SPI_MOSI_GPIO, SD_SPI_MISO_GPIO, SD_SPI_DETECT_GPIO 
       and SD_SPI_SCK_GPIO Periph clock enable */
  
  SD_CS_PERIPH_CLOCK_CMD(SD_CS_GPIO_CLK, ENABLE);
  SD_SPI_SCK_PERIPH_CLOCK_CMD(SD_SPI_SCK_GPIO_CLK, ENABLE);
  SD_SPI_MOSI_PERIPH_CLOCK_CMD(SD_SPI_MOSI_GPIO_CLK, ENABLE);
  SD_SPI_MISO_PERIPH_CLOCK_CMD(SD_SPI_MISO_GPIO_CLK, ENABLE);
       
  /*!< SD_SPI Periph clock enable */
  SD_SPI_PERIPH_CLOCK_CMD(SD_SPI_CLK, ENABLE);
  
  /*!< AFIO Periph clock enable */
  /*!< Remap SPI Pins */
  
  GPIO_PinAFConfig(SD_SPI_SCK_GPIO_PORT, SD_SPI_SCK_SOURCE, SD_SPI_SCK_AF);
  GPIO_PinAFConfig(SD_SPI_MISO_GPIO_PORT, SD_SPI_MISO_SOURCE, SD_SPI_MISO_AF);
  GPIO_PinAFConfig(SD_SPI_MOSI_GPIO_PORT, SD_SPI_MOSI_SOURCE, SD_SPI_MOSI_AF);

  // configure SPI_SD GPIO
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; // 中速 - 降低EMC
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL; // 官方实现 - 无上下拉(MISO/MOSI/CS有外部上拉, SCK无上下拉)
  
  // configure SPI_SD GPIO - SCK
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 官方实现 - 管脚为备用功能
  GPIO_InitStructure.GPIO_Pin = SD_SPI_SCK_PIN;
  
  GPIO_Init(SD_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);

  /*!< Configure SD_SPI pins: MOSI */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 官方实现 - 管脚为备用功能
  GPIO_InitStructure.GPIO_Pin = SD_SPI_MOSI_PIN;
  
  GPIO_Init(SD_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);

  /*!< Configure SD_SPI pins: MISO */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 官方实现 - 管脚为备用功能
  GPIO_InitStructure.GPIO_Pin = SD_SPI_MISO_PIN;
  
  GPIO_Init(SD_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
  
  /*!< Configure SD_SPI_CS_PIN pin: SD Card CS pin */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_Pin = SD_CS_PIN;
  
  GPIO_Init(SD_CS_GPIO_PORT, &GPIO_InitStructure);

  /*!< Configure SD_SPI_DETECT_PIN pin: SD Card detect pin */
//  GPIO_InitStructure.GPIO_Pin = SD_DETECT_PIN;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
//  GPIO_Init(SD_DETECT_GPIO_PORT, &GPIO_InitStructure);

  /*!< SD_SPI Config */
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  
  // 如果 GPIO_Speed_xMHz 和 SPI_BaudRatePrescaler_x不匹配, SD卡会挂载失败
  // 匹配的列表如下
  // GPIO_Speed_50MHz 配 SPI_BaudRatePrescaler_2
  // GPIO_Speed_10MHz 配 SPI_BaudRatePrescaler_4
  // GPIO_Speed_10MHz 配 SPI_BaudRatePrescaler_8
  // GPIO_Speed_10MHz 配 SPI_BaudRatePrescaler_16
  // GPIO_Speed_10MHz 配 SPI_BaudRatePrescaler_32
  // GPIO_Speed_10MHz 配 SPI_BaudRatePrescaler_64
  // GPIO_Speed_10MHz 配 SPI_BaudRatePrescaler_128
  // GPIO_Speed_10MHz 配 SPI_BaudRatePrescaler_256
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  
  SPI_Init(SD_SPI, &SPI_InitStructure);
  
  SPI_Cmd(SD_SPI, ENABLE); /*!< SD_SPI enable */
}

\bsp\sd\bsp_spi_sdcard.h

// \BSP\SD_Card_Driver\bsp_spi_sdcard.h
#ifndef __BSP_SPI_SDCARD_H__
#define __BSP_SPI_SDCARD_H__

#ifdef __cplusplus
 extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
// #include "stm32f10x.h"

#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"

// 固定只支持blocksize大小为512的卡,兼容大于512的卡时,该卡容量会变小
#define SD_BLOCKSIZE     512 // SDCardInfo.CardBlockSize 
	 
/** @addtogroup Utilities
  * @{
  */

// SPI device	 
#define SD_SPI                          SPI2
#define SD_SPI_CLK                      RCC_APB1Periph_SPI2
#define SD_SPI_PERIPH_CLOCK_CMD         RCC_APB1PeriphClockCmd

// sd card SCK		 
#define SD_SPI_SCK_PIN                  GPIO_Pin_13 // 这里是PB13, 不是PB3
#define SD_SPI_SCK_GPIO_PORT            GPIOB                       
#define SD_SPI_SCK_GPIO_CLK             RCC_AHB1Periph_GPIOB
#define SD_SPI_SCK_PERIPH_CLOCK_CMD     RCC_AHB1PeriphClockCmd
#define SD_SPI_SCK_AF                   GPIO_AF_SPI2

// PB3是SWO, 如果手误将GPIO_PinSource13 写成 GPIO_PinSource3
// 调用了SPI2初始化之后 GPIO_PinAFConfig(SD_SPI_SCK_GPIO_PORT, SD_SPI_SCK_SOURCE, SD_SPI_SCK_AF);
// PC端就收不到ITM信息了
#define SD_SPI_SCK_SOURCE               GPIO_PinSource13
	 
// sd card MISO
#define SD_SPI_MISO_PIN                 GPIO_Pin_14                
#define SD_SPI_MISO_GPIO_PORT           GPIOB                       
#define SD_SPI_MISO_GPIO_CLK            RCC_AHB1Periph_GPIOB
#define SD_SPI_MISO_PERIPH_CLOCK_CMD    RCC_AHB1PeriphClockCmd
#define SD_SPI_MISO_AF                  GPIO_AF_SPI2
#define SD_SPI_MISO_SOURCE              GPIO_PinSource14

// sd card MOSI
#define SD_SPI_MOSI_PIN                 GPIO_Pin_15                
#define SD_SPI_MOSI_GPIO_PORT           GPIOB                       
#define SD_SPI_MOSI_GPIO_CLK            RCC_AHB1Periph_GPIOB
#define SD_SPI_MOSI_PERIPH_CLOCK_CMD    RCC_AHB1PeriphClockCmd
#define SD_SPI_MOSI_AF                  GPIO_AF_SPI2
#define SD_SPI_MOSI_SOURCE              GPIO_PinSource15

// sd card CS	 
#define SD_CS_PIN                       GPIO_Pin_12
#define SD_CS_GPIO_PORT                 GPIOB      
#define SD_CS_GPIO_CLK                  RCC_AHB1Periph_GPIOB
#define SD_CS_PERIPH_CLOCK_CMD          RCC_AHB1PeriphClockCmd

//  #define SD_DETECT_PIN                    GPIO_Pin_0                 
//  #define SD_DETECT_GPIO_PORT              GPIOE                       
//  #define SD_DETECT_GPIO_CLK               RCC_APB2Periph_GPIOE

  
/** @addtogroup STM32_EVAL
  * @{
  */ 

GPIO初始化时,为了维护方便,将参数都写成了宏。
这个试验在其他开发板上试验时,用的是SPI1. 在这个开发板上试验,改成了SPI2上接SD卡模块
F407有3个SPI接口, 用CubeMX模拟新建一个工程, 使能SWD调试,使能全部的3个SPI, 看的清楚。
在这里插入图片描述
在这里插入图片描述
可以看到SWD调试引脚有3个:
SWCLK = PA14
SWDIO = PA13
SWO = PB3

SPI操作要用到SPI_CS/SPI_CLK/SPI_MOSI/SPI_MISO

F407的SPI1用到的默认管脚如下:
SPI1_CS = PA4
SPI1_CLK = PA5
SPI1_MISO = PA6
SPI1_MOSI = PA7

F407的SPI2用到的默认管脚如下:
SPI2_CS = PB12
SPI2_CLK = PB10
SPI2_MISO = PC2
SPI2_MOSI = PC3

F407的SPI3用到的默认管脚如下:
SPI3_CS = PA15
SPI3_CLK = PC10
SPI3_MISO = PC11
SPI3_MOSI = PC12

在前面那块开发板上, SPI管脚用的都是默认的。

在现在这块开发板上, SPI2复用了另外的管脚如下:
在这里插入图片描述
SPI2_CS = PB12
SPI2_CLK = PB13
SPI2_MISO = PB14
SPI2_MOSI = PB15
我就是在改SPI2_CLK时,将PB13失误写成PB3, 导致覆盖了MCU的SWO默认引脚,导致ITM信息打印不出来。

F407的默认SPI管脚, SP1/SP3的4根连线(CS/CLK/MISO/MOSI)都是挨着的,方便布线。
只有SPI2的4根连线不是挨着的,不方便布线。在第三方开发板上,人家将SPI2复用过来后,SPI2的4根线就是挨着的,方便布线。
如果是用F407重新布板,将SPI2调整到(PB12/PB13/PB14/PB15)是一个好选择.

总结

感觉更换不同开发板作试验时,先建立一个CubeMX工程,将管脚都摆好,先有个直观的印象. 再去改程序中的GPIO配置,能少走些弯路和手误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值