您的位置:首页 > 运维架构 > Linux

Linux 2.6.23下SPI设备模型--------基于AT91RM9200分析

2011-03-16 17:52 381 查看
1、内核版本:LINUX2.6.23

在内核艮目录下:make menuconfig后,进入driver->spi supprot目录下,配置如下



在character devices-->下,取消


既可以

2、修改文件arch/arm/mach-at91/board-dk.c 中:

static struct spi_board_info dk_spi_devices[] = {
{ /* DataFlash chip */
// .modalias = "mtd_dataflash",
.modalias = "spidev",
.chip_select = 0,
.max_speed_hz = 15 * 1000 * 1000,
},

{ /* UR6HCPS2-SP40 PS2-to-SPI adapter */
.modalias = "ur6hcps2", //修改成.modalias = "spidev",即可添加一个设备节点
.chip_select = 1,
.max_speed_hz = 250 * 1000,
},
{ /* TLV1504 ADC, 4 channels, 10 bits; one is a temp sensor */
.modalias = "tlv1504",//修改成.modalias = "spidev",即可添加一个设备节点
.chip_select = 2,
.max_speed_hz = 20 * 1000 * 1000,
},
#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
{ /* DataFlash card */
.modalias = "mtd_dataflash",//修改成.modalias = "spidev",即可添加一个设备节点
.chip_select = 3,
.max_speed_hz = 15 * 1000 * 1000,
}
#endif
};

3、修改好后,即可编译:make zImage;make uImage

生成的内核down到flash后,即可发现在/dev下生产了设备节点spidev



4、测试代码

/*
* 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 <linux/spi/spidev.h>
#include <math.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

static void pabort(const char *s)
{
perror(s);
abort();
}

//static char *device = "/dev/spidev1.1";
//static char *device = "/dev/spidev0.1"; //chip_select = 1 46 pio
static char *device = "/dev/spidev0.2"; //chip_select = 2 47 pio
//static char *device = "/dev/spidev0.3"; //chip_select = 3 48 pio
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 tx[] = {
0xaa, 0xaa, 0xaa, 0xaa
//0x55,0x55,0x55,0x55
};
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;

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("");
}

void print_usage(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);
}

void parse_opts(int argc, char *argv[])
{
while (1) {
static 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' },
{ NULL, 0, 0, 0 },
};
int c;

c = getopt_long(argc, argv, "D:s:d:b:lHOLC3", 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;
default:
print_usage(argv[0]);
break;
}
}
}

int main(int argc, char *argv[])
{
int ret = 0;
int fd;
unsigned char test_write[4] = {0};
unsigned char test_read[4] = {0};
//unsigned char buf1, buf2, buf3, buf4;
uint8_t buf1[2], buf2[2], buf3[2], buf4[2];
int a1, a2, a3, a4, i, j;

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);

printf("Please Input(xx xx xx xx): ");
//scanf("%s %s %s %s", &buf1, &buf2, &buf3, &buf4 );
scanf("%s %s %s %s", buf1, buf2, buf3, buf4 );
a1 = StrToHex(buf1);
a2 = StrToHex(buf2);
a3 = StrToHex(buf3);
a4 = StrToHex(buf4);
//printf("------------a1 = %x a2 = %x a2 = %x a2 = %x/n", a1, a2, a3, a4);
test_write[0] = a1;
test_write[1] = a2;
test_write[2] = a3;
test_write[3] = a4;
//printf("buf1 = %x buf2 = %x buf3 = %x buf4 = %x/n", buf1, buf2, buf3, buf4);

while(1)
{
write(fd, test_write, sizeof(test_write));
read(fd, test_read, sizeof(test_read));

for(j = 0; j < sizeof(test_read); j++)
{
printf("test_write[%d] = %x ", j, test_write[j]);

printf("test_read[%d] = %x", j, test_read[j]);
printf("/n");
}
//transfer(fd);
}
close(fd);
return ret;
}

int StrToHex( char *p )
{
int i, sum;
int temp, length;
char c;
sum = 0;
length = strlen( p );
for( i = 0; i < length ; i++ )
{
// Modify in 2010-09-19 by Lijun Hua, 讲字母转化成16进制数
c = *p;
if( c >= 'a' && c <= 'z')
{
temp = c - 87;
sum += (temp)* ( pow(16, (length - i - 1)) );
}
else if( c >= 'A' && c <= 'Z')
{
temp = c - 55;
sum += (temp)* ( pow(16, (length - i - 1)) );
}
else
{
temp = c - 48;
sum = sum + ( temp ) * pow(16, ( length - i - 1 ) ); //double pow(double x, double y);x 的 y 次方 xy
}

p = p + 1;
}
return sum;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: