Rasberry Pi I2C EEPROM Program

From richud.com
Jump to navigation Jump to search

Requirements

Enable all the I2C bits

/etc/modules

Load the i2c modules on boot (check with lsmod)

snd-bcm2835
i2c-bcm2708 
i2c-dev

/etc/modprobe.d/raspi-blacklist.conf

comment out the blacklist of the i2c module, although mine loads modules when still blacklisted here

blacklist spi-bcm2708
#blacklist i2c-bcm2708

/etc/modprobe.d/i2c.conf

options i2c_bcm2708 baudrate=400000
  • Generally use the lowest you can to mitigate the clock stretching bug, if your device supports clock stretching. (these eeproms dont)

baudrate=400000 for 400kbit. Check actual looking at dmesg

baudrate=1000000 1Mbit

/etc/boot.txt

For >= 3.18 kernel

Append file with this ;

dtparam=i2c0=on
dtparam=i2c1=on
dtparam=i2c_arm=on

If you are using a newer pi with i2c bus on 1 then only need dtparam=i2c1=on, older just need 0, but doesn't seem to matter setting both.

Without above you will also get(assuming older Pi with i2c on 0)

pi@raspberrypi ~ $ sudo i2cdetect -y 0
Error: Could not open file `/dev/i2c-0' or `/dev/i2c/0': No such file or directory

working config

If all correct lsmod should show at least i2c_bcm2708 and i2c_dev

$ lsmod
Module                  Size  Used by
lirc_dev               11060  0 
rc_core                23581  1 lirc_dev
i2c_dev                 6730  0 
snd_bcm2835            22317  0 
snd_pcm                92581  1 snd_bcm2835
snd_seq                61957  0 
snd_seq_device          5130  1 snd_seq
snd_timer              23454  2 snd_pcm,snd_seq
snd                    68161  5 snd_bcm2835,snd_timer,snd_pcm,snd_seq,snd_seq_device
i2c_bcm2708             6252  0 
bcm2835_gpiomem         3703  0 
uio_pdrv_genirq         3690  0 
uio                    10002  1 uio_pdrv_genirq

and /dev should show this snipit within it, the i2c-0 and/or i2c-1 (depending on what you set in /etc/boot.txt)

$ ls -al /dev

crw-------  1 root root    245,   0 Jan  1  1970 gpiomem
crw-------  1 root root     10, 183 Jan  1  1970 hwrng
crw-rw---T  1 root i2c      89,   0 Feb  6 12:03 i2c-0
crw-rw---T  1 root i2c      89,   1 Feb  6 12:03 i2c-1
drwxr-xr-x  2 root root          60 Jan  1  1970 input
crw-r--r--  1 root root      1,  11 Jan  1  1970 kmsg
srw-rw-rw-  1 root root           0 Feb  6 12:03 log

programs to get

i2c-tools and hexedit

sudo apt-get install i2c-tools hexedit

eeprog

