Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Bootloader + Прерывания + Proteus
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Radi0
Добрый день уважаемые пользователи.
Помогите разобраться с прерываниями в Bootloader-е.
Я набросал скелет загрузочника, но во время симуляции(когда должно возникать прерывание), они не срабатывают.
Я не совсем понимаю где должен располагаться обработчик прерывания и где он находится у меня. Что происходит с вектором прерывания при выставлении бита
Код
MCUCR= (1<<IVCE);
MCUCR= (1<<IVSEL);


Исходные данные такие: Контроллер Atmega 128, компилятор MicroC Pro версия 6, Proteus версия 8.1. Фьюзы везде выставлены одинаково bootrst 1, boot loader Size 0xf800.

Исходник и полученный hex прилагаю.

CODE

#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

CODE

: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
Radi0
Смотрю я на HEX фаил и никак не могу понять, разве я не должен там видеть диапазон памяти от 0xF800?
AlanDrakes
Компилятор (или линкер) решил, что таблица векторов по умолчанию у Вас будет находиться в нулевых адресах, и разместил её там (о чём говорят первые строки с адресами xx0000xx... и дальше), затем идёт разрыв и продолжается уже с 0xF000 адреса. Так что, у Вас явно нелады с параметрами сборки.
Посмотрите настройки проекта. Возомжно, нужно явно указать положение секции .text для сборки загрузчика (например, так: --section-start=.text=0x1F000 для Вашего случая). Адрес фактически сдвинут на 1 бит ВЛЕВО. То есть, 0xF800 -> 0x1F000
При этом, уже не будет необходимости указывать начало секции где-то в коде.

> #pragma orgall 0xF800
Вот эту строку нужно желательно будет убрать.

Если используете AVRStudio - ключ начала секции указывать в параметрах сборки проекта. Точнее не подскажу.
pavel-pervomaysk
Возможно здесь есть ответы на некоторые вопросы.
CRC-16 и AES128 не вложены.
Сначала нужно добиться устойчивой работы в открытом виде, затем применить шифрование (если оно необходимо) на свой вкус. В 4КБ многое влезет...

ЕЕпром не делал, ибо у меня он не использовался.


Кстати, рекомендую скорость выбрать хотя бы 57600, на 9600 уснуть можно, читая - записывая 120кБ...
В моем варианте (500k) чтение занимает 7 секунд, запись 33 сенкунды.


CODE
; 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 sm.gif
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"



После того, как мы выходим из бута, обязательно нужно вернуть прерывания обратно!


CODE

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
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.