S32K324 数据初始化Rom到Ram Copy的方式

文章目录

    • 前言
    • 基础知识
      • ld文件中的段定义
      • ld文件中的符号定义
    • ld定义copy地址范围
    • 启动文件中的定义
    • Copy的使用
    • 总结

前言

之前一直不理解在ld文件中加__xxx_ram_start,__xxx_rom_start,__xxx_rom_end这些的作用,也不清楚原理。前几天遇到一个内存copy的问题,对这些有了更进一步的理解,记录一下过程。

基础知识

ld文件中的段定义

具体可以参考The Gnu Linker-3.8.3Output Section Attributes章节,下面的定义不是完整的解释,仅供参考

section [address][type] : [ALIGN(section_align)] [(flags)] [AT(address)]

其中:

section:是要定位的输入或输出段的名称,如 .text、.data 或用户自定义的段名。

[address]:可选参数,用于直接指定该段在内存或文件中的起始地址。如果不指定,通常由链接器根据其他规则(如链接脚本中的其他命令或默认布局)确定。

[type]:可选参数,用来指定段的类型,如 PROGBITS、NOLOAD 等。若不指定,链接器会根据段的内容自动推断其类型。

ALIGN:字节对齐使用。

[(flags)]:可选参数,包含一组以逗号分隔的标志,用于指定段的属性,如 ALLOC(分配空间)、READONLY(只读)、WRITE(可写)等。

AT(address):关键部分,用于指定该段在加载或运行时应被放置到的绝对地址。这里的 address 是一个具体的内存地址值。

ld文件中的符号定义

ld文件中以“__”开头定义的符号,一般会关联到指定的地址。例如:

        __SysCore_INIT_RAM_START = .;

在链接脚本上下文中,.表示当前位置(即当前正在处理的段的起始地址)。通过该符号,即可记录对应段的起始地址及结束地址。该符号后面可以被源文件使用。(c文件中使用时需要加extern,s文件中可以直接使用)

ld定义copy地址范围

了解之前符号的定义,我们可以获取需要copy的ram起始地址,ram结束地址,rom起始地址,rom结束地址。最终实际传递到.c或.s的只需要3个地址即可(ram起始地址,rom起始地址,rom结束地址)

/* -------------------------------------------------------------------------- */
/* Sections of INIT                                                          */
/* -------------------------------------------------------------------------- */
SECTIONS
{.SysCore_init ALIGN(4): AT(__POSTBUILD_CONST_END){__SysCore_INIT_RAM_START = .;...__SysCore_INIT_RAM_END = .;} > int_sram_sys__SysCore_INIT_ROM_START = __POSTBUILD_CONST_END;
__SysCore_INIT_ROM_END = __SysCore_INIT_ROM_START + (__SysCore_INIT_RAM_END - __SysCore_INIT_RAM_START);
}

__POSTBUILD_CONST_END是之前记录的一块flash区的结束地址,此处表示在其之后,作为ram数据的存放地址。

使用AT指令,指定该Ram区的数据放到对应flash中。

此处我们得到了__SysCore_INIT_RAM_START,__SysCore_INIT_ROM_START,__SysCore_INIT_ROM_END

在后面会使用

启动文件中的定义

.section ".init_table", "a".long 6.long __RAM_CACHEABLE_START.long __ROM_CACHEABLE_START.long __ROM_CACHEABLE_END.long __RAM_NO_CACHEABLE_START.long __ROM_NO_CACHEABLE_START.long __ROM_NO_CACHEABLE_END.long __RAM_SHAREABLE_START.long __ROM_SHAREABLE_START.long __ROM_SHAREABLE_END.long __RAM_INTERRUPT_START.long __ROM_INTERRUPT_START.long __ROM_INTERRUPT_END.long __shared_INIT_RAM_START.long __shared_INIT_ROM_START.long __shared_INIT_ROM_END.long __SysCore_INIT_RAM_START.long __SysCore_INIT_ROM_START.long __SysCore_INIT_ROM_END

.section “.init_table”, “a” 定义一个可分配的段init_table

这个段其实在ld文件中定义了,放在pflash中

此处相当于往里面写数据,实际可以理解为指针或者数组的应用,在后面使用的时候其实也是按数组来用的

