简而言之,当微控制器通电时,如何将数据存储在sram中进行初始化?

时间:2012-06-08 01:37:51

标签: assembly avr avr-gcc

首先是一些背景。在微小的数据中,数据可以存储在寄存器,sram,eeprom或程序空间中。寄存器和sram是易失性存储,而eeprom和程序空间则不是。 (即:未通电时数据停留。)

在c中编程时(使用avr-gcc库),典型代码可能如下所示:

#define F_CPU 8000000UL
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>

//This data is put in the eeprom
const uint8_t dat_eeprom EEMEM= 0xab;
//This data is put in the program space
const uint8_t dat_pgm_space PROGMEM= 0xcd;
//This data is stored in the sram
uint8_t dat_sram = 0xef;

int main(){
    while(1){
    ;;
    }
}

编译:

avr-gcc -g -mmcu=attiny44 -o test.elf test.c

从.elf中提取英特尔.hex:

avr-objcopy -j .text -j .data -O ihex test.elf test.hex

我们得到以下test.hex:

:1000000011C023C022C021C020C01FC01EC01DC0FF
:100010001CC01BC01AC019C018C017C016C015C01C
:1000200014C0CD0011241FBECFE5D1E0DEBFCDBF8F
:1000300010E0A0E6B0E0EAE5F0E002C005900D9225
:10004000A236B107D9F702D006C0DACFCF93DF933B
:0A005000CDB7DEB7FFCFF894FFCF65
:02005A00EF00B5
:00000001FF

以下的反汇编:

00000000 <.sec1>:
0:  11 c0           rjmp    .+34        ;  0x24
      <...skipped interrupt vector table...> 
20: 14 c0           rjmp    .+40        ;  0x4a
22: cd 00           .word   0x00cd  ; this is our data stored in the program mem.
24: 11 24           eor r1, r1  
26: 1f be           out 0x3f, r1    ; 63
28: cf e5           ldi r28, 0x5F   ; 95
2a: d1 e0           ldi r29, 0x01   ; 1
2c: de bf           out 0x3e, r29   ; 62
2e: cd bf           out 0x3d, r28   ; 61
30: 10 e0           ldi r17, 0x00   ; 0
32: a0 e6           ldi r26, 0x60   ; X register low byte ; address of dest. in
34: b0 e0           ldi r27, 0x00   ; X register high byte; sram
36: ea e5           ldi r30, 0x5A   ; z register low byte ; address of data in 
38: f0 e0           ldi r31, 0x00   ; z register high byte; program memory
3a: 02 c0           rjmp    .+4         ;  0x40
3c: 05 90           lpm r0, Z+
3e: 0d 92           st  X+, r0
40: a2 36           cpi r26, 0x62   ; 98
42: b1 07           cpc r27, r17
44: d9 f7           brne    .-10        ;  0x3c
          <...skipped rcall to main...>
5a: ef 00           .word   0x00ef  ; this is our data that
                                      should be stored in the sram.

那么我们想要在sram中初始化的数据(0xef)如何? 答案是通过main之前的例行程序。

应该存储在sram中的数据位于程序空间中的地址0x5a处。它以下列方式放入sram中:

  1. x寄存器的高低字节设置为我们要将数据放入sram的地址。(0x60)请注意,该地址不在程序存储器中,而是在数据存储器中。
  2. z寄存器相同,但是数据在程序空间中的地址(0x5a)
  3. 存储在z寄存器中的地址的程序存储器的内容通过lpm操作码加载到寄存器r0中。请注意,z寄存器值会递增以指向要加载到sram中的(最终,此处为none)下一个数据。
  4. 然后将r0中的数据存储在sram中,存储在x寄存器中。
  5. 重复,直到所有应该在sram中的数据都已初始化。
  6. 这发生在到主要的rcall之前。

    有更好/更清楚的答案吗?

2 个答案:

答案 0 :(得分:1)

是的,在gnu工具世界中,当然与其他工具类似。

链接器被赋予.text,.data,.bss数据,并且必须将它放在二进制文件中。对于基于闪存的系统,没有特定于avr,所有平台都相同,所有非易失性信息都必须在闪存上。链接器脚本告诉链接器.data段有两个home,一个home用.text和flash中的其他任何东西加上,然后是ram地址空间中的home。您可以使用链接器将填充到引导代码中的外部变量(调用main的asm)中的一些关键字来制作链接描述文件。此代码使用这些变量将.data复制到ram并在调用main之前清零.bss以便C语言假设(单元化变量为零,初始化变量是您的代码初始化它们的内容)。如果您编写代码以便永远不会假设变量在main之前被初始化,则您不必执行任何操作,您的pre-main init代码可以简单地设置堆栈指针并分支到main。

答案 1 :(得分:-1)

如果你想要SRAM中的数据,你的程序必须把它放在那里。

那里,为你做了那件事。