spi test
硬件協(xié)議
http://www.mct.net/faq/spi.html
http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
http://baike.baidu.com/view/245026.htm
軟件
①.添加spi平臺設(shè)備
在arch/arm/plat-s3c24xx/devs.c已經(jīng)定義了spi平臺設(shè)備3c_device_spi0和3c_device_spi1,如下
/* SPI (0) */static struct resource s3c_spi0_resource[] = {[0] = {.start = S3C24XX_PA_SPI,.end = S3C24XX_PA_SPI + 0x1f,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_SPI0,.end = IRQ_SPI0,.flags = IORESOURCE_IRQ,}};static u64 s3c_device_spi0_dmamask = 0xffffffffUL;struct platform_device s3c_device_spi0 = {.name = "s3c2410-spi",.id = 0,.num_resources = ARRAY_SIZE(s3c_spi0_resource),.resource = s3c_spi0_resource,.dev = {.dma_mask = &s3c_device_spi0_dmamask,.coherent_dma_mask = 0xffffffffUL} };EXPORT_SYMBOL(s3c_device_spi0);/* SPI (1) */static struct resource s3c_spi1_resource[] = {[0] = {.start = S3C24XX_PA_SPI + S3C2410_SPI1,.end = S3C24XX_PA_SPI + S3C2410_SPI1 + 0x1f,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_SPI1,.end = IRQ_SPI1,.flags = IORESOURCE_IRQ,}};static u64 s3c_device_spi1_dmamask = 0xffffffffUL;struct platform_device s3c_device_spi1 = {.name = "s3c2410-spi",.id = 1,.num_resources = ARRAY_SIZE(s3c_spi1_resource),.resource = s3c_spi1_resource,.dev = {.dma_mask = &s3c_device_spi1_dmamask,.coherent_dma_mask = 0xffffffffUL} };EXPORT_SYMBOL(s3c_device_spi1);
只是沒有加入到mach-mini2440.c,所以只需加入即可如下-----添加3c_device_spi0-------搜索for spi取得關(guān)鍵點
/opt/FriendlyArm/mini2440/linux-2.6.32.2/arch/arm/mach-s3c2440/mach-mini2440.c
//for spi #include <linux/spi/spi.h> #include <mach/spi.h> //for spi static struct spi_board_info s3c2410_spi0_board[] = {[0] = {.modalias = "spidev",.bus_num = 0, //此spi外設(shè)掛接在了哪個spi總線上.2440有兩個spi總線(spi主控制器,就像有3個串口一樣)。根據(jù)外設(shè)接線填寫。 .chip_select = 0,//片選引腳序號。從0開始。在bus_num(=0)對應(yīng)的3c2410_spi_info結(jié)構(gòu)體中描述起始片選引腳和數(shù)目。.max_speed_hz = 500*1000,}, }; static struct s3c2410_spi_info s3c2410_spi0_platdata = {.pin_cs = S3C2410_GPF(2),//第一個片選引腳.num_cs = 1,//片選引腳數(shù)目即外接幾個spi slave.bus_num = 0,//spi總線編號。因為2440有兩個,所以可選值0 1 }; /* devices we initialise */ static struct platform_device *mini2440_devices[] __initdata = {&s3c_device_usb,&s3c_device_rtc,&s3c_device_lcd,&s3c_device_wdt,&s3c_device_i2c0,&s3c_device_iis,&mini2440_device_eth,&s3c24xx_uda134x,&s3c_device_nand,&s3c_device_sdi,&s3c_device_usbgadget,&s3c_device_spi0,//for spi };static void __init mini2440_machine_init(void) { #if defined (LCD_WIDTH)s3c24xx_fb_set_platdata(&mini2440_fb_info); #endifs3c_i2c0_set_platdata(NULL);s3c2410_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);s3c_device_nand.dev.platform_data = &friendly_arm_nand_info;s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));s3c_pm_init();s3c_device_spi0.dev.platform_data= &s3c2410_spi0_platdata;//for spispi_register_board_info(s3c2410_spi0_board, ARRAY_SIZE(s3c2410_spi0_board));//for spi }/**********************************
note: about nss from 2440 spec
When the SPI system is enabled, the direction of pins except nSS pin is controlled by MSTR bit of SPCONn
register. The direction of nSS pin is always input.
When the SPI is a master, nSS pin is used to check multi-master error, provided that the SPPIN's ENMUL bit is
active, and another GPIO should be used to select a slave.
If the SPI is configured as a slave, the nSS pin is used to select SPI as a slave by one master.
nss 引腳大多數(shù)情況下都作為輸入(基本上都是)
當(dāng)2440作為spi master時,nss不要使用(在SPPIN's ENMUL=1時,nss腳要用于排錯)。2440的spi master需要使用其他gpio來選中spi slave。當(dāng)然有幾個slave,2440就要再花費幾個gpio.
當(dāng)2400作為spi slave時,2440的nss作為輸入,其他spi master要用這個nss來選中這個spi slave.
看來nss的片選功能用于slave模式里面-被片選。
**********************************/
然后配置spi的平臺驅(qū)動(亦實現(xiàn)spi主機控制器驅(qū)動) Samsung S3C24XX series SPI,
還需配置spi外設(shè)驅(qū)動 User mode SPI device driver support,以便生成設(shè)備節(jié)點。為便于操作,配置成模塊,如下
Device Drivers ---> [*] SPI support ---> <M>?? Samsung S3C24XX series SPI<M>?? User mode SPI device driver support
重新編譯內(nèi)核燒寫
編譯模塊得到兩個ko,考到板子上執(zhí)行
[root@FriendlyARM plg]# insmod spi_s3c24xx.ko [root@FriendlyARM plg]# insmod spidev.ko 先insmod spidev.ko也行,如下
[root@FriendlyARM plg]# insmod spidev.ko [root@FriendlyARM plg]# insmod spi_s3c24xx.ko insmod spidev.ko后會出現(xiàn)設(shè)備/dev/spidev0.0
②測試/dev/spidev0.0 .在源碼的Documentation/spi目錄有寫好的測試代碼
[root@localhost spi]# pwd /opt/FriendlyArm/mini2440/linux-2.6.32.2/Documentation/spi [root@localhost spi]# ls butterfly Makefile~ spidev spidev_fdx.c spidev_test.c spi-lm70llp Makefile pxa2xx spidev_fdx spidev_test spidev_test.c~ spi-summary 編譯spidev_test.c
在spidev_test.c ,我的/usr/include/linux/spi/spidev.h 不管用,所以就直接連接到2.6.32里面
//#include <linux/spi/spidev.h> #include </opt/FriendlyArm/mini2440/linux-2.6.32.2/include/linux/spi/spidev.h> [root@localhost spi]# arm-linux-gcc spidev_test.c -o spidev_test
考到板子上執(zhí)行
[root@FriendlyARM plg]# ./spidev_test -D /dev/spidev0.0 spi mode: 0 bits per word: 8 max speed: 500000 Hz (500 KHz)00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
source code for testing
/** 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 <unistd.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/types.h> #include </opt/FriendlyArm/mini2440/linux-2.6.32.2/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.1"; static uint8_t mode; static uint8_t bits = 8; static uint32_t speed = 500000; static uint16_t delay;static void transfer(int fd) {int ret;uint8_t tx[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0x40, 0x00, 0x00, 0x00, 0x00, 0x95,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,0xF0, 0x0D,};uint8_t rx[ARRAY_SIZEARRAY_SIZE(tx)] = {0, };struct spi_ioc_transfer tr = {.tx_buf = (unsigned long)tx,.rx_buf = (unsigned long)rx,.len = ARRAY_SIZE(tx),.delay_usecs = delay,.speed_hz = speed,.bits_per_word = bits,};ret = ioctl(fd, SPI_IOC_MESSAGE(1), &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(""); }static void print_usage(const char *prog) {printf("Usage: %s [-DsbdlHOLC3]\n", prog);puts(" -D --device device to use (default /dev/spidev1.1)\n"" -s --speed max speed (Hz)\n"" -d --delay delay (usec)\n"" -b --bpw bits per word \n"" -l --loop loopback\n"" -H --cpha clock phase\n"" -O --cpol clock polarity\n"" -L --lsb least significant bit first\n"" -C --cs-high chip select active high\n"" -3 --3wire SI/SO signals shared\n");exit(1); }static void parse_opts(int argc, char *argv[]) {while (1) {static const struct option lopts[] = {{ "device", 1, 0, 'D' },{ "speed", 1, 0, 's' },{ "delay", 1, 0, 'd' },{ "bpw", 1, 0, 'b' },{ "loop", 0, 0, 'l' },{ "cpha", 0, 0, 'H' },{ "cpol", 0, 0, 'O' },{ "lsb", 0, 0, 'L' },{ "cs-high", 0, 0, 'C' },{ "3wire", 0, 0, '3' },{ "no-cs", 0, 0, 'N' },{ "ready", 0, 0, 'R' },{ NULL, 0, 0, 0 },};int c;c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);if (c == -1)break;switch (c) {case 'D':device = optarg;break;case 's':speed = atoi(optarg);break;case 'd':delay = atoi(optarg);break;case 'b':bits = atoi(optarg);break;case 'l':mode |= SPI_LOOP;break;case 'H':mode |= SPI_CPHA;break;case 'O':mode |= SPI_CPOL;break;case 'L':mode |= SPI_LSB_FIRST;break;case 'C':mode |= SPI_CS_HIGH;break;case '3':mode |= SPI_3WIRE;break;case 'N':mode |= SPI_NO_CS;break;case 'R':mode |= SPI_READY;break;default:print_usage(argv[0]);break;}} }int main(int argc, char *argv[]) {int ret = 0;int fd;parse_opts(argc, argv);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; }
refer to
http://www.arm9home.net/read.php?tid-4422.html
http://www.arm9home.net/read.php?tid-10788.html
http://www.arm9home.net/read.php?tid-11762.html
http://www.cnblogs.com/nkzc/archive/2010/07/21/1781959.html
*********************************************************************************************************************************************************
對于te6410 2012-6-10 21
spi平臺設(shè)備platform_device s3c64xx_device_spi,arch/arm/mach-s3c64xx/dev-spi.c
static struct resource s3c64xx_spi1_resource[] = {[0] = {.start = S3C64XX_PA_SPI1,.end = S3C64XX_PA_SPI1 + 0x100 - 1,.flags = IORESOURCE_MEM,},[1] = {.start = DMACH_SPI1_TX,.end = DMACH_SPI1_TX,.flags = IORESOURCE_DMA,},[2] = {.start = DMACH_SPI1_RX,.end = DMACH_SPI1_RX,.flags = IORESOURCE_DMA,},[3] = {.start = IRQ_SPI1,.end = IRQ_SPI1,.flags = IORESOURCE_IRQ,}, };static struct s3c64xx_spi_info s3c64xx_spi1_pdata = {.cfg_gpio = s3c64xx_spi_cfg_gpio,.fifo_lvl_mask = 0x7f,.rx_lvl_offset = 13, };struct platform_device s3c64xx_device_spi1 = {.name = "s3c64xx-spi",.id = 1,.num_resources = ARRAY_SIZE(s3c64xx_spi1_resource),.resource = s3c64xx_spi1_resource,.dev = {.dma_mask = &spi_dmamask,.coherent_dma_mask = DMA_BIT_MASK(32),.platform_data = &s3c64xx_spi1_pdata,}, }; EXPORT_SYMBOL(s3c64xx_device_spi1);void __init s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs) {struct s3c64xx_spi_info *pd;/* Reject invalid configuration */if (!num_cs || src_clk_nr < 0|| src_clk_nr > S3C64XX_SPI_SRCCLK_48M) {printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);return;}switch (cntrlr) {case 0:pd = &s3c64xx_spi0_pdata;break;case 1:pd = &s3c64xx_spi1_pdata;break;default:printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",__func__, cntrlr);return;}pd->num_cs = num_cs;pd->src_clk_nr = src_clk_nr;pd->src_clk_name = spi_src_clks[src_clk_nr]; } 添加信息到板子文件中,arch/arm/mach-s3c64xx/mach-s3c6410.c
/*add by fatfish for mcp251x*/ static void cs_set_level(unsigned line_id, int lvl) {gpio_direction_output(line_id, lvl); };static struct s3c64xx_spi_csinfo s3c64xx_spi1_csinfo = {.fb_delay=0x3,.line=S3C64XX_GPC(7),.set_level=cs_set_level, };static int mcp251x_ioSetup(struct spi_device *spi) { // printk(KERN_INFO "mcp251x: setup gpio pins CS and External Int\n");printk("mcp251x_ioSetup\n");s3c_gpio_setpull(S3C64XX_GPL(8), S3C_GPIO_PULL_UP); // External interrupt from CAN controllers3c_gpio_cfgpin(S3C64XX_GPL(8), S3C_GPIO_SFN(3)); // External interrupt from CAN controller (hopefully external interrupt) // s3c_gpio_cfgpin(S3C64XX_GPL(8), S3C_GPIO_INPUT); // External interrupt from CAN controllers3c_gpio_setpull(S3C64XX_GPC(7), S3C_GPIO_PULL_NONE); // Manual chip select pin as used in 6410_set_css3c_gpio_cfgpin(S3C64XX_GPC(7), S3C_GPIO_OUTPUT); // Manual chip select pin as used in 6410_set_csreturn 0; }static struct mcp251x_platform_data mcp251x_info = {.oscillator_frequency = 16000000,.board_specific_setup = mcp251x_ioSetup,.transceiver_enable = NULL,.power_enable = NULL, };//spi_device的板信息使用spi_board_info結(jié)構(gòu)體描述,記錄了該spi外設(shè)的名字,使用的主機控制器序號,片選序號,波特率,spi傳輸模式(CPHA,CPOL)等 static struct spi_board_info __initdata forlinx6410_mc251x_info[] = {{.modalias = "mcp2515", .platform_data = &mcp251x_info,.irq = IRQ_EINT(16),.max_speed_hz = 10*1000*1000, .bus_num = 1,.chip_select = 0,.mode = SPI_MODE_0, .controller_data=&s3c64xx_spi1_csinfo,}, }; static struct platform_device *smdk6410_devices[] __initdata = { ...&s3c64xx_device_spi0,&s3c64xx_device_spi1,//添加dev-spi.c中的s3c64xx_device_spi1 ... };static void __init smdk6410_machine_init(void) {s3c64xx_spi_set_info(0,0,1);s3c64xx_spi_set_info(1,0,1);//添加dev-spi.c中的s3c64xx_spi1_pdataspi_register_board_info(forlinx6410_mc251x_info,ARRAY_SIZE(forlinx6410_mc251x_info));//注冊spi_board_info ...platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices)); }
2012-7-15 19:57:34
關(guān)于autorequest?GPIO-24? 的內(nèi)核崩潰
后來跟蹤到drivers/spi/spi.c里的一個函數(shù)里面spi_setup()調(diào)用的??? status = spi->master->setup(spi);
有用的信息
http://e2e.ti.com/support/embedded/linux/f/354/p/119946/427889.aspx#427889
http://www.mct.net/faq/spi.html
http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
http://baike.baidu.com/view/245026.htm
軟件
①.添加spi平臺設(shè)備
在arch/arm/plat-s3c24xx/devs.c已經(jīng)定義了spi平臺設(shè)備3c_device_spi0和3c_device_spi1,如下
/* SPI (0) */static struct resource s3c_spi0_resource[] = {[0] = {.start = S3C24XX_PA_SPI,.end = S3C24XX_PA_SPI + 0x1f,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_SPI0,.end = IRQ_SPI0,.flags = IORESOURCE_IRQ,}};static u64 s3c_device_spi0_dmamask = 0xffffffffUL;struct platform_device s3c_device_spi0 = {.name = "s3c2410-spi",.id = 0,.num_resources = ARRAY_SIZE(s3c_spi0_resource),.resource = s3c_spi0_resource,.dev = {.dma_mask = &s3c_device_spi0_dmamask,.coherent_dma_mask = 0xffffffffUL} };EXPORT_SYMBOL(s3c_device_spi0);/* SPI (1) */static struct resource s3c_spi1_resource[] = {[0] = {.start = S3C24XX_PA_SPI + S3C2410_SPI1,.end = S3C24XX_PA_SPI + S3C2410_SPI1 + 0x1f,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_SPI1,.end = IRQ_SPI1,.flags = IORESOURCE_IRQ,}};static u64 s3c_device_spi1_dmamask = 0xffffffffUL;struct platform_device s3c_device_spi1 = {.name = "s3c2410-spi",.id = 1,.num_resources = ARRAY_SIZE(s3c_spi1_resource),.resource = s3c_spi1_resource,.dev = {.dma_mask = &s3c_device_spi1_dmamask,.coherent_dma_mask = 0xffffffffUL} };EXPORT_SYMBOL(s3c_device_spi1);
只是沒有加入到mach-mini2440.c,所以只需加入即可如下-----添加3c_device_spi0-------搜索for spi取得關(guān)鍵點
/opt/FriendlyArm/mini2440/linux-2.6.32.2/arch/arm/mach-s3c2440/mach-mini2440.c
//for spi #include <linux/spi/spi.h> #include <mach/spi.h> //for spi static struct spi_board_info s3c2410_spi0_board[] = {[0] = {.modalias = "spidev",.bus_num = 0, //此spi外設(shè)掛接在了哪個spi總線上.2440有兩個spi總線(spi主控制器,就像有3個串口一樣)。根據(jù)外設(shè)接線填寫。 .chip_select = 0,//片選引腳序號。從0開始。在bus_num(=0)對應(yīng)的3c2410_spi_info結(jié)構(gòu)體中描述起始片選引腳和數(shù)目。.max_speed_hz = 500*1000,}, }; static struct s3c2410_spi_info s3c2410_spi0_platdata = {.pin_cs = S3C2410_GPF(2),//第一個片選引腳.num_cs = 1,//片選引腳數(shù)目即外接幾個spi slave.bus_num = 0,//spi總線編號。因為2440有兩個,所以可選值0 1 }; /* devices we initialise */ static struct platform_device *mini2440_devices[] __initdata = {&s3c_device_usb,&s3c_device_rtc,&s3c_device_lcd,&s3c_device_wdt,&s3c_device_i2c0,&s3c_device_iis,&mini2440_device_eth,&s3c24xx_uda134x,&s3c_device_nand,&s3c_device_sdi,&s3c_device_usbgadget,&s3c_device_spi0,//for spi };static void __init mini2440_machine_init(void) { #if defined (LCD_WIDTH)s3c24xx_fb_set_platdata(&mini2440_fb_info); #endifs3c_i2c0_set_platdata(NULL);s3c2410_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);s3c_device_nand.dev.platform_data = &friendly_arm_nand_info;s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));s3c_pm_init();s3c_device_spi0.dev.platform_data= &s3c2410_spi0_platdata;//for spispi_register_board_info(s3c2410_spi0_board, ARRAY_SIZE(s3c2410_spi0_board));//for spi }/**********************************
note: about nss from 2440 spec
When the SPI system is enabled, the direction of pins except nSS pin is controlled by MSTR bit of SPCONn
register. The direction of nSS pin is always input.
When the SPI is a master, nSS pin is used to check multi-master error, provided that the SPPIN's ENMUL bit is
active, and another GPIO should be used to select a slave.
If the SPI is configured as a slave, the nSS pin is used to select SPI as a slave by one master.
nss 引腳大多數(shù)情況下都作為輸入(基本上都是)
當(dāng)2440作為spi master時,nss不要使用(在SPPIN's ENMUL=1時,nss腳要用于排錯)。2440的spi master需要使用其他gpio來選中spi slave。當(dāng)然有幾個slave,2440就要再花費幾個gpio.
當(dāng)2400作為spi slave時,2440的nss作為輸入,其他spi master要用這個nss來選中這個spi slave.
看來nss的片選功能用于slave模式里面-被片選。
**********************************/
然后配置spi的平臺驅(qū)動(亦實現(xiàn)spi主機控制器驅(qū)動) Samsung S3C24XX series SPI,
還需配置spi外設(shè)驅(qū)動 User mode SPI device driver support,以便生成設(shè)備節(jié)點。為便于操作,配置成模塊,如下
Device Drivers ---> [*] SPI support ---> <M>?? Samsung S3C24XX series SPI<M>?? User mode SPI device driver support
重新編譯內(nèi)核燒寫
編譯模塊得到兩個ko,考到板子上執(zhí)行
[root@FriendlyARM plg]# insmod spi_s3c24xx.ko [root@FriendlyARM plg]# insmod spidev.ko 先insmod spidev.ko也行,如下
[root@FriendlyARM plg]# insmod spidev.ko [root@FriendlyARM plg]# insmod spi_s3c24xx.ko insmod spidev.ko后會出現(xiàn)設(shè)備/dev/spidev0.0
②測試/dev/spidev0.0 .在源碼的Documentation/spi目錄有寫好的測試代碼
[root@localhost spi]# pwd /opt/FriendlyArm/mini2440/linux-2.6.32.2/Documentation/spi [root@localhost spi]# ls butterfly Makefile~ spidev spidev_fdx.c spidev_test.c spi-lm70llp Makefile pxa2xx spidev_fdx spidev_test spidev_test.c~ spi-summary 編譯spidev_test.c
在spidev_test.c ,我的/usr/include/linux/spi/spidev.h 不管用,所以就直接連接到2.6.32里面
//#include <linux/spi/spidev.h> #include </opt/FriendlyArm/mini2440/linux-2.6.32.2/include/linux/spi/spidev.h> [root@localhost spi]# arm-linux-gcc spidev_test.c -o spidev_test
考到板子上執(zhí)行
[root@FriendlyARM plg]# ./spidev_test -D /dev/spidev0.0 spi mode: 0 bits per word: 8 max speed: 500000 Hz (500 KHz)00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
source code for testing
/** 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 <unistd.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/types.h> #include </opt/FriendlyArm/mini2440/linux-2.6.32.2/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.1"; static uint8_t mode; static uint8_t bits = 8; static uint32_t speed = 500000; static uint16_t delay;static void transfer(int fd) {int ret;uint8_t tx[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0x40, 0x00, 0x00, 0x00, 0x00, 0x95,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,0xF0, 0x0D,};uint8_t rx[ARRAY_SIZEARRAY_SIZE(tx)] = {0, };struct spi_ioc_transfer tr = {.tx_buf = (unsigned long)tx,.rx_buf = (unsigned long)rx,.len = ARRAY_SIZE(tx),.delay_usecs = delay,.speed_hz = speed,.bits_per_word = bits,};ret = ioctl(fd, SPI_IOC_MESSAGE(1), &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(""); }static void print_usage(const char *prog) {printf("Usage: %s [-DsbdlHOLC3]\n", prog);puts(" -D --device device to use (default /dev/spidev1.1)\n"" -s --speed max speed (Hz)\n"" -d --delay delay (usec)\n"" -b --bpw bits per word \n"" -l --loop loopback\n"" -H --cpha clock phase\n"" -O --cpol clock polarity\n"" -L --lsb least significant bit first\n"" -C --cs-high chip select active high\n"" -3 --3wire SI/SO signals shared\n");exit(1); }static void parse_opts(int argc, char *argv[]) {while (1) {static const struct option lopts[] = {{ "device", 1, 0, 'D' },{ "speed", 1, 0, 's' },{ "delay", 1, 0, 'd' },{ "bpw", 1, 0, 'b' },{ "loop", 0, 0, 'l' },{ "cpha", 0, 0, 'H' },{ "cpol", 0, 0, 'O' },{ "lsb", 0, 0, 'L' },{ "cs-high", 0, 0, 'C' },{ "3wire", 0, 0, '3' },{ "no-cs", 0, 0, 'N' },{ "ready", 0, 0, 'R' },{ NULL, 0, 0, 0 },};int c;c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);if (c == -1)break;switch (c) {case 'D':device = optarg;break;case 's':speed = atoi(optarg);break;case 'd':delay = atoi(optarg);break;case 'b':bits = atoi(optarg);break;case 'l':mode |= SPI_LOOP;break;case 'H':mode |= SPI_CPHA;break;case 'O':mode |= SPI_CPOL;break;case 'L':mode |= SPI_LSB_FIRST;break;case 'C':mode |= SPI_CS_HIGH;break;case '3':mode |= SPI_3WIRE;break;case 'N':mode |= SPI_NO_CS;break;case 'R':mode |= SPI_READY;break;default:print_usage(argv[0]);break;}} }int main(int argc, char *argv[]) {int ret = 0;int fd;parse_opts(argc, argv);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; }
refer to
http://www.arm9home.net/read.php?tid-4422.html
http://www.arm9home.net/read.php?tid-10788.html
http://www.arm9home.net/read.php?tid-11762.html
http://www.cnblogs.com/nkzc/archive/2010/07/21/1781959.html
*********************************************************************************************************************************************************
對于te6410 2012-6-10 21
spi平臺設(shè)備platform_device s3c64xx_device_spi,arch/arm/mach-s3c64xx/dev-spi.c
static struct resource s3c64xx_spi1_resource[] = {[0] = {.start = S3C64XX_PA_SPI1,.end = S3C64XX_PA_SPI1 + 0x100 - 1,.flags = IORESOURCE_MEM,},[1] = {.start = DMACH_SPI1_TX,.end = DMACH_SPI1_TX,.flags = IORESOURCE_DMA,},[2] = {.start = DMACH_SPI1_RX,.end = DMACH_SPI1_RX,.flags = IORESOURCE_DMA,},[3] = {.start = IRQ_SPI1,.end = IRQ_SPI1,.flags = IORESOURCE_IRQ,}, };static struct s3c64xx_spi_info s3c64xx_spi1_pdata = {.cfg_gpio = s3c64xx_spi_cfg_gpio,.fifo_lvl_mask = 0x7f,.rx_lvl_offset = 13, };struct platform_device s3c64xx_device_spi1 = {.name = "s3c64xx-spi",.id = 1,.num_resources = ARRAY_SIZE(s3c64xx_spi1_resource),.resource = s3c64xx_spi1_resource,.dev = {.dma_mask = &spi_dmamask,.coherent_dma_mask = DMA_BIT_MASK(32),.platform_data = &s3c64xx_spi1_pdata,}, }; EXPORT_SYMBOL(s3c64xx_device_spi1);void __init s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs) {struct s3c64xx_spi_info *pd;/* Reject invalid configuration */if (!num_cs || src_clk_nr < 0|| src_clk_nr > S3C64XX_SPI_SRCCLK_48M) {printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);return;}switch (cntrlr) {case 0:pd = &s3c64xx_spi0_pdata;break;case 1:pd = &s3c64xx_spi1_pdata;break;default:printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",__func__, cntrlr);return;}pd->num_cs = num_cs;pd->src_clk_nr = src_clk_nr;pd->src_clk_name = spi_src_clks[src_clk_nr]; } 添加信息到板子文件中,arch/arm/mach-s3c64xx/mach-s3c6410.c
/*add by fatfish for mcp251x*/ static void cs_set_level(unsigned line_id, int lvl) {gpio_direction_output(line_id, lvl); };static struct s3c64xx_spi_csinfo s3c64xx_spi1_csinfo = {.fb_delay=0x3,.line=S3C64XX_GPC(7),.set_level=cs_set_level, };static int mcp251x_ioSetup(struct spi_device *spi) { // printk(KERN_INFO "mcp251x: setup gpio pins CS and External Int\n");printk("mcp251x_ioSetup\n");s3c_gpio_setpull(S3C64XX_GPL(8), S3C_GPIO_PULL_UP); // External interrupt from CAN controllers3c_gpio_cfgpin(S3C64XX_GPL(8), S3C_GPIO_SFN(3)); // External interrupt from CAN controller (hopefully external interrupt) // s3c_gpio_cfgpin(S3C64XX_GPL(8), S3C_GPIO_INPUT); // External interrupt from CAN controllers3c_gpio_setpull(S3C64XX_GPC(7), S3C_GPIO_PULL_NONE); // Manual chip select pin as used in 6410_set_css3c_gpio_cfgpin(S3C64XX_GPC(7), S3C_GPIO_OUTPUT); // Manual chip select pin as used in 6410_set_csreturn 0; }static struct mcp251x_platform_data mcp251x_info = {.oscillator_frequency = 16000000,.board_specific_setup = mcp251x_ioSetup,.transceiver_enable = NULL,.power_enable = NULL, };//spi_device的板信息使用spi_board_info結(jié)構(gòu)體描述,記錄了該spi外設(shè)的名字,使用的主機控制器序號,片選序號,波特率,spi傳輸模式(CPHA,CPOL)等 static struct spi_board_info __initdata forlinx6410_mc251x_info[] = {{.modalias = "mcp2515", .platform_data = &mcp251x_info,.irq = IRQ_EINT(16),.max_speed_hz = 10*1000*1000, .bus_num = 1,.chip_select = 0,.mode = SPI_MODE_0, .controller_data=&s3c64xx_spi1_csinfo,}, }; static struct platform_device *smdk6410_devices[] __initdata = { ...&s3c64xx_device_spi0,&s3c64xx_device_spi1,//添加dev-spi.c中的s3c64xx_device_spi1 ... };static void __init smdk6410_machine_init(void) {s3c64xx_spi_set_info(0,0,1);s3c64xx_spi_set_info(1,0,1);//添加dev-spi.c中的s3c64xx_spi1_pdataspi_register_board_info(forlinx6410_mc251x_info,ARRAY_SIZE(forlinx6410_mc251x_info));//注冊spi_board_info ...platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices)); }
2012-7-15 19:57:34
關(guān)于autorequest?GPIO-24? 的內(nèi)核崩潰
后來跟蹤到drivers/spi/spi.c里的一個函數(shù)里面spi_setup()調(diào)用的??? status = spi->master->setup(spi);
有用的信息
http://e2e.ti.com/support/embedded/linux/f/354/p/119946/427889.aspx#427889
HI , i solved the above issue.... by adding the below function call?
gpio_request(gpio, NULL); before we set the direction of gpio i.e?gpio_direction_output(gpio,0);
Thanks & Regards
Siva Prasad T
轉(zhuǎn)載于:https://www.cnblogs.com/-song/archive/2011/12/03/3331908.html
總結(jié)
- 上一篇: 扩展adc 1
- 下一篇: spi 外设驱动(spi_driver)