Radi0 0 24 июня, 2015 Опубликовано 24 июня, 2015 (изменено) · Жалоба Добрый день уважаемые пользователи. Помогите разобраться с прерываниями в Bootloader-е. Я набросал скелет загрузочника, но во время симуляции(когда должно возникать прерывание), они не срабатывают. Я не совсем понимаю где должен располагаться обработчик прерывания и где он находится у меня. Что происходит с вектором прерывания при выставлении бита MCUCR= (1<<IVCE); MCUCR= (1<<IVSEL); Исходные данные такие: Контроллер Atmega 128, компилятор MicroC Pro версия 6, Proteus версия 8.1. Фьюзы везде выставлены одинаково bootrst 1, boot loader Size 0xf800. Исходник и полученный hex прилагаю. #pragma orgall 0xF800 // Place all above specified address #define PLATA_NUMBERS 0x31 // Индивидуальный номер платы у каждой свой #define RXB8 1 #define TXB8 0 #define UPE 2 #define OVR 3 #define FE 4 #define UDRE 5 #define RXC 7 #define FRAMING_ERROR (1<<FE) #define PARITY_ERROR (1<<UPE) #define DATA_OVERRUN (1<<OVR) #define DATA_REGISTER_EMPTY (1<<UDRE) #define RX_COMPLETE (1<<RXC) const unsigned int BOOTLOADER_START_ADDRESS = 0xF800; // Адрес расположения бутлоадера const unsigned int VECT_TEST= BOOTLOADER_START_ADDRESS + IVT_ADDR_TIMER1_COMPA; const unsigned int FLASH_PAGE_SIZE_BYTES = __FLASH_PAGE_SIZE*2; // Размер в байтах //static unsigned int block[__FLASH_PAGE_SIZE]; // #define PROTOCOL_COM_SIZE 12 static unsigned short buff[PROTOCOL_COM_SIZE]; // Входной буфер для комманд. sbit TEST_LINE2 at PORTG0_bit; //#include "built_in.h" void USART0_INIT_9600(void); // Инициализация USART 0 на скорости 9600 void __BootDelay(void); // Задержка void Write_UART0(char text); // Отправка байта в УАРТ 0 void WDT_init(void); //Инициализация сторожевого таймера void Start_Program(void); // Функция для старта основной программы void Move_interrupts(void); // Перенос прерываний в загрузчик void Move_interrupts_back(void); //Функция возврата прерываний в область программ void init_io_ports(void); //Инициализация портов unsigned short UART_Write_Loop(char send, char receive); // Эта фугкция ждет команды void Start_Bootload(void); // Старт бутлоадера void TIMER_init(void); //Инициализация таймера void RX0_interrupt() iv IVT_ADDR_USART0__RX // Прерывание при поступлении сигнала на УСАРТ 0 { unsigned char rx_status=0; asm{wdr} // Write_UART0(0x31); PORTB=(++DDRB); asm{cli} rx_status=UCSR0A; if (((rx_status)&(DATA_OVERRUN))==0) { buff[++buff[0]]=UDR0; if ( buff[0]==PROTOCOL_COM_SIZE) { buff[0]=0; } PORTB=(++DDRB); } asm{sei} } void void INT_Interrupt() iv IVT_ADDR_TIMER1_COMPA //Все время работающий счетчик времени с частотой 10000 Гц { if (TEST_LINE2==1) TEST_LINE2=0; else TEST_LINE2=1; // Тестовая нога TCNT1L=0x00; //Cброс таймера TIMSK|=(1<<OCIE1A); //Запуск таймера снова } void TIMER_init(void) //Инициализация таймера { // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 1382,400 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // OC1C output: Discon. // Noise Canceler: On // Input Capture on Rising Edge // Timer1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: On // Compare B Match Interrupt: Off // Compare C Match Interrupt: Off TCCR1A=0x00; TCCR1B=0xC2; TCNT1H=0x00; TCNT1L=0x00; // НАЧАЛЬНОЕ ЗНАЧЕНИЕ ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x8A; //СОВПАДЕНИЕ OCR1BH=0x00; OCR1BL=0x00; OCR1CH=0x00; OCR1CL=0x00; //TIMSK&=~(1<<OCIE1A); //Запрет прерыыаний TIMSK|=(1<<OCIE1A); //Разрешение прерывания ETIMSK=0x00; } void __BootDelay(void) // Задержка { asm{wdr} DDRA++; PORTA++; delay_ms(100); } void USART0_INIT_9600(void) { asm{wdr} // asm{cli} // USART1 initialization // Communication Parameters: 8 Data, 1 Stop, No Parity // USART0 Receiver: On // USART0 Transmitter: On // USART0 Mode: Asynchronous // USART0 Baud Rate: 9600 UCSR0A=0x00; UCSR0B=0x18; UCSR0C=0x06; UBRR0H=0x00; UBRR0L=0x47; // UCSR0B&=~(1<<RXCIE0); //Запрет прерывания UCSR0B|=(1<<RXEN0); // Включаем вход УАРТ 0 UCSR0B|=(1<<RXCIE0); // Разрешение прерывания Delay_ms(50); } void Write_UART0(char text) // запись в порт усарт 0 { //asm{cli} while ((UCSR0A & DATA_REGISTER_EMPTY)==0); UDR0=text; //asm{sei} asm{wdr} } void WDT_init(void) { asm{wdr} // asm{cli} // Watchdog Timer initialization // Watchdog Timer Prescaler: OSC/2048k WDTCR=0x1F; WDTCR=0x0F; // asm{sei} } void Start_Program(void) // Функция для старта основной программы { // asm JMP 0; asm JMP 0xF800; //BOOTLOADER_START_ADDRESS } void Move_interrupts(void) // Перенос прерываний в загрузчик { asm{cli} // Запрет прерываний MCUCR= (1<<IVCE); // Разрешение изменения вектора прерываний MCUCR= (1<<IVSEL); // Перемещение вектора в загрузочную область флеш // asm{sei} // Разрешение прерываний } void Move_interrupts_back(void) //Функция возврата прерываний в область программ { // asm{cli} // Запрет прерываний MCUCR=(1<<IVCE); // Разрешение изменения вектора прерываний MCUCR = 0; // Перемещение вектора в область программы // asm{sei} // Разрешение прерываний } void init_io_ports(void) //Инициализация портов { DDRA =(0<< DDA0)|(0<< DDA1)|(0<< DDA2)|(0<< DDA3)|(0<< DDA4)|(0<< DDA5)|(0<< DDA6)|(0<< DDA7); DDRB =(0<< DDB0)|(0<< DDB1)|(0<< DDB2)|(0<< DDB3)|(0<< DDB4)|(0<< DDB5)|(0<< DDB6)|(0<< DDB7); DDRC =(1<< DDC0)|(0<< DDC1)|(0<< DDC2)|(0<< DDC3)|(0<< DDC4)|(0<< DDC5)|(0<< DDC6)|(0<< DDC7); DDRD =(0<< DDD0)|(0<< DDD1)|(0<< DDD2)|(0<< DDD3)|(0<< DDD4)|(0<< DDD5)|(0<< DDD6)|(0<< DDD7); DDRE =(0<< DDE0)|(1<< DDE1)|(0<< DDE2)|(0<< DDE3)|(0<< DDE4)|(0<< DDE5)|(0<< DDE6)|(0<< DDE7); DDRF =(0<< DDF0)|(0<< DDF1)|(0<< DDF2)|(0<< DDF3)|(0<< DDF4)|(0<< DDF5)|(0<< DDF6)|(0<< DDF7); DDRG =(1<< DDG0)|(0<< DDG1)|(0<< DDG2)|(0<< DDG3)|(0<< DDG4); PORTA =(0<< PORTA0)|(0<< PORTA1)|(0<< PORTA2)|(0<< PORTA3)|(0<< PORTA4)|(0<< PORTA5)|(0<< PORTA6)|(0<< PORTA7); PORTB =(0<< PORTB0)|(0<< PORTB1)|(0<< PORTB2)|(0<< PORTB3)|(0<< PORTB4)|(0<< PORTB5)|(0<< PORTB6)|(0<< PORTB7); PORTC =(1<< PORTC0)|(0<< PORTC1)|(0<< PORTC2)|(0<< PORTC3)|(0<< PORTC4)|(0<< PORTC5)|(0<< PORTC6)|(0<< PORTC7); PORTD =(0<< PORTD0)|(0<< PORTD1)|(0<< PORTD2)|(0<< PORTD3)|(0<< PORTD4)|(0<< PORTD5)|(0<< PORTD6)|(0<< PORTD7); PORTE =(1<< PORTE0)|(1<< PORTE1)|(0<< PORTE2)|(0<< PORTE3)|(0<< PORTE4)|(0<< PORTD5)|(0<< PORTE6)|(0<< PORTE7); PORTF =(0<< PORTF0)|(0<< PORTF1)|(0<< PORTF2)|(0<< PORTF3)|(0<< PORTF4)|(0<< PORTF5)|(0<< PORTF6)|(0<< PORTF7); PORTG =(0<< PORTG0)|(0<< PORTG1)|(0<< PORTG2)|(0<< PORTG3)|(0<< PORTG4); } unsigned short UART_Write_Loop(char send, char receive) // Эта функция ждет команды { unsigned short rslt = 0; while(1) { asm{wdr} __BootDelay(); Write_UART0(SEND); __BootDelay(); rslt++; if (rslt == 10) { return 0; } if (buff[1]==receive) { return 1; } } } void Start_Bootload(void) // Старт бутлоадера { while(1) { asm{wdr} DDRC=PORTC=0b11111111; } } void main() org BOOTLOADER_START_ADDRESS { asm{cli} Move_interrupts(); // Перенос прерываний в область памяти бутлоадера init_io_ports(); WDT_init(); USART0_INIT_9600(); // Инициализация УАРТ 0 на 9600 memset(&buff[0], 0, sizeof(buff)); // Очистка входного буфера УАРТ 0 TIMER_init(); asm{wdr} SREG|=(1<<7); // Глобальное разрешение прерываний DDRA=PORTA=0x1; if (UART_Write_Loop('0','r')) // Шлём '0' и ждем 'r' { Start_Bootload(); // Получили r и стартуем бутлоадер } else { // Move_interrupts_back(); Start_Program(); // Запуск основной программы } } HEX :100000000C9400F80C9400000C9400000C94000078 :100010000C9400000C9400000C9400000C94000060 :100020000C9400000C9400000C9400000C94000050 :100030000C94F6F80C9400000C9400000C94000052 :100040000C9400000C9400000C9415F90C94000022 :100050000C9400000C9400000C9400000C94000020 :100060000C9400000C9400000C9400000C94000010 :100070000C9400000C9400000C9400000C94000000 :0C0080000C9400000C9400000C94000094 :020000040001F9 :10F00000BFEFBDBFB0E1BEBF2F923F924F925F9264 :10F010006F92F894ADD08BD0B1D0CBD0BCE05B2E4A :10F02000B0E06B2E4424B0E02B2EB1E03B2EACD0F0 :10F030005DD0A895BFB7B068BFBFB1E0BBBBB1E0C2 :10F04000BABBB2E73B2EB0E32B2E25D0002311F044 :10F0500046D001C041D06F905F904F903F902F906D :02F06000FFCFE0 :0CF17000F894B1E0B5BFB2E0B5BF08955F :10F12E00B0E0BABBB0E0B7BBB1E0B4BBB0E0B1BBCE :10F13E00B2E0B2B9B0E0B0936100B1E0B093640058 :10F14E00B0E0BBBBB0E0B8BBB1E0B5BBB0E0B2BBAA :10F15E00B3E0B3B9B0E0B0936200B0E0B093650035 :02F16E00089502 :0CF17C00A895BFE1B1BDBFE0B1BD089592 :10F1B200A895B0E0BBB9B8E1BAB9B6E0B093950092 :10F1C200B0E0B0939000B7E4B9B9BAB1B061BAB9DE :10F1D2000AB100680AB923E01FEC0EE10A95F1F7C3 :0AF1E2001A95E1F72A95D1F7089578 :10F18800A101252D362D052D162D01501040502E8C :10F19800612EB22FB32B39F0FA0140828A010F5F3A :0AF1A8001F4FA801EECF810108956A :10F0EC00B0E0BFBDB2ECBEBDB0E0BDBDB0E0BCBDDC :10F0FC00B0E0B7BDB0E0B6BDB0E0BBBDBAE8BABDDC :10F10C00B0E0B9BDB0E0B8BDB0E0B0937900B0E00C :10F11C00B0937800B7B7B061B7BFB0E0B0937D00E3 :02F12C00089544 :10F09600CF93DF93CDB7DEB72197CDBFDEBF2196E5 :10F0A600B0E0B883A895E2DFD9DFE0DF08810F5F23 :10F0B60008830A3011F400E007C00091010103152E :10F0C60011F401E001C0EECFCDBFDEBFDF91CF91DD :02F0D60008959B :10F07200A8950AB30F5F0ABB0BB30F5F0BBB26E069 :10F082001DE90DE30A95F1F71A95E1F72A95D1F7F3 :04F0920000000895DD :10F062000BB10072003009F4FBCF2CB8A8950895BB :00F072009E :0EF0DE00A895BFEFB5BBBFEFB4BBFACF089546 :06F0D8000C9400F80895FD :10F22A000F931F932F93EF93FF93BF93BFB7BF9390 :10F23A00A89507B30F5F07BB08BBF8941BB1012F52 :10F24A0008700030C9F400910001202F2F5F20932D :10F25A00000100E011E0E22FF0E0E00FF11F0CB135 :10F26A000083009100010C3019F4B0E0B093000162 :10F27A0007B30F5F07BB08BB7894BF91BFBFBF91AD :0CF28A00FF91EF912F911F910F911895AB :10F1EC00EF93FF93BF93BFB7BF93B0916500B0FF90 :10F1FC0006C0B0916500BE7FB093650005C0B091AC :10F20C006500B160B0936500B0E0BCBDB7B7B0614C :0EF21C00B7BFBF91BFBFBF91FF91EF91189593 :00000001FF Изменено 24 июня, 2015 пользователем Radi0 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Radi0 0 24 июня, 2015 Опубликовано 24 июня, 2015 · Жалоба Смотрю я на HEX фаил и никак не могу понять, разве я не должен там видеть диапазон памяти от 0xF800? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlanDrakes 1 25 июня, 2015 Опубликовано 25 июня, 2015 (изменено) · Жалоба Компилятор (или линкер) решил, что таблица векторов по умолчанию у Вас будет находиться в нулевых адресах, и разместил её там (о чём говорят первые строки с адресами xx0000xx... и дальше), затем идёт разрыв и продолжается уже с 0xF000 адреса. Так что, у Вас явно нелады с параметрами сборки. Посмотрите настройки проекта. Возомжно, нужно явно указать положение секции .text для сборки загрузчика (например, так: --section-start=.text=0x1F000 для Вашего случая). Адрес фактически сдвинут на 1 бит ВЛЕВО. То есть, 0xF800 -> 0x1F000 При этом, уже не будет необходимости указывать начало секции где-то в коде. > #pragma orgall 0xF800 Вот эту строку нужно желательно будет убрать. Если используете AVRStudio - ключ начала секции указывать в параметрах сборки проекта. Точнее не подскажу. Изменено 25 июня, 2015 пользователем AlanDrakes Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pavel-pervomaysk 0 27 июня, 2015 Опубликовано 27 июня, 2015 · Жалоба Возможно здесь есть ответы на некоторые вопросы. CRC-16 и AES128 не вложены. Сначала нужно добиться устойчивой работы в открытом виде, затем применить шифрование (если оно необходимо) на свой вкус. В 4КБ многое влезет... ЕЕпром не делал, ибо у меня он не использовался. Кстати, рекомендую скорость выбрать хотя бы 57600, на 9600 уснуть можно, читая - записывая 120кБ... В моем варианте (500k) чтение занимает 7 секунд, запись 33 сенкунды. ; AT90CAN bootloader ; Boot exchange via USART1 ; main osc 16MHz. speed - 500k ; each message format - (command byte)(page address H M L)(data 256 bytes)(crc16) ; total 262 bytes ; Possible programming space 124 kBytes for AT90CAN128 ; Using AES-128 CBC Encryption/Decryprion for Read/Write Flash memory ; pavel-pervomaysk ; date 10 FEB 2015 .equ L_addr = (((FLASHEND+1)*2)-4096) ; Last programmed Block address ; Констатны для работы с бутом, на ваш вкус могут быть любыми ; Constants for managing Bootloader .equ p_size = PAGESIZE*2 ; amount bytes in page .equ boot_en = 0xA5 ; Enable boot command Bootin <- .equ restart = 0xAF ; Restart bootloader Bootin <- .equ rd_page = 0x3C ; read page command Bootin <- .equ wr_page = 0x59 ; write page command Bootin <- .equ st_ok = 0x85 ; Command status ok! Bootout -> .equ st_err = 0x8A ; Command status ERROR Bootout -> .dseg ; Boot Data RAM sedment .dseg ; .org 0x200 ; ;------------------------; b_com: .byte 1 ; Bootloader command p_ah: .byte 1 ; Page address H &1 p_am: .byte 1 ; Page address M p_al: .byte 1 ; Page address L bc_data: .byte 256 ; Block crypted received data p_crch: .byte 1 ; Page CRC H-byte p_crcl: .byte 1 ; Page CRC L-byte ;------------------------; ack: .byte 1 ; ACK status bmode: .byte 1 ; Bootloader mode 0 - off, 1 - on rxch: .byte 1 ; Received bytes counteh H rxcl: .byte 1 ; Received bytes counteh L dummy: .byte 4 ; aesm: .byte 1 ; AES mode 0 - decrypt 1 - encrypt aesbc: .byte 1 ; AES128 - blocks counter! aeskey: .byte 16 ; AES128 - key aesdata: .byte 16 ; AES128 - data OUT aesiv: .byte 16 ; AES128 - init vector aesdin: .byte 16 ; AES128 - data IN bdc_data: .byte 256 ; Block Decrypted data for writing! .cseg ; здесь внимательно смотрим! .org THIRDBOOTSTART ; boot size 2048words 4096 bytes 0xF800 (Dump 0x1F000) jmp BOOTRESET ; Reset Handler .org 0xF802 ; External Interrupt Request 0 reti .org 0xF804 ; External Interrupt Request 1 reti .org 0xF806 ; External Interrupt Request 2 reti .org 0xF808 ; External Interrupt Request 3 reti .org 0xF80A ; External Interrupt Request 4 reti .org 0xF80C ; External Interrupt Request 5 reti .org 0xF80E ; External Interrupt Request 6 reti .org 0xF810 ; External Interrupt Request 7 reti .org 0xF812 ; Timer/Counter2 Compare Match reti .org 0xF814 ; Timer/Counter2 Overflow reti .org 0xF816 ; Timer/Counter1 Capture Event reti .org 0xF818 ; Timer/Counter1 Compare Match A reti .org 0xF81A ; Timer/Counter Compare Match B reti .org 0xF81C ; Timer/Counter1 Compare Match C reti .org 0xF81E ; Timer/Counter1 Overflow reti .org 0xF820 ; Timer/Counter0 Compare Match reti .org 0xF822 ; Timer/Counter0 Overflow jmp boot_T0_ovf ; .org 0xF824 ; CAN Transfer Complete or Error reti .org 0xF826 ; CAN Timer Overrun reti .org 0xF828 ; SPI Serial Transfer Complete reti .org 0xF82A ; USART0, Rx Complete reti .org 0xF82C ; USART0 Data Register Empty reti .org 0xF82E ; USART0, Tx Complete reti .org 0xF830 ; Analog Comparator reti .org 0xF832 ; ADC Conversion Complete reti .org 0xF834 ; EEPROM Ready reti .org 0xF836 ; Timer/Counter3 Capture Event reti .org 0xF838 ; Timer/Counter3 Compare Match A reti .org 0xF83A ; Timer/Counter3 Compare Match B reti .org 0xF83C ; Timer/Counter3 Compare Match C reti .org 0xF83E ; Timer/Counter3 Overflow jmp boot_T3_ovf ; .org 0xF840 ; USART1, Rx Complete jmp _b_rxd1 ; Get byte via USART1! .org 0xF842 ; USART1, Data Register Empty reti .org 0xF844 ; USART1, Tx Complete reti .org 0xF846 ; 2-wire Serial Interface reti .org 0xF848 ; Store Program Memory Read reti BOOTRESET: ; Bootloader reset point! ;---- STACK INIT --------; ldi tmp, low(ramend) ; out SPL,tmp ; ldi tmp,high(ramend) ; out SPH,tmp ; cli ;---- Move_interrupts ---; in tmp,MCUCR ; Get MCUCR mov tmp1,tmp ; ori tmp,(1<<IVCE) ; Enable change of Interrupt Vectors out MCUCR,tmp ; ori tmp1,(1<<IVSEL) ; Move interrupts to Boot Flash section out MCUCR,tmp1 ; ;------------------------; clr zero ; ZERO - Always =0! ;---- USART1 ------------; Warning ! U2X1 = 1 Right values! ;---- 500k --------------; RXD interrupt mode! sts UBRR1H,zero ; USART1 speed select for 16MHz! ldi tmp,3 ; (207)-9600;(51)-38400;(16)-115200;(7)-250k;(3)-500k;(1)-1m sts UBRR1L,tmp ; ; RXC1 TXC1 UDRE1 FE1 DOR1 UPE1 U2X1 MPCM1 ldi tmp,0b00000010 ; sts UCSR1A,tmp ; ; RXCIE1 TXCIE1 UDRIE1 RXEN1 TXEN1 UCSZ12 RXB81 TXB81 ldi tmp,0b10011000 ; Receive bytes interrupt mode! sts UCSR1B,tmp ; ; low 7 bits ; – UMSEL1 UPM11 UPM10 USBS1 UCSZ11 UCSZ10 UCPO1L ldi tmp,0b00000110 ; andi tmp,0x7f ; sts UCSR1C,tmp ; ;---- TIMER0 ------------; ; FOC0A WGM00 COM0A1 COM0A0 WGM01 CS02 CS01 CS00 ldi tmp,0b00000001 ; (0-off),(1-F/1),(2-F/8),(3-F/64),(4-F/256),(5-F/1024),(6,7-External,f,r) out TCCR0A,tmp ; out TCNT0,zero ; out OCR0A,zero ; out TIFR0,zero ; ; – – – – – – OCIE0A TOIE0 ldi tmp,(1<<TOIE0) ; sts TIMSK0,tmp ; Timer/Counter0 Overflow Interrupt Enable 0x01 ;---- TIMER3 ------------; ; COM3A1 COM3A0 COM3B1 COM3B0 COM3C1 COM3C0 WGM31 WGM30 ldi tmp,0b00000000 ; sts TCCR3A,tmp ; ; ICNC3 ICES3 – WGM33 WGM32 CS32 CS31 CS30 ; Fclk 16MHz OVF time ldi tmp,2 ; (1-t ~4ms);(2-t ~33ms);(3-t ~260ms);(4-t ~1s);(5-t !4.19s); sts TCCR3B,tmp ; ; FOC3A FOC3B FOC3C – – – – – sts TCCR3C,zero ; sts TCNT3H,zero ; счетчик таймера_1 H sts TCNT3L,zero ; счетчик таймера_1 L sts ICR3H,zero ; sts ICR3L,zero ; sts OCR3AH,zero ; sts OCR3AL,zero ; sts OCR3BH,zero ; sts OCR3BL,zero ; ; – – ICF3 – OCF3C OCF3B OCF3A TOV3 sts TIFR3,zero ; ; – – ICIE3 – OCIE3C OCIE3B OCIE3A TOIE3 ldi tmp,(1<<TOIE3) ; sts TIMSK3,tmp ; Timer/Counter3 Overflow Interrupt Enable ;---- PORTA -------------; ldi tmp,0x00 ; PA3 - debug led out PORTA,tmp ; When boot started - status LED turn off! ldi tmp,0x08 ; out DDRA,tmp ; ;------------------------; ;---- BOOT RAM CLEAR ----; Очистка оперативной памяти от случайного мусора ldi yl,low (SRAM_START); RAM start address ldi yh,high(SRAM_START); ldi xl,low (SRAM_SIZE) ; amount bytes ldi xh,high(SRAM_SIZE) ; ldi tmp,0xFF ; Fill RAM 0xFF b_ram_clear: ; st Y+,tmp ; sbiw xl,1 ; brne b_ram_clear ; ;------------------------; ;------------------------; sts aesm,zero ; aesmode! sts aesbc,zero ; Clear aes block counter clr xh ; clr xl ; sts rcnt1,zero ; Ramcounter1 =0! sts rcnt3,zero ; Ramcounter3 =0! sts bmode,zero ; Turn ON ckecking bootloader timeout counter sts rxch,zero ; sts rxcl,zero ; clear RX bytes counter! ;------------------------; ; load AES128 key ; ldi ZL, byte3(key<<1) ; Initialize Z pointer out RAMPZ,ZL ; ldi ZH, byte2(key<<1) ; ldi ZL, byte1(key<<1) ; ldi YH,high(aeskey) ; ldi YL,low (aeskey) ; loadaeskey: ; elpm tmp,Z+ ; st Y+,tmp ; cpi YL,low(aeskey+16) ; brne loadaeskey ; ;------------------------; ; load AES128 Init Vector from flash! ldi ZL, byte3(Bl_ver<<1); Initialize Z pointer out RAMPZ,ZL ; ldi ZH, byte2(Bl_ver<<1); ldi ZL, byte1(Bl_ver<<1); ldi YH,high(aesiv) ; ldi YL,low (aesiv) ; ld_aesiv: ; cycle 16 elpm tmp,z+ ; st y+,tmp ; store AES init vector! cpi yl,low(aesiv+16) ; brne ld_aesiv ; ;------------------------; sei ; Enable interrupts! ;----------------------; ; while(tmp=!0xA5){ ; ; tmp=b_com ; ; } ; ;----------------------; waiting_boot: ; Waiting & checking boot command 0xA5! ldi yl,low (b_com) ; ldi yh,high(b_com) ; RAM pointer ld tmp,y ; load command from RAM cpi tmp,boot_en ; compare with (0xA5) breq run_loader ; rjmp waiting_boot ; ;----------------------; run_loader: ; Start bootloader main loop ldi tmp2,st_ok ; load constanr rcall us_tx ; Send Status_OK! ;----------------------; ldi tmp,1 ; sts bmode,tmp ; Turn OFF ckecking bootloader timeout counter sts rcnt3,zero ; clear timeout counter ;************************************************************************ init_flags: ; clr flags ; Clear flags ;----------------------; boot_main: ; ;----------------------; sbrc flags,0 ; Check 0-th bit rjmp read_blockx ; Read blockX ;----------------------; sbrc flags,1 ; Check 1-th bit rjmp write_blockx ; write blockX ;----------------------; sbrc flags,7 ; Check 7-th bit rjmp check_b_com ; ;----------------------; end of boot main handler loop rjmp boot_main ; jump to boot clear flags ;************************************************************************* ;boot_en = 0xA5 ; Enable boot command Bootin <- ;restart = 0xAF ; Restart bootloader Bootin <- ;rd_page = 0x3C ; read page command Bootin <- ;wr_page = 0x59 ; write page command Bootin <- ;st_ok = 0x80 ; Command status ok! Bootout -> ;st_err = 0x81 ; Command status ERROR Bootout -> check_b_com: ; Checking BOOT commands! lds tmp,b_com ; Load command ;----------------------; Check command 1 ch_n1: ; label1 cpi tmp,restart ; compare received command with (0xAF) breq reset_boot ; rjmp ch_n2 ; check next constant -> reset_boot: ; cli ; sts bmode,zero ; rjmp BOOTRESET ; jump to BOOTRESET ;----------------------; Check command 2 ch_n2: ; label 2 cpi tmp,rd_page ; compare received command with (0x3C) breq set_rd_fl ; rjmp ch_n3 ; check next constant -> set_rd_fl: ; ldi flags,0x01 ; set bin no.0 rjmp boot_main ; ;----------------------; Check command 3 ch_n3: ; label 3 cpi tmp,wr_page ; compare received command with (0x59) breq set_wr_fl ; rjmp ch_b_ok ; leave checking commands set_wr_fl: ; ldi flags,0x02 ; set bin no.1 rjmp ch_wr_d ; check write data ch_b_ok: ; rjmp init_flags ; clear flags jump to boot_main ;----------------------; ;----------------------; Load address, encrypt block, send to usart read_blockx: ; ldi tmp2,st_ok ; rcall us_tx ; Send command to the USART1 ;----------------------; lds zl,p_ah ; Init RAMPZ:Z pointer out RAMPZ,zl ; Flash address RAMPZ0 lds zh,p_am ; Flash address M lds zl,p_al ; Flash address L ldi yl,low (bc_data) ; Encrypted AES data ldi yh,high(bc_data) ; RAM pointer ;----------------------; Read 256 bytes from Flash ldi loop3,0 ; amount read_b_c: ; elpm tmp2,z+ ; load byte, address=+1 st y+,tmp2 ; store byte in ram dec loop3 ; brne read_b_c ; ;----------------------; Encrypt block ldi tmp,1 ; load aes ecncrypt mode sts aesm,tmp ; AES Encryption rcall _aesB ; Encrypt stored Block ;----------------------; Send block to USART1 ldi yl,low (bdc_data) ; Encrypted AES data ldi yh,high(bdc_data) ; RAM pointer ldi loop3,0 ; 256 bytes! read_b_ce: ; ld tmp2,y+ ; rcall us_tx ; Send data to the USART1 dec loop3 ; brne read_b_ce ; ;----------------------; rjmp init_flags ; clear flags jump to boot_main ;----------------------; write_blockx: ; clr tmp ; selecl mode Decrypt sts aesm,tmp ; save mode rcall _aesB ; decrypr received block 256bytes ; save result block 256 bytes in (bdc_data) lds zl,p_ah ; Init RAMPZ:Z pointer out RAMPZ,zl ; Flash address RAMPZ0 lds zh,p_am ; Flash address M lds zl,p_al ; Flash address L ;----------------------; ;ldi yl,low (bc_data) ; pure received data without decrypting ;ldi yh,high(bc_data) ; RAM pointer ldi yl,low (bdc_data) ; Decrypted AES data ldi yh,high(bdc_data) ; RAM pointer rcall write_page ; Write page to flash! wr_b_end: ; rcall us_tx ; Send command to the USART1 rjmp init_flags ; clear flags jump to boot_main ;----------------------; ch_wr_d: ; check write data block! ; 262 bytes = 0x0106 ldi tmp,6 ; amount bytes! mov r0,tmp ; ldi tmp,1 ; mov r1,tmp ; r1:r0 = 0x0106 (same 262) ;---- comparing -------; lds xl,rxcl ; lds xh,rxch ; Load amount received bytes! cp xl,r0 ; cpc xh,r1 ; breq check_b262 ; rjmp init_flags ; clear flags jump to boot_main ;----------------------; check_b262: ; check crc in received ram block rcall crc16 ; check received data block CRC rjmp boot_main ; crc16: ; CRC-16 POLY 0xA001 ; your CRC16 code :) ret ; return ;----------------------; us_tx: ; lds tmp,UCSR1A ; sbrs tmp,UDRE1 ; rjmp us_tx ; ; Put data (data) into buffer, sends the data sts UDR1,tmp2 ; ret ; return ;----------------------; ;----------------------; _b_rxd1: ; USART1 receive interrupt ; we've got (n) bytes from USART1 ; (n) = X push tmp ; store register in stack in tmp,SREG ; store SREG push tmp ; store register in stack push yl ; store register in stack push yh ; store register in stack ;----------------------; ; received bytes max length - lds tmp,UDR1 ; tmp= RXD byte ldi yl,low (b_com) ; ldi yh,high(b_com) ; RAM pointer add yl,xl ; adc yh,xh ; RAM pointer + RXD bytes loop st y,tmp ; save RXD byte in RAM adiw xl,1 ; Received bytes pointer +1 out TCNT0,zero ; Clear counter Timer0 ldi tmp,2 ; FOC0A FOC0B – – WGM02 CS02 CS01 CS00 out TCCR0A,tmp ; F.clk/1024 normal mode time overflow (~ ) ;----------------------; pop yh ; restore register from stack pop yl ; restore register from stack pop tmp ; restore register from stack out SREG,tmp ; restore SREG pop tmp ; restore register from stack reti ; Interrupt exit ;----------------------; boot_T0_ovf: ; Timer 0 overflow in boot section push tmp ; store register in stack in tmp,SREG ; store SREG push tmp ; store register in stack sts rxch,xh ; save amount received bytes H sts rxcl,xl ; save amount received bytes L clr xh ; clear received bytes counter H clr xl ; clear received bytes counter L ldi flags,0x80 ; set 7-th bit out TCCR0A,zero ; Stop Timer 0 out TCNT0,zero ; Clear counter Timer0 pop tmp ; Restore tmp from STACK out SREG,tmp ; Restore SREG pop tmp ; Restore tmp from STACK reti ; Interrupt exit ;----------------------; For debug led blinking each 0.25 seconds ; (TCCR3B=3) boot_T3_ovf: ; Timer 3 overflow push tmp ; Store tmp, stack in tmp,SREG ; read status register push tmp ; Store tmp, stack push tmp1 ; Store tmp1, stack push tmp2 ; Store tmp2, stack ;----------------------; lds tmp,bmode ; Load bootloader mode andi tmp,1 ; mark bit.0 sbrc tmp,0 ; skip next command if bit cleared rjmp t3_blink ; ;----------------------; ch_mreset_time: ; Chech MainRESET time lds tmp,rcnt3 ; amount OVF3 value cpi tmp,2 ; bootloader without (boot_en) command working ~ 67ms! brsh _jump_mreset ; led blink single ;----------------------; t3_blink: ; lds tmp1,rcnt1 ; Get Led value mov tmp2,tmp1 ; copy data andi tmp2,1 ; mark bit.0 tst tmp2 ; counter?0 breq boot_led_0 ; branch if equal sbi ledp,lstat ; Led ON rjmp boot_led_ok ; jump PC+2 boot_led_0: ; cbi ledp,lstat ; Led OFF boot_led_ok: ; inc tmp ; ovf counter=+1 inc tmp1 ; blink counter=+1 sts rcnt1,tmp1 ; Store led counter sts rcnt3,tmp ; Store OVF counter value pop tmp2 ; restore register from stack pop tmp1 ; restore register from stack pop tmp ; restore register from stack out SREG,tmp ; Restore SREG pop tmp ; restore register from stack reti ; Interrupt exit _jump_mreset: ; cli ; disable interrupts! jmp RESET ; jump to main RESET! ; code from datasheet AT90CAN32/64/128 ; Y = RAM data pointer ; RAMPZ0:Z = flash address pointer ; Edited lpm to ELPM! ; added Status wrote page! Write_page: ; Write flash page 256 bytes ldi tmp,(1<<PGERS)|(1<<SPMEN) call Do_spm ; Page Erase ldi tmp, (1<<RWWSRE)|(1<<SPMEN) call Do_spm ; re-enable the RWW section ; transfer data from RAM to Flash page buffer ldi xl,low (p_size) ; init loop variable ldi xh,high(p_size) ; not required for PAGESIZEB<=256 Wrloop: ; ld r0,Y+ ; ld r1,Y+ ; ldi tmp,(1<<SPMEN) ; call Do_spm ; adiw ZH:ZL,2 ; sbiw xh:xl,2 ; use subi for PAGESIZEB<=256 brne Wrloop ; ;--------------------------; execute Page Write subi ZL,low (p_size) ; restore pointer sbci ZH,high(p_size) ; not required for PAGESIZEB<=256 ldi tmp, (1<<PGWRT) | (1<<SPMEN) call Do_spm ; re-enable the RWW section ldi tmp, (1<<RWWSRE) | (1<<SPMEN) call Do_spm ; read back and check, optional ldi xl,low (p_size) ; init loop variable ldi xh,high(p_size) ; not required for PAGESIZEB<=256 subi YL,low (p_size) ; restore pointer sbci YH,high(p_size) ; ;--------------------------; Rdloop: ; elpm r0,Z+ ; Load wrote data from flash ld r1,Y+ ; Load right data from Ram cpse r0,r1 ; compare and skip if equal rjmp Loader_Error ; If not equal - STATUS ERROR! rdl_p: sbiw xh:xl,2 ; use subi for PAGESIZEB<=256 brne Rdloop ; ; return to RWW section ; verify that RWW section is safe to read Return: in tmp1,SPMCSR sbrs tmp1,RWWSB ; If RWWSB is set, the RWW section is not ready yet ldi tmp2,st_ok ; ret ; re-enable the RWW section ldi tmp,(1<<RWWSRE)|(1<<SPMEN) call Do_spm ; rjmp Return ; Do_spm: Wait_spm: ; check for previous SPM complete in tmp1,SPMCSR sbrc tmp1,SPMEN rjmp Wait_spm ; input: spmcsrval determines SPM action in tmp2,SREG ; disable interrupts if enabled, store status cli Wait_ee: ; check that no EEPROM write access is present sbic EECR,EEWE ; rjmp Wait_ee ; out SPMCSR,tmp ; SPM timed sequence spm out SREG,tmp2 ; restore SREG (to enable interrupts if originally enabled) ret ; return loader_error: ; ldi tmp2,st_err ; load status error ret ; leave write_page .include "aes128.asm" После того, как мы выходим из бута, обязательно нужно вернуть прерывания обратно! RESET: ; ;---- STACK INIT ------; ldi tmp, low(ramend) ; out SPL,tmp ; ldi tmp,high(ramend) ; out SPH,tmp ; ;----------------------; clr zero ; clr loop2 ; ;--- Move_interrupts --; in tmp,MCUCR ; Get MCUCR ori tmp,(1<<IVCE) ; Enable change of Interrupt Vectors out MCUCR,tmp ; out MCUCR,zero ; ;----------------------; sts WDTCR,zero ; disable watchdog Timer sei ; enable interrupts Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться