]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/atm128/spi/Atm128SpiP.nc
Merge TinyOS 2.1.1 into master.
[tinyos-2.x.git] / tos / chips / atm128 / spi / Atm128SpiP.nc
index 43b95f145ea74a9728bc2298e7bba1538c1f89cd..1838f7b0d00a48c6a76858b0341c825ebeca97d7 100644 (file)
  *
  */
 
-module Atm128SpiP {
+module Atm128SpiP @safe() {
   provides {
     interface Init;
     interface SpiByte;
+    interface FastSpiByte;
     interface SpiPacket;
     interface Resource[uint8_t id];
   }
@@ -87,9 +88,9 @@ module Atm128SpiP {
   }
 }
 implementation {
-  uint8_t* txBuffer;
-  uint8_t* rxBuffer;
   uint16_t len;
+  uint8_t* COUNT_NOK(len) txBuffer;
+  uint8_t* COUNT_NOK(len) rxBuffer;
   uint16_t pos;
   
   enum {
@@ -101,7 +102,6 @@ implementation {
   command error_t Init.init() {
     return SUCCESS;
   }
-  bool started;
   
   void startSpi() {
     call Spi.enableSpi(FALSE);
@@ -119,19 +119,53 @@ implementation {
 
   void stopSpi() {
     call Spi.enableSpi(FALSE);
-    started = FALSE;
     atomic {
       call Spi.sleep();
     }
     call McuPowerState.update();
   }
-  
-  async command void SpiByte.write( uint8_t tx, uint8_t* rx ) {
+
+  async command uint8_t SpiByte.write( uint8_t tx ) {
+    /* There is no need to enable the SPI bus and update the power state
+       here since that must have been done when the resource was granted. 
+       However there seems to be a bug somewhere in the radio driver for 
+       the MicaZ platform so we cannot remove the following two lines 
+       before that problem is resolved. (Miklos Maroti) */
+    call Spi.enableSpi(TRUE);
+    call McuPowerState.update();
+
     call Spi.write( tx );
     while ( !( SPSR & 0x80 ) );
-    *rx = call Spi.read();
+    return call Spi.read();
+  }
+
+  inline async command void FastSpiByte.splitWrite(uint8_t data) {
+    call Spi.write(data);
+  }
+
+  inline async command uint8_t FastSpiByte.splitRead() {
+    while( !( SPSR & 0x80 ) )
+      ;
+    return call Spi.read();
+  }
+
+  inline async command uint8_t FastSpiByte.splitReadWrite(uint8_t data) {
+    uint8_t b;
+
+    while( !( SPSR & 0x80 ) )
+       ;
+    b = call Spi.read();
+    call Spi.write(data);
+
+    return b;
   }
 
+  inline async command uint8_t FastSpiByte.write(uint8_t data) {
+    call Spi.write(data);
+    while( !( SPSR & 0x80 ) )
+      ;
+    return call Spi.read();
+  }
 
   /**
    * This component sends SPI packets in chunks of size SPI_ATOMIC_SIZE
@@ -162,10 +196,12 @@ implementation {
   error_t sendNextPart() {
     uint16_t end;
     uint16_t tmpPos;
-    uint8_t* tx;
-    uint8_t* rx;
+    uint16_t myLen;
+    uint8_t* COUNT_NOK(myLen) tx;
+    uint8_t* COUNT_NOK(myLen) rx;
     
     atomic {
+      myLen = len;
       tx = txBuffer;
       rx = rxBuffer;
       tmpPos = pos;
@@ -176,9 +212,9 @@ implementation {
     for (;tmpPos < (end - 1) ; tmpPos++) {
       uint8_t val;
       if (tx != NULL) 
-       call SpiByte.write( tx[tmpPos], &val );
+       val = call SpiByte.write( tx[tmpPos] );
       else
-       call SpiByte.write( 0, &val );
+       val = call SpiByte.write( 0 );
     
       if (rx != NULL) {
        rx[tmpPos] = val;
@@ -201,6 +237,24 @@ implementation {
     return SUCCESS;
   }
 
+
+  task void zeroTask() {
+     uint16_t  myLen;
+     uint8_t* COUNT_NOK(myLen) rx;
+     uint8_t* COUNT_NOK(myLen) tx;
+
+     atomic {
+       myLen = len;
+       rx = rxBuffer;
+       tx = txBuffer;
+       rxBuffer = NULL;
+       txBuffer = NULL;
+       len = 0;
+       pos = 0;
+       signal SpiPacket.sendDone(tx, rx, myLen, SUCCESS);
+     }
+  }
+
   /**
    * Send bufLen bytes in <tt>writeBuf</tt> and receive bufLen bytes
    * into <tt>readBuf</tt>. If <tt>readBuf</tt> is NULL, bytes will be
@@ -210,24 +264,32 @@ implementation {
    *
    * This command only sets up the state variables and clears the SPI:
    * <tt>sendNextPart()</tt> does the real work.
-   *
+   * 
+   * If there's a send of zero bytes, short-circuit and just post
+   * a task to signal the sendDone. This generally occurs due to an
+   * error in the caler, but signaling an event will hopefully let
+   * it recover better than returning FAIL.
    */
-  
+
   
   async command error_t SpiPacket.send(uint8_t* writeBuf, 
                                       uint8_t* readBuf, 
                                       uint16_t  bufLen) {
     uint8_t discard;
     atomic {
+      len = bufLen;
       txBuffer = writeBuf;
       rxBuffer = readBuf;
-      len = bufLen;
       pos = 0;
     }
-    
-    discard = call Spi.read();
-    
-    return sendNextPart();
+    if (bufLen > 0) {
+      discard = call Spi.read();
+      return sendNextPart();
+    }
+    else {
+      post zeroTask();
+      return SUCCESS;
+    }
   }
 
  default async event void SpiPacket.sendDone
@@ -254,15 +316,15 @@ implementation {
      sendNextPart();
    }
    else {
-     uint8_t* rx;
-     uint8_t* tx;
-     uint16_t  myLen;
      uint8_t discard;
+     uint16_t  myLen;
+     uint8_t* COUNT_NOK(myLen) rx;
+     uint8_t* COUNT_NOK(myLen) tx;
      
      atomic {
+       myLen = len;
        rx = rxBuffer;
        tx = txBuffer;
-       myLen = len;
        rxBuffer = NULL;
        txBuffer = NULL;
        len = 0;
@@ -291,13 +353,14 @@ implementation {
    return call ResourceArbiter.request[ id ]();
  }
 
- async command void Resource.release[ uint8_t id ]() {
-   call ResourceArbiter.release[ id ]();
+ async command error_t Resource.release[ uint8_t id ]() {
+   error_t error = call ResourceArbiter.release[ id ]();
    atomic {
      if (!call ArbiterInfo.inUse()) {
        stopSpi();
      }
    }
+   return error;
  }
 
  async command uint8_t Resource.isOwner[uint8_t id]() {