这个可以算是我来到新公司写的第一个驱动吧,在之前公司写过spi的驱动,这个跟spi比较类似,只不过只有两跟线,scl(时钟)和sda(数据),写的时候有代码参照,just easy job,调试的时候也只碰到几个小障碍:
1. iic_write的时候漏了一个i2c_start(),造成写入时序不正确,这时可以通过示波器抓波形查出来,波形中在sda改变输入输出方向时会出现一些毛刺,属正常现象,数据改变发生在scl为低的时候。
2.i2c_simu_read_byte的时候数据移位和取bit值的的顺序搞反了,应该是先移位,再取值!道理很简单,第一次移位是无效值,最后那次移位是有效值
3.GPIO pin角属性定义,当时是sfp设备不能scan到,但其他I2C设备正常,里面代码都是一样的,还是叶大师提醒才去看了连到sfp上的pin角属性定义,发现这些pin被定义成非GPIO的了,那当然是不行啦!
下面是正确属性值:
/* I2c BUS */ /*PA0 */ {PORTA, 0, IO_OUT, 0, GPIO, 1},/* SFP0_SCL */ /*PA1 */ {PORTA, 1, IO_OUT, 0, GPIO, 1},/*SFP0_SDA */ /*PA2 */ {PORTA, 2, IO_OUT, 0 , GPIO, 1},/*SFP1_SCL */ /*PA4 */ {PORTA, 4, IO_OUT, 0 , GPIO, 1},/*SFP1_SDA */ /*PA5 */ {PORTA, 5, IO_OUT, 0 , GPIO, 1},/*CPU_SCL */ /*PA6 */ {PORTA, 6, IO_OUT, 0 , GPIO, 1},/*CPU_SDA */
一。先上王道:
二.GPIO pin 定义
PA0 |
|
GPI |
F0_SCL |
PA1 |
|
GPI |
F0_SDA |
PA2 |
|
GPI |
F1_SCL |
PA4 |
|
GPI |
F1_SDA |
PA5 |
|
GPI |
GPIO CPU_SCK |
PA6 |
|
GPI |
GPIO CPU_SDA |
三源代码
1,i2cbussimu.c
- /**********************************************************************************
- Module:
- i2cbussimu.c
- History:
- xu xinlin created in 2011.3.7
- Description:
- This file define the interface to operate I2C, simulated by GPIO.
- ***********************************************************************************/
- #include <vxWorks.h>
- #include <string.h>
- #include "immap_83xx.h"
- #include "rdb8323.h"
- #include "gpio.h"
- #include "i2cbussimu.h"
- #include "i2cDevices.h"
- extern void sysUsDelay(int delay);
- #define i2c_debug 0
- #define i2c_printf(fmt,arg...) {if(i2c_debug)printf(fmt,##arg);}
- #define I2CBUS_FREN (85937) /* Hz */
- #define I2CBUS_CYCLE ((1000000+I2CBUS_FREN)/I2CBUS_FREN) /* In Us */
- #define BYTE_TRANSFER_TIME (I2CBUS_CYCLE*15) /* I2CBUS_CYCLE * 9 */
- #define BYTE_TRANSFER_TIME2 (I2CBUS_CYCLE*50) /* I2CBUS_CYCLE * 9 */
- #define I2CDELAY sysUsDelay(I2CBUS_CYCLE/4)
- const UINT8 aI2cDevAddr[] =
- {
- /* i2c line 0 */
- /*I2C_MB_EEPROM */ 0xAE, /* 0 device number for eeprom in main board */
- /*I2C_PM_SENSOR */ 0x30, /* 1 Thermal Sensor for Power module */
- /*I2C_CPU_SENSOR */ 0x98, /* 2 Thermal Sensor for CPU */
- /*I2C_AD */ 0x90, /* 3 A/D ADS7830IPWR */
- /*I2C_ZL30142 */ 0xCE, /* 4 ZL30142 */
-
- /* i2c line 1 */
- /*I2C_SFP0_EL */ 0xA0, /* 5 SFP0 electric port*/
- /*I2C_SFP0_FB */ 0xA2, /* 6 SFP0 fiber port */
-
- /* i2c line 2 */
- /*I2C_SFP1_EL */ 0xA0, /* 7 SFP1 electric port */
- /*I2C_SFP1_FB */ 0xA2, /* 8 SFP1 fiber port */
- };
- /* Proto definition */
- LOCAL void SDA_OUTPUT_ACTIVE(struct i2c_simu_dev i2c_dev);
- LOCAL void SDA_OUTPUT_ACTIVE(struct i2c_simu_dev i2c_dev);
- LOCAL void SDA_INPUT_ACTIVE(struct i2c_simu_dev i2c_dev);
- LOCAL void SCL_OUTPUT_ACTIVE(struct i2c_simu_dev i2c_dev);
- LOCAL void SCL_INPUT_ACTIVE(struct i2c_simu_dev i2c_dev);
- LOCAL void SCL_WRITE(struct i2c_simu_dev i2c_dev, UINT8 bitval);
- LOCAL STATUS SCL_READ(struct i2c_simu_dev i2c_dev);
- LOCAL void SDA_WRITE(struct i2c_simu_dev i2c_dev, UINT8 bitval);
- LOCAL STATUS SDA_READ(struct i2c_simu_dev i2c_dev);
- LOCAL STATUS i2c_start(struct i2c_simu_dev i2c_dev);
- LOCAL void i2c_stop(struct i2c_simu_dev i2c_dev);
- LOCAL STATUS receive_i2c_ack(struct i2c_simu_dev i2c_dev);
- LOCAL STATUS send_i2c_ack(struct i2c_simu_dev i2c_dev);
- LOCAL STATUS send_i2c_nack(struct i2c_simu_dev i2c_dev);
- LOCAL STATUS i2c_simu_read_byte (struct i2c_simu_dev i2c_dev, UINT8 *data,UINT32 length);
- LOCAL STATUS i2c_simu_write_byte (struct i2c_simu_dev i2c_dev, UINT8 writeData);
- LOCAL STATUS i2c_stat_check(struct i2c_simu_dev i2c_dev);
- LOCAL void SDA_OUTPUT_ACTIVE(struct i2c_simu_dev i2c_dev)
- {
- volatile immap_t * immr =(immap_t *)CCSBAR;
- immr->qepio.ioport[i2c_dev.port].dir1 &= ~(0x80000000 >> (i2c_dev.sda<<1));
- immr->qepio.ioport[i2c_dev.port].dir1 |= (0x80000000 >> ((i2c_dev.sda<<1) + 1));
-
- }
- LOCAL void SDA_INPUT_ACTIVE(struct i2c_simu_dev i2c_dev)
- {
- volatile immap_t * immr =(immap_t *)CCSBAR;
- immr->qepio.ioport[i2c_dev.port].dir1 &= ~(0x80000000 >> ((i2c_dev.sda<<1) + 1));
- immr->qepio.ioport[i2c_dev.port].dir1 |= (0x80000000 >> (i2c_dev.sda<<1));
- }
- LOCAL void SCL_OUTPUT_ACTIVE(struct i2c_simu_dev i2c_dev)
- {
- volatile immap_t * immr =(immap_t *)CCSBAR;
- immr->qepio.ioport[i2c_dev.port].dir1 &= ~(0x80000000 >> (i2c_dev.scl<<1));
- immr->qepio.ioport[i2c_dev.port].dir1 |= (0x80000000 >> ((i2c_dev.scl<<1) + 1));
- }
- LOCAL void SCL_INPUT_ACTIVE(struct i2c_simu_dev i2c_dev)
- {
- volatile immap_t * immr =(immap_t *)CCSBAR;
- immr->qepio.ioport[i2c_dev.port].dir1 &= ~(0x80000000 >> ((i2c_dev.scl<<1) + 1));
- immr->qepio.ioport[i2c_dev.port].dir1 |= (0x80000000 >> (i2c_dev.scl<<1));
- }
- LOCAL void SCL_WRITE(struct i2c_simu_dev i2c_dev, UINT8 bitval)
- {
- volatile immap_t * immr =(immap_t *)CCSBAR;
- if(bitval)
- immr->qepio.ioport[i2c_dev.port].pdat |= 0x80000000 >> i2c_dev.scl;
- else
- immr->qepio.ioport[i2c_dev.port].pdat &= ~(0x80000000>> i2c_dev.scl);
- }
- LOCAL STATUS SCL_READ(struct i2c_simu_dev i2c_dev)
- {
- volatile immap_t * immr =(immap_t *)CCSBAR;
- return (((immr->qepio.ioport[i2c_dev.port].pdat) & (0x80000000 >> i2c_dev.scl)) != 0);
- }
- LOCAL void SDA_WRITE(struct i2c_simu_dev i2c_dev, UINT8 bitval)
- {
- volatile immap_t * immr =(immap_t *)CCSBAR;
- if(bitval)
- immr->qepio.ioport[i2c_dev.port].pdat |= 0x80000000 >> i2c_dev.sda;
- else
- immr->qepio.ioport[i2c_dev.port].pdat &= ~(0x80000000>> i2c_dev.sda);
- }
- LOCAL STATUS SDA_READ(struct i2c_simu_dev i2c_dev)
- {
- volatile immap_t * immr =(immap_t *)CCSBAR;
- return (((immr->qepio.ioport[i2c_dev.port].pdat) & (0x80000000 >> i2c_dev.sda)) != 0);
-
- }
- /* -------------------------------------------------------------------------*
- * Function : i2cDrvInit *
- * Description: i2c device initial, configure i2c port/pin *
- * Parameters : i2c device structure & device number *
- * Return : OK if i2c start successfully,or I2C_ERROR_UNKNOW_DEVICE *
- * -------------------------------------------------------------------------*/
- STATUS i2cDrvInit(UINT8 devNum,struct i2c_simu_dev *i2c_dev)
- {
- /*****************************************************
- PA0--->F0_SCL
- PA1--->F0_SDA :SFP0
-
- PA2--->F1_SCL
- PA4--->F1_SDA :SFP1
- PA5--->CPU_SCL
- PA6--->CPU_SDA :I2C_MB_EEPROM,I2C_PM_SENSOR,I2C_CPU_SENSOR,I2C_AD,I2C_ZL30142
- ******************************************************/
- if ((devNum <= I2C_ZL30142) && (devNum >= I2C_MB_EEPROM))
- {
- i2c_dev->port = 0;
- i2c_dev->scl = 5;
- i2c_dev->sda = 6;
- }
- else if ((devNum <= I2C_SFP0_FB) && (devNum >= I2C_SFP0_EL))
- {
- i2c_dev->port = 0;
- i2c_dev->scl = 0;
- i2c_dev->sda = 1;
- }
- else if ((devNum <= I2C_SFP1_FB) && (devNum >= I2C_SFP1_EL))
- {
- i2c_dev->port = 0;
- i2c_dev->scl = 2;
- i2c_dev->sda = 4;
- }
- else
- {
- return I2C_ERROR_UNKNOW_DEVICE;
- }
- /* Get the device address */
- i2c_dev->i2cDevAddr = aI2cDevAddr[devNum];
- /* set sda&scl output mode */
- SCL_OUTPUT_ACTIVE(*i2c_dev);
- SDA_OUTPUT_ACTIVE(*i2c_dev);
- /* pull sda&scl high */
- SDA_WRITE(*i2c_dev, 1);
- SCL_WRITE(*i2c_dev, 1);
- return OK;
- }
- /* -------------------------------------------------------------------------*
- * Function : i2c_stat_check *
- * Description: restore I2C bus from dead lock by sending 9 clocks pusle *
- * Parameters : i2c device structure *
- * Return : OK if i2c start successfully,or I2C_ERROR_TIME_OUT *
- * -------------------------------------------------------------------------*/
- LOCAL STATUS i2c_stat_check(struct i2c_simu_dev i2c_dev)
- {
- UINT32 j = 0; /* counter */
-
- /* check scl&sda status,if it's low ,send 9 clocks pusle to restore it */
- if((!SDA_READ(i2c_dev)) || (!SCL_READ(i2c_dev)))
- {
- SDA_INPUT_ACTIVE (i2c_dev);
- for (j=0; j<9; j++)
- {
- SCL_WRITE(i2c_dev, 0); /* pull SCL low */
- I2CDELAY;
- I2CDELAY;
- SCL_WRITE(i2c_dev, 1); /* pull SCL high */
- I2CDELAY;
- I2CDELAY;
- }
- i2c_stop(i2c_dev);
- SDA_INPUT_ACTIVE (i2c_dev);
- }
- return OK;
- }
- /* -------------------------------------------------------------------------*
- * Function : i2c_start *
- * Description: SDA change from high to low when SCL keep in high. *
- * Parameters : i2c device structure *
- * Return : OK if i2c start successfully,or I2C_ERROR_TIME_OUT *
- * -------------------------------------------------------------------------*/
- LOCAL STATUS i2c_start(struct i2c_simu_dev i2c_dev)
- {
- I2CDELAY;
- SDA_WRITE (i2c_dev, 1); /* pull SDA high */
- SDA_OUTPUT_ACTIVE(i2c_dev); /* driver GPIO direction:output */
- I2CDELAY;
- SCL_WRITE(i2c_dev, 1); /* pull SCL high */
- I2CDELAY;
- SDA_WRITE (i2c_dev, 0); /* pull SDA low */
- I2CDELAY;
- return OK;
- }
- /* -------------------------------------------------------------------------*
- * Function : i2c_stop *
- * Description: SDA change from low to high when SCL keep in high. *
- * Parameters : i2c device structure *
- * Return : NULL *
- * -------------------------------------------------------------------------*/
- void i2c_stop(struct i2c_simu_dev i2c_dev)
- {
- SCL_WRITE(i2c_dev, 0); /* pull SCL low */
- I2CDELAY;
- SDA_WRITE (i2c_dev, 0); /* pull SDA low */
- SDA_OUTPUT_ACTIVE(i2c_dev); /* driver GPIO direction:output */
- I2CDELAY;
- SCL_WRITE (i2c_dev, 1); /* pull SCL high */
- I2CDELAY;
- SDA_WRITE (i2c_dev, 1); /* pull SDA high */
- I2CDELAY;
- SDA_INPUT_ACTIVE(i2c_dev); /* driver GPIO direction:input */
- }
- /* -------------------------------------------------------------------------*
- * Function : receive_i2c_ack *
- * Description: During SCL high, when SDA holds low is ACK otherwise NACK. *
- * Parameters : i2c device structure *
- * Return : OK is ACK, or is NACK. *
- * Notes : This function gets the ACK signal from the slave. *
- * -------------------------------------------------------------------------*/
- LOCAL STATUS receive_i2c_ack(struct i2c_simu_dev i2c_dev)
- {
- INT32 isAck = 0;
- SCL_WRITE (i2c_dev, 0); /* pull SCL low */
- I2CDELAY;
- SDA_WRITE (i2c_dev, 1); /* pull SDA high */
- SDA_INPUT_ACTIVE(i2c_dev); /* driver GPIO direction:input */
- I2CDELAY;
- SCL_WRITE (i2c_dev, 1); /* pull SCL high */
- I2CDELAY;
- I2CDELAY;
- if(SDA_READ(i2c_dev))
- {
- isAck = I2C_ERROR_CYCLE_ACKIN;
- }
- else
- {
- isAck = OK;
- }
- SCL_WRITE (i2c_dev, 0);
- I2CDELAY;
- SDA_OUTPUT_ACTIVE(i2c_dev); /* driver GPIO direction:output */
- return isAck;
- }
- /* -------------------------------------------------------------------------*
- * Function : send_i2c_ack *
- * Description: During SCL high, when SDA holds low is ACK otherwise NACK. *
- * Parameters : i2c device structure *
- * Return : OK if success,or I2C_ERROR_ACK *
- * Notes : This function send ACK to slave device *
- * -------------------------------------------------------------------------*/
- LOCAL STATUS send_i2c_ack(struct i2c_simu_dev i2c_dev)
- {
- SCL_WRITE (i2c_dev, 0); /* pull SCL low */
- I2CDELAY;
- SDA_OUTPUT_ACTIVE(i2c_dev); /* driver GPIO direction:output */
- SDA_WRITE (i2c_dev, 0); /* pull SDA low */
- I2CDELAY;
- SCL_WRITE (i2c_dev, 1); /* pull SCL high */
- I2CDELAY;
- I2CDELAY;
- SCL_WRITE (i2c_dev, 0); /* pull SCL low */
- I2CDELAY;
- return OK;
- }
- /* -------------------------------------------------------------------------*
- * Function : send_i2c_nack *
- * Description: During SCL high, when SDA holds low is ACK otherwise NACK. *
- * Parameters : i2c device structure *
- * Return : OK if success,or I2C_ERROR_NACK *
- * Notes : This function send NACK to slave device *
- * -------------------------------------------------------------------------*/
- LOCAL STATUS send_i2c_nack(struct i2c_simu_dev i2c_dev)
- {
- SCL_WRITE (i2c_dev, 0); /* pull SCL low */
- I2CDELAY;
- SDA_OUTPUT_ACTIVE(i2c_dev);/* driver GPIO direction:output */
- SDA_WRITE (i2c_dev, 1); /* pull SDA high */
- I2CDELAY;
- SCL_WRITE (i2c_dev, 1); /* pull SCL high */
- I2CDELAY;
- I2CDELAY;
- SCL_WRITE (i2c_dev, 0); /* pull SCL low */
- I2CDELAY;
- return OK;
- }
- /*-------------------------------------------------------------------*
- * Probe to see if a chip is present. Also good for checking for the *
- * completion of EEPROM writes since the chip stops responding until *
- * the write completes (typically 10mSec). *
- * -------------------------------------------------------------------*/
- STATUS i2c_probe (struct i2c_simu_dev i2c_dev)
- {
- INT32 iRc = 0;
-
- if (i2c_stat_check(i2c_dev) != OK)
- {
- return I2C_ERROR_KNOWN_STATE;
- }
- if (i2c_start(i2c_dev) != OK)
- {
- (void)i2c_stop(i2c_dev);
- return I2C_ERROR_CYCLE_START;
- }
- iRc = (i2c_simu_write_byte(i2c_dev, (i2c_dev.i2cDevAddr)) != OK) ? I2C_ERROR_CYCLE_WRITE:OK;
- (void)i2c_stop(i2c_dev);
- return (iRc);
- }
- /* -------------------------------------------------------------------------*
- * Function : i2c_simu_read_byte *
- * Description: Get the Data from slave device *
- * Parameters : i2c device structure,data buffer for loading data *
- * Return : OK if read byte successfully,or failure *
- * -------------------------------------------------------------------------*/
- LOCAL STATUS i2c_simu_read_byte (struct i2c_simu_dev i2c_dev, UINT8 *data,UINT32 length)
- {
- UINT8 i = 0,j = 0,input_byte = 0; /* counter */
-
- /* set GPIO pin direction:input */
- I2CDELAY;
-
- /* receive bytes of data */
- for (i = 0; i < length; i++)
- {
- SDA_INPUT_ACTIVE(i2c_dev);
- input_byte = 0x00;
- /*SCL(i2c_dev, 1);*/
- for (j = 0; j < 8; j++)
- {
- SCL_WRITE(i2c_dev, 0);
- I2CDELAY;
- I2CDELAY;
- SCL_WRITE (i2c_dev, 1);
- I2CDELAY;
- input_byte <<= 1;
- if (SDA_READ(i2c_dev))
- {
- input_byte++;
- }
- I2CDELAY;
-
- }
- data[i] = input_byte;
- if (i == length - 1)
- {
- break;
- }
- if (send_i2c_ack(i2c_dev)) /* always return OK */
- {
- i2c_stop(i2c_dev);
- return I2C_ERROR_CYCLE_ACKOUT;
- }
- }
- return OK;
- }
- /* -------------------------------------------------------------------------*
- * Function : i2c_simu_write_byte *
- * Description: Send the byte output of gpio, MSB first. *
- * Parameters : i2c device structure,data to be shifted. *
- * Return : OK if write byte successfully,or failure *
- * -------------------------------------------------------------------------*/
- LOCAL STATUS i2c_simu_write_byte (struct i2c_simu_dev i2c_dev, UINT8 writeData)
- {
- UINT8 j = 0; /* counter */
-
- /* set GPIO pin direction:output */
- SDA_OUTPUT_ACTIVE(i2c_dev);
- for (j = 0; j < 8; j++)
- {
- SCL_WRITE (i2c_dev, 0);
- I2CDELAY;
- if ((writeData & 0x80) == 0)
- {
- SDA_WRITE (i2c_dev, 0);
- }
- else
- {
- SDA_WRITE (i2c_dev, 1);
- }
- I2CDELAY;
-
- SCL_WRITE (i2c_dev, 1);
- I2CDELAY;
- I2CDELAY;
- writeData <<= 1;
- }
- if (receive_i2c_ack(i2c_dev))
- {
- i2c_stop(i2c_dev);
- return I2C_ERROR_CYCLE_ACKIN;
- }
- return OK;
- }
- void i2cSearch()
- {
- UINT32 i = 0, j = 0, iRc = 0;
- struct i2c_simu_dev i2c_dev;
-
- for(i=4; i<11;i++)
- {
- /* i2c device initial */
- if (i2cDrvInit(i,&i2c_dev) != OK)
- {
- printf("\n[i2c]init failed");
- continue;
- }
- /*
- printf("\ndebug_device=%x",aI2cDevAddr[i]);
- if(!i2c_probe(i2c_dev))
- {
- printf("\ndevice=%x",aI2cDevAddr[i]);
- }
- */
- for(j = 0; j < 128; j++)
- {
- if (i2c_stat_check(i2c_dev) != OK)
- {
- return I2C_ERROR_KNOWN_STATE;
- }
- if (i2c_start(i2c_dev) != OK)
- {
- (void)i2c_stop(i2c_dev);
- return I2C_ERROR_CYCLE_START;
- }
- iRc = (i2c_simu_write_byte(i2c_dev, j<<1) != OK) ? I2C_ERROR_CYCLE_WRITE:OK;
- (void)i2c_stop(i2c_dev);
- if (OK == iRc)
- {
- printf("\ndevice=%x", j<<1);
- }
- }
- }
- }
- /* -------------------------------------------------------------------------*
- * Function : iic_read *
- * Description: Read slave datas from gpio, MSB first *
- * Parameters : i2c device structure,slave address,data buffer to be loaded.*
- * Return : the amount of reading bytes ,or failure *
- * -------------------------------------------------------------------------*/
- STATUS iic_read(struct i2c_simu_dev i2c_dev, UINT32 addr, UINT32 alen, UINT8 *buffer, UINT32 len)
- {
- INT32 shift,iRc;
- i2c_printf("iic_read: chip %02X addr %02X alen %d buffer %p len %d\n",
- i2c_dev.i2cDevAddr, addr, alen, buffer, len);
- /*
- * Do the addressing portion of a write cycle to set the
- * chip's address pointer. If the address length is zero,
- * don't do the normal write cycle to set the address pointer,
- * there is no address pointer in this chip.
- */
- if (i2c_stat_check(i2c_dev) != OK)
- {
- return I2C_ERROR_KNOWN_STATE;
- }
- /* Send the chip address for a read cycle. */
- if(alen > 0)
- {
- if (i2c_start(i2c_dev) != OK)
- {
- (void)i2c_stop(i2c_dev);
- return I2C_ERROR_CYCLE_START;
- }
- /* write slave address */
- if(i2c_simu_write_byte(i2c_dev, i2c_dev.i2cDevAddr))
- { /* write cycle */
- (void)i2c_stop(i2c_dev);
- i2c_printf("iic_read, no chip responded %02X\n", i2c_dev.i2cDevAddr);
- return I2C_ERROR_CYCLE_WRITE;
- }
-
- shift = (alen-1) * 8;
- while(alen-- > 0)
- {
- if(i2c_simu_write_byte(i2c_dev, (addr >> shift)))
- {
- (void)i2c_stop(i2c_dev);
- i2c_printf("iic_read, address not <ACK>ed\n");
- return I2C_ERROR_CYCLE_WRITE;
- }
- shift -= 8;
- }
- i2c_stop(i2c_dev); /* reportedly some chips need a full stop */
- }
- /*
- * Send the chip address again, this time for a read cycle.
- * Then read the data. On the last byte, we do a NACK instead
- * of an ACK(len == 0) to terminate the read.
- */
- if (i2c_start(i2c_dev) != OK)
- {
- (void)i2c_stop(i2c_dev);
- return I2C_ERROR_CYCLE_START;
- }
-
- if(i2c_simu_write_byte(i2c_dev, ((i2c_dev.i2cDevAddr) | 1)))
- {
- (void)i2c_stop(i2c_dev);
- return I2C_ERROR_CYCLE_WRITE;
- }
-
- iRc = (i2c_simu_read_byte(i2c_dev, buffer,len) == len) ? OK : ERROR;
- (void)i2c_stop(i2c_dev);
- return iRc;
-
- }
- /*-----------------------------------------------------------------------
- * Write bytes
- */
- /* -------------------------------------------------------------------------*
- * Function : iic_write *
- * Description: Send the bytes out to gpio, MSB first. *
- * Parameters : i2c device structure,slave address,data to be shifted. *
- * Return : OK if write bytes successfully,or failure times *
- * -------------------------------------------------------------------------*/
- STATUS iic_write(struct i2c_simu_dev i2c_dev, UINT32 addr, UINT32 alen, UINT8 *buffer, UINT32 len)
- {
- INT32 shift,failures = 0;
- i2c_printf("iic_write: chip %02X addr %02X alen %d buffer %p len %d\n",
- i2c_dev.i2cDevAddr, addr, alen, buffer, len);
- if (i2c_stat_check(i2c_dev) != OK)
- {
- return I2C_ERROR_KNOWN_STATE;
- }
- if (i2c_start(i2c_dev) != OK)
- {
- (void)i2c_stop(i2c_dev);
- return I2C_ERROR_CYCLE_START;
- }
-
- if (i2c_simu_write_byte(i2c_dev, i2c_dev.i2cDevAddr) != OK)
- {
- (void)i2c_stop(i2c_dev);
- i2c_printf("iic_write, no chip responded %02X\n", i2c_dev.i2cDevAddr);
- return I2C_ERROR_CYCLE_START;
- }
-
- shift = (alen-1) * 8;
- while(alen-- > 0)
- {
- if(i2c_simu_write_byte(i2c_dev, (addr >> shift)))
- {
- (void)i2c_stop(i2c_dev);
- i2c_printf("iic_write, address not <ACK>ed\n");
- return I2C_ERROR_CYCLE_WRITE;
- }
- shift -= 8;
- }
- while(len-- > 0)
- {
- if(i2c_simu_write_byte(i2c_dev, *buffer++))
- {
- failures--;/* negative value */
- }
- }
- i2c_stop(i2c_dev);
- return(failures);
- }
2.i2cDevices.c
- #include <vxWorks.h>
- #include <stdio.h>
- #include <semLib.h>
- #include "i2cbussimu.h"
- #include "i2cDevices.h"
- #include "bsp.h"
- #define AT24C02_BUF_LEN 0x8
- #define MIN(a,b) ((a) < (b) ? (a) : (b))
- #define i2c_debug 0
- #define i2c_printf(fmt,arg...) {if(i2c_debug)printf(fmt,##arg);}
- extern SEM_ID i2cMutex;
- extern void sysUsDelay(int delay);
- LOCAL int at24c02_read(struct i2c_simu_dev i2c_dev,void *dst, UINT32 src,int cnt)
- {
- if(((int)src+cnt>0x100) || (cnt<0)||(dst == 0))
- {
- return ERROR;
- }
- if(iic_read(i2c_dev,src,1,(UINT8 *)dst,cnt)!=OK)
- {
- return ERROR;
- }
- return cnt;
- }
- LOCAL int progDone(INT32 i2c_dev_addr, INT32 dummy)
- {
- return (!i2c_probe(*((struct i2c_simu_dev *)i2c_dev_addr)));
- }
- LOCAL int at24c02_write(struct i2c_simu_dev i2c_dev, UINT32 offset,void *buffer,int byteCnt)
- {
- UINT32 dst,src,cnt;
- int iRc;
- dst = offset;
- src = (UINT32)buffer;
- iRc = byteCnt;
- do{
- cnt = MIN(AT24C02_BUF_LEN-((UINT32)dst & (AT24C02_BUF_LEN-1)),byteCnt);
- if((OK != iic_write(i2c_dev,dst,1,(UINT8 *)src,cnt)) ||
- (OK != sysUsDelayPoll(20000, progDone,(INT32)&i2c_dev,0))) /* Self-timed Write Cycle (12 ms Max) */
- {
- return ERROR;
- }
- dst += cnt;
- src += cnt;
- byteCnt -= cnt;
- }while(byteCnt>0);
- return iRc;
- }
- /*
- @devNum: device number for FPH800H from 0 to 11
- @cmd: IIC_READ or IIC_WEITW
- @offset:I2C device register address
- @buffer :buffer address provided by user
- @bufLen: the length of buffer
- */
- UINT32 i2c_dev_access (UINT32 devNum,UINT32 cmd, UINT32 offset, void *buffer, UINT32 bufLen)
- {
- UINT8 i2cDevAddr;
- int alen,iRc=0;
- if(devNum < I2C_MB_EEPROM || devNum > I2C_SFP1_FB || !(cmd == I2C_READ || cmd == I2C_WRITE) || !buffer )
- {
- return ERROR;
- }
-
- i2c_printf("\n[i2c]begin,DevNum=%d,cmd=%d,offset=%d,buffer=0x%x,bufLen=%d",
- devNum, cmd, offset,(int)buffer, bufLen);
- if(i2cMutex)
- {
- semTake (i2cMutex,WAIT_FOREVER);
- }
- struct i2c_simu_dev i2c_dev;
-
- /* i2c device initial */
- if (i2cDrvInit(devNum,&i2c_dev) != OK)
- {
- i2c_printf("\n[i2c]init failed");
- goto IIC_END;
- }
- /* Get the register address length */
- alen = 1; /* currently, It seems that the length of address is 1 byte */
- if (cmd == I2C_READ)
- {
- if(devNum == I2C_MB_EEPROM)
- {
- iRc = at24c02_read(i2c_dev,(void *)buffer,offset,bufLen); /* error or count */
- }
- else
- {
- iRc = iic_read(i2c_dev,offset,alen,buffer,bufLen); /* OK or error */
- }
- }
- else /* cmd == IIC_WRITE */
- {
- if(devNum == I2C_MB_EEPROM)
- {
- iRc = at24c02_write(i2c_dev,offset,(void *)buffer,bufLen); /* error or count */
- }
- else
- {
- iRc = iic_write(i2c_dev,offset,alen,buffer,bufLen);/*OK or negative count */
- }
- }
- IIC_END:
- if(i2cMutex)
- {
- semGive (i2cMutex);
- }
- i2c_printf("\n[i2c]end, iRc=0x%X",iRc);
-
- return iRc;
- }
|