]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
restored use of tosh_uwait (added back msp430hardware.h) ; it's much
authorayer1 <ayer1>
Fri, 4 Sep 2009 18:15:31 +0000 (18:15 +0000)
committerayer1 <ayer1>
Fri, 4 Sep 2009 18:15:31 +0000 (18:15 +0000)
more accurate that busywaitmicro.

added in real tos-2 spi transaction code

added in updates from tos-1 for handling docking availability, and
power-cycling card when switching between sd to spi modes.

got rid of auto-init from boot, adding stdcontrol back in.  left out
.init usage, because tos-1 version had no real functionality in
stdcontrol.start, so old stdcontrol.init routine is carried to .start.

tos/platforms/shimmer/chips/sd/SDP.nc

index e0eeb9c72b95a7028ed50bdef826e96714007bad..ac9746a5acd37c112d5c4e63015f8b79b909c688 100644 (file)
@@ -3,7 +3,7 @@
 * REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, 
 * INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR 
-* COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE.           
+* COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE. 
 * TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET 
 * POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY 
 * INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR 
  *
  * functional pieces based upon or copied from Texas Instruments sample code
  *
- */
- /**                                   
- * @author Steve Ayer
- * @author Konrad Lorincz
- * @date March 25, 2008 - ported to TOS 2.x
+ * @author  Steve Ayer
+ * @date    May 2006
+ * @date    July 2009  (extensive rework, tep conformance)
+ * @author  Konrad Lorincz  (initial port to tos-2)
+ * @date    March 25, 2008
  */
 
 #include "SD.h"
+#include "msp430usart.h"
 
