[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