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

news2024/11/28 20:59:20

一、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。

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加载地址

四、源码分享

点击我下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/763711.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文了解近端边缘 IT 基础架构技术需求

随着边缘计算相关技术的逐渐成熟&#xff0c;边缘应用的种类也呈现多样化发展。IDC 2023 年发布的《全球边缘支出指南》归纳出 400 多种跟边缘相关的应用——这是在从 9 个地理区域、17 个技术市场、6 个技术领域和 19 个行业当中汇总出来的。 边缘计算的复杂和边缘应用的多样…

Leetcode-每日一题【24.两两交换链表中的节点】

题目 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4]输出&#xff1a;[…

【玩转Linux操作】详细讲解 Linux分区磁盘 操作以及相关的命令

&#x1f38a;专栏【玩转Linux操作】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【Counting Stars 】 欢迎并且感谢大家指出小吉的问题&#x1f970; 文章目录 &#x1f354;什么是Linux的分区&#x1f354;Linux分区的作用&a…

没有代码基础如何学习自动化测试

因为最近在群里有一些同学&#xff0c;之前没做过自动化测试&#xff0c;但是限于领导要求&#xff0c;或者自己想提升了&#xff0c;开始研究自动化测试&#xff0c;最近记忆比较深的低级的几个问题是&#xff1a; 1、编写一个python的类将 __init__写成_init_苦于问题一直解…

springboot项目使用mybatis-plus启动报错

在使用最新的mybatis-plus的时候&#xff0c;遇到一个报错 org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name payMentController: Unsatisfied dependency expressed through field payMentService; nested exception is…

mybatis-plus代码生成器使用指南

mybatis-plus代码生成器 官网&#xff1a;mp代码生成器&#xff08;新&#xff09; 1、导入依赖 使用最新版本&#xff1a;3.5.3.1版本&#xff0c;老版本不兼容 <properties><mybatis-plus.version>3.5.3.1</mybatis-plus.version><freemarker.versio…

集成VCO-Cadence ADE相位噪声分析

集成VCO-Cadence ADE相位噪声分析 简介环境软件工艺 参考振荡器原理图相位噪声说明pss设置1234 pnoise设置12345 结果 简介 本文主要是使用Cadence ADE仿真1GHz交叉耦合振荡器&#xff0c;得到相位噪声曲线&#xff0c;主要记录仿真设置过程&#xff0c;仅供参考&#xff0c;如…

零拷贝技术(DMA、MMAP、sendfile)

零拷贝mmap、sendfile 定义 零拷贝技术主要是解决传统网络I/O操作中发送文件的性能问题&#xff1a;如下图表示一次read和write时传统I/O涉及到的CPU操作&#xff1a; 涉及到4次用户态↔内核态上下文切换&#xff0c;其中read切换两次、write切换两次&#xff1b;涉及到4次数…

IntelliJ IDEA 忽略Git提交

在项目下新建 .gitignore 文件 在 .gitignore 文件写入以下内容&#xff0c;从上图可以看到&#xff0c;忽略提交的这些目录/文件变成了黄色

P2372 yyy2015c01挑战算周长

yyy2015c01挑战算周长 题目背景 yyy2015c01 快速的解决了问题&#xff0c;受到邻居们的赞许&#xff0c;高兴的回到家&#xff0c;把糖给了妈妈&#xff0c;吃了香喷喷的午饭&#xff0c;又睡了一个甜甜的午觉&#xff0c;感觉人生真美好。下午爸爸回到家&#xff0c;听说了 …

设计模式 ~ 单例模式

单例模式 单例模式是一种设计模式&#xff0c;指在确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例&#xff1b; 前端对于单例模式不常用&#xff0c;但是单例的思想无处不在&#xff1b; 创建之后缓存以便继续使用&#xff1b; 如&#xff1a;弹窗、遮罩…

HCIP——HCIA回顾及静态实验

HCIP HCIA一、知识回顾1、OSI七层参考模型&#xff1a;2、重要的几个协议报头格式 二、静态实验1、实验拓扑图2、实验要求3、实验思路4、实验步骤1、给接口划分IP地址以及配置环回地址2、交换机配置划分VLAN3、配置静态路由4、配置DHCP服务5、测试6、优化 HCIA 1、七层参考模型…

遭黑客攻击后反而涨了千百倍?

近期&#xff0c;遭遇黑客攻击后的某数字藏品平台悄悄“复活”&#xff0c;引发业界关注。复出后&#xff0c;该平台上的数字藏品持续暴涨&#xff0c;大部分涨幅均超过百倍&#xff0c;少数藏品甚至超过了千倍。事出反常必有妖。这波涨势难免令人怀疑其中是否存在投机炒作行为…

常用API学习05(Java)

Runtime Runtime表示当前虚拟机的运行环境&#xff0c;Runtime的方法我们不能自己直接去new。 public static Runtime getRuntime() 当前系统的运行环境对象 public void exit(int status) 停止虚拟机 public int availableProcessors() 获得cpu的线程数 publ…

UEC++:间接属性引用

1. 优点&#xff1a;优化内存和时间加载问题&#xff1b; 2. 实现&#xff1a;4.18之前使用的是FStringAssetReference&#xff1a; 所有资源文件都能拾取&#xff01;&#xff01;&#xff01; 结果&#xff1a; 3. 实现&#xff1a; 设置音频文件&#xff1a;

ping的工作原理

ICMP包头格式&#xff1a; icmp报文封装在IP包内&#xff0c;工作在网络层&#xff0c;是IP协议帮手。 查询报文类型 可向对端主机发送回送请求的消息&#xff08;类型 8&#xff09;也可接收对端主机发回来的回送应答消息&#xff08;类型 0&#xff09; 查询报文又增添了标…

怎么通过UI自动化方式获取文章信息?

出于学习研究&#xff0c;对某账号的文章、视频分析一翻&#xff0c;尝试使用自动化方式看能否获取相应信息。 获取某号的文章有多重方法&#xff1a; 第一种是通过搜狗浏览器搜索账号&#xff08;这种方式每天只能获取一篇文章&#xff0c;基本上没啥用。&#xff09;&#…

手把手教你写通讯录(含动态版)

目录 一、框架 二、实现 1.初始化通讯录 2.增加联系人 3.打印通讯录 4.删除联系人 5.修改联系人 6.查找联系人 7.退出通讯录 8.拓展&#xff1a;通讯录排序 9.全代码 三、动态版 1.结构体修改 2.初始化修改 3.扩容实现 4.善后函数 5.全代码 一、框架 实现通讯录…

IntelliJ IDEA 版本控制

IntelliJ IDEA 版本控制&#xff08;VCS&#xff09;日常使用方法备忘 1、搁置更改 2、移至另一个更改列表 对于工程项目中的配置文件&#xff0c;已经在本地修改但是不能提交&#xff0c;如果在提交项目代码时全选变更的文件&#xff0c;可能会误提交配置文件&#xff0c;此…

语音芯片播放消耗电流过大,导致MCU复位

1、问题 在多次遇到播放声音时突然黑屏&#xff0c;单片机复位或者语音播放不全现象&#xff0c;之前使用示波器测量播放声音时供电电池电压&#xff0c;电池电压的确被拉低。之前的解决方案是使用南孚电池&#xff0c;先把供电电压给高一些&#xff0c;这样即使把电压拉低&am…