Особенности процесса самопрограммирования

Особенности процесса самопрограммирования

С точки зрения самопрограммирования, FLASH-память программ разделена на две части. Такое разделение для ATmega8 приведено на рис.1. Это секция прикладной программы Application Section и секция загрузчика Boot Loader Section. Код загрузчика может выполняться только во второй секции. Размер Boot Loader Section на этапе программирования задается двумя битами конфигурации: BOOTSZ1 и BOOTSZ0. У ATmega8 он может составлять 128, 256, 512 и 1024 слова. Сброс конфигурационной ячейки BOOTRST на 0 заставит перенести вектор сброса, нормально расположенный по адресу 0, в самое начало загрузочной секции.

Рис.1 Разделение Flash-памяти у ATmega8

У большинства моделей FLASH-память также разделена по способу доступа на области RWW (Read-While-Write) и NRWW (No Read-While-Write). Различие между ними проявляется только на этапе программирования. В моменты модификации содержимого памяти программ доступ к секции RWW, посредством инструкций lpm, rjmp, rcall и др. запрещен, а их использование может привести к непредсказуемым последствиям. То же самое касается и прерываний, которые должны быть временно запрещены, или перемещены в секцию загрузчика. Размер NRWW всегда совпадает с наибольшим размером Boot Loader Section.

Память программ AVR имеет страничную организацию (размер страницы у разных моделей может составлять 32,64 или 128 слов). Поэтому взаимодействие с FLASH-памятью производится через внутренний буфер обмена. Во время записи, буфер сначала заполняется данными, а затем его содержимое целиком переносится в заданную страницу. Это приводит к небольшим затруднениям, когда, например, необходимо перезаписать только одно или несколько слов. В этом случае придется сначала переписать страницу в SRAM микроконтроллера, затем модифицировать необходимые байты и только потом перенести данные в буфер и произвести запись. Стирание памяти производится также по страницам. Запись страницы, без предварительного стирания, равно как и запись во время изменения памяти FLASH или EEPROM, – невозможна. Распределение памяти ATmega8 приведено на рис.2.

Рис.2 Адресация Flash-памяти при самопрограммировании

Самопрограммирование AVR происходит на двух уровнях. Тип операции задается битами управляющего РВВ SPMCR, а запуск самого процесса командой spm (Store Program Memory). Адресация данных производится с помощью указателя ZH:ZL. В случае ATmega8 биты Z12:Z6 регистра Z задают номер страницы (0…127), а биты Z5:Z1 определяют порядковый номер слова в пределах страницы (0…31). LSB Z0 всегда должен быть равен 0 (адресовать байты 16-разрядных слов нет необходимости). Сами данные, если они необходимы передаются/принимаются в регистровой паре R1:R0.

Активизация инструкции spm происходит в течении 4 машинных циклов после установки бита SPMEN (в некоторых моделях бит носит название SELFPRSEN) в регистре SPMCR. Другие биты SPMCR при совместном использовании с SPMEN, как было сказано выше, определяют род действия команды spm. Кроме того, бит SPMEN служит еще и признаком окончания операции. Он аппаратно сбрасывается на нуль в случае завершения необходимого действия, либо если в течении 4 циклов после его установки не была встречена команда spm. С учетом вышесказанного подпрограмма записи в регистр SPMCR должна выглядеть следующим образом (в R16 передается новое значение SPMCR):

do_spm: in R17,SPMCR ;ожидаем пока не закончится brc R17,SPMEN ;предыдущая операция rjmp do_spm ds1: sbic EECR,EEWE ;ожидаем пока не закончится rjmp ds1 ;запись в EEPROM-память out SPMCR,R16 ;модифицируем регистр SPMCR spm ;в течении 4-х циклов выполняем команду spm ret

Стирание производится установкой битов SPMEN, PGERS в SPMCR и выполнением команды spm в течении четырех машинных циклов. Перед этим действием в регистре Z нужно занести номер страницы (регистры R1, R0 в этом процессе не участвуют):

ldi R16,(1<< PGERS)|(1<< SPMEN) rcall do_spm ;стираем страницу spm .

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

Запись страницы происходит в три этапа: стирание, заполнение данными страничного буфера обмена и, непосредственно, выполнение команды записи. При заполнении буфера каждое 16-разрядное слово заносится в регистровую пару R1:R0 и копируется в буфер установкой бита SPMEN в SPMCR и командой spm. В указателе Z при этом должен находиться номер страницы и текущий адрес слова. После подготовки буфера производится запись страницы посредством установки битов SPMEN, PGWRT в SPMCR и выполнением инструкции spm в течении четырех машинных циклов:

