clear_table&copy_table使用解析(以TC275为例)
本文最后更新于6 天前,其中的信息可能已经过时,如有错误请留言评论。

一、.bss段.data段 的启动初始化机制解析

  1. 两种段的区别与特性
段名用途是否占ROM空间是否占RAM空间初始化方式
.bss未初始化的全局/静态变量❌ 不占ROM✅ 占用RAM启动时清0(memset)
.data已初始化的全局/静态变量✅ 初值存在ROM✅ 占用RAM启动时从ROM复制到RAM

.rodata 与栈变量说明:

  • .rodata:只读常量(如 conststatic const),常驻ROM。
  • 栈变量(局部变量):程序运行时动态分配,位于栈(Stack)中,不占ROM。

二、启动代码初始化原理

在TC275启动流程中,函数 Ifx_C_Init() 完成 .bss 清零与 .data 段的复制。该函数通常由 _Core0_start() 调用:

void _Core0_start(void)
{
    ...
    Ifx_C_Init();  // 初始化 .data 和 .bss 段
    ...
    __non_return_call(core0_main);
}

三、关键函数 Ifx_C_Init() 实现分析

extern uint32 __clear_table[];
extern uint32 __copy_table[];

.bss段 清零操作

while (pTable)
{
    pDest = (uint32*)*pTable++;     // RAM地址
    length = *pTable++;             // 字节数
    if (length == 0xFFFFFFFF) break;

    memset(pDest, 0, length);       // 实际逻辑简化为清0
}

.data段 复制操作

while (pTable)
{
    pSrc  = (uint32*)*pTable++;     // ROM地址(初值)
    pDest = (uint32*)*pTable++;     // RAM地址
    length = *pTable++;             // 字节数
    if (length == 0xFFFFFFFF) break;

    memcpy(pDest, pSrc, length);    // 实际逻辑简化为内存复制
}

四、这些地址和长度是从哪里来的?

ld链接脚本(Linker Script)中定义的 __clear_table__copy_table

.rodata : FLAGS(arl)
{
    *(.rodata*)
    ...

    // 清零表(.bss段)
    PROVIDE(__clear_table = .);
    LONG(ADDR(.bss)); LONG(SIZEOF(.bss));
    ...
    LONG(-1); LONG(-1);  // 终止标志

    // 复制表(.data段)
    PROVIDE(__copy_table = .);
    LONG(LOADADDR(.data)); LONG(ADDR(.data)); LONG(SIZEOF(.data));
    ...
    LONG(-1); LONG(-1); LONG(-1);  // 终止标志
}

LOADADDR(.data):获取段的ROM地址(初值存放地址)
ADDR(.data):段的RAM运行地址
SIZEOF(.data):段的大小

五、如何将函数放入 RAM 执行(可执行代码段搬移)

  • #pragma section 指定段名
#pragma section ".my_ram_fun" ax
void fast_func(void) { ... }
#pragma section
  • 在链接脚本中定义此段及其复制行为
.CPU0.psram_text :
{
    . = ALIGN(8);
    *(.my_ram_fun*)
} > RAM_PSRAM AT> ROM_FLASH
	CORE_SEC(.psram_text)  : 
	{
	    . = ALIGN(8);
	    *(.my_ram_fun)
	} > RAM_PSRAM AT> ROM_FLASH

上边两段 Linker Script 的写法在表达相似意图——将 .my_ram_fun段内容链接到 RAM_PSRAM 段,但存在一些关键语法和行为差异

  • CORE_SEC(...) 是某些多核支持的链接脚本宏/语法(比如 TI C2000 / Infineon AURIX 系列工具链)中,用于生成核特定的段,并带有访问权限标记(FLAGS(awx) 表示 可读写、可执行)。
  • .CPU1.psram_text1 是普通的段名,自定义的 Section,直接定义而已。

所以,CORE_SEC(...) 通常是编译器工具链扩展语法,用于支持多核链接;而 .CPU1.psram_text1 是标准 GNU Linker Script 的命名段。

  • .rodata 段中加入该段对应的 copy_table 项:
LONG(LOADADDR(.CPU0.psram_text)); 
LONG(ADDR(.CPU0.psram_text)); 
LONG(SIZEOF(.CPU0.psram_text));

程序启动时就会自动从 ROM 复制此函数到 RAM 中运行。

六、总结:__clear_table__copy_table 的作用

表名功能定义位置启动操作
__clear_table清零 .bssLinker Script将目标地址内存清0
__copy_table复制 .data 段等段Linker Script将数据从 ROM 拷贝到 RAM 初始化

七、内存初始化流程图

A[上电复位]
A –> B[执行 _Core0_start()]
B –> C[调用 Ifx_C_Init()]
C –> D[读取 __clear_table]
D –> E[清空.bss段的RAM空间 (memset)]
C –> F[读取 __copy_table]
F –> G[从ROM读取.data初值]
G –> H[拷贝到RAM指定地址]
H –> I[执行 main()]

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