Программирование Arduino на ассемблере: ничего не происходит

Привет, сообщество StackOverflow,

Я пытаюсь запрограммировать свою старую плату Arduino Duemilanove (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;
}

Ассемблерный дамп компилятора приводит к (сокращенно),

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

который работает и активирует светодиод на выводе 13 Arduino (вывод AVR PB5).

Но когда я использую этот ассемблерный файл,

// 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

что может объяснить, почему ничего не происходит.

Кроме того, здесь находятся make-файлы для 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

(Извините за форматирование) Любая идея, откуда эта ошибка?


person Sojaki    schedule 22.01.2013    source источник
comment
Очевидно, что DDRB и PORTB в вашем файле сборки разрешаются по-разному, поэтому, возможно, вы используете неправильную версию io.h, где они предположительно определены?   -  person 500 - Internal Server Error    schedule 22.01.2013
comment
Я только что добавил #define __SFR_OFFSET 0x00 в начало моего исходного файла на ассемблере. В ассемблерном дампе показывает теперь out ((0x04) + 0x00), r24 и out ((0x05) + 0x00), r24 и работает.   -  person Sojaki    schedule 23.01.2013


Ответы (1)


Вы должны использовать вспомогательные макросы _SFR_IO_ADDR() и _SFR_MEM_ADDR() для доступа к SFR с использованием инструкций ввода-вывода и памяти соответственно, потому что они имеют разные адреса в двух пространствах имен. По умолчанию, по-видимому, отображается память, но не рассчитывайте на это.

Таким образом, ваш код может выглядеть так:

#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
person Jester    schedule 22.01.2013