.long 6 -定义4个字节,值为6,实际是表示的需要copy的rom-ram的对数,此处有6对

后面的定义3个为1组,分别为ram起始地址,rom起始地址,rom结束地址,都是在ld文件中定义的

此处定义好的数据在pflash中如下

image
从0x41BB14到0x41BB5F.存放了6组数据,包括其对应的ram起始地址,rom起始地址,rom结束地址

ld文件中通过 __INIT_TABLE获取首地址

__INIT_TABLE                  = ADDR(.init_table);

Copy的使用

在startup.c中对__INIT_TABLE声明,并使用

typedef struct
{uint8 * ram_start; /*!< Start address of section in RAM */uint8 * rom_start; /*!< Start address of section in ROM */uint8 * rom_end;   /*!< End address of section in ROM */
} Sys_CopyLayoutType;
typedef struct
{uint8 * ram_start; /*!< Start address of section in RAM */uint8 * ram_end;   /*!< End address of section in RAM */
} Sys_ZeroLayoutType;extern uint32 __INIT_TABLE[];
extern uint32 __ZERO_TABLE[];
#if (defined(__ARMCC_VERSION))extern uint32 __VECTOR_RAM;
#elseextern uint32 __VECTOR_RAM[];
#endif
/******************************************************************************** Code******************************************************************************/
/*FUNCTION************************************************************************ Function Name : init_data_bss* Description   : Make necessary initializations for RAM.* - Copy the vector table from ROM to RAM.* - Copy initialized data from ROM to RAM.* - Copy code that should reside in RAM from ROM* - Clear the zero-initialized data section.** Tool Chains:*   __GNUC__           : GNU Compiler Collection*   __ghs__            : Green Hills ARM Compiler*   __ICCARM__         : IAR ARM Compiler*   __DCC__            : Wind River Diab Compiler*   __ARMCC_VERSION    : ARMC Compiler** Implements    : init_data_bss_Activity*END**************************************************************************/
#define PLATFORM_START_SEC_CODE
#include "Platform_MemMap.h"void init_data_bss(void);void init_data_bss(void)
{const Sys_CopyLayoutType * copy_layout;const Sys_ZeroLayoutType * zero_layout;const uint8 * rom;uint8 * ram;uint32 len = 0U;uint32 size = 0U;uint32 i = 0U;uint32 j = 0U;const uint32 * initTable_Ptr = (uint32 *)__INIT_TABLE;const uint32 * zeroTable_Ptr = (uint32*)__ZERO_TABLE;/* Copy initialized table */len = *initTable_Ptr;initTable_Ptr++;copy_layout = (const Sys_CopyLayoutType *)initTable_Ptr;for(i = 0; i < len; i++){rom = copy_layout[i].rom_start;ram = copy_layout[i].ram_start;size = (uint32)copy_layout[i].rom_end - (uint32)copy_layout[i].rom_start;for(j = 0UL; j < size; j++){ram[j] = rom[j];}}/* Clear zero table */len = *zeroTable_Ptr;zeroTable_Ptr++;zero_layout = (const Sys_ZeroLayoutType *)zeroTable_Ptr;for(i = 0; i < len; i++){ram = zero_layout[i].ram_start;size = (uint32)zero_layout[i].ram_end - (uint32)zero_layout[i].ram_start;for(j = 0UL; j < size; j++){ram[j] = 0U;}}
}
#define PLATFORM_STOP_SEC_CODE
#include "Platform_MemMap.h"

通过上面的代码,实现了rom到ram的拷贝,实际只需要在.s中配置对应的参数即可

那这个函数是什么时候被调用的呢?

在启动文件中被调用,如下所示

_DATA_INIT:
#ifndef RAM_DATA_INIT_ON_ALL_CORES/* If this is the primary core, initialize data and bss */ldr  r0, =0x40260004ldr  r1,[r0]ldr  r0, =MAIN_COREcmp  r1,r0beq	 _INIT_DATA_BSSb    __SYSTEM_INIT
#endif_INIT_DATA_BSS:bl init_data_bss

上述启动代码解释如下:

1.条件判断:检查是否需要在所有核心上进行 RAM 数据初始化。若仅需在主核心上进行初始化(即未定义 RAM_DATA_INIT_ON_ALL_CORES),则执行后续操作;否则,直接执行_INIT_DATA_BSS(调用init_data_bss函数)。

