STM32F0 使用ST-LINK实现对外部Flash芯片的烧录

本文介绍了如何在外挂GD25Q32芯片上进行STM32F0平台的SPI闪存烧录,包括初始化步骤、驱动移植、烧录工具使用和注意事项,为解决资源加载难题提供了实践指导。

最近项目用到STM32F0驱动TFT显示,因存在字库及图片资源,有限的内部Flash肯定无法胜任这些资源,所以外挂了个GD25Q32芯片作为资源,设计板子时候没考虑到外部flash初始化数据的需求,这样开发过程频繁的修改flash数据就面临一大难题。

仔细分析认为只有几个方法:

1、飞线直接用外部的USB烧录器在线烧录,看似解决问题,但日后升级就很尴尬,不可能每个板子都飞线一次吧?

2、通过调试串口自定义协议,实现间接升级flash数据,看似合情合理,可还要面临开发个PC端APP实现协议对接,时间伤不起。

3、网上一搜,果然也有不少人碰到同样问题,之前没注意STLINK也支持在线烧录,不正是我需要的吗?大喜,分析看到官方提供了一些驱动例程都不是基于我的硬件,只好自己改,话不多说直接开工。

随便找个接近的例程,复制文件夹再重新命名为自己项目文件夹,此例用25Q32_STM32F072-EVAL,见下图:

替换用到的STD库文件,参考工程为STMF1系列,此处需要替换为STM32F0系列,包括源文件及头文件等,见下图:

 

然后进入工程,修改工程MCU为STM32F0系列,输出文件改成自己容易识别的。

下一步就是调整硬件对应的GPIO及代码移植了,注意,F1和F0系列的时钟有点不同,下面是重要修改部分,增加了AF功能开启,GPIO时钟也对应修改:
 

/**
  * @brief  Initializes the peripherals used by the SPI FLASH driver.
  * @param  None
  * @retval None
  */
void sFLASH_LowLevel_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /*!< sFLASH_SPI_CS_GPIO, sFLASH_SPI_MOSI_GPIO, sFLASH_SPI_MISO_GPIO 
       and sFLASH_SPI_SCK_GPIO Periph clock enable */
  RCC_AHBPeriphClockCmd(sFLASH_CS_GPIO_CLK | sFLASH_SPI_MOSI_GPIO_CLK | sFLASH_SPI_MISO_GPIO_CLK |
                         sFLASH_SPI_SCK_GPIO_CLK, ENABLE);
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE) ;
  /*!< sFLASH_SPI Periph clock enable */
  RCC_APB2PeriphClockCmd(sFLASH_SPI_CLK, ENABLE);
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_0);  
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_0);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_0); 
  /*!< Configure sFLASH_SPI pins: SCK */
  GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_SCK_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_Init(sFLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);

  /*!< Configure sFLASH_SPI pins: MOSI */
  GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_MOSI_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_Init(sFLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);

  /*!< Configure sFLASH_SPI pins: MISO */
  GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_MISO_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(sFLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
  
  /*!< Configure sFLASH_CS_PIN pin: sFLASH Card CS pin */
  GPIO_InitStructure.GPIO_Pin = sFLASH_CS_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_Init(sFLASH_CS_GPIO_PORT, &GPIO_InitStructure);
  GPIO_SetBits(sFLASH_CS_GPIO_PORT, sFLASH_CS_PIN);
}

然后是在Dev_inf.c定义flash规格,此处英文备注容易误导,试了好几次才弄清楚,我对注释做了更正直观一些,继续保留英文风格不伤大雅:

#if defined (__ICCARM__)
__root struct StorageInfo const StorageInfo  =  {
#else
struct StorageInfo const StorageInfo  =  {
#endif
   "GD25Q32_STM32F0XX-EVAL", 	 	 // Device Name + version number
   SPI_FLASH,                  		// Device Type
   0x00000000,                		// Device Start Address, STM32 external flash start at 0H
   4*1024*1024,                 	// Device Size in Bytes (4MBytes/32Mbits)
   0x00000100,                 		// Programming Page Size 256Bytes
   0xFF,                       		// Initial Content of Erased Memory
// Specify Size and Address of Sectors (view example below)
   0x00000040, 0x00010000,     		// Block count : 64 ,each block has 64k byte
   0x00000000, 0x00000000,			// end flag
}; 

对应的spi读写函数也有点修改:


/**
  * @brief  Sends a byte through the SPI interface and return the byte received
  *         from the SPI bus.
  * @param  byte: byte to send.
  * @retval The value of the received byte.
  */
uint8_t sFLASH_SendByte(uint8_t byte)
{
  /*!< Loop while DR register in not emplty */
  while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET);

  /*!< Send byte through the SPI1 peripheral */
  SPI_SendData8(sFLASH_SPI, byte);

  /*!< Wait to receive a byte */
  while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET);

  /*!< Return the byte read from the SPI bus */
  return SPI_ReceiveData8(sFLASH_SPI);
}

