中断的添加过程:
首先,因为中断要调用上下文切换代码,所以用汇编语言入口。
再从汇编语言中调用C语言。 需然在中断程序中不会完成多少任务,但是用C毕竟简化了工作,并给了代码充分的可读性。
最后就是将中断向量写入AIC的中断向寄存器了。
中断程序:
汇编部分:
RSEG ICODE:CODE
CODE32
EXTERN vUARTISR
PUBLIC vUARTISREntry
; Wrapper for the EMAC interrupt service routine. This can cause a
; context switch so requires an assembly wrapper.
; Defines the portSAVE_CONTEXT and portRESTORE_CONTEXT macros.
#include "ISR_Support.h"
vUARTISREntry:
portSAVE_CONTEXT ; Save the context of the current task.
bl vUARTISR ; Call the ISR routine.
portRESTORE_CONTEXT ; Restore the context of the current task -
; which may be different to the task that
; was interrupted.
END
C语言部分:
__arm void vUARTISR( void )
{
unsigned int status;
int i;
status = AT91C_BASE_US0->US_CSR;
AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA;
if( status & AT91C_US_ENDRX )
{
for( i = 0; i < Rx_Count; i++ )
{
US0_BuffTx[ i ] = US0_BuffRx[ i ];
}
Tx_Count = Rx_Count;
AT91C_BASE_US0->US_TPR = ( unsigned int )US0_BuffTx;
AT91C_BASE_US0->US_TCR = ( unsigned int )Tx_Count;
AT91C_BASE_US0->US_RPR = (unsigned int )US0_BuffRx;
Rx_Count = 8;
AT91C_BASE_US0->US_RCR = Rx_Count;
}
else if( status & AT91C_US_ENDTX )
{
}
else
{
AT91C_BASE_US0->US_THR = 'C';
}
//中断结束之后要通知系统中断处理完毕,否则下次此器件将不会产生中断
AT91C_BASE_AIC->AIC_EOICR = 0x1234;
}
其中有一部分是在外面定义的全局变量。
unsigned int US0_BuffRx[256];
int Rx_Count;
unsigned int US0_BuffTx[256];
int Tx_Count;
中断设置部分:
/*-----------------------------------------------------------*/
void Init_UART_DMA()
{
AT91PS_PIO pIO = AT91C_BASE_PIOA;
pIO->PIO_PDR |= 0x03;
pIO->PIO_ASR |= 0x03;
AT91C_BASE_PMC->PMC_PCER |= ( 1 << AT91C_ID_US0 );
//USART :Normal Mode
//USCLKS:MCK
//CHRL(CHARACTER LENGTH):8BIT(11)
//SYNC:0 In Asynchronous Mode
//PAR100) No Parity
//NBSTOP:1 stop bit
//CHMODE(CHANNEL MODE):Normal Mode
AT91C_BASE_US0->US_MR = 0x08C0;
//baudrate = Select_Clock/(8(2-over)CD) = 47923200/(16*312) = 9600
AT91C_BASE_US0->US_BRGR = 312;
//reset usart0
AT91C_BASE_US0->US_CR = 0x010C;
//set interrupt bit
AT91C_BASE_US0->US_IDR = 0xFFFFF;
//enable rxen and txen
AT91C_BASE_US0->US_CR = 0x0050;
//Disable AIC interrupt
AT91F_AIC_DisableIt( AT91C_BASE_AIC, AT91C_ID_US0 );
//Enable Interrupt in us0
AT91C_BASE_US0->US_IER = 0x00018;
AT91F_DBGU_Print32( AT91C_BASE_US0->US_CSR );
AT91C_BASE_US0->US_PTCR = 0x00000101;
prvSetupUARTInterrupt( );
AT91C_BASE_US0->US_RPR = ( unsigned int )US0_BuffRx;
Rx_Count = 8;
AT91C_BASE_US0->US_RCR = Rx_Count;
}
/*-----------------------------------------------------------*/
static void prvSetupUARTInterrupt( void )
{
/* Enable the interrupts in the AIC. */
AT91F_AIC_ConfigureIt(
AT91C_BASE_AIC,
AT91C_ID_US0, 6,
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
( void (*)( void ) ) vUARTISREntry
);
AT91F_AIC_EnableIt( AT91C_BASE_AIC, AT91C_ID_US0 );
}
文章评论(0条评论)
登录后参与讨论