#include "nios2_ctrl_reg_macros.h"
void main(void);
void interrupt_handler(void);
void interval_timer_isr(void);
void pushbutton_ISR(void);
/* глобальные переменные */
extern int key_pressed;
/* Код на языке ассемблер, выполняющийся при сбросе процессора */
void the_reset (void) __attribute__ ((section (".reset")));
void the_reset (void)
/************************************************************************************
* Обработчик сброса
***********************************************************************************/
{
asm (".set noat");
asm (".set nobreak");
asm ("movia r2, main"); //вызывается основная программа на С
asm ("jmp r2");
}
/* Код на языке ассемблер, выполняющийся при возникновении прерывания или исключения*/
void the_exception (void) __attribute__ ((section (".exceptions")));
void the_exception (void)
/*******************************************************************************
* Обработчик исключений
******************************************************************************/
{
asm (".set noat");
asm (".set nobreak");
asm ("subi sp, sp, 128");
asm ("stw et, 96(sp)");
asm ("rdctl et, ctl4");
asm ("beq et, r0, SKIP_EA_DEC"); //прерывания не внешние
asm ("subi ea, ea, 4"); //декрементируем регистр ea на 1 команду
asm ("SKIP_EA_DEC:");
asm ("stw r1, 4(sp)"); //сохраняем содержимое всех регистров в стеке
asm ("stw r2, 8(sp)");
asm ("stw r3, 12(sp)");
asm ("stw r4, 16(sp)");
asm ("stw r5, 20(sp)");
asm ("stw r6, 24(sp)");
asm ("stw r7, 28(sp)");
asm ("stw r8, 32(sp)");
asm ("stw r9, 36(sp)");
asm ("stw r10, 40(sp)");
asm ("stw r11, 44(sp)");
asm ("stw r12, 48(sp)");
asm ("stw r13, 52(sp)");
asm ("stw r14, 56(sp)");
asm ("stw r15, 60(sp)");
asm ("stw r16, 64(sp)");
asm ("stw r17, 68(sp)");
asm ("stw r18, 72(sp)");
asm ("stw r19, 76(sp)");
asm ("stw r20, 80(sp)");
asm ("stw r21, 84(sp)");
asm ("stw r22, 88(sp)");
asm ("stw r23, 92(sp)");
asm ("stw r25, 100(sp)"); // r25 = bt
asm ("stw r26, 104(sp)"); // r26 = gp
asm ("stw r28, 112(sp)"); // r28 = fp
asm ("stw r29, 116(sp)"); // r29 = ea
asm ("stw r30, 120(sp)"); // r30 = ba
asm ("stw r31, 124(sp)"); // r31 = ra
asm ("addi fp, sp, 128");
asm ("call interrupt_handler"); //вызываем процедуру обработки прерывания
asm ("ldw r1, 4(sp)"); //восстанавливаем содержимое всех регистров
asm ("ldw r2, 8(sp)");
asm ("ldw r3, 12(sp)");
asm ("ldw r4, 16(sp)");
asm ("ldw r5, 20(sp)");
asm ("ldw r6, 24(sp)");
asm ("ldw r7, 28(sp)");
asm ("ldw r8, 32(sp)");
asm ("ldw r9, 36(sp)");
asm ("ldw r10, 40(sp)");
asm ("ldw r11, 44(sp)");
asm ("ldw r12, 48(sp)");
asm ("ldw r13, 52(sp)");
asm ("ldw r14, 56(sp)");
asm ("ldw r15, 60(sp)");
asm ("ldw r16, 64(sp)");
asm ("ldw r17, 68(sp)");
asm ("ldw r18, 72(sp)");
asm ("ldw r19, 76(sp)");
asm ("ldw r20, 80(sp)");
asm ("ldw r21, 84(sp)");
asm ("ldw r22, 88(sp)");
asm ("ldw r23, 92(sp)");
asm ("ldw r24, 96(sp)");
asm ("ldw r25, 100(sp)"); // r25 = bt
asm ("ldw r26, 104(sp)"); // r26 = gp
asm ("ldw r28, 112(sp)"); // r28 = fp
asm ("ldw r29, 116(sp)"); // r29 = ea
asm ("ldw r30, 120(sp)"); // r30 = ba
asm ("ldw r31, 124(sp)"); // r31 = ra
asm ("addi sp, sp, 128"); //увеличиваем адрес указателя стека
asm ("eret"); //выходим из обработчика прерывания
}
/*****************************************************************************
*Процедура обработки прерываний
*****************************************************************************/
void interrupt_handler(void)
{
int ipending;
NIOS2_READ_IPENDING(ipending); //читаем содержимое бита ipending
if (ipending & 0x1) //если было обнаружено прерывание от таймера
{
interval_timer_isr(); //вызываем процедуру обработки прерываний от таймера
}
if (ipending & 0x2) // если было обнаружено прерывание от кнопок
{
pushbutton_ISR(); //вызываем процедуру обработки прерываний от кнопок
}
return;
}
Листинг 14. Программа обслуживания прерываний от интервального таймера
#include "key_codes.h"
extern volatile int key_pressed;
extern volatile int pattern;
/*****************************************************************************
* Процедура обработки прерываний от интервального таймера
******************************************************************************/
void interval_timer_isr()
{
volatile int * interval_timer_ptr = (int *) 0x10002000; //базовый адрес таймера
volatile int * HEX3_HEX0_ptr = (int *) 0x10000020; //адрес HEX3_HEX0
volatile int * HEX7_HEX4_ptr = (int *) 0x10000030; //адрес HEX7_HEX4
*(interval_timer_ptr) = 0; //Сбрасываем прерывания
*(HEX3_HEX0_ptr) = pattern; // вывод заготовки на HEX3_HEX0
*(HEX7_HEX4_ptr) = pattern; // вывод заготовки на HEX7_HEX4
/* сдвигаем текст на 7-сегментных индикаторах */
if (key_pressed == KEY2) //если была нажата кнопка KEY2, то сдвигаем текст влево
if (pattern & 0x80000000)
pattern = (pattern << 1) | 1;
else
pattern = pattern << 1;
else if (key_pressed == KEY1) //если была нажата кнопка KEY1, то сдвигаем текст вправо
if (pattern & 0x00000001)
pattern = (pattern >> 1) | 0x80000000;
else
pattern = (pattern >> 1) & 0x7FFFFFFF;
return;
}