基于MDK-Keil环境如何把STM32程序直接下载到SRAM运行

1. 前言

对于 Cortex-M 内核的微控制器,它们都可以支持在 RAM 中执行程序,有些非 ARM 的微控制器是不支持的。

在内部 SRAM 执行程序,有基于以下几方面的原因:

  • 1、所使用的设备可能具有OTP(One-time Programmable,一次性可编程)ROM区域,还没有确定最终代码之前,还不会把程序编程到芯片中;
  • 2、有些MCU内部内部可能没有Flash,可能会使用到外部的存储器。但是在软件开发阶段可以下载到SRAM进行开发测试;
  • 3、对于特定的测试场合,Flash已经烧录了程序,但是不想擦除。这时可以把测试程序下载到SRAM运行;
  • 4、对于有些Flash被锁定的芯片,可以把代码下载到SRAM,然后进行解锁;
  • 5、Flash写入需要先擦除,所以SRAM的写入速度要比Flash快很多,如果程序很大的话,在开发阶段直接在SRAM运行可以提高效率。

对于程序下载到内部SRAM运行,有多种方法:

  • 1、配置boot引脚,然后下载代码到SRAM,使程序从SRAM启动
  • 2、不修改boot引脚启动模式,借助仿真器,进入仿真模式,然后强制更改 PC SP 指针,从SRAM位置取值开始运行
  • 3、程序下载到内部Flash或者外部的SD卡、SPI Flash等存储设备,然后上电之后把代码搬运到SRAM运行(类似代码的重定位)

下面只介绍前面两种方式。

首先在修改程序在SRAM运行之前,要先准备好一份可以正常在Flash运行的程序。

2. 修改散列文件

散列文件,就是链接脚本,指导链接器如何对程序进行链接的。

我们要让代码在SRAM运行,首先就要修改散列文件,让程序链接地址修改在内部SRAM空间。

在这里插入图片描述

我们打开Keil的配置界面,然后使用我们自己修改的散列文件。

修改后的散列文件内容如下:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************LR_IROM1 0x20000000 0x00010000  {    ; load region size_regionER_IROM1 0x20000000 0x00010000  {  ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO).ANY (+XO)}RW_IRAM1 0x20010000 0x00010000  {  ; RW data.ANY (+RW +ZI)}
}

我使用的MCU型号是 STM32F407ZG ,IARM1 的 SRAM 大小有 0x20000 ,即 128KB。我这里分配的代码区域(ER_IROM1)大小是 0x10000(64KB),然后可读可写的数据区域大小是0x10000(64KB),也就是把他们平均分了。

在实际的项目开发中,可根据实际情况改写分配。

3. 修改中断向量表基地址

默认的中断向量表基地址是指向 0x08000000 的地址处的,现在我们已经更改了链接地址,把程序链接到内部SRAM 0x20000000 区域了。

如果发生中断,CPU还是跳到0x08000000开始的地址处执行中断服务函数的话,那么肯定是程序崩溃,因为现在0x08000000处的地址已经没有代码了。

要想正常使用中断的话,就必须修改中断向量表的基地址指向0x20000000地址处。

修改中断向量表基地址,只要修改 SCB->VTOR 寄存器的值就行。

具体代码,在 system_stm3f4xx.c 的 SystemInit 函数就有。如下:

void SystemInit(void)
{/* 部分代码省略 ........ *//* Configure the Vector Table location add offset address */#ifdef VECT_TAB_SRAMSCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */#elseSCB->VTOR = FMC_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */#endif
}

我们只要定义这个 VECT_TAB_SRAM 宏,就可以修改中断向量表的基地址指向 0x20000000 的地址处了。

这个宏可以直接在Keil的配置界面 C/C++ 选项里面的宏定义那里填写,当然直接在 system_stm3f4xx.c 这个文件前面自己手动写一下也可以。

4. 修改下载算法的配置

为了把代码下载到SRAM中,还需要修改Jlink的下载算法配置,只要其实就是更改下载的地址改为 SRAM 的地址。

在这里插入图片描述

对于上面的配置简单解释如下:

  • 1、由于是下载到SRAM,SRAM写入是不需要擦除的,所以勾选 DO not Erase 即可
  • 2、“Programming Algorithm”一栏的配置,由于没有内置的SRAM下载算法,所以下载算法选择的还是原来的Flash下载算法。但是下面的起始地址和大小需要更改,就改为我们在散列文件定义代码区域的起始地址和大小。
  • 2、“RAM for Algorithm”一栏是指“编程算法”(Programming Algorithm)可使用的 RAM 空间,下载程序到 FLASH 时运行的编程算法需要使用 RAM 空间,在默认配置中它的首地址为 0x20000000,即内部 SRAM 的首地址。但是现在我们修改了0x20000000开始处存放的是代码,所以这里的起始地址要修改了散列文件设置的 RW 区域的起始地址,即 0x20010000 。然后大小默认不用改。

5. 修改boot启动模式

配置到这里,其实我们这时如果更改Boot的启动引脚,配置为内部SRAM启动,然后点击下载按钮,程序就可以正常跑了的。

