Jump to content

    

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

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

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

Смотрю я на HEX фаил и никак не могу понять, разве я не должен там видеть диапазон памяти от 0xF800?

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this