Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
AVR_01-2010.doc
Скачиваний:
10
Добавлен:
19.09.2019
Размер:
368 Кб
Скачать
☆

&

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

#include <inttypes.h> #include <avr/interrupt.h> #include <avr/pgmspace.h>

Void boot_program_page (uint32_t page, uint8_t *buf){

uint16_t i;

uint8_t sreg;

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

sreg = SREG;

cli();

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

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

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

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

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

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

uint16_t w = *buf++;

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

boot_page_fill (page + i, w); }

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

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

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

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

boot_rww_enable();

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

SREG = sreg; }

BOOTLOADER_SECTION - модифика­тор атрибутов переменной или функции в программе пользователя. Наличие этого макроса дает указание компоновщику раз­местить соответствующий объект в строго определенной области памяти, соответ­ственно требованиям используемого мик­роконтроллера.

Пример: BOOTLOADER_SECTION void funcl(void); - функция func1() будет разме­щена в области памяти микроконтроллера, отведенной для загрузчика.

GET_LOW_FUSE_BITS

GET_LOW_FUSE_BITS - константа, за­дающая адрес чтения младшего байта fuse- битов микроконтроллера для применения в boot_lock_fuse_bits_get()

GET_LOCK_BITS

GET_LOCK_BITS - константа, зада­ющая адрес чтения байта lock-битов мик­роконтроллера для применения в boot_lock_fuse_bits_get()

GET_EXTENDED_FUSE_BITS

GET_EXTENDED_FUSE_BITS - кон­станта, задающая адрес чтения байта рас­ширенных fuse-битов микроконтроллера для применения в boot_lock_fuse_bits_get()

GET_HIGH_FUSE_BITS

GET_HIGH_FUSE_BITS - константа, задающая адрес чтения старшего байта fuse-битов микроконтроллера для примене­ния в boot_lock_fuse_bits_get()

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

Так как большинство макросов выпол­нены в виде макросов-функций, далее они будут рассмотрены без упоминания того, что это не функции на самом деле.

boot_spm_interrupt_enable()

boot_spm_interrupt_enable()

Описание: разрешает прерывания пос­ле исполнения инструкции записи в память программ.

boot_spm_interrupt_disable()

boot_spm_interrupt_disable()

Описание: запрещает прерывания пос­ле исполнения инструкции записи в память программ.

boot_is_spm_interrupt()

boot_is_spm_interrupt()

Описание: проверяет, разрешены ли прерывания после исполнения инструкции записи в память программ.

boot_rww_busy()

boot_rww_busy()

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

boot_spm_busy()

boot_spm_busy()

Описание: проверяет, завершена ли инструкция записи в память программ.

boot_spm_busy_wait()

boot_spm_busy_wait()

Описание: ожидает, пока не завершит­ся инструкция записи в память программ.

boot_lock_fuse_bits_get()

boot_lock_fuse_bits_get(address)

Описание: возвращает считанный байт fuse-битов или lock-битов микроконтрол­лера в зависимости от значения address, которое может принимать одно из следую­щих значений: GET_LOW_FUSE_BITS, GET_EXTENDED_FUSE_BITS, GET_HIGH_FUSE_BITS или

GET_LOCK_BITS.

Примечание: возвращается физичес­ки реальное значение соответствующего байта, т.е. запрограммированные биты яв­ляются нулями, а незапрограммированные биты - единицами.

boot_signature_byte_get()

boot_signature_byte_get(addr)

Описание: возвращает байт из обла­сти сигнатуры микроконтроллера. Для микроконтроллеров, поддерживающих калибровочные байты встроенных RC-гене- раторов, этот макрос так же может возвра­щать и эти значения. Значение addr может находиться в пределах от 0 до 0x1F - см. документацию на примененный микрокон­троллер.

boot_page_fill()

boot_page_fill(address, data) Описание: записывает во временный буфер страницы по указанному адресу address заданные данные data.

Примечание: address - это адрес бай­та, data - это 16-битное значение (слово). AVR адресуют память побайтно, но за один раз записывают слово! Правиль­ное использование макроса заключается в том, чтобы от обращения к обращению увеличивать значение address на 2, а в data помещать сразу по 2 байта, как еди­ное слово.

boot_page_erase()

boot_page_erase(address) Описание: выполняет стирание страни­цы памяти программ.

Примечание: address - это адрес бай­та, а не слова.

boot_page_write()

boot_page_write(address) Описание: выполняет запись буфера в указанную address страницу памяти про­грамм.

Примечание: address - это адрес бай­та, а не слова.

boot_rww_enable()

boot_rww_enable()

Описание: включает доступ к RWW- секции памяти программ.

boot_lock_bits_set()

boot_lock_bits_set(lock_bits) Описание: устанавливает биты защи­ты загрузчика (BLB-биты). Примечания:

  1. Параметр lock_bits в данном макро­се должен содержать единицы в тех пози­циях, которые должны быть запрограмми­рованы, т.е. записаны в ноль.

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

  3. Как и любые биты защиты, единож­ды установленные BLB-биты могут быть стерты только при полном стирании памяти микроконтроллера.

