5

最初にいくつかの背景。avr tiny では、データはレジスタ、sram、eeprom、またはプログラム空間に格納できます。レジスタと sram は揮発性ストレージですが、eeprom とプログラム空間はそうではありません。(つまり、電源が入っていなくてもデータは残ります。)

(avr-gcc ライブラリを使用して) c でプログラミングする場合、典型的なコードは次のようになります。

#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 から intel .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) はどのように初期化されるのでしょうか?
答えは、メインの前のルーチンによるものです。

sram に格納する必要があるデータは、プログラム空間のアドレス 0x5a にあります。次の方法で sram に挿入します。

  1. x レジスタの上位バイトと下位バイトは、sram 内のデータを配置するアドレス (0x60) に設定されます。このアドレスはプログラム メモリではなく、データ メモリ内にあることに注意してください。
  2. z レジスタも同様ですが、データがプログラム空間 (0x5a) 内にあるアドレスを使用します。
  3. z レジスタに格納されているアドレスのプログラム メモリの内容は、lpm オペコードを介してレジスタ r0 にロードされます。z レジスタ値は、sram にロードする次のデータ (最終的に、ここではなし) を指すようにインクリメントされることに注意してください。
  4. r0 のデータは、sram の x レジスタに格納されているアドレスに格納されます。
  5. sram にあるはずのすべてのデータが初期化されるまで繰り返します。

これは、メインへの rcall の前に発生します。

より良い/より明確な答えはありますか?

4

2 に答える 2

2

そうです、gnu ツールの世界では、確かに他のツールと同様の方法です。

リンカーには .text、.data、.bss データが与えられ、バイナリに配置する必要があります。フラッシュ ベースのシステムの場合、avr に固有のものはなく、すべてのプラットフォームで同じです。すべての不揮発性情報はフラッシュ上にある必要があります。リンカ スクリプトは、.data セグメントに 2 つのホームがあり、1 つのホームはフラッシュ内の .text とその他のもので固定され、次に RAM アドレス空間にホームがあることをリンカに伝えます。リンカーがブート コード (main を呼び出す asm) の外部変数に入力するいくつかのキーワードを使用して、リンカー スクリプトを作成します。このコードは、main を呼び出す前にこれらの変数を使用して .data を ram にコピーし、.bss をゼロにして、C 言語の仮定 (初期化された変数はゼロであり、初期化された変数はコードで初期化されたものです) を行います。

于 2012-06-08T03:23:30.407 に答える
-1

SRAM にデータが必要な場合は、プログラムでデータをそこに配置する必要があります。

そこ、あなたのためにそれをしました。

于 2012-06-08T02:05:19.780 に答える