i2c

----- i2c.h----

#ifndef _I2C_H_
#define _I2C_H_

#include "tistdtypes.h"

// Prevent C++ name mangling
#ifdef __cplusplus
extern far "c" {
#endif

/************************************************************
* Global Macro Declarations                                 *
************************************************************/

#define I2C_TIMEOUT       (0x10000u)

/***********************************************************
* Global Typedef declarations                              *
***********************************************************/

// I2C Module Roles
typedef enum _I2C_ROLE_
{
  I2C_ROLE_MASTER = 0x01,
  I2C_ROLE_SLAVE = 0x02
}
I2C_Role;

// I2C Module Modes of Operation
typedef enum _I2C_MODE_
{
  I2C_MODE_MANUAL_STOP          = 0x01,
  I2C_MODE_REPEAT_MANUAL_STOP   = 0x02,
  I2C_MODE_AUTO_STOP            = 0x04,
  I2C_MODE_REPEAT_AUTO_STOP     = 0x08
}
I2C_Mode;

typedef enum _I2C_STATUS_
{
  I2C_STATUS_RESET = 0x01,
  I2C_STATUS_READY = 0x02,
  I2C_STATUS_BUSY  = 0x03
}
I2C_Status;

typedef enum _I2C_ADDRESSING_MODE_
{
  I2C_ADDRESSING_7BIT  = 0x01,
  I2C_ADDRESSING_10BIT = 0x02
}
I2C_AddressingMode;

typedef struct _I2C_CONFIG_
{
  Uint32              ownAddr;
  Uint8               i2cclkl;
  Uint8               i2cclkh;
  Uint8               prescalar;
  I2C_AddressingMode  addrMode;
}
I2C_ConfigObj, *I2C_ConfigHandle;

// I2C driver structure
typedef struct _I2C_INFO_
{
  Uint32      peripheralNum;
  void        *regs;
  Uint32      slaveAddr;
  I2C_Role    role;
  I2C_Mode    mode;
  I2C_Status  status;
}
I2C_InfoObj, *I2C_InfoHandle;


/************************************************************
* Global Function Declarations                              *
************************************************************/

extern I2C_InfoHandle I2C_open(Uint32 i2cPeripheralNum, I2C_Role role, I2C_Mode mode, I2C_ConfigHandle hConfig);
extern void I2C_assertReset(I2C_InfoHandle hI2CInfo);
extern void I2C_releaseReset(I2C_InfoHandle hI2CInfo);
void I2C_setStopCondition(I2C_InfoHandle hI2CInfo);
void I2C_setStartCondition(I2C_InfoHandle hI2CInfo, Uint32 i2cmdr);
extern Uint32 I2C_readBytes(I2C_InfoHandle hI2CInfo, Uint32 byteCnt, Uint8 *dest);
extern Uint32 I2C_writeBytes(I2C_InfoHandle hI2CInfo, Uint32 byteCnt, Uint8 *src);


/***********************************************************
* End file                                                 *
***********************************************************/

#ifdef __cplusplus
}
#endif

#endif // _I2C_H_

-----i2c.c-----


// General type include
#include "tistdtypes.h"

// Device specific CSL
#include "device.h"

// Util functions
#include "util.h"

// This module's header file
#include "i2c.h"


/************************************************************
* Explicit External Declarations                            *
************************************************************/


/************************************************************
* Local Macro Declarations                                  *
************************************************************/


/************************************************************
* Local Function Declarations                               *
************************************************************/


/************************************************************
* Local Variable Definitions                                *
************************************************************/


/************************************************************
* Global Variable Definitions                               *
************************************************************/

#ifdef USE_IN_ROM
I2C_InfoObj gI2CInfo;
#endif


/************************************************************
* Global Function Definitions                               *
************************************************************/

