3

こんにちはStackOverflowコミュニティ、

古いArduinoDuemilanoveボード(Atmega 168V-10PU)をアセンブラーでプログラムしようとしています。以前に数回試しましたが、コードが実行されないたびに。だから私はCで同等のテストプログラムをプログラムしようとしました、そしてそれはうまくいきました。ここにあります:

// file led.c
#include <avr/io.h>

int main(void)
{

    DDRB = 0xFF;
    PORTB = 0xFF;

    while (1) {
        asm("nop\n");
    }

    return 0;
}

コンパイラのasmダンプは、(短縮された)結果になります。

ldi r24,lo8(-1)  ;  tmp44,
out 0x4,r24  ;  MEM[(volatile uint8_t *)36B], tmp44
out 0x5,r24  ;  MEM[(volatile uint8_t *)37B], tmp44

これは、Arduinoピン13(AVRピンPB5)でLEDを作動させてアクティブにします。

しかし、このasmファイルを使用すると、

// file led.S
#include "avr/io.h"

.global main

main:
    ldi r24, 0xFF
    out DDRB, r24
    out PORTB, r24

 end:
    jmp end

コンパイラのダンプの結果は(短縮)、

ldi r24, 0xFF
out ((0x04) + 0x20), r24
out ((0x05) + 0x20), r24

何が起こらないのか説明できるかもしれません。

さらに、Cバージョンアセンブラーバージョンのメイクファイルもあります

助けてくれてありがとう!

編集: Cバージョンアセンブラーバージョンの完全なアセンブラーダンプファイルもあります

編集2:インクルードファイルiom168.hでレジスタアドレスを検索しました。このファイルは、iomx8.hを参照しています#define PORTB _SFR_IO8 (0x05)。コンパイラはインクルードチェーンに従います

io.h -> iom168.h -> iomx8.h
io.h -> common.h -> sfr_defs.h

sfr_defs.hには次のように記述されています。

#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)

オフセットが定義されているのは、さらに数行上です。

#ifndef __SFR_OFFSET
/* Define as 0 before including this file for compatibility with old asm
sources that don't subtract __SFR_OFFSET from symbolic I/O addresses.  */
#  if __AVR_ARCH__ >= 100
#    define __SFR_OFFSET 0x00
#  else
#    define __SFR_OFFSET 0x20
#  endif
#endif

(フォーマットして申し訳ありません)このエラーの原因は何ですか?

4

1 に答える 1

5

ヘルパー マクロ_SFR_IO_ADDR()を使用して、 _SFR_MEM_ADDR()SFR にアクセスするには、それぞれ i/o 命令とメモリ命令を使用する必要があります。これらは 2 つの名前空間で異なるアドレスを持っているためです。デフォルトは明らかにメモリマップされていますが、それを当てにしないでください。

そのため、コードは次のようになります。

#include "avr/io.h"

.global main

main:
    ldi r24, 0xFF
    out _SFR_IO_ADDR(DDRB), r24
    out _SFR_IO_ADDR(PORTB), r24

 end:
    jmp end

または、メモリ マップド アクセスに切り替えることもできます。

#include "avr/io.h"

.global main

main:
    ldi r24, 0xFF
    sts _SFR_MEM_ADDR(DDRB), r24
    sts _SFR_MEM_ADDR(PORTB), r24

 end:
    jmp end
于 2013-01-22T18:15:51.157 に答える