Using Raspberry Pi for rapid prototyping - I2C SPD reader

DDR DIMM SPD Adapter for Raspberry Pi

All computer DDR memory today have little I2C EEPROMs to store vendor, configuration and module spec information.
This is done to allow computer to detect memory type, and configure memory interface to correct speeds and voltages according to module spec. This mechanism is based on JEDEC Serial presence detection specification (SPD) which is available for download.

Sometimes it’s needed to modify SPD and there are rarely available software tools to do so in-system.
To overcome this issue design can be done stand-alone, with independent hardware to read/write EEPROM on memory module.
Raspberry Pi is one from hundreds of possible ways to do such, and it’s easy and widely popular linux platform, which enables lot of engineers to customize and discover new uses of ARM embedded platform.

And since we don’t want to modify anything on DIMM modules directly, there is requirement to have standard DIMM sockets, so user can easily interchange modules to perform SPD operations, without any damage risk or soldering.

Basic spec for this little project

  • Open-source project, managed via and mercurial DVCS
  • Full-size DDR3/DDR4 UDIMM/RDIMM slots to support most of standard memory modules
  • Standard header for direct connection to Raspberry Pi host
  • I2C EEPROM interface connection for Raspberry Pi port
  • Fixed +3.3V voltage level for SPD power
  • Power switch to allow swapping modules without RPI power down.
  • I2C address switch to enable multiple adapters to be used with single RPI.
  • Onboard MCU (LPC11U37FBD64) for future development/standalone operation without RPI (e.g. automation usage)

Project file tree

All project files and documentation tracked by Mercurial DVCS.
It’s free and well maintained version control engine, with syntax similar to git and SVN.

So if you want to play with project or repeat by yourself, you can get tree by running

hg clone

Or to view just some files you can browse project tree here
Login and password are guest.

Hardware design

After few hours here is adapter board schematics (PDF format on click).

Pretty simple design with low amount of parts. MCU section is optional and not required for operation with RPI.

PCB Layout is done for 4-layer FR4, with silkscreen on both sides for assembly aid. All parts except connectors, switches and solid capacitor are SMD. Gerber files available for download as well

For DIY assembly or custom applications this can be simplified even more

This is as simple as it goes, two pull-up resistors for I2C bus, +3.3V power taken from RPI and power switch with LED.

Manufactured adapter (hand assembled board and bare PCB)

Required parts for Raspberry Pi only operation:

  • Power switch SW4 (2-position)
  • I2C pullup resistors R10,R9 (2.2kOhm, 0603 5%)
  • Bypass resistor R7 (0-10 ohm, 0603 5%)
  • Decoupling capacitors C3,C2 (0.1uF 0603 ×7R)
  • Bulk capacitor C4 (100-560uF 6.3-16V 7mm diameter, pin pitch 4mm)
  • 2.54mm 26-pin header for RPI extension port P1.
  • DDR3 240-pin DIMM slot
  • DDR4 288-pin DIMM slot (if required)

All these components located in bottom right area.

Bottom side have only optional decorative 0603 LEDs.

Power, I2C, SPI and UART are routed from 26-pin header, which mates with Raspberry Pi expansion port just with straight ribbon cable.

Adressing for multiple adapters is set via 2-position switches and indicated by LEDs. It’s just usual A0,A1,A2 pin signaling for I2C EEPROMs.

Onboard MCU is NXP LPC11U37FBD64 with SWD header for debug/firmware development. SMD crystal is 12.000 MHz, to support UART and USB.

Overall kit looks like this:

From top to bottom – DDR3 Corsair UDIMM, DDR adapter board, Raspberry Pi Model B with 2GB SD card and 26-pin 2.54mm cable.

Using DDR3 module and connections:

Using DDR4 RDIMM module and connections:

Cannot use both DIMM types at same time, as there will be address conflict on I2C bus.

Inner layers just carry ground and power. PCB stackup photo:

Software design

This is step-by-step tutorial how to get fresh Raspberry Pi up and running for this project:

I used minimal OS, as intention was only to use network-based connection to RPI via ssh.
OS Image can be downloaded from origin here:
or from local mirror
It’s 120MB, so can take a little time to download.
To write image onto SD card you can use any imager tool.
For Win32 there is free Win32 Disk imager from gruemaster, tuxinator2009

The root password is raspberry.

Software setup

For accessing Raspberry Pi via network you will need to have network (eth0) configured properly.
If your network have DHCP service, usually enough just to add next line to /etc/network/interfaces

iface eth0 inet dhcp

If SD card is bigger than 1GB (which follows filesystem in linux image mentioned above), you may want to add extra partition to use extra space.

Create new partition using fdisk, so final table can look like this:

root@raspberry-pi:/# fdisk /dev/mmcblk0
Command (m for help): p
Disk /dev/mmcblk0: 32.1 GB, 32127320064 bytes
        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1            2048      104447       51200    b  W95 FAT32
/dev/mmcblk0p2          104448     1742847      819200   83  Linux
/dev/mmcblk0p3         1742848     1945599      101376   82  Linux swap / Solaris
/dev/mmcblk0p4         1945600    62748671    30401536   83  Linux

Then make ext4 filesystem in new partition.

root@raspberry-pi:/# mkfs.ext4 /dev/mmcblk0p4 -L ummspi2
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=ummspi2
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

Now make sure your /etc/fstab is updated:

root@raspberry-pi:/# cat /etc/fstab
# <file system> <mount point>   <type>          <options>               <dump>  <pass>
proc            /proc           proc            defaults                0       0
/dev/mmcblk0p1  /boot           vfat            defaults                0       0
/dev/mmcblk0p3  none            swap            sw                      0       0
*/dev/mmcblk0p4  /repo           ext4            defaults                0       0*

Here I have /repo filesystem partition with ext4 Linux type.
Now we can mount it.

root@raspberry-pi:/# mount -a

And it’s ready to use:

root@raspberry-pi:/# df -h
Filesystem      Size  Used Avail Use% Mounted on
rootfs          788M  566M  222M  72% /
/dev/root       788M  566M  222M  72% /
devtmpfs        212M     0  212M   0% /dev
tmpfs            44M  180K   44M   1% /run
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           108M     0  108M   0% /run/shm
/dev/mmcblk0p1   50M   19M   32M  37% /boot
*/dev/mmcblk0p4   29G  172M   27G   1% /repo*

It’s usually good idea to update your OS packages prior to installation of new software.
Be aware, than if your memory storage is limited, then you may run out of space if new packages occupy too much size.
Aptitude is common way for updating:

root@raspberry-pi:~# aptitude update
Get: 1 wheezy Release.gpg [490 B]
Get: 2 wheezy Release [14.4 kB]
Get: 3 wheezy/main Sources [6262 kB]
70% [3 Sources 4375 kB/6262 kB 70%].....79.8 kB/s 23s
Current status: 33 updates [+33], 77 new [+77].

And then run actual update.
Example output can be like below:

root@raspberry-pi:~# aptitude dist-upgrade
The following packages will be upgraded:
  apt apt-utils base-files dmsetup dpkg gnupg gpgv initscripts libapt-inst1.5 libapt-pkg-dev libapt-pkg4.12 libc-bin libc-dev-bin libc6 libc6-dev libdevmapper1.02.1 libgnutls26
  libssl1.0.0 linux-libc-dev locales lsb-base multiarch-support openssh-client openssh-server perl perl-base perl-modules ssh sysv-rc sysvinit sysvinit-utils tzdata wget
The following packages are RECOMMENDED but will NOT be installed:
  bcc gcc gcc-4.4 gcc-4.5 gcc-4.6 gcc-4.7 gnupg-curl libldap-2.4-2 manpages-dev psmisc
33 packages upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 35.5 MB of archives. After unpacking 234 kB will be freed.
Do you want to continue? [Y/n/?] Y
Setting up ssh (1:6.0p1-4+deb7u1) ...
Setting up perl (5.14.2-21+rpi2+deb7u1) ...
Current status: 0 updates [-33].

Also since i’m DOS-grown, prefer to use mcedit as default system editor. To change default nano to mcedit you can run

