STM32H7使用QSPI外扩flash(linux下使用openocd操作)

这篇具有很好参考价值的文章主要介绍了STM32H7使用QSPI外扩flash(linux下使用openocd操作)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

根据安福莱的STM32H7教程,H7单片机的QSPI外设是直接连到芯片内核上的,地址是0X90000000;那么就可以通过QSPI外设,将外置flash内存映射,并由此执行代码。

stm32 qspi flash,stm32,linux
相关操作在keil5上比较简单,配置点东西就行;可以参考安福莱教程。

这里要介绍的是在linux环境下没有keil5 IDE的情况下,如何使用clion+openocd实现

  • 将大体积代码下载到外置flash并执行
  • 对外置flash执行的代码进行仿真

代码配置

修改系统配置文件

STM32的代码都是有起始地址的,每一句代码,编译为相关机器码执行时,都有对应地址的;对于一般情况的代码,起始地址都是0X8000000;

stm32 qspi flash,stm32,linux
该文件中详细的配置了单片机所使用的flash大小,ram大小,地址等信息。

由于采用外置flash启动,我们需要将flash地址配置为QSPI地址,并修改LENGTH为我们的flash芯片大小。

MEMORY
{
  FLASH (rx)     : ORIGIN = 0x90000000, LENGTH = 8192K
  DTCMRAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 128K
  RAM_D1 (xrw)   : ORIGIN = 0x24000000, LENGTH = 512K
  RAM_D2 (xrw)   : ORIGIN = 0x30000000, LENGTH = 288K
  RAM_D3 (xrw)   : ORIGIN = 0x38000000, LENGTH = 64K
  ITCMRAM (xrw)  : ORIGIN = 0x00000000, LENGTH = 64K
}

修改系统初始化函数

STM32单片机启动时会先执行汇编启动文件,先定义中断向量表,再执行复位,设置栈顶指针,再执行系统初始化函数,再跳转main函数。

其中系统初始化函数中需要修改SCB->VTOR的值。
SCB->VTOR为Cortex内核的中断向量表的基地址,一般为程序执行的初始地址。 #12AA9C
关于该变量理解,参考链接

这里需要修改为我们程序启动的地址0X90000000。
stm32 qspi flash,stm32,linux

编译

点击编译,即可制作一个运行在外部flash的代码,下载到外置flash中,引导运行即可。

那么现在出现两个问题:

  • 如何下载到外置flash
  • 如何从外置flash中启动

代码下载

使用CubeProgramer工具下载

使用ST提供的下载工具下载;
需要:

  • 对应板子的下载算法文件
  • 烧录器
  • 能够运行在外置flash的代码

刚才已经成功编译了外置执行代码,烧录器咱也有,而烧录算法呢,推荐看安福莱的相关教程。
相关教程

使用Clion下载

这个是我主要想讲的,在一个编辑器里完成编译、下载、调试,嘿嘿

先解决下载问题。

我们知道,STM32下载代码时会先执行一个配置程序,该程序运行在RAM中,会初始化部分关于下载代码的外设。

使用keil5时,我们会使用一个.flm文件下载代码,该文件就是下载引导程序,其制作流程安福莱里讲的有。

stm32 qspi flash,stm32,linux

同样,在正常下载的时候也会有一个keil5官方提供的.flm文件,这些文件就储存在官方目录里。

对于CubeMX而言,也有相应的文件,

所以,我们使用的openocd工具也是有的,在我们的工程目录里,有一些配置文件,都具有各自相应的功能。

stm32 qspi flash,stm32,linux
在stm32h750b-disco.cfg文件中,初始化了芯片时钟,和部分必要的下载外设;

在19行、23行:跳转到了其他配置文件中,执行具体的操作

# enable stmqspi
if {![info exists QUADSPI]} {
	set QUADSPI 1
}

source [find target/stm32h7x.cfg]

reset_config srst_only

source [find board/stm32h7x_dual_qspi.cfg]

在这里,代码定义了QUADSPI为1,即会在stm32h7x_dual_qspi.cfg中执行该外设的初始化;

但是,这里该外设的初始化是以STM32官方出的板子的引脚定义的,不一定适合我们,而且实操下来,该文件改来改去效果不大,而且我觉得不建议跳到人家官方配置文件里修修改改,这里我们直接在该配置语句下面执行我们板子的配置代码;

# ART_Pi qspi.

