一种基于STM32F4的字库及图片下载方法

一 、概述

目前,越来越多的应用需要扩展外部的Flash来满足存储需求,在调试及批量生产的过程中,需要对外扩的Flash进行烧录操作。在之前的学习中,一直用外部SPI Flash存放字库文件,之前的数据下载方法是用SD卡拷贝到SPIFLASH中,一直觉得在开发板上学习还算方便,如果在项目中应用,不是很方便,偶然机会,发现ST官方工具STM32 ST-LINK Utility支持对外部SPIFLASH直接进行读写。前几天介绍了在原子精英板上,用STM32 ST-LINK实现中文字库、图片下载的方法。

本文中介绍基于STM32F4系列的外挂SpiFlash烧录方法。

二、硬件平台

原子阿波罗开发板(SPIFLASH芯片信号W25Q128),单片机STM32F429。

三、代码解析

  1. 工程创建

该工程比较特殊,无main函数,其中system_stm32f4xx.c和大家熟悉的工程文件相同,BSP_sFLASH.c文件为外挂Flash的驱动程序,主要完成外挂Flash的初始化、读、写、擦除等操作。针对不同的Flash型号完成Loader文件夹下Dev_Info.c和Loader_Src.c文件编写。

一种基于STM32F4的字库及图片下载方法_第1张图片
  1. DevInfo.c文件

Dev_Info.c中声明了结构体StorageInfo,包含ST-LINK Utility编程及擦除芯片的信息。代码如下:

/*
* W25Q256
* 4Kbytes为1个Sector
* 16个扇区为1个Block
* 容量为32M字节
*/
struct StorageInfo const StorageInfo  =  {

   "W25Q256_REG",                 // FLASH 名称
   SPI_FLASH,                      // FLASH类型
   0x00000000,                    // FLASH 起始地址
   0x02000000,                     // FLASH 大小,单位字节
   256,                         // page大小    
   0xFF,                           // 擦除FLASH后,FLASH中的默认数据
// Specify Size and Address of Sectors (view example below) 
   4096, 0,                     // Sector大小: 4KBytes    
   SECTOR_END                    // SECTOR_END
};
  1. Loader_Src.c文件

提供ST-LINKUtility的External Loader功能所需要的函数,主要代码如下:

  • 首先需完成STM32时钟初始化,外挂Flash初始化。

int Init (void)
{  
    SystemInit();   //初始化时钟
    Stm32_Clock_Init(360,25,2,8);//设置时钟,180Mhz
    sFLASH_Init();    //初始化sFLASH,如W25Q128等
    return 1;
}
  • 按如下格式声明外挂Flash的读函数。

int Read (uint32_t Address, uint32_t Size, uint8_t* buffer)
{ 
    sFLASH_ReadBuffer(buffer, Address, Size);    
    return 1;
}
  • 按如下格式声明外挂Flash的写函数。

int Write (uint32_t Address, uint32_t Size, uint8_t* buffer)
{
    sFLASH_WriteBuffer(buffer, Address, Size);
    return 1;
}
  • 按如下格式声明外挂Flash的芯片擦除函数。

int MassErase (void)
{  
    sFLASH_EraseBulk();
    return 1;    
}
  • 按如下格式声明外挂Flash的扇区擦除函数。

int SectorErase (uint32_t EraseStartAddress ,uint32_t EraseEndAddress)
{      
    EraseStartAddress = EraseStartAddress -  EraseStartAddress%0x10000;
    while (EraseEndAddress>=EraseStartAddress)
    {
     sFLASH_EraseSector(EraseStartAddress);
     EraseStartAddress += 0x10000;
    }
     return 1;    
}
  • 编写校验函数如下:

uint32_t CheckSum(uint32_t StartAddress, uint32_t Size, uint32_t InitVal)
{
  uint8_t missalignementAddress = StartAddress%4;
  uint8_t missalignementSize = Size ;
  int cnt;
  uint32_t Val;
  uint8_t value;
    
  StartAddress-=StartAddress%4;
  Size += (Size%4==0)?0:4-(Size%4);
  
  for(cnt=0; cnt>8 & 0xff);
          InitVal += (uint8_t) (Val>>16 & 0xff);
          InitVal += (uint8_t) (Val>>24 & 0xff);
          missalignementAddress-=1;
          break;
        case 2:
          InitVal += (uint8_t) (Val>>16 & 0xff);
          InitVal += (uint8_t) (Val>>24 & 0xff);
          missalignementAddress-=2;
          break;
        case 3:   
          InitVal += (uint8_t) (Val>>24 & 0xff);
          missalignementAddress-=3;
          break;
      }  
    }
    else if((Size-missalignementSize)%4 && (Size-cnt) <=4)
    {
      switch (Size-missalignementSize)
      {
        case 1:
          InitVal += (uint8_t) Val;
          InitVal += (uint8_t) (Val>>8 & 0xff);
          InitVal += (uint8_t) (Val>>16 & 0xff);
          missalignementSize-=1;
          break;
        case 2:
          InitVal += (uint8_t) Val;
          InitVal += (uint8_t) (Val>>8 & 0xff);
          missalignementSize-=2;
          break;
        case 3:   
          InitVal += (uint8_t) Val;
          missalignementSize-=3;
          break;
      } 
    }
    else
    {
      InitVal += (uint8_t) Val;
      InitVal += (uint8_t) (Val>>8 & 0xff);
      InitVal += (uint8_t) (Val>>16 & 0xff);
      InitVal += (uint8_t) (Val>>24 & 0xff);
    }
    StartAddress+=4;
  } 
  return (InitVal);
}
  • 更新函数如下:

int Verify (uint32_t MemoryAddr, uint32_t RAMBufferAddr, uint32_t Size)
{ 
        uint32_t VerifiedData = 0;
        uint8_t TmpBuffer = 0x00;
        Size*=4;
        
        while (Size>VerifiedData)
        {
          sFLASH_ReadBuffer(&TmpBuffer, MemoryAddr+VerifiedData, 1);
          
          if (TmpBuffer != *((uint8_t*)RAMBufferAddr+VerifiedData))
            return MemoryAddr+VerifiedData;
          
          VerifiedData++;  
        }
        
        return 0;
}
  1. 生成文件

在user中的Run#1中输入cmd.exe /C copy "!L""..\..\..\@L.stldr",如下图,编译后生成一个.stldr的文件。将该文件拷贝到:STM32 ST-LINK Utility v4.2.0 setup.exe安装目录\STM32ST-LINK Utility\ST-LINK Utility\ExternalLoader文件夹下。

一种基于STM32F4的字库及图片下载方法_第2张图片

四、效果展示

打开软件STM32 ST-LINK Utility->External Loader->Add ExteranlLoader->勾选相应文件(如图)->Validate

一种基于STM32F4的字库及图片下载方法_第3张图片

擦除外部FLASH。ExternalLoader->W25Q256_REG->Mass Erase。

一种基于STM32F4的字库及图片下载方法_第4张图片
一种基于STM32F4的字库及图片下载方法_第5张图片

下载字库、图片或其他文件到外部FLASH

一种基于STM32F4的字库及图片下载方法_第6张图片
一种基于STM32F4的字库及图片下载方法_第7张图片

等待下载结束,耗时约2分钟,显示Verification…OK,下载成功。

五、代码下载

代码地址:一种基于STM32F4的字库及图片下载工程源码

打字不易,点波关注,评论区留下邮箱,作者无偿提供源码和问题解答。

你可能感兴趣的:(STM32进阶,stm32,嵌入式硬件)