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 + -
显示快捷键?