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

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

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

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

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

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

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

STM32F0 使用ST-LINK实现对外部Flash芯片的烧录_第1张图片

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

STM32F0 使用ST-LINK实现对外部Flash芯片的烧录_第2张图片

 

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

STM32F0 使用ST-LINK实现对外部Flash芯片的烧录_第3张图片

下一步就是调整硬件对应的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 就会自动出现这个选择,见下图:

STM32F0 使用ST-LINK实现对外部Flash芯片的烧录_第4张图片

 点击Validate就可以验证了。

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

STM32F0 使用ST-LINK实现对外部Flash芯片的烧录_第5张图片

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

STM32F0 使用ST-LINK实现对外部Flash芯片的烧录_第6张图片

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

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

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

你可能感兴趣的:(随笔,stm32,单片机,arm)