STM32H743 W25Q128 Keil烧录算法的制作、内存映射代码、分散加载文件源码分享

一、W25Q128烧录算法的制作

1、前言

最近做项目用到STM32H743这款芯片,其内部FLash有2M,但是项目中用到touchgfx,如果资源放到内部Flash中会造成两个问题,一是图片过多会导致内部Flash不够用,二是每次修改一下程序都要下载整个Flash,下载时间过长。所以想到用外部QSPI接口的Flash专门存放图片等资源文件。

2、创建下载算法工程

a、工程搭建

如果你电脑已经安装Keil,那么可以在以下目录找到官方的工程模板:{Keil安装录}\ARM\PACK\ARM\CMSIS\5.3.0\Device\_Template_Flash
将这些全部复制到新文件夹,再将相关的芯片驱动库复制进去,之后打开工程如果打开之后提示:
在这里插入图片描述
需要将工程模板的文件选择、然后右键进属性选项,把只读选项去掉,再重新打开即可。

在这里插入图片描述

b、文件添加

需要将qspi和w25qxx的驱动文件添加进来。
在这里插入图片描述
之后点编译如果遇到以下问题:

\xxx.axf: Error: L6265E: Non-PI Section xxxxxxxxx.o(.data) cannot be assigned to PI Exec region PrgData.

暂时不用管

b、算法实现

先根据片外FLASH芯片调整参数,在FlashDev.c文件里头的结构体:
在这里插入图片描述
具体解释如下:

struct FlashDevice const FlashDevice  =  {
    
    
   FLASH_DRV_VERS,                                  // 驱动版本 不需要修改!
   "XP_H743_W25Q128",              // 下载算法名称(Keil里显示)
   EXTSPI,                                          // 设备类型:片外FLASH
   0x90000000,                                      // 片外FLASH地址
   0x1000000,                                  // 片外FLASH大小(32MB)
   4096,                                            // 页大小(一次写入的数据大小,这边W25Q32页大小是256,为了写入快点这边设置1024)
   0,                                               // 保留位,必须是0
   0xFF,                                            // 擦除后数据值
   1000,                                            // 页写入超时时间(1S)
   3000,                                            // 扇区擦除超时时间(6S)
 
   0x001000, 0x000000,                              // 扇区大小:4KB 地址:0x000000
   SECTOR_END
};

之后实现FlashPrg.c里的相关函数:

/* -----------------------------------------------------------------------------
 * Copyright (c) 2016 ARM Ltd.
 *
 * This software is provided 'as-is', without any express or implied warranty.
 * In no event will the authors be held liable for any damages arising from
 * the use of this software. Permission is granted to anyone to use this
 * software for any purpose, including commercial applications, and to alter
 * it and redistribute it freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software in
 *    a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source distribution.
 *
 *
 * $Date:        10. October 2018
 * $Revision:    V1.0.0
 *
 * Project:      Flash Device Description for
 *               STM32H743 W25Q256 SPIFI Flash
 * --------------------------------------------------------------------------- */

#include "..\FlashOS.H"        // FlashOS Structures
#include "sys.h"
#include "W25QXX.h"
#include "qspi.h"


#define PAGE_SIZE            4096

/*
 *  Initialize Flash Programming Functions
 *    Parameter:      adr:  Device Base Address
 *                    clk:  Clock Frequency (Hz)
 *                    fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
 *    Return Value:   0 - OK,  1 - Failed
 */
 
uint8_t aux_buf[PAGE_SIZE];
uint32_t base_adr;

//这个函数在keil下载后,在擦除、编程都会重新调用一次此函数,而且在调用此函数之前keil会复位单片机,相当于单片机跑起来的初始化功能要在擦除、编程时都要初始化一遍
int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {
    
    

	Stm32_Clock_Init(160,5,2,4);	//设置时钟,400Mhz
	W25QXX_Init();				//初始化NORFLASH
	base_adr = adr;
	
  return (0);
}


/*
 *  De-Initialize Flash Programming Functions
 *    Parameter:      fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
 *    Return Value:   0 - OK,  1 - Failed
 */

int UnInit (unsigned long fnc) {
    
    

  return (0);
}


/*
 *  Erase complete Flash Memory
 *    Return Value:   0 - OK,  1 - Failed
 */

int EraseChip (void) {
    
    

  W25QXX_Erase_Chip();
  return (0);                                        /* Finished without Errors */
}


/*
 *    Erase Sector in Flash Memory
 *    Parameter:      adr:  Sector Address
 *    Return Value:   0 - OK,  1 - Failed
 */

int EraseSector (unsigned long adr) {
    
    

	W25QXX_Erase_Sector(adr-base_adr);
  return (0);                                        /* Finished without Errors */
}


