i2c_prom.c
来自「ESS3890+SL原代码(1*16内存)」· C语言 代码 · 共 774 行 · 第 1/2 页
C
774 行
/* SCCSID @(#)i2cdrv.h 1.9 03/14/01 */#ifdef I2C_E2PROM/* Header Files */#include "mvd.h"#include "common.h"#include "util.h"#include "ioport.h"#include "debug.h"#include "sysinfo.h"/****************************************************************** Global Function Declarations.*******************************************************************/int I2C_config(int dev_addr, void (*SCL_set)(int), void (*SDA_set)(int), int (*SCL_sense)(), int (*SDA_sense)(), int *time_array);int I2C_bytewrite(int, int, uchar);int I2C_ackpolling(int);int I2C_byteread(int, int );uchar EepromErr;/****************************************************************** Global Variables.*******************************************************************//****************************************************************** Global Function Declarations.*******************************************************************/int I2C_PROM_init(); /* Configure parameters */int i2c_e2prom_bywrite(uchar, uchar);int i2c_e2prom_byread(uchar);#if EEPROM_TESTvoid I2C_driver_test(int mode); /* for debug */#endif/******************************************************************* IC2_E2PROM Constant Declaration******************************************************************//******************************************************************* Note:* If there are the value 'zj' in the first 2 byte of E2PROM, it means* that E2PROM has been initialized, then we should read out stored values* and use them.**********************************************************************/ /****************************************************************** This is a single generic I2C driver with api.*******************************************************************//****************************************************************** Various Defines.*******************************************************************/#define CHEAT #ifndef PRINTF#define PRINTF(x)#endif#define I2C_DEV_MAX 3 /* maximum no. of device */#define TRY_COUNT 5 /* retry if no ack */#define I2C_TIME_NUM 13 /* total no. of time config */#define UPLIMIT (0x80000000/(3*CPUCLK)) /* for ackpolling *///#define wait_timer(x) risc_sleep_a_bit(x) /* waiting time *//* device specification */typedef struct { int dev_addr; /* device I2C address */ void (*SCL_set)(int); /* SCL_set fn ptr */ void (*SDA_set)(int); /* SDA_set fn ptr */ int (*SCL_sense)(); /* SCL_sense fn ptr */ int (*SDA_sense)(); /* SDA_sense fn ptr */ /* timing info */ int tAA; /* SCL Low to SDA Data Out Valid. */ int tBUF; /* Time the Bus Must be Free before a New Transmission Can Start. */ int tHD_STA; /* Start Condition Hold Time. */ int tSU_STA; /* Start Condition Setup Time (for a Repeated Start Condition). */ int tLOW; /* Clock Low Time. */ int tHIGH; /* Clock High Time. */ int tHD_DAT; /* Data In Hold Time. */ int tSU_DAT; /* Data In Setup Time. */ int tR; /* SDA and SCL Rise Time. */ int tF; /* SDA and SCL Fall Time. */ int tSU_STO; /* Stop Condition Setup Time. */ int tDH; /* Data Out Hold Time. */ int tWR; /* Write Cycle Time. */ /* timeout periods */ int poll_wtime; /* ack-polling timeout */ int ack_wtime; /* ack timeout */} IIC_CONFIG;/****************************************************************** Variables.*******************************************************************/static IIC_CONFIG i2c_dev[I2C_DEV_MAX]; /* device parameters */ static int i2c_dev_num = -1; /* device id used so far */static int timeout = 0; /* acknowledge timeout */static int need_to_stop = 0; /* stop if no ack *//* for debug */static int yes_ack = 0;static int no_ack = 0;/****************************************************************** Local Function Declarations.*******************************************************************/static void i2c_raise_scl(IIC_CONFIG *cptr);static void i2c_start(IIC_CONFIG *cptr); /* start condition */static void i2c_stop(IIC_CONFIG *cptr); /* stop condition */static void i2c_writebyte(IIC_CONFIG *cptr, uchar c);static int i2c_ack(IIC_CONFIG *cptr, int mode);static uchar i2c_readbyte(IIC_CONFIG *cptr);/****************************************************************** Function Definitions (Local and Global).*******************************************************************//**************************************************** Set up i2c parameters for each device and assign a device id. arguments: dev_addr i2c device address SCL_set function to toggle SCL pin SDA_set function to toggle SDA pin SCL_sense function to sense SCL pin SDA_sense function to sense SDA pin *time_array devicetiming info return: dev_id device id assigned *****************************************************/int I2C_config( int dev_addr, void (*SCL_set)(int), void (*SDA_set)(int), int (*SCL_sense)(), int (*SDA_sense)(), int *time_array){ int i; int *p; IIC_CONFIG *cptr; PRINTF(( "I2C_config 0x%x\n", dev_addr )); i2c_dev_num=1;#if 0 i2c_dev_num++; if (i2c_dev_num >= I2C_DEV_MAX) { EPRINTF(("I2C_config: exceed max no. of devices!\n")); return(-1); }#endif /* configure device parameters */ cptr = i2c_dev + i2c_dev_num; cptr->dev_addr = dev_addr; cptr->SCL_set = SCL_set; cptr->SDA_set = SDA_set; cptr->SCL_sense = SCL_sense; cptr->SDA_sense = SDA_sense; p = &(cptr->tAA); /* ptr to the first timing parameter */ for (i = 0; i < I2C_TIME_NUM; i++) /* load timing parameters */ *(p++) = *(time_array++); /* calculate wait time for I2C_ackpolling */ if (cptr->tWR >= UPLIMIT) cptr->poll_wtime = 3 * ((cptr->tWR)/10000) * CPUCLK; /* if tWR is large */ else cptr->poll_wtime = 3 * (cptr->tWR) * CPUCLK / 10000; /* calculate wait time for i2c_ack */ cptr->ack_wtime = (cptr->tHIGH) * CPUCLK / 10000; /* To confirm the device */ for (i=0; i<TRY_COUNT; i++) { timeout = 0; // wait_timer(cptr->tBUF); i2c_start(cptr); i2c_writebyte(cptr, cptr->dev_addr); i2c_stop(cptr); // wait_timer(cptr->tWR); if (!timeout) return(i2c_dev_num); } i2c_dev_num--; return (-1);}/**************************************************** Write a byte to the i2c device specified by its device id. arguments: dev_id device id addr address to be written ( ignore if < 0 ) data data to be written return: 0 okay (got ack) -1 error (no ack) *****************************************************/int I2C_bytewrite(int dev_id, int addr, uchar data){ int i; uchar w_addr = (uchar)(addr & 0xff); IIC_CONFIG *cptr; /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (i = 0; i < TRY_COUNT; i++) { /* try again if no ack */ timeout = 0; /* reset timeout */ // wait_timer(cptr->tBUF); /* bus free time: // both SCL and SDA are high */ i2c_start(cptr); /* start condition */ i2c_writebyte(cptr, cptr->dev_addr); /* control byte */ if( addr >= 0 ) { i2c_writebyte(cptr, w_addr); /* word address */ } i2c_writebyte(cptr, data); /* data */ i2c_stop(cptr); /* stop condition */#ifndef CHEATq // wait_timer(cptr->tWR); /* write cycle time */#endif if (!timeout) return(0); } return(-1); /* timeout without acknowledge after several attempts */} /**************************************************** Read a byte from the i2c device specified by its device id. arguments: dev_id device id addr address to be read (ignore if < 0 ) return: >= 0 data read -1 error (no ack)*****************************************************/int I2C_byteread(int dev_id, int addr){ int i; uchar b; uchar w_addr = (uchar)(addr & 0xff); IIC_CONFIG *cptr; /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (i = 0; i < TRY_COUNT; i++) { /* try again if no ack */ timeout = 0; /* reset timeout */ // wait_timer(cptr->tBUF); /* bus free time: // both SCL and SDA are high */ if( addr >= 0 ) { i2c_start(cptr); /* start condition */ i2c_writebyte(cptr, cptr->dev_addr); /* control byte: for write */ i2c_writebyte(cptr, w_addr); /* word address */ } i2c_start(cptr); /* start condition */ i2c_writebyte(cptr, (cptr->dev_addr) | 0x01); /* control byte: for read */ b = i2c_readbyte(cptr); /* read one byte of data */ /* ack clock cycle: no ack is needed for read */ i2c_ack(cptr, 0); i2c_stop(cptr); /* stop condition */ if (!timeout) return(b); /* data read */ } return(-1); /* timeout without acknowledge after several attempts */}/**************************************************** Acknowledge polling to see if the write cycle is finished or not. arguments: dev_id device id return: 1 device acknowledge 0 device not acknowledge*****************************************************/int I2C_ackpolling(int dev_id){ int tmp, stime; IIC_CONFIG *cptr; /* ptr to device parameters */ cptr = i2c_dev + dev_id; stime = mvd[riface_timer2]; while (1) { /* polling */ timeout = 0; // wait_timer(cptr->tBUF); i2c_start(cptr); i2c_writebyte(cptr, cptr->dev_addr); need_to_stop = 0; /* reset the flag after one attempt */ if (!timeout) { /* got ack */ return(1); }else { /* no ack */ tmp = mvd[riface_timer2] - stime; if (tmp < 0) tmp += -timer2_period; if (tmp >= cptr->poll_wtime) { return(0); /* no ack (exit after timeout) */ } }// AUD_service(); // cf }}/* * Local Functions *//**************************************************** set and wait till scl is really high. arguments: *cptr ptr to the current device parameters. return:*****************************************************/static void i2c_raise_scl(IIC_CONFIG *cptr){ int tmp; int ack_starttime; int k = -1; cptr->SCL_set(1); /* SCL TRISTATE_EAUX18 */ ack_starttime = mvd[riface_timer2]; /* ack start time */ while (1) { // wait hi if (cptr->SCL_sense()){ break; //return; // }else { k = -1; tmp = mvd[riface_timer2] - ack_starttime; if (tmp < 0) tmp += -timer2_period; if (tmp >= cptr->ack_wtime) { //16C timeout++; no_ack++; break; /* acknowledge timeout */ } } }}/**************************************************** I2C start condition. arguments: *cptr ptr to the current device parameters. return:*****************************************************/static void i2c_start(IIC_CONFIG *cptr){ if (!need_to_stop) { cptr->SDA_set(1); /*1 SDA 1 */#ifndef CHEAT // wait_timer(cptr->tLOW); /* SCL low time */#endif i2c_raise_scl(cptr); /*2 SCL high */ // wait_timer((cptr->tR)+(cptr->tSU_STA)); /* SCL rise time + start condition setup time */ cptr->SDA_set(0); /*3 SDA low */ // wait_timer((cptr->tF)+(cptr->tHD_STA)); /* SDA fall time + start condition hold time */ cptr->SCL_set(0); /*4 SCL low */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?