Cepгeй Бopщ (21.01.2012 15:15 - 15:26, просмотров: 151) ответил Точка опоры из дому на Я ещё только учусь, поэтому никак не могу победить Си. Имеется некий "черный ящик" в памяти программ, а именно - начальный загрузчик. О нём известно несколько точек входа в подпрограммы и регистры процессора принимающие данные и
GCC позволяет это сделать очень красиво и эффективно. Он позволяет объяснить компилятору, что функция принимает параметры в конкретных регистрах и в конкретных отдает, и компилятор строит код с учетом этого. inline uint16_t driver::serial_no()
{
// drv_serial_no возвращает результат в R16:R17
register uint16_t result asm ("r16");
asm volatile
(
" RCALL drv_serial_no\n\t"
: "=r" (result)
:
);
return result;
}
inline void driver::rf::init(uint16_t coeff)
{
// drv_synth_init ожидает параметр в R16:R17 и портит их содержимое
register uint16_t Tmp asm("r16");
Tmp = coeff;
asm volatile
(
" RCALL drv_synth_init\n "
:"+r" (Tmp)
);
}
inline void driver::rrt::send(void const * data, uint8_t size)
{
// drv_rrt_send ожидает указатель в R30:R31, размер в R16 и портит их содержимое
register void const * Src asm("r30");
register uint8_t Size asm("r16");
Src = data;
Size = size;
asm volatile
(
" RCALL drv_rrt_send\n\t"
:"+r" (Src), "+r" (Size)
);
}
Адреса функций прописываются в скрипте линкера
drv_serial_no = 0x1832;
drv_rrt_send = 0x1838;
drv_synth_init = 0x183A;
либо в командной строке линкера:
LDFLAGS += -Wl,--defsym,drv_serial_no=0x1832
LDFLAGS += -Wl,--defsym,drv_rrt_send=0x1838
LDFLAGS += -Wl,--defsym,drv_synth_init=0x183A
Вам надо будет почитать по поводу constrains асмовых вставок, там выбирая '+' '=' и '' можно еще объяснить, что функция не портит входные параметры и тогда компилятор не будет обновлять их при вызове функции в цикле. В общем штука довольно мощная, но надо почитать доку. В комплектк WinAVR это описано в доке на avr-libc в файле с названием чего-то-там-inline-чего-то-там.html
А, ну и если функция не требует параметров или параметры передаются в соответствии с принятым в gcc соглашнеии о вызовах, то тогда в заголовочном файле пишем extern void Bootloader(); а в командной строке линкера
LDFLAGS += -Wl,--defsym,BootLoader=0x1800