I have a high speed AD conversion, a DMA is implemented. After the AD DMA complete, then interrupt occur, but the "AT91C_ADC_ENDRX" flag can't be cleared, so the interrupt keep occuring, if I put a bearkpoint in the in the interrupt routine, then the flag can be cleared.
AT91C_BASE_ADC->ADC_SR; can't clear the flag, why?
here are the source code:
static void Configure_AD(void)
{
unsigned short* ADC_Ptr;
unsigned short* ADC_Ptr_Next;
int i;
/*
ADCClock = MCK/ ((AD_PRESCAL +1) *2);
Startup Time = (AD_STARTUP +1) *8 /ADCClock;
Sample&Hold Time = (AD_SHTIM + 1) /ADCClock;
*/
#define AD_PRESCAL 1
#define AD_STARTUP 1
#define AD_SHTIM 2
// Enable peripheral clock
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_ADC;
//Notice: After ADC_SR = 0xc000 after Reset;
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; //Reset AD
//Rxternal trigger: TIOA2 output pulse; Get data using ISP.
AT91C_BASE_ADC->ADC_MR = ((AD_SHTIM << 24) | (AD_STARTUP << 16) | (AD_PRESCAL <<

| AT91C_ADC_TRGEN_EN | AT91C_ADC_TRGSEL_TIOA2);
AT91C_BASE_ADC->ADC_CHER = AT91C_ADC_CH4; //channel 4 enable
//Configure PDC; Write Counter Register reset ADC_SR.
ADC_Ptr = ADC_Result;
ADC_Ptr_Next = ADC_Result_Next;
AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTDIS ;
AT91C_BASE_ADC->ADC_RPR = (unsigned long)ADC_Ptr; // Receive Pointer Register
AT91C_BASE_ADC->ADC_RCR = AD_DATA_BUFFER_SIZE; // Receive Counter Register
AT91C_BASE_ADC->ADC_RNPR = (unsigned long)ADC_Ptr_Next; // Receive Next Pointer Register
AT91C_BASE_ADC-> ADC_RNCR = AD_DATA_BUFFER_SIZE ; // Receive Next Counter Register
AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTEN ; //Enable PDC
AT91C_BASE_ADC->ADC_IER = AT91C_ADC_ENDRX | AT91C_ADC_RXBUFF; //enable interrupt on transfer complete
//AT91C_BASE_ADC->ADC_IER = AT91C_ADC_DRDY;
// Configure and enable interrupt
AIC_ConfigureIT(AT91C_ID_ADC, AT91C_AIC_PRIOR_LOWEST, ISR_adc);
AIC_EnableIT(AT91C_ID_ADC);
}
=================================================
static void ISR_adc(void)
{
unsigned int AdcStatus = AT91C_BASE_ADC->ADC_SR;
unsigned short* ADC_Ptr;
unsigned short* ADC_Ptr_Next;
if(((AdcStatus & AT91C_ADC_RXBUFF) == AT91C_ADC_RXBUFF) &
((AdcStatus & AT91C_ADC_ENDRX) == AT91C_ADC_ENDRX))
{//Both bit set when get the end of next buffer
ADC_Ptr = ADC_Result;
ADC_Ptr_Next = ADC_Result_Next;
AT91C_BASE_ADC->ADC_RPR = (unsigned long) ADC_Ptr; // Receive Pointer Register
AT91C_BASE_ADC->ADC_RCR = AD_DATA_BUFFER_SIZE; // Receive Counter Register
AT91C_BASE_ADC->ADC_RNPR = (unsigned long)ADC_Ptr_Next; // Receive Next Pointer Register
AT91C_BASE_ADC->ADC_RNCR = AD_DATA_BUFFER_SIZE ; // Receive Next Counter Registe
TC_Stop(AT91C_BASE_TC2); // Stop the Timer to stop automatic AD conversion.
}
else if((AdcStatus & AT91C_ADC_ENDRX) == AT91C_ADC_ENDRX)
{//ENDRX bit set when reach the end of buffer.
AT91C_BASE_ADC->ADC_RNCR = AD_DATA_BUFFER_SIZE; //Write the register to Clear STATUS register ENDRX bit
}
}