Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
266
Добавлен:
23.03.2016
Размер:
308.57 Кб
Скачать

СПРАВОЧНЫЙ МАТЕРИАЛ

 

 

 

Роман Абраш

Книга по работе

 

 

 

 

 

 

 

 

 

 

 

 

 

 

г. Новочеркасск

с WinAVR и AVR Studio

 

 

 

E-mail: arv@radioliga.com

 

 

 

 

 

 

программе пользователя. Наличие этого

 

Макросы-функции, определен-

 

 

 

Продолжение.

 

 

 

 

 

 

макроса дает указание компоновщику раз-

 

ные в модуле

 

 

 

Начало в №1-12/2010

 

 

 

 

 

 

местить соответствующий объект в строго

 

Так как большинство макросов выпол-

 

 

 

 

 

определенной области памяти, соответ-

 

нены в виде макросов-функций, далее они

 

AVR-СПЕЦИФИЧНЫЕ МОДУЛИ

ственно требованиям используемого мик-

 

будут рассмотрены без упоминания того,

 

К специфичным для AVR относятся мо-

роконтроллера.

 

что это не функции на самом деле.

 

 

дули, реализующие ряд функций, выполне-

Пример: BOOTLOADER_SECTION void

 

 

 

 

 

 

ние которых возможно исключительно на

func1(void); - функция func1() будет разме-

 

boot_spm_interrupt_enable()

 

 

платформе AVR-микроконтроллеров, т.е.

щена в области памяти микроконтроллера,

 

boot_spm_interrupt_enable()

 

 

аппаратно-зависимые функции. В основном

отведенной для загрузчика.

 

Описание: разрешает прерывания пос-

 

эти функции реализуют поддержку особен-

 

 

 

ле исполнения инструкции записи в память

 

ностей архитектуры микроконтроллеров,

GET_LOW_FUSE_BITS

 

программ.

 

 

например, встроенную EEPROM или воз-

GET_LOW_FUSE_BITS – константа, за-

 

 

 

 

 

 

можность записи в память программ.

дающая адрес чтения младшего байта fuse-

 

boot_spm_interrupt_disable()

 

 

 

 

 

 

битов микроконтроллера для применения в

 

boot_spm_interrupt_disable()

 

 

avr/boot.h – Поддержка

boot_lock_fuse_bits_get()

 

Описание: запрещает прерывания пос-

 

загрузчиков AVR

 

 

 

ле исполнения инструкции записи в память

 

Модуль определяет ряд макросов, уп-

GET_LOCK_BITS

 

программ.

 

 

рощающих разработку программ пользова-

GET_LOCK_BITS – константа, зада-

 

 

 

 

 

 

теля, реализующих алгоритм самозагруз-

ющая адрес чтения байта lock-битов мик-

 

boot_is_spm_interrupt()

 

 

ки программы (boot-loading). Это возможно

роконтроллера для применения в

 

boot_is_spm_interrupt()

 

 

не для любого микроконтроллера AVR. Мак-

boot_lock_fuse_bits_get()

 

Описание: проверяет, разрешены ли

 

росы модуля позволяют работать со всей

 

 

 

прерывания после исполнения инструкции

 

областью памяти программ микроконтрол-

GET_EXTENDED_FUSE_BITS

 

записи в память программ.

 

 

леров.

 

 

GET_EXTENDED_FUSE_BITS – кон-

 

 

 

 

 

 

Макросы не используют глобальное

станта, задающая адрес чтения байта рас-

 

boot_rww_busy()

 

 

запрещение прерываний, это оставлено на

ширенных fuse-битов микроконтроллера

 

boot_rww_busy()

 

 

совести программиста. Пример функции са-

для применения в boot_lock_fuse_bits_get()

 

Описание: проверяет, занята ли секция

 

мозаписи памяти программ см. на врезке.

 

 

 

RWW памяти программ.

 

 

 

 

 

 

GET_HIGH_FUSE_BITS

 

 

 

 

 

 

Определения модуля

GET_HIGH_FUSE_BITS – константа,

 

boot_spm_busy()

 

 

 

 

 

 

задающая адрес чтения старшего байта

 

boot_spm_busy()

 

 

BOOTLOADER_SECTION

fuse-битов микроконтроллера для примене-

 

Описание: проверяет, завершена ли

 

BOOTLOADER_SECTION – модифика-

ния в boot_lock_fuse_bits_get()

 

инструкция записи в память программ.

 

тор атрибутов переменной или функции в

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

boot_spm_busy_wait()

 

 

 

 

 

 

 

 

 

boot_spm_busy_wait()

 

 

 

 

Врезка. Пример функции самозаписи памяти программ.

 

 

Описание: ожидает, пока не завершит-

 

 

 

 

 

ся инструкция записи в память программ.

 

 

 

 

 

 

 

 

 

#include <inttypes.h>

 

 

 

 

 

boot_lock_fuse_bits_get()

 

 

#include <avr/interrupt.h>

 

 

 

 

 

 

 

 

boot_lock_fuse_bits_get(address)

 

 

#include <avr/pgmspace.h>

 

 

 

 

 

 

 

 

Описание: возвращает считанный байт

 

