AVR - GNU 链接器脚本 - 如何获取 .data 部分的加载地址
Posted
技术标签:
【中文标题】AVR - GNU 链接器脚本 - 如何获取 .data 部分的加载地址【英文标题】:AVR - GNU linker script - How to get the load address of .data section 【发布时间】:2021-10-10 16:40:09 【问题描述】:我对 GNU 链接器脚本很陌生。想要为 AVR MCU 创建一个裸机(没有avr-libc
)应用程序。在项目的早期阶段,我不需要初始化 .data
部分。但现在我需要它。
我当前的链接器脚本:
OUTPUT_FORMAT(elf32-avr)
OUTPUT_ARCH(avr51)
ENTRY(_start)
MEMORY
FLASH_APP (rx) : ORIGIN = 0x00000000, LENGTH = 120K
FLASH_BOOT (rx) : ORIGIN = 0x0001E000, LENGTH = 8K
SRAM (rw) : ORIGIN = 0x00800100, LENGTH = 16K
STACK_SIZE = 4K;
SECTIONS
.text :
_text_s = .;
KEEP(*(.isr_vector))
*(.text)
*(.text*)
_text_e = .;
> FLASH_BOOT
.rodata :
. = ALIGN(2);
_rodata_s = .;
*(.rodata)
*(.rodata*)
_rodata_e = .;
. = ALIGN(2);
> FLASH_BOOT
.data :
. = ALIGN(2);
_data_s = .;
*(.data)
*(.data*)
_data_e = .;
. = ALIGN(2);
> SRAM AT > FLASH_BOOT
.bss (NOLOAD):
. = ALIGN(2);
_bss_s = .;
*(.bss)
*(.bss*)
*(COMMON)
_bss_e = .;
> SRAM
HEAP_SIZE = (ORIGIN(SRAM) + LENGTH(SRAM)) - _heap_s - STACK_SIZE;
.heap (NOLOAD):
. = ALIGN(2);
_heap_s = .;
. = . + HEAP_SIZE;
_heap_e = .;
> SRAM
.stack (NOLOAD):
. = ALIGN(2);
_stack_s = .;
. = . + STACK_SIZE;
_stack_e = .;
> SRAM
对于.bss
部分,我在链接描述文件中使用符号,我在汇编中使用它来将.bss
部分归零。我编写这些函数是为了从.bss
部分获取开始和结束:
/* Get .bss start */
FUNCTION(asm_self_get_bss_s)
ldi r24, lo8(_bss_s)
ldi r25, hi8(_bss_s)
ret
/* Get .bss end */
FUNCTION(asm_self_get_bss_e)
ldi r24, lo8(_bss_e)
ldi r25, hi8(_bss_e)
ret
如何获取链接描述文件中.data
部分的加载地址(FLASH)以从SRAM 中的FLASH 复制(初始化)数据?我的链接器脚本中的符号 _data_s
和 _data_e
返回 SRAM 地址。但是我怎样才能从 FLASH 中得到地址呢? GNU-ld 是否有特殊功能?
【问题讨论】:
【参考方案1】:我找到了解决办法。
LOADADDR()
是从链接描述文件中的.data
部分获取加载地址的正确函数。
加载地址(部分) 返回命名节的绝对加载地址。这通常与 ADDR 相同,但如果 AT 关键字可能会有所不同 在节定义中使用(请参阅节可选节 属性)。
Quote from GNU linker manual
以下内容现在适用于我的改进链接器脚本:
.data :
. = ALIGN(2);
_data_s_load = LOADADDR(.data);
_data_s = .;
*(.data)
*(.data*)
_data_e = .;
. = ALIGN(2);
> SRAM AT > FLASH_BOOT
以及具体的组装功能:
/* Get .data start */
FUNCTION(asm_self_get_data_s)
ldi r24, lo8(_data_s)
ldi r25, hi8(_data_s)
ret
/* Get .data end */
FUNCTION(asm_self_get_data_e)
ldi r24, lo8(_data_e)
ldi r25, hi8(_data_e)
ret
/* Get .data start (load address) */
FUNCTION(asm_self_get_data_s_load)
ldi r22, lo8(_data_s_load)
ldi r23, hi8(_data_s_load)
ldi r24, hh8(_data_s_load)
eor r25, r25
ret
我现在可以使用指令elpm
将数据从FLASH 复制(初始化)到SRAM。
【讨论】:
以上是关于AVR - GNU 链接器脚本 - 如何获取 .data 部分的加载地址的主要内容,如果未能解决你的问题,请参考以下文章