[Tinyos-beta-commits] CVS: tinyos-1.x/beta/platform/pxa27x
PXA27XI2CM.nc, NONE, 1.1 pxa27x_registers.h, 1.8, 1.9
Konrad Lorincz
konradlorincz at users.sourceforge.net
Thu Aug 25 16:06:57 PDT 2005
Update of /cvsroot/tinyos/tinyos-1.x/beta/platform/pxa27x
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4783
Modified Files:
pxa27x_registers.h
Added Files:
PXA27XI2CM.nc
Log Message:
Added pxa27x I2C module and updated the pxa27x_registers.h registers with the I2C ones.
--- NEW FILE: PXA27XI2CM.nc ---
// $Id: PXA27XI2CM.nc,v 1.1 2005/08/25 23:06:55 konradlorincz Exp $
/* tab:4
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
* downloading, copying, installing or using the software you agree to
* this license. If you do not agree to this license, do not download,
* install, copy or use the software.
*
* Intel Open Source License
*
* Copyright (c) 2005 Intel 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 Intel 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 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.
*/
/**
* Description - PXA27X I2C interface.
* ---------- Usage example ----------
* // (1) - To read 1 byte from a slave device's register
* call I2C.sendStart(); // wait for sendStartDone()
* call I2C.write( getDataFromAddr(DEVICE_SLAVEADDR, FALSE) ); // wait for writeDone()
* call I2C.write(deviceRegAddr); // wait for writeDone()
* call I2C.sendStart(); // wait for sendStartDone()
* call I2C.write( getDataFromAddr(DEVICE_SLAVEADDR, TRUE) ); // wait for writeDone()
* call I2C.sendEnd(); // wait for sendEndDone()
* call I2C.read(FALSE); // wait for readDone()
* // the data is returned in readDone()
* -----------------------------------
*
* @author Konrad Lorincz
* @version 1.0, August 10, 2005
*/
includes pxa27x_registers;
includes pxa27x_registersI2C;
module PXA27XI2CM
{
provides interface StdControl;
provides interface I2C;
}
implementation
{
// ======================= Data ==================================
uint8_t nextReadOrWrite;
enum {
START = 1,
NO_START_OR_STOP,
STOP,
};
uint8_t state;
enum {
IDLE = 1,
WAITING_SEND_START,
WAITING_SEND_STOP,
WAITING_READ,
WAITING_WRITE,
};
// ======================= Methods ===============================
// ----------------------- Internal private helper functions -----
void I2C_configurePins()
{
/*
* Need to configure the I2C pins the correct functionality
* GPIO<117> = I2C_SCL = ALT1(in)/ALT1(out)
* GPIO<118> = I2C_SDA = ALT1(in)/ALT1(out)
*/
// (1) - Configure the GPIO Alt functions and directions
// a) tha alt functions
_GPIO_setaltfn(117,1);
_GPIO_setaltfn(118,1);
// b) the directions
// Nothing to set because SCL and SDA are special bidirectional GPIOs
// The direction of the pin is controlled by the peripheral directly
// overwritting the GPIO directional settings for the pin (GPDR)
}
void I2C_init()
{
// (1) - Configure the GPIO pins
I2C_configurePins();
// (2) - Enablet the I2C clocks
CKEN |= CKEN14_I2C; // enable I2C clock
CKEN |= CKEN15_PMI2C; // Power Manager I2C Unit Clock Enable, this is necessary to
// enable ICR[IUE]
}
void I2C_enable()
{
// Enable the I2C unit and SCL
ICR |= ICR_IUE; // enable the I2C interface
ICR |= ICR_SCLE; // enable the SCL
}
void I2C_disable()
{
// Disable the I2C unit and SCL
ICR &= ~(ICR_IUE); // disable the I2C interface
ICR &= ~(ICR_SCLE); // disable the SCL
}
void I2C_reset()
{
// Reset the I2C
ICR |= ICR_UR; // 1. Set the reset bit in ICR, and
ICR &= ICR_UR; // clear the rest of the register
ISR ^= ISR; // 2. Clear the ISR register
ICR &= ~(ICR_UR); // 3. Clear reset in the ICR
}
result_t I2C_waitInterruptRxDone()
{
while ( !(ISR & ISR_IRF) && !(ISR & ISR_BED) )
TOSH_wait();
if (ISR & ISR_IRF)
return SUCCESS;
else
return FAIL;
}
result_t I2C_waitInterruptTxDone()
{
while ( !(ISR & ISR_ITE) && !(ISR & ISR_BED) )
TOSH_wait();
if (ISR & ISR_ITE)
return SUCCESS;
else
return FAIL;
}
void I2C_clearInterruptTxDone()
{
// Clear the "IDBR transmit-empty" by writting a logic 1
// if ISR_ITE == 0 => The data byte is still being transmitted
// if ISR_ITE == 1 => The data byte was transmitted on the I2C bus
ISR |= ISR_ITE;
}
void I2C_clearInterruptRxDone()
{
// Clear the "IDBR receive-full" by writting a logic 1
// if ISR_IRF == 0 => The IDBR has not received a new data on the I2C
// if ISR_IRF == 1 => The IDBR received a new data byte from the I2C
ISR |= ISR_IRF;
}
void I2C_clearInterruptArbitrLoss()
{
// Clear the "IDBR arbitration loss" by writting a logic 1, if set
// if ISR_ALD == 0 => When arbitration is won or never took place
// if ISR_ALD == 1 => When it loses arbitration
// Note: If the master loses aribtration, it performs an address retry when
// the bus becomes free. The arbitration-loss-detected interrupt is
// disabled to allow the address retry.
if (ISR & ISR_ALD)
ISR |= ISR_ALD;
}
void I2C_clearStateSend(bool clearACKNAK)
{
ICR &= ~(ICR_STOP);
if (clearACKNAK)
ICR &= ~(ICR_ACKNAK);
}
void I2C_loadIDBRwithAddr(uint8_t targetSlaveAddr7Bit, bool isRnWTypeRead)
{
// (1) - Load target address and R/nW bin in IDBR.
// Note: RnW is the LSB of IDBR (i.e. 7-bitTargetSlaveAddr + RnW-bit)
IDBR = (targetSlaveAddr7Bit << 1); // upper 7-bits
if (isRnWTypeRead)
IDBR |= (1 << 0); // for Read, RnW=1
else
IDBR &= ~(1 << 0); // for Write, RnW=0
}
void I2C_loadIDBRwithData(uint8_t dataByte)
{
// Load the dataByte in the IDBR register
IDBR = dataByte;
}
// ----------------------- StdControl interface ------------------
command result_t StdControl.init()
{
return SUCCESS;
}
command result_t StdControl.start()
{
atomic {
state = IDLE;
nextReadOrWrite = NO_START_OR_STOP;
}
I2C_init();
I2C_enable();
return SUCCESS;
}
command result_t StdControl.stop()
{
I2C_disable();
return SUCCESS;
}
// ----------------------- I2C interface -------------------------
void task triggerEvent()
{
result_t result;
switch (state) {
case WAITING_SEND_START:
atomic {
state = IDLE;
nextReadOrWrite = START;
signal I2C.sendStartDone();
}
break;
case WAITING_SEND_STOP:
atomic {
state = IDLE;
nextReadOrWrite = STOP;
signal I2C.sendEndDone();
}
break;
case WAITING_READ:
if (I2C_waitInterruptRxDone())
result = SUCCESS;
else
result = FAIL;
I2C_clearInterruptRxDone();
if (nextReadOrWrite == STOP)
I2C_clearStateSend(TRUE);
atomic {
state = IDLE;
nextReadOrWrite = NO_START_OR_STOP;
signal I2C.readDone(IDBR);
}
break;
case WAITING_WRITE:
if (I2C_waitInterruptTxDone())
result = SUCCESS;
else
result = FAIL;
I2C_clearInterruptTxDone();
if (nextReadOrWrite == STOP)
I2C_clearStateSend(FALSE);
atomic {
state = IDLE;
nextReadOrWrite = NO_START_OR_STOP;
signal I2C.writeDone(result);
}
break;
default:
break;
}
}
command result_t I2C.sendStart()
{
atomic {
if (state != IDLE)
return FAIL;
}
if (post triggerEvent()) {
atomic state = WAITING_SEND_START;
return SUCCESS;
}
else {
return FAIL;
}
}
command result_t I2C.sendEnd()
{
atomic {
if (state != IDLE)
return FAIL;
}
if (post triggerEvent()) {
atomic state = WAITING_SEND_STOP;
return SUCCESS;
}
else
return FAIL;
}
command result_t I2C.read(bool ack)
{
atomic {
if (state != IDLE)
return FAIL;
}
// (1) - Do the read
switch (nextReadOrWrite) {
case START:
return FAIL; // TO DO: not yet implemented (not sure if this is valid)
case NO_START_OR_STOP:
ICR &= ~(ICR_START);
ICR &= ~(ICR_STOP);
ICR |= ICR_ALDIE;
if (!ack)
ICR |= ICR_ACKNAK;
ICR |= ICR_TB;
break;
case STOP:
ICR &= ~(ICR_START);
ICR |= ICR_STOP;
ICR |= ICR_ALDIE;
if (!ack)
ICR |= ICR_ACKNAK;
ICR |= ICR_TB;
break;
default:
return FAIL;
}
if (post triggerEvent()) {
atomic state = WAITING_READ;
return SUCCESS;
}
else
return FAIL;
}
command result_t I2C.write(char data)
{
atomic {
if (state != IDLE)
return FAIL;
}
// (1) - Load the data in the IDBR register
IDBR = data;
// (2) - Do the write
switch (nextReadOrWrite) {
case START:
ICR |= ICR_START;
ICR &= ~(ICR_STOP);
ICR &= ~(ICR_ALDIE);
ICR |= ICR_TB;
break;
case NO_START_OR_STOP:
ICR &= ~(ICR_START);
ICR &= ~(ICR_STOP);
ICR |= ICR_ALDIE;
ICR |= ICR_TB;
break;
case STOP:
ICR &= ~(ICR_START);
ICR |= ICR_STOP;
ICR |= ICR_ALDIE;
ICR |= ICR_TB;
break;
default:
return FAIL;
}
if (post triggerEvent()) {
atomic state = WAITING_WRITE;
return SUCCESS;
}
else
return FAIL;
}
default event result_t I2C.sendStartDone()
{
return SUCCESS;
}
default event result_t I2C.sendEndDone()
{
return SUCCESS;
}
default event result_t I2C.readDone(char data)
{
return SUCCESS;
}
default event result_t I2C.writeDone(bool success)
{
return SUCCESS;
}
}
Index: pxa27x_registers.h
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/beta/platform/pxa27x/pxa27x_registers.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** pxa27x_registers.h 18 Aug 2005 23:24:39 -0000 1.8
--- pxa27x_registers.h 25 Aug 2005 23:06:55 -0000 1.9
***************
*** 702,705 ****
--- 702,742 ----
#define ISAR _PXAREG(0x403016A0) /* I2C Slave Address register 9-28 */
+ /* I2C - Control Register */
+ #define ICR_FM (1 << 15) /* Fast Mode */
+ #define ICR_UR (1 << 14) /* Unit Reset */
+ #define ICR_SADIE (1 << 13) /* Slave Address Detected Interrupt Enable */
+ #define ICR_ALDIE (1 << 12) /* Arbitratino Loss Detected Interrupt Enable */
+ #define ICR_SSDIE (1 << 11) /* Slave STOP Detected Interrupt Enable */
+ #define ICR_BEIE (1 << 10) /* Bus Error Interrupt Enable */
+ #define ICR_DRFIE (1 << 9) /* DBR Receive Full Interupt Enable */
+ #define ICR_ITEIE (1 << 8) /* IDBR Transmit Empty Interrupt Enable */
+ #define ICR_GCD (1 << 7) /* General Call Disable */
+ #define ICR_IUE (1 << 6) /* I2C Unit Enable */
+ #define ICR_SCLE (1 << 5) /* SCL Enable */
+ #define ICR_MA (1 << 4) /* Master Abort */
+ #define ICR_TB (1 << 3) /* Transfer Byte */
+ #define ICR_ACKNAK (1 << 2) /* Positive/Negative Acknowledge */
+ #define ICR_STOP (1 << 1) /* Stop */
+ #define ICR_START (1 << 0) /* Start */
+
+ /* I2C - Status Register */
+ #define ISR_BED (1 << 10) /* Bus Error Detected */
+ #define ISR_SAD (1 << 9) /* Slave Address Detected */
+ #define ISR_GCAD (1 << 8) /* General Call Address Detected */
+ #define ISR_IRF (1 << 7) /* IDBR Receive Full */
+ #define ISR_ITE (1 << 6) /* IDBR Transmit Empty */
+ #define ISR_ALD (1 << 5) /* Arbitration Loss Detection */
+ #define ISR_SSD (1 << 4) /* Slave STOP Detected */
+ #define ISR_IBB (1 << 3) /* I2C Bus Busy */
+ #define ISR_UB (1 << 2) /* Unit Busy */
+ #define ISR_ACKNAK (1 << 1) /* Ack/Nack Status */
+ #define ISR_RWM (1 << 0) /* Read/Write Mode */
+
+ /* I2C - Bus Monitor Register */
+ #define IBMR_SCL (1 << 1) /* Continousely reflects the value of the SCL pin */
+ #define IBMR_SDA (1 << 0) /* Continousely reflects the value of the SDA pin */
+
+
+
/******************************************************************************/
More information about the Tinyos-beta-commits
mailing list