AVR-GCC не может вызвать функцию, расположенную по фиксированному адресу

Я написал следующий код:

#include <avr/io.h>

__attribute__((noinline, section(".app_start"))) void app_start() //секция app_start начинается с 0xFA0
{
    //register_packet_dispatch(packet_received);
    PORTB = 0xFF;
}

__attribute__ ((noinline)) void call_app()
{
    asm ("call 0xFA0\nret");
    //приложение_start();
}

int main()
{
    DDRB = 0xFF;
    //вызов_приложение();
    app_start();
    while(1){}
}

Что я скомпилировал:

avr-gcc -Wl,--section-start=.reg_dispatch=0xdac -Wl,--section-start=.app_start=0xFA0 -mmcu=atmega328p -Os -o ubb.o ub_bootloader.cpp -DF_CPU=16000000

Который пытается имитировать хост-приложение, которое пытается вызвать перемещенное клиентское приложение, начинается с адреса 4000 (0xFA0). Если это сработает, загорится светодиод, подключенный к 13-му контакту Arduino. Но почему app_start не вызывается?

Я также проверил выходную сборку:

avr-objcopy -j .text -j .data -O ihex ubb.o ubb.hex

00000fa0 <_Z9app_startv>:
 fa0:   8f ef           ldi r24, 0xFF   ; 255
 fa2:   85 b9           out 0x05, r24   ; 5
 fa4:   08 95           ret

00000080 <main>:
  80:   8f ef           ldi r24, 0xFF   ; 255
  82:   84 b9           out 0x04, r24   ; 4
  84:   0e 94 d0 07     call    0xfa0   ; 0xfa0 <_Z9app_startv>
  88:   ff cf           rjmp    .-2         ; 0x88 <main+0x8>

Вроде все правильно, почему вообще не работает? Конечно, если я удалю атрибут noinline, это сработает. Но это мираж, компилятор встраивает содержимое функции, но когда я встрою это в приложение, код после адреса 0xFA0 будет перезаписан хост-приложением.

, 👍2

Обсуждение

Примечание: app_start не будет вызываться, даже если я позвоню напрямую (вызов app_start() показан в комментарии вместо asm «вызов 0xFA0»), @Dankó Dávid

Вы имеете в виду -o ubb.elf?, @Edgar Bonet

но рассматриваемая версия с вызовом app_start из main работает?, @Juraj

Нет, вызов app_start напрямую из main тоже не работает., @Dankó Dávid

ubb.o: .elf и .o — это просто окончания файлов. file ubb.o говорит: ubb.o: 32-битный исполняемый файл ELF LSB, 8-битный Atmel AVR, версия 1 (SYSV) , статически связанный, не разделенный., @Dankó Dávid

Ваша программа отлично работает на моем Uno., @Edgar Bonet


1 ответ


Лучший ответ:

3

Я пробовал этот код с arduino, и он работал (я учил, конечно, что я не могу добавить флаг "-Wl,--section-start=.app_start=0xFA0" в процесс компиляции, поэтому функция не перенесу в другой раздел) Поэтому я настроил IDE arudino так, чтобы отображалась каждая команда от компиляции до конца процесса загрузки.

Проблема заключается в использовании avr-objdump, который я где-то нашел и использовал без просмотра переключателей CLI.

Я тоже допустил ошибку, когда задавал вопрос. Чтобы дизассемблировать объектный файл, правильная команда:

avr-objdump -S --disassemble  ubb.o > ubb.asm

Команда, которую я использовал для создания шестнадцатеричного файла:

avr-objcopy -j .text -j .data -O ihex ubb.o ubb.hex

Рабочий (взято из arduino):

avr-objcopy -O ihex -R .eeprom ubb.o ubb.hex

-j означает оставить только заданный раздел(ы)

пока

-R означает удалить только указанный раздел(ы)

,