I'm studying the Kinetis KwikStik board (K40) and specially the audioscope demo.
After an analysis of the producer consumer role of PE_ISR(DMA_ADC_DoneInterrupt) (in Events.c) and ShowData() (in ProcessorExpert.c), I think the implementation in this demo has a race condition where the display function reads the data pointed to be written by the ADC thus turning useless the intended double buffer mechanism:
This is the code for the interrupt service routine:
PE_ISR(DMA_ADC_DoneInterrupt)
{
/* Write your interrupt code here ... */
// Clear all DMA interrupt flags
DMA_CINT = 0x40;
// switch bufstart to other part of buffer
BufStart = ADC_BUFFER_SIZE - BufStart;
// reset destination address
DMA_TCD0_DADDR = (uint32_t)&(MeasuredValues[BufStart]);
// toggle pin
GPIO1_ToggleFieldBits(GPIOPtr, TST,1);
// toggle flag
Measured = TRUE;
}
In the routine above the setting of BufStart switches the start of the buffer to be written by the ADC and toggles the flag "Measured" to true which is tested in the main of ProcessorExpert.c:
The pertaining snippet of the code is the following:
if (Measured) {
cntr++;
// display only time after time
if (cntr > 10) {
// display data
ShowData();
cntr = 0;
}
// reset flag
Measured = FALSE;
}
The call to ShowData() is only made if the flag "Measured" is true, this procedure has the following code:
for (i=0; i<37; i++) {
val = MeasuredValues[BufStart+i];
sum += val;
// substract last average
val = val - LastAvg;
if (val < -150) {
pos = 0;
} else if (val < -90) {
pos = 1;
} else if (val < -60) {
pos = 2;
} else if (val < -30) {
pos = 3;
} else if (val < 30) {
pos = 4;
} else if (val < 60) {
pos = 5;
} else if (val < 90) {
pos = 6;
} else {
pos = 7;
}
So when this code is reached the for loop has the values addressed by MeasuredValues[BufStart+i] where BufStart already has been advanced to the (double) buffer region shared between the ADC DMA channel and this routine effectively reading the region which the ADC is writing to it.
Did I miss something or you agree with my understating?
Regards,
--
Cesar Rabak