# QUADSPI initialization
proc qspi_init {  } {
    global a
    mmw 0x580244E0 0x000007FF 0             ;# RCC_AHB4ENR |= GPIOAEN-GPIOKEN (enable clocks)
    mmw 0x580244D4 0x00004000 0             ;# RCC_AHB3ENR |= QSPIEN (enable clock)
    sleep 1                                 ;# Wait for clock startup

    # PF10:AF09:H, PF09:AF10:H, PF08:AF10:H, PF07:AF09:H, PF06:AF09:H, PG06:AF10:H

    # Port F: PF10:AF09:H, PF09:AF10:H, PF08:AF10:H, PF07:AF09:H, PF06:AF09:H
    mmw 0x58021400 0x002AA000 0x00155000    ;# MODER
    mmw 0x58021408 0x002AA000 0x00155000    ;# OSPEEDR
    mmw 0x5802140C 0x00000000 0x003FF000    ;# PUPDR
    mmw 0x58021420 0x99000000 0x66000000    ;# AFRL
    mmw 0x58021424 0x000009AA 0x00000655    ;# AFRH
    # Port G: PG06:AF10:H
    mmw 0x58021800 0x00002000 0x00001000    ;# MODER
    mmw 0x58021808 0x00002000 0x00001000    ;# OSPEEDR
    mmw 0x5802180C 0x00000000 0x00003000    ;# PUPDR
    mmw 0x58021820 0x0A000000 0x05000000    ;# AFRL

    # correct FSIZE is 0x16, however, this causes trouble when
    # reading the last bytes at end of bank in *memory mapped* mode

    # for single flash mode w25q64jv
                                            ;# 010101010000000000000 0 011000
    mww 0x52005000 0x05500018               ;# QUADSPI_CR: PRESCALER=5, APMS=1, FTHRES=1, FSEL=0, DFM=0, SSHIFT=1, TCEN=1
    mww 0x52005004 0x00160500               ;# QUADSPI_DCR: FSIZE=0x16, CSHT=0x05, CKMODE=0
                                            ;# FSIZE flash的大小。

    mww 0x52005030 0x00001000               ;# QUADSPI_LPTR: deactivate CS after 4096 clocks when FIFO is full
                                            ;# 11010000000000 10 010100000011
    mww 0x52005014 0x0D002503               ;# QUADSPI_CCR: FMODE=0x3, DMODE=0x1, DCYC=0x0, ADSIZE=0x2, ADMODE=0x1, IMODE=0x1
    mmw 0x52005000 0x00000001 0             ;# QUADSPI_CR: EN=1

    # Exit QPI mode
    #mmw 0x52005000 0x00000002 0            ;# QUADSPI_CR: ABORT=1
    #mww 0x52005014 0x000003F5              ;# QUADSPI_CCR: FMODE=0x0, DMODE=0x0, DCYC=0x0, ADSIZE=0x0, ADMODE=0x0, IMODE=0x3, INSTR=Exit QPI
    sleep 1

    # reset flash
    mmw 0x52005000 0x00000002 0             ;# QUADSPI_CR: ABORT=1
    mww 0x52005014 0x00000166               ;# QUADSPI_CCR: FMODE=0x0, DMODE=0x0, DCYC=0x0, ADSIZE=0x0, ADMODE=0x0, IMODE=0x1, INSTR=0x66
    mww 0x52005014 0x00000199               ;# QUADSPI_CCR: FMODE=0x0, DMODE=0x0, DCYC=0x0, ADSIZE=0x0, ADMODE=0x0, IMODE=0x1, INSTR=0x99

    # memory-mapped read mode with 3-byte addresses
    mmw 0x52005000 0x00000002 0             ;# QUADSPI_CR: ABORT=1
                                            ;# 11 11 0 00100 00 11 10 11 01 11101011
    mww 0x52005014 0x0F10EDEB               ;# QUADSPI_CCR: FMODE=0x3, DMODE=0x3, DCYC=0x4, ADSIZE=0x2, ADMODE=0x3, IMODE=0x1, INSTR=READ
    ;mww 0x52005014 0x0D002503
}

