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 будет перезаписан хост-приложением.
@Dankó Dávid, 👍2
Обсуждение1 ответ
Лучший ответ:
Я пробовал этот код с 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 означает удалить только указанный раздел(ы)
- программирование ардуино на чистом с
- Как создать и загрузить программу на C++ без библиотеки Arduino или IDE?
- avr-gcc -D игнорируется
- Поскольку double и float представляют один и тот же тип данных (обычно), что предпочтительнее?
- avr/io.h ошибка "No such file or directory" при компиляции с использованием avr-gcc
- Как включить библиотеки Arduino с помощью AVR-gcc без IDE?
- Arduino EEPROM сохраняет старые данные после прошивки новой программой
- AVRdude неправильно считывает значения байтов предохранителя
Примечание:
app_start
не будет вызываться, даже если я позвоню напрямую (вызов app_start() показан в комментарии вместо asm «вызов 0xFA0»), @Dankó DávidВы имеете в виду
-o ubb.elf
?, @Edgar Bonetно рассматриваемая версия с вызовом app_start из main работает?, @Juraj
Нет, вызов
app_start
напрямую изmain
тоже не работает., @Dankó Dávidubb.o
:.elf
и.o
— это просто окончания файлов.file ubb.o
говорит:ubb.o: 32-битный исполняемый файл ELF LSB, 8-битный Atmel AVR, версия 1 (SYSV) , статически связанный, не разделенный
., @Dankó DávidВаша программа отлично работает на моем Uno., @Edgar Bonet