Chinaunix首页 | 论坛 | 博客
  • 博客访问: 493951
  • 博文数量: 174
  • 博客积分: 2502
  • 博客等级: 少校
  • 技术积分: 1923
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-28 09:47
文章分类

全部博文(174)

文章存档

2011年(8)

2010年(16)

2009年(68)

2008年(82)

我的朋友

分类: 嵌入式

2010-03-29 20:09:15

在嵌入式中,I2C设备的使用比较广泛,U-Boot集成了i2c的操作函数及命令。如下
> help i2c
i2c speed [speed] - show or set I2C bus speed
i2c dev [dev] - show or set current I2C bus
i2c md chip address[.0, .1, .2] [# of objects] - read from I2C device
i2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing)
i2c mw chip address[.0, .1, .2] value [count] - write to I2C device (fill)
i2c nm chip address[.0, .1, .2] - write to I2C device (constant address)
i2c crc32 chip address[.0, .1, .2] count - compute CRC32 checksum
i2c probe - show devices on the I2C bus
i2c reset - re-init the I2C Controller
i2c loop chip address[.0, .1, .2] [# of objects] - looping read of device
i2c sdram chip - print SDRAM configuration information

> i2c dev   // 查看当前的i2c总线
Current bus is 1
> iprobe   // i2c设备地址探测
Valid chip addresses: 51 68
Excluded chip addresses: 20 21 38 39
> imd 0x51 0.0  // 读i2c设备
0000: 08 07 0d 0a 01 40 00 04 50 70 00 82 10 00 01 0e    ......

 
Freescale的PowerPC芯片MPC8349E内部集成了两个i2c控制器,在MPC8349E-mITX开发板中用控制器I2C1连接M24256-BWMN6P
(i2c eeprom芯片,256kB大小),用I2C2连接了PCF8574(0x20, 0x21), DS1339U-33 RTC(0x39), DDR SPD eeprom(0x51)等。
其中M24256-BWMN6P这个i2c eeprom可以用来存储硬复位配置字HRCW,作为PowerPC启动时的复位配置字源。
一开始在板子上操作iprobe命令时,发现始终读写不了设备地址0x50,后来看了一下U-Boot实现i2c eeprom写HRCW的实现,
才明白iprobe命令是和i2c当前总线控制器有关,它只探测当前总线上的i2c设备。通过如下命令可以进行总线控制器的设置

> i2c dev 0
Setting bus to 0
> iprobe
Valid chip addresses: 50
Excluded chip addresses:
> imd 0x50 .2 17  // 从i2c eeprom的起始地址0开始开始读17个对象,等同于imd 0x50 0.2 17
0000: aa 55 aa 7c 02 40 04 04 00 00 7c 02 41 b4 60 a0    .`.
0010: 00 ff ff ff ff ff ff    .......
> imm 0x50 .2
00000000: ff ? aa
00000001: ff ? .
> isdram 0x51
SPD data revision            1.1
Bytes used                   0x80
Serial memory size           0x100
.....

在u-boot代码中如下实现HRCW对I2C EEPROM的写入。
// board/freescale/mpc8349itx/mpc8349itx.c
242 /*
243  * Miscellaneous late-boot configurations
244  *
245  * Make sure the EEPROM has the HRCW correctly programmed.
246  * Make sure the RTC is correctly programmed.
247  *
248  * The MPC8349E-mITX can be configured to load the HRCW from
249  * EEPROM instead of flash.  This is controlled via jumpers
250  * LGPL0, 1, and 3.  Normally, these jumpers are set to 000 (all
251  * jumpered), but if they're set to 001 or 010, then the HRCW is
252  * read from the "I2C EEPROM".
253  *
254  * This function makes sure that the I2C EEPROM is programmed
255  * correctly.
256  *
258  */
259 int misc_init_r(void)   // 此函数在lib_ppc/board.c的board_init_r()中被调用
260 {
261     int rc = 0;
262
263 #ifdef CONFIG_HARD_I2C
264
265     unsigned int orig_bus = i2c_get_bus_num();
266     u8 i2c_data;
267
268 #ifdef CONFIG_SYS_I2C_RTC_ADDR
269     u8 ds1339_data[17];
270 #endif
271
272 #ifdef CONFIG_SYS_I2C_EEPROM_ADDR
273     static u8 eeprom_data[] =   /* HRCW data */
274     {
275         0xAA, 0x55, 0xAA,       /* Preamble */
276         0x7C,               /* ACS=0, BYTE_EN=1111, CONT=1 */
277         0x02, 0x40,         /* RCWL ADDR=0x0_0900 */
278         (CONFIG_SYS_HRCW_LOW >> 24) & 0xFF,
279         (CONFIG_SYS_HRCW_LOW >> 16) & 0xFF,
280         (CONFIG_SYS_HRCW_LOW >> 8) & 0xFF,
281         CONFIG_SYS_HRCW_LOW & 0xFF,
282         0x7C,               /* ACS=0, BYTE_EN=1111, CONT=1 */
283         0x02, 0x41,         /* RCWH ADDR=0x0_0904 */
284         (CONFIG_SYS_HRCW_HIGH >> 24) & 0xFF,
285         (CONFIG_SYS_HRCW_HIGH >> 16) & 0xFF,
286         (CONFIG_SYS_HRCW_HIGH >> 8) & 0xFF,
287         CONFIG_SYS_HRCW_HIGH & 0xFF
288     };
289
290     u8 data[sizeof(eeprom_data)];
291 #endif
292
293     printf("Board revision: ");
294     i2c_set_bus_num(1);
295     if (i2c_read(CONFIG_SYS_I2C_8574A_ADDR2, 0, 0, &i2c_data, sizeof(i2c_data)) == 0)
296         printf("%u.%u (PCF8475A)\n", (i2c_data & 0x02) >> 1, i2c_data & 0x01);
297     else if (i2c_read(CONFIG_SYS_I2C_8574_ADDR2, 0, 0, &i2c_data, sizeof(i2c_data)) == 0)
298         printf("%u.%u (PCF8475)\n",  (i2c_data & 0x02) >> 1, i2c_data & 0x01);
299     else {
300         printf("Unknown\n");
301         rc = 1;
302     }
303
304 #ifdef CONFIG_SYS_I2C_EEPROM_ADDR
305     i2c_set_bus_num(0);
306
307     if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2, data, sizeof(data)) == 0) {
308         if (memcmp(data, eeprom_data, sizeof(data)) != 0) {
309             if (i2c_write
310                 (CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2, eeprom_data,
311                  sizeof(eeprom_data)) != 0) {
312                 puts("Failure writing the HRCW to EEPROM via I2C.\n");
313                 rc = 1;
314             }
315         }
316     } else {
317         puts("Failure reading the HRCW from EEPROM via I2C.\n");
318         rc = 1;
319     }
320 #endif
321
322 #ifdef CONFIG_SYS_I2C_RTC_ADDR
323     i2c_set_bus_num(1);
    // ... skip
378 #endif
379
380     i2c_set_bus_num(orig_bus);
381 #endif
391     return rc;
392 }

读写函数说明:
int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len);
int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len);
/*
 * Read/Write interface:
 *   chip:    I2C chip address, range 0..127
 *   addr:    Memory (register) address within the chip
 *   alen:    Number of bytes to use for addr (typically 1, 2 for larger
 *              memories, 0 for register type devices with only one
 *              register)
 *   其中alen 为1,说明chip是8bit的, 为2则是 16bit的。
 *   buffer:  Where to read/write the data
 *   len:     How many bytes to read/write
 *
 *   Returns: 0 on success, not 0 on failure
 */

阅读(12850) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~