$_CHIPNAME.cpu0 configure -event reset-init {
    global QUADSPI

    mmw 0x52002000 0x00000004 0x0000000B    ;# FLASH_ACR: 4 WS for 192 MHZ HCLK

    mmw 0x58024400 0x00000001 0x00000018    ;# RCC_CR: HSIDIV=1, HSI on
    mmw 0x58024410 0x10000000 0xEE000007    ;# RCC_CFGR: MCO2=system, MCO2PRE=8, HSI as system clock
    mww 0x58024418 0x00000040               ;# RCC_D1CFGR: D1CPRE=1, D1PPRE=2, HPRE=1
    mww 0x5802441C 0x00000440               ;# RCC_D2CFGR: D2PPRE2=2, D2PPRE1=2
    mww 0x58024420 0x00000040               ;# RCC_D3CFGR: D3PPRE=2
    mww 0x58024428 0x00000040               ;# RCC_PPLCKSELR: DIVM3=0, DIVM2=0, DIVM1=4, PLLSRC=HSI
    mmw 0x5802442C 0x0001000C 0x00000002    ;# RCC_PLLCFGR: PLL1RGE=8MHz to 16MHz, PLL1VCOSEL=wide
    mww 0x58024430 0x01070217               ;# RCC_PLL1DIVR: 192 MHz: DIVR1=2, DIVQ=8, DIVP1=2, DIVN1=24
    mmw 0x58024400 0x01000000 0             ;# RCC_CR: PLL1ON=1
    sleep 1
    mmw 0x58024410 0x00000003 0             ;# RCC_CFGR: PLL1 as system clock
    sleep 1

    adapter speed 24000

    if { $QUADSPI } {
        qspi_init
    }
}

改代码中主要就初始化了QSPI外设的GPIO,并配置了QSPI外设,使用的板子是ART-Pi;

使用的GPIO是: PF10,PF09,PF08,PF07,PF06,PG06.

相关外设初始化主要时钟匹配自己的芯片速度。

这里主要参考链接:

在CLion上实现STM32H750VBT6的Bootloader

使用openOCD擦写ART_Pi外部qspi_flash

两个教程都很全面,并且将代码文件、配置文件都开源了,去点星星咯。

大家可以根据自己的板子的引脚定义进行修改相关寄存器即可。

到这里,基本完成了配置,可以实现在clion中通过openocd实现向单片机外置flash下载代码,并进行仿真调试了。

从外置flash中启动代码

不管上面如何下载代码,都需要从外置flash启动,前面也简略提到了——我们需要在单片机的内置flash中下载一个bootloader代码,用于从外置flash启动。

这个代码比较简单,就初始化一点点外设,主要还是QSPI,然后关闭Cache、MPU,对外置flash进行内存映射,并启动。具体内容可以参考安福莱教程。

硬汉嵌入式的bootloader教程

我的是修改的反客科技的bootloader代码,将其QSPI外设的引脚改成我的板子的就可以用了。是之前用keil5写的,也可以自己用cubemx生成一个,添加应用代码即可。比较简单。

适配ART-Pi的下载算法和bootloader

另外,从外置flash引导的代码,受flash限制,运行速度并不快,不如芯片内部的flash,对此,我们参考安福莱教程,使用MPU配置外置flash内存,用Cache预存取指令,提高代码运行速度。相关配置:
stm32 qspi flash,stm32,linux

  MPU_Region_InitTypeDef MPU_InitStruct = {0};

  /* Disables the MPU */
  HAL_MPU_Disable();

  /** Initializes and configures the Region and the memory to be protected
  */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER0;
  MPU_InitStruct.BaseAddress = 0x90000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_8MB;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  /* Enables the MPU */
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

MPU配置代码。

相关教程:

理论学习,详细好理解

硬汉哥的MPU教程

硬汉哥的实战教程,超级好用

添加

在clion使用openocd仿真的话,为了查看各个寄存器的值,需要添加寄存器配置文件,一般keil5安装目录里有,我把我的上传到Github上了,欢迎下载。

SVD文件

stm32 qspi flash,stm32,linux文章来源地址https://www.toymoban.com/news/detail-792246.html