.dseg ;32 слова для записи во FLASH-память page_buffer: .byte 2*PAGESIZE .сseg . ldi R16,(1<< PGERS)|(1<< SPMEN) ;стираем страницу rcall do_spm ;стираем страницу ldi YH,high(page_buffer) ;заносим в указатель Y адрес ldi YL,low(page_buffer) ;начала буфера для записи ldi R17,PAGESIZE ;инициализируем счетчик слов pf1: ld R0,Y+ ld R1,Y+ ldi R16,1<< SPMEN rcall do_spm ;копируем слово из R1:R0 в буфер adiw ZH:ZL,2 ;устанавливаем адрес следующего слова dec R17 brne pf1 ;переносим в страничный буфер все 32 слова subi ZL,PAGESIZE ;восстанавливаем адрес страницы sbci ZH,0 ldi R16,(1<< PGWRT)|(1<< SPMEN) rcall do_spm ;записываем страницу .

Считать память программ, если это необходимо, можно с помощью инструкций lpm/elpm. Однако чтение из Boot Loader Section имеет одну важную особенность: доступ к данным, находящимся в области RWW, после операции стирания/записи страницы FLASH-памяти блокируется. Для разрешения чтения необходимо установить в регистре SPMCR биты SPMEN и RWWSRE и в течении четырех циклов выполнить команду spm:

.dseg ;32 слова для чтения из FLASH-памяти page_buffer: .byte 2*PAGESIZE .сseg . ldi R16,(1<< RWWSRE)|(1<< SPMEN) ;разрешаем доступ к RWW rcall do_spm ldi YH,high(page_buffer) ;заносим в указатель Y адрес ldi YL,low(page_buffer) ;начала буфера для чтения ldi R17,PAGESIZE ;инициализируем счетчик слов rf1: lpm R16,Z+ st Y+,R16 lpm R16,Z+ st Y+,R16 dec R18 brne rf1 ;считываем в буфер все 32 слова .

Кроме FLASH-памяти загрузчик может обращаться также к пространству байтов конфигурации и ячеек защиты микроконтроллера. Перед их считыванием в регистр Z нужно занести адрес байта (0x0000 – младший байт конфигурации, 0x0003 – старший байт конфигурации, 0x0002 – дополнительный байт конфигурации, если он имеется, 0x0001 – байт, содержащий ячейки защиты). Затем в РВВ SPMCR необходимо установить биты SPMEN и BLBSET и в течении трех машинных циклов считать содержимое выбранного байта командой lpm:

clr ZH ;устанавливаем адрес младшего байта конфигурации clr ZL ldi R17,(1<< BLBSET)|(1<< SPMEN) out SPMCR,R17 lpm R16,Z ;считываем младший байт конфигурации в R16 . clr ZH ;устанавливаем адрес старшего байта конфигурации ldi ZL,3 ldi R17,(1<< BLBSET)|(1<< SPMEN) out SPMCR,R17 lpm R16,Z ;считываем старший байт конфигурации в R16 . clr ZH ;устанавливаем адрес байта ячеек защиты ldi ZL,1 ldi R17,(1<< BLBSET)|(1<< SPMEN) out SPMCR,R17 lpm R16,Z ;считываем содержимое ячеек защиты в R16 .

Изменять такие аппаратные настройки, как частота, тип генератора, положение вектора сброса и т.д., boot-loader, к сожалению, не может. Модификация FUSE-битов не из области прикладной программы, не из области загрузчика невозможна. Зато имеется возможность влиять на ячейки защиты BLB12,BLB11,BLB02, BLB01. Для их программирования в регистре Z необходимо указать адрес байта ячеек защиты 0x0001, занести в R0, данные для записи, установить в SPMCR биты SPMEN и BLBSET и в течении четырех циклов выполнить команду spm:

clr ZH ;устанавливаем адрес байта ячеек защиты ldi ZL,1 ldi R16,~((1<< BLB12)|(1<< BLB11)|(1<< BLB02)|(1<< BLB01)) mov R0,R16 ;полная блокировка инструкций lpm и spm ldi R16,(1<< BLBSET)|(1<< SPMEN) rcall do_spm .

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


Категория: Микроконтроллеры
Метки:

Написать коментарий

*
= 3 + 6

Добавить изображение

Последние статьи