Добрался - таки я до загрузчика и, пользуясь случаем, решил немного расписать последовательность.
Думаю кому-нибудь вроде меня пригодится для пинка.
Значит так, лезем
сюда, забираем
вот это.
Кстати, спасибо
DI HALT за то, что "озвучил" этот bootloader на родном языке.
Так вот, из всего этого мне понадобились makefile и папка со скриптами. В makefile необходимо: выбрать тип проца, выбрать размер загрузчика, разрешить прерывания, ну и вроде бы все. Дальше - творческая работа.
Чуть не забыл, после правки makefile необходимо выполнить
Rebild All, иначе изменения не производятся.
Для примера приведу исходник демо-моргалки, которая при включении моргает десять раз с частотой 1Гц, затем прошивает основную программу, после чего передает ей управление. В задачу основной программы входит моргание сигнала "SOS".
CODE
#include <avr/io.h>
#include <avr/boot.h>
#include <avr/interrupt.h>
uint8_t Data[816] = { // Это бинарник основной (демо) программы, которую необходимо прошить
0x0C, 0x94, 0x46, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00,
0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00,
0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00,
0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x67, 0x00, 0x0C, 0x94, 0x65, 0x00,
0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00,
0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00,
0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00,
0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00,
0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x0C, 0x94, 0x65, 0x00, 0x11, 0x24, 0x1F, 0xBE,
0xCF, 0xEF, 0xD0, 0xE1, 0xDE, 0xBF, 0xCD, 0xBF, 0x11, 0xE0, 0xA0, 0xE0, 0xB1, 0xE0, 0xE0, 0xE3,
0xF3, 0xE0, 0x00, 0xE0, 0x0B, 0xBF, 0x02, 0xC0, 0x07, 0x90, 0x0D, 0x92, 0xA0, 0x30, 0xB1, 0x07,
0xD9, 0xF7, 0x11, 0xE0, 0xA0, 0xE0, 0xB1, 0xE0, 0x01, 0xC0, 0x1D, 0x92, 0xA1, 0x30, 0xB1, 0x07,
0xE1, 0xF7, 0x0E, 0x94, 0x82, 0x00, 0x0C, 0x94, 0x96, 0x01, 0x0C, 0x94, 0x00, 0x00, 0x1F, 0x92,
0x0F, 0x92, 0x0F, 0xB6, 0x0F, 0x92, 0x11, 0x24, 0x8F, 0x93, 0xDF, 0x93, 0xCF, 0x93, 0xCD, 0xB7,
0xDE, 0xB7, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23, 0x29, 0xF0, 0x80, 0x91, 0x00, 0x01, 0x81, 0x50,
0x80, 0x93, 0x00, 0x01, 0xCF, 0x91, 0xDF, 0x91, 0x8F, 0x91, 0x0F, 0x90, 0x0F, 0xBE, 0x0F, 0x90,
0x1F, 0x90, 0x18, 0x95, 0xDF, 0x93, 0xCF, 0x93, 0xCD, 0xB7, 0xDE, 0xB7, 0xEE, 0xE4, 0xF0, 0xE0,
0x81, 0xE0, 0x80, 0x83, 0xA7, 0xE5, 0xB0, 0xE0, 0xE7, 0xE5, 0xF0, 0xE0, 0x80, 0x81, 0x84, 0x60,
0x8C, 0x93, 0xA2, 0xE2, 0xB0, 0xE0, 0xE2, 0xE2, 0xF0, 0xE0, 0x80, 0x81, 0x80, 0x68, 0x8C, 0x93,
0x78, 0x94, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81, 0x80, 0x68, 0x8C, 0x93,
0x84, 0xE1, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2,
0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81, 0x8F, 0x77, 0x8C, 0x93, 0x82, 0xE3, 0x80, 0x93,
0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2,
0xF0, 0xE0, 0x80, 0x81, 0x80, 0x68, 0x8C, 0x93, 0x84, 0xE1, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91,
0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81,
0x8F, 0x77, 0x8C, 0x93, 0x82, 0xE3, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23,
0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81, 0x80, 0x68, 0x8C, 0x93,
0x84, 0xE1, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2,
0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81, 0x8F, 0x77, 0x8C, 0x93, 0x84, 0xE6, 0x80, 0x93,
0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2,
0xF0, 0xE0, 0x80, 0x81, 0x80, 0x68, 0x8C, 0x93, 0x86, 0xE4, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91,
0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81,
0x8F, 0x77, 0x8C, 0x93, 0x88, 0xE2, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23,
0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81, 0x80, 0x68, 0x8C, 0x93,
0x86, 0xE4, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2,
0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81, 0x8F, 0x77, 0x8C, 0x93, 0x88, 0xE2, 0x80, 0x93,
0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2,
0xF0, 0xE0, 0x80, 0x81, 0x80, 0x68, 0x8C, 0x93, 0x86, 0xE4, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91,
0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81,
0x8F, 0x77, 0x8C, 0x93, 0x84, 0xE6, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23,
0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81, 0x80, 0x68, 0x8C, 0x93,
0x84, 0xE1, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2,
0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81, 0x8F, 0x77, 0x8C, 0x93, 0x82, 0xE3, 0x80, 0x93,
0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2,
0xF0, 0xE0, 0x80, 0x81, 0x80, 0x68, 0x8C, 0x93, 0x84, 0xE1, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91,
0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81,
0x8F, 0x77, 0x8C, 0x93, 0x82, 0xE3, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23,
0xE1, 0xF7, 0xA3, 0xE2, 0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81, 0x80, 0x68, 0x8C, 0x93,
0x84, 0xE1, 0x80, 0x93, 0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0xA3, 0xE2,
0xB0, 0xE0, 0xE3, 0xE2, 0xF0, 0xE0, 0x80, 0x81, 0x8F, 0x77, 0x8C, 0x93, 0x8A, 0xEF, 0x80, 0x93,
0x00, 0x01, 0x80, 0x91, 0x00, 0x01, 0x88, 0x23, 0xE1, 0xF7, 0x03, 0xCF, 0xF8, 0x94, 0xFF, 0xCF
};
// Функция writeFlashPage записывает одну страницу флэш,
// принимает: номер записываемой страницы
// размер записываемых данных (в байтах)
// адрес, откуда брать данные для записи
void writeFlashPage(uint8_t number, uint16_t size, uint8_t* pData){
uint32_t pagestart = number * SPM_PAGESIZE;
uint32_t baddr = pagestart;
uint16_t data;
uint8_t *tmp = pData;
do{
data = *tmp++;
data |= *tmp++ << 8;
boot_page_fill(baddr, data); // Заполнить буфер СЛОВАМИ данных
baddr += 2; // Перейти к следующему слову в памяти
size -= 2; //
}while(size); // Выполнять, пока не достигнут конец буфера
boot_page_write(pagestart); // Записать заполненный буфер во флеш
boot_spm_busy_wait(); // Дождаться окончания выполнения этой операции
boot_rww_enable(); // Разрешить доступ к секции RWW
return;
}
volatile uint8_t time = 0;
ISR(TIMER1_OVF_vect){ // Обработчик прерывания таймера
if(time)
--time;
}
void main(void){
TCCR1B = _BV(CS10); // clk
TIMSK |= _BV(TOIE1); // Разрешить прерывание по переполнению
MCUCR = (1<<IVCE); // Разрешить изменение положения таблицы прерываний
MCUCR = (1<<IVSEL); // Изменить положение таблицы
DDRE |= _BV(PE7); // Эта нога будет "дергаться"
asm("sei");
for(uint8_t i=0; i<20; ++i){ // Поморгать лампой десять раз
PORTE ^= _BV(PE7);
time = 100; // Задать время паузы
while(time); // Дождаться, пока таймер T1 обнулит time
}
// Далее начинается непосредственно перепрошивка контроллера
// В данном случае используется Mega128, размер страницы которой 256 байт, т.е SPM_PAGESIZE = 256
writeFlashPage(0, SPM_PAGESIZE, &Data[SPM_PAGESIZE*0]);
writeFlashPage(1, SPM_PAGESIZE, &Data[SPM_PAGESIZE*1]);
writeFlashPage(2, SPM_PAGESIZE, &Data[SPM_PAGESIZE*2]);
writeFlashPage(3, sizeof(Data) - 768, &Data[SPM_PAGESIZE*3]);
asm("cli");
MCUCR |= _BV(IVCE); // Вернуть положение таблицы прерываний на начало
MCUCR &= ~(_BV(IVSEL) | _BV(IVCE));
void (*funcptr)(void) = 0x0000; // Указатель на функцию с адресом 0x0000
funcptr(); // Запустить выполнение основной программы
return;
}
Нажмите для просмотра прикрепленного файлаСпасибо всем тем, кто пнул меня в правильном направлении.
з.ы. будут сложности, буду ныть дальше.