2.核心识别:通过读取特定内存地址处的值,判断当前运行的核心是否为主核心。

3.主核心处理:若当前核心为主核心,跳转至 _INIT_DATA_BSS 标签处,执行数据和 BSS 初始化。

4.data与 BSS 初始化:在 _INIT_DATA_BSS 标签处,调用 init_data_bss 函数,完成数据段和 BSS 段的初始化工作。

5.非主核心处理或系统初始化:若当前核心非主核心(或不需要在所有核心上进行数据初始化),直接跳转至 __SYSTEM_INIT 标签处,继续进行其他系统初始化任务(调用SystemInit函数)。

总结

虽然没学过汇编语言,但遇到问题还是得上~慢慢学习吧!学无止境!

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

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

相关文章

从入门到放弃:Docker基础教程

一、引言 1. 什么是Docker Docker是一种用于开发、交付和运行应用程序的平台。它通过将应用程序打包成一个可以轻松部署的容器来实现隔离&#xff0c;从而简化了应用程序部署的流程。 2. Docker能解决什么问题 传统的应用程序部署和管理方式往往存在着各种问题&#xff0c;…

HarmonyOS时区和语言设置-使用相关api实现系统语言和地区设置

介绍 本示例展示了i18n&#xff0c;intl&#xff0c;resourceManager在eTS中的使用&#xff0c;使用相关api实现系统语言和地区设置、时间和时区设置&#xff0c;展示了区域格式化示例。 效果预览 使用说明 1.启动应用&#xff0c;进入应用&#xff0c;首页分为三个按钮&…

【JVM】GC导致的性能问题排查与解决方案,日志、堆分析工具介绍

一、必要性 重要应用程序在使用过程中&#xff0c;忽然无法响应用户请求&#xff0c;排查发现网络联通无问题&#xff0c;gateway能够正常接收分发请求&#xff0c;应用进程正常&#xff0c;正常向注册中心发送请求&#xff0c;但是接收http请求全部返回报错。 添加gc后发现内…

C#项目引用解决方案中其他项目dll时,出现黄色感叹号的解决方案

问题引入 今天拿着老师傅的老项目&#xff0c;需要做通讯调试&#xff0c;说测试一下&#xff0c;便添加了一个项目A来编写结构体&#xff0c;然后在窗体程序项目B中引用A&#xff0c;发现B一引用A&#xff0c;在B项目的引用下面A就多了个黄色感叹号&#xff0c;一编译B项目&am…

网工内推 | 上市公司网工,最高30K,思科认证优先,多次晋升机会

01 牧原股份 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1、负责公司及下属子公司办公网络及IOT网络架构规划、设计、重大网络变更评审或实施及重大疑难问题处理&#xff1b; 2、负责公司网络运维监控体系、自动化网络运维及服务体系&#xff0c;并持续优化改进&am…

20240408在全志H3平台的Nano Pi NEO CORE开发板的eMMC刷Ubuntu Core 16.04

20240408在全志H3平台的Nano Pi NEO CORE开发板的eMMC刷Ubuntu Core 16.04 2024/4/8 20:46 参考资料&#xff1a; https://wiki.friendlyelec.com/wiki/index.php/NanoPi_NEO_Core/zh#.E5.AE.89.E8.A3.85.E7.B3.BB.E7.BB.9F [ OK ] Created slice Slice /system/getty. [ …

arm 的CoreLink 是什么?

ARM的CoreLink是一套由ARM公司开发的系统互连IP解决方案&#xff0c;旨在为片上系统&#xff08;SoC&#xff09;提供高性能和高效率的互连架构。CoreLink系列包括多种技术和组件&#xff0c;每个都针对特定的系统设计需求进行了优化。以下是CoreLink系列的一些关键组件及其使用…

代码随想录Day48