在这里插入图片描述

但是如果不修改boot启动模式,然后从SRAM启动的话,也可以借助仿真器配置,进入仿真调试模式,然后通过仿真器配置强制 PC SP 指针从 0x20000000 开始处取值,这样也能让程序正常从SRAM运行。

6. 通过仿真器配置修改 PC SP 的值

修改boot模式的目的,其实就是让MCU上电之后,可以从正确的地址处获取到 PC SP 指针的初始值,这样代码才可以正常开始运行。

让 PC SP 获取到正确的值,有两种方式:

  • 修改Boot启动模式,让程序从内部SRAM启动
  • 不修改启动模式,然后通过仿真器配置,进入仿真模式,强制修改 PC SP 的值。

下面介绍下怎么通过仿真器配置,让代码在SRAM运行。

首先我们自己编写一份 .ini 的调试配置文件,强制 PC SP 指针的地址值。内容如下:

/***********************************************************/
/* Debug_RAM.ini: Initialization File for Debugging from Internal RAM */
/******************************************************/
/* This file is part of the uVision/ARM development tools. */
/* Copyright (c) 2005-2014 Keil Software. All rights reserved.*/
/* This software may only be used under the terms of a valid, current */
/* end user licence from KEIL for a compatible version of KEIL software */
/*development tools. Nothing else gives you the right to use this software ?*/
/***************************************************/FUNC void Setup (void) {SP = _RDWORD(0x20000000); // 设置栈指针 SP,把 0x20000000 地址中的内容赋值到 SP。PC = _RDWORD(0x20000004); // 设置程序指针 PC,把 0x20000004 地址中的内容赋值到 PC。// XPSR = 0x01000000; // 设置状态寄存器指针 xPSR_WDWORD(0xE000ED08, 0x20000000); // Setup Vector Table Offset Register}LOAD %L INCREMENTAL // 下载 axf 文件到 RAMSetup(); //调用上面定义的 setup 函数设置运行环境g, main //跳转到 main 函数

然后配置Keil的选项,如下:

在这里插入图片描述

这样,通过这种方式,不需要修改boot引脚的启动模式,点击 debug 调式按钮,也一样可以正常在SRAM运行。

缺点就是下载程序必须是点击进入调试界面,不能通过下载程序的按钮下载程序。因为这种方式是通过仿真器的配置强制设置 PC SP 指向正确的地址的。

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

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

相关文章

笔记一:odoo透视表和图表

透视表 1、首先在xml文件添加pivot 说明:(1)根元素pivot中属性: disable_linking:设置为True,删除表格单元格到列表视图的链接 display_quantity:设置为True,默认显示“数量”列 d…

关于IDEA中gradle项目bootrun无法进入断点以及gradle配置页面不全的解决方案

问题背景 在使用gradle编写的bootrun,采用debug方式启动项目时,无法进入断点,程序正常运行 并发现象1 此处无法识别为大象图标 点击右键后,没有圈中的这个选项 并发现象2 图片圈中的位置缺失 问题原因 正常的 run 命令是通过…

SoapUI实践:自动化测试、压力测试、持续集成

因为项目的原因,前段时间研究并使用了 SoapUI 测试工具进行自测开发的 api。下面将研究的成果展示给大家,希望对需要的人有所帮助。 SoapUI 是什么? SoapUI 是一个开源测试工具,通过 soap/http 来检查、调用、实现 Web Service …

springboot和vue:十、vue2和vue3的差异+组件间的传值

首先用vue-cli创建一个vue2的项目。 vue2和vue3的差异 main.js的语法有所差别。 vue2是 import Vue from vue import App from ./App.vuenew Vue({render: h > h(App), }).$mount(#app)vue3是 import { createApp } from vue import App from ./App.vuecreateApp(App).…

Java虚拟机内存模型

JVM虚拟机将内存数据分为: 程序计数器、虚拟机栈、本地方法栈、Java堆、方法区等部分。 程序计数器用于存放下一条运行的指令; 虚拟机栈和本地方法栈用于存放函数调用堆栈信息; Java堆用于存放Java程序运行时所需的对象等数据&#xff1b…

学习笔记|串口通信的基础知识|同步/异步|RS232|常见的串口软件的参数|STC32G单片机视频开发教程(冲哥)|第二十集:串口通信基础

目录 1.串口通信的基础知识串口通信(Serial Communication)同步/异步?全双工?常见的串口软件的参数 2.STC32的串口通信实现原理引脚选择:实现分时复用模式选择串口1模式1,模式1波特率计算公式 3.串口通信代码实现编写串口1通信程序…

前端 | AjaxAxios模块

文章目录 1. Ajax1.1 Ajax介绍1.2 Ajax作用1.3 同步异步1.4 原生Ajax 2. Axios2.1 Axios下载2.2 Axios基本使用2.3 Axios方法 1. Ajax 1.1 Ajax介绍 Ajax: 全称(Asynchronous JavaScript And XML),异步的JavaScript和XML。 1.2 Ajax作用 …

vue3+elementPlus:el-tree复制粘贴数据功能,并且有弹窗组件

在tree控件里添加contextmenu属性表示右键点击事件。 因右键自定义菜单事件需要获取当前点击的位置&#xff0c;所以此处绑定动态样式来控制菜单实时跟踪鼠标右键点击位置。 //html <div class"box-list"><el-tree ref"treeRef" node-key"id…

python+selenium实现UI自动化(入门篇)

一、基础准备。 python环境安装&#xff0c;参考&#xff1a;CSDN pycharm安装&#xff0c;参考&#xff1a;CSDN 谷歌浏览器驱动配置&#xff0c;参考&#xff1a;CSDN二、新建pycharm项目 截图中&#xff0c;上面是项目地址&#xff08;可以提前在指定位置创建文件夹&#xf…

Redis 主从复制及哨兵模式

目录 1 Redis 主从复制 1.1 主从复制的作用 1.2 主从复制流程 2 搭建Redis 主从复制 2.1 安装 Redis 2.2 修改 Redis 配置文件&#xff08;Master节点操作&#xff09; 2.3 修改 Redis 配置文件&#xff08;Slave节点操作&#xff09; 2.4 验证主从效果 3 Redis 哨兵模…

数据结构——排序算法(C语言)

本篇将详细讲一下以下排序算法&#xff1a; 直接插入排序希尔排序选择排序快速排序归并排序计数排序 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某写关键字的大小&#xff0c;按照递增或递减0排列起来的操作。 稳定性的概念…

JAVA开发中常用RDMS

一、前言 JAVA的开发离不开数据库的支持&#xff0c;常见的有关系型数据库和非关系型数据库。java除了处理不依赖与数据库的通信技术。很多的java项目或者应用程序都需要建立在数据库的基础上。所以java开发早已经不是单纯的java开发&#xff0c;更多的是基于对数据的处理&…

一文教你如何快速备考云计算HCIE 3.0 !

大家好&#xff0c;在誉天实验辅导老师的耐心帮助下&#xff0c;本人在9月21日的云计算HCIE 3.0考试已顺利通过&#xff0c;很高兴有这个机会给大家分享备考的经历&#xff0c;希望对还在备考的同学能有一定的帮助。 备考准备 在云计算HCIE3.0的课程学习结束之后&#xff0c;就…

一款构建Python命令行应用的开源库

1 简介 当我们编写 Python 程序时&#xff0c;我们经常需要与用户进行交互&#xff0c;接收输入并输出结果。Python 提供了许多方法来实现这一点&#xff0c;其中一个非常方便的方法是使用 typer 库。typer 是一个用于构建命令行应用程序的 Python 库&#xff0c;它使得创建命令…

使用MATLAB进行傅里叶变换

1、定义 T1;% 周期0-1 N20;% 最大谐波 k-N:N;% -20:20——-20表示a_(20)e^(j*20*w0*t) N1length(k);%N141 % ceil(N1/2)21%即21是N1的中位数tlinspace(0,T,100); Ntlength(t); ttlinspace(-4*T,4*T,1024); Nttlength(tt);2、原函数 w02*pi/T; % 0-T xt(t>T/4).* 1.0; fig…

嵌入式学习笔记(49)由I2C学通信时序

10.2.1什么是时序&#xff1f; 字面意思&#xff0c;时序就是时间顺序&#xff0c;实际上在通信中时序就是通信线上按照时间顺序发生的电平变化&#xff0c;以及这些变化对通信的意义就叫时序。 10.2.2 I2C总线空闲状态、起始位、结束位 (1)I2C总线上有1个主设备&#xff0c…

二叉树的顺序存储——堆——初识堆排序

前面我们学过可以把完全二叉树存入到顺序表中&#xff0c;然后利用完全二叉树的情缘关系&#xff0c;就可以通过数组下标来联系。 但是并不是把二叉树存入到数组中就是堆了&#xff0c;要看原原来的二叉树是否满足&#xff1a;所有的父都小于等于子&#xff0c;或者所有的父都…

2023年铷铁硼行业分析:低端供应过剩,高性能材料供应不足[图]

铷铁硼材料是一种Fe基磁性材料&#xff0c;主要由钕铁硼按一定比例组成的四方晶体结构&#xff0c;其中Fe元素约占总质量的三分之二&#xff0c;Nd元素约占总量的三分之一&#xff0c;而B等含量最少&#xff0c;约占1%。铷铁硼是现今磁性最强的永久磁铁&#xff0c;也是最常使用…

记录vue开发实例

封装的表格组件 <template><div><div style"width: 100%" v-if"showList"><el-table v-loading.lock"loading" :data"dataList":header-cell-style"{background: #F2FCFE,fontSize: 14px,color: #50606D}&…

sed 命令

sed是Stream Editor&#xff08;字符流编辑器&#xff09;的缩写&#xff0c;简称流编辑器。 sed 命令是一个面向行处理的工具&#xff0c;它以“行”为处理单位&#xff0c;针对每一行进行处理&#xff0c;处理后的结果会输出到标准输出stdout。sed 命令是很懂礼貌的一个命令&…