И ещё пример.
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено ReAl 21 августа 2003 г. 16:49
В ответ на: В чем идея создания сегментов у IAR, Почему бы линковщику не сгенирить весь код в одном сегменте, зачем нужно распределять данные в один сегмент код в другой , прерывания в третий. В чем преимущество? отправлено JTAG 21 августа 2003 г. 14:57

Сегменты из разных файлов с одинаковым именем сшиваются в один (это я так, напоминаю) непрерывный кусок. Порядком сегментов можно управлять.
Если теперь сделать сегменты initstart init initend, в initstart-е сложить стандартную начальную инициализацию, init разрешить задавать всем файлам, initend опять в файле-"запускалке" - окончание инициализации и переход на главный код.
Если теперь


; запускалка
.section initstart
что-то поделали

.section initend
sei ; открыли все прерывания
jmp main

; файл работы с uart
.section init
инициализируем SFR уарта, взводим бит разрешения его
прерываний (но общим битом они ещё запрещены)

.section .text
а тут функции работы с уартом

; файл с системными часами и т.п.
.section init
аналогично, как выше
.section .text

После линковки код будет объединён так:


.initstart из запускали
.init из uart.asm
.init из systmr.asm
.initend из запускалки ; только тут разрешены прерывания
.text из uart.asm
.text из systmr.asm
.text из main.asm

Т.е. по окончании кода initstart без никаких переходов (они слитно расположены!) будет выполнен код init из всех файлов, потом код initend
Итого ещё до самой main будет выполнен весь инициализационный код, в начале main не надо ставить кучу

call inituart
call initsystmr
...

В GCC это можно делать и на уровне С:

// setup_io must be "called" _after_ .init2
// because of __zero_reg__ cleared in .init2
void setup_io(void) __attribute__ ((section(".init3"))) __attribute__ ((naked));
void setup_io(void)
{
OSCCAL = __LPM(&osccal_value);
DDRB = 0x0E; // IR_PULSE, OC1B, SCK, DO - outputs
PORTB = 0xF6; // SCK, DO high, DI w/o pull-up
DDRA = 0x61; // LEDS, PULSE, DF_SELECT - outputs,
// XJ4,XJ5 - input w/o pull-up
PORTA = 0x09;
ACSR = (1 << ACD); // disable analog comparator
TIMSK = 0;
TCCR0 = 1 << CS00; // CK, 32us overflow
}

naked - функция оформляется без пролога и эпилога, читсый код.
Этот код запихивается в секцию .init3 (у avrgcc толпа секций инициализации, свою можно втиснуть на разных этапах).
Итого данная функция вызовется после того, как gcc произвёл начальную инициализацию регистров, но до функции main().

Подобным образом HiTech для PIC (если мне не изменяет память) пришивает небольшие секции со входом и выходом из прерывания к секции кода функции-обработчика прерывания.

Составить ответ  |||  Конференция  |||  Архив

Ответы



Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание  |||  Без кадра

E-mail: info@telesys.ru