Листинг 13. Обработчики сброса и исключений на С
#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;
}
Дата добавления: 2015-05-30; просмотров: 770;