Вход

Регистрация
Главная
 

 

Пиротехнические пульты, пиротехническое оборудование
и пиротехника
Pyro Alex RF 48
Open Pyro SFX 8 D
Open Pyro SFX 10/120
Pyro Man 200 M
Spets 150
Приём заказов на изготовление пиротехнических пультов
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Пиропульты - Электроника Форум » Электроника » Микроконтроллеры и ПЛИС » Создание Bootloader’a в AVR мк
Создание Bootloader’a в AVR мк
alexval2007Дата: Среда, 19.05.2010, 16:05 | Сообщение # 1
Электро воспламенитель
Группа: Администраторы
Сообщений: 659
Награды: 7
Репутация: 7
Статус: Offline
Создание Bootloader’a в AVR мк
Введение
На написание данной статьи меня сподвигло практически полное отсутствие какой либо вменяемой информации по теме бутлоадеров на русском языке, и конкретно для чипов основанных на архитектуре AVR.

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

И в один прекрасный день мне на работе дали партийное задание — разработать систему позволяющую дистанционно обновлять прошивку кое-каких устройств, сами железки стоят под взрывозащитными кожухами в шахтах на значительной глубине. Лазить туда и разбирать каждый девайс чтобы воткнуть шлейф ISP понятное дело не самая лучшая идея, однако устройства соединены интерфейсом RS485 это позволяет использовать бутлоадер в проекте.

Конечно можно взять один из OVER чем 9000 готовых бутлоадеров на Сях и доработать напильником, переделать под задачу, но мне давно было интересно разобраться в теме самопрошивки МК. И, думаю, не только мне, поэтому вооружившись даташитом и найдя скудную документацию на утилиту AVRprog я сел за AVR Studio изобетать велосипед — писать свой загрузчик. Естественно на асме (под 8ми битки только на асме пишу).

Так, для разгрева, разработаем проект бутлоадера с прошивкой по RS232 и поддержкой протокола AVRprog v1.4, а дальше можно его заточить хоть под I2C или SPI, RS485 и т. д.

WARNING
Для того чтобы полностью вкурить о чём тут говорится - рекомендуется к прочтению статья DI HALT о использовании бутлоадеров.

Поехали!
Итак, первое, что нам надо сделать, кроме создания нового прожекта, это в меню AVR Studio выбрать опцию отладки бутлоадера, чтобы студия стартовала с адреса первой инструкции бутлоадера, а не 0×0000 для этого (Debug->AVR Simulation Options) выставляем флажок Enable boot reset и стартовый адрес на 0×1E00 – наш загрузчик будет занимать 512 команд.

Теперь накидаем простейший исходник – скажем чтоб выплёвывал на UART 9600/8/n/1 пару символов, это будет юзерское приложение (здесь и далее огрызки кода, подробней в полном исходнике из архива).

Code

Reset:
;Тут код инициализации

main:
ldi  R16, 0x55
rcall  SendUART
ldi  R16, 0xAA
rcall  SendUART
rcall  Delay
jmp  main

Далее начнём писать сам лоадер. Создаём новый модуль пропишем простенькую функцию инициализации UART’а на скорость 19200 (тут надо прописать отдельную инициализацию УАРТа отправки и приёма – надеюсь помните, что если вы используете какую-либо уарт либу из основной области памяти – она будет заблокирована в процессе прошивки и затёрта). Так ну и незабываем про адрес старта, и условие входа в бут загрузчик, стартовый код будет выглядеть примерно так:

Code
.org 0x1E00 ; Для бутака отвели 512 слов
BootLoader:
ldi  R16, low(RAMEND) ; Никуда без стека
out  SPL, R16
ldi  R16, high(RAMEND)
out  SPH, R16

ldi  R16, 0xFF
out  DDRC, R16  ; Тут диоды у нас
cbi  DDRC, 4  ; А тут кнопарь
cbi  PORTC, 4

sbic  PINC, 4  ; Собсно и есть стартовый кондишн – если отпущена кнопка бежим в основную прогу
jmp  Reset

LED3_ON   ; Макрос включения светодиода «Режим программирования»
rcall  InitUART

Далее идёт цикл с ожиданием байтов от AVRprog и их обработкой – довльно рутинный процесс, но поясню на примере запросов процедур идентификации – без неё AVRprog не подхватит ваш чип:

Code
Wait4Command: ; Главный цикл – тут получаем команды от AVRprog
rcall ReadUART

; Тут всё просто – смотрим что в буфере R16 и идём на обработчик
cpi  R16, 'S'  ; Байтик приветствия – надо на него ответить 7и символьным
; идентификатором начинающимся на “AVRxxxx” – у меня например – “AVRm162”
breq  Greething

