⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 csbi2c.c

📁 umon bootloader source code, support mips cpu.
💻 C
字号:
//==========================================================================
//
//      i2c.c
//
// Author(s):   Michael Kelly - Cogent Computer Systems, Inc.
// Date:        07/22/2002
// Description:	Generic bit banging I2C routines
//
//==========================================================================

#include "config.h"
#include "cpuio.h"
#include "genlib.h"
#include "stddefs.h"
#include "cpu_i2c.h"
#include "i2c.h"

//--------------------------------------------------------------------------
// The following low level I2C macros must be defined for this file
//
// examples from CSB250 cpuio.h
// #define I2C_SCL_CLR		GPIO_out(GPIO_SCL)	// puts 0 on pin
// #define I2C_SCL_SET		GPIO_in(GPIO_SCL)	// releases pin to be pulled high
// #define I2C_SDA_CLR		GPIO_out(GPIO_SDA)	// puts 0 on pin		
// #define I2C_SDA_SET		GPIO_in(GPIO_SDA)	// releases pin to be pulled high		
// #define I2C_SCL_RD		GPIO_tst(GPIO_SCL)	// return state of pin
// #define I2C_SDA_RD		GPIO_tst(GPIO_SDA)
// #define I2C_DELAY 		udelay(100)

//--------------------------------------------------------------------------
// function prototypes
//
ulong i2c_init(void);
ulong i2c_wr_device(uchar dev, uchar reg, uchar data);
ulong i2c_rd_device(uchar dev, uchar reg, uchar *data);
ulong i2c_wr_byte(uchar data);
uchar i2c_rd_byte(void);
void i2c_start(void);
void i2c_stop(void);

extern void udelay(int delay);
extern int GPIO_set(int);
extern int GPIO_clr(int);
extern int GPIO_in(int);
extern int GPIO_out(int);
extern int GPIO_tst(int);

//--------------------------------------------------------------------------
// i2c_wr_device()
//
// This function writes an 8-bit value to the I2C device at the requested
// register.
//
ulong i2c_wr_device(uchar dev, uchar reg, uchar data)
{

	// issue a start command
	i2c_start();

	// write the 7-bit device address with write = 0
	if(i2c_wr_byte((dev << 1) & 0xfe)){
		return -1;
	}
	// Write the 8-bit register address
	if(i2c_wr_byte(reg)){
		return -1;
	}
	// Write the 8-bit data value
	if(i2c_wr_byte(data)){
		return -1;
	}

	// issue a stop
	i2c_stop();
	
	return 0;
}

//--------------------------------------------------------------------------
// i2c_rd_device()
//
// This function reads an 8-bit value from the I2C device at the requested
// register.
//
ulong i2c_rd_device(uchar dev, uchar reg, uchar *data)
{

	// issue a start command
	i2c_start();

	// write the 7-bit device address with write = 0
	if(i2c_wr_byte((dev << 1) & 0xfe)){
		return -1;
	}
	// Write the 8-bit register address
	if(i2c_wr_byte(reg)){
		return -1;
	}
	// repeat the start command
	i2c_start();
	// write the 7-bit device address again plus data direction (read = 1)
	if(i2c_wr_byte((dev << 1) | 0x01)){
		return -1;
	}
	*data = i2c_rd_byte();

	// issue a stop
	i2c_stop();

	return 0;
}

//--------------------------------------------------------------------------
// i2c_wr_byte()
//
// This function writes an 8-bit value to the I2C bus, MSB first.
// Data is written by changing SDA during SCL low, then bringing
// SCL high.  SCL is returned low to setup for the next transition.
//
ulong i2c_wr_byte(uchar data)
{

	int i;

	for (i = 0; i < 8; i++){
		if (data & 0x80) {
			// write a 1 bit
			I2C_SDA_SET;
			I2C_DELAY;
			I2C_SCL_SET;
			I2C_DELAY;
			I2C_SCL_CLR;
			I2C_DELAY;
		}
		else {
			// write a 0 bit
			I2C_SDA_CLR;
			I2C_DELAY;
			I2C_SCL_SET;
			I2C_DELAY;
			I2C_SCL_CLR;
			I2C_DELAY;
		}
		data = data << 1;
	}
	// Release SDA, bring SCL high, then read SDA.
	// A low indicates an acknowledge.
	I2C_SDA_SET;
	I2C_DELAY;
   	I2C_SCL_SET;
	I2C_DELAY;
	if(I2C_SDA_RD){	// a high means no ack
		// re-enable SDA for output
	   	I2C_SCL_CLR;
		I2C_DELAY;
		return -1;
	}

   	I2C_SCL_CLR;
	I2C_DELAY;

	return 0;
}

