在 Keil 中将 STM32 工程下载到 RAM 进行调试运行

在使用 STM32 进行调试时,默认情况下代码会被烧写到 Flash 中运行。然而,Flash 写入速度较慢,擦写次数有限,且调试过程中频繁烧写可能影响开发效率。在某些场景下(如快速验证代码或避免 Flash 擦写),我们可以将代码直接下载到 STM32 的内部 RAM 中运行并进行调试。

本文以 STM32H750 为例,详细介绍如何在 Keil 中配置工程,使代码下载到 RAM 并进行调试。其他 STM32 系列芯片的配置方法类似,只需根据芯片的 RAM 地址和大小进行调整。


1. 关闭默认的 Memory Layout 配置

在 Keil 中,打开工程配置窗口:

  1. 点击菜单栏 Project -> Options for Target
  2. 切换到 Linker 选项卡。
  3. 取消勾选 Use Memory Layout from Target Dialog

说明
取消该选项后,Keil 将不再使用 Target 选项卡中配置的 ROM 和 RAM 地址,而是完全依赖用户自定义的 Scatter File (.sct) 来定义代码和数据的内存布局。这一步是实现 RAM 调试的关键。
在这里插入图片描述


2. 配置 Scatter File (.sct)

由于取消了默认内存布局,需要创建一个分散加载文件(.sct 文件)来指定代码和数据的存储位置。
Options for Target -> Linker 中,启用 Use Scatter File 选项,并创建一个 .sct 文件,用于定义代码和数据的内存分配。
在这里插入图片描述

以下是以 STM32H750 为例的 .sct 文件内容:

; *************************************************************
; *** Scatter-Loading Description File for STM32H750 RAM Debug ***
; *************************************************************LR_IROM1 0x24000000 0x00080000  {    ; Load region: AXI SRAM (512KB)ER_IROM1 0x24000000 0x00080000  {  ; Execution region: Code and constants*.o (RESET, +First)              ; Reset vector and Reset_Handler*(InRoot$$Sections)              ; Linker-specific root sections.ANY (+RO)                       ; Read-only sections (code and constants).ANY (+XO)                       ; Execute-only sections (if any)}RW_IRAM1 0x20000000 0x00020000  {  ; Execution region: DTCM RAM (128KB).ANY (+RW +ZI)                   ; Read-write and zero-initialized data}
}

说明

  • LR_IROM1:定义加载区域,起始地址为 0x24000000(STM32H750 的 AXI SRAM 起始地址),大小为 512KB
  • ER_IROM1:定义代码和常量数据的执行区域,放置在 AXI SRAM 中。
    • *.o (RESET, +First):将复位向量表和 Reset_Handler 放在执行区域的开头。
    • *(InRoot$$Sections):包含链接器需要的根区段(如初始化代码)。
    • .ANY (+RO):将所有只读数据(代码和常量)分配到该区域。
    • .ANY (+XO):将仅执行代码(若有)分配到该区域。
  • RW_IRAM1:定义读写数据和零初始化数据的执行区域,起始地址为 0x20000000(DTCM RAM 起始地址),大小为 128KB
    • .ANY (+RW +ZI):将读写数据和零初始化数据分配到 DTCM RAM。

注意

  • 不同 STM32 芯片的 RAM 地址和大小不同,请参考芯片的参考手册或数据手册(如 STM32H750 的 AXI SRAM 和 DTCM RAM 地址)。
  • 确保程序的代码和数据总大小不超过目标 RAM 的容量。

3. 禁用 Flash 编程算法

由于我们希望代码运行在 RAM 中,而不是 Flash 中,因此需要禁用 Keil 的 Flash 编程功能:

  1. 打开 Options for Target -> Utilities
  2. 取消勾选 Use Target Driver for Flash Programming
  3. 选择 Use External Tool for Flash Programming

说明
禁用 Flash 编程算法后,Keil 不会尝试将代码写入 Flash,而是直接将程序加载到指定的 RAM 地址。
在这里插入图片描述


4. 配置调试初始化文件 (.ini)

为了确保程序从 RAM 正确启动,需要配置一个调试初始化文件(.ini),用于设置栈指针(SP)、程序计数器(PC)以及向量表偏移寄存器(VTOR)。在 Options for Target -> Debug 中,启用 Initialization File 选项,并创建一个 .ini 文件,
在这里插入图片描述

