Contiki 2.6
|
00001 #include <AT91SAM7S64.h> 00002 #include <stdint.h> 00003 #include <dev/spi.h> 00004 #include <sam7s-spi.h> 00005 00006 /* Prevents interrupts using SPI at inappropriate times */ 00007 unsigned char spi_busy = 0; 00008 00009 #define SPI_SPEED 1000000 /* 1MHz clock*/ 00010 #define SPI_DLYBCT 1 00011 #define SPI_DLYBS 20 00012 00013 #define SPI_TRANSFER (AT91C_PA12_MISO | AT91C_PA13_MOSI | AT91C_PA14_SPCK) 00014 00015 #define SPI_CS (AT91C_PA11_NPCS0 | AT91C_PA31_NPCS1) 00016 00017 void 00018 spi_init() 00019 { 00020 static uint8_t initialised = 0; 00021 if (!initialised) { 00022 *AT91C_SPI_CR = AT91C_SPI_SPIDIS | AT91C_SPI_SWRST; 00023 *AT91C_PMC_PCER = (1 << AT91C_ID_SPI); 00024 *AT91C_PIOA_ASR = SPI_TRANSFER | SPI_CS; 00025 *AT91C_PIOA_PDR = SPI_TRANSFER | SPI_CS; 00026 *AT91C_PIOA_PPUER = AT91C_PA12_MISO | SPI_CS; 00027 *AT91C_SPI_MR = (AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED 00028 | AT91C_SPI_MODFDIS | AT91C_SPI_PCS); 00029 00030 /* It seems necessary to set the clock speed for chip select 0 00031 even if it's not used. */ 00032 AT91C_SPI_CSR[0] = (MCK/SPI_SPEED)<<8; 00033 00034 *AT91C_SPI_CR = AT91C_SPI_SPIEN; 00035 initialised = 1; 00036 } 00037 } 00038 00039 void 00040 spi_init_chip_select(unsigned int chip, unsigned int speed, 00041 unsigned int dlybct, 00042 unsigned int dlybs, unsigned int phase, 00043 unsigned int polarity) 00044 { 00045 spi_init(); 00046 00047 AT91C_SPI_CSR[chip] = 00048 ((dlybct<<24) | (dlybs<<16) | (((MCK+speed/2)/speed)<<8) 00049 | (phase?AT91C_SPI_NCPHA:0) | (polarity?AT91C_SPI_CPOL:0) 00050 | AT91C_SPI_BITS_8 | AT91C_SPI_CSAAT); 00051 } 00052 00053 #if 0 00054 #define DBG_SEND dbg_blocking_putchar('>'); 00055 #define DBG_RECV dbg_blocking_putchar('<'); 00056 #else 00057 #define DBG_SEND 00058 #define DBG_RECV 00059 #endif 00060 00061 void 00062 spi_transfer(unsigned int chip, const struct spi_block *block, unsigned int blocks) 00063 { 00064 spi_busy = 1; 00065 while(!(*AT91C_SPI_SR & AT91C_SPI_TXEMPTY)); /* wait unti previous transfer is done */ 00066 00067 /* Clear any data left in the receiver */ 00068 (void)*AT91C_SPI_RDR; 00069 (void)*AT91C_SPI_RDR; 00070 00071 /* Select chip */ 00072 *AT91C_SPI_MR = ((*AT91C_SPI_MR & ~AT91C_SPI_PCS) 00073 | ((~(1<<chip) & 0x0f) << 16)); 00074 00075 while(blocks-- > 0) { 00076 struct spi_block current = *block++; 00077 if (current.send) { 00078 if (current.receive) { 00079 /* Send and receive */ 00080 while(current.len-- > 0) { 00081 while(!(*AT91C_SPI_SR & AT91C_SPI_TDRE)); 00082 *AT91C_SPI_TDR = *current.send++; 00083 DBG_SEND; 00084 while(!(*AT91C_SPI_SR & AT91C_SPI_RDRF)); 00085 *current.receive++ = *AT91C_SPI_RDR; 00086 DBG_RECV; 00087 } 00088 } else { 00089 /* Send only */ 00090 while(current.len-- > 0) { 00091 while(!(*AT91C_SPI_SR & AT91C_SPI_TDRE)); 00092 *AT91C_SPI_TDR = *current.send++; 00093 DBG_SEND; 00094 while(!(*AT91C_SPI_SR & AT91C_SPI_RDRF)); 00095 (void)*AT91C_SPI_RDR; 00096 DBG_RECV; 00097 } 00098 } 00099 } else { 00100 if (current.receive) { 00101 /* Receive only */ 00102 while(current.len-- > 0) { 00103 while(!(*AT91C_SPI_SR & AT91C_SPI_TDRE)); 00104 *AT91C_SPI_TDR = 0; 00105 DBG_SEND; 00106 while(!(*AT91C_SPI_SR & AT91C_SPI_RDRF)); 00107 *current.receive++ = *AT91C_SPI_RDR; 00108 DBG_RECV; 00109 } 00110 } else { 00111 /* Clock only */ 00112 while(current.len-- > 0) { 00113 while(!(*AT91C_SPI_SR & AT91C_SPI_TDRE)); 00114 *AT91C_SPI_TDR = 0; 00115 DBG_SEND; 00116 while(!(*AT91C_SPI_SR & AT91C_SPI_RDRF)); 00117 (void)*AT91C_SPI_RDR; 00118 DBG_RECV; 00119 } 00120 } 00121 } 00122 } 00123 *AT91C_SPI_CR = AT91C_SPI_LASTXFER; 00124 00125 spi_busy = 0; 00126 }