Changes

How to use SPI

12,993 bytes added, 13:10, 21 August 2012
m
no edit summary
(please contribute with this article)== 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 [http://isee.biz/component/zoo/item/igep-sdk-software-user-manual 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 [http://isee.biz/component/zoo/item/igep-sdk-software-user-manual 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 (suggestionat least 2Gbytes) == How Works == '''LIS3DH accelerometer:''' It is the accelerometer mounted in IGEP New York.  '''Omap3 SPI Peripheral: how ''' 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.bz2cd 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.gitjdoe@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 handle 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 mux 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 usb0usb0 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.1root@igep00x0:~# </pre> Check your changes (spidev will be enabled): <pre>root@igep00x0:~# lsmodModule Size Used byip_tables 9402 0 rfcomm 48492 0 hidp 13271 0 l2cap 48548 4 rfcomm,hidpbluetooth 67154 3 rfcomm,hidp,l2capoption 13048 0 usb_wwan 7163 1 optionlibertas_sdio 13919 0 twl4030_wdt 2623 0 spidev 4906 0 libertas 98995 1 libertas_sdioomap_wdt 3171 0 usbserial 23882 2 option,usb_wwanroot@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-gnueabiarm-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:Work in progress]]
[[Category:SPI]]
4,199
edits