编译后生成对应的stldr文件,因为项目文件夹与其他平行,所以生成的代码也在STLINK扫描的文件夹中,这样在STLINK中的External loader 菜单的add external loader 就会自动出现这个选择,见下图:

 点击Validate就可以验证了。

注意,注意,注意!重要事情说3次,外挂Flash起始地址为0,注意烧录时候选择正确地址烧写bin文件,选择烧录后校验比较安全,毕竟是全部读回烧写的数据100%无误。

烧录后,可以直接在内存视图看到刚才烧录的数据了:

 测试2M文件用了不到1分钟,通过更改spi分频还可以加快,我用了4分频。 

至于具体字库及图片合并在另一文章讨论,因找不到合适软件,我做了个混合多个资源工具,自动生成资源地址定义,类似MFC资源索引。

本文仅针对外部flash烧录移植做了抛砖引玉的介绍,具体其他型号可以根据需求自行更改,有需求的也可以到我的下载中下载完整工程,代码在ST原装MCU和国产替代APM都测试通过,其他规格估计不行,因为STM32 STLINK 本身就不识别非ST芯片,目前只有Device ID兼容的高仿才可以用到这个便利功能。

<think>首先,用户的问题是:“我想解决STM32烧录程序时找不到Cortex-M0的问题请问STM32烧录程序找不到Cortex-M0解决方案”。这似乎是关于STM32微控制器烧录程序时遇到错误,具体是找不到Cortex-M0核心。从系统级指令中,我需要:-所有行内数学表达式用$...$格式。-独立公式用$$...$$格式并单独成段。-LaTeX语法正确。-使用中文回答。-生成相关问题。-在回答中引用的段落末尾自然地添加引用标识,例如[^1]。-回答结构清晰,帮助用户逐步解决问题。-参考站内引用:[^1],[^2],[^3],[^4]。站内引用内容:-[^1]:关于STM32远程烧录程序,涉及启动机制、BootLoader等。-[^2]:关于STM32通过USB烧录程序,包括使用Arduinobootloader。-[^3]:关于STM32flash被锁导致错误,解决办法。-[^4]:关于STM32烧录程序方式,启动模式等。用户的问题核心是“找不到Cortex-M0”,这可能是在烧录工具(如KeiluVision,ST-LinkUtility等)中出现的错误。常见原因包括:1.连接问题:硬件连接不正确,如SWD/JTAG接口未连接好。2.启动模式设置错误:STM32的BOOT引脚配置不正确。3.Flash被锁:芯片被保护,无法访问。4.工具配置错误:烧录软件中的设备选择错误。5.芯片损坏:硬件故障。从引用中,[^3]直接提到“ErrorFlashDownloadfailedCortex-M4”,并提供了解决办法,这类似于用户的问题,但用户是Cortex-M0。Cortex-M0和M4都是ARM核心,但错误类似,解决方法可能相通。[^4]提到启动模式,这可能相关。[^2]提到USB烧录,可能涉及bootloader。[^1]是关于远程烧录。我的回答应该:1.结构清晰:逐步解决问题。2.参考引用:自然地添加引用标识。3.使用中文。4.生成相关问题。步骤:1.**确认问题**:用户烧录STM32时,工具报告找不到Cortex-M0核心。2.**常见原因和解决方案**:-检查硬件连接:确保SWD/JTAG接口正确连接,电源稳定。-检查启动模式:BOOT引脚设置是否正确(通常BOOT0=0,BOOT1=0为正常启动)。-解锁Flash:如果芯片被锁,需要擦除或解锁。-软件配置:在烧录工具中,确保选择了正确的设备型号(如STM32F0系列,如果是Cortex-M0)。-其他:复位芯片,检查电路板。从引用[^3],它提到“ErrorFlashDownloadfailedCortex-M4”,解决办法包括使用J-Flash擦除。类似地,对于Cortex-M0,可以使用ST-LinkUtility或其他工具解锁。从引用[^4],启动模式重要,BOOT[1:0]引脚配置。回答结构:-引言:确认问题。-步骤1:检查硬件连接。-步骤2:检查启动模式。-步骤3:解锁Flash或擦除芯片-步骤4:软件配置。-步骤5:其他建议。-结尾:总结。-生成相关问题。添加引用:在相关部分末尾添加引用标识,例如在讨论解锁Flash时引用[^3],在启动模式时引用[^4]。使用中文。生成相关问题:基于主题,如烧录错误、STM32配置等。确保行内数学表达式正确:如果有任何数学内容,但这里可能不需要,除非涉及地址或值,如BOOT引脚值。例如,BOOT引脚设置:BOOT0和BOOT1的值,可以用行内格式,如$BOOT0=0$,$BOOT1=0$。独立公式:可能不需要。现在,构建回答。</think>### STM32烧录程序时找不到Cortex-M0的解决方案 您在烧录STM32程序时遇到工具报告“找不到Cortex-M0”的错误,这通常发生在使用Keil uVision、ST-Link Utility或其他烧录软件时。此错误表明烧录工具无法识别或连接到STM32芯片的Cortex-M0核心,可能由硬件连接、启动模式、Flash锁状态或软件配置问题引起。下面我将一步步引导您解决此问题,确保解决方案真实可靠。解决方案基于STM32常见烧录机制和参考内容,我会在相关部分添加引用标识。 #### 步骤1: 检查硬件连接(优先排除基础问题) - **原因分析**:SWD(Serial Wire Debug)或JTAG接口连接不良、电源不稳定或电路板故障可能导致工具无法检测核心。 - **解决方案**: - 确保烧录器(如ST-Link、J-Link)与STM32开发板的SWD接口正确连接:通常包括`SWCLK`(时钟线)、`SWDIO`(数据线)、`GND`(地线)和`VCC`(电源线)。检查线缆是否松动或损坏。 - 验证电源供应:STM32芯片需要稳定电压(通常3.3V)。使用万用表测量$V_{CC}$和$GND$引脚电压,确保在$3.0V - 3.6V$范围内。 - 尝试复位芯片:按下开发板上的复位按钮,或在烧录前断开再重新连接电源。 - 如果问题持续,用另一块已知正常的STM32开发板测试烧录器,以排除硬件故障。 #### 步骤2: 检查启动模式设置(关键配置步骤) - **原因分析**:STM32的启动模式由BOOT引脚控制。如果BOOT引脚配置错误(如设置为从系统存储器启动),芯片可能无法进入调试模式,导致工具找不到核心[^4]。 - **解决方案**: - 确认BOOT引脚状态:STM32 Cortex-M0系列通常需设置$BOOT0 = 0$和$BOOT1 = 0$(或$BOOT1$悬空)以从主Flash启动(正常烧录模式)。参考您的芯片数据手册,使用跳线帽或万用表检查引脚电平。 - 调整BOOT模式: - 断开电源,将BOOT0引脚接地($BOOT0 = 0$),BOOT1引脚也接地或保持悬空。 - 重新上电并尝试烧录。如果成功,说明原配置错误。 - 启动模式错误是常见原因,尤其是在开发板设计或手动焊接时易忽略[^4]。 #### 步骤3: 解锁Flash或擦除芯片(处理保护状态) - **原因分析**:如果Flash被写保护(例如,之前烧录失败导致锁死),烧录工具无法访问核心,引发“找不到Cortex-M0”错误。类似问题在Cortex-M4芯片中也有报道[^3]。 - **解决方案**: - 使用ST-Link Utility解锁: - 下载并安装ST-Link Utility软件。 - 连接烧录器,打开软件,进入`Target` > `Connect`。 - 如果连接失败,选择`Target` > `Erase Chip`进行全片擦除(这会移除保护)。 - 成功后,重新烧录程序。此方法在引用中针对Flash锁死问题有效[^3]。 - 替代工具:如果ST-Link Utility无效,使用J-Flash(针对J-Link烧录器)执行擦除操作。步骤类似:连接后选择`Erase Chip`。 - 注意:擦除操作会清除芯片所有数据,确保备份重要内容。 #### 步骤4: 验证软件配置和设备选择(排除工具错误) - **原因分析**:烧录软件中设备型号选择错误(如误选Cortex-M3而非M0),或调试接口设置不当,会导致核心识别失败。 - **解决方案**: - 在Keil uVision中: - 打开项目,进入`Options for Target` > `Debug`选项卡。 - 确保调试器类型(如ST-Link)正确,并在`Settings`中选择`SWD`接口(而非JTAG)。 - 在`Device`选项卡中,确认芯片型号匹配您的STM32(如STM32F0系列针对Cortex-M0)。 -STM32CubeProgrammer中: - 连接后,检查`Target`菜单下的核心类型是否为`Cortex-M0`。 - 如果型号不匹配,重新安装设备支持包(如STM32F0xx_DFP)。 - 更新工具和驱动:确保烧录软件、固件和USB驱动为最新版本(从ST官网下载)。 #### 步骤5: 其他建议和高级排查 - **复位电路检查**:某些STM32开发板的复位引脚(NRST)需要外部上拉电阻。如果缺失,添加一个10kΩ电阻到$V_{CC}$。 - **BootLoader修复**:如果以上步骤无效,考虑烧录新的BootLoader(如使用USB DFU模式)。引用中提到通过Arduino bootloader实现USB烧录,但需注意兼容性[^2]。 - **芯片损坏测试**:如果所有步骤失败,芯片可能物理损坏。替换新芯片测试。 - **参考文档**:查阅STM32官方参考手册(RM系列),特别是调试和启动章节。整个过程体现了STM32启动机制的重要性[^1]。 通过以上步骤,大多数“找不到Cortex-M0”问题可解决。核心是:优先硬件连接和启动模式,再处理Flash保护,最后优化软件。如果您提供更多细节(如具体芯片型号和烧录工具),我可给出更针对性建议。 ### 相关问题 1. 如何正确设置STM32的BOOT引脚以实现不同启动模式? 2. STM32 Flash被锁后,除了擦除还有其他解锁方法吗? 3. Cortex-M0和Cortex-M4在烧录程序时有哪些常见区别? 4. 如何使用USB接口直接烧录STM32程序而无需额外烧录器? 5. STM32远程烧录程序的基本步骤和注意事项是什么? [^1]: STM32远程烧录程序。至此,STM32成功实现了远程烧录,这其中主要知识点就是STM32的启动机制、BootLoader程序、ESP8266基本的AT指令使用,和部分外设(串口、按键、FSMC驱动TFT LCD)等......,我自己去研究这个远程烧录的时候,也学了很多东西,因为遇到了不少bug,但是遇到一个问题就去解决一个问题,我们就能不断的进步。 [^2]: STM32 如何通过 USB 烧录程序。在前面的文章中,我们介绍了使用“Arduino IDE + FTDI”对STM32F103C8开发板进行了编程使板载LED闪烁。但它有一个小小的缺点,需要对其烧录时,我们需要使用FTDI模块,并且在烧录和测试代码时还必须在跳线0和1之间来回切换,有点麻烦。开发板上的mini-USB端口也完全未使用。而我们把USB插上电脑时,是识别不到该板的,因为它没有Arduinobootloader。接下来我们就把Arduino bootloader烧写进STM32F103C8,实现USB烧录程序。目前尚不知道这种方式会不会出现不可预知的bug,不建议用于关键应用程序。 所需材料。 [^3]: STM32芯片flash被锁导致Error Flash Download failed Cortex-M4,解决办法(全)亲测有效。方法3转载Keil : Error-Flash Download failed Cortex-M4错误解决方案整理(J-Flash擦除下载教程)_keil flash download_白浪博客的博客-优快云博客。 [^4]: STM32烧录程序方式。一、启动模式(Boot modes) 阅读:STM32中文参考手册_V10.pdf 查看启动配置(Boot modes)。 在STM32F10xxx里,可以通过BOOT[1:0]引脚选择三种不同启动模式。。。 ```
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值