试验原因

在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 GPIOGPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; // 中速 - 降低EMCGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL; // 官方实现 - 无上下拉(MISO/MOSI/CS有外部上拉, SCK无上下拉)// configure SPI_SD GPIO - SCKGPIO_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_256SPI_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 __cplusplusextern "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配置,能少走些弯路和手误。

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

  1. 乐鑫esp8266学习rtos3.0笔记第11篇:详细分析Esp8266上电信息打印的数据,如何做到串口通讯上电不乱码打印。

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,不做开发板.仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 序号 SDK版本 内容 链接 1 nonos2.0 搭建 ...

  2. IP地址配置冲突导致路由振荡怎么办

    本期小编为大家带来的是:由于IP地址配置冲突导致路由振荡,使用户业务时断时通. 背景知识: IP地址在一个局域网内具有唯一性,也就是说局域网内,不能为不同的设备配置相同的IP地址. 组网情况: RTA ...

  3. muduo网络库学习(九)日志类Logger和LogStream,将日志信息打印到屏幕

    每一个成熟的项目都有大大小小的日志系统,在关键的地方打印日志信息,常用来跟踪程序运行,查找错误原因等,可以节省大量的debug时间 muduo的日志信息有5个级别 TRACE,细粒度最高的日志信息,打 ...

  4. springBoot项目配置文件加载优先级及同配置覆盖问题

    背景: 由于目前网上对于springboot配置文件的加载问题,存在着各种不同的说法.所以导致自己不敢确定到底何种结论才是真正正确的,故专门花费了一些时间进行亲自验证. 验证: 在经过自己对配置文件的 ...

  5. DNS配置错误导致无法访问网络

    DNS配置错误导致无法访问网络 背景 今天居家办公,发现vbox上的centos无法访问到yum仓库.以为是vbox的配置有问题.yum源的问题,折腾了大半天,最后才发现的DNS的问题. 问题复现 使 ...

  6. 学生信息打印辅助系统

    学生信息打印辅助系统 #详情访问:https://github.com/tongxunkeji/student_info_system 如果你是在校师生你的日常是否也和我一样,混迹在各种,学籍证明.转 ...

  7. laravel-admin 关闭debug模式导致异常信息到页面的排查

    laravel-admin 关闭debug模式导致异常信息到页面的排查 参考文章: (1)laravel-admin 关闭debug模式导致异常信息到页面的排查 (2)https://www.cnbl ...

  8. STM32 端口复用与重映射及低功耗引脚配置

    STM32 端口复用与重映射及低功耗引脚配置 什么是复用? 在TSM32里面,大部分的引脚都是有GPIO复用功能,也就是说,一个 GPIO如果可以复用为内置外设的功能引脚,那么当这个 GPIO 作为内 ...

  9. jni程序中获取签名信息打印截断问题

    在jni获取的签名信息打印出来与java层获取的不一样,少了一部分,验证jni程序LOG最长只能打印1024字节,因此不是获取错误,只是打印限制. 转载于:https://www.cnblogs.co ...

最新文章

  1. python三个小题
  2. emmet快速缩写展开的基本写法与心得
  3. html5显示字幕信息,HTML5 Placeholder实现input背景文字提示效果
  4. CVPR 2020 | 反传统的无监督人脸旋转方案:旋转-渲染
  5. 中煤保险 公司举办“虎啸杯”保险知识竞赛活动
  6. 带你见识不一样的世界,这5部豆瓣纪录片不可错过!
  7. 运维质变育新机,华为云能否引领政企运维破局?
  8. 快捷键_AutoCAD 2021中的默认快捷键、新建或编辑快捷键
  9. Speed Reading(POJ-3619 )
  10. 安装Oracle提示OracleMTSRecoveryService 已经存在,解决方法
  11. 《C++ primer 》 猎豹网校 函数模板 2018/10/9
  12. ICPC2017沈阳赛区游记
  13. Android计步模块(类似微信运动 今日步数)
  14. android+动态光圈效果,OpenGL Shader实例分析(8)彩色光圈效果
  15. 【基础机器学习算法原理与实现】使用感知器算法LDA、最小二乘法LSM、Fisher线性判别分析与KNN算法实现鸢尾花数据集的二分类问题
  16. 在ROS下控制dobot(magician)机械手的吸盘
  17. 2018华为校招笔试题
  18. 微信小程序 延时执行 延时跳转
  19. 怎么做 空间杜宾模型_空间杜宾模型在应用中新进展.doc
  20. 惠普(HP)笔记本的型号解析

热门文章

  1. 泡妞技术帖:一物降一物 金庸爷爷教你如何谈恋爱
  2. 看了多篇2019年的面经后的个人总结
  3. 2017年浙江工业大学大学生程序设计迎新赛热身赛-J-Forever97与寄信
  4. 七、后台入口及添加影院实现《仿淘票票系统前后端完全制作(除支付外)》
  5. sql server 中 create or replace 视图方法
  6. SqlServer 并发事务:死锁跟踪(一)简单测试
  7. [Java JVM] Hotspot GC研究- 64位引用指针压缩技术
  8. java用星星符号打印出一个直角三角形
  9. Python3使用动态规划处理背包问题:完全背包(含背包恰好装满的情况)
  10. word-wrap html,word-wrap