halpxa27xi2cmasterp.nc

来自「tinyos-2.x.rar」· NC 代码 · 共 317 行

NC
317
字号
/* $Id: HalPXA27xI2CMasterP.nc,v 1.5 2008/06/11 00:42:13 razvanm Exp $ */
/*
 * Copyright (c) 2005 Arch Rock Corporation 
 * All rights reserved. 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *	Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *	Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *  
 *   Neither the name of the Arch Rock Corporation nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * 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 ARCHED
 * ROCK 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.
 */
/**
 * This Hal module implements the TinyOS 2.0 I2CPacket interface over
 * the PXA27x I2C Hpl
 *
 * @author Phil Buonadonna
 */

#include <I2C.h>

generic module HalPXA27xI2CMasterP(bool fast_mode)
{
  provides interface Init;
  provides interface I2CPacket<TI2CBasicAddr>;

  uses interface HplPXA27xI2C as I2C;

  uses interface HplPXA27xGPIOPin as I2CSCL;
  uses interface HplPXA27xGPIOPin as I2CSDA;

}

implementation
{
  // These states don't necessarily reflect the state of the I2C bus, rather the state of this
  // module WRT an operation.  I.E. the module might be in STATE_IDLE, but the I2C bus still
  // held by the master for a continued read.
  enum {
    I2C_STATE_IDLE,
    I2C_STATE_READSTART,
    I2C_STATE_READ,
    I2C_STATE_READEND,
    I2C_STATE_WRITE,
    I2C_STATE_WRITEEND,
    I2C_STATE_ERROR
  };

  uint8_t mI2CState;
  uint16_t mCurTargetAddr;
  uint8_t *mCurBuf, mCurBufLen, mCurBufIndex;
  i2c_flags_t mCurFlags;
  uint32_t mBaseICRFlags;

  static void readNextByte() {
    if (mCurBufIndex >= (mCurBufLen - 1)) {
      atomic { mI2CState = I2C_STATE_READEND; }
      if (mCurFlags & I2C_STOP) {
	call I2C.setICR((mBaseICRFlags) | (ICR_ALDIE | ICR_DRFIE | ICR_ACKNAK | ICR_TB | ICR_STOP));
      }
      else if (mCurFlags & I2C_ACK_END) {
	call I2C.setICR((mBaseICRFlags) | (ICR_ALDIE | ICR_DRFIE | ICR_TB));
      }
      else {
	call I2C.setICR((mBaseICRFlags) | (ICR_ALDIE | ICR_DRFIE | ICR_ACKNAK | ICR_TB));
      }
    }
    else {
      atomic { mI2CState = I2C_STATE_READ; }
      call I2C.setICR((mBaseICRFlags) | (ICR_ALDIE | ICR_DRFIE | ICR_TB));
    }
    return;
  }

  static void writeNextByte() {
    if (mCurBufIndex >= mCurBufLen) {
      atomic { mI2CState = I2C_STATE_WRITEEND; }
      
      if (mCurFlags & I2C_STOP) {
	call I2C.setICR((mBaseICRFlags) | (ICR_ALDIE | ICR_TB | ICR_ITEIE | ICR_STOP));
      }
      
      else {
	call I2C.setICR((mBaseICRFlags) | (ICR_ALDIE | ICR_ITEIE | ICR_TB));
      }
      
    }
    else {
      call I2C.setICR((mBaseICRFlags) | (ICR_ALDIE | ICR_ITEIE |ICR_TB));
    }
    return;
  }
  
  static error_t startI2CTransact(uint8_t nextState, uint16_t addr, uint8_t length, uint8_t *data, 
			   i2c_flags_t flags, bool bRnW) {
    error_t error = SUCCESS;
    uint8_t tmpAddr;

    if ((data == NULL) || (length == 0)) {
      return EINVAL;
    }

    atomic {
      if (mI2CState == I2C_STATE_IDLE) {
	mI2CState = nextState;
	mCurTargetAddr = addr;
	mCurBuf = data;
	mCurBufLen = length;
	mCurBufIndex = 0;
	mCurFlags = flags;
      }
      else {
	error = EBUSY;
      }
    }
    if (error) {
      return error;
    }

    if (flags & I2C_START) {

      tmpAddr = (bRnW) ? 0x1 : 0x0;
      tmpAddr |= ((addr << 1) & 0xFE);
      call I2C.setIDBR(tmpAddr);
      call I2C.setICR( mBaseICRFlags | ICR_ITEIE | ICR_TB | ICR_START);
    }
    else if (bRnW) {
      atomic {
	readNextByte();
      }
    }
    else {
      atomic {
	writeNextByte();
      }
    }
    return error;
  }


  task void handleReadError() {
    call I2C.setISAR(0x7F0);
    call I2C.setICR(mBaseICRFlags | ICR_MA);
    call I2C.setICR(ICR_UR);
    call I2C.setICR(mBaseICRFlags);
    atomic {
      mI2CState = I2C_STATE_IDLE;
      signal I2CPacket.readDone(FAIL,mCurTargetAddr,mCurBufLen,mCurBuf);
    }
    return;
  }
    
  task void handleWriteError() {
    call I2C.setISAR(0x7F0);
    call I2C.setICR(mBaseICRFlags | ICR_MA);
    call I2C.setICR(ICR_UR);
    call I2C.setICR(mBaseICRFlags);
    atomic {
      mI2CState = I2C_STATE_IDLE;
      signal I2CPacket.writeDone(FAIL,mCurTargetAddr,mCurBufLen,mCurBuf);
    }
    return;
  }

  command error_t Init.init() {
    atomic {
      mBaseICRFlags = (fast_mode) ? (ICR_FM | ICR_BEIE | ICR_IUE | ICR_SCLE) : (ICR_BEIE | ICR_IUE | ICR_SCLE);

      call I2CSCL.setGAFRpin(I2C_SCL_ALTFN);
      call I2CSCL.setGPDRbit(TRUE);
      call I2CSDA.setGAFRpin(I2C_SDA_ALTFN);
      call I2CSDA.setGPDRbit(TRUE);

      mI2CState = I2C_STATE_IDLE;
      call I2C.setISAR(0);
      call I2C.setICR(mBaseICRFlags | ICR_ITEIE | ICR_DRFIE);
    }    
    return SUCCESS;
  }

  async command error_t I2CPacket.read(i2c_flags_t flags, uint16_t addr, uint8_t length, uint8_t* data) {
    error_t error = SUCCESS;

    if ((flags & I2C_ACK_END) && (flags & I2C_STOP)) {
      error = EINVAL;
      return error;
    }

    if (flags & I2C_START) {
      error = startI2CTransact(I2C_STATE_READSTART,addr,length,data,flags,TRUE);
    }
    else {
      error = startI2CTransact(I2C_STATE_READ,addr,length,data,flags,TRUE);
    }
    
    return error;
  }

  async command error_t I2CPacket.write(i2c_flags_t flags, uint16_t addr, uint8_t length, uint8_t* data) {
    error_t error = SUCCESS;

    error = startI2CTransact(I2C_STATE_WRITE,addr,length,data,flags,FALSE);

    return error;
  }

  async event void I2C.interruptI2C() {
    uint32_t valISR;

    // PXA27x Devel Guide is wrong.  You have to write to the ISR to clear the bits.
    valISR = call I2C.getISR();
    call I2C.setISR(ISR_ITE | ISR_IRF);

    // turn off DRFIE and ITEIE
    //call I2C.setICR((call I2C.getICR()) & ~(ICR_DRFIE | ICR_ITEIE));
    //call I2C.setICR(mBaseICRFlags);

    switch (mI2CState) {
    case I2C_STATE_IDLE:
      // Should never get here. Reset all pending interrupts.
      break;

    case I2C_STATE_READSTART:
      if (valISR & (ISR_BED | ISR_ALD)) {
	mI2CState = I2C_STATE_ERROR;
	post handleReadError();
	break;
      }
      readNextByte();
      break;

    case I2C_STATE_READ:
      if (valISR & (ISR_BED | ISR_ALD)) {
	mI2CState = I2C_STATE_ERROR;
	post handleReadError();
	break;
      }
      mCurBuf[mCurBufIndex] = call I2C.getIDBR();
      mCurBufIndex++;
      readNextByte();
      break;

    case I2C_STATE_READEND:
      if (valISR & (ISR_BED | ISR_ALD)) {
	mI2CState = I2C_STATE_ERROR;
	post handleReadError();
	break;
      }
      mCurBuf[mCurBufIndex] = call I2C.getIDBR();
      mI2CState = I2C_STATE_IDLE;
      signal I2CPacket.readDone(SUCCESS,mCurTargetAddr,mCurBufLen,mCurBuf);
      break;

    case I2C_STATE_WRITE:
      if (valISR & (ISR_BED | ISR_ALD)) {
	mI2CState = I2C_STATE_ERROR;
	post handleWriteError();
	break;
      }
      call I2C.setIDBR(mCurBuf[mCurBufIndex]);
      mCurBufIndex++;
      writeNextByte();

      break;

    case I2C_STATE_WRITEEND:
      if (valISR & (ISR_BED | ISR_ALD)) {
	mI2CState = I2C_STATE_ERROR;
	post handleWriteError();
	break;
      }
      mI2CState= I2C_STATE_IDLE;
      //call I2C.setICR(call I2C.getICR() & ~I2C_STOP);
      call I2C.setICR(mBaseICRFlags);
      signal I2CPacket.writeDone(SUCCESS,mCurTargetAddr,mCurBufLen,mCurBuf);
      break;

    default:
      break;
    }

      
    return;
  }

  default async event void I2CPacket.readDone(error_t error, uint16_t addr, 
					     uint8_t length, uint8_t* data) {
    return;
  }

  default async event void I2CPacket.writeDone(error_t error, uint16_t addr, 
						     uint8_t length, uint8_t* data) { 
    return;
  }

  async event void I2CSDA.interruptGPIOPin() {}
  async event void I2CSCL.interruptGPIOPin() {}
}

⌨️ 快捷键说明

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