内容如下:

/***********************************************************/
/* Debug_RAM.ini: Initialization File for Debugging from RAM */
/***********************************************************/FUNC void Setup (void) {SP = _RDWORD(0x24000000);        // Set Stack Pointer (SP) from RAM vector tablePC = _RDWORD(0x24000004);        // Set Program Counter (PC) from RAM reset vector_WDWORD(0xE000ED08, 0x24000000); // Set Vector Table Offset Register (VTOR) to RAM
}FUNC void OnResetExec (void) {      // Executes upon software resetSetup();                          // Reinitialize runtime environment
}LOAD %L INCREMENTAL                // Load the .axf file to RAM
Setup();                           // Call Setup function to initialize runtime
g, main                            // Jump to main function

说明

  • _RDWORD(addr):从指定地址读取一个 4 字节的字。
  • _WDWORD(addr, val):向指定地址写入一个 4 字节的字。
  • SP = _RDWORD(0x24000000):从 RAM 的起始地址(AXI SRAM)读取栈指针初值。
  • PC = _RDWORD(0x24000004):从 RAM 的复位向量地址读取程序计数器初值。
  • _WDWORD(0xE000ED08, 0x24000000):将向量表偏移寄存器(VTOR)设置为 RAM 起始地址,确保中断向量表正确指向 RAM。
  • LOAD %L INCREMENTAL:将编译生成的 .axf 文件加载到 RAM。
  • g, main:跳转到 main 函数开始执行。

注意

  • 确保 .ini 文件中的地址与 .sct 文件中的 RAM 地址一致。
  • 如果芯片的 RAM 地址不同,需要相应修改 .ini 文件中的地址。

5. 配置调试和下载选项

为了确保程序只加载到 RAM 而不影响 Flash,需要调整调试和下载设置:

  1. 打开 Options for Target -> Debug -> Settings -> Flash Download
  2. Programming Algorithm 中,删除所有与 Flash 相关的算法。
  3. Download Function 中:
    • 选择 Do not Erase
    • 取消勾选 Program

说明
这些设置确保 Keil 不会擦除或写入 Flash,而是直接将程序加载到 RAM 中运行。
在这里插入图片描述


6. 编译并进入调试模式

完成以上配置后:

  1. 点击 Build 编译工程,确保无错误。
  2. 点击 Debug -> Start/Stop Debug Session 进入调试模式。
  3. 程序将自动下载到 RAM 并从 RAM 启动运行。

验证

  • 在调试模式下,检查程序计数器(PC)是否指向 RAM 地址(如 0x24000000 开头的地址)。
  • 确保中断和函数调用正常工作。
    在这里插入图片描述

常见问题与注意事项

  1. RAM 大小限制
    确保程序的代码和数据总大小不超过目标 RAM 的容量。例如,STM32H750 的 AXI SRAM 为 512KB,DTCM RAM 为 128KB。如果程序过大,可能需要优化代码或选择其他 RAM 区域。

  2. 复位向量地址
    .sct 文件中,RESET 段必须位于 RAM 的起始地址(如 0x24000000),否则程序无法正确启动。

  3. 中断向量表
    确保 .ini 文件中正确设置了 VTOR 寄存器(如 _WDWORD(0xE000ED08, 0x24000000)),以将中断向量表重定位到 RAM,否则中断可能无法正常工作。

  4. 硬件断点限制
    在 RAM 调试时,调试器支持的硬件断点数量可能有限(通常为 6-8 个,具体取决于调试器和芯片)。如果需要设置更多断点,可以考虑使用软件断点(需确保代码支持)。

  5. 调试器兼容性
    确保使用的调试器(如 ST-Link、J-Link)支持 RAM 调试。某些低端调试器可能对 RAM 调试支持有限。

  6. 初始化代码
    如果程序依赖特定的硬件初始化(如时钟或外设),确保这些代码在 RAM 运行时仍然有效。某些外设可能需要额外的配置以支持 RAM 执行。


总结

