Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
en:xu3_hardware_spi [2015/07/31 16:15] odroid [Reading the SPI Flash device ID on Expansion-Board] |
en:xu3_hardware_spi [2016/12/24 12:15] (current) odroid [Reading the SPI Flash device ID on Expansion-Board] |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== SPI ====== | ||
+ | This page introduces how you can use SPI interface using Expansion Board. | ||
+ | ===== Reading the SPI Flash device ID on Expansion-Board ===== | ||
+ | To use spidev on your **ODROID-XU3** you should fix device tree source. | ||
+ | |||
+ | <WRAP center round important 100%> | ||
+ | To use the SPI, you first need to update the kernel version to "3.10.82" or higher. | ||
+ | sudo apt-get update && sudo apt-get dist-upgrade | ||
+ | </WRAP> | ||
+ | |||
+ | <WRAP center round important 100%> | ||
+ | SPI MODE 3 doesn't work by unknown reason. Please try to use the SPI MODE 0. | ||
+ | </WRAP> | ||
+ | |||
+ | === How to enable driver (Only Ubuntu 16.04 or higher is required) === | ||
+ | Edit /etc/modprobe.d/blacklist-odroid.conf to comment out following two ines. | ||
+ | <code> | ||
+ | blacklist spidev | ||
+ | blacklist spi_s3c64xx | ||
+ | </code> | ||
+ | |||
+ | Reboot. | ||
+ | reboot | ||
+ | Check your SPI node. | ||
+ | ls /dev/spidev* | ||
+ | === Compile & run SPI test example source code === | ||
+ | gcc -o spidev_test spidev_test.c | ||
+ | |||
+ | <code> | ||
+ | odroid@odroid:~$ ./spidev_test | ||
+ | spi mode: 0 | ||
+ | bits per word: 8 | ||
+ | max speed: 500000 Hz (500 KHz) | ||
+ | |||
+ | 34 34 34 34 | ||
+ | </code> | ||
+ | |||
+ | If you tie the MOSI and MISO pins, the output is "AB 00 00 00".\\ | ||
+ | We call it loopback test. | ||
+ | |||
+ | <file c spidev_test.c> | ||
+ | /* | ||
+ | * SPI testing utility (using spidev driver) | ||
+ | * | ||
+ | * Copyright (c) 2007 MontaVista Software, Inc. | ||
+ | * Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com> | ||
+ | * | ||
+ | * This program is free software; you can redistribute it and/or modify | ||
+ | * it under the terms of the GNU General Public License as published by | ||
+ | * the Free Software Foundation; either version 2 of the License. | ||
+ | * | ||
+ | * Cross-compile with cross-gcc -I/path/to/cross-kernel/include | ||
+ | */ | ||
+ | | ||
+ | #include <stdint.h> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <sys/ioctl.h> | ||
+ | #include <linux/spi/spidev.h> | ||
+ | | ||
+ | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) | ||
+ | | ||
+ | static void pabort(const char *s) | ||
+ | { | ||
+ | perror(s); | ||
+ | abort(); | ||
+ | } | ||
+ | | ||
+ | static const char *device = "/dev/spidev1.0"; | ||
+ | static uint8_t mode; | ||
+ | static uint8_t bits = 8; | ||
+ | static uint32_t speed = 500000; | ||
+ | | ||
+ | static void transfer(int fd) | ||
+ | { | ||
+ | int ret; | ||
+ | uint8_t tx[] = { | ||
+ | 0xAB, 0x00, 0x00, 0x00 | ||
+ | }; | ||
+ | uint8_t rx[ARRAY_SIZE(tx)] = {0, }; | ||
+ | | ||
+ | struct spi_ioc_transfer tr[2]; | ||
+ | tr[0].tx_buf = (unsigned long)tx; | ||
+ | tr[0].rx_buf = (unsigned long)rx; | ||
+ | tr[0].len = ARRAY_SIZE(tx); | ||
+ | tr[0].speed_hz = speed; | ||
+ | tr[0].bits_per_word = bits; | ||
+ | tr[0].delay_usecs = 0; | ||
+ | tr[0].cs_change = 0; | ||
+ | |||
+ | tr[1].tx_buf = (unsigned long)tx; | ||
+ | tr[1].rx_buf = (unsigned long)rx; | ||
+ | tr[1].len = ARRAY_SIZE(tx); | ||
+ | tr[1].speed_hz = speed; | ||
+ | tr[1].bits_per_word = bits; | ||
+ | tr[1].delay_usecs = 0; | ||
+ | tr[1].cs_change = 0; | ||
+ | |||
+ | ret = ioctl(fd, SPI_IOC_MESSAGE(2), tr); | ||
+ | if (ret < 1) | ||
+ | pabort("can't send spi message"); | ||
+ | | ||
+ | for (ret = 0; ret < ARRAY_SIZE(tx); ret++) { | ||
+ | if (!(ret % 6)) | ||
+ | puts(""); | ||
+ | printf("%.2X ", rx[ret]); | ||
+ | } | ||
+ | puts(""); | ||
+ | } | ||
+ | | ||
+ | int main(void) | ||
+ | { | ||
+ | int ret = 0; | ||
+ | int fd; | ||
+ | | ||
+ | fd = open(device, O_RDWR); | ||
+ | if (fd < 0) | ||
+ | pabort("can't open device"); | ||
+ | | ||
+ | /* | ||
+ | * spi mode | ||
+ | */ | ||
+ | ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); | ||
+ | if (ret == -1) | ||
+ | pabort("can't set spi mode"); | ||
+ | | ||
+ | ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); | ||
+ | if (ret == -1) | ||
+ | pabort("can't get spi mode"); | ||
+ | | ||
+ | /* | ||
+ | * bits per word | ||
+ | */ | ||
+ | ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); | ||
+ | if (ret == -1) | ||
+ | pabort("can't set bits per word"); | ||
+ | | ||
+ | ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); | ||
+ | if (ret == -1) | ||
+ | pabort("can't get bits per word"); | ||
+ | | ||
+ | /* | ||
+ | * max speed hz | ||
+ | */ | ||
+ | ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); | ||
+ | if (ret == -1) | ||
+ | pabort("can't set max speed hz"); | ||
+ | | ||
+ | ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); | ||
+ | if (ret == -1) | ||
+ | pabort("can't get max speed hz"); | ||
+ | | ||
+ | printf("spi mode: %d\n", mode); | ||
+ | printf("bits per word: %d\n", bits); | ||
+ | printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); | ||
+ | | ||
+ | transfer(fd); | ||
+ | | ||
+ | close(fd); | ||
+ | | ||
+ | return ret; | ||
+ | } | ||
+ | </file> | ||
+ | |||
+ | |||
+ | **If you want to use 16bit/32bit length protocol with different SPI speed on XU4, refer this [[en:c1_hardware_spidev|c1_hardware_spidev]].** | ||