Помогите разобраться с прерываниями в Bootloader-е.
Я набросал скелет загрузочника, но во время симуляции(когда должно возникать прерывание), они не срабатывают.
Я не совсем понимаю где должен располагаться обработчик прерывания и где он находится у меня. Что происходит с вектором прерывания при выставлении бита
Код
MCUCR= (1<<IVCE);
MCUCR= (1<<IVSEL);
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