void boot_program_page (uint32_t page, uint8_t *buf){

 

 

 

 

 

fuse-битов или lock-битов микроконтрол-

 

uint16_t i;

 

 

 

 

 

 

 

 

 

 

 

лера в зависимости от значения address,

 

uint8_t sreg;

 

 

 

 

 

 

 

 

 

 

 

которое может принимать одно из следую-

 

// запрещаем прерывания

 

 

 

 

 

 

 

 

 

 

 

щих значений: GET_LOW_FUSE_BITS,

 

sreg = SREG;

 

 

 

 

 

 

 

 

 

 

 

G E T _ E X T E N D E D _ F U S E _ B I T S ,

 

cli();

 

 

 

 

 

 

 

 

 

 

 

GET_HIGH_FUSE_BITS

или

 

eeprom_busy_wait();

// ожидаем, завершения предыдущей записи

 

 

 

 

 

GET_LOCK_BITS.

 

 

boot_page_erase (page);// стираем указанную страницу

 

 

 

 

 

 

Примечание: возвращается физичес-

 

boot_spm_busy_wait();

// ожидаем завершения стирания

 

 

 

 

 

ки реальное значение соответствующего

 

// цикл заполнения страницы памяти

 

 

 

 

 

 

 

байта, т.е. запрограммированные биты яв-

 

for (i=0; i<SPM_PAGESIZE; i+=2){

 

 

 

 

 

 

 

ляются нулями, а незапрограммированные

 

// заполняем словами «в обратном порядке»

 

 

 

 

 

 

 

биты – единицами.

 

 

uint16_t w = *buf++;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

w += (*buf++) << 8;

 

 

 

 

 

boot_signature_byte_get()

 

 

boot_page_fill (page + i, w);

 

 

 

 

 

 

 

 

boot_signature_byte_get(addr)

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Описание: возвращает байт из обла-

 

boot_page_write (page);// записываем заполненную страницу

 

 

 

 

 

сти сигнатуры микроконтроллера. Для

 

boot_spm_busy_wait();

// ожидаем завершения записи

 

 

 

 

 

микроконтроллеров, поддерживающих

 

// разрешение перехода к RWW секции памяти. Это нужно, если

 

 

 

 

 

калибровочные байты встроенных RC-гене-

 

// после самозаписи должен быть осуществлен переход к основной программе

 

 

 

 

 

раторов, этот макрос так же может возвра-

 

boot_rww_enable();

 

 

 

 

 

 

 

 

 

 

 

щать и эти значения. Значение addr может

 

// восстановление состояния прерываний, как было при входе в функцию

 

 

 

 

 

находиться в пределах от 0 до 0x1F – см.

 

SREG = sreg;

 

 

 

 

 

 

 

 

 

 

 

документацию на примененный микрокон-

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

троллер.

 

 

 

 

 

 

 

 

 

 

5 4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Радиолюбитель – 01/2011

 

 

 

 

 

 

 

 

 

 

СПРАВОЧНЫЙ МАТЕРИАЛ

boot_page_fill()

boot_rww_enable_safe()

eeprom_is_ready()

boot_page_fill(address, data)

boot_rww_enable_safe()

eeprom_is_ready()

Описание: записывает во временный

Описание: выполняет то же действие,

Описание: макрос, возвращающий не

буфер страницы по указанному адресу

что и boot_rww_enable(), но перед этим до-

нулевое значение, если EEPROM готова для

address заданные данные data.

жидается завершения ранее начатой опе-

очередного обращения, 0 – в противном слу-

Примечание: address – это адрес бай-

рации самопрограммирования.

чае.

та, data – это 16-битное значение (слово).

 

 

 

AVR адресуют память побайтно, но за

boot_lock_bits_set_safe()

eeprom_busy_wait()

один раз записывают слово! Правиль-

boot_lock_bits_set_safe(lock_bits)

eeprom_busy_wait()

ное использование макроса заключается

Описание: выполняет то же действие,

Описание: макрос, выполняющий цикл

в том, чтобы от обращения к обращению

что и boot_lock_bits_set(), но перед этим

ожидания завершения операции записи в

увеличивать значение address на 2, а в

дожидается завершения ранее начатой опе-

EEPROM.

data помещать сразу по 2 байта, как еди-

рации самопрограммирования.

Функции модуля

ное слово.

 

 

 

 

avr/eeprom.h – Поддержка

Большинство функций реализованы как

boot_page_erase()

EEPROM AVR

static inline-функции или макросы-функции.

boot_page_erase(address)

Этот модуль содержит ряд простых

 

 

Описание: выполняет стирание страни-

функций и макросов, реализующих основ-

eeprom_read_byte()

цы памяти программ.

ные операции для работы со встроенным

uint8_t eeprom_read_byte (const uint8_t

Примечание: address – это адрес бай-

EEPROM микроконтроллеров AVR. Все фун-

*p)

та, а не слова.

кции действуют по принципу «ожидания»,

Параметры:

 

 

 

т.е. достаточно длительные. Если требует-

const uint8_t *p – указатель на байт в

boot_page_write()

ся реализация работы по прерываниям для

EEPROM

boot_page_write(address)

максимально эффективного кода, она дол-

Возвращаемое значение: считанный

Описание: выполняет запись буфера в

жна быть реализована пользователем са-

из EEPROM байт.

указанную address страницу памяти про-

мостоятельно.

Описание: функция выполняет считы-

грамм.

Все функции выполняют проверку го-

вание байта по указанному адресу из

Примечание: address – это адрес бай-

товности EEPROM для очередного обраще-

EEPROM.

та, а не слова.

ния, но они не контролируют состояние ав-

 

 

 

 

 

томата записи в память программ (т.е. са-

eeprom_read_word()

boot_rww_enable()

мопрограммирования). Если ваша програм-

uint16_t eeprom_read_word (const

boot_rww_enable()

ма содержит код самопрограммирования,

uint16_t *p)

Описание: включает доступ к RWW-

вы должны самостоятельно реализовать

Параметры:

секции памяти программ.

проверку завершения любой операции са-

const uint16_t *p – указатель на слово в

 

 

 

мопрограммирования перед обращением к

EEPROM

boot_lock_bits_set()

EEPROM.

Возвращаемое значение: считанное

boot_lock_bits_set(lock_bits)

Так как функции используют фиксиро-

из EEPROM слово.

Описание: устанавливает биты защи-

ванные регистры для работы, они не реен-

Описание: функция выполняет считы-

ты загрузчика (BLB-биты).

терабельны, т.е. если эти функции вызы-

вание 16-битного значения из EEPROM.

Примечания:

ваются и из обычного цикла программы и

 

 

1. Параметр lock_bits в данном макро-

из обработчиков прерываний, следует зап-

eeprom_read_dword()

се должен содержать единицы в тех пози-

рещать глобально прерывания перед об-

uint32_t eeprom_read_dword (const

циях, которые должны быть запрограмми-

ращениям к этим функциям из основной

uint32_t *p)

рованы, т.е. записаны в ноль.

программы.

Параметры:

2. Макрос устанавливает только BLB-

Определения модуля

const uint32_t *p – указатель на двой-

биты защиты.

ное слово в EEPROM

3. Как и любые биты защиты, единож-

Модуль вводит ряд определений (кон-

Возвращаемое значение: считанное

ды установленные BLB-биты могут быть

стант и макросов), часть из которых позво-

из EEPROM двойное слово.

стерты только при полном стирании памяти

ляет упростить совместимость исходного

Описание: функция выполняет считы-

микроконтроллера.

текста со средой разработки IAR.

вание 32-битного числа из EEPROM.

boot_page_fill_safe()

_EEPUT()

eeprom_read_block()

boot_page_fill_safe(address, data)

_EEPUT(addr, val)

void eeprom_read_block (void *dst, const

Описание: выполняет то же действие,

Описание: макрос, осуществляющий

void *src, size_t n)

что и boot_page_fill(), но перед этим дожи-

запись байта val в EEPROM по адреса addr.

Параметры:

дается завершения ранее начатой опера-

Введен для совместимости с IAR.

void *dst – указатель на начало области

ции самопрограммирования.

 

в ОЗУ

 

 

 

_EEGET()

const void *src – указатель на начало

boot_page_erase_safe()

_EEGET(var, addr)

области EEPROM

boot_page_erase_safe(address)

Описание: макрос, осуществляющий

size_t n – количество байт

Описание: выполняет то же действие,

чтение байта из EEPROM по адресу addr.

Возвращаемое значение: нет.

что и boot_page_erase(), но перед этим до-

Введен для совместимости с IAR.

Описание: функция выполняет считы-

жидается завершения ранее начатой опе-

 

вание n байтов из EEPROM по адресу src

рации самопрограммирования.

EEMEM

и размещает их в ОЗУ, начиная с адреса

 

 

 

EEMEM

dest.

boot_page_write_safe()

Описание: атрибут, указывающий на

 

 

boot_page_write_safe(address)

то, что переменная должна размещаться в

eeprom_write_byte()

Описание: выполняет то же действие,

EEPROM. Пример использования: EEMEM

void eeprom_write_byte (uint8_t *p, uint8_t

что и boot_page_write(), но перед этим до-

int k; - переменная k должна быть размеще-

value)

жидается завершения ранее начатой опе-

на в EEPROM.

Параметры:

рации самопрограммирования.

 

uint8_t *p – указатель на ячейку в

 

 

 

 

EEPROM

 

 

 

 

 

5 5

Радиолюбитель – 01/2011

 

 

 

 

 

 

 

 

 

СПРАВОЧНЫЙ МАТЕРИАЛ

uint8_t value – записываемый байт

 

Врезка. Пример использования.

Возвращаемое значение: нет.

 

 

 

 

 

 

Описание: функция выполняет запись

#include <avr/io.h>

 

 

 

байта value в EEPROM по адресу p.

 

 

 

FUSES ={

 

 

 

 

 

 

 

eeprom_write_word()

.low = LFUSE_DEFAULT,

 

 

 

.high = (FUSE_BOOTSZ0 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),

void eeprom_write_word (uint16_t *p,

.extended = EFUSE_DEFAULT,

 

 

 

uint16_t value)

 

 

 

};

 

 

 

 

uint16_t *p – указатель на ячейку в

 

 

 

 

 

 

 

 

 

EEPROM

int main(void){

 

 

 

uint16_t value – записываемое слово

 

 

 

return 0;

 

 

 

Возвращаемое значение: нет.

 

 

 

}

 

 

 

 

Описание: функция выполняет запись

 

 

 

 

 

 

 

 

 

16-битного числа value в EEPROM по адре-

avr/fuse.h – Поддержка

 

 

 

су p.

 

FUSES представляет собой структуру с тре-

 

 

fuse-битов AVR

 

мя полями типа int8_t low, high и extended.

eeprom_write_dword()

Модуль позволяет разместить в осо-

 

Наконец, если МК содержит более 3-х fuse-

void eeprom_write_dword (uint32_t *p,

бой секции ELF-файла информацию о со-

 

байтов, FUSES определена как массив бай-

uint32_t value)

стоянии fuse-битов, которую может извле-

 

тов соответствующей длины.

uint32 *p – указатель на ячейку в

кать программное обеспечение програм-

 

Следует учитывать, что компоновщик

EEPROM

матора для установки fuse-битов при про-

 

использует только значения переменной

uint32 value – записываемое двойное

граммировании микроконтроллера. Раз-

 

FUSES, которые были указаны на этапе

слово

мещение этой информации в ELF-файле

 

начальной инициализации, и игнорирует все

Возвращаемое значение: нет.

осуществляется при компоновке програм-

 

изменения, которые могли быть сделаны в

Описание: функция выполняет запись

мы. К сожалению, в HEX-формате сведе-

 

ходе выполнения программы.

32-битного числа value в EEPROM по адре-

ния о состоянии fuse-битов размещены

 

Пример использования см. на врезке.

су p.

быть не могут.

 

Важно, что всегда необходимо инициа-

 

Данный модуль – универсальный, т.е.

 

лизировать все поля структуры FUSES.

eeprom_write_block()

ориентирован на весь спектр поддержи-

 

Суть

рассматриваемого модуля

void eeprom_write_block (const void *src,

ваемых микроконтроллеров. Необходимо

 

заключена в том, что получаемый в

void *dst, size_t n)

обязательно подключать к проекту модуль

 

результате компиляции elf-файл содержит

Параметры:

io.h, в котором определяются глобальные

 

абсолютно всю информацию, необходимую

void *src – указатель на начало области

параметры, используемые затем в моду-

 

для правильного программирования

ОЗУ

ле fuse.h. Сам модуль fuse.h подключа-

 

микроконтроллера. Остается только решить

void *dst – указатель на начало области

ется в этом случае автоматически, поэто-

 

вопрос,

какое именно программное

в EEPROM

му нужды в явном его подключении нет.

 

обеспечение в состоянии воспользоваться

size_t n – количество байт

В зависимости от типа примененно-

 

этой информацией. В какой-то мере эту

Возвращаемое значение: нет.

го микроконтроллера fuse-биты могут

 

задачу может решить утилита avrdude,

Описание: функция осуществляет за-

располагаться в младшем, старшем

 

входящая в состав WinAVR, однако, только

пись n байт из области ОЗУ src в область

или расширенном fuse-байте. Для каж-

 

в связке с другой утилитой avr-objcopy.

EEPROM dest.

дого отдельно взятого fuse-бита вводят-

 

Avrdude – это универсальный программатор,

Следует признать, что модуль

ся константы-маски, соответствующие

 

поддерживающий огромное количество

eeprom.h от релиза к релизу WinAVR пре-

наименованию fuse-бита, например,

 

схем для прошивки микроконтроллеров

терпевает существенные модификации, в

FUSE_SPIEN, FUSE_RSTDSBL и т.д.34 .

 

AVR, а утилита avr-objcopy позволяет

частности, неоднократно менялись места-

Если необходимо установить несколько

 

извлекать из elf-файла информационные

ми параметры функций блочного чтения-

fuse-битов в одном байте, нужно объединять

 

блоки о flash, eeprom и fuse-битах (из

записи, что, разумеется, порождает опре-

их при помощи битовой операции AND, т.е.

 

соответствующих секций) и сохранять их в

деленные сложности с совместимостью

так: (FUSE_SPIEN & FUSE_RSTDISBL &

 

виде hex-файлов, которые уже могут

ранее разработанного кода и новой вер-

….).

 

использоваться avrdude для прошивки. К

сии компилятора. Поэтому рекомендуется

Для каждого из fuse-байтов конкретно-

 

сожалению, обе эти утилиты имеют немалое

тщательно изучить документацию на све-

го микроконтроллера определены значения

 

количество опций запуска, поэтому в рамках

жий релиз WinAVR, т.к. в нем могут быть

fuse-битов по умолчанию, которые следует

 

данного изложения не рассматриваются

сюрпризы.

применять, если изменять их не требуется:

 

(это планируется сделать позже).

Из числа приятных сюрпризов, появив-

LFUSE_DEFAULT для младшего байта,

 

avr/interrupt.h – Прерывания

шихся с версии WinAVR 20100110, можно

HFUSE_DEFAULT для старшего и

 

назвать появление «бережных» функций

EFUSE_DEFAULT для расширенного.

 

Общие сведения

записи EEPROM eeprom_update_xxxx(),

Модуль определяет всего одну глобаль-

 

где xxxx – это суффикс byte, word,

ную переменную-структуру FUSES, к зада-

 

При обработке прерываний происходит

dword или block. Параметры этих фун-

нию начальных значений для которой и сво-

 

конфликт между декларируемой Си неза-

кций такие же, как у соответствующих

дится вся работа с fuse-битами. Данная пе-

 

висимостью от аппаратуры, и жесткой при-

eeprom_write_xxxx(), а отличие в том, что

ременная в зависимости от микроконтрол-

 

вязке векторов прерываний к этой самой

новые функции перед тем, как записать

лера может быть разного типа: если микро-

 

аппаратуре. Таким образом, любая реали-

новое значение в ячейку EEPROM, прове-

контроллер содержит всего один fuse-байт,

 

зация обработки прерываний на Си стано-

ряют ее текущее значение и, если оба зна-

то эта переменная является просто пере-

 

вится уникальной для конкретной среды

чения одинаковы, то запись в ячейку не про-

менной типа int8_t; если микроконтроллер

 

программирования.

изводится. Так как ресурс записей EEPROM

имеет 2 fuse-байта, то FUSES представля-

 

В WinAVR принято, что каждому оп-

AVR ограничен 100000 записей, использо-

ет собой структуру с 2-я полями low и high

 

ределенному вектору прерывания сопо-

вание новых функций позволяет увеличить

соответственно типа int8_t каждое; для мик-

 

ставлена особым образом поименован-

живучесть EEPROM без принятия каких-то

роконтроллеров с тремя fuse-байтами

 

ная функция-обработчик. Определение в

особых мер.

 

 

 

 

 

Рекомендуется использовать эти фун-

34 Т.к. fuse-биты отличаются в зависимости от модели микроконтроллера, следует ознакомиться с их наименованием

кции всегда.

по соответствующей документации к выбранному контроллеру; в настоящей документации они не приводятся.

5 6

Радиолюбитель – 01/2011

 

СПРАВОЧНЫЙ МАТЕРИАЛ

программе функции, названной в соответ-

определить обработчик, который не дела-

(оканчиваются на суффикс _vect, например,

ствии с определенными соглашениями, при-

ет ничего.

ADC_vect). Кроме этого можно использо-

водит к тому, что компилятор генерирует для

Наконец, во многих случаях может

вать константу BADISR_vect для задания об-

нее нестандартный код пролога и эпилога,

оказаться, что неизбежно генерируемый

работчика «по умолчанию».

в частности, обязательно сохраняет SREG

компилятором для обработчика прерыва-

Второй параметр attributes – необяза-

в начале и восстанавливает в конце, а так

ния код пролога и эпилога оказывается

тельный, определяет опциональные вари-

же использует для возврата из функции ко-

слишком велик. Было бы удобно в таком

анты реализации соответствующего обра-

манду RETI. Кроме того, в таблице векто-

случае использовать обработчик, реали-

ботчика. Допустимо использовать несколь-

ров прерываний для каждой определенной

зованный на ассемблере, либо попы-

ко атрибутов из числа следующих (атрибу-

пользователем функции-обработчика поме-

таться обойтись средствами Си для по-

ты разделяются запятыми):

щается команда перехода к соответствую-

лучения более оптимального кода. Сде-

ISR_BLOCK – атрибут по умолчанию,

щей функции.

лать это можно при помощи параметра

означает запрет прерываний, пока не отра-

Далее кратко перечислены основные

ISR_NAKED, указываемого для ISR(). В

ботает текущий обработчик

характерные особенности реализации об-

этом случае компилятор не генерирует

ISR_NOBLOCK – разрешает глобально

работчиков прерываний WinAVR. Подроб-

вообще никакого пролога и эпилога, по-

прерывания сразу после пролога обработ-

ности следует искать в описаниях соответ-

этому программист сам должен обеспе-

чика

ствующих макросов.

чить сохранение контекста программы (в

ISR_NAKED – указывает, что вся реа-

Детали реализации этого подхода ос-

частности, содержимого SREG), и, глав-

лизация кода обработчика делается про-

таются за кадром, т.к. программисту доста-

ное, использовать макрос reti() для выхо-

граммистом (нет никакого пролога и эпило-

точно определить при помощи макроса ISR()

да из обработчика.

га)

функцию – и она будет назначена (и соот-

Для каждого микроконтроллера опре-

ISR_ALIASOF(v) – позволяет назначить

ветственно оформлена) обработчиком оп-

делены свои константы для указания со-

текущему обработчику несколько векторов

ределенного прерывания.

ответствующего вектора прерывания. Эти

(см. врезку для ISR_ALIASOF).

Особенность аппаратного строения AVR

константы содержат в своем составе

 

заключается в том, что во время работы

суффиксc _vect. Для совместимости с

SIGNAL()

одного обработчика прерываний все про-

предыдущими версиями WinAVR сохране-

SIGNAL(vector) – макрос определения

чие прерывания запрещены. Такая ситуа-

на и возможность определять обработчик

обработчика, сохраненный исключительно

ция в некоторых случаях может быть неже-

прерывания при помощи «сигналов», т.е.

для совместимости со старым кодом. Не ре-

лательной, для чего можно (естественно,

констант, имеющих «префикс» SIG_ (пре-

комендуется использование в новых разра-

осознавая последствия, к которым это мо-

фиксы и суффиксы соответствующих век-

ботках. В качестве параметра vector дол-

жет привести) разрешить прерывания при-

торов определены в заголовочных фай-

жен получать константу с префиксом SIG_

нудительно внутри функции-обработчика,

лах для каждого типа микроконтролле-

из заголовочного файла конкретного мик-

используя макрос sei(). Но можно поступить

ров). Рекомендуется использовать «но-

роконтроллера (например, SIG_ADC).

и проще, указав для макроса ISR() параметр

вую» форму _vect.

 

ISR_NOBLOCK, что заставит компилятор

Макросы и определения

EMPTY_INTERRUPT()

поместить соответствующую инструкцию

EMPTY_INTERRUPT(vector) – макрос

глобального разрешения прерываний сра-

 

определения «пустого» обработчика, т.е.

зу после пролога функции (т.е. инициали-

sei()

состоящего только из команды RETI. В ка-

зирующего участка кода).

sei() – глобальное разрешение преры-

честве параметра принимаются те же зна-

При разработке программ не исключе-

ваний

чения, что и для ISR().

на ситуация, когда случайно будет сгенери-

 

 

ровано прерывание, для которого нет на-

cli()

ISR_ALIAS()

значенного обработчика (ситуация «баг про-

cli() – глобальное запрещение преры-

ISR_ALIAS(vector, target_vector) – мак-

граммы»). По умолчанию компилятор гене-

ваний

рос, связывающий два вектора в один об-

рирует код, который в этом случае приве-

 

работчик. Не рекомендуется использование

дет к переходу на адрес 0х0000, т.е. пове-

reti()

в новых разработках. В качестве парамет-

дение кода равносильно сбросу микрокон-

reti() – макрос принудительно помеща-

ра vector и target_vector используется лю-

троллера. Однако такое поведение можно

ет в код программы инструкцию RETI, обес-

бая из констант, как и для ISR(), причем

изменить, определив особый обработчик

печивая возврат из прерывания.

параметр target_vector к моменту вызова

«неверного прерывания», который автома-

 

макроса должен быть уже определен (см.

тически назначается все «незанятым» век-

ISR()

врезку ISR_ALIAS):

торам прерываний. Делается это при помо-

ISR(vector, attributes) – макрос для оп-

 

щи указания для ISR() «плохого» вектора

ределения обработчика прерываний.

ISR_ALIASOF()

BADISR_vect.Такойобработчикбудетисполь-

Первый параметр vector – это одна

ISR_ALIASOF(target_vector) – макрос,

зован для всех векторов прерываний, для

из констант, определяющих номер век-

используемый в качестве опционального

которых не указаны явно их обработчики.

тора прерывания. Реальные константы

параметра ISR() для того, чтобы связать об-

Так же часто может возникать ситуа-

определены в соответствующем заголовоч-

работчик, определенный ISR(), еще и с век-

ция, когда один и тот же обработчик дол-

ном файле модели микроконтроллера

торомtarget_vector(см.врезкуISR_ALIASOF).

жен использоваться для нескольких пре-

 

 

рываний. Можно, конечно, определить не-

Врезка ISR_ALIAS

 

 

 

сколько абсолютно идентичных функций,

// определяем обработчик внешнего запроса прерывания №0

 

 

однако, можно и сэкономить память, ука-

ISR(INT0_vect){

 

 

 

зав для ISR() параметр ISR_ALIASOF().

PORTB = 42;

 

 

 

Еще одной занимательной ситуаци-

}

 

 

 

ей, связанной с прерываниями, является

// назначаем этот обработчик и для запроса №1

 

 

 

пробуждение микроконтроллера по пре-

ISR_ALIAS(INT1_vect, INT0_vect);

 

 

 

рыванию из «спящего» режима. В этом

 

 

Врезка ISR_ALIASOF

 

случае обработчик прерывания вызыва-

 

// определяем обработчик внешнего запроса прерывания №0 и одновременно №1

ется, однако, часто в нем никаких полез-

ISR(INT0_vect, ISR_ALIASOF(INT1_vect)){

 

ных действий выполняться не должно.

 

PORTB = 42;

 

Для таких случаев предусмотрен мак-

 

}

 

рос EMPTY_INTERRUPT(), позволяющий

 

 

 

 

 

 

5 7

Радиолюбитель – 01/2011

 

 

 

 

 

СПРАВОЧНЫЙ МАТЕРИАЛ

BADISR_vect

FLASHEND – соответствует адресу пос-

PGM_VOID_P

BADISR_vect – константа «псевдовек-

ледней ячейки памяти программ, т.е. фак-

PGM_VOID_P – макрос, определяющий

тора», обозначающая любой явно не задан-

тически определяет размер сегмента кода.

указатель на объект в сегменте кода

ный вектор. По умолчанию соответствует

SPM_PAGESIZE – соответствует разме-

 

переходу на начало программной памяти,

ру страницы для операций самопрограмми-

pgm_read_byte_near()

вызывая переинициализацию всего кода

рования (т.е. записи из программы в сег-

pgm_read_byte_near(address_short) –

при поступлении «необрабатываемого»

мент кода).

макрос, возвращающий значение байта,

прерывания.

 

считанного из программной памяти по ад-

 

avr/pgmspace.h – Поддержка

ресу address_short (в первых 64К).

ISR_BLOCK

обращения к сегменту кода AVR

 

ISR_BLOCK – опциональный атрибут,

В этом модуле определяются ряд фун-

pgm_read_word_near()

используемый в ISR(), и обозначающий, что

кций и макросов, позволяющих обращать-

pgm_read_word_near(address_short) –

прерывания будут запрещены в течение

ся к данным, хранящимся в памяти про-

макрос, возвращающий значение 16-битно-

работы всего обработчика прерывания.

грамм, т.е. сегменте кода. Для этого необ-

го числа, считанного из программной памя-

Если этот атрибут не задан явно (т.е. исполь-

ходимо, чтобы микроконтроллер поддержи-

ти по адресу address_short (в первых 64К).

зуется ISR() без атрибутов вообще), преры-

вал инструкции LPM или ELPM.

 

вания все равно будут запрещены.

Функции этого модуля – попытка облег-

pgm_read_dword_near()

 

чить процесс адаптации программ для IAR,

pgm_read_dword_near(address_short) –

ISR_NOBLOCK

однако полной совместимости нет по прин-

макрос, возвращающий значение 32-бит-

ISR_NOBLOCK – опциональный атри-

ципиальным особенностям GCC.

ного числа, считанного из программной па-

бут, используемый в ISR(), и обозначающий,

Если вы работаете со строками, кото-

мяти по адресу address_short (в первых

что прерывания будут разрешены в тече-

рые постоянно размещены в ОЗУ, вы мо-

64К).

ние работы всего обработчика прерывания.

жете использовать функции для работы с

 

Это позволит быстрее отреагировать на

ними из модуля string.h – Строки, но для

pgm_read_byte_far()

ожидающие в очереди другие запросы пре-

неизменных строк более удачным будет

pgm_read_byte_far(address_long) – мак-

рываний, однако увеличивает требования

размещение их в сегменте кода. В этом слу-

рос, возвращающий значение байта, счи-

к объему стека.

чае вы можете работать с ними при помо-

танного из программной памяти по адресу

 

щи функций этого модуля, которые совпа-

address_long (32 бита, нет ограничения в

ISR_NAKED

дают по имени с аналогичными из string.h,

64К).

ISR_NAKED – опциональный атрибут,

но имеют суффикс _Р – признак того, что

 

используемый в ISR(), и обозначающий, что

строка находится в программной памяти

pgm_read_word_far()

компилятор не должен добавлять пролог и

(такой принцип так же использовался и в

pgm_read_word_far(address_long) – мак-

эпилог к функции. В этом случае програм-

модуле stdio.h – Стандартный ввод-вывод).

рос, возвращающий значение 16-битного

мист обязан сам выполнить все необходи-

Однако следует учитывать, что функции

числа, считанного из программной памяти

мые меры, включая выход из обработчика

из настоящего модуля могут работать толь-

по адресу address_long (32 бита, нет огра-

макросом reti().

ко со строками, размещенными в первых

ничения в 64К).

 

64К адресного пространства микроконтрол-

 

avr/io.h – Специфичные

лера, т.к. не используют инструкцию ELPM.

pgm_read_dword_far()

для AVR функции ввода-вывода

Это не страшно в обычных случаях. Но мо-

pgm_read_dword_far(address_long) –

Этот заголовочный файл по существу

жет вызвать проблемы, если имеется много

макрос, возвращающий значение 32-битно-

реализует автоматическое подключение

текстовых констант или же используется са-

го числа, считанного из программной памя-

одного конкретного файла, соответствую-

мозагрузка кода. При написании программы

ти по адресу address_long (32 бита, нет ог-

щего выбранному микроконтроллеру. Во

вы не должны беспокоиться о месте разме-

раничения в 64К).

всяком случае, для определения констант и

щения строк, т.к. компоновщик автоматичес-

 

макросов портов ввода-вывода и т.п. пери-

ки разместит все данные в программной

pgm_read_byte()

ферии программист более не должен при-

памяти сразу после векторов прерывания.

pgm_read_byte(address_short) – аналог

менять никаких усилий, кроме подключения

Так же следует помнить о том, что все

pgm_read_byte_near()

этого файла к проекту и задания типа мик-

используемые для обращения к сегменту

 

роконтроллера. Фактически происходит

кода указатели представляют себя адре-

pgm_read_word()

подключение целого ряда заголовочных

са байтов (хотя программная адресация у

pgm_read_word(address_short) – аналог

файлов, в которых определены константы

AVR – 16-битная).

pgm_read_word_near()

и макросы для обращения к различной пе-

 

 

риферии микроконтроллера (см. например

Определения модуля

pgm_read_dword()

avr/sfr_defs.h – Регистры специальных фун-

Модуль определяет ряд констант, атри-

pgm_read_dword(address_short) – ана-

кций AVR).

бутов и макросов, облегчающих разработ-

лог pgm_read_dword_near()

Рассмотрение всех этих определений

ку программ, работающих с данными в сег-

 

опущено, т.к. подразумевается, что про-

менте кода.

Типы, вводимые модулем

граммист, работающий с AVR, вполне ин-

 

Модуль вводит ряд типов, которые про-

формирован о его периферии. Из прочего

PROGMEM

сто облегчают определение констант в сег-

стоит обратить внимание лишь на следую-

PROGMEM – макрос, устанавливающий

менте кода. По смыслу все эти типы анало-

щие константы:

атрибут, указывающий, что переменная на

гичны определенным в inttypes.h – Целочис-

RAMEND – соответствует адресу пос-

самом деле представляет собой константу

ленные преобразования, только содержат

ледней существующей ячейки ОЗУ, т.е. в

в сегменте кода

префикс prog_, означающий, что соответ-

сущности, определяет размер ОЗУ выбран-

 

ствующий объект размещается в памяти

ного микроконтроллера.

PSTR()

программ. В связи с этим расшифровка

XRAMEND – соответствует адресу пос-

PSTR(s) – макрос, используемый для

значения типов не приводится.

ледней существующей ячейки внешнего

определения указателя на строку s, разме-

prog_void

или дополнительно адресуемого ОЗУ (если

щенную в сегменте кода

prog_char

его поддержка имеется в микроконтролле-

 

prog_uchar

ре).

PGM_P

prog_int8_t

E2END – соответствует адресу после-

PGM_P – макрос, определяющий ука-

prog_uint8_t

дней ячейки встроенного EEPROM

затель на символ в сегменте кода

prog_int16_t

5 8

Радиолюбитель – 01/2011

 

СПРАВОЧНЫЙ МАТЕРИАЛ

prog_uint16_t

strcmp_P()

 

strpbrk_P()

prog_int32_t

int strcmp_P (const char *s1, PGM_P s2)

 

char * strpbrk_P (const char *s, PGM_P

prog_uint32_t

Функция аналогична strcmp(), за исклю-

accept)

prog_int64_t

чением того, что s2 находится в программ-

 

Функция аналогична strpbrk(), за исклю-

prog_uint64_t

ной памяти.

чением того, что accept находится в про-

 

 

 

 

граммной памяти

Функции модуля

strcpy_P()

 

 

 

Так как все функции не более чем ана-

char * strcpy_P (char *s1, PGM_P s2)

 

strrchr_P()

логи string.h – Строки, вместо подробного

Функция аналогична strcpy(), за исклю-

 

PGM_P strrchr_P (PGM_P s, int val)

описания будут указаны ссылки на функ-

чением того, что s2 находится в программ-

 

Функция аналогична strrchr(), за исклю-

ции для работы со строками в ОЗУ. Един-

ной памяти.

чением того, что s находится в программ-

ственное, на что должен обратить програм-

 

ной памяти

мист, это типы передаваемых в функции па-

strcspn_P()

 

 

 

раметров и возвращаемых значений: как

size_t strcspn_P (const char *s, PGM_P

 

strsep_P()

правило, все указатели в функциях этого

reject)

 

char * strsep_P (char **sp, PGM_P delim)

модуля – это указатели на объекты в сег-

Функция аналогична strcspn(), за исклю-

 

Функция аналогична strsep(), за исклю-

менте кода.

чением того, что reject находится в про-

чением того, что delim находится в про-

 

 

 

граммной памяти.

граммной памяти

memchr_P()

 

 

 

 

PGM_VOID_P memchr_P (PGM_VOID_P

strlcat_P()

 

strspn_P()

s, int val, size_t len)

size_t strlcat_P (char *dest, PGM_P src,

 

size_t strspn_P (const char *s, PGM_P

Функция ищет в области программной

size_t siz)

accept)

памяти s символ, возвращая указатель на

Функция аналогична strlcat(), за исклю-

 

Функция аналогична strspn(), за исклю-

него или NULL, если не найдено. Подробно-

чением того, что src находится в программ-

чением того, что accept находится в про-

сти см. в memrchr()

ной памяти

 

граммной памяти

memcmp_P()

strlcpy_P()

 

strstr_P()

int memcmp_P (const void *s1,

size_t strlcpy_P (char *dest, PGM_P src,

 

char * strstr_P (const char *s1, PGM_P s2)

PGM_VOID_P s2, size_t len)

size_t siz)

 

Функция аналогична strstr(), за исклю-

Функция сравнивает область ОЗУ s1 и

Функция аналогична strlcpy(), за исклю-

 

чением того, что s2 находится в программ-

памяти программ s2. Подробности см. в

чением того, что src находится в программ-

 

ной памяти

memcmp()

ной памяти

 

 

 

 

 

 

 

 

memmem_P()

memcpy_P()

strlen_P()

 

void * memmem_P (const void *s1, size_t

void * memcpy_P (void *dest,

size_t strlen_P (PGM_P s)

 

len1, PGM_VOID_P s2, size_t len2)

PGM_VOID_P src, size_t len)

Функция аналогична strlen(), за исклю-

 

Функция аналогична memmem(), за ис-

Функция копирует в область ОЗу dest

чением того, что s находится в программ-

 

ключением того, что s2 находится в про-

содержимое области памяти программ src.

ной памяти

граммной памяти

Подробности см. в memcpy()

 

 

 

 

 

 

 

strncasecmp_P()

 

strcasestr_P()

memrchr_P()

int strncasecmp_P (const char *s1, PGM_P

 

char * strcasestr_P (const char *s1, PGM_P

PGM_VOID_P memrchr_P (PGM_VOID_P

s2, size_t n)

s2)

s, int val, size_t len)

Функция аналогична strncasecmp(), за

 

Функция аналогична strcasestr(), за ис-

Функция ищет в области программной

исключением того, что s2 находится в про-

ключением того, что s2 находится в про-

памяти s символ. Подробности см. в

граммной памяти

граммной памяти

memrchr() и memchr_P()

 

 

 

 

 

 

 

strncat_P()

 

 

 

strcasecmp_P()

char * strncat_P (char *dest, PGM_P src,

 

 

 

int strcasecmp_P (const char *s1, PGM_P

size_t len)

 

 

 

s2)

Функция аналогична strncat(), за исклю-

 

 

 

Функция сравнивает строку s1 в ОЗУ

чением того, что src находится в программ-

 

 

 

со строкой в памяти программ s2 без учета

ной памяти

 

 

 

регистра символов. См. strcasecmp()

 

 

 

 

 

 

 

strncmp_P()

 

 

 

strcat_P()

int strncmp_P (const char *s1, PGM_P s2,

 

 

 

char * strcat_P (char *dest, PGM_P src)

size_t n)

 

 

 

Функция осуществляет конкатенацию

Функция аналогична strncmp(), за ис-

 

 

 

строки src из памяти программ к строке dest

ключением того, что s2 находится в про-

 

 

 

в ОЗУ. См. strcat()

граммной памяти

 

 

 

strchr_P()

strncpy_P()

 

 

 

PGM_P strchr_P (PGM_P s, int val)

char * strncpy_P (char *dest, PGM_P src,

 

 

 

Функция ищет символ в строке s в про-

size_t n)

 

 

 

граммной памяти. См. strchr()

Функция аналогична strncpy(), за исклю-

 

 

 

 

 

 

чением того, что src находится в программ-

 

 

 

strchrnul_P()

ной памяти

 

 

 

PGM_P strchrnul_P (PGM_P s, int val)

 

 

 

 

Функция, аналогичная strchr_P(), за ис-

strnlen_P()

 

 

 

ключением того, что всегда возвращает не-

size_t strnlen_P (PGM_P src, size_t len)

 

 

 

NULL указатель: если символ не найден,

Функция аналогична strnlen(), за исклю-

 

 

 

возвращается указатель на завершающий

чением того, что src находится в программ-

 

 

 

 

Продолжение в №2/2011

 

ноль строки s

ной памяти

 

 

 

 

 

 

 

 

5 9

Радиолюбитель – 01/2011

 

 

 

 

 

 

 

 

 

 

 

Соседние файлы в папке Книга по работе с WinAVR и AVR Studio