OLIMEX CS-E9302: Accessing ADC and IO-Ports

Hi everybody!

After solving my basic compilation problems I’d like to know how to access ADC and the other DIO-Ports. I could not find any documentation for the OLIMEX CS-E9302 concerning this topic.

Has anybody figured out how to get values from the ADC/DIO-Port

Kind Regards

I found some sources and combined them for accessing the adc.

Somehow it delivers values, maybe anybody has some expiriances …

/*

  • ADC_OLIMEX.c

  • Created by fritz on 21.12.08.

ADC Operation

================

1 To enable clocks for the ADC block, set the TSEN bit in the Syscon section (ADCClkDiv register).

2 Set the DeviceCfg.ADCEN bit.

3 Clear the DeviceCfg.ADCPD bit.

4 Select an input. First unlock the software lock by writing 0xAA to the ADCSWLock register.

Then write an appropriate value (selected from Table 20-2on page520) to the ADCSwitch register.

5 To poll, read the ADCResult register repeatedly. Bit 31 of this register is the SDR,

or Synchronous Data Ready, bit. This bit is set when a new valid conversion value appears in

this register and is cleared when this register is read.

So when two consecutive reads show the bit clear and then set, the second read has the new valid value.

6 Conversion data may also be processed using interrupts from this module. If bit 11 in the ADCIntEn register

(the RINTEN bit) is set, an interrupt occurs whenever the SDR bit in the ADCResult register is set.

Therefore, an interrupt handler can read the ADCResult register whenever a new valid sample appears

in the register, which both returns a new conversion value and clears the interrupt.

Register Memory Map

====================

Address Name SW locked Type Size Description


0x8090_0000 Reserved

0x8090_0004 Reserved

0x8090_0008 ADCResult No Read Only 32 bits ADC result register.

0x8090_000C Reserved

0x8090_0010 Reserved

0x8090_0014 Reserved

0x8090_0018 ADCSwitch Write Read/Write 28 bits ADC Switch Matrix control register.

0x8090_001C Reserved

0x8090_0020 ADCSWLock NA Read/Write 1-bit read ADC software lock register.

8-bit write

0x8090_0024 ADCIntEn No Read/Write 9 bits ADC Interrupt Enable Register

0x8093_0090 ADCClkDiv Yes R/W 32 ADC Clock Divider

0x8093_0080 DeviceCfg Yes R/W 32 Device configuration

ADC result register: 0x8090_0008

Bit 31: SDR: Synchronous Data Ready

Bit 0-12: AD: Analog-to-digital converter output at 12-bit resolution

ADCSwitch: 0x8090_0018

Input to Measure ADC Switch Value

ADC4 0x0000_0610

ADC3 0x0000_0620

ADC2 0x0000_0640

ADC1 0x0000_0680

ADC0 0x0000_0608

ADCSWLock: 0x8090_0020

SWLCK Software lock bits

WRITE: The Unlock value for this feature is 0xAA

READ: During a read operation SWLCK[0] has the following meaning:

1 = Unlocked for current bus access.

0 = Locked

ADCIntEn: 0x8090_0024

RINTEN: Bit 11: Synchronous Data Ready Interrupt Enable. Setting this bit results in an

interrupt whenever the Synchronous Data Ready (SDR) bit in the ADCResult register is set.

ADCClkDiv: 0x8093_0090

ADCEN: Bit 31: ADC clock enable.

ADIV: Bit 16: ADC clock divider value.

0 - ADC Clock is divide-by-16 from the external oscillator.

1 - ADC Clock is divide-by-4 from the external oscillator.

DeviceCfg: 0x8093_0080

ADCPD: Bit 2: ADC Power Down.

1 - ADC and clocks are powered down.

0 - ADC and clocks are active. ADCPD must be zero for normal ADC operation.

ADCEN: Bit 17: ADC Enable.

The ADCEN bit does not affect the ADC power state.

ADC power down is directly controlled by the ADCPD bit.

1 = ADC Interface enabled.

0 = ADC Interface disabled.

*/

#include<unistd.h>

#include<sys/types.h>

#include<sys/mman.h>

#include<stdio.h>

#include<fcntl.h>

#include<assert.h>

#include<time.h>

#define ADC_PAGE 0x80900000 // ADC result (+0x08) ADCSwitch (+0x18) ADCSWLock(+0x20) ADCIntEn(+0x24)

#define ADCRESULT_OFFSET 0x0008

#define SDR_MASK 0x80000000

#define DATA_OFFSET 0x0008

#define DATA_MASK 0xFFFF

#define ADCSWITCH_OFFSET 0x0018

#define ADC_CH0 0x0608

#define ADC_CH1 0x0680

#define ADC_CH2 0x0640

#define ADC_CH3 0x0620

#define ADC_CH4 0x0610

#define ADCSWLOCK_OFFSET 0x0020

#define UNLOCK_VAL 0xAA

