Jump to content

    
Sign in to follow this  
Radi0

Bootloader + Прерывания + Proteus

Recommended Posts

Добрый день уважаемые пользователи.

Помогите разобраться с прерываниями в 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

Edited by Radi0

Share this post


Link to post
Share on other sites

Компилятор (или линкер) решил, что таблица векторов по умолчанию у Вас будет находиться в нулевых адресах, и разместил её там (о чём говорят первые строки с адресами xx0000xx... и дальше), затем идёт разрыв и продолжается уже с 0xF000 адреса. Так что, у Вас явно нелады с параметрами сборки.

Посмотрите настройки проекта. Возомжно, нужно явно указать положение секции .text для сборки загрузчика (например, так: --section-start=.text=0x1F000 для Вашего случая). Адрес фактически сдвинут на 1 бит ВЛЕВО. То есть, 0xF800 -> 0x1F000

При этом, уже не будет необходимости указывать начало секции где-то в коде.

 

> #pragma orgall 0xF800

Вот эту строку нужно желательно будет убрать.

 

Если используете AVRStudio - ключ начала секции указывать в параметрах сборки проекта. Точнее не подскажу.

Edited by AlanDrakes

Share this post


Link to post
Share on other sites

Возможно здесь есть ответы на некоторые вопросы.

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this