[En-Nut-Discussion] Attempted at91_adc rework
Marcus Jansson
jansson.marcus at yahoo.se
Thu Aug 20 23:44:52 CEST 2009
Hi list,
This is my first try at NutOS.
Related to Ref:
http://lists.egnite.de/pipermail/en-nut-discussion/2009-July/010942.html
I played around with /arch/arm/dev/at91_adc.c for sam7x256.
I'd be glad to email my code to anyone interested in supervise/mentoring me.
Highlights:
* ADCInit(int, int, int) - Init can be done with individual channels,
allocating just the buffers needed and not all 8 as the previous
ADCInit() did. Switching between new and old ADCInit can be done with
#define ADC_USE_INDIVIDUAL_CHANNELS, without adding weight to the OS.
* Some new status values are added: ADC_NO_BUFFER, ADC_BUFFER_OVERWRITE,
ADC_NO_NEW_VALUE.
* ADCBufRead/Write() - Circular buffers of any lenght != 0 (previously
needed to be a power of 2). The buffer overwrites itself nicely with
status ADC_BUFFER_OVERWRITE returned if values are not read before the
buffer wrap head and tail. This might break existing code. Fishy use of
_adc_buf_head/tail and constants (+1, +2) removed. Multiple reads from
the buffer without new values comming in from the ADC gives last ADC
value, without disturbing the buffer.
* ADCBufReadCurrent() - Read current ADC-value (the last sample),
without disturbing the buffer. Drawback: Adds some extra weight to the OS.
* ADCSetFrequency() instead of ADCSetPrescale(). Sets PRESCAL, STARTUP
and SHTIM in ADC_MR according to the desired ADC clock frequency given
(previous code used fixed values for STARTUP and SHTIM). I dont know if
ADCSetPrescale() is necessary, other than not to break code.
* ADCSetMode() was cleaned up a little, now always uses ADC SLEEP mode.
Example of use:
//Activate ADC channel 5-7
//in single conversion mode,
//with ADC clock frequency 950 kHz
ADCInit(ADC_CH5 | ADC_CH6 | ADC_CH7, SINGLE_CONVERSION, 950000UL);
ADCStartConversion();
for(i = 0; i < ADC_MAX_CHANNEL; ++i)
{
if(ADCBufRead(i, &adcvalue) != ADC_NO_BUFFER)
printf("ch#%d: %d ", i, adcvalue);
}
Outputs:
ch#5: 514 ch#6: 203 ch#7: 506
I dont know if you like this at all.
Anyway, I've had problems with ADC frequency higher than 950 kHz.
Probably due to the interrupts occuring "too fast" (maybe it is due to
the ADC SLEEP mode?), but I have not yet figured out how to speed up the
code, use nutEnterCritical()/nutExitCritical() or semaphores in the adc
irq to avoid problems. Advice?
I have not tested my code throughly for correctness or analysed how much
extra weight it adds to the OS. Hopefully no code is broken, but I dont
know. As said, any comments is appreciated.
Regards,
Marcus Jansson
More information about the En-Nut-Discussion
mailing list