boot_page_fill_safe()

boot_page_fill_safe(address, data) Описание: выполняет то же действие, что и boot_page_fill(), но перед этим дожи­дается завершения ранее начатой опера­ции самопрограммирования.

boot_page_erase_safe()

boot_page_erase_safe(address) Описание: выполняет то же действие, что и boot_page_erase(), но перед этим до­жидается завершения ранее начатой опе­рации самопрограммирования.

boot_page_write_safe()

boot_page_write_safe(address) Описание: выполняет то же действие, что и boot_page_write(), но перед этим до­жидается завершения ранее начатой опе­рации самопрограммирования.

boot_rww_enable_safe()

boot_rww_enable_safe()

Описание: выполняет то же действие, что и boot_rww_enable(), но перед этим до­жидается завершения ранее начатой опе­рации самопрограммирования.

boot_lock_bits_set_safe()

boot_lock_bits_set_safe(lock_bits)

Описание: выполняет то же действие, что и boot_lock_bits_set(), но перед этим дожидается завершения ранее начатой опе­рации самопрограммирования.

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

EEPROM AVR

Этот модуль содержит ряд простых функций и макросов, реализующих основ­ные операции для работы со встроенным EEPROM микроконтроллеров AVR. Все фун­кции действуют по принципу «ожидания», т.е. достаточно длительные. Если требует­ся реализация работы по прерываниям для максимально эффективного кода, она дол­жна быть реализована пользователем са­мостоятельно.

Все функции выполняют проверку го­товности EEPROM для очередного обраще­ния, но они не контролируют состояние ав­томата записи в память программ (т.е. са­мопрограммирования). Если ваша програм­ма содержит код самопрограммирования, вы должны самостоятельно реализовать проверку завершения любой операции са­мопрограммирования перед обращением к EEPROM.

Так как функции используют фиксиро­ванные регистры для работы, они не реен- терабельны, т.е. если эти функции вызы­ваются и из обычного цикла программы и из обработчиков прерываний, следует зап­рещать глобально прерывания перед об­ращениям к этим функциям из основной программы.

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

Модуль вводит ряд определений (кон­стант и макросов), часть из которых позво­ляет упростить совместимость исходного текста со средой разработки IAR.

_EEPUT()

_EEPUT(addr, val)

Описание: макрос, осуществляющий запись байта val в EEPROM по адреса addr. Введен для совместимости с IAR.

_EEGET()

_EEGET(var, addr)

Описание: макрос, осуществляющий чтение байта из EEPROM по адресу addr. Введен для совместимости с IAR.

EEMEM

EEMEM

Описание: атрибут, указывающий на то, что переменная должна размещаться в EEPROM. Пример использования: EEMEM int k; - переменная k должна быть размеще­на в EEPROM.

eeprom_is_ready()

eeprom_is_ready()

Описание: макрос, возвращающий не нулевое значение, если EEPROM готова для очередного обращения, 0 - в противном слу­чае.

eeprom_busy_wait()

eeprom_busy_wait()

Описание: макрос, выполняющий цикл ожидания завершения операции записи в EEPROM.

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

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

eeprom_read_byte()

uint8_t eeprom_read_byte (const uint8_t

*p)

Параметры:

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

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

Описание: функция выполняет считы­вание байта по указанному адресу из EEPROM.

eeprom_read_word()

uint16_t eeprom_read_word (const uint16_t *p)

Параметры:

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

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

Описание: функция выполняет считы­вание 16-битного значения из EEPROM.

eeprom_read_dword()

uint32_t eeprom_read_dword (const uint32_t *p)

Параметры:

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

Возвращаемое значение: считанное из EEPROM двойное слово.

Описание: функция выполняет считы­вание 32-битного числа из EEPROM.

eeprom_read_block()

void eeprom_read_block (void *dst, const void *src, size_t n) Параметры:

void *dst - указатель на начало области в ОЗУ

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

size_t n - количество байт Возвращаемое значение: нет. Описание: функция выполняет считы­вание n байтов из EEPROM по адресу src и размещает их в ОЗУ, начиная с адреса dest.

eeprom_write_byte()

void eeprom_write_byte (uint8_t *p, uint8_t value)

Параметры:

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

uint8_t value - записываемый байт Возвращаемое значение: нет. Описание: функция выполняет запись байта value в EEPROM по адресу p.

eeprom_write_word()

void eeprom_write_word (uint16_t *p, uint16_t value)

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

uint16_t value - записываемое слово Возвращаемое значение: нет. Описание: функция выполняет запись 16-битного числа value в EEPROM по адре­су p.

eeprom_write_dword()

void eeprom_write_dword (uint32_t *p, uint32_t value)

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

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

Возвращаемое значение: нет. Описание: функция выполняет запись 32-битного числа value в EEPROM по адре­су p.

eeprom_write_block()

void eeprom_write_block (const void *src, void *dst, size_t n) Параметры:

void *src - указатель на начало области ОЗУ

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

