Главная » Микроконтроллеры
Призовой фонд
на май 2017 г.
1. Тестер компонентов MG328
Паяльник
2. Осциллограф DSO138
Паяльник
3. Регулируемый паяльник 60 Вт
Паяльник
4. 100 руб.
От пользователей

Перенос программы между разными моделями

Иногда может возникнуть необходимость в переносе программы с одной модели AVR на другую. Если под рукой находится исходный текст, то в этом нет ни какой проблемы. Другое дело, когда в распоряжении имеется только 16-тиричный hex-файл. В этом случае можно воспользоваться описанным ниже способом, затратив лишь немного времени на доработку программы.

Сразу необходимо оговорится, что подобное возможно только в том случае, если перенос программного обеспечения производится на микроконтроллер с объемом FLASH-памяти превышающем исходный, как минимум в два раза. Модели должны быть также совместимы на уровне РВВ, используемых в программе. В значительной степени все вышесказанное относится, например, к моделям ATmega8535, ATmega16, ATmega32 и др. В дальнейшем все примеры будут относиться к переносу программы с ATmega8535 на ATmega16.

Выполнение кода, предназначенного для 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.

Перейти к следующей части:

Теги:

Котов Игорь Юрьевич Опубликована: 2012 г. 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (0) | Я собрал (0) | Подписаться

Статью еще никто не комментировал. Вы можете стать первым.
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется напряжение?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Программатор Pickit3
Программатор Pickit3
Набор для сборки - LED лампа Осциллограф DSO138
вверх