在没有avr-libc的情况下将数据存储在RAM中。如何使用自定义链接描述文件和初始化代码配置正确的内存部分?

时间:2013-07-08 06:34:25

标签: memory avr avr-gcc sections

这是我的链接器脚本:

MEMORY {

  text   (rx)   : ORIGIN = 0x000000, LENGTH = 64K

  data   (rw!x) : ORIGIN = 0x800100, LENGTH = 0xFFA0

}

SECTIONS {

    .vectors : AT (0x0000) { entry.o (.vectors); }

    .text    : AT (ADDR (.vectors) + SIZEOF(.vectors)) { * (.text.startup); * (.text); * (.progmem.data); _etext = .; }

    .data    : AT (ADDR (.text) + SIZEOF (.text)) { PROVIDE (__data_start = .); * (.data); * (.rodata); * (.rodata.str1.1); PROVIDE (__data_end = .); } > data

    .bss     : AT (ADDR (.bss)) { PROVIDE (__bss_start = .); * (.bss); PROVIDE (__bss_end = .); } > data

    __data_load_start = LOADADDR(.data);

    __data_load_end = __data_load_start + SIZEOF(.data);

}

这是我的初始化代码。重置时调用init

.section .text,"ax",@progbits

/* Handle low level hardware initialization. */

.global init

init:                       eor r1, r1

                            out 0x3f, r1

                            ldi r28, 0xFF

                            ldi r29, 0x02

                            out 0x3e, r29

                            out 0x3d, r28

                            rjmp __do_copy_data

                            rjmp __do_clear_bss

                            jmp main

/* Handle copying data into RAM. */

.global __do_copy_data

__do_copy_data:             ldi r17, hi8(__data_end)

                            ldi r26, lo8(__data_start)

                            ldi r27, hi8(__data_start)

                            ldi r30, lo8(__data_load_start)

                            ldi r31, hi8(__data_load_start)

                            rjmp .L__do_copy_data_start

.L__do_copy_data_loop:      lpm r0, Z+

                            st X+, r0

.L__do_copy_data_start:     cpi r26, lo8(__data_end)

                            cpc r27, r17

                            brne .L__do_copy_data_loop

                            rjmp main

/* Handle clearing the BSS. */

.global __do_clear_bss

__do_clear_bss:             ldi r17, hi8(__bss_end)

                            ldi r26, lo8(__bss_start)

                            ldi r27, hi8(__bss_start)

                            rjmp .L__do_clear_bss_start

.L__do_clear_bss_loop:      st X+, r1

.L__do_clear_bss_start:     cpi r26, lo8(__bss_end)

                            cpc r27, r17

                            brne .L__do_clear_bss_loop

问题是初始化代码在复制过程中会暂停。这是我的符号表的编辑转储,如果它对任何人都有帮助。

00000000 a __tmp_reg__
...
00000000 t reset
...
00000001 a __zero_reg__
...
0000003d a __SP_L__
...
00000074 T main
0000009a T init
000000ae T __do_copy_data
000000c6 T __do_clear_bss
...
00000446 A __data_load_start
00000446 T _etext
0000045b A __data_load_end
00800100 D __data_start
00800100 D myint
00800115 B __bss_start
00800115 D __data_end
00800115 b foobar.1671
00800135 B ticks
00800139 B __bss_end

3 个答案:

答案 0 :(得分:3)

C旨在用于冯·诺依曼架构。 AVR是以哈佛为基础的。这意味着C期望字符串在RAM中。因此,如果您查看最终将作为十六进制复制到AVR芯片的任何elf二进制文件的反汇编,您将看到两个部分:__do_copy_data__do_clear_bss [需要时] ]。这些例程在链接阶段添加,可以满足C语言的基本需求。因此,您在指针中看到的可能是指向错误的地址。换句话说,它们要么指向程序空间中的地址,要么是从数据空间[不同的地址总线]读取。或者你是故意从数据空间读取但没有复制字符串。

请参阅:

avr/pgmspace.h FAQ: ROM Array and scroll down for strings 当然,Atmel提供的AVR指令集,特别是将程序存储器复制到数据存储器的指令

编辑以反映新问题和评论:您对两个部分的汇编看起来都不错。我将不得不仔细查看您的链接器脚本,以检查是否有任何有趣的业务。既然你正在编写一个引导加载程序,你介意我问你是否看过bootloader support on AVR-libc

答案 1 :(得分:0)

http://deans-avr-tutorials.googlecode.com/svn/trunk/Progmem/Output/Progmem.pdf 本文档可能有助于澄清AVR的闪存/ RAM存储器的使用。

答案 2 :(得分:0)

我实际上已经开始工作了。我所要做的就是在SREG中启用读写外部RAM的功能。我知道,这很明显和简单,但它被埋没在数据表中,并且记录很少。

这个资源很有帮助,但我的芯片没有任何文档。如果您遇到此问题,请查看AVR的数据表并查看其相关性。对于AVR的所有变体,该过程并不相同。

How to use external RAM.