Day 48 动态规划part09 今日任务 198.打家劫舍213.打家劫舍II337.打家劫舍III 代码实现 基础打家劫舍 class Solution {public static int rob(int[] nums) {if (nums null || nums.length 0) return 0;if (nums.length 1) return nums[0];int[] dp new int[nums.leng…

获取淘宝销量API商品详情页原数据APP接口:测试key获取(含测试链接)

淘宝/天猫获得淘宝app商品详情原数据 API 返回值说明 item_get_app-获得淘宝app商品详情原数据 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地…

注入类型(一)

一、整数类型 1 and 11 # 1 or 11 -- 二、字符串类型 1 and 11 -- 1 and 11 # 三、搜素类型 搜索型注入&#xff0c;需要额外的考虑后面的问题 总结&#xff1a; 前闭合 " ) ") % %" 无 后闭合 " ( (" % …

百度松果菁英班——机器学习实践五:明星图片爬取

飞桨AI Studio星河社区-人工智能学习与实训社区 &#x1f96a;图片爬取 import requests import os import urllib ​ class GetImage():def __init__(self,keyword大雁,paginator1):# self.url: 链接头self.url http://image.baidu.com/search/acjson?self.headers {User…

Linux安装并配置Miniconda

miniconda官方文档&#xff1a; Miniconda — Anaconda 文档 官方文档中有讲到怎么安装Miniconda&#xff0c;如下&#xff1a; 以下是我得出的经验&#xff1a; 1. 新建新目录并下载和安装miniconda&#xff08;安装过程中&#xff0c;当提示是否继续时&#xff0c;一直按回…

蓝桥杯22年javaB组省赛真题

22年java_b组题目解析 写该博客既是为了分享题目解法&#xff0c;也是对之前写的题复习&#xff0c;毕竟已经24年了&#xff0c;写22年的题解 233&#x1f92d; 文章目录 22年java_b组题目解析A.星期计算(填空题)B.山&#xff08;填空题&#xff09;C.字符统计&#xff08;编…

day75 js 正则表达式 window对象轮播图片调用定时器

一 正则表达式: RegExp 对象: 对字符串执行模式匹配的强大工具。 1 创建正则表达式对象 let reg /模式/修饰符 修饰符 attributes 是一个可选的字符串&#xff0c;包含属性 "g"、"i" 和 "m"&#xff0c; …

Azure的VFP和虚拟IP地址

Azure 的Virtual filtering platform (VFP) 是Azure 网络地址转换,端口转换和端口分配的基础。 下面我们来深入介绍一下VFP的工作方式。 VFP的出站动作。 对于客户端地址作为虚拟IP的出站目的地址的时候,VFP 驱动会负责做以下两个动作。 源地址转换。端口地址转换。VFP 和 S…

20240325-1-HMM

HMM 直观理解 马尔可夫链&#xff08;英语&#xff1a;Markov chain&#xff09;&#xff0c;又称离散时间马尔可夫链&#xff08;discrete-time Markov chain&#xff0c;缩写为DTMC&#xff09;&#xff0c;因俄国数学家安德烈马尔可夫&#xff08;俄语&#xff1a;Андре…

【C++进阶】用哈希实现unordered_set和unordered_map的模拟

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;c大冒险 总有光环在陨落&#xff0c;总有新星在闪烁 前言&#xff1a; 之前我…

H5移动端 Vue3 + vue-virtual-scroller 实现长列表性能优化

文章目录 安装 vue-virtual-scroller引入&#x1f4e2;注意事项使用基础使用上拉加载下拉刷新 移动端在渲染长列表时 大量dom节点的渲染和重绘重排会导致页面卡顿、滚动不流畅、设备耗电加快、影响移动设备电池寿命等性能问题 这里分享使用【虚拟滚动】方案进行长列表优化&…

【C++ STL算法】sort 排序

文章目录 【 1. 基本原理 】【 2. sort 的应用 】实例 - sort 函数实现 升序排序和降序排序 函数名用法sort (first, last)基于 快速排序&#xff0c;对容器或普通数组中 [ first, last ) 范围内的元素进行排序&#xff0c;默认进行升序排序&#xff08;从小到大&#xff09;。…

2024年面试AI编译器岗经验总结

面试经历: 面试中必备的知识: 1.用C++实现一个卷积 (图解)一步一步使用CPP实现深度学习中的卷积 - GiantPandaCVGiantPandaCVhttp://giantpandacv.com/academic/%E7%AE%97%E6%B3%95%E7%A7%91%E6%99%AE/%E5%B0%BD%E8%A7%88%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E…