三、如何将代码放到Ram中运行

1.Flash的特性

Flash分为不同的Partion,主要是0 Partion和1 Partion,且0 Partion和1 Partion在整个物理地址中是交互存在的,如下图。所以你的Code既会存在0 Partion中又会存在1 Partion中。但是当你要去擦Flash的时候,如果你的Code完全存在0 partion中,是可以擦1 partion的;反之依然。但一般不是这么存放的,即Code既会存在0 Partion又会存在1 Partion中。所以,当你想去擦Flash的时候,是不可以直接去擦的,目前常规的做法是将Code拷贝到Ram中运行。方法如下:

2.首先将和Flash相关的代码,通过静态编译放到想要的段内,此段为Ram段,如下。

3.在link文件中,将.ramcode段放到对应的Ram分区中,即将代码生成到Ram段,但初始值在对应的Flash中,在上电初始化时,为做Copy动作做准备,如下:

4.在启动代码里做将flash_memory拷贝到int_sram段的动作,如下:

5.最终查看生成的Map文件如下,CddBootFnt_ErsFlDt已经在Ram段内,如下:

【实验题目】 在RAM中执行程序代码 【实验目的】 掌握片外RAM扩展方法(重点是硬件接法,而程序操作很简单)。 弄清楚什么是“哈佛存储结构”和“冯·诺依曼存储结构”。 【硬件接法】 P1.2接交流蜂鸣器。 请认真参考硬件电路图中RAM的接法。RAM映射到地址“0x8000~0xBFFF”,共16KB。 【实验原理】 8051单片机本来是“哈佛存储结构”,程序ROM和片外数据RAM位于完全分开的存储空间。/WR和/RD信号用于访问片外数据RAM。当使用片外程序ROM时,/PSEN管脚负责读取程序代码或固定数表。通常ROM不可写,所以未安排ROM的写信号。ROM和RAM共用地址和数据总线,但读写选通信号是分开的,所以在逻辑上分属两个不同的64KB空间,总共128KB。另外片内数据RAM和SFR空间又与前两者有别,是独立编址的。在软件上,访问不同的存储空间采用不同的指令,如“MOVX A,@DPTR”、“MOVC A,@A+DPTR”、“MOV A,@Ri”等。 注意,/PSEN和/RD可以经过“与门”后再接到RAM的/OE。这样,代码和数据都位于相同的地址空间,在RAM中也可以跑程序,用“MOVC”和“MOVX”指令都能访问RAM的存储单元。如果把程序代码加载到片外RAM中,然后用“LJMP”指令跳转过去就能在RAM中执行程序代码。 【说明:片内Flash中的引导程序】 这是一个比较复杂的程序,其中还牵涉到了C51中嵌入汇编的用法。对大多数初学者来说,只要了解其工作过程即可,不必深究。如果您确实对其感兴趣,请自行仔细研究。 该引导程序位于片内Flash中,其作用是通过串行口加载HEX格式的程序文件,并自动转换成BIN格式,然后保存到片外RAM中,最后跳转过去执行。RAM起始地址为0x8000。引导完毕后,蜂鸣器鸣叫,并等待按下K4键。K4按下后,才开始执行。 【说明:在片外RAM运行的程序】 编写在片外RAM运行的程序与编写正常的A51或C51程序基本相同,但是需要做一些小的调整。正常的程序起始地址总是0x0000,但现在片外RAM的起始地址是0x8000,因此要在原有程序的基础上重新设置起始地址。 对于A51编程,找到ORG命令,修改复位地址和全部中断向量入口地址,使它们都偏移0x8000。例如复位地址为0x0000要改成0x8000,定时器T0中断入口地址0x000B要改成0x800B,等等。重新编译,生成HEX程序文件,备用。 而对于C51编程,设置的项目稍多一些,步骤如下: 第一,打开Keil C51安装目录“C:\Keil\C51\LIB”,找到文件“STARTUP.A51”,将其复制到您的工程文件夹下,然后右击项目管理窗口的“Source Group1”添加该文件。另一种方法是:在新建工程选择“CPU”后,当出现是否添加启动文件对话框时选择“是”,则文件“STARTUP.A51”会自动被加入。 第二,双击项目管理窗口里的“STARTUP.A51”,找到“CSEG AT 0”这一行,将起始地址“0”改成“0x8000”,保存。 第,设置片外程序ROM的起始地址和大小。打开编译环境中设置(点击工具栏的那个绿色按钮进入该设置),在“Off-chip Code memory”Eprom(在这里,Eprom实际上已被RAM代替)栏第一行填入0x8000和0x3000(共12KB空间)。 第四,程序中有可能用到xdata数据,因此还要设置片外数据RAM的起始地址和大小。可以在“Off-chip Xdata memory”Ram栏第一行填入0xB000和0x1000,留足空间(有4KB呀!)。 第五,设置中断向量。打开“Options fo Target”设置里的“C51”选项页,找到“Interrupt vectors at...”项,修改为“0x8000”。 OK,所有设置都已完成,重新编译,生成HEX程序文件,备用。 【实验步骤】 1、ISP下载开关扳到“01”,用Flash Magic软件下载程序文件“HexLoader.hex”,暂时不要运行。 2、打开串行调试助手软件ZLGCOMView,操作如下: 勾中“HEX发送”(非常重要!); 通信口:选择实际的串行口(通常为COM1); 波特率:4800; 数据位:8; 停止位:1; 点击“打开文件”装入文件夹“在片外RAM运行的程序”下的一个程序文件(HEX格式),在这些程序中,所有起始地址都已经预先设置好了; 按实验箱上单片机的RST键,会看到显示“Ready”; 点击“发送文件”,程序开始下载到片外RAM; 下载完毕,出现“OK, press K4...”,蜂鸣器同时鸣叫; 按一次实验箱上的K4键,程
<think>好的,用户想了解如何在Keil中将代码放到RAM运行。我需要先回忆一下Keil的相关配置步骤。通常,将代码放入RAM涉及到链接脚本(scatter file)的修改,可能还需要使用特定的编译器指令,比如__attribute__((section))。 首先,用户可能是嵌入式开发者,可能在使用ARM Cortex-M系列芯片,这类需求常见于需要快速执行的代码或减少Flash磨损的情况。需要确认用户是否有特定的硬件,但可能用户没有提到,所以保持一般性。 接下来,要考虑Keil的配置步骤。首先是分散加载文件(scatter file)的修改,定义RAM域,并将特定的代码段映射到那里。然后是在代码中使用属性指定段名。同时,启动文件可能需要调整初始化部分,避免将RAM中的代码覆盖掉。另外,代码搬运的问题,比如是否需要将代码从Flash复制到RAM,并在运行时执行。 用户可能遇到的问题包括:忘记修改启动文件导致初始化时覆盖RAM代码,或者没有正确配置分散加载文件导致链接错误。需要提醒注意事项,比如RAM的容量限制,掉电丢失代码的问题,以及初始化顺序。 需要分步骤说明,确保结构清晰。首先介绍分散加载文件的修改,然后代码中的属性设置,启动文件的调整,搬运代码的方法,最后注意事项。这样用户能逐步操作。 另外,是否需要示例代码?提供简单的示例会更有帮助,比如使用__attribute__定义函数到RAM段,并给出分散加载文件的示例片段。但用户可能只需要步骤,不一定需要完整代码,所以点到为止。 还要考虑不同的情况,比如是否使用C++,但可能用户主要用C,所以保持C语言的示例。同时,检查是否有其他方法,比如通过Keil的配置选项,而不仅仅是代码修改。 最后,确保回答准确,避免错误。比如,在分散加载文件中正确指定执行域和加载域,确保在RAM中的代码正确初始化。可能需要强调复制代码RAM的过程,因为上电后RAM是空的,必须从Flash复制过去,除非使用持久化RAM,但这种情况较少。</think>在Keil中让代码RAM运行需要修改链接配置和代码属性,以下是具体实现步骤: 一、底层原理 1. 通过分散加载文件(scatter file)定义RAM域 2. 使用__attribute__指定代码段 3. 修改启动文件初始化过程 4. 实现代码搬运(Flash->RAM) 二、操作步骤 1. 修改分散加载文件(.sct) ```scatter LR_IROM1 0x08000000 0x00080000 { ; Flash配置 ER_IROM1 0x08000000 0x00080000 { *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00020000 { ; RAM配置 .ANY (+RW +ZI) *.o(RAM_CODE) ; 自定义RAM代码段 } } ``` 2. 代码标注(使用GCC扩展语法) ```c // 定义函数在RAM中执行 __attribute__((section("RAM_CODE"), noinline, used)) void Critical_Function(void) { // 时间敏感代码 } ``` 3. 启动文件修改(以STM32为例) 在SystemInit函数中添加搬运代码: ```c extern uint32_t _sramcode; // RAM代码起始地址 extern uint32_t _eramcode; // RAM代码结束地址 extern uint32_t _siramcode; // Flash中代码起始地址 void SystemInit(void) { // ...其他初始化代码 // 代码搬运 uint32_t *src = &_siramcode; uint32_t *dst = &_sramcode; while(dst < &_eramcode) { *dst++ = *src++; } } ``` 、注意事项 1. RAM空间有限,建议只将关键代码(如中断服务程序、高频调用的函数)放入RAM 2. 代码执行前必须完成搬运操作 3. 调试时需设置正确断点(RAM地址范围) 4. 需在Options->Target中勾选"Use Memory Layout from Target Dialog" 四、验证方法 1. 在调试模式下查看Disassembly窗口 2. 检查函数地址是否在RAM域(如0x2000xxxx) 3. 使用逻辑分析仪测量执行时间差异 此方案适用于需要高速执行或减少Flash擦写次数的场景(如EEPROM模拟),但会占用RAM资源,请根据实际需求权衡使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值