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

📄 i2c.c

📁 Linux2.4.27在AT91RM9200下的U-BOOT代码。可以在Redhat9等版本下使用。适合ARM学习者使用。
💻 C
字号:
#include <common.h>#include <mpc8xx.h>#include <malloc.h>#include <galileo/gt64260R.h>#include <galileo/core.h>#define MAX_I2C_RETRYS	    10#define I2C_DELAY	    1000  /* Should be at least the # of MHz of Tclk */#undef	DEBUG_I2C#ifdef DEBUG_I2C#define DP(x) x#else#define DP(x)#endif/* Assuming that there is only one master on the bus (us) */static voidi2c_init(int speed, int slaveaddr){	unsigned int n, m, freq, margin, power;	unsigned int actualFreq, actualN=0, actualM=0;	unsigned int control, status;	unsigned int minMargin = 0xffffffff;	unsigned int tclk = 125000000;	DP(puts("i2c_init\n"));	for(n = 0 ; n < 8 ; n++)	{		for(m = 0 ; m < 16 ; m++)		{			power = 2<<n; /* power = 2^(n+1) */			freq = tclk/(10*(m+1)*power);			if (speed > freq)				margin = speed - freq;			else				margin = freq - speed;			if(margin < minMargin)			{				minMargin   = margin;				actualFreq  = freq;				actualN	    = n;				actualM	    = m;			}		}	}	DP(puts("setup i2c bus\n"));	/* Setup bus */	GT_REG_WRITE(I2C_SOFT_RESET, 0);	DP(puts("udelay...\n"));	udelay(I2C_DELAY);	DP(puts("set baudrate\n"));	GT_REG_WRITE(I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN);	GT_REG_WRITE(I2C_CONTROL, (0x1 << 2) | (0x1 << 6));	udelay(I2C_DELAY * 10);	DP(puts("read control, baudrate\n"));	GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);	GT_REG_READ(I2C_CONTROL, &control);}static uchari2c_start(void){	unsigned int control, status;	int count = 0;	DP(puts("i2c_start\n"));	/* Set the start bit */	GT_REG_READ(I2C_CONTROL, &control);	control |= (0x1 << 5);	GT_REG_WRITE(I2C_CONTROL, control);	GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);	count = 0;	while ((status & 0xff) != 0x08) {		udelay(I2C_DELAY);		if (count > 20) {			GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/			return (status);		}		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);		count++;	}	return (0);}static uchari2c_select_device(uchar dev_addr, uchar read, int ten_bit){	unsigned int status, data, bits = 7;	int count = 0;	DP(puts("i2c_select_device\n"));	/* Output slave address */	if (ten_bit) {		bits = 10;	}	data = (dev_addr << 1);	/* set the read bit */	data |= read;	GT_REG_WRITE(I2C_DATA, data);	/* assert the address */	RESET_REG_BITS(I2C_CONTROL, BIT3);	udelay(I2C_DELAY);	GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);	count = 0;	while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) {		udelay(I2C_DELAY);		if (count > 20) {			GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/			return(status);		}		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);		count++;	}	if (bits == 10) {		printf("10 bit I2C addressing not yet implemented\n");		return (0xff);	}	return (0);}static uchari2c_get_data(uchar* return_data, int len) {	unsigned int data, status;	int count = 0;	DP(puts("i2c_get_data\n"));	while (len) {		/* Get and return the data */		RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));		udelay(I2C_DELAY * 5);		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);		count++;		while ((status & 0xff) != 0x50) {			udelay(I2C_DELAY);			if(count > 2) {				GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/				return 0;			}			GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);			count++;		}		GT_REG_READ(I2C_DATA, &data);		len--;		*return_data = (uchar)data;		return_data++;	}	RESET_REG_BITS(I2C_CONTROL, BIT2|BIT3);	while ((status & 0xff) != 0x58) {		udelay(I2C_DELAY);		if(count > 200) {			GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/			return (status);		}		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);		count++;	}	GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /* stop */	return (0);}static uchari2c_write_data(unsigned int data, int len){	unsigned int status;	int count = 0;	DP(puts("i2c_write_data\n"));	if (len > 4)		return -1;	while (len) {		/* Set and assert the data */		GT_REG_WRITE(I2C_DATA, (unsigned int)data);		RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));		udelay(I2C_DELAY);		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);		count++;		while ((status & 0xff) != 0x28) {			udelay(I2C_DELAY);			if(count > 20) {				GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/				return (status);			}			GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);			count++;		}		len--;	}	GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4));	GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));	udelay(I2C_DELAY * 10);	return (0);}static uchari2c_set_dev_offset(uchar dev_addr, unsigned int offset, int ten_bit){	uchar status;	DP(puts("i2c_set_dev_offset\n"));	status = i2c_select_device(dev_addr, 0, ten_bit);	if (status) {#ifdef DEBUG_I2C		printf("Failed to select device setting offset: 0x%02x\n",		       status);#endif		return status;	}	status = i2c_write_data(offset, 1);	if (status) {#ifdef DEBUG_I2C		printf("Failed to write data: 0x%02x\n", status);#endif		return status;	}	return (0);}uchari2c_read(uchar dev_addr, unsigned int offset, int len, uchar* data,	 int ten_bit){	uchar status = 0;	unsigned int i2cFreq = 400000;	DP(puts("i2c_read\n"));	i2c_init(i2cFreq,0);	status = i2c_start();	if (status) {#ifdef DEBUG_I2C		printf("Transaction start failed: 0x%02x\n", status);#endif		return status;	}	status = i2c_set_dev_offset(dev_addr, 0, 0);	if (status) {#ifdef DEBUG_I2C		printf("Failed to set offset: 0x%02x\n", status);#endif		return status;	}	i2c_init(i2cFreq,0);	status = i2c_start();	if (status) {#ifdef DEBUG_I2C		printf("Transaction restart failed: 0x%02x\n", status);#endif		return status;	}	status = i2c_select_device(dev_addr, 1, ten_bit);	if (status) {#ifdef DEBUG_I2C		printf("Address not acknowledged: 0x%02x\n", status);#endif		return status;	}	status = i2c_get_data(data, len);	if (status) {#ifdef DEBUG_I2C		printf("Data not recieved: 0x%02x\n", status);#endif		return status;	}	return 0;}

⌨️ 快捷键说明

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