/*
 *  Blank Check Checks if Memory is Blank
 *    Parameter:      adr:  Block Start Address
 *                    sz:   Block Size (in bytes)
 *                    pat:  Block Pattern
 *    Return Value:   0 - OK,  1 - Failed
 */

int BlankCheck (unsigned long adr, unsigned long sz, unsigned char pat) {
    
    

  return (1);                                        /* Always Force Erase */
}


/*
 *  Program Page in Flash Memory
 *    Parameter:      adr:  Page Start Address
 *                    sz:   Page Size
 *                    buf:  Page Data
 *    Return Value:   0 - OK,  1 - Failed
 */

int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) {
    
    
	
	W25QXX_Write_NoCheck(buf,adr-base_adr,sz);
  return (0);                                        /* Finished without Errors */
}


/*  
 *  Verify Flash Contents
 *    Parameter:      adr:  Start Address
 *                    sz:   Size (in bytes)
 *                    buf:  Data
 *    Return Value:   (adr+sz) - OK, Failed Address
 */

/*
   Verify function is obsolete because all other function leave 
    the SPIFI in memory mode so a memory compare could be used.
 */
unsigned long Verify (unsigned long adr, unsigned long sz, unsigned char *buf) {
    
    

  int i;
  W25QXX_Read(aux_buf, adr-base_adr, sz);
  for (i = 0; i< sz; i++) 
	{
    
    
    if (aux_buf[i] != buf[i]) 
      return (adr+i);                   // Verification Failed (return address)
  }
  return (adr+sz);                      // Done successfully
}

d、工程设置

输出名称设置
在这里插入图片描述
设置算法与地址无关,因为下载算法是加载到ram中运行的
在这里插入图片描述
汇编设置如上

在这里插入图片描述
链接器设置
在这里插入图片描述
Target.lin文件中填入如下内容:

; Linker Control File (scatter-loading)
;

PRG 0 PI               ; Programming Functions
{
    
    
  PrgCode +0           ; Code
  {
    
    
    * (+RO)
  }
  PrgData +0           ; Data
  {
    
    
    * (+RW,+ZI)
  }
}

DSCR +0                ; Device Description
{
    
    
  DevDscr +0
  {
    
    
    FlashDev.o
  }
}

在这里插入图片描述
格式如下:

cmd.exe /C copy "!L" "..\@L.FLM"

编译生成烧录文件,后缀格式为FLM。

扫描二维码关注公众号,回复: 15962777 查看本文章

3、下载算法的使用

将生成的XXXX.FLM文件复制到keil下载算法目录:
路径:{Keil安装目录}\ARM\Flash
之后就可以在配置界面看到了
在这里插入图片描述

二、内存映射代码编写

