Hi!
I'm using a LM4F232 Evaluation Kit and have come across some strange behavior in ADC module, not sure if it is a hw issue or
just me. I'm setting up an ADC to sample 3 channels at constant rate (via timer trigger). Every now and then, when I reset
the board after programming, the mcu enters NMI just after SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); The set up code is as follows:
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlPeripheralReset(SYSCTL_PERIPH_ADC0);
SysCtlDelay(1000); // delay, otherwise a wild NMI appears now and then
ADCReferenceSet(ADC0_BASE, ADC_REF_EXT_3V);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // erratum 6.1
HWREG(GPIO_PORTB_BASE + GPIO_O_AMSEL) |= GPIO_PIN_6; // erratum 6.1
ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0);
ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0 );
ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH1 );
ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH2 | ADC_CTL_IE | ADC_CTL_END);
ADCSequenceEnable(ADC0_BASE, 0);
ADCIntEnable(ADC0_BASE, 0);
When I insert a small delay just after enabling and resetting the module, the issue dissapears and the module operates
as intended. No sure what is causing the issue here. I'm running at 80Mhz:
SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
Timer which controls aquisition rate is configured as 32 bit timer with interrupt on timeout
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
SysCtlPeripheralReset(SYSCTL_PERIPH_TIMER0);
TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet()/ADC_RATE);
TimerControlTrigger(TIMER0_BASE, TIMER_A, true);
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
TimerEnable(TIMER0_BASE, TIMER_A);
Interrupt routine for time just clears the interrupt source. While the interrupt routine for ADC clears the source and fetches data:
void ADCIntHandler (void)
{
ADCIntClear(ADC0_BASE, 0);
samples_aquired = ADCSequenceDataGet(ADC0_BASE, 0, &adc_data[0]);
}
Another thing I've noticed is that ADCSequenceOverflow(ADC0_BASE, 0) always returns 1, even if capture rate is below 500Hz (ADC_RATE). Not sure why this occurs, running at 80Mhz gives me plenty of time to empty the FIFO in the ISR.
Any ideas?
P.S I'm using Keil 4.22a