root@raspberry-pi:/etc/mercurial# update-alternatives —config editor
There are 3 choices for the alternative editor (providing /usr/bin/editor).

Selection Path Priority Status 0 /bin/nano 40 auto mode 1 /bin/nano 40 manual mode 2 /usr/bin/mcedit 25 manual mode 3 /usr/bin/vim.tiny 10 manual mode

Press enter to keep the current choice[*], or type selection number: 2
update-alternatives: using /usr/bin/mcedit to provide /usr/bin/editor (editor) in manual mode

I usually prefer to keep all develpoment and project files in local repository, install mercurial so we can develop our software and commit changes right away from Raspberry Pi system.

apt-get install mercurial
root@raspberry-pi:~# apt-get install mercurial
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  ca-certificates mercurial-common openssl python python-minimal
Suggested packages:
  qct wish vim emacs kdiff3 kdiff3-qt kompare meld xxdiff tkcvs mgdiff python-mysqldb python-pygments python-openssl python-doc python-tk
The following NEW packages will be installed:
  ca-certificates mercurial mercurial-common openssl python python-minimal
0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
Need to get 3514 kB of archives.
After this operation, 10.3 MB of additional disk space will be used.
Do you want to continue [Y/n]? Y
Get:1 wheezy/main python-minimal all 2.7.3-4+deb7u1 [42.8 kB]
Creating config file /etc/mercurial/hgrc.d/hgext.rc with new version
Processing triggers for ca-certificates ...
Updating certificates in /etc/ssl/certs... 158 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.

For mercurial repostory system how-to you can reference official documentation or short article here.

Now it’s time to do actual software setup for accessing our I2C hardware.

1. Add to /etc/modules


1b. If your Linux kernel is 3.18 or newer, add next lines to */boot/config.txt. This is due to migration for new Device Tree method.


2. sudo apt-get install python-smbus

root@raspberry-pi:~# apt-get install python-smbus
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
Suggested packages:
The following NEW packages will be installed:
  i2c-tools python-smbus
0 upgraded, 2 newly installed, 0 to remove and 32 not upgraded.
Need to get 71.0 kB of archives.
After this operation, 317 kB of additional disk space will be used.
Do you want to continue [Y/n]? Y
Get:1 wheezy/main i2c-tools armhf 3.1.0-2 [59.5 kB]
Get:2 wheezy/main python-smbus armhf 3.1.0-2 [11.5 kB]
Fetched 71.0 kB in 1s (36.0 kB/s)
Selecting previously unselected package i2c-tools.
(Reading database ... 22286 files and directories currently installed.)
Unpacking i2c-tools (from .../i2c-tools_3.1.0-2_armhf.deb) ...
Selecting previously unselected package python-smbus.
Unpacking python-smbus (from .../python-smbus_3.1.0-2_armhf.deb) ...
Processing triggers for man-db ...
Setting up i2c-tools (3.1.0-2) ...
Setting up python-smbus (3.1.0-2) ...

3. sudo apt-get install i2c-tools

root@raspberry-pi:~# apt-get install i2c-tools
Reading package lists... Done
Building dependency tree
Reading state information... Done
i2c-tools is already the newest version.
i2c-tools set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 32 not upgraded.

4. Now we can connect adapter board and try i2c detect tool to see if I2C interface working.

i2cdetect -y 1

When no devices / memory modules installed there should be no devices present on any address.
Just like this:

root@raspberry-pi:~# 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: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

5. Minimalist linux builds may not have gcc compiler as well, so install it before you can compile/test own code.

apt-get install gcc
apt-get install make 

If you get errors like:

sudo: unable to resolve host raspberry-pi

Then add line to /etc/hosts raspberry-pi

6. If you have wiringPi library not installed, need to install it.
If you used OS image attached in this code repository, then you will need to install wiringPi library.

