Иногда может возникнуть необходимость в переносе программы с одной модели AVR на другую. Если под рукой находится исходный текст, то в этом нет ни какой проблемы. Другое дело, когда в распоряжении имеется только 16-тиричный hex-файл. В этом случае можно воспользоваться описанным ниже способом, затратив лишь немного времени на доработку программы.
Сразу необходимо оговорится, что подобное возможно только в том случае, если перенос программного обеспечения производится на микроконтроллер с объемом FLASH-памяти превышающем исходный, как минимум в два раза. Модели должны быть также совместимы на уровне РВВ, используемых в программе. В значительной степени все вышесказанное относится, например, к моделям ATmega8535, ATmega16, ATmega32 и др. В дальнейшем все примеры будут относиться к переносу программы с ATmega8535 на ATmega16.
Рис.1 Выполнение кода, предназначенного для ATmega8535,
в адресном пространстве модели ATmega16
Непосредственному выполнению программного кода в адресном пространстве нового процессора помешают два обстоятельства. Первое из них это несоответствие между таблицами векторов прерывания. В пределах целого семейства не существует двух микроконтроллеров, у которых адреса векторов совпадают. Кроме того и размеры самих таблиц у всех моделей различны. Вторая, значительно более серьезная проблема, проявляется в искаженном действии инструкций rjmp k, rcall k, brbs k, brbc k и всех остальных, осуществляющих относительные переходы (относительно текущего значения программного счетчика) в памяти программ. Понять это можно, если взглянуть на рис.1. На нем изображено адресное пространство памяти программ микроконтроллеров ATmega8535 и ATmega16. Допустим, что в слове программ под номером 0x0E00 встретится инструкция rjmp PC+0x0400. К программному счетчику при этом будет добавлено смещение 0x0400, в результате чего произойдет относительный переход по новому адресу. Очевидно, что этим адресом будет являться 0x0E00+0x0400 = 0x0200. Переполнение 0x1000 у 12-разрядного программного счетчика программ ATmega8535 будет отброшено. Совсем иначе обстоит дело с микроконтроллером ATmega16, у которого на борту расположено 8192 16-разрядных слова программ и, соответственно, 13-битный счетчик команд. Переполнение в этом случае не произойдет и после перехода rjmp PC+0x0400 программа продолжит свое выполнение с команды по адресу 0x1200. Функционирование устройства будет нарушено.
Проблема с несоответствием векторов прерываний решается достаточно легко. У AVR-микроконтроллеров положения вектора сброса и таблицы прерываний могут быть перемещены в область загрузчика
.cseg .org LARGEBOOTSTART jmp initial ;начало основной прграммы jmp 0x0001 ;внешнее прерывание 0 ATmega8535 jmp 0x0002 ;внешнее прерывание 1 ATmega8535 jmp 0x0003 ;совпадение TCNT2 и OCR2 ATmega8535 jmp 0x0004 ;переполнение TCNT2 ATmega8535 jmp 0x0005 ;захват в ICP1 ATmega8535 jmp 0x0006 ;совпадение TCNT1 и OCR1A ATmega8535 jmp 0x0007 ;совпадение TCNT1 и OCR1B ATmega8535 jmp 0x0008 ;переполнение TCNT1 ATmega8535 jmp 0x0009 ;переполнение TCNT0 ATmega8535 jmp 0x000A ;прерывание от модуля SPI ATmega8535 jmp 0x000B ;получение байта по USART ATmega8535 jmp 0x000C ;опустошение UDR в USART ATmega8535 jmp 0x000D ;передача байта по USART ATmega8535 jmp 0x000E ;прерывание от АЦП ATmega8535 jmp 0x000F ;завершение записи в EEPROM ATmega8535 jmp 0x0010 ;прерывание от компаратора ATmega8535 jmp 0x0011 ;прерывание от модуля TWI ATmega8535 jmp 0x0012 ;внешнее прерывание 2 ATmega8535 jmp 0x0013 ;совпадение TCNT0 и OCR0 ATmega8535 jmp 0x0014 ;завершение выполнения spm ATmega8535 initial: ldi R16,1 << IVCE ;таблицу векторов прерывания out GICR,R16 ;переносим в область загрузчика ldi R16,1 << IVSEL out GICR,R16 jmp 0 ;переходим на начало программы
Для этого необходимо сбросить FUSE-бит BOOTRST. Биты BOOTSZ1: BOOTSZ0 будут определять размер Boot Loader Section (см. разд. Самопрограммирование AVR). В данном примере BOOTSZ1:BOOTSZ0=00 (размер загрузочной секции 1024 слова, сброс по адресу LARGEBOOTSTART=0x1C00).
Таким образом, каждый раз после запуска устройства программа будет стартовать по адресу 0x1C00 и начинаться с метки initial. Последовательность следующих пяти команд фиксирует таблицу векторов прерывания в области загрузчика и передает управление на начало основной программы с нулевого адреса.
Допустим, в ходе работы устройства в основной программе возникает прерывание от переполнения таймера-счетчика 0. Процессор перейдет на обработчик прерывания по адресу 0x1C12, что соответствует положению вектора прерывания от таймера 0 для модели ATmega16. Слово программ 0x1C12 должно содержать инструкцию перехода на адрес соответствующего вектора в основной программе для модели ATmega8535 (в данном случае jmp 0x0009). Тоже самое касается и всех остальных векторов из области загрузчика.
Теперь рассмотрим, как можно исправить действия различного рода инструкций относительного перехода. Для этого все свободные адреса с 0x1000 по 0x1FFF в памяти программ ATmega16 “забиваются” командами вызова подпрограммы new_adr:
.cseg .org 0x1000 . rcall new_adr rcall new_adr rcall new_adr . .org 0x1800 new_adr: push R16 in R16,SREG push R16 push ZH push ZL in ZH,SPH in ZL,SPL ldd R16,Z+6 subi R16,low(0x1001) std Z+6,R16 ldd R16,Z+5 sbci R16,high(0x1001) std Z+5,R16 pop ZL pop ZH pop R16 out SREG,R16 pop R16 ret rcall new_adr rcall new_adr . rcall new_adr
Смысл подпрограммы new_adr заключается в следующем. Когда возникнет ошибочный переход в запрещенное адресное пространство, например, переход по адресу 0x1200 вместо 0x0200, то после вызова rcall new_adr адрес возврата 0x1201 (возврат на следующую команду) будет сохранен в стеке. В теле new_adr этот адрес (размещается в SRAM) подлежит коррекции. В нашем случае из него нужно вычесть смещение 0x1001. После завершения new_adr программа продолжит свое выполнение не с команды по адресу PC = 0x1201, а с нового места PC = 0x1201 - 0x1001 = 0x0200.
Подпрограмма new_adr должна находится по адресу 0x1800, чтобы быть в пределах досягаемости инструкций rcall k (±2047 слов).
В файле m8535to16.asm находится полный текст программы, а в m8535to16.hex, соответственно исполняемый код. Если возникнет необходимость в переносе программы с ATmega8535 на ATmega16, то в любом текстовом редакторе к исходному hex-файлу нужно присоединить файл m8535to16.hex и загрузить новую прошивку в микроконтроллер (установки FUSE-битов BOOTSZ1:BOOTSZ0=00, BOOTRST=0):
:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;файл предназначенный :XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;для ATmega8535 ̣̣̣̣̣̣̣̣ ̣̣̣̣̣̣̣̣ :XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX :XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX :00000001FF ;удаление строки окончания файла! + :020000020000FC ;добавление к исходному hex-файлу :10200000FFD7FED7FDD7FCD7FBD7FAD7F9D7F8D73C ;файла m8535to16.hex :10201000F7D7F6D7F5D7F4D7F3D7F2D7F1D7F0D76C ̣̣̣̣̣̣̣̣ ̣̣̣̣̣̣̣̣ :103FE0000FD80ED80DD80CD80BD80AD809D808D8B5 :103FF00007D806D805D804D803D802D801D800D8E5 :00000001FF
С очень большой вероятностью модифицированная программа успешно заработает на новой модели. Правда такая доработка накладывает и ряд ограничений. Переход, в случае попадания в запрещенный диапазон адресов, будет длиться на 37 циклов дольше и потребует в стеке дополнительных 8 б. Вызов каждого прерывания будет отложен на 2 цикла. И, конечно, каждый переход из основной программы в область 0x1000…0x1FFF обязательно должен попадать на инструкцию rcall new_adr.
Перейти к следующей части: Самопрограммирование микроконтроллеров AVR - Область применения
Комментарии (0) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация