【问题标题】:AVR - GNU linker script - How to get the load address of .data sectionAVR - GNU 链接器脚本 - 如何获取 .data 部分的加载地址
【发布时间】: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 是否有特殊功能?

【问题讨论】:

    标签: assembly avr bare-metal linker-scripts


    【解决方案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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 2015-07-31
      相关资源
      最近更新 更多