|
AT91SAM960 - не работает SPI |
|
|
|
 |
Ответов
|
Nov 26 2009, 08:56
|
Участник

Группа: Свой
Сообщений: 42
Регистрация: 11-04-06
Пользователь №: 16 019

|
Код #include <stdio.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h>
#include <linux/types.h> #include <linux/spi/spidev.h>
int main(){ int fd; int status; unsigned char u8_ret; unsigned int u32_ret; struct spi_ioc_transfer xfer[2]; unsigned char buf[10]; fd = open("/dev/spi1.1",O_RDWR); if (fd == -1){ printf("error on open device,%d\n",fd); return -1; } status = ioctl(fd,SPI_IOC_RD_MODE,&u8_ret); printf("RD_MODE(%d) :0x%x,",status,u8_ret); status = ioctl(fd,SPI_IOC_RD_LSB_FIRST,&u8_ret); printf("LSB_FIRST(%d) :0x%x,",status,u8_ret); status = ioctl(fd,SPI_IOC_RD_BITS_PER_WORD,&u8_ret); printf("BITS_PER_WORD(%d) :0x%x,",status,u8_ret); status = ioctl(fd,SPI_IOC_RD_MAX_SPEED_HZ,&u32_ret); printf("MAX_SPEED_HZ(%d) :0x%x\n",status,u32_ret); u8_ret = 8; status = ioctl(fd,SPI_IOC_WR_BITS_PER_WORD,&u8_ret); printf("set BITS_PER_WORD(%d) :0x%x\n",status,u8_ret);
u32_ret = 1000000; status = ioctl(fd,SPI_IOC_WR_MAX_SPEED_HZ,&u32_ret); printf("set MAX_SPEED_HZ(%d) :0x%x\n",status,u32_ret); memset(xfer, 0, sizeof xfer); memset(buf, 0, sizeof buf); buf[0] = 0xaa; xfer[0].tx_buf = (__u64) buf; xfer[0].len = 1; xfer[1].rx_buf = (__u64) buf; xfer[1].len = 4;
status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer); printf("ioctl return %d\n",status); printf("buf[0]=%d, buf[1]=%d, buf[2]=%d\n",buf[0],buf[1],buf[2]); return 0; } В board-sam9260ek.c : Код ..... static struct spi_board_info ek_spi_devices[] = { .... { /* SPI device 1,CS 0*/ .modalias = "spidev", .chip_select = 0, .max_speed_hz = 15 * 1000 * 1000, .bus_num = 1, }, { /* SPI device 1, CS 1*/ .modalias = "spidev", .chip_select = 1, .max_speed_hz = 15 * 1000 * 1000, .bus_num = 1, }, { /* SPI device 1, CS 2*/ .modalias = "spidev", .chip_select = 2, .max_speed_hz = 15 * 1000 * 1000, .bus_num = 1, }, { /* SPI device 1, CS 3*/ .modalias = "spidev", .chip_select = 3, .max_speed_hz = 15 * 1000 * 1000, .bus_num = 1, }, .... } Ядро версии 2.6.30 Если работают read и write, то вероятней всего вы забыли сделать memset(xfer, 0, sizeof xfer);
|
|
|
|
|
Nov 27 2009, 15:58
|
Частый гость
 
Группа: Свой
Сообщений: 107
Регистрация: 4-03-09
Из: Беларусь, Минск
Пользователь №: 45 665

|
Итак, небольшое резюме по итогам работы с SPI для AT91SAM9260(ядро 2.6.28):
Начну с конца, с драйвера шины SPI (файл atmel_spi.c) В функции atmel_spi_transfer() есть такой код:
if (xfer->bits_per_word || xfer->speed_hz) {
dev_dbg(&spi->dev, "no protocol options yet\n"); return -ENOPROTOOPT; }
xfer->bits_per_word и xfer->speed_hz собственно и есть те самые параметры, которые передаются в драйвер из пользовательского приложения, где инциализируется структура spi_ioc_transfer. Если эти параметры не обнулить(всю структуру нулить не обязательно, достаточно только этих двух) то мы и нарываемся на "отлуп" в виде "no protocol options yet". Для чего это сделано я не разбирался. Вроде логичным было-бы сделать наооборот - считать ошибкой когда параметры передачи не установлены или сброшены в ноль. Ведь эти самые структуры spi_ioc_transfer можно паковать в массивы и подсовывать драйверу для передачи через вызов ioctl(fd, SPI_IOC_MESSAGE(кол-во мессаг), адрес_массива_структур); При этом была бы теоретическая возможность каждую мессагу слать с собственными параметрами передачи(понятно, что для этого нужно было-бы драйверу перепрограммировать аппаратные регистры контроллера SPI). Возможно это невозвожно(пардон за тавталогию) или есть какие-либо причины мне неизвестные. А может я просто до конца не разобрался. Но сделано так, как сделано.
Поэтому всем, кто как и я будет юзать пример работы с SPI, взятый из документации ядра, файл spidev_test.c: перед вызовом ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
сделайте как минимум tr.speed_hz = 0; tr.bits_per_word = 0;
Без этого будете получать "no protocol options yet" .
И еще одна описка/опечатка: ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); if (ret == 1) pabort("can't send spi message");
Привильно будет if (ret < 0) т.к. в ret при успешной передаче будет возвращаться ОБЩЕЕ число переданных/принятых байт во ВСЕЙ пачке(массиве) структур, которые мы подготовили к моменту вызова
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); // здесь передается ОДНО сообщение по SPI
Если сделать ret = ioctl(fd, SPI_IOC_MESSAGE(5), array_st_mess_spi) - то будет передано 5 сообщений из массива структур array_st_mess_spi, которые мы должны предварительно подготовить, а именно - проинициализировать указатели на приемо/передающие буфера, длину передачи и ОБНУЛИТЬ speed_hz и bits_per_word. И в ret вернется ОБЩЕЕ число переданных байт всех 5 посылок.
В случае неудачи у меня было ret < 0 .
Вот собственно и все. На сегодняшний момент SPI работает отлично, никаких проблем отмечено пока не было. Все вышесказанное сугубо ИМХО, если ошибся где - поправьте. Надеюсь это поможет остальным избежать граблей, на которые наступил я.
Еще раз всем спасибо за помощь и внимание.
|
|
|
|
Сообщений в этой теме
Pasa AT91SAM960 - не работает SPI Nov 21 2009, 08:28 vmp Нет только данных или тактов тоже? Nov 21 2009, 09:57 Pasa Цитата(vmp @ Nov 21 2009, 13:27) Нет толь... Nov 21 2009, 23:52 vmp Тут уже ничего не подскажу - проблема явно не с же... Nov 22 2009, 13:32 Pasa Может кто подскажет точку входа и в каком файле ис... Nov 23 2009, 02:47    A.t.a.m.a.n Цитата(Pasa @ Nov 27 2009, 18:58) Итак, н... Sep 5 2011, 11:12 coolzero Добрый день. я новичёк в линуксе, начал разбиратьс... Jun 16 2010, 08:56
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|