// Initialze NAND interface and find the details of the NAND used
I2C_InfoHandle I2C_open(Uint32 i2cPeripheralNum, I2C_Role role, I2C_Mode mode, I2C_ConfigHandle hConfig)
{
  I2C_InfoHandle hI2CInfo;
  DEVICE_I2CRegs *I2C;

  // Set NandInfo handle
#ifdef USE_IN_ROM
  hI2CInfo = (I2C_InfoHandle) &gI2CInfo;
#else
  hI2CInfo = (I2C_InfoHandle) UTIL_allocMem(sizeof(I2C_InfoObj));
#endif

  // Do device level init (pinmux, power domain, etc.)
  if (DEVICE_I2CInit(i2cPeripheralNum) != E_PASS)
  {
    return NULL;
  }

  hI2CInfo->peripheralNum = i2cPeripheralNum;
  hI2CInfo->regs = (void *) (((Uint32)I2C0) + (I2C_MEMORYMAP_SPACING *i2cPeripheralNum) );
  I2C = (DEVICE_I2CRegs *) hI2CInfo->regs;

  // Put the I2C peripheral into reset
  I2C_assertReset(hI2CInfo);
 
    // Set Own Address
    I2C->ICOAR = hConfig->ownAddr;
    
    // Set Default I2C High and Low Clock Hold
    I2C->ICPSC  = (hConfig->prescalar - 1) & 0xFF;
    I2C->ICCLKL = (hConfig->i2cclkl - 1) & 0xFF;
    I2C->ICCLKH = (hConfig->i2cclkh - 1) & 0xFF;
   
    // Set the device role
  hI2CInfo->role = role;
 
  // Set the device mode the
  hI2CInfo->mode = mode;
                       
  // Take I2C Out of Reset
  I2C_releaseReset(hI2CInfo);

  // Clear BB and ARDY
  I2C->ICSTR |= (I2C_ICSTR_ARDY_MSK | I2C_ICSTR_BB_MSK);
 
  return hI2CInfo;
}

// Routine to reset the I2C device
void I2C_assertReset(I2C_InfoHandle hI2CInfo)
{
  DEVICE_I2CRegs *I2C;
  I2C = (DEVICE_I2CRegs *) hI2CInfo->regs;

  // Send reset command to I2C
  I2C->ICMDR &= (~I2C_ICMDR_IRS);

  hI2CInfo->status = I2C_STATUS_RESET;
}

void I2C_releaseReset(I2C_InfoHandle hI2CInfo)
{
  DEVICE_I2CRegs *I2C;
  I2C = (DEVICE_I2CRegs *) hI2CInfo->regs;

  // Release from reset
  I2C->ICMDR |= I2C_ICMDR_IRS;

  hI2CInfo->status = I2C_STATUS_READY;
}

void I2C_setStopCondition(I2C_InfoHandle hI2CInfo)
{
  DEVICE_I2CRegs *I2C;
  I2C = (DEVICE_I2CRegs *) hI2CInfo->regs;

  if (hI2CInfo->role == I2C_ROLE_MASTER)
  {
    // Generate the Stop Condition
    I2C->ICMDR |= I2C_ICMDR_STP;

      // Wait for Master mode cleared
      while(I2C->ICMDR & I2C_ICMDR_MST);
  }

  // Put I2C in reset
  I2C->ICMDR &= ~I2C_ICMDR_IRS;

  // Set the status
  hI2CInfo->status = I2C_STATUS_RESET;
}

void I2C_setStartCondition(I2C_InfoHandle hI2CInfo, Uint32 i2cmdr)
{
  DEVICE_I2CRegs *I2C;
  I2C = (DEVICE_I2CRegs *) hI2CInfo->regs;

  if (hI2CInfo->role == I2C_ROLE_MASTER)
  {
    i2cmdr |= I2C_ICMDR_MST;

    if (hI2CInfo->status != I2C_STATUS_BUSY)
    {
      // Wait till the Bus is free for transfer
        while(I2C->ICSTR & I2C_ICSTR_BB_MSK);
    }

    I2C->ICMDR = (i2cmdr | I2C_ICMDR_STT | I2C_ICMDR_IRS);

    // Make sure the bus now says we are busy (since we set start cond.)
      while(!(I2C->ICSTR & I2C_ICSTR_BB_MSK));

    // Set the status
    hI2CInfo->status = I2C_STATUS_BUSY;
  }
  else
  {
    I2C->ICMDR = (i2cmdr | I2C_ICMDR_IRS);
    hI2CInfo->status = I2C_STATUS_READY;
  }

}

