atm128spip.nc

来自「tinyos-2.0源代码!转载而已!要的尽管拿!」· NC 代码 · 共 314 行

NC
314
字号
/// $Id: Atm128SpiP.nc,v 1.1.2.8 2006/03/08 02:01:44 klueska Exp $/* * "Copyright (c) 2005 Stanford University. All rights reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose, without fee, and without written * agreement is hereby granted, provided that the above copyright * notice, the following two paragraphs and the author appear in all * copies of this software. *  * IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN * IF STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. *  * STANFORD UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND STANFORD UNIVERSITY * HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * ENHANCEMENTS, OR MODIFICATIONS." * *  Copyright (c) 2004-2005 Crossbow Technology, Inc. *  Copyright (c) 2000-2005 The Regents of the University  of California. *  All rights reserved. * *  Permission to use, copy, modify, and distribute this software and its *  documentation for any purpose, without fee, and without written *  agreement is hereby granted, provided that the above copyright *  notice, the (updated) modification history and the author appear in *  all copies of this source code. * *  Permission is also granted to distribute this software under the *  standard BSD license as contained in the TinyOS distribution. * *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE INTEL OR ITS *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *//** * Primitives for accessing the SPI module on ATmega128 * microcontroller.  This module assumes the bus has been reserved and * checks that the bus owner is in fact the person using the bus. * SpiPacket provides an asynchronous send interface where the * transmit data length is equal to the receive data length, while * SpiByte provides an interface for sending a single byte * synchronously. SpiByte allows a component to send a few bytes * in a simple fashion: if more than a handful need to be sent, * SpiPacket should be used. * * * <pre> *  $Id: Atm128SpiP.nc,v 1.1.2.8 2006/03/08 02:01:44 klueska Exp $ * </pre> * * @author Philip Levis * @author Joe Polastre * @author Martin Turon <mturon@xbow.com> * */module Atm128SpiP {  provides {    interface Init;    interface SpiByte;    interface SpiPacket;    interface Resource[uint8_t id];  }  uses {    interface Atm128Spi as Spi;    interface Resource as ResourceArbiter[uint8_t id];    interface ArbiterInfo;    interface McuPowerState;  }}implementation {  uint8_t* txBuffer;  uint8_t* rxBuffer;  uint16_t len;  uint16_t pos;    enum {    SPI_IDLE,    SPI_BUSY,    SPI_ATOMIC_SIZE = 10,  };  command error_t Init.init() {    return SUCCESS;  }  bool started;    void startSpi() {    call Spi.enableSpi(FALSE);    atomic {      call Spi.initMaster();      call Spi.enableInterrupt(FALSE);      call Spi.setMasterDoubleSpeed(TRUE);      call Spi.setClockPolarity(FALSE);      call Spi.setClockPhase(FALSE);      call Spi.setClock(0);      call Spi.enableSpi(TRUE);    }    call McuPowerState.update();  }  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 ) {    call Spi.write( tx );    while ( !( SPSR & 0x80 ) );    *rx = call Spi.read();  }  /**   * This component sends SPI packets in chunks of size SPI_ATOMIC_SIZE   * (which is normally 5). The tradeoff is between SPI performance   * (throughput) and how much the component limits concurrency in the   * rest of the system. Handling an interrupt on each byte is   * very expensive: the context saving/register spilling constrains   * the rate at which one can write out bytes. A more efficient   * approach is to write out a byte and wait for a few cycles until   * the byte is written (a tiny spin loop). This leads to greater   * throughput, but blocks the system and prevents it from doing   * useful work.   *   * This component takes a middle ground. When asked to transmit X   * bytes in a packet, it transmits those X bytes in 10-byte parts.   * <tt>sendNextPart()</tt> is responsible for sending one such   * part. It transmits bytes with the SpiByte interface, which   * disables interrupts and spins on the SPI control register for   * completion. On the last byte, however, <tt>sendNextPart</tt>   * re-enables SPI interrupts and sends the byte through the   * underlying split-phase SPI interface. When this component handles   * the SPI transmit completion event (handles the SPI interrupt),   * it calls sendNextPart() again. As the SPI interrupt does   * not disable interrupts, this allows processing in the rest of the   * system to continue.   */     error_t sendNextPart() {    uint16_t end;    uint16_t tmpPos;    uint8_t* tx;    uint8_t* rx;        atomic {      tx = txBuffer;      rx = rxBuffer;      tmpPos = pos;      end = pos + SPI_ATOMIC_SIZE;      end = (end > len)? len:end;    }    for (;tmpPos < (end - 1) ; tmpPos++) {      uint8_t val;      if (tx != NULL) 	call SpiByte.write( tx[tmpPos], &val );      else	call SpiByte.write( 0, &val );          if (rx != NULL) {	rx[tmpPos] = val;      }    }    // For the last byte, we re-enable interrupts.   call Spi.enableInterrupt(TRUE);   atomic {     if (tx != NULL)       call Spi.write(tx[tmpPos]);     else       call Spi.write(0);          pos = tmpPos;      // The final increment will be in the interrupt      // handler.    }    return 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   * read out of the SPI, but they will be discarded. A byte is read   * from the SPI before writing and discarded (to clear any buffered   * bytes that might have been left around).   *   * This command only sets up the state variables and clears the SPI:   * <tt>sendNextPart()</tt> does the real work.   *   */      async command error_t SpiPacket.send(uint8_t* writeBuf, 				       uint8_t* readBuf, 				       uint16_t  bufLen) {    uint8_t discard;    atomic {      txBuffer = writeBuf;      rxBuffer = readBuf;      len = bufLen;      pos = 0;    }        discard = call Spi.read();        return sendNextPart();  } default async event void SpiPacket.sendDone      (uint8_t* _txbuffer, uint8_t* _rxbuffer,        uint16_t _length, error_t _success) { } async event void Spi.dataReady(uint8_t data) {   bool again;      atomic {     if (rxBuffer != NULL) {       rxBuffer[pos] = data;       // Increment position     }     pos++;   }   call Spi.enableInterrupt(FALSE);      atomic {     again = (pos < len);   }      if (again) {     sendNextPart();   }   else {     uint8_t* rx;     uint8_t* tx;     uint16_t  myLen;     uint8_t discard;          atomic {       rx = rxBuffer;       tx = txBuffer;       myLen = len;       rxBuffer = NULL;       txBuffer = NULL;       len = 0;       pos = 0;     }     discard = call Spi.read();     signal SpiPacket.sendDone(tx, rx, myLen, SUCCESS);   } } async command error_t Resource.immediateRequest[ uint8_t id ]() {   error_t result = call ResourceArbiter.immediateRequest[ id ]();   if ( result == SUCCESS ) {     startSpi();   }   return result; }  async command error_t Resource.request[ uint8_t id ]() {   atomic {     if (!call ArbiterInfo.inUse()) {       startSpi();     }   }   return call ResourceArbiter.request[ id ](); } async command void Resource.release[ uint8_t id ]() {   call ResourceArbiter.release[ id ]();   atomic {     if (!call ArbiterInfo.inUse()) {       stopSpi();     }   } } async command uint8_t Resource.isOwner[uint8_t id]() {   return call ResourceArbiter.isOwner[id](); }  event void ResourceArbiter.granted[ uint8_t id ]() {   signal Resource.granted[ id ](); }  default event void Resource.granted[ uint8_t id ]() {} }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?