Changes

How to use SPI

12,906 bytes added, 12:53, 14 August 2012
no edit summary
(please contribute with this article) = How to use SPI =
(suggestion: how to handle SPI and mux configuration) == Overview ==
This How-To is meant to be a starting point for people to learn use SPI for IGEP devices as quickly and easily as possible. In this how-to, we run an example program that reads and writes registers from 3-axis accelerometer ([http://www.st.com/internet/analog/product/250725.jsp LIS3DH]) included on the board IGEP New York. <br>
 
== Requirements ==
 
There are some requisites to follow this guide:
 
*[http://isee.biz/component/zoo/item/igep-virtual-machine-sdk-yocto IGEP SDK VM]: follow the IGEP&nbsp;SDK&nbsp;SOFTWARE&nbsp;USER&nbsp;MANUAL (chapter 2.3 "Setting up and running the VM")<br>
*[http://isee.biz/component/zoo/item/igep-firmware-yocto-1-2 IGEP Firmware]: follow the IGEP&nbsp;SDK SOFTWARE&nbsp;USER&nbsp;MANUAL (chapter 6.1 "Create IGEP firmware bootable micro-sd card")
*[http://isee.biz/products/processor-boards/igep-com-module IGEP&nbsp;COM&nbsp;MODULE] and [http://isee.biz/products/expansion-boards/product-igep-new-york IGEP NEW&nbsp;YORK]<br>
*[http://labs.isee.biz/images/b/b8/Spiexamplebeta2.tar.bz2 SPI example program]
*MicroSD Card (at least 2Gbytes)
 
== How Works ==
 
'''LIS3DH accelerometer:''' It is the accelerometer mounted in IGEP New York.
 
'''Omap3 SPI Peripheral:''' It is the hardware used to communicated with accelerometer and other SPI devices.
 
'''Omap2_mcspi:''' It is a bus driver than controls Omap3 SPI Peripheral.
 
'''Spi:''' It is a protocol driver that defines functions and strucs used in SPI bus.
 
'''Spidev:''' It is a device driver that export spi driver functionalities to userspace.
 
'''Lis3lv02d_spi:''' SPI glue layer for lis3lv02d
 
'''Lis31v02d:''' Device driver for LIS3DH accelerometer.
 
'''Exp_ilms0015:''' It is a startup program for IGEP New York. It attach lis31v02d with Spi driver.
 
{| cellspacing="1" cellpadding="1" border="1" width="200"
|-
| [[Image:Spi linux schematic.png|501x600px]]
|}
 
<br> More information about Linux Kernel SPI at:
 
*[http://git.isee.biz/?p=pub/scm/linux-omap-2.6.git;a=blob;f=Documentation/spi/spi-summary;h=4884cb33845d7629987f60610eeedb863561006e;hb=refs/heads/linux-2.6.37.y SPI Overview]
 
*[http://git.isee.biz/?p=pub/scm/linux-omap-2.6.git;a=blob;f=Documentation/spi/spidev;h=ed2da5e5b28a4490a3b03787b02df66d083692be;hb=refs/heads/linux-2.6.37.y SPIDEV]
 
== Prepare Micro SD Card ==
 
=== Generate Micro SD Card ===
 
Open a terminal and use the following steps to download and generate a Micro SD card.
<pre>wget http://downloads.isee.biz/denzil/binary/igep_firmware-yocto-1.2.1-1.tar.bz2
tar jxf igep_firmware-yocto-*.tar.bz2
cd igep_firmware-yocto-* </pre>
Insert a SD-Card and use the igep-media-create script to copy the firmware.
 
./igep-media-create -–mmc &lt;mmc&gt; --image demo-image-sato-igep00x0.tar.bz2&nbsp;--machine igep0030
 
where &lt;mmc&gt; - is the SD-Card device of your computer. For example, assuming the SD-card device takes '/dev/sdb' type:
<pre>./igep-media-create --mmc /dev/sdb --machine igep0030 --image demo-image-sato-igep00x0.tar.bz2 </pre>
This should give you a bootable SD-card with IGEP&nbsp;COM&nbsp;MODULE support.
 
=== Custom Micro SD Card ===
 
==== Get Linux kernel sources ====
 
We will get from git repository the kernel sources:
 
*Clone the Kernel git repository
<pre>jdoe@ubuntu ~ $ git clone git://git.igep.es/pub/scm/linux-omap-2.6.git
jdoe@ubuntu ~ $ cd linux-omap-2.6/</pre>
*Checkout your desired branch (we used for this howto 2.6.37.y)
<pre>jdoe@ubuntu ~/linux-omap-2.6 $ git checkout origin/linux-2.6.37.y -b linux-2-6-37.y</pre>
==== Modify Linux Kernel Sources to attach Spidev to SPI&nbsp;driver ====
 
To read accelerometer registers from spidev, we need to attach spidev driver to spi driver at start up. So it is necessary to modify spi_board.
 
Go to $(Kernel path)/arch/arm/mach-omap2/exp-ilms0015.c and edit the next fields in bold words.
 
{| cellspacing="1" cellpadding="1" border="1" width="500"
|-
|
static struct spi_board_info lis3lv02d_spi_board_info __initdata = {
 
&nbsp;&nbsp;&nbsp;&nbsp;'''.modalias = "spidev",'''
 
&nbsp;&nbsp;&nbsp; '''//.modalias&nbsp;&nbsp;&nbsp; = "lis3lv02d_spi",'''
 
&nbsp;&nbsp;&nbsp; .bus_num&nbsp;&nbsp;&nbsp; = -EINVAL,
 
&nbsp;&nbsp;&nbsp; .chip_select&nbsp;&nbsp;&nbsp; = -EINVAL,
 
&nbsp;&nbsp;&nbsp; .max_speed_hz&nbsp;&nbsp;&nbsp; = 1*1000*1000,
 
&nbsp;&nbsp;&nbsp; .irq&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; = -EINVAL,
 
&nbsp;&nbsp;&nbsp; .mode&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; = SPI_MODE_0,
 
&nbsp;&nbsp;&nbsp;'''//.platform_data&nbsp;&nbsp;&nbsp; = &amp;lis3lv02d_pdata,'''
 
};
 
inline void __init ilms0015_lis3lv02d_init(int bus_num, int cs, int irq)
 
{
 
&nbsp;&nbsp;&nbsp; struct spi_board_info *spi = &amp;lis3lv02d_spi_board_info;
 
&nbsp;&nbsp;&nbsp; if ((gpio_request(irq, "LIS3LV02D IRQ") == 0)
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; (gpio_direction_input(irq) == 0))
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gpio_export(irq, 0);
 
&nbsp;&nbsp;&nbsp; else {
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pr_err("IGEP: Could not obtain gpio LIS3LV02D IRQ\n");
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;
 
&nbsp;&nbsp;&nbsp; }
 
&nbsp;&nbsp;&nbsp; spi-&gt;bus_num = bus_num;
 
&nbsp;&nbsp;&nbsp; spi-&gt;chip_select = cs;
 
&nbsp;&nbsp;&nbsp; spi-&gt;irq = OMAP_GPIO_IRQ(irq),
 
&nbsp;&nbsp;&nbsp; spi_register_board_info(&amp;lis3lv02d_spi_board_info, 1);
 
}
 
...
 
void __init ilms0015_init(void)
 
{
 
&nbsp;&nbsp;&nbsp; mux_partition = omap_mux_get("core");
 
&nbsp;&nbsp;&nbsp; /* Mux initialitzation for ilms0015 */
 
&nbsp;&nbsp;&nbsp; omap_mux_write_array(mux_partition, ilms0015_mux);
 
&nbsp;&nbsp;&nbsp; /* 3-axis accelerometer */
 
&nbsp;&nbsp;&nbsp; ilms0015_lis3lv02d_init(1, 2, 174);
 
&nbsp;&nbsp;&nbsp; /* Export some GPIO */
 
&nbsp;&nbsp;&nbsp; ilms0015_gpio_init();
 
}
 
|}
 
Now spi_register_board_info has all information necessary to attach spidev driver instead lis3lv02d_spi.
 
==== Compile Kernel ====
 
Export IGEP SDK sources
<pre>jdoe@ubuntu ~ $ source /opt/poky/1.2/environment-setup-armv7a-vfp-neon-poky-linux-gnueabi</pre>
*Configure the kernel
<pre>jdoe@ubuntu ~ $ cd linux-omap-2.6/
jdoe@ubuntu ~/linux-omap-2.6 $ make ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- igep00x0_defconfig</pre>
*Build the kernel and Modules
<pre>jdoe@ubuntu ~/linux-omap-2.6 $ make ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- zImage modules</pre>
==== Copy Kernel to SD card ====
 
*Kernel binary resides inside the directory:$(Kernel path)/arch/arm/boot/zImage. Copy binary to SD boot partition:
<pre>jdoe@ubuntu ~/linux-omap-2.6 $ mv arch/arm/boot/zImage /media/boot/zImage</pre>
*Copy Kernel modules:
<pre>jdoe@ubuntu ~/linux-omap-2.6 $ sudo make ARCH=arm modules_install INSTALL_MOD_PATH=/media/rootfs</pre>
==== Enable ilms0015 support ====
 
By default, igep-media-create configured as igep0030, gives support only for IGEP Expansions Paris and Berlin. We need to configure igep.ini (located at boot partition) and gives support to IGEP New York:
 
{| cellspacing="1" cellpadding="1" border="1" width="500"
|-
| &nbsp;; Machine configuration
'''&nbsp;&nbsp;&nbsp;&nbsp;;buddy=base0010 buddy.revision=B '''
 
'''&nbsp;&nbsp;&nbsp; buddy=ilms0015'''
 
|}
 
'''NOTE:''' “ilms0015” is the technical name of IGEP New York.
 
==== Test changes ====
 
Once you copy your new Kernel binaries and edit igep.ini:
 
*Power up your board with your new SD card
*Enable removable device: RNDIS/Ethernet Gadget
*Set up usb0 network device:
<pre>jdoe@ubuntu ~ $ sudo ifup usb0
jdoe@ubuntu ~ $ ifconfig usb0
usb0 Link encap:Ethernet HWaddr 32:3a:b0:bc:cc:15
inet addr:192.168.7.10 Bcast:192.168.7.255 Mask:255.255.255.0
inet6 addr: fe80::303a:b0ff:febc:cc15/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:53 errors:0 dropped:0 overruns:0 frame:0
TX packets:46 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:10584 (10.5 KB) TX bytes:9203 (9.2 KB)
 
jdoe@ubuntu ~ $ </pre>
<br> Log in:
<pre>jdoe@ubuntu ~ $ ssh root@192.168.7.1
root@igep00x0:~# </pre>
Check your changes (spidev will be enabled):
<pre>root@igep00x0:~# lsmod
Module Size Used by
ip_tables 9402 0
rfcomm 48492 0
hidp 13271 0
l2cap 48548 4 rfcomm,hidp
bluetooth 67154 3 rfcomm,hidp,l2cap
option 13048 0
usb_wwan 7163 1 option
libertas_sdio 13919 0
twl4030_wdt 2623 0
spidev 4906 0
libertas 98995 1 libertas_sdio
omap_wdt 3171 0
usbserial 23882 2 option,usb_wwan
root@igep00x0:~#
</pre>
“spidev1.2”: refers at McSPI1 bus 2. Now we can communicate to accelerometer using spi driver functions.
 
== SPI Test program ==
 
=== Overview ===
 
This program is based in [http://git.isee.biz/?p=pub/scm/linux-omap-2.6.git;a=blob;f=Documentation/spi/spidev_test.c;h=16feda9014692a87a4996bf51d759ab9e7500ee5;hb=refs/heads/linux-2.6.37.y spidev_test] and it was edited to run with LIS3DH accelerometer. Program can be explained in four parts:
 
'''Connection properties:''' program lets change via parameters SPI configurations like: device, max speed, delay, bits per word, clock phase, clock polarity, etc. If you don't use any of this parameters program will use default options for LIS3DH communication.
 
'''Read mode: '''Reads a word from a register.
 
'''Write mode: '''Writes a word in a register.
 
'''Test mode:''' Reads X, Y and Z axes from accelerometer.
 
We recommend to read peripheral datasheet before use or modify program.
 
=== Compile program ===
 
The program source was compiled with Yocto SDK but you can use other compilers like Linaro Toolchain:
<pre>source /opt/poky/1.2/environment-setup-armv7a-vfp-neon-poky-linux-gnueabi
arm-poky-linux-gnueabi-gcc spiexamplebeta2.c -o spiexampleb2 </pre>
Copy your final binary to rootfs.
 
== Test program<br> ==
 
=== Read WHO_AM_I register(0Fh) ===
 
LIS3DH has this dummy register (See 8.6 chapter) as a device identification. Its value is 0x33:
<pre>root@igep00x0:~# ./spiexampleb2 -R 0F
spi mode: 0
bits per word: 8
max speed: 1000000 Hz (1000 KHz)
Value from 0F is: 33
root@igep00x0:~# </pre>
=== Read and Write CTRL_REG1 (20h) ===
 
This register is used to enable/disable: accelerometer and XYZ axes (See 8.8 chapter). The default value at startup is:
<pre>root@igep00x0:~# ./spiexampleb2 -R 20
spi mode: 0
bits per word: 8
max speed: 1000000 Hz (1000 KHz)
Value from 20 is: 07
root@igep00x0:~# </pre>
It means that accelerometer was disabled and X, Y and Z axes was enabled. For example we can disable X axe typing:
<pre>root@igep00x0:~# ./spiexampleb2 -W 20 -V 06
spi mode: 0
bits per word: 8
max speed: 1000000 Hz (1000 KHz)
Register to write 20 with value 06
root@igep00x0:~# ./spiexampleb2 -R 20
spi mode: 0
bits per word: 8
max speed: 1000000 Hz (1000 KHz)
Value from 20 is: 06
root@igep00x0:~#
</pre>
=== Read accelerometer axes ===
 
[[Image:Lis3dhxyzaxes.png|right|150x159px]]Finally we are going to read gravity force: LIS3DH has ±2g/±4g/±8g/±16g dynamically selectable full scale (See chapter 8.11). The axes values are expressed in two’s complement in 16 bits (See chapters 8.16, 8.17 and 8.18).&nbsp;
<pre>root@igep00x0:~# ./spiexampleb2 -T
spi mode: 0
bits per word: 8
max speed: 1000000 Hz (1000 KHz)
Accelerometer TEST
Values from X -64, Values from Y -15872 and Values from Z -256
root@igep00x0:~#
</pre>
The next table shows results at different positions:
 
{| cellspacing="1" cellpadding="1" border="1" width="600"
|-
| Position
| ±2g scale
| ±4g scale
| ±8g scale
| ±16g scale
|-
| [[Image:NYtopimagetest.png|center|100x100px]]
| X = 832
Y = 1024
 
Z = 15680
 
|
X = 256
 
Y = 128
 
Z = 7872
 
|
X = 128
 
Y = 128
 
Z = 4032
 
|
X = 64
 
Y = 128
 
Z = 1280
 
|-
| [[Image:NYbotimagetest.png|center|100x100px]]
|
X = 256
 
Y = 704
 
Z = -17216
 
|
X = 256
 
Y = 256
 
Z = -8320
 
|
X = 64
 
Y = 128
 
Z = -4096
 
|
X = 128
 
Y = 128
 
Z = -1344
 
|-
| [[Image:NYtophoritzontalimagetest.png|center|100x100px]]
|
X = -15872
 
Y = 64
 
Z = -320
 
|
X = -7936
 
Y = 64
 
Z = -512
 
|
X = -3968
 
Y = 128
 
Z = -192
 
|
X = -1280
 
Y = 64
 
Z = -128
 
|-
| [[Image:NYbothoritzontalimagetest.png|center|100x100px]]
|
X = 16448
 
Y = 640
 
Z = 640
 
|
X = 8128
 
Y = 192
 
Z = 384
 
|
X = 4032
 
Y = 64
 
Z = 64
 
|
X = 1344
 
Y = 64
 
Z = 192
 
|-
| [[Image:NYtopverticalimagetest.png|center|100x100px]]
|
X = 896
 
Y = 16512
 
Z = -576
 
|
X = 320
 
Y = 8128
 
Z = -128
 
|
X = 192
 
Y = 4096
 
Z = -64
 
|
X = 128
 
Y = 1344
 
Z = -128
 
|-
| [[Image:NYbotverticalimagetest.png|center|100x100px]]
|
X = -64
 
Y = -15872
 
Z = -256
 
|
X = -512
 
Y = -7808
 
Z = -384
 
|
X = -64
 
&gt;Y = -3840
 
Z = -384
 
|
X = -128
 
Y = -1216
 
Z = -128
 
|}
[[Category:SPI]]
4,199
edits