// Generic routines to read a page from I2C
Uint32 I2C_readBytes(I2C_InfoHandle hI2CInfo, Uint32 byteCnt, Uint8 *dest)
{
  Uint8* currDestPtr;
  Uint32 currByteCnt,i2cstr,i2cmdr;
  DEVICE_I2CRegs *I2C;
  I2C = (DEVICE_I2CRegs *) hI2CInfo->regs;

  currDestPtr = dest;
  currByteCnt = byteCnt;
  i2cmdr      = 0x0000;

  // Clear or set repeat mode
  if ((hI2CInfo->mode==I2C_MODE_REPEAT_MANUAL_STOP) || (hI2CInfo->mode==I2C_MODE_REPEAT_AUTO_STOP))
  {
    i2cmdr |= I2C_ICMDR_RM;
  }
  else
  {
    // Set the byte count to transfer
    I2C->ICCNT = currByteCnt;
  }

  // Set slave address
    I2C->ICSAR = hI2CInfo->slaveAddr;

  // Start Sending the bytes (only
  I2C_setStartCondition(hI2CInfo,i2cmdr);

  while (currByteCnt)
  {
    i2cstr = I2C->ICSTR;

    //Check if Receive Data Register is Ready
      if (i2cstr & I2C_ICSTR_ICRRDY_MSK)
    {
      // Read data from Receive Data Register
      *currDestPtr++ = I2C->ICDRR;
      currByteCnt--;
    }
  }

  // Wait for register access to be ready
  while (!(I2C->ICSTR & I2C_ICSTR_ARDY_MSK));

  if ((hI2CInfo->mode == I2C_MODE_AUTO_STOP) || (hI2CInfo->mode == I2C_MODE_REPEAT_AUTO_STOP))
    I2C_setStopCondition(hI2CInfo);
 
    return E_PASS;
}


// Generic routine to write bytes to I2C
Uint32 I2C_writeBytes(I2C_InfoHandle hI2CInfo, Uint32 byteCnt, Uint8 *src)
{
  Uint8* currSrcPtr;
  Uint32 currByteCnt,i2cstr,i2cmdr;
  DEVICE_I2CRegs *I2C;
  I2C = (DEVICE_I2CRegs *) hI2CInfo->regs;
 
  currByteCnt = byteCnt;
  currSrcPtr  = src;
  i2cmdr      = 0x0000;

  // Set as transmitter
  i2cmdr |= (I2C_ICMDR_TRX);

  // Clear or set repeat mode
  if ( (hI2CInfo->mode == I2C_MODE_REPEAT_MANUAL_STOP) || (hI2CInfo->mode == I2C_MODE_REPEAT_AUTO_STOP) )
  {
    i2cmdr |= I2C_ICMDR_RM;
  }
  else
  {
    I2C->ICCNT = currByteCnt;
  }

  // Set slave address
    I2C->ICSAR = hI2CInfo->slaveAddr;

  I2C_setStartCondition(hI2CInfo,i2cmdr);

  UTIL_waitLoop(100);

  // Transmit all bytes
  while (currByteCnt)
  {
    Int32 timeout;
    I2C->ICDXR = *currSrcPtr++;
    currByteCnt--;

    timeout = I2C_TIMEOUT;
    do
    {
      i2cstr = I2C->ICSTR;
      if ( timeout-- < 0 )
      {
     timeout = I2C_TIMEOUT;
        I2C_assertReset(hI2CInfo);
        return E_TIMEOUT;
      }
    } while ( (i2cstr & I2C_ICSTR_ICXRDY_MSK) == 0 ); // Wait for Tx Ready

    // If NACK condition, then we fail
    if (i2cstr & (I2C_ICSTR_NACK_MSK | I2C_ICSTR_AL_MSK))
      {
          I2C_assertReset(hI2CInfo);
      I2C_releaseReset(hI2CInfo);
        return E_FAIL;
    }
  }

  if ((hI2CInfo->mode == I2C_MODE_AUTO_STOP) || (hI2CInfo->mode == I2C_MODE_REPEAT_AUTO_STOP))
    I2C_setStopCondition(hI2CInfo);

  return E_PASS;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值