-module SDP 
-{
-    provides interface SD;
-
-    uses interface Boot;
-    uses interface HplMsp430Usart;
-    uses interface HplMsp430UsartInterrupts;
+module SDP {
+  provides {
+    interface StdControl;
+    interface SD;
+  }
+  uses {
+    interface HplMsp430Usart as Usart;
+    interface HplMsp430Interrupt as DockInterrupt;
+    interface Leds;
+  }
 }
-implementation 
-{                                                                      
 
-#define SPI_TX_DONE        while(call HplMsp430Usart.isTxEmpty() == FALSE);
+implementation {
+  error_t cardInit();
+  
+#define SPI_TX_DONE        while(call Usart.isTxEmpty() == FALSE);
 
 #define CS_LOW()    TOSH_CLR_SD_CS_N_PIN();              // Card Select
 #define CS_HIGH()   SPI_TX_DONE; TOSH_SET_SD_CS_N_PIN();
 
-    async event void HplMsp430UsartInterrupts.txDone()             {/*do nothing*/}
-    async event void HplMsp430UsartInterrupts.rxDone(uint8_t data) {/*do nothing*/}
+  /* 
+   * this routine is supposed to prevent windows from locking up when 
+   * the device is docked.
+   */
+  void powerCycle() {
+    // wait until the tx buf is clear before killing the card
+    CS_HIGH();
 
+    // this connects the path from mcu to card
+    TOSH_MAKE_DOCK_N_OUTPUT();
+    TOSH_SET_DOCK_N_PIN();
 
-  // This is from TOS 1.x!
-  void setModeSPI()
-  {
-      // call USARTControl.disableUART();
-      atomic ME1 &= ~(UTXE0 | URXE0);   // USART0 UART module enable
-      TOSH_SEL_UTXD0_IOFUNC();
-      TOSH_SEL_URXD0_IOFUNC();
+    TOSH_SET_SW_SD_PWR_N_PIN();    
+    TOSH_CLR_SD_CS_N_PIN();             
 
-      //call USARTControl.disableI2C();
-      //#ifdef __msp430_have_usart0_with_i2c
-      //if (call USARTControl.isI2C())
-        atomic U0CTL &= ~(I2C | I2CEN | SYNC);
-      //#endif
+    /* 
+     * here we have to clear all input pins to the card, as
+     * the card in spi mode will leech power from any pin
+     */
+    call Usart.disableSpi();
+    TOSH_CLR_SD_DI_PIN();
+    TOSH_CLR_SD_DO_PIN();
+    TOSH_CLR_SD_CLK_PIN();
 
+    TOSH_uwait(20000);  
 
-    atomic {
-      TOSH_SEL_SIMO0_MODFUNC();
-      TOSH_SEL_SOMI0_MODFUNC();
-      TOSH_SEL_UCLK0_MODFUNC();
+    TOSH_SET_SD_CS_N_PIN();             
+    TOSH_CLR_SW_SD_PWR_N_PIN();    
 
-      IE1 &= ~(UTXIE0 | URXIE0);  // interrupt disable    
+    // undo the override above
+    TOSH_MAKE_DOCK_N_INPUT();
+  }
+    
+  command error_t StdControl.start(){
+    TOSH_CLR_SW_SD_PWR_N_PIN();    // powers up module on models so equipped
+
+    /* 
+     * this pin, when low, tells us that the sd card is unavailable to the processor
+     * it should be attached to a pullup unless platform has a docking pin doing an sd override;
+     * generally, we need to avoid talking to the sd with the mcu when the pin is low;
+     * if it's low now, we'll fire an interrupt when the sd is available to software.
+     */
+    if(!TOSH_READ_DOCK_N_PIN()){
+      call DockInterrupt.edge(TRUE);    // watch for it to go high, off the dock
+      powerCycle();
+      signal SD.unavailable();
+    }
+    else{
+      call DockInterrupt.edge(FALSE);    // tell us when we're docked
 
-      U0CTL = SWRST;
-      U0CTL |= CHAR | SYNC | MM;  // 8-bit char, SPI-mode, USART as master
-      U0CTL &= ~(0x20); 
+      cardInit();
 
-      U0TCTL = STC ;     // 3-pin
-      U0TCTL |= CKPH;    // half-cycle delayed UCLK
+      signal SD.available();
+    }
 
-      // call USARTControl.setClockSource(SSEL_SMCLK)
-      U0TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3);
-      U0TCTL |= (SSEL_SMCLK & 0x7F); 
+    call DockInterrupt.enable();
+    call DockInterrupt.clear();
+    
+    return SUCCESS;
+  }
 
-      // call USARTControl.setClockRate(UBR_SMCLK_115200, UMCTL_SMCLK_115200);
-      // UBR_SMCLK_115200=0x0009, UMCTL_SMCLK_115200=0x10,
-      U0BR0 = 0x0009 & 0x0FF;
-      U0BR1 = ((0x0009) >> 8) & 0x0FF;
-      U0MCTL = 0x10;
+  command error_t StdControl.stop(){
+    TOSH_SET_SW_SD_PWR_N_PIN();    // powers down module
+    TOSH_CLR_SD_CS_N_PIN();
 
-      ME1 &= ~(UTXE0 | URXE0); //USART UART module disable
-      ME1 |= USPIE0;   // USART SPI module enable
-      U0CTL &= ~SWRST;  
+    call DockInterrupt.disable();
+    call DockInterrupt.clear();
 
-      IFG1 &= ~(UTXIFG0 | URXIFG0);
-      IE1 &= ~(UTXIE0 | URXIE0);  // interrupt disabled    
+    return SUCCESS;
+  }
+
+  async event void DockInterrupt.fired() {
+    if (call DockInterrupt.getValue() == TRUE){      // off the dock
+      cardInit();
+
+      call DockInterrupt.edge(FALSE);
+      signal SD.available();                         // tell the app that it can talk to the sd card
+    }
+    else{
+      call DockInterrupt.edge(TRUE);      
+      signal SD.unavailable();                         // tell the app to stop talking to the card
+      powerCycle();
     }
+    call DockInterrupt.clear();
   }
 
-  // setup usart1 in spi mode
   void initSPI() {
+    msp430_spi_union_config_t * config;
+
     TOSH_MAKE_SD_CS_N_OUTPUT();
     TOSH_SEL_SD_CS_N_IOFUNC();
 
-    // call USARTControl.setClockSource(SSEL_SMCLK);
-    // call USARTControl.setClockRate(UBR_SMCLK_115200, UMCTL_SMCLK_115200);
-    // call USARTControl.setModeSPI();
-    setModeSPI();  // the above 3 commands are implemented in this call
+    config = &msp430_spi_default_config;
+    
+    call Usart.setModeSpi(config);
+
+    /*
+     * set the clock to 115200 for sd init, default is smclk / 2
+     * cardInit raises speed back to 512k at end of init routine
+     */
+    call Usart.setUbr(UBR_1MHZ_115200);
+    call Usart.setUmctl(UMCTL_1MHZ_115200);
+
+    call Usart.enableRxIntr();
 
     TOSH_SET_SD_CS_N_PIN();
 
-    while(call HplMsp430Usart.isTxEmpty() == FALSE);
+    while(call Usart.isTxEmpty() == FALSE);
   }
 
   uint8_t spiSendByte (const uint8_t data){
     atomic{
-      while(call HplMsp430Usart.isTxEmpty() == FALSE);   
-
-      call HplMsp430Usart.tx(data);
-
-      while(call HplMsp430Usart.isRxIntrPending() == FALSE);    // rx buffer has a character
+      while(call Usart.isTxEmpty() == FALSE);   
+      
+      call Usart.tx(data);
+      
+      while(call Usart.isRxIntrPending() == FALSE);    // rx buffer has a character
     }
     
-    return call HplMsp430Usart.rx();
+    return call Usart.rx();
   }
-    
+  
   void sendCmd(const uint8_t cmd, uint32_t data, const uint8_t crc){
     uint8_t frame[6];
     register int8_t i;
@@ -238,7 +286,7 @@ implementation
     for(i = 0; i < 65; i++){
       response = spiSendByte(0xff);
       response &= 0x1f;
-
+      
       switch(response){
       case 0x05: 
        rvalue = MMC_SUCCESS;
@@ -266,7 +314,7 @@ implementation
     return response;
   }
 
-  mmcerror_t SD_setIdle() {
+  error_t setIdle(){
     char response;
     CS_LOW();
 
@@ -290,8 +338,9 @@ implementation
     return MMC_SUCCESS;
   }
 
-  mmcerror_t SD_init() {
+  error_t cardInit(){
     register uint8_t i;
+    uint8_t r;
 
     initSPI();
 
@@ -300,25 +349,25 @@ implementation
     for(i = 0; i < 10; i++)
       spiSendByte(0xff);
     
-    return SD_setIdle();
-  }
+    r = setIdle();
 
-    event void Boot.booted()
-    {
-        SD_init();
-    }
+    // here's where we set the clock speed up to smclk / 2 (512k)
+    
+    call Usart.setUbr(0x0002);
+    call Usart.setUmctl(0x00);
 
+    return r;
+  }
 
-  // we don't have pin for this one yet; it uses cd pin, which we don't have wired in mock-up
   // change block length to 2^len bytes; default is 512
-  mmcerror_t SD_setBlockLength (const uint16_t len) {
+  error_t setBlockLength (const uint16_t len) {
     CS_LOW ();
 
     sendCmd(MMC_SET_BLOCKLEN, len, 0xff);
 
     // get response from card, should be 0; so, shouldn't this be 'while'?
     if(getResponse() != 0x00){
-      SD_init();
+      cardInit();
       sendCmd(MMC_SET_BLOCKLEN, len, 0xff);
       getResponse();
     }
@@ -331,16 +380,19 @@ implementation
     return MMC_SUCCESS;
   }
     
-
-  // see macro in module for writing to a sector instead of an address
-  mmcerror_t SD_readBlock(const uint32_t address, const uint16_t count, uint8_t * buffer){
+  /* 
+   * renamed to clear the way for renaming what was readSector -- which called this -- 
+   * to be renamed readBlock.  --sma
+   */
+  
+  error_t read_block(const uint32_t address, const uint16_t count, uint8_t * buffer){
     register uint16_t i = 0;
     uint8_t rvalue = MMC_RESPONSE_ERROR;
-
+    
     // Set the block length to read
-    if(SD_setBlockLength(count) == MMC_SUCCESS){   // block length can be set
+    if(setBlockLength(count) == MMC_SUCCESS){   // block length can be set
       CS_LOW ();
-
+      
       sendCmd(MMC_READ_SINGLE_BLOCK, address, 0xff);
       // Send 8 Clock pulses of delay, check if the MMC acknowledged the read block command
       // it will do this by sending an affirmative response
@@ -348,11 +400,11 @@ implementation
       if(getResponse() == 0x00){
        // now look for the data token to signify the start of the data
        if(getXXResponse(MMC_START_DATA_BLOCK_TOKEN) == MMC_START_DATA_BLOCK_TOKEN){
-
+         
          // clock the actual data transfer and receive the bytes; spi_read automatically finds the Data Block
          for (i = 0; i < count; i++)
            buffer[i] = spiSendByte(0xff);   // is executed with card inserted
-
+         
          // get CRC bytes (not really needed by us, but required by MMC)
          spiSendByte(0xff);
          spiSendByte(0xff);
@@ -371,20 +423,30 @@ implementation
     else{
       rvalue = MMC_BLOCK_SET_ERROR;           // 1
     }
-
+    
     CS_HIGH ();
     spiSendByte(0xff);
-
+    
     return rvalue;
   }
 
-  mmcerror_t SD_writeBlock(const uint32_t address, const uint16_t count, uint8_t * buffer){
+  /*
+   * need to test dock pin for some platforms
+   * on others this will be attached to a pullup
+   */
+  command error_t SD.readBlock(const uint32_t sector, uint8_t * buffer) {
+    if(!TOSH_READ_DOCK_N_PIN())
+      return MMC_INIT_ERROR;
+
+    return read_block(sector * 512, 512, buffer);
+  }
+
+  error_t write_block(const uint32_t address, const uint16_t count, uint8_t * buffer){
     register uint16_t i;
     uint8_t rvalue = MMC_RESPONSE_ERROR;         // MMC_SUCCESS;
 
     // Set the block length to write
-    if(SD_setBlockLength (count) == MMC_SUCCESS){   // block length could be set
-      //      call Leds.yellowOn();
+    if(setBlockLength (count) == MMC_SUCCESS){   // block length could be set
       CS_LOW ();
       sendCmd(MMC_WRITE_BLOCK, address, 0xff);
 
@@ -420,63 +482,48 @@ implementation
     CS_HIGH ();
     // Send 8 Clock pulses of delay.
     spiSendByte(0xff);
-    //    call Leds.greenOn();
-    return rvalue;
-  }
 
-  command error_t SD.readBlock(const uint32_t sector, void *bufferPtr)
-  {
-    mmcerror_t mmcerror = SD_readBlock(sector * 512, 512, bufferPtr);
-    if (mmcerror == MMC_SUCCESS)
-      return SUCCESS;
-    else
-      return FAIL;
+    return rvalue;
   }
 
+  command error_t SD.writeBlock(const uint32_t sector, uint8_t * buffer){
+    /*
+     * need to test dock pin for some platforms
+     * on others this will be attached to a pullup
+     */
+    if(!TOSH_READ_DOCK_N_PIN())
+      return MMC_INIT_ERROR;
 
-  command error_t SD.writeBlock(const uint32_t sector, void *bufferPtr)
-  {
-    mmcerror_t mmcerror = SD_writeBlock(sector * 512, 512, bufferPtr);
-    if (mmcerror == MMC_SUCCESS)
-      return SUCCESS;
-    else
-      return FAIL;
+    return write_block(sector * 512, 512, buffer);
   }
 
-
-  // register read of length len into buffer
-  mmcerror_t SD_readRegister(const uint8_t reg, const uint8_t len, uint8_t * buffer){
-    uint8_t uc, rvalue = MMC_TIMEOUT_ERROR;
-
-    if((SD_setBlockLength (len)) == MMC_SUCCESS){
-      CS_LOW ();
-      // CRC not used: 0xff as last byte
-      sendCmd(reg, 0x000000, 0xff);
-
-      // wait for response
-      // in the R1 format (0x00 is no errors)
-      if(getResponse() == 0x00){
-       if(getXXResponse(0xfe) == 0xfe)
-         for(uc = 0; uc < len; uc++)
-           buffer[uc] = spiSendByte(0xff);  
-
-       // get CRC bytes (not really needed by us, but required by MMC)
-       spiSendByte(0xff);
-       spiSendByte(0xff);
-       rvalue = MMC_SUCCESS;
+  /*
+   * feel our way out over the cliff of the card to estimate the size
+   * turns out cmd9 is not supported on sdio, as there's no csd register
+   */
+  uint32_t hackGetCardSize() {
+    uint32_t howbig = 0;
+    uint8_t b[512];
+    error_t failed;
+    
+    /* we'll estimate based upon popular sizes of cards, e.g. 128mb, 256 mb, 512mb, 1gb, 2gb
+     * experimentally, we find that 512mb == ~990900 sectors, 1gb == ~1983000 sectors
+     * extrapolating down, we'll say that 247700 should be readable on a 128mb
+     * reading beyond that returns an error
+     */
+
+    failed = call SD.readBlock(0, b);
+    failed = call SD.readBlock(200000, b);
+    // if we can't get this far, we're toast anyway
+    if(!failed){
+      howbig = 247000;
+      while(!call SD.readBlock(howbig, b)){
+       howbig = howbig * 2;
       }
-      else
-       rvalue = MMC_RESPONSE_ERROR;
-
-      CS_HIGH ();
-
-      // Send 8 Clock pulses of delay.
-      spiSendByte(0xff);
+      howbig = howbig / 2;
     }
-    CS_HIGH ();
-
-    return rvalue;
-  } 
+    return howbig;
+  }
 
   // Read the Card Size from the CSD Register
   // this command is unsupported on sdio-only, like sandisk micro sd cards
@@ -487,6 +534,8 @@ implementation
     uint16_t i, j, b, response, mmc_C_SIZE;
     uint8_t mmc_READ_BL_LEN, mmc_C_SIZE_MULT;
 
+    //    return hackGetCardSize();
+    
     CS_LOW ();
 
     spiSendByte(MMC_READ_CSD);   // CMD 9
@@ -562,4 +611,3 @@ implementation
   }
 
 }
-