通过以上步骤,您可以在 Keil 中将 STM32 工程配置为从 RAM 运行并进行调试,从而避免频繁擦写 Flash,提高调试效率。关键步骤包括:

  1. 使用 .sct 文件手动定义内存布局。
  2. 配置 .ini 文件以设置 RAM 启动环境。
  3. 禁用 Flash 编程算法,仅将程序加载到 RAM。

此方法适用于快速调试、验证代码逻辑或需要保护 Flash 的场景。希望这篇教程能帮助您顺利实现 STM32 的 RAM 调试!🚀

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

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

相关文章

【51单片机】【protues仿真】基于51单片机宠物投食系统

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 一、主要功能 1、LCD1602液晶显示时间、温度、食物重量 2、按键手动投喂食物​ 3、称重模块检测当前食物重量 4、食物重量小于阈值会声光警报并自动投喂 二、使用步骤 基于51单片机的宠物投食…

腾讯云负载均衡增加访问策略后访问失败

为了测试,在负载均衡的安全组添加2条安全策略,限制办公室内IP可访问,其他IP地址拒绝所有访问。结果,访问失败。经过反复测试,主要是js问价加载失败,动态接口访问代码返回正常。再进行测试,发现去…

CSS的文本样式

1.文本样式的分类注意&#xff1a;必须先建立标签&#xff0c;再在head中修改1.1字体样式1.1.1字体颜色代码演示<head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&g…

R语言读取excel文件数据-解决na问题

文章目录安装R语言运行环境实现代码遇到的问题总结安装R语言运行环境 安装教程连接, 包含国内镜像快速下载 实现代码 实现思路&#xff1a;使用python将文件的空字符的位置变成0&#xff0c;生成csv文件后交给R语言处理python实现代码如下&#xff1a; import pandas as pd…

【Nginx 运维实战】版本替换:强制 vs 平滑升级全解析

【Nginx 运维实战】版本替换&#xff1a;强制 vs 平滑升级全解析一&#xff1a;版本替换的两种思路二&#xff1a;使用场景对比三&#xff1a;实战1&#xff09;强制替换1.备份旧版本2.替换为新版本3.**赋予执行权限**4.**重启 Nginx**2&#xff09;平滑替换1.确认进程文件2.备…

MQ-消息队列

定义 Mssage Queue&#xff1a;消息队列。它是一种“先进先出”&#xff08;FIFO&#xff09;的数据结构&#xff0c;用于在分布式系统或应用程序之间进行异步通信。组成1. 生产者&#xff08;Producer&#xff09;定义&#xff1a;消息的发送方&#xff0c;负责将业务系…

NVIDIA驱动程序核心的“即时编译器”(Just-in-Time, JIT Compiler)详细介绍

我们来详细、深入地剖析这个位于NVIDIA驱动程序核心的“即时编译器”&#xff08;Just-in-Time, JIT Compiler&#xff09;。它堪称CUDA生态系统成功的“幕后英雄”&#xff0c;是连接软件稳定性和硬件飞速发展的关键桥梁。 第一部分&#xff1a;JIT编译器的本质 首先&#xff…

【PS2025全网最新版】稳定版PS2025保姆级下载安装详细图文教程(附安装包)(Adobe Photoshop)

今天&#xff0c;给大家带来PS2025的保姆级下载安装图文教程。 前言&#xff1a; Adobe Photoshop 作为业界领先的图像处理与设计软件&#xff0c;持续推动着数字创意领域的发展。其应用涵盖平面设计、摄影后期、UI/UX 设计、影视特效等多个专业方向&#xff0c;为用户提供强…

分享TWS充电仓方案开发设计

TWS耳机市场“卷”到最后&#xff0c;拼的早已不只是音质&#xff0c;而是续航、交互、体积、成本四位一体。传统充电仓用多颗IC堆砌&#xff1a;升压、电量计、霍尔、LED驱动、保护IC……BOM高、贴片复杂、调试周期长。8位MCU把上述功能“一锅端”&#xff1a;单芯片即完成电源…

【Java实战㉖】深入Java单元测试:JUnit 5实战指南

目录一、单元测试概述1.1 单元测试概念1.2 单元测试优势1.3 JUnit 5 框架组成1.4 JUnit 5 环境搭建二、JUnit 5 核心功能实战2.1 测试类与测试方法2.2 测试生命周期2.3 断言方法2.4 异常测试三、单元测试进阶实战3.1 参数化测试3.2 测试套件3.3 Mockito 框架3.4 单元测试实战案…