size_t n - количество байт Возвращаемое значение: нет. Описание: функция осуществляет за­пись n байт из области ОЗУ src в область EEPROM dest.

Следует признать, что модуль eeprom.h от релиза к релизу WinAVR пре­терпевает существенные модификации, в частности, неоднократно менялись места­ми параметры функций блочного чтения- записи, что, разумеется, порождает опре­деленные сложности с совместимостью ранее разработанного кода и новой вер­сии компилятора. Поэтому рекомендуется тщательно изучить документацию на све­жий релиз WinAVR, т.к. в нем могут быть сюрпризы.

Из числа приятных сюрпризов, появив­шихся с версии WinAVR 20100110, можно назвать появление «бережных» функций записи EEPROM eeprom_update_xxxx(), где xxxx - это суффикс byte, word, dword или block. Параметры этих фун­кций такие же, как у соответствующих eeprom_write_xxxx(), а отличие в том, что новые функции перед тем, как записать новое значение в ячейку EEPROM, прове­ряют ее текущее значение и, если оба зна­чения одинаковы, то запись в ячейку не про­изводится. Так как ресурс записей EEPROM AVR ограничен 100000 записей, использо­вание новых функций позволяет увеличить живучесть EEPROM без принятия каких-то особых мер.

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

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

fuse-битов AVR

Модуль позволяет разместить в осо­бой секции ELF-файла информацию о со­стоянии fuse-битов, которую может извле­кать программное обеспечение програм­матора для установки fuse-битов при про­граммировании микроконтроллера. Раз­мещение этой информации в ELF-файле осуществляется при компоновке програм­мы. К сожалению, в HEX-формате сведе­ния о состоянии fuse-битов размещены быть не могут.

Данный модуль - универсальный, т.е. ориентирован на весь спектр поддержи­ваемых микроконтроллеров. Необходимо обязательно подключать к проекту модуль io.h, в котором определяются глобальные параметры, используемые затем в моду­ле fuse.h. Сам модуль fuse.h подключа­ется в этом случае автоматически, поэто­му нужды в явном его подключении нет.

В зависимости от типа примененно­го микроконтроллера fuse-биты могут располагаться в младшем, старшем или расширенном fuse-байте. Для каж­дого отдельно взятого fuse-бита вводят­ся константы-маски, соответствующие наименованию fuse-бита, например, FUSE_SPIEN, FUSE_RSTDSBL и т.д.34. Если необходимо установить несколько fuse-битов в одном байте, нужно объединять их при помощи битовой операции AND, т.е. так: (FUSE_SPIEN & FUSE_RSTDISBL & ....).

Для каждого из fuse-байтов конкретно­го микроконтроллера определены значения fuse-битов по умолчанию, которые следует применять, если изменять их не требуется: LFUSE_DEFAULT для младшего байта, HFUSE_DEFAULT для старшего и EFUSE_DEFAULT для расширенного.

Модуль определяет всего одну глобаль­ную переменную-структуру FUSES, к зада­нию начальных значений для которой и сво­дится вся работа с fuse-битами. Данная пе­ременная в зависимости от микроконтрол­лера может быть разного типа: если микро­контроллер содержит всего один fuse-байт, то эта переменная является просто пере­менной типа int8_t; если микроконтроллер имеет 2 fuse-байта, то FUSES представля­ет собой структуру с 2-я полями low и high соответственно типа int8_t каждое; для мик­роконтроллеров с тремя fuse-байтами

FUSES представляет собой структуру с тре­мя полями типа int8_t - low, high и extended.

Наконец, если МК содержит более 3-х fuse- байтов, FUSES определена как массив бай­тов соответствующей длины.

Следует учитывать, что компоновщик использует только значения переменной FUSES, которые были указаны на этапе начальной инициализации, и игнорирует все изменения, которые могли быть сделаны в ходе выполнения программы.

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

Важно, что всегда необходимо инициа­лизировать все поля структуры FUSES.

Суть рассматриваемого модуля заключена в том, что получаемый в результате компиляции elf-файл содержит абсолютно всю информацию, необходимую для правильного программирования микроконтроллера. Остается только решить вопрос, какое именно программное обеспечение в состоянии воспользоваться этой информацией. В какой-то мере эту задачу может решить утилита avrdude, входящая в состав WinAVR, однако, только в связке с другой утилитой avr-objcopy. Avrdude - это универсальный программатор, поддерживающий огромное количество схем для прошивки микроконтроллеров AVR, а утилита avr-objcopy позволяет извлекать из elf-файла информационные блоки о flash, eeprom и fuse-битах (из соответствующих секций) и сохранять их в виде hex-файлов, которые уже могут использоваться avrdude для прошивки. К сожалению, обе эти утилиты имеют немалое количество опций запуска, поэтому в рамках данного изложения не рассматриваются (это планируется сделать позже).

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

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

При обработке прерываний происходит конфликт между декларируемой Си неза­висимостью от аппаратуры, и жесткой при­вязке векторов прерываний к этой самой аппаратуре. Таким образом, любая реали­зация обработки прерываний на Си стано­вится уникальной для конкретной среды программирования.