eeprog-0.7.6-tear5.tar.gz NOT the original eeprog as it wont program (anything I've tried) on a Pi, you will get this without a write cycle time delay

  Writing stdin starting at address 0x0
..Error i2c_write_3b: Input/output error
Error at line 150: write error

Board Revisions

Your Pi GPIO pins can be using i2c bus 0 or 1 depending on the board revision. In this case the 'Revision' below is '000e' which is;

'000e' => 'Model B Revision 2.0 512MB', (Sony) i.e. rev 2 = i2c bus 1

(Just to confuse, the examples below were done on a rev.1 board so its on 0!!)

$ cat /proc/cpuinfo 
processor	: 0
model name	: ARMv6-compatible processor rev 7 (v6l)
Features	: swp half thumb fastmult vfp edsp java tls 
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x0
CPU part	: 0xb76
CPU revision	: 7

Hardware	: BCM2708
Revision	: 100000e
Serial		: 000000003422697f

Atmel 24C256 EEPROM Programming

This is set with address pins A0 A1 set high (wired to Vcc) so address is 0x53 not 0x50. (A2 isn't connected on this chip)

chip specs

16 bit addressing (use -16)

262144 bits = 32768 bytes = 32k = 0x8000

Addressable range thus = 0 to 32767 , i.e. 0x0 to 0x7FFF

  • Note, confusingly, to read the whole chip, from 0 to 0x7FF you would use -r 0x00:0x8000 as it start:length not start:end
  • Note if you have it in 8 bit mode it may look like its working but the data you get will just be garbage.

Example 1

find address

$ sudo i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- 53 -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         

So chip is at address 0x53

write

root@raspberrypi:/tmp/eeprog-0.7.6-tear12# date | ./eeprog -f -16 -w 0 -t 5 /dev/i2c-0 0x53
eeprog 0.7.6-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
  Bus: /dev/i2c-0, Address: 0x53, Mode: 16bit
  Operation: write at offset 0, Input file: <stdin>
  Write cycle time: 5 milliseconds
  Writing <stdin> starting at address 0x0
.............................

read

root@raspberrypi:/tmp/eeprog-0.7.6-tear12# ./eeprog -xf /dev/i2c-0 0x53 -16 -r 0x00:0x100
eeprog 0.7.6-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
  Bus: /dev/i2c-0, Address: 0x53, Mode: 16bit
  Operation: read 256 bytes from offset 0, Output file: <stdout>
  Reading 256 bytes from 0x0

 0000|  46 72 69 20 41 75 67 20   31 35 20 32 32 3a 32 36 
 0010|  3a 33 35 20 55 54 43 20   32 30 31 34 0a 00 00 00 
 0020|  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00 
 0030|  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00 
 0040|  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00 
<SNIP>

read with i2cdump

(For some reason this needs running twice to get proper read)

(Update : On another Rev 2 Pi ~ 6 months later it seems to work first time)

i = I2C mode, seems to dump the first 512 bytes.

root@raspberrypi:/tmp/eeprog-0.7.6-tear12# i2cdump -y 0 0x53 i
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 46 72 69 20 41 75 67 20 31 35 20 32 32 3a 32 36    Fri Aug 15 22:26
10: 3a 33 35 20 55 54 43 20 32 30 31 34 0a 00 00 00    :35 UTC 2014?...
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
<SNIP>

Example 2

This just shows how to offset and uses writing from a source file rather than std input.

Generate 256 bytes of data with dd

dd, input data is random - blocksize = 1 byte , count = 256 of them, output to a file '256.dump'

$ dd if=/dev/urandom bs=1 count=256 > 256.dump
256+0 records in
256+0 records out
256 bytes (256 B) copied, 0.0156784 s, 16.3 kB/s

(you may need to do; $ sudo apt-get install hexdump)

 $ hexdump -C 256.dump 
00000000  6a d6 48 db a3 ef 7a 86  6c ab be 12 2b 6b 50 79  |j.H...z.l...+kPy|
00000010  e7 10 7c c0 0d 16 b9 d0  d6 43 77 58 83 46 c8 31  |..|......CwX.F.1|
00000020  17 90 f9 3c 26 64 38 8b  96 81 d1 57 42 a0 04 c0  |...<&d8....WB...|
00000030  3a ef ae 40 6a c9 98 89  24 5f 0d 6d 26 1e 70 03  |:..@j...$_.m&.p.|
00000040  95 88 dc 61 bf ee 8a ca  30 05 4b f4 cc 4d f7 c5  |...a....0.K..M..|
00000050  c1 9e 38 48 f9 70 01 7c  8f 66 0a bc 43 c6 2b 99  |..8H.p.|.f..C.+.|
00000060  d9 7b f9 54 c6 e9 da 1c  be 57 ef 8f 00 ae 39 3d  |.{.T.....W....9=|
00000070  cd a1 cf e3 51 3f 99 48  51 64 47 35 31 34 bb 18  |....Q?.HQdG514..|
00000080  ae 24 98 cf 83 ce cd 63  dd 39 26 d1 ec 41 9c 07  |.$.....c.9&..A..|
00000090  d2 28 23 1c 14 0f 70 97  94 1e d9 e2 77 b4 18 d8  |.(#...p.....w...|
000000a0  1b bc 2e b2 f8 f4 f9 19  c7 95 a9 2b b9 ae 2c 60  |...........+..,`|
000000b0  14 97 ac 5a a8 ff 73 d8  d1 61 53 c3 a6 00 1b d7  |...Z..s..aS.....|
000000c0  6e d4 86 6e e7 b1 26 c7  56 12 4c d2 07 3f fe b7  |n..n..&.V.L..?..|
000000d0  79 6f fb 51 3d a3 a9 8f  88 98 25 b3 ef 1d 4f 57  |yo.Q=.....%...OW|
000000e0  65 05 b6 94 51 85 ec 02  6f 18 1d b4 56 5f 59 6b  |e...Q...o...V_Yk|
000000f0  7c 24 c9 84 e9 96 d6 29  32 56 3b ea 1a 8a 39 ac  ||$.....)2V;...9.|
00000100

Write to start of eeprom

write out the 256 byte of random data to eeprom at the beginning

suppress warnings (-f), 16 bit (-16) , input file (-i), offset 0x00 (-w), 5 ms delay (-t), bus /dev/i2c-0, bus address 0x53 (A0,A1 set high at vcc)

$ ./eeprog -f -16 -i 256.dump -w 0x00 -t 5 /dev/i2c-0 0x53
eeprog 0.7.6-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
  Bus: /dev/i2c-0, Address: 0x53, Mode: 16bit
  Operation: write at offset 0, Input file: 256.dump
  Write cycle time: 5 milliseconds
  Writing 256.dump starting at address 0x0
................................................................................................................................................................................................................................................................

write out the 256 byte of random data to eeprom, after first one (first is 00 to FF, then this is 100 to 1FF)

./eeprog -f -16 -i 256.dump -w 0x100 -t 5 /dev/i2c-0 0x53
eeprog 0.7.6-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
  Bus: /dev/i2c-0, Address: 0x53, Mode: 16bit
  Operation: write at offset 256, Input file: 256.dump
  Write cycle time: 5 milliseconds
  Writing 256.dump starting at address 0x100
................................................................................................................................................................................................................................................................

read it back

You should have two copies of the 256 bytes of random data, one after another.

Notice you have to read to 0x200 and not 1FF because it is 512 bytes from 0, not an end address.

$ sudo ./eeprog -xf /dev/i2c-0 0x53 -16 -r 0x00:0x200
eeprog 0.7.6-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
  Bus: /dev/i2c-0, Address: 0x53, Mode: 16bit
  Operation: read 512 bytes from offset 0, Output file: <stdout>
  Reading 512 bytes from 0x0

 0000|  6a d6 48 db a3 ef 7a 86   6c ab be 12 2b 6b 50 79 
 0010|  e7 10 7c c0 0d 16 b9 d0   d6 43 77 58 83 46 c8 31 
 0020|  17 90 f9 3c 26 64 38 8b   96 81 d1 57 42 a0 04 c0 
 0030|  3a ef ae 40 6a c9 98 89   24 5f 0d 6d 26 1e 70 03 
 0040|  95 88 dc 61 bf ee 8a ca   30 05 4b f4 cc 4d f7 c5 
 0050|  c1 9e 38 48 f9 70 01 7c   8f 66 0a bc 43 c6 2b 99 
 0060|  d9 7b f9 54 c6 e9 da 1c   be 57 ef 8f 00 ae 39 3d 
 0070|  cd a1 cf e3 51 3f 99 48   51 64 47 35 31 34 bb 18 
 0080|  ae 24 98 cf 83 ce cd 63   dd 39 26 d1 ec 41 9c 07 
 0090|  d2 28 23 1c 14 0f 70 97   94 1e d9 e2 77 b4 18 d8 
 00a0|  1b bc 2e b2 f8 f4 f9 19   c7 95 a9 2b b9 ae 2c 60 
 00b0|  14 97 ac 5a a8 ff 73 d8   d1 61 53 c3 a6 00 1b d7 
 00c0|  6e d4 86 6e e7 b1 26 c7   56 12 4c d2 07 3f fe b7 
 00d0|  79 6f fb 51 3d a3 a9 8f   88 98 25 b3 ef 1d 4f 57 
 00e0|  65 05 b6 94 51 85 ec 02   6f 18 1d b4 56 5f 59 6b 
 00f0|  7c 24 c9 84 e9 96 d6 29   32 56 3b ea 1a 8a 39 ac 
 0100|  6a d6 48 db a3 ef 7a 86   6c ab be 12 2b 6b 50 79 
 0110|  e7 10 7c c0 0d 16 b9 d0   d6 43 77 58 83 46 c8 31 
 0120|  17 90 f9 3c 26 64 38 8b   96 81 d1 57 42 a0 04 c0 
 0130|  3a ef ae 40 6a c9 98 89   24 5f 0d 6d 26 1e 70 03 
 0140|  95 88 dc 61 bf ee 8a ca   30 05 4b f4 cc 4d f7 c5 
 0150|  c1 9e 38 48 f9 70 01 7c   8f 66 0a bc 43 c6 2b 99 
 0160|  d9 7b f9 54 c6 e9 da 1c   be 57 ef 8f 00 ae 39 3d 
 0170|  cd a1 cf e3 51 3f 99 48   51 64 47 35 31 34 bb 18 
 0180|  ae 24 98 cf 83 ce cd 63   dd 39 26 d1 ec 41 9c 07 
 0190|  d2 28 23 1c 14 0f 70 97   94 1e d9 e2 77 b4 18 d8 
 01a0|  1b bc 2e b2 f8 f4 f9 19   c7 95 a9 2b b9 ae 2c 60 
 01b0|  14 97 ac 5a a8 ff 73 d8   d1 61 53 c3 a6 00 1b d7 
 01c0|  6e d4 86 6e e7 b1 26 c7   56 12 4c d2 07 3f fe b7 
 01d0|  79 6f fb 51 3d a3 a9 8f   88 98 25 b3 ef 1d 4f 57 
 01e0|  65 05 b6 94 51 85 ec 02   6f 18 1d b4 56 5f 59 6b 
 01f0|  7c 24 c9 84 e9 96 d6 29   32 56 3b ea 1a 8a 39 ac

To read just the second 256 block you would use ./eeprog -xf /dev/i2c-0 0x53 -16 -r 0x100:0x100

Atmel 24C02 I2C EPROM

8 bit addressing

2048 bits = 256 bytes = 1/4k = 0x100

Addressable range = 0 to 255 , i.e 0x0 to 0xFF

  • Note, confusingly, to read the whole chip, from 0 to 0xFF you would use -r 0x00:0x100 as it start:length not start:end
  • Note can use thee pins A0,A1,A2 voltage levels to give an address from 0x50 (all grnd) to 0x57 (all at vcc)
  • Note this also needs a 5 ms pause for writing

read, output to file

./eeprog -f -o 2c02.bin -r 0x00:0x100 /dev/i2c-0 0x57

or

./i2cdump -y 0 0x57 i

I am not sure how this knows to use 8 or 16 bit addressing? I think it is probably a lack of my understanding.

write from file

./eeprog -f  -i 2c02.bin -w 0x00 -t 5 /dev/i2c-0 0x57

poke a byte to and address with i2cset

address 0x03 set to 0x35

i2cset -y 0 0x57 0x03 0x35

Programming I2C via VGA port

VGA out can often support I2C directly so no need for any external devices. My Toshiba Portege R830 does. vga on bus /dev/i2c-1

$ sudo i2cdetect -l
i2c-3	i2c       	i915 gmbus dpc                  	I2C adapter
i2c-1	i2c       	i915 gmbus vga                  	I2C adapter
i2c-8	i2c       	DPDDC-D                         	I2C adapter
<snip>

Pin 5 Ground

Pin 9 5V (need v cheap i2c level shifter if you are using 3.3v or lower!)

Pin 12 SDA

Pin 15 SCL

$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         

Fiddling with the settings in eeprogs was needed to get reliable writing depending on what you are doing. (writing to Atmel EPROM in my case)

  • Note eeprogs needs gcc-4.8 to compile and not coredump. In ubuntu 16.04, make CC=gcc-4.8

Comments

blog comments powered by Disqus