#define SYSCON_PAGE 0x80930000 //ADCClkDiv (+0x90) DeviceCfg (+0x80)

#define ADCCLKDIV_OFFSET 0x0090

#define SYSCON_UNLOCK 0x00C0

#define TSEN_MASK 0x80000000

#define DEVICECFG_OFFSET 0x0080

#define ADCPD_MASK 0x02

#define ADCEN_MASK 0x20000

#define TRUE 0x01

#define FALSE 0x00

/* prototypes */

void init_ADC(unsigned long adc_page, unsigned long syscon_page);

int read_channel(unsigned long adc_page, unsigned short channel);

static char is_ADC_busy(unsigned long adc_page);

/* globals */

static unsigned long dr_page, adc_page, syscon_page, pld_page;

int adc_result;

/* READ&WRITEs */

static inline unsigned short READ16(unsigned long addr)

{

unsigned short ret;

asm volatile (

“ldrh %0, [ %1 ]\n”

: “=r” (ret)

: “r” (addr)

: “memory”

);

return ret;

}

static inline void WRITE16(unsigned long addr, unsigned short dat)

{

asm volatile (

“strh %1, [ %0 ]\n”

:

: “r” (addr), “r” (dat)

: “memory”

);

}

static inline unsigned long READ32(unsigned long addr)

{

unsigned long ret;

asm volatile (

“ldr %0, [ %1 ]\n”

: “=r” (ret)

: “r” (addr)

: “memory”

);

return ret;

}

static inline void WRITE32(unsigned long addr, unsigned long dat)

{

asm volatile (

“str %1, [ %0 ]\n”

:

: “r” (addr), “r” (dat)

: “memory”

);

}

static inline unsigned char READ8(unsigned long addr)

{

unsigned char ret;

asm volatile (

“ldrb %0, [ %1 ]\n”

: “=r” (ret)

: “r” (addr)

: “memory”

);

return ret;

}

static inline void WRITE8(unsigned long addr, unsigned char dat)

{

asm volatile (

“strb %1, [ %0 ]\n”

:

: “r” (addr), “r” (dat)

: “memory”

);

}

void init_ADC(unsigned long adc_page, unsigned long syscon_page)

{

unsigned long val;

/* set TSEN bit */

val = READ32(syscon_page + ADCCLKDIV_OFFSET);

//unlock the software lock

WRITE32(syscon_page + SYSCON_UNLOCK, UNLOCK_VAL);

WRITE32(syscon_page + ADCCLKDIV_OFFSET, TSEN_MASK | val);

/* set ADCEN bit */

val = READ32(syscon_page + DEVICECFG_OFFSET);

WRITE32(adc_page + SYSCON_UNLOCK, UNLOCK_VAL); //unlock the soft lock

WRITE32(syscon_page + DEVICECFG_OFFSET, val | ADCEN_MASK);

/* clear ADCPD bit */

val = READ32(syscon_page + DEVICECFG_OFFSET);

WRITE32(adc_page + SYSCON_UNLOCK, UNLOCK_VAL); //unlock the soft lock

WRITE32(syscon_page + DEVICECFG_OFFSET, val & ~ADCPD_MASK);

}

int read_channel(unsigned long adc_page, unsigned short channel)

{

unsigned long val;

WRITE32(adc_page + ADCSWLOCK_OFFSET, UNLOCK_VAL); //unlock the soft lock

//write ADCSwitch reg to select channel

WRITE32(adc_page + ADCSWITCH_OFFSET, channel);

while(is_ADC_busy(adc_page)); //poll ADCResult

//read result from data regisyyter

val = READ32(adc_page + DATA_OFFSET) ;

val = val & DATA_MASK;

return val;

}

static char is_ADC_busy(unsigned long adc_page)

{

unsigned long val;

val = READ32(adc_page + ADCRESULT_OFFSET);

if((val & SDR_MASK) == SDR_MASK)

return TRUE;

return FALSE;

}

int main(void)

{

int devmem = open(“/dev/mem”, O_RDWR|O_SYNC);

assert(devmem != -1);

adc_page = (unsigned long)mmap(0, getpagesize(), PROT_READ|PROT_WRITE,

MAP_SHARED, devmem, ADC_PAGE);

assert(&adc_page != MAP_FAILED);

syscon_page = (unsigned long)mmap(0, getpagesize(), PROT_READ|PROT_WRITE

, MAP_SHARED, devmem, SYSCON_PAGE);

assert(&syscon_page != MAP_FAILED);

alarm(10); //this program has 10 seconds to complete

init_ADC(adc_page, syscon_page);

adc_result = read_channel(adc_page, ADC_CH0);

printf(“Channel 0: Value %d\n”, adc_result);

adc_result = read_channel(adc_page, ADC_CH0);

printf(“Channel 0: Value %d\n”, adc_result);

adc_result = read_channel(adc_page, ADC_CH0);

printf(“Channel 0: Value %d\n”, adc_result);

close(devmem);

return 0;

}

uups