分布式微服务--ZooKeeper作为分布式锁

看这篇博客之前可以先去了解博主的另一篇讲解ZooKeeper的博客&#xff1a;分布式微服务--ZooKeeper的客户端常用命令 & Java API 操作-CSDN博客 1. 为什么需要分布式锁&#xff1f; 在分布式系统中&#xff0c;多个服务节点可能同时访问或修改同一份共享资源&#xff08;例…

基于容器化云原生的 MySQL 及中间件高可用自动化集群项目

1 项目概述 本项目旨在构建一个高可用、高性能的 MySQL 集群,能够处理大规模并发业务。通过容器化部署、多级缓存、完善的监控和备份策略,确保数据库服务的连续性和数据安全性。 架构总览 预期目标 数据库服务可用性达到 99.99% 支持每秒 thousands 级别的并发访问 实现秒…

如何将 iPhone 备份到电脑/PC 的前 5 种方法

定期备份你的 iPhone&#xff08;最好每两周一次&#xff09;对于保护你的数据至关重要。它确保了如果设备损坏、丢失或被盗&#xff0c;或者你换了新手机&#xff0c;你不会丢失重要信息&#xff0c;并且可以轻松地从备份中恢复应用程序、照片、设置等。如果你不确定如何备份 …

国产AI芯片编程模型深度对比:寒武纪MLU vs 壁仞BR100异构计算设计

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;H卡级别算力&#xff0c;80G大显存&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生更享专属优惠。 引言&#xff1a;国产AI芯片的崛起与挑战 随着人工智能技术的飞速…

【项目】基于One Thread One Loop模型的高性能网络库实现 - 项目介绍与前置知识

目录 项目介绍 HTTP服务器基本认识 Reactor模式基本认识 单Reactor单线程模式认识 单Reactor多线程模式认识 多Reactor多线程模式认识 模块划分 Server模块 Buffer模块 Socket模块 Channel模块 Connection模块 Acceptor模块 TimerQueue模块 Poller模块 EventLo…

lua中table键类型及lua中table的初始化有几种方式

在 Lua 中&#xff0c;table 的键几乎可以是任何类型&#xff0c;但有几个重要的规则和最佳实践需要了解。1. 主要键类型(1) 字符串 (string)这是最常见、最推荐的键类型。local person {name "Alice", -- 等同于 ["name"] "Alice"["age…

matlab实现利用双MZI产生RZ33-QPSK信号

利用MATLAB实现双MZI产生RZ33-QPSK信号的代码&#xff1a; 参数设置 % 信号参数 fs 1e6; % 采样频率 fc 10e6; % 载波频率 T 1e-6; % 符号周期 N 1000; % 采样点数 t 0:1/fs:(N-1)/fs; % 时间向量生成QPSK信号 % 生成随机二进制序列 data randi([0,1],1,N);% 将二进制序列…

Vue响应式更新 vs React状态更新:两种范式的底层逻辑与实践差异

在现代前端框架中&#xff0c;Vue和React作为两大主流选择&#xff0c;分别采用了截然不同的状态管理与更新机制。Vue的“响应式更新”通过自动追踪依赖实现数据与视图的联动&#xff0c;而React的“状态更新”则依赖显式setState触发重新渲染。本文将从底层原理、更新流程、优…

Spring MVC 的常用注解

一、控制器相关注解ControllerController注解用于标记一个类为 Spring MVC 的控制器。在 Spring MVC 框架里&#xff0c;控制器扮演着关键角色&#xff0c;负责接收 HTTP 请求并返回响应。当一个类被Controller注解标记后&#xff0c;Spring 容器会自动识别并将其纳入管理。例如…

Oracle APEX 利用卡片实现翻转(方法一)

目录 0. 以 Oracle 的标准示例表 EMP 为例&#xff0c;实现卡片翻转 1. 创建PL/SQL动态内容区域 2. 添加 CSS 实现翻转效果 3. 添加动态操作 (Dynamic Action) 4. 看效果 0. 以 Oracle 的标准示例表 EMP 为例&#xff0c;实现卡片翻转 正面&#xff1a; 显示员工姓名 (EN…