Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не выходит одолеть прерывания в Bootloader'е
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Sirko
За основу было взято вот Это. Вернее хочу использовать Makefile от сюда.
CODE
#include <stdint.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/boot.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#if defined(BOOTLOADERHASNOVECTORS)
#warning "This Bootloader does not link interrupt vectors - see makefile"
/* make the linker happy - it wants to see __vector_default */
// void __vector_default(void) { ; }

void __vector_default(void) { ; }
#endif

volatile unsigned char b = 0;

ISR(TIMER0_COMP_vect){
b = 1;
}

ISR(TIMER0_OVF_vect){
b = 1;
}

int main(void){

TCCR0 = _BV(CS02) | _BV(CS00);
OCR0 = 100;
TIMSK |= _BV(OCIE0) | _BV(TOIE0);
MCUCR |= (1<<IVCE); // Enable change of Interrupt Vectors
MCUCR |= (1<<IVSEL); // Move interrupts to Boot Flash section


DDRE |= _BV(PE7);
unsigned long x = 0;
while(1){
asm("sei");
x = (cool.gif ? (1UL<<15) : (1UL<<18);
while(--x){asm("nop");}
PORTE ^= _BV(PE7);
}
return 0;
}
Тест не мудреный, Если прерывания запретить, то лампа моргает редко. Если разрешить, - то почащще. А в моем случае, при разрешении прерывания она не горит вовсе. Вероятно при наступлении прерывания происходит улет в ???.
Проц - Mega128, компилятор - WinAVR-20100110.
LDFLAGS += -Wl,--section-start=.text=0x1E000, наверное
НЕХ на выходе начинается вот так:
:020000021000EC
:10E0000011241FBECFEFD0E1DEBFCDBF11E0A0E0F5
Фьюзы настроены на 4кБ, addr-$F000

Что где править, ума не приложу.
А проект, если понадобится прилагаю.
Нажмите для просмотра прикрепленного файла
Vetal-Soft
Скорее всего заморочка с измерением памяти программ: В GCC - байты, у Atmel - слова.
Настройте фъюзы на 2k.
Sirko
Цитата
Скорее всего...

Скорее всего. Кто бы носом ткнул.

Цитата
Настройте фъюзы на 2k

Нажмите для просмотра прикрепленного файла

Полученый на выходе HEX:
:020000021000EC
:10F0000011241FBECFEFD0E1DEBFCDBF11E0A0E0E5
:10F01000B1E0E0EDF0EF01E00BBF02C007900D9210
:10F02000A030B107D9F711E0A0E0B1E001C01D9216
:10F03000A130B107E1F70E9440F80C9466F80C94F7
:10F0400021F808951F920F920FB60F9211248F93FB
:10F0500081E0809300018F910F900FBE0F901F9061
:10F0600018951F920F920FB60F9211248F9381E083
:10F07000809300018F910F900FBE0F901F901895F5
:10F0800085E083BF84E681BF87B7836087BF85B78C
:10F09000816085BF85B7826085BF179A789480911B
:10F0A0000001882329F480E090E0A4E0B0E006C0ED
:10F0B00080E090E8A0E0B0E001C000000197A10965
:10F0C000B109D9F783B1805883B9E8CFF894FFCF5D
:040000031000F000F9
:00000001FF

т.е. 0x1F000 байт / 2 = 0xF800 слов, что вроде сходится с картинкой программатора.
Прерывания разрешил, страницу векторов тоже поменял, какого рожна ему нужно?



Кстати, за одно хочу уточнить такой момент:
:02 0000 02 1000 EC
Если здесь двойка, значит последующее за ней двухбайтовое значение отражает: на сколько последующие данные будут сдвинуты относительно их текущего адреса. Если значение - 0000, значит заполняется первая половина флэша (mega128); если 1000 - значит вторая половина; если 2000 - значит сегмент будет 128 - 192КБ (в более емких процах).
Поправьте, если я ошибаюсь. И еще, для EEPROM какие то обрамления секций будут в хексе, или разница только в расширении? Если в приведенной строке вместо 02 будет 03, значит последующее значение за ней - это адрес стартапа программы, и на эту строку можно забить при парсинге.

Vetal-Soft
У Вас в makefile:
Код
#/* Select Boot Size in Words (select one, comment out the others) */
## NO! BOOTSIZE=128
## NO! BOOTSIZE=256
## BOOTSIZE=512
## BOOTSIZE=1024
BOOTSIZE=2048
## BOOTSIZE=4096


2 кБайта, а в программаторе 2 кСлова
defunct
Цитата(Sirko @ Apr 11 2011, 03:06) *
LDFLAGS += -Wl,--section-start=.text=0x1E000, наверное

0x1E000 - это начало 8kbyte'ой boot секции.


Для примера кусочек xml из IAR'а
/* Code (flash) segments 8KB BOOT section */
-D_..X_INTVEC_SIZE=8C /* 4 bytes * 35 vectors */
-D_..BOOT_START=1E000
-D_..BOOT_INTVEC_END=1E08C
-D_..BOOT_FLASH_TEND=1E0FF
-D_..BOOT_FLASH_NEND=1FFFF /* End of near BOOT flash memory */
-D_..BOOT_FLASH_END=1FFFF /* End of BOOT flash memory */
alag57
Попробуйте так:
Код
    //MCUCR = (1<<IVCE);        // Enable change of Interrupt Vectors
    //MCUCR = (1<<IVSEL);        // Move interrupts to Boot Flash section
    asm("ldi r24, 1");
    asm("out 0x35, r24");
    asm("ldi r24, 2");
    asm("out 0x35, r24");

Похоже вы не укладываетесь в отведенные 4 такта на изменение начала таблицы векторов.
Sirko
Цитата
Похоже вы не укладываетесь в... Попробуйте так:

Обратил внимание, что в "Попробуйте так:" в регистре MCUCR сначала выставляется флаг IVCE, а в последствии вместо него флаг IVCEL. В моем коде эти биты в конечном итоге взводились оба.
Исправил код исходя из совета:

MCUCR = (1<<IVCE); // Enable change of Interrupt Vectors
MCUCR = (1<<IVSEL); // Move interrupts to Boot Flash section

Лампа заморгала, - заморгала с частотой отражающей отсутствие деятельности обработчиков прерывания.
Так же само ведет себя и мой код, если закоментировать SEI.

Стало быть в отведенные 4 такта я укладываюсь, прерывания таки генерятся и теоретически обрабатываются. Только вот что на самом деле творится в момент перехода к обработчику, - неясно. Лампа не горит вовсе.
Так, что если это не опечатка, то alag57 пусть возьмет это на заметку.

Цитата
0x1E000 - это начало 8kbyte'ой boot секции

Вырезка из Маке
Код
## BOOTSIZE=1024
BOOTSIZE=2048
## BOOTSIZE=4096
.
.
.
ifeq ($(BOOTSIZE), 2048)
MT_BOOTLOADER_ADDRESS = 0x1F000
endif

0x1F000 / 2 = 0xF800 т.е. два "киловорда до финиша", во всяком случае в фьюзах программатора фигурирует это значение

Вырезка из HEX
:020000021000EC
:10F0000011241FBECFEFD0E1DEBFCDBF11E0A0E0E5
:10F01000B1E0ECECF0EF01E00BBF02C007900D9205
Вроде как сходится
SysRq
Цитата(Sirko @ Apr 12 2011, 22:29) *
Лампа заморгала, - заморгала с частотой отражающей отсутствие деятельности обработчиков прерывания.
И правильно, ибо у вас таблицы векторов-то нету:
Цитата
# /* Select if bootloader should include the inverrupt-vectors
# when selecting 'no' here, the bootloader must not use
# any interrupts and the modified linker-scripts are used. */
##BOOTINTVEC=yes
BOOTINTVEC=no

Sirko
Спасибо, не видел. Исправил.
К сожалению пока-что результат не изменился.

Попробовал запустить HEX в отладчике студии. Курсор стартует с адреса 0x00. Ну это скорее всего глюк студии. Переставляю курсор на 0xF800. Стартую. Выставляю флажок TOV0 и наблюдаю перелет к 0xF020. Если учесть, что номер вектора перепелнения T0 - №16 тобишь 0x20, значит таблица начинается с 0xF000. А мне нужно 0xF800. Это конечно тоже можно списать на отладчик, но железо по прежнему мертво.

Прилагаю дизасемблер, может пригодится.
CODE
+0000F7FD: FFFF ??? Data or unknown opcode
+0000F7FE: FFFF ??? Data or unknown opcode
+0000F7FF: FFFF ??? Data or unknown opcode

+0000F800: 940CF846 JMP 0x0000F846 Jump
+0000F802: 940CF865 JMP 0x0000F865 Jump
+0000F804: 940CF865 JMP 0x0000F865 Jump
+0000F806: 940CF865 JMP 0x0000F865 Jump
+0000F808: 940CF865 JMP 0x0000F865 Jump
+0000F80A: 940CF865 JMP 0x0000F865 Jump
+0000F80C: 940CF865 JMP 0x0000F865 Jump
+0000F80E: 940CF865 JMP 0x0000F865 Jump
+0000F810: 940CF865 JMP 0x0000F865 Jump
+0000F812: 940CF865 JMP 0x0000F865 Jump
+0000F814: 940CF865 JMP 0x0000F865 Jump
+0000F816: 940CF865 JMP 0x0000F865 Jump
+0000F818: 940CF865 JMP 0x0000F865 Jump
+0000F81A: 940CF865 JMP 0x0000F865 Jump
+0000F81C: 940CF865 JMP 0x0000F865 Jump
+0000F81E: 940CF867 JMP 0x0000F867 Jump <---- Вроде, как оно
+0000F820: 940CF876 JMP 0x0000F876 Jump <----
+0000F822: 940CF865 JMP 0x0000F865 Jump
+0000F824: 940CF865 JMP 0x0000F865 Jump
+0000F826: 940CF865 JMP 0x0000F865 Jump
+0000F828: 940CF865 JMP 0x0000F865 Jump
+0000F82A: 940CF865 JMP 0x0000F865 Jump
+0000F82C: 940CF865 JMP 0x0000F865 Jump
+0000F82E: 940CF865 JMP 0x0000F865 Jump
+0000F830: 940CF865 JMP 0x0000F865 Jump
+0000F832: 940CF865 JMP 0x0000F865 Jump
+0000F834: 940CF865 JMP 0x0000F865 Jump
+0000F836: 940CF865 JMP 0x0000F865 Jump
+0000F838: 940CF865 JMP 0x0000F865 Jump
+0000F83A: 940CF865 JMP 0x0000F865 Jump
+0000F83C: 940CF865 JMP 0x0000F865 Jump
+0000F83E: 940CF865 JMP 0x0000F865 Jump
+0000F840: 940CF865 JMP 0x0000F865 Jump
+0000F842: 940CF865 JMP 0x0000F865 Jump
+0000F844: 940CF865 JMP 0x0000F865 Jump
+0000F846: 2411 CLR R1 Clear Register
+0000F847: BE1F OUT 0x3F,R1 Out to I/O location
+0000F848: EFCF SER R28 Set Register
+0000F849: E1D0 LDI R29,0x10 Load immediate
+0000F84A: BFDE OUT 0x3E,R29 Out to I/O location
+0000F84B: BFCD OUT 0x3D,R28 Out to I/O location
+0000F84C: E011 LDI R17,0x01 Load immediate
+0000F84D: E0A0 LDI R26,0x00 Load immediate
+0000F84E: E0B1 LDI R27,0x01 Load immediate
+0000F84F: E5E8 LDI R30,0x58 Load immediate
+0000F850: EFF1 LDI R31,0xF1 Load immediate
+0000F851: E001 LDI R16,0x01 Load immediate
+0000F852: BF0B OUT 0x3B,R16 Out to I/O location
+0000F853: C002 RJMP PC+0x0003 Relative jump
+0000F854: 9007 ELPM R0,Z+ Extended load program memory and postincrement
+0000F855: 920D ST X+,R0 Store indirect and postincrement
+0000F856: 30A0 CPI R26,0x00 Compare with immediate
+0000F857: 07B1 CPC R27,R17 Compare with carry
+0000F858: F7D9 BRNE PC-0x04 Branch if not equal
+0000F859: E011 LDI R17,0x01 Load immediate
+0000F85A: E0A0 LDI R26,0x00 Load immediate
+0000F85B: E0B1 LDI R27,0x01 Load immediate
+0000F85C: C001 RJMP PC+0x0002 Relative jump
+0000F85D: 921D ST X+,R1 Store indirect and postincrement
+0000F85E: 30A1 CPI R26,0x01 Compare with immediate
+0000F85F: 07B1 CPC R27,R17 Compare with carry
+0000F860: F7E1 BRNE PC-0x03 Branch if not equal
+0000F861: 940EF885 CALL 0x0000F885 Call subroutine
+0000F863: 940CF8AA JMP 0x0000F8AA Jump
+0000F865: 940CF800 JMP 0x0000F800 Jump
+0000F867: 921F PUSH R1 Push register on stack
+0000F868: 920F PUSH R0 Push register on stack
+0000F869: B60F IN R0,0x3F In from I/O location
+0000F86A: 920F PUSH R0 Push register on stack
+0000F86B: 2411 CLR R1 Clear Register
+0000F86C: 938F PUSH R24 Push register on stack
+0000F86D: E081 LDI R24,0x01 Load immediate
+0000F86E: 93800100 STS 0x0100,R24 Store direct to data space
+0000F870: 918F POP R24 Pop register from stack
+0000F871: 900F POP R0 Pop register from stack
+0000F872: BE0F OUT 0x3F,R0 Out to I/O location
+0000F873: 900F POP R0 Pop register from stack
+0000F874: 901F POP R1 Pop register from stack
+0000F875: 9518 RETI Interrupt return
+0000F876: 921F PUSH R1 Push register on stack
+0000F877: 920F PUSH R0 Push register on stack
+0000F878: B60F IN R0,0x3F In from I/O location
+0000F879: 920F PUSH R0 Push register on stack
+0000F87A: 2411 CLR R1 Clear Register
+0000F87B: 938F PUSH R24 Push register on stack
+0000F87C: E081 LDI R24,0x01 Load immediate
+0000F87D: 93800100 STS 0x0100,R24 Store direct to data space
+0000F87F: 918F POP R24 Pop register from stack
+0000F880: 900F POP R0 Pop register from stack
+0000F881: BE0F OUT 0x3F,R0 Out to I/O location
+0000F882: 900F POP R0 Pop register from stack
+0000F883: 901F POP R1 Pop register from stack
+0000F884: 9518 RETI Interrupt return
+0000F885: E085 LDI R24,0x05 Load immediate
+0000F886: BF83 OUT 0x33,R24 Out to I/O location
+0000F887: E684 LDI R24,0x64 Load immediate
+0000F888: BF81 OUT 0x31,R24 Out to I/O location
+0000F889: B787 IN R24,0x37 In from I/O location
+0000F88A: 6083 ORI R24,0x03 Logical OR with immediate
+0000F88B: BF87 OUT 0x37,R24 Out to I/O location
+0000F88C: E081 LDI R24,0x01 Load immediate
+0000F88D: BF85 OUT 0x35,R24 Out to I/O location
+0000F88E: B785 IN R24,0x35 In from I/O location
+0000F88F: 6082 ORI R24,0x02 Logical OR with immediate
+0000F890: BF85 OUT 0x35,R24 Out to I/O location
+0000F891: 9A17 SBI 0x02,7 Set bit in I/O register
+0000F892: 9478 SEI Global Interrupt Enable
+0000F893: 91800100 LDS R24,0x0100 Load direct from data space
+0000F895: 2388 TST R24 Test for Zero or Minus
+0000F896: F429 BRNE PC+0x06 Branch if not equal
+0000F897: E080 LDI R24,0x00 Load immediate
+0000F898: E090 LDI R25,0x00 Load immediate
+0000F899: E0A4 LDI R26,0x04 Load immediate
+0000F89A: E0B0 LDI R27,0x00 Load immediate
+0000F89B: C006 RJMP PC+0x0007 Relative jump
+0000F89C: E080 LDI R24,0x00 Load immediate
+0000F89D: E890 LDI R25,0x80 Load immediate
+0000F89E: E0A0 LDI R26,0x00 Load immediate
+0000F89F: E0B0 LDI R27,0x00 Load immediate
+0000F8A0: C001 RJMP PC+0x0002 Relative jump
+0000F8A1: 0000 NOP No operation
+0000F8A2: 9701 SBIW R24,0x01 Subtract immediate from word
+0000F8A3: 09A1 SBC R26,R1 Subtract with carry
+0000F8A4: 09B1 SBC R27,R1 Subtract with carry
+0000F8A5: F7D9 BRNE PC-0x04 Branch if not equal
+0000F8A6: B183 IN R24,0x03 In from I/O location
+0000F8A7: 5880 SUBI R24,0x80 Subtract immediate
+0000F8A8: B983 OUT 0x03,R24 Out to I/O location
+0000F8A9: CFE9 RJMP PC-0x0016 Relative jump
+0000F8AA: 94F8 CLI Global Interrupt Disable
+0000F8AB: CFFF RJMP PC-0x0000 Relative jump

+0000F86C: FFFF ??? Data or unknown opcode
+0000F86D: FFFF ??? Data or unknown opcode
+0000F86E: FFFF ??? Data or unknown opcode


Кстати, обратил внимание на HEX
:020000021000EC
:10F000000C9446F80C9465F80C9465F80C9465F82B
:10F010000C9465F80C9465F80C9465F80C9465F8FC
:10F020000C9465F80C9465F80C9465F80C9465F8EC
:10F030000C9465F80C9465F80C9465F80C9467F8DA
:10F040000C9476F80C9465F80C9465F80C9465F8BB
:10F050000C9465F80C9465F80C9465F80C9465F8BC
:10F060000C9465F80C9465F80C9465F80C9465F8AC
:10F070000C9465F80C9465F80C9465F80C9465F89C
:10F080000C9465F80C9465F80C9465F811241FBE77
:10F09000CFEFD0E1DEBFCDBF11E0A0E0B1E0E8E509
:10F0A000F1EF01E00BBF02C007900D92A030B10755
:10F0B000D9F711E0A0E0B1E001C01D92A130B10785
:10F0C000E1F70E9485F80C94AAF80C9400F81F92BE
:10F0D0000F920FB60F9211248F9381E0809300015D
:10F0E0008F910F900FBE0F901F9018951F920F9247
:10F0F0000FB60F9211248F9381E0809300018F91BE
:10F100000F900FBE0F901F90189585E083BF84E687
:10F1100081BF87B7836087BF81E085BF85B7826085
:10F1200085BF179A789480910001882329F480E0A4
:10F1300090E0A4E0B0E006C080E090E8A0E0B0E09D
:10F1400001C000000197A109B109D9F783B1805826
:08F1500083B9E9CFF894FFCF69
:040000031000F000F9
:00000001FF

Если я правильно понял, то здесь явно указано: стартовать с 0x1F000 т.е. 0xF800 слов. Значит глюк курсора это глюк отладчика.
SysRq
Цитата
1. Write the Interrupt Vector Change Enable (IVCE) bit to one.
2. Within four cycles, write the desired value to IVSEL while writing a zero to IVCE.


PS: симулятор AVRStudio настройте, в опции его наведайтесь, - он умеет стартовать с секции загрузчика.
Sirko
Цитата
1. Write the Interrupt Vector Change Enable (IVCE) bit to one.
2. Within four cycles, write the desired value to IVSEL while writing a zero to IVCE.


Огромнейшее спасибо, вроде как ОНО. 08.gif

По поводу
Цитата
если это не опечатка, то alag57 пусть...
простите, беру свои слова обратно.



alag57
Цитата
простите, беру свои слова обратно.

Да все нормально.
Код
+0000F88C:   E081        LDI       R24,0x01       Load immediate
+0000F88D:   BF85        OUT       0x35,R24       Out to I/O location
+0000F88E:   B785        IN        R24,0x35       In from I/O location
+0000F88F:   6082        ORI       R24,0x02       Logical OR with immediate
+0000F890:   BF85        OUT       0x35,R24       Out to I/O location

Вот как это происходит. Я специально привел инициализацию на ассемблере.
BOOTINTVEC=no в майкфайле я конечно же исправил, забыл напомнить.
Цитата
он умеет стартовать с секции загрузчика

Не получилось у меня, стартует с адреса 0х00007800. Ну да не помешало sm.gif
Sirko
Добрался - таки я до загрузчика и, пользуясь случаем, решил немного расписать последовательность.
Думаю кому-нибудь вроде меня пригодится для пинка.

Значит так, лезем сюда, забираем вот это.
Кстати, спасибо 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;
}


Нажмите для просмотра прикрепленного файла

Спасибо всем тем, кто пнул меня в правильном направлении. cheers.gif

з.ы. будут сложности, буду ныть дальше.
SysRq
Цитата(Sirko @ Apr 15 2011, 02:20) *
буду ныть дальше
Раньше вас ныть начнёт МК, у которого станет дохнуть flash: перепрошивка при каждом старте убьёт его очень быстро.
Sirko
Цитата
Раньше вас ныть начнёт МК

Безусловно, но этот исходник для понимания сути, а не для CopyPaste

p.s. Прошивка основной программы в бутлоадер не влезет biggrin.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.