AT91sam7x 256:仅中断 运行 一次
AT91sam7x 256: Interrupt just run once
我在 at91sam7x256 上使用带 DMA 的 USART 读取和写入数据。
因为我没有成功,所以我开始创建一个简单的例子,但问题已经存在。
主要问题是中断例程第一次触发,第一次后我无法从 USART 接收数据!
#include "at91sam7x256.h"
char Buffer[10]; // holds received characters
unsigned long nChars = 0; // counts number of received chars
char *pBuffer = &Buffer[0]; // pointer into Buffer
void Usart0IrqHandler (void);
void USART0Setup(void);
int main(void)
{
unsigned long j;
unsigned int IdleCount = 0;
// set up USART0
USART0Setup();
// *****************************
// * endless blink loop *
// *****************************
while (1) {
for (j = 1000000; j != 0; j-- ); // wait 1 second 1000000
IdleCount++; // count # of times through the idle loop
for (j = 1000000; j != 0; j-- ); // wait 1 second 1000000
}
}
////////
void Usart0IrqHandler (void) {
volatile AT91PS_USART pUsart0 = AT91C_BASE_US0; // create a pointer to USART0 structure
if ((pUsart0->US_CSR & AT91C_US_ENDRX) == AT91C_US_ENDRX) {
// we have a end-of-receive interrupt (ENDRX)
pUsart0->US_RCR = 10; // restore the receive count - clears ENDRX flag
}
}
void USART0Setup(void) {
volatile AT91PS_USART pUSART0 = AT91C_BASE_US0; // create a pointer to USART0 structure
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC; // pointer to AIC data structure
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; // pointer to PIO data structure
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; // pointer to PMC data structure
pPMC->PMC_PCER = (1<<AT91C_ID_US0); // enable usart0 peripheral clock
pPIO->PIO_PDR = AT91C_PA0_RXD0 | AT91C_PA1_TXD0; // enable peripheral control of PA0 and PA1 (RXD0 and TXD0)
pPIO->PIO_ASR = AT91C_PIO_PA0 | AT91C_PIO_PA1; // assigns the 2 I/O lines to peripheral A function
pPIO->PIO_BSR = 0; // peripheral B function set to "no effect"
pUSART0->US_CR = AT91C_US_RSTRX | // reset receiver
AT91C_US_RSTTX | // reset transmitter
AT91C_US_RXDIS | // disable receiver
AT91C_US_TXDIS; // disable transmitter
pUSART0->US_MR = AT91C_US_PAR_NONE | // no parity
0x3 << 6; // 8-bit characters
pUSART0->US_IER = 0x00; // no usart0 interrupts enabled (no effect)
pUSART0->US_IDR = 0xFFFF; // disable all USART0 interrupts
pUSART0->US_BRGR = 0x139; // CD = 0x139 (313 from above calculation for 9600 baud)
// FP=0 (not used)
pUSART0->US_RTOR = 0; // receiver time-out (disabled)
pUSART0->US_TTGR = 0; // transmitter timeguard (disabled)
pUSART0->US_RPR = (unsigned int)Buffer; // address of DMA input buffer
pUSART0->US_RCR = 10; // we'll read in 10 chars via DMA
pUSART0->US_TPR = (unsigned int)0; // address of DMA output buffer (use same one)
pUSART0->US_TCR = 0; // we'll transmit 0 chars via DMA
pUSART0->US_RNPR = (unsigned int)0; // next DMA receive buffer address
// if set to zero, it is not used
pUSART0->US_RNCR = (unsigned int)0; // next DMA receive counter
// if set to zero, it is not used
pUSART0->US_TNPR = (unsigned int)0; // next DMA transmit buffer address
// if set to zero, it is not used
pUSART0->US_TNCR = (unsigned int)0; // next DMA transmit counter
// if set to zero, it is not used
pUSART0->US_PTCR = AT91C_PDC_RXTEN | // enable receive transfer,
AT91C_PDC_TXTDIS; // disable transmit transfer
// Disable USART0 interrupt in AIC Interrupt Disable Command Register
pAIC->AIC_IDCR = (1<<AT91C_ID_US0);
// Set the USART0 IRQ handler address in AIC Source
pAIC->AIC_SVR[AT91C_ID_US0] =
(unsigned int)Usart0IrqHandler; // Vector Register[6]
// Set the interrupt source type and priority
pAIC->AIC_SMR[AT91C_ID_US0] =
(AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 0x4 ); // in AIC Source Mode Register[6]
// Enable the USART0 interrupt in AIC Interrupt Enable Command Register
pAIC->AIC_IECR = (1<<AT91C_ID_US0);
// enable the USART0 receiver and transmitter
pUSART0->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
// enable the USART0 end-of-receive interrupt
pUSART0->US_IER = AT91C_US_ENDRX; // enable ENDRX usart0 end-of-receive interrupt
pUSART0->US_IDR = ~AT91C_US_ENDRX; // disable all interrupts except ENDRX
}
//------------------
// end of file
//------------------
在中断中设置计数(US_RCR)之前,需要重新初始化接收指针:
pUSART0->US_RPR = (unsigned int)Buffer;
您的设备可能出现故障,因为 PDC 正在缓冲区外写入。
有两个问题:
1- 当我使用 Keil uVision 时,我需要使用 __irq
来定义中断服务程序!
2-令人惊讶的是,中断的结束没有被触发!所以使用:
*AT91C_AIC_EOICR = 0;
void __irq Usart0IrqHandler (void) {
volatile AT91PS_USART pUsart0 = AT91C_BASE_US0; // create a pointer to USART0 structure
if ((pUsart0->US_CSR & AT91C_US_ENDRX) == AT91C_US_ENDRX) {
pUsart0->US_RPR = (unsigned int)Buffer; // we have a end-of-receive interrupt (ENDRX)
pUsart0->US_RCR = 10; // restore the receive count - clears ENDRX flag
}
*AT91C_AIC_EOICR = 0; // end of interrupts
}
我在 at91sam7x256 上使用带 DMA 的 USART 读取和写入数据。 因为我没有成功,所以我开始创建一个简单的例子,但问题已经存在。 主要问题是中断例程第一次触发,第一次后我无法从 USART 接收数据!
#include "at91sam7x256.h"
char Buffer[10]; // holds received characters
unsigned long nChars = 0; // counts number of received chars
char *pBuffer = &Buffer[0]; // pointer into Buffer
void Usart0IrqHandler (void);
void USART0Setup(void);
int main(void)
{
unsigned long j;
unsigned int IdleCount = 0;
// set up USART0
USART0Setup();
// *****************************
// * endless blink loop *
// *****************************
while (1) {
for (j = 1000000; j != 0; j-- ); // wait 1 second 1000000
IdleCount++; // count # of times through the idle loop
for (j = 1000000; j != 0; j-- ); // wait 1 second 1000000
}
}
////////
void Usart0IrqHandler (void) {
volatile AT91PS_USART pUsart0 = AT91C_BASE_US0; // create a pointer to USART0 structure
if ((pUsart0->US_CSR & AT91C_US_ENDRX) == AT91C_US_ENDRX) {
// we have a end-of-receive interrupt (ENDRX)
pUsart0->US_RCR = 10; // restore the receive count - clears ENDRX flag
}
}
void USART0Setup(void) {
volatile AT91PS_USART pUSART0 = AT91C_BASE_US0; // create a pointer to USART0 structure
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC; // pointer to AIC data structure
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; // pointer to PIO data structure
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; // pointer to PMC data structure
pPMC->PMC_PCER = (1<<AT91C_ID_US0); // enable usart0 peripheral clock
pPIO->PIO_PDR = AT91C_PA0_RXD0 | AT91C_PA1_TXD0; // enable peripheral control of PA0 and PA1 (RXD0 and TXD0)
pPIO->PIO_ASR = AT91C_PIO_PA0 | AT91C_PIO_PA1; // assigns the 2 I/O lines to peripheral A function
pPIO->PIO_BSR = 0; // peripheral B function set to "no effect"
pUSART0->US_CR = AT91C_US_RSTRX | // reset receiver
AT91C_US_RSTTX | // reset transmitter
AT91C_US_RXDIS | // disable receiver
AT91C_US_TXDIS; // disable transmitter
pUSART0->US_MR = AT91C_US_PAR_NONE | // no parity
0x3 << 6; // 8-bit characters
pUSART0->US_IER = 0x00; // no usart0 interrupts enabled (no effect)
pUSART0->US_IDR = 0xFFFF; // disable all USART0 interrupts
pUSART0->US_BRGR = 0x139; // CD = 0x139 (313 from above calculation for 9600 baud)
// FP=0 (not used)
pUSART0->US_RTOR = 0; // receiver time-out (disabled)
pUSART0->US_TTGR = 0; // transmitter timeguard (disabled)
pUSART0->US_RPR = (unsigned int)Buffer; // address of DMA input buffer
pUSART0->US_RCR = 10; // we'll read in 10 chars via DMA
pUSART0->US_TPR = (unsigned int)0; // address of DMA output buffer (use same one)
pUSART0->US_TCR = 0; // we'll transmit 0 chars via DMA
pUSART0->US_RNPR = (unsigned int)0; // next DMA receive buffer address
// if set to zero, it is not used
pUSART0->US_RNCR = (unsigned int)0; // next DMA receive counter
// if set to zero, it is not used
pUSART0->US_TNPR = (unsigned int)0; // next DMA transmit buffer address
// if set to zero, it is not used
pUSART0->US_TNCR = (unsigned int)0; // next DMA transmit counter
// if set to zero, it is not used
pUSART0->US_PTCR = AT91C_PDC_RXTEN | // enable receive transfer,
AT91C_PDC_TXTDIS; // disable transmit transfer
// Disable USART0 interrupt in AIC Interrupt Disable Command Register
pAIC->AIC_IDCR = (1<<AT91C_ID_US0);
// Set the USART0 IRQ handler address in AIC Source
pAIC->AIC_SVR[AT91C_ID_US0] =
(unsigned int)Usart0IrqHandler; // Vector Register[6]
// Set the interrupt source type and priority
pAIC->AIC_SMR[AT91C_ID_US0] =
(AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 0x4 ); // in AIC Source Mode Register[6]
// Enable the USART0 interrupt in AIC Interrupt Enable Command Register
pAIC->AIC_IECR = (1<<AT91C_ID_US0);
// enable the USART0 receiver and transmitter
pUSART0->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
// enable the USART0 end-of-receive interrupt
pUSART0->US_IER = AT91C_US_ENDRX; // enable ENDRX usart0 end-of-receive interrupt
pUSART0->US_IDR = ~AT91C_US_ENDRX; // disable all interrupts except ENDRX
}
//------------------
// end of file
//------------------
在中断中设置计数(US_RCR)之前,需要重新初始化接收指针:
pUSART0->US_RPR = (unsigned int)Buffer;
您的设备可能出现故障,因为 PDC 正在缓冲区外写入。
有两个问题:
1- 当我使用 Keil uVision 时,我需要使用 __irq
来定义中断服务程序!
2-令人惊讶的是,中断的结束没有被触发!所以使用:
*AT91C_AIC_EOICR = 0;
void __irq Usart0IrqHandler (void) {
volatile AT91PS_USART pUsart0 = AT91C_BASE_US0; // create a pointer to USART0 structure
if ((pUsart0->US_CSR & AT91C_US_ENDRX) == AT91C_US_ENDRX) {
pUsart0->US_RPR = (unsigned int)Buffer; // we have a end-of-receive interrupt (ENDRX)
pUsart0->US_RCR = 10; // restore the receive count - clears ENDRX flag
}
*AT91C_AIC_EOICR = 0; // end of interrupts
}