cpi  R16, 'a'  ; Запрос автоинкремента
breq  AutoInc

cpi  R16, 't'  ; Запрос типа устройства
breq  DeviceType

cpi  R16, 'V'  ; Запрос версии софта – у меня 0.1
breq  SoftwareVersion

cpi  R16, 'b'  ; Запрос поддержки буферизации – отвечаем, что поддерживаем буфер
;размером в одну страницу
breq  SetBufferInfo

cpi R16, 's'

Далее по коду запросы на программирование, но о них позже, а пока что рассмотрим обработчики для этих событий на примере нескольких:

Code
AutoInc:
OutUART 'y'   ; OutUART - макрос вывода байта в UART
rjmp  Wait4Command

SetupLED:
rcall  ReadUART
OutUART 0xD   ; На некоторые команды надо отвечать 0xD.
rjmp  Wait4Command

SoftwareVersion:
OutUART '0'
OutUART '1'
rjmp  Wait4Command

GetSignature:
OutUART 0x1E   ; байтики сигнатуры
OutUART 0x94   ;
OutUART 0x04   ;
rjmp  Wait4Command

GetProgramerType:
OutUART 'S'   ; предствляемся последовательным прошивальщиком =)
rjmp  Wait4Command

SetBufferInfo:
OutUART 'Y'    ; Ответ на запрос размера буфера (в байтах!) – одна страница
OutUART high(PAGESIZEB)  ; PAGESIZEB= PAGESIZE*2;
OutUART low(PAGESIZEB)
rjmp  Wait4Command

Ну чтож вот мы и подошли к самому интересному – работа с флешем.
Запросы на работу с памятью выглядят так:

Code
cpi  R16, 'A'
breq  SetAddress   ; Установка адреса страницы для чтения/записи

cpi  R16, 'g'
breq  ReadBlock   ; Запрос на буферизированное чтение сектора

cpi  R16, 'B'
breq  BufferedWrite   ; Буферизированная запись

cpi  R16, 'e'
breq  EraseChip   ; Очистить чип

Теперь рассмотрим обработчики на это дело. Чтобы понять смысл следующего кода надо представлять себе принцип работы команды SPM – запись в память программ – я объясню как это работает на примере очистки чипа – дальше всё просто как 2 рубля.

Code
EraseChip:
ldi  R18, 112   ; количество страниц на очистку – зависит от чипа
clr  ZH
clr  ZL

doErase:
ldi R17, (1<<PGERS) | (1<<SPMEN)  ; в R17 передаётся параметр в регистр SPMCR
; SPMEN – разрешает вызов команды SPM в следующих 4х тактах; PGERS – команда на очистку
;страницы флеша

rcall  SPMnWAIT
ldi  R17, (1<<RWWSRE) | (1<<SPMEN)  ; ре-инициализация страницы
rcall SPMnWAIT

ldi  R19, PAGESIZE   ; инкремент указателя на страницу
add  ZL, R19
clr  R19
adc  ZH, R19
dec  R18
brne  doErase
OutUART 0xD
rjmp  Wait4Command