void QSPI_Enable_Memmapmode(void)
{
    
    
	unsigned int tempreg=0; 
	volatile unsigned int *data_reg=&QUADSPI->DR;
	GPIO_InitTypeDef qspi_gpio;
	
	
	RCC->AHB4ENR|=1<<1;    						//使能PORTB时钟	   
	RCC->AHB4ENR|=1<<5;    						//使能PORTF时钟	   
	RCC->AHB3ENR|=1<<14;   						//QSPI时钟使能

	qspi_gpio.Pin=GPIO_PIN_6;					//PB6 AF10	
	qspi_gpio.Mode=GPIO_MODE_AF_PP;
	qspi_gpio.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
	qspi_gpio.Pull=GPIO_NOPULL;
	qspi_gpio.Alternate=GPIO_AF10_QUADSPI;
	HAL_GPIO_Init(GPIOB,&qspi_gpio);
	
	qspi_gpio.Pin=GPIO_PIN_2;					//PB2 AF9	
	qspi_gpio.Alternate=GPIO_AF9_QUADSPI;
	HAL_GPIO_Init(GPIOB,&qspi_gpio);
	
	qspi_gpio.Pin=GPIO_PIN_6|GPIO_PIN_7;		//PF6,7 AF9	
	qspi_gpio.Alternate=GPIO_AF9_QUADSPI;
	HAL_GPIO_Init(GPIOF,&qspi_gpio);
	
	qspi_gpio.Pin=GPIO_PIN_8|GPIO_PIN_9;		//PF8,9 AF10		
	qspi_gpio.Alternate=GPIO_AF10_QUADSPI;
	HAL_GPIO_Init(GPIOF,&qspi_gpio);
	
	//QSPI设置,参考QSPI实验的QSPI_Init函数
	RCC->AHB3RSTR|=1<<14;			//复位QSPI
	RCC->AHB3RSTR&=~(1<<14);		//停止复位QSPI
	while(QUADSPI->SR&(1<<5));		//等待BUSY位清零 
	QUADSPI->CR=0X01000310;			//设置CR寄存器,这些值怎么来的,请参考QSPI实验/看H750参考手册寄存器描述分析
	QUADSPI->DCR=0X00160401;		//设置DCR寄存器
	QUADSPI->CR|=1<<0;				//使能QSPI 

	//注意:QSPI QE位的使能,在QSPI烧写算法里面,就已经设置了
	//所以,这里可以不用设置QE位,否则需要加入对QE位置1的代码
	//不过,代码必须通过仿真器下载,直接烧录到外部QSPI FLASH,是不可用的
	//如果想直接烧录到外部QSPI FLASH也可以用,则需要在这里添加QE位置1的代码
	
	//W25QXX进入QPI模式(0X38指令)
	while(QUADSPI->SR&(1<<5));		//等待BUSY位清零 
	QUADSPI->CCR=0X00000138;		//发送0X38指令,W25QXX进入QPI模式
	while((QUADSPI->SR&(1<<1))==0);	//等待指令发送完成
	QUADSPI->FCR|=1<<1;				//清除发送完成标志位 	

	//W25QXX写使能(0X06指令)
	while(QUADSPI->SR&(1<<5));		//等待BUSY位清零 
	QUADSPI->CCR=0X00000106;		//发送0X06指令,W25QXX写使能
	while((QUADSPI->SR&(1<<1))==0);	//等待指令发送完成
	QUADSPI->FCR|=1<<1;				//清除发送完成标志位 
	
	//W25QXX设置QPI相关读参数(0XC0)
	while(QUADSPI->SR&(1<<5));		//等待BUSY位清零 
	QUADSPI->CCR=0X030003C0;		//发送0XC0指令,W25QXX读参数设置
	QUADSPI->DLR=0;
	while((QUADSPI->SR&(1<<2))==0);	//等待FTF
	*(unsigned char *)data_reg=3<<4;			//设置P4&P5=11,8个dummy clocks,104M
	QUADSPI->CR|=1<<2;				//终止传输 
	while((QUADSPI->SR&(1<<1))==0);	//等待数据发送完成
	QUADSPI->FCR|=1<<1;				//清除发送完成标志位  
	while(QUADSPI->SR&(1<<5));		//等待BUSY位清零 	 

	//MemroyMap 模式设置
	while(QUADSPI->SR&(1<<5));		//等待BUSY位清零 
	QUADSPI->ABR=0;					//交替字节设置为0,实际上就是W25Q 0XEB指令的,M0~M7=0
	tempreg=0XEB;					//INSTRUCTION[7:0]=0XEB,发送0XEB指令(Fast Read QUAD I/O)
	tempreg|=3<<8;					//IMODE[1:0]=3,四线传输指令
	tempreg|=3<<10;					//ADDRESS[1:0]=3,四线传输地址
	tempreg|=2<<12;					//ADSIZE[1:0]=2,24位地址长度
	tempreg|=3<<14;					//ABMODE[1:0]=3,四线传输交替字节
	tempreg|=0<<16;					//ABSIZE[1:0]=0,8位交替字节(M0~M7)
	tempreg|=6<<18;					//DCYC[4:0]=6,6个dummy周期
	tempreg|=3<<24;					//DMODE[1:0]=3,四线传输数据
	tempreg|=3<<26;					//FMODE[1:0]=3,内存映射模式
	QUADSPI->CCR=tempreg;			//设置CCR寄存器
	
	//设置QSPI FLASH空间的MPU保护
	SCB->SHCSR&=~(1<<16);			//禁止MemManage 
	MPU->CTRL&=~(1<<0);				//禁止MPU
	MPU->RNR=0;						//设置保护区域编号为0(1~7可以给其他内存用)
	MPU->RBAR=0X90000000;			//基地址为0X9000 000,即QSPI的起始地址
	MPU->RASR=0X0303002D;			//设置相关保护参数(禁止共用,允许cache,允许缓冲),详见MPU实验的解析
	MPU->CTRL=(1<<2)|(1<<0);		//使能PRIVDEFENA,使能MPU 
	SCB->SHCSR|=1<<16;				//使能MemManage
}

三、分散加载文件编写

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************


LR_IROM1 0x08000000 0x00180000  {
    
        ; load region size_region
  ER_IROM1 0x08000000 0x00180000  {
    
      ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   * (Veneer$$Code)
	.ANY (+RO)
	.ANY (+XO)
  }
  RW_IRAM1 0x24000000 0x00080000  {
    
      ; RW data
   .ANY (+RW +ZI)
  }
}

LR_QSPI 0X90000000 0X1000000 {
    
    
	ER_QSPI 0X90000000 0X1000000 {
    
    
	*.o (ExtFlashSection)
	}
}

0X90000000 就是外部FLASH加载地址

四、源码分享

点击我下载

猜你喜欢

转载自blog.csdn.net/qq_15181569/article/details/131767270
今日推荐