PortuxG20 Analog-Digital Converter

I'm trying to make the ADC converter of the PortuxG20 work. I'm not one hundred percent sure that I've got my software correct yet, but when studying the documentation I found the following:

Maximum clock frequency for 8 bit conversion is 5MHz
Maximum clock frequency for 10 bit conversion is 1 MHz.

The Portux Master Clock (MCK) is at 132 MHz. The Prescaler (a 6 bit value, maximum value 63) is used to derive the ADC Clock from the MCK using the formula 132 / (PRESCALER x 2) MHz, i.e. at 132 / 126 MHz... which is > 1MHz. this would mean that I cannot use 10 bits ADC conversion anymore ?

Is there a way of reducing the clock speed of the PortuxG20 MCK?

Does anyone have a sample of software for driving the ADC controller of the PortuxG20?

Peter

Re: PortuxG20 Analog-Digital Converter

The only way to reduce the clock would be to reprogram the PMC in U-Boot (either U-Boot source or on the U-Boot CLI with the memory access functions), but I think it is still possible to use the ADC with the current MCK even if it is slightly over the specified maximum.

Here is a sample program reading all channels in 10 bit mode:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)

#define ADC_BASE    0xfffe0000
#define ADC_CR      0x00
#define ADC_MR      0x04
#define ADC_CHER    0x10
#define ADC_SR      0x1c
#define ADC_CDR(x) (0x30+(x)*0x4)

#define PMC_BASE    0xfffffc00
#define PMC_PCER    0x10
#define ADC_PID     5;

void *adc_base;
void *pmc_base;

int main(int argc, char **argv) {
	int fd;


	if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
		printf("couldn't open /dev/mem\n");
		return 1;
	}
	/* map adc memory region */
	adc_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, ADC_BASE  & ~MAP_MASK);
	if(adc_base == MAP_FAILED)
	{
		printf("mmap failed\n");
		return 1;
	}
	/* map pmc memory region */
	pmc_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PMC_BASE  & ~MAP_MASK);
	if(pmc_base == MAP_FAILED)
	{
		printf("mmap failed\n");
		return 1;
	}

	/* enable adc clock in pmc */
	*((volatile unsigned long *) (pmc_base + ((PMC_BASE + PMC_PCER) & MAP_MASK))) = 1 << ADC_PID;

	/* software reset */
	*((volatile unsigned long *) (adc_base + ((ADC_BASE + ADC_CR) & MAP_MASK))) = 0x00000001;
	/* enable adc channels 0-3 */
	*((volatile unsigned long *) (adc_base + ((ADC_BASE + ADC_CHER) & MAP_MASK))) = 0x0000000f;
	/* maximum start and sample & hold time, maximum prescaler, normal and high resolution mode, no hardware trigger */
	*((volatile unsigned long *) (adc_base + ((ADC_BASE + ADC_MR) & MAP_MASK))) = 0x0f1f3f00;
	/* start conversion */
	*((volatile unsigned long *) (adc_base + ((ADC_BASE + ADC_CR) & MAP_MASK))) = 0x00000002;

	/* wait for end of conversion of all channels */
	while((*(volatile unsigned long *) (adc_base + ((ADC_BASE + ADC_SR) & MAP_MASK)) & 0xf) != 0xf);

	/* read out adc values */
	printf("%08x\n", *((volatile unsigned long *) (adc_base + ((ADC_BASE + ADC_CDR(0)) & MAP_MASK))));
	printf("%08x\n", *((volatile unsigned long *) (adc_base + ((ADC_BASE + ADC_CDR(1)) & MAP_MASK))));
	printf("%08x\n", *((volatile unsigned long *) (adc_base + ((ADC_BASE + ADC_CDR(2)) & MAP_MASK))));
	printf("%08x\n", *((volatile unsigned long *) (adc_base + ((ADC_BASE + ADC_CDR(3)) & MAP_MASK))));

	if(munmap(adc_base, MAP_SIZE) == -1)
		return 1;
	close(fd);

	return 0;
}

Re: PortuxG20 Analog-Digital Converter

Thanks, also for your sample code. I did not set the PMC and now my code also works (also at 10 bit). Onward with development!

Syndicate content