//--------------------------------------------------------------------------
// i2c_rd_byte()
//
// This function reads an 8-bit data value from the I2C bus, MSB first. 
// Data is read from SDA after each low to high SCL transition.
//
uchar i2c_rd_byte()
{

	int i;
	uchar volatile data;

	data = 0;

	for (i = 0; i < 8; i++){
		data = data << 1;
		data = data & 0xfe;
		// clock the data out of the slave
		I2C_SCL_SET;
		I2C_DELAY;
		// check it
		if (I2C_SDA_RD){
			data = data | 0x01;
		}
		I2C_SCL_CLR;
		I2C_DELAY;
	}
	// generate an extra SCL transition
	// The slave generates no acknowledge for reads.
	I2C_SCL_SET;
	I2C_DELAY;
	I2C_SCL_CLR;
	I2C_DELAY;

	return data;
}


//--------------------------------------------------------------------------
// i2c_start()
//
// This function issues an I2C start command which is a high to low
// transition on SDA while SCL is high.
//
void i2c_start()
{

	I2C_SDA_SET;
	I2C_DELAY;
   	I2C_SCL_SET;
	I2C_DELAY;
   	I2C_SDA_CLR;
	I2C_DELAY;
   	I2C_SCL_CLR;
	I2C_DELAY;
	I2C_SDA_SET;
	I2C_DELAY;
}

//--------------------------------------------------------------------------
// i2c_stop()
//
// This function issues an I2C stop command which is a low to high
// transition on SDA while SCL is high.
//
void i2c_stop()
{
	I2C_SDA_CLR;
	I2C_DELAY;
	I2C_SCL_SET;
	I2C_DELAY;
	I2C_SDA_SET;
	I2C_DELAY;
	I2C_SCL_CLR;
	I2C_DELAY;
}

/* The following three fucntions have been added to hook into
 * the MicroMonitor's I2C command.
 */
int
i2cCtrl(int interface, int cmd, unsigned long arg1, unsigned long arg2)
{
	int	rslt;

	rslt = 0;
	switch(cmd) {
		case I2CCTRL_INIT:
			i2c_init();
			break;
		case I2CCTRL_SHOW:
			i2cShow(0);	/* target-specific */
			break;
		default:
			rslt = -1;
			break;
	}
	return(rslt);
}

/* i2cRead():
 * For general information, see notes in common/monitor/i2c.h.
 *
 * If len is greater than 1, just do a loop.  We don't support
 * burst (multiple reads within one START/STOP) here.
 */
int
i2cRead(int interface,int bigaddr,unsigned char *data,int len)
{
	int	i;
#if 0
	/* If the REPEATED_START bit is set in the address, then we
	 * do a write prior to the read.
	 */ 
	if (bigaddr & REPEATED_START) {
		i2c_start();
		if(i2c_wr_byte(*(data+1)))
			return(-1);
	}
#endif
	/* Steps for each iteration of the loop:
	 * 1. Issue start
	 * 2. Write 7-bit device address and direction bit = 1 (read)
	 * 3. Retrieve byte
	 * 4. Issue stop.
	 */
	for(i=0;i<len;i++) {
		i2c_start();

		if(i2c_wr_byte(((uchar)bigaddr << 1) | 0x01))
			return(-2);

		*data = i2c_rd_byte();

		i2c_stop();
	}

	return(len);
}

int
i2cWrite(int interface,int bigaddr,unsigned char *data,int len)
{
	int	i;

	/* Steps for each iteration of the loop:
	 * 1. Issue a start command
	 * 2. Write 7-bit device address with direction bit = 0 (write)
	 * 3. Write the 8-bit data value.
	 * 4. Issue stop.
	 */
	for(i=0;i<len;i++) {
		i2c_start();

		if(i2c_wr_byte(((uchar)bigaddr << 1) & 0xfe))
			return(-2);

		if(i2c_wr_byte(*data))
			return(-3);

		i2c_stop();
	}
	
	return(1);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -