U-Boot下的I2C设备的读写

来源:互联网 发布:淘宝如何设置花呗支付 编辑:程序博客网 时间:2024/06/18 07:56

在嵌入式中,I2C设备的使用比较广泛,U-Boot集成了i2c的操作函数及命令。如下
mpc8349@MITC> 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

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

 
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设备。通过如下命令可以进行总线控制器的设置

mpc8349@MITC> i2c dev 0
Setting bus to 0
mpc8349@MITC> iprobe
Valid chip addresses: 50
Excluded chip addresses:
mpc8349@MITC> 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    .U.|.@....|.A.`.
0010: 00 ff ff ff ff ff ff    .......
mpc8349@MITC> imm 0x50 .2
00000000: ff ? aa
00000001: ff ? .
mpc8349@MITC> 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 
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[] =  
274     {
275         0xAA0x550xAA     
276         0x7C             
277         0x020x40       
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             
283         0x020x41       
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, 00, &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, 00, &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, 02, data, sizeof(data)) == 0) {
308         if (memcmp(data, eeprom_data, sizeof(data)) != 0) {
309             if (i2c_write
310                 (CONFIG_SYS_I2C_EEPROM_ADDR, 02, 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);
0 0
原创粉丝点击