Cама процедура вызова SPM (ВХОД: R17 – SPMCR; ZH:ZL – указатель на страницу флеша для выполнения операций R0:R1 – непосредственное слово для записи в буфер флеша.

Code
SPMnWAIT:
out  SPMCR, R17
spm     ; Очищаем/пишем во флеш – зависит от параметра SPMCR

WaitSPM:
in  R16, SPMCR
sbrc  R16, SPMEN
rjmp  WaitSPM
ret

Формат регистра SPMCR

* Bit 7 – SPMIE: SPM Interrupt Enable – разрешение прерывания по окончании записи во флеш
* Bit 6 – RWWSB: Read-While-Write Section Busy – проверка занятости секции
* Bit 5 – Res: Reserved Bit
* Bit 4 – RWWSRE: Read-While-Write Section Read Enable - реинициализация страницы после записи/очистки
* Bit 3 – BLBSET: Boot Lock Bit Set – операции над фьюзами
* Bit 2 – PGWRT: Page Write – запись странциы
* Bit 1 – PGERS: Page Erase - очистка
* Bit 0 – SPMEN: Store Program Memory Enable – разрешение на исполнение SPM в следующие 4 такта.

Итак, подведём небольшой итог:

* Запись выполняется естественно командой SPM, чтение LPM
* Параметры: указатель - ZH:ZL- куда пишем (либо что очищаем), R0:R1 – слово которое пишем по (Z)
* Регистр SPMCR разрешает и определяет поведение команды SPM

Теперь внимательно рассмотрим процедуру записи флеша:
в YH:YL – указатель на начало оперы 0×100
в ZH:ZL – указатель на страницу флеша

WritePage2Flash:
ldi R24, low(PAGESIZEB) ; счётчик
ldi R25, high(PAGESIZEB)

Write2FlashBuffer:
ld R0, Y+
ld R1, Y+
ldi R17, (1< ; флеша - в SPMCR устанавливаем только SPMEN!!!
rcall SPMnWAIT
adiw ZH:ZL, 2 ; указатель на текущий адрес записи
sbiw R25:R24, 2
brne Write2FlashBuffer

; А ТЕПЕРЬ МОМЕНТ ИСТИННЫ – ЗАПИСЬ СТРАНИЦЫ ВО ФЛЕШ

subi ZL, low(PAGESIZEB) ; восстановление указателя
sbci ZH, high(PAGESIZEB)
ldi R17, (1< rcall SPMnWAIT

ldi R17, (1< rcall SPMnWAIT
ret

Вот так всё на самом деле просто выглядит!
Ну и часть обработчика вызывающего этот код:

тут очистка памяти и приём одной страницы через UART

; вызываем процедуру записи страницы
ldi YH, high(SRAM_START)
ldi YL, low(SRAM_START) ; Буфер в начале RAM
rcall WritePage2Flash

; Ну незабываем делать автоинкремент страницы – обязательно если при
; инициализации ответили ‘y’ на ‘A’ запрос.

ldi R19, PAGESIZE
add ZL, R19
clr R19
adc ZH, R19

OutUART 0xD ; говорим AVRprog что записали страницу и всё ок!

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

SetAddress:
rcall ReadUART
mov ZH, R16
rcall ReadUART
mov ZL, R16 ; ну всё просто сохраняем в регистры ZH:ZL адрес
;куда писать и не трогаем его больше, а н-нееет…

lsl ZL ; адрес надо преобразовать в байтовый т. е. сдвинуть на 1 битик влево =)
rol ZH

OutUART 0xD ; рапортуем об успешной установке адреса

Злоключение или это ещё не конец?
Таким образом мы рассмотрели наиболее ключевые моменты. На первый взгляд процедура самозаливки кода может показаться сложной, но на самом деле всё очень просто и сводится к реализации интерфейса для программатора - ожидать и выполнять команды. Также следует стараться уделять особое внимание некоторым неочевидным моментам (подводные камни) с которыми возможно столкнуться при написании своего проекта, для этого писалась статья и откомментирован исходник.

BootExample.zip

Кстати за кадром осталась работа с прерываниями в бутлоадере (которые могут быть перемещены в секцию бутлоадера, если вы конечно их используете), установке фьюз битов, ну или перезаписи самого бутлоадера самим собой (до конца не разобрался, но такое извращение судя по всему поддерживается) –- это оставляю в качестве домашнего задания читателю. А если и возникнут сложности, либо найдутся глюки в программе, (что весьма вероятно т. к. код толком не обкатан, но как говорится – отладчик всему голова) то, возможно, распишу это всё в отдельной статье.

Автор: Гринёв Роман aka Exp10der.
Источник: http://easyelectronics.ru

 
MRACOBESSS-Дата: Четверг, 20.05.2010, 14:58 | Сообщение # 2
Рядовой
Группа: Проверенные
Сообщений: 11
Награды: 1
Репутация: 0
Статус: Offline
дяденька, а ты сейчас с кем разговаривал? wacko
 
alexval2007Дата: Четверг, 20.05.2010, 18:06 | Сообщение # 3
Электро воспламенитель
Группа: Администраторы
Сообщений: 659
Награды: 7
Репутация: 7
Статус: Offline
ну это для тех кто в теме но им не хватает небольшого толчка раздел называться Микроконтроллеры и ПЛИС если ты не в к biggrin курсе темы марш читать обучалку http://radiokot.ru/start/mcu_fpga/avr/
 
dimmer122Дата: Воскресенье, 18.09.2016, 00:53 | Сообщение # 4
Рядовой
Группа: Пользователи
Сообщений: 1
Награды: 0
Репутация: 0
Статус: Offline
Пилил я эту тему тоже - avr-assm.ru
 
alexval2007Дата: Суббота, 19.11.2016, 10:51 | Сообщение # 5
Электро воспламенитель
Группа: Администраторы
Сообщений: 659
Награды: 7
Репутация: 7
Статус: Offline
неплохой проект взял на заметку
 
Пиропульты - Электроника Форум » Электроника » Микроконтроллеры и ПЛИС » Создание Bootloader’a в AVR мк
  • Страница 1 из 1
  • 1
Поиск:


Rambler's Top100 Пиротехника, салюты, фейерверки. Яндекс цитирования
www.alexval2007.ucoz.ru © 2008