到了这里,关于STM32H7使用QSPI外扩flash(linux下使用openocd操作)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32H7系列MCU的MPU和Cache功能介绍

    参考资料 :PM0253 STM32F7 Series and STM32H7 Series Cortex®-M7 processor programming manualV5.0 1.1 MPU 的作用 防止不受信任的应用程序访问受保护的内存区域; 防止用户应用程序破坏操作系统使用的数据;通过阻止任务访问其它任务的数据区;允许将内存区域定义为只读,以便保护重要数据;

    2024年02月01日
    浏览(41)
  • stm32h7中RTC的BCD模式与BIN模式

    BCD(Binary-Coded Decimal)和BIN(Binary)是两种不同的数字表示格式。 BCD格式: BCD是一种用二进制编码表示十进制数字的格式。在BCD格式中,每个十进制数位使用4位二进制数来表示,范围从0到9。例如,数字5在BCD格式中表示为0101,数字9表示为1001。这种编码方式使得BCD数值的每

    2024年01月23日
    浏览(45)
  • STM32 CubeMX 无法将 STM32H7 的最大 CPU 频率设置为 480 MHz

    使用stm32cubemx设置时钟树为480MHz时,提示 cpu clock frequency must be =200MHZ 对于STM32H7 需要CPU修订版 为 V 才能达到 480 MHz 的最大频率。 使用STM32Programmer查看芯片修订版,确认是V版本: 在STM32CubeMX PinConfiguration 界面修改RCC选项,将Product Version设置为V: 此时时钟树界面已可以设置48

    2024年02月16日
    浏览(50)
  • STM32H7 SDMMC+FATFS+USBMSC+FREERTOS 虚拟U盘

    通过cubemx配置 实现STM32H7 SDMMC+FATFS+USBMSC+FREERTOS 虚拟U盘 1.使用FAFTS文件操作系统,实现STM32虚拟U盘,读写外部SD卡,fatfs和usb mass storage class共存。 2.请先完成上一个帖子的步骤 -- 跳转https://blog.csdn.net/hjn0618/article/details/130383593 硬件平台:正点原子阿波罗 STM32H734IIT6 开发工具:

    2024年02月10日
    浏览(40)
  • STM32H7并行读取AD7606数据以及片内AD值不准解决办法

    先了解一下AD7606,16位,单电源,200k采样率,8路,除了贵没有其他缺点,数据相当的稳,一个5V供电,不用运放的情况下采集电压精度可以达到1mv,非常Nice 与单片机相连 单片机 调用代码 测试发现AD采集到的电压要远小于实际电压,H7的AD还是16位的,不能这么拉跨吧,在网上

    2024年02月11日
    浏览(49)
  • 【正点原子STM32】QSPI四线SPI模式(Quad-SPI存储器、间接模式、状态轮询模式、内存映射模式、命令序列、QSPI基本使用步骤、SPI FLASH基本使用步骤)

    一、QSPI介绍 1.1、QSPI功能框图(双闪存模式禁止) 1.2、QSPI 时钟源 1.3、间接模式 1.4、内存映射模式 1.5、命令序列(间接模式 或 内存映射模式) 1.6、指令、地址、交替字节、空指令周期、数据各阶段 1.7、QSPI FLASH设置 1.8、QSPI 中断类型 二、QSPI相关寄存器介绍 三、QSPI相关

    2024年04月22日
    浏览(72)
  • 【STM32H7 开发笔记】| 02 - 通过定时器级联方式同步启动多个定时器并输出 PWM 波形

    (STM32H723xE/G) 所有定时器包括 两个高级控制定时器、十二个通用定时器、两个基本定时器、五个低功耗定时器、两个看门狗定时器和一个SysTick定时器 。所有计时器计数器都可以在Debug模式下冻结。 本次实验主频配置的是500MHz 高级控制定时器(TIM1,TIM8)可以看作是在6通道

    2024年02月14日
    浏览(44)
  • STM32 使用HAL库操作FLASH

    本文参考 :STM32CubeMX学习笔记(51)——读写内部Flash - 简书 STM32F103C8T6 stmhalflash.h stmhalflash.c 使用示例

    2024年02月12日
    浏览(40)
  • 13.STM32F103C8使用PSRAM64H外扩RAM空间

    最近在调试STM32F103C8驱动墨水屏的实验,在使用过程中,需要使用大内存的RAM需要,由于C8T6的RAM空间只有20KB,而墨水屏的需要的内存为800*480*2/8=93.75KB。 在网上查了相关的方案,都是使用STM32F103ZE外扩IS62WV51216这种并口SRAM的,使用IS62WV51216需要使用多引脚的STM32F103Zx系列,对于

    2024年02月15日
    浏览(46)
  • 【Clion+OpenOCD+Stm32CubeMX+gcc】linux交叉编译开发stm32全过程

    双系统:ubuntu 22.04 电脑:拯救者Y7000 板子:stm32f103c8t6 一段摸爬滚打的辛酸史,囊括了我在过程中遇见的所有报错及解决方法! 记录自己实现的步骤,过程已经跟新完毕,笔者能力有限所用的方法以及代码考虑的不一定全面,也希望大佬多多补充! 目录 安装stm32cubeIDE 官网下

    2024年02月22日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包