Somehow the Button BUT seems not to work.

I could read in state of certain pins on the EXT connector:

/*

  • ioPort.c

  • =========

  • 0x8093_0080 DeviceCfg Device Configuration Register.

  • This register controls the operation of major system functions.

  • 0x8093_00C0 SysSWLock Software Lock Register

  • Provides software control port for all Syscon locked registers.

  • Writing the LOCK field to 0xAA opens the lock.

  • Reading the register will return 0x0000_0001 when the lock

  • is open, and all zeros when the lock is closed (locked).

  • 0x8084_0000 PADR

  • 0x8084_0004 PBDR

  • 0x8084_0008 PCDR

  • 0x8084_0010 PADDR

  • 0x8084_0014 PBDDR

  • 0x8084_0018 PCDDR

*/

#include<unistd.h>

#include<sys/types.h>

#include<sys/mman.h>

#include<stdio.h>

#include<fcntl.h>

#include<assert.h>

#include<time.h>

/*Register addresses */

#define DIGITAL_IO_PAGE 0x80840000UL

#define SYSTEM_CTRL_PAGE 0x80930000UL

/Offsets/

#define DEVICE_CONFIG 0x80 /* Device Config Register */

#define DEVIVE_SYSSWLOCK 0xC0 /* Device SysSWLock Register:

Reads 0x01 when the lock is open,

0x00 when the lock is closed */

#define LOCKOPEN 0xAA /* Writing the LOCK field to 0xAA opens the lock */

#define DIO_PORTA_DATA 0x00 /* Port A Data Register */

#define DIO_PORTA_DDR 0x10 /* Port A Data Direction Register */

#define DIO_PORTB_DATA 0x04 /* Port B Data Register */

#define DIO_PORTB_DDR 0x14 /* Port B Data Direction Register */

#define DIO_PORTC_DATA 0x08 /* Port C Data Register */

#define DIO_PORTC_DDR 0x18 /* Port C Data Direction Register */

#define DIO_PORTH_DATA 0x40 /* Port H Data Register */

#define DIO_PORTH_DDR 0x44 /* Port H Data Direction Register */

#define TRUE 0

#define FALSE !TRUE

int main(int argc, char **argv)

{

volatile unsigned char *digital_io_page, *sysctrl_page;

volatile unsigned char portADDR, portADR;

volatile unsigned char portBDDR, portBDR;

volatile unsigned char portCDDR, portCDR;

volatile unsigned char portHDDR, portHDR;

volatile unsigned long deviceCFG;

int i;

int fd = open(“/dev/mem”, O_RDWR);

assert(fd != -1);

/* this program has 200 seconds to complete or it will be killed */

alarm(200);

/* Intialize our pointers */

digital_io_page = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd ,

DIGITAL_IO_PAGE);

assert(digital_io_page != MAP_FAILED);

sysctrl_page = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd,

SYSTEM_CTRL_PAGE);

assert(sysctrl_page != MAP_FAILED);

//make sure Port C is configured as GPIO (EP9315 user gudie page 157,804)

for(i=0; i<10; i++)

{

deviceCFG=READP32( (unsigned long)(sysctrl_page + DEVICE_CONFIG) );

if( (deviceCFG & 0x08000000ul) > 0)

break;

deviceCFG |= 0x08000000ul;

outl(LOCKOPEN, sysctrl_page + DEVIVE_SYSSWLOCK);

outl(deviceCFG, sysctrl_page + DEVICE_CONFIG);

usleep(100);

}

assert(i<10);

// all ports are input

WRITEP32( (unsigned long)(digital_io_page + DIO_PORTA_DDR), 0x00);

WRITEP32( (unsigned long)(digital_io_page + DIO_PORTB_DDR), 0x00);

WRITEP32( (unsigned long)(digital_io_page + DIO_PORTC_DDR), 0x00);

WRITEP32( (unsigned long)(digital_io_page + DIO_PORTH_DDR), 0x00);

printf(“Port Values:\n”);

while(1)

{

portADR = READP8((unsigned long)(digital_io_page + DIO_PORTA_DATA));

portBDR = READP8((unsigned long)(digital_io_page + DIO_PORTB_DATA));

portCDR = READP8((unsigned long)(digital_io_page + DIO_PORTC_DATA));

portHDR = READP8((unsigned long)(digital_io_page + DIO_PORTH_DATA));

printf(“%d %d %d %d\n”,portADR,portBDR,portCDR,portHDR);

usleep(1000);

}

close(fd);

return 0;

}

Outputs:

A B C H

127 255 255 0

127 255 255 0

127 255 255 0

. . .

Connecting PIN10(EGPIO[7] PORTA:BIT7) to +3V3

255 255 255 0

Connecting PIN09(EGPIO[8] PORTB:BIT0) to GND

127 254 255 0

Hello,

Im’ newbie in CS9302, I’m looking for some code source or executable to read the ADC. Is it possble somebody send it to me ?

regards