Contiki 2.6

efs-sdcard-arch.c

00001 #include <AT91SAM7S64.h>
00002 #include <interfaces/sd.h>
00003 #include <efs-sdcard.h>
00004 #include <sys/etimer.h>
00005 #include <stdio.h>
00006 
00007 #define SPI_SPEED 10000000  /* 10MHz clock*/
00008 
00009 #define SPI_TRANSFER (AT91C_PA12_MISO | AT91C_PA13_MOSI | AT91C_PA14_SPCK)
00010 
00011 #define SPI_CS (AT91C_PA11_NPCS0)
00012 
00013 static struct process *event_process = NULL;
00014 
00015 static void
00016 init_spi()
00017 {
00018   *AT91C_SPI_CR = AT91C_SPI_SPIDIS | AT91C_SPI_SWRST;
00019   *AT91C_PMC_PCER = (1 << AT91C_ID_SPI);
00020   *AT91C_PIOA_ASR = SPI_TRANSFER | SPI_CS;
00021   *AT91C_PIOA_PDR = SPI_TRANSFER | SPI_CS;
00022   *AT91C_PIOA_PPUER = AT91C_PA12_MISO | SPI_CS;
00023   *AT91C_SPI_MR = (AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED
00024                    | AT91C_SPI_MODFDIS);
00025   
00026   /* It seems necessary to set the clock speed for chip select 0
00027      even if it's not used. */
00028 
00029   AT91C_SPI_CSR[0] =
00030     ((((MCK+SPI_SPEED/2)/SPI_SPEED)<<8) | AT91C_SPI_CPOL
00031      | AT91C_SPI_BITS_8 | AT91C_SPI_CSAAT);
00032   *AT91C_SPI_CR = AT91C_SPI_SPIEN;
00033   
00034 }
00035 
00036 void
00037 if_spiInit(hwInterface *iface)
00038 {
00039   unsigned int i;
00040   *AT91C_PIOA_SODR = AT91C_PA11_NPCS0;
00041   *AT91C_PIOA_PER = AT91C_PA11_NPCS0;
00042   for(i=0;i<20;i++) {
00043     if_spiSend(iface, 0xff);
00044   }
00045   *AT91C_PIOA_PDR = AT91C_PA11_NPCS0;
00046 }
00047 
00048 /* Borrowed from at91_spi.c  (c)2006 Martin Thomas */
00049 
00050 esint8
00051 if_initInterface(hwInterface* file, eint8* opts)
00052 {
00053   euint32 sc;
00054   
00055   if_spiInit(file);
00056   if(sd_Init(file)<0)     {
00057     DBG((TXT("Card failed to init, breaking up...\n")));
00058     return(-1);
00059   }
00060   
00061   if(sd_State(file)<0){
00062     DBG((TXT("Card didn't return the ready state, breaking up...\n")
00063          ));
00064     return(-2);
00065   }
00066   
00067 
00068   
00069   sd_getDriveSize(file, &sc);
00070   file->sectorCount = sc/512;
00071   if( (sc%512) != 0) {
00072     file->sectorCount--;
00073   }
00074   DBG((TXT("Card Capacity is %lu Bytes (%lu Sectors)\n"), sc, file->sectorCount));
00075   
00076   
00077   return(0);
00078 }
00079 
00080 /* Borrowed from lpc2000_spi.c  (c)2005 Martin Thomas */
00081 
00082 esint8
00083 if_readBuf(hwInterface* file,euint32 address,euint8* buf)
00084 {
00085         return(sd_readSector(file,address,buf,512));
00086 }
00087 
00088 esint8
00089 if_writeBuf(hwInterface* file,euint32 address,euint8* buf)
00090 {
00091         return(sd_writeSector(file,address, buf));
00092 }
00093 
00094 esint8
00095 if_setPos(hwInterface* file,euint32 address)
00096 {
00097         return(0);
00098 }
00099 
00100 
00101 euint8
00102 if_spiSend(hwInterface *iface, euint8 outgoing)
00103 {
00104   euint8 ingoing;
00105   *AT91C_SPI_TDR = outgoing;
00106   while(!(*AT91C_SPI_SR & AT91C_SPI_RDRF));
00107   ingoing = *AT91C_SPI_RDR;
00108   /* printf(">%02x <%02x\n", outgoing, ingoing); */
00109   return ingoing;
00110 }
00111 
00112 static EmbeddedFileSystem sdcard_efs;
00113 
00114 PROCESS(sdcard_process, "SD card process");
00115 
00116 PROCESS_THREAD(sdcard_process, ev , data)
00117 {
00118   static struct etimer timer;
00119   PROCESS_BEGIN();
00120   *AT91C_PIOA_PER = AT91C_PIO_PA20 | AT91C_PIO_PA1;
00121   *AT91C_PIOA_ODR = AT91C_PIO_PA20 | AT91C_PIO_PA1;
00122   
00123   
00124   /* Card not inserted */
00125   sdcard_efs.myCard.sectorCount = 0;
00126   init_spi();
00127   
00128   while(1) {
00129     if (!(*AT91C_PIOA_PDSR & AT91C_PA20_IRQ0)) {
00130       if (sdcard_efs.myCard.sectorCount == 0) {
00131         if (efs_init(&sdcard_efs,0) == 0) {
00132           if (event_process) {
00133             process_post(event_process, sdcard_inserted_event, NULL);
00134           }
00135           printf("SD card inserted\n");
00136         } else {
00137           printf("SD card insertion failed\n");
00138         }
00139       }
00140     } else {
00141       if (sdcard_efs.myCard.sectorCount != 0) {
00142         /* Card removed */
00143           fs_umount(&sdcard_efs.myFs);
00144           sdcard_efs.myCard.sectorCount = 0;
00145           if (event_process) {
00146             process_post(event_process, sdcard_removed_event, NULL);
00147           }
00148           printf("SD card removed\n");
00149       }
00150     }
00151     
00152     etimer_set(&timer, CLOCK_SECOND);
00153     PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_EXIT ||
00154                              ev == PROCESS_EVENT_TIMER);
00155     if (ev == PROCESS_EVENT_EXIT) break;
00156     if (!(*AT91C_PIOA_PDSR & AT91C_PA20_IRQ0)) {
00157       /* Wait for card to be preperly inserted */
00158       etimer_set(&timer,CLOCK_SECOND/2);
00159       PROCESS_WAIT_EVENT_UNTIL(ev== PROCESS_EVENT_TIMER);
00160     }
00161     
00162   }
00163   PROCESS_END();
00164 }
00165 
00166 FileSystem *
00167 efs_sdcard_get_fs()
00168 {
00169   efs_sdcard_init();
00170   return &sdcard_efs.myFs;
00171 }
00172 
00173 void
00174 efs_sdcard_init()
00175 {
00176   static int initialized = 0;
00177   if (!initialized) {
00178     sdcard_inserted_event = process_alloc_event();
00179     sdcard_removed_event = process_alloc_event();
00180     process_start(&sdcard_process, NULL);
00181     initialized = 1;
00182   }
00183 }
00184 
00185 int
00186 sdcard_ready()
00187 {
00188   return sdcard_efs.myCard.sectorCount > 0;
00189 }
00190 
00191 void
00192 sdcard_event_process(struct process *p)
00193 {
00194   event_process = p;
00195 }