halpxa27xi2cmasterp.nc

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

NC
287
字号
/* $Id: HalPXA27xI2CMasterP.nc,v 1.1.2.3 2006/06/20 19:43:58 philipb Exp $ */
/*
 * Copyright (c) 2005 Arched 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 Arched 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>

module HalPXA27xI2CMasterP
{
  provides interface Init;
  provides interface I2CPacket<TI2CBasicAddr>;

  uses interface HplPXA27xI2C as I2C;
}

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;
  const uint32_t mBaseICRFlags = (ICR_FM | ICR_BEIE | ICR_IUE | ICR_SCLE);

  static void readNextByte() {
    if (mCurBufIndex >= (mCurBufLen - 1)) {
      mI2CState = I2C_STATE_READEND;
      if (mI2CFlags & I2C_STOP) {
	call I2C.setICR((mBaseICRFlags) | (ICR_ALDIE | ICR_DRFIE | ICR_ACKNAK | ICR_TB | ICR_STOP));
      }
      else if (mI2C_FLAGS & 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 {
      call I2C.setICR((mBaseICRFlags) | (ICR_ALDIE | ICR_DRFIE | ICR_TB));
    }
    return;
  }

  static void writeNextByte() {
    if (mCurBufIndex >= mCurBufLen) {
      mI2CState = I2C_STATE_WRITEEND;
      if (mI2CFlags & I2C_STOP) {
	call I2C.setICR((mBaseICRFlags) | (ICR_ALDIE | ICR_TB | ICR_STOP));
      }
      else {
	call I2C.setICR((mBaseICRFlags) | (ICR_ALDIE | ICR_TB));
      }
    }
    else {
      call I2C.setICR((mBaseICRfFlags) | (ICR_ALDIE | 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.setISR(0x7F0);
    call I2C.setICR(mBaseICRFlags | ICR_MA);
    call I2C.setICR(ICR_UR);
    call I2C.setICR(mBaseICRFlags);
    mI2CState = I2C_STATE_IDLE;
    atomic {
      signal I2CPacket.readDone(FAIL,mCurTargetAddr,mCurBufLen,mCurBuf);
    }
    return;
  }
    
  task void handleWriteError() {
    call I2C.setISR(0x7F0);
    call I2C.setICR(mBaseICRFlags | ICR_MA);
    call I2C.setICR(ICR_UR);
    call I2C.setICR(mBaseICRFlags);
    mI2CState = I2C_STATE_IDLE;
    atomic {
      signal I2CPacket.readDone(FAIL,mCurTargetAddr,mCurBufLen,mCurBuf);
    }
    return;
  }

  command error_t Init.init() {
    atomic {
      mI2CState = I2C_STATE_IDLE;
    }    
  }

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

    if ((flags & I2C_ACKEND) && (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;
    uint8_t tmpAddr;

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

    return error;
  }

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

    valISR = call I2C.getISR();

    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++;

      break;

    case I2C_STATE_WRITEEND:
      if (valISR & (ISR_BED | ISR_ALD)) {
	mI2CState = I2C_STATE_ERROR;
	post handleWriteError();
	break;
      }
      mI2CState= I2C_STATE_IDLE;
      signal I2CPacket.writeDone(SUCCESS,mCurTargetAddr,mCurBufLen,mCurBuf);
      break;

    default:
      break;
    }

      
    return;
  }

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

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

⌨️ 快捷键说明

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