root@raspberry-pi:/rpdb/ddr4s/fw/wiringPi# ./build
wiringPi Build script
WiringPi Library
[Compile] wiringPi.c
[Compile] wiringSerial.c
[Compile] wiringShift.c
[Compile] wiringPiSPI.c
[Compile] wiringPiI2C.c
[Compile] drcSerial.c
[Link (Dynamic)]
[Install Headers]
[Install Dynamic Lib]
WiringPi Devices Library
[Compile] ds1302.c
[Compile] maxdetect.c
[Compile] piNes.c
[Compile] gertboard.c
[Compile] piFace.c
[Compile] lcd128x64.c
[Compile] lcd.c
[Compile] piGlow.c
[Link (Dynamic)]
[Install Headers]
[Install Dynamic Lib]
GPIO Utility
[Compile] gpio.c
gpio.c:85:12: warning: 'decodePin' defined but not used [-Wunused-function]
[Compile] extensions.c
[Compile] readall.c
All Done.
NOTE: This is wiringPi v2, and if you need to use the lcd, Piface,
  Gertboard, MaxDetext, etc. routines then you must change your
  compile scripts to add -lwiringPiDev

7. Running test GCC-compiled software in putty terminal connection to Raspberry Pi’s Debian Linux.

8. Usage:

  • /* – compiler script to run gcc compiler with spd_prog_both.c to generate spd_prog main app executable (*nix)
  • /* – compiler script to run gcc compiler with checksum.c to generate checksum tool executable (*nix)
  • /spd_prog* – runs application to read/write DDR3/DDR4 SPD. It operates with plain binary files only.
  • /checksum* – runs tool to calculate and check CRC16 fields in DDR3/DDR4 plain binary file. It accepts filename with parameter -f [filename]

9. Check sum tool example:
DDR3 dump example:

$:/repo/ddr4s/fw/Pi$ ./checksum -f ddr3.bin 
/********************** DDR4s Project ************************/
 DDR3/DDR4 dump checksum check tool | calculates CRC16 for input binary  
 Usage: checksum -f [dump_filename] 
File DDR3 CRC16 = 600E | byte 126 = E | byte 127 = 60 
Calculated DDR3 CRC16 = 600E | byte 126 = E | byte 127 = 60 
CRC in dump is correct

DDR4 Dump example

$:/repo/ddr4s/fw/Pi$ ./checksum -f ddr4.bin 
/********************** DDR4s Project ************************/
 DDR3/DDR4 dump checksum check tool | calculates CRC16 for input binary  
 Usage: checksum -f [dump_filename] 
-i- DDR4 mode enabled, 512 bytes parsed 
File DDR4 CRC16 = E752 | byte 126 = 52 | byte 127 = E7 
File vendor section DDR4 CRC16 = 0 | byte 382 = 0 | byte 383 = 0 
Calculated DDR4 CRC16 = E752 | byte 126 = 52 | byte 127 = E7 
CRC in dump is correct



JEDEC Standard No. 21C : Serial Presence Detect (SPD), General Standard
JEDEC Registration – DDR4 DIMM PTH 288 Pin Socket Outline, 0.85 mm Pitch. SKT
JEDEC Definitions of the EE1004-v 4 Kbit Serial Presence Detect (SPD) EEPROM and TSE2004av 4 Kbit SPD EEPROM with Temperature Sensor (TS) for Memory Module Applications
JEDEC DDR4 UDIMM Design Specification Annex D
JEDEC Proposed Annex for DDR4 UDIMM, R/C B
JEDEC Standard No. 21C : Annex L: Serial Presence Detect (SPD) for DDR4 SDRAM Modules
JEDEC Standard No. 21C : Serial Presence Detect (SPD) for DDR3 SDRAM Modules DDR3 SPD Document Release 6
JEDEC Standard No. 21C : Memory Module Nomenclature
JEDEC Standard No. 21C : Definition of the TSE2002av Serial Presence Detect (SPD) EEPROM with Temperature Sensor (TS) for Memory Module Applications

Guide revision:

Rev 10, Initial release to public, added low-cost option schematics
Rev 11, Added extra settings for Kernel 3.18+ to enable I2C operation

Author: Ilya Tsemenko
Created: Aug. 9, 2014, 7:48 a.m.
Modified: Jan. 11, 2018, 3:12 p.m.