SPI1 - AT91SAM9G20 - external ADC

Hi,

I have an Electrum100 board from Micromint and it has an SPI ADC (ADC128S052) hooked to the SPI1 with PC4 as CS.

I managed to start the SPI port (bit/clock/master settings and so on). Unfortunately, the CS would not toggle (it’s always low). The SPI_CLK and MOSI pins look just fine on the scope.

The code that I put together is given below:

/* user-land driver for external ADC on SPI1 CS2 (PC4)
Board: Electrum100 - Micromint, AT91SAM9G20
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>

#include "definitions.h"


#define MAP_SIZE 4096UL //4k
#define MAP_MASK (MAP_SIZE - 1)

#define SPI_PCS1(npcs) ((~(1 << npcs) & 0xF) << 16)

typedef unsigned char u08;
typedef signed char s08;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned long u32;
typedef signed long s32;
typedef unsigned long long u64;
typedef signed long long s64;


int fd, i, repetitions;
void *piob_base, *pioc_base, *spi1_base, *pmc_base, *aic_base;

// found on Atmel website
u16 spi_tx_rx(u32 TxData)
{
unsigned int RxData = 0;

//MASK UNUSED BITS
TxData &= 0x0000FFFF;
TxData|=SPI_PCS1(1)| AT91C_SPI_LASTXFER;
//WAIT UNTIL TRANSMIT REGISTER IS EMPTY
while (!(*((unsigned long *) (spi1_base+(AT91C_SPI1_SR & MAP_MASK))) & AT91C_SPI_TXEMPTY));
// TRANSMIT DATA
*((unsigned long *) (spi1_base+(AT91C_SPI1_TDR & MAP_MASK))) = TxData ;
//READ THE RECEIVED DATA
//WAIT UNTIL RECEIVE REGISTER IS FULL
while (!(*((unsigned long *) (spi1_base+(AT91C_SPI1_SR & MAP_MASK))) & AT91C_SPI_RDRF));
//READ RDR AND MASK UNUSED BITS
RxData = (*((unsigned long *) (spi1_base+(AT91C_SPI1_RDR & MAP_MASK))));

return (RxData&0xffff) ;
}



void open_controller(){

...
...
...

mmap() and error checking ...

}

int main() {


int buf[10000];
i=0;


open_controller();
// PMC setting

*((unsigned long *) (pmc_base+(AT91C_PMC_PCER & MAP_MASK))) = 1<<AT91C_ID_SPI1;


*((unsigned long *) (piob_base + (PIOB_PDR & MAP_MASK))) = AT91C_PB0_SPI1_MISO | AT91C_PB1_SPI1_MOSI | AT91C_PB2_SPI1_SPCK;
*((unsigned long *) (pioc_base + (PIOC_PDR & MAP_MASK))) = AT91C_PC4_SPI1_NPCS2_0;


// peripherals definitions
*((unsigned long *) piob_base + (PIOB_ASR & MAP_MASK)) = AT91C_PB0_SPI1_MISO | AT91C_PB1_SPI1_MOSI | AT91C_PB2_SPI1_SPCK;
*((unsigned long *) pioc_base + (PIOC_BSR & MAP_MASK)) = AT91C_PC4_SPI1_NPCS2_0;



// SPI1 setup

*((unsigned long *) (spi1_base+(AT91C_SPI1_CR & MAP_MASK))) = AT91C_SPI_SPIDIS;
*((unsigned long *) (spi1_base+(AT91C_SPI1_CR & MAP_MASK))) = AT91C_SPI_SWRST ;
*((unsigned long *) (spi1_base+(AT91C_SPI1_CR & MAP_MASK))) = AT91C_SPI_SPIEN | AT91C_SPI_LASTXFER ;
*((unsigned long *) (spi1_base+(AT91C_SPI1_MR & MAP_MASK))) = AT91C_SPI_MSTR | SPI_PCS1(1)|AT91C_SPI_PS_VARIABLE ;
*((unsigned long *) (spi1_base+(AT91C_SPI1_CSR1 & MAP_MASK))) = AT91C_SPI_NCPHA| AT91C_SPI_CPOL | AT91C_SPI_BITS_16 |0x6f<<8 ;


while(i<100000){
usleep(30);
printf("%lu \n",spi_tx_rx(1<<10));

i++;
}

*((unsigned long *) (spi1_base+(AT91C_SPI1_CR & MAP_MASK))) = AT91C_SPI_SPIDIS;

close(fd);
return 0;
}

Thanks a lot.

Anybody?

All of my 9G20s run Linux :slight_smile:

You can perhaps look at the SPI driver there for ideas.

Thanks for answering my post.

No help there. That was the first thing I did.