реклама на сайте
подробности

 
 
> AT91SAM960 - не работает SPI
Pasa
сообщение Nov 21 2009, 08:28
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 107
Регистрация: 4-03-09
Из: Беларусь, Минск
Пользователь №: 45 665



Процессор AT91SAM9260

Из документации ядра 2.6.28 взял пример работы с SPI - spidev_test.c
В конфигурации ядра сделал все как описывали на форуме. Все подключилось.
В /dev появилось устройство spidev. Пример заработал - обращения к драйверу проходят.
Передача вроде должна идти.А вот данных осцилографом не вижу.

Распечатал на консоль значения портов и регистров SPI - режимы вроде установлены верно.
А передачи нет. При этом датафлэш висящая на SPI работает отлично, и когда идет
обращение к ней, то осцилографом все прекрасно видно.

Подскажите в чем тут загвоздка?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Pasa
сообщение Nov 25 2009, 16:17
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 107
Регистрация: 4-03-09
Из: Беларусь, Минск
Пользователь №: 45 665



Эксперименты привели к следующему: вызовы write и read прекрасно работают. А если через ioctl вызывать spidev_ioctl(для полнодуплексного обмена), то из драйвера SPI (atmel_spi.c) идет возврат с ошибкой опций устновленного протокола. И естественно передачи никакой нет. По исходнику посмотрел - там где анализ на нулевую скорость передачи и ноль бит в слове. В уровень spidev.c структура с параметрами доходит нормально(параметры ставятся в верхнем юзерском слое в самой проге). А потом где-то теряются/затираются/обнуляются и до дравера SPI не доходят. Вот счас пробую проследить всю цепочку...

Мда....вот уж не ожидал таких плясок с бубном....не покидает ощущение, что ну не может быть таких ошибок в ядре и я не совсем правильно пользуюсь вызовами ioctl(). Но ведь все взято из примера в документации которая идет с самим ядром. Хотя с другой стороны в этом самом примере сходу нашел одну описку/опечатку/ошибку.

Может кто сталкивался с таким и подскажет что-нибудь дельное? Уж больно не хочется лезть в потроха ядра, править его и с ужасом думать о следущих "танцах", когда придется браться за сокеты и шину I2C
Go to the top of the page
 
+Quote Post
lamination
сообщение Nov 26 2009, 08:56
Сообщение #3


Участник
*

Группа: Свой
Сообщений: 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);
Go to the top of the page
 
+Quote Post
Pasa
сообщение Nov 26 2009, 10:05
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 107
Регистрация: 4-03-09
Из: Беларусь, Минск
Пользователь №: 45 665



to lamination:

Ваш пример сразу заработал. Огромное спасибо.

В примере из документации по ядру main() организована по другому. Хотя там структура на передачу вроде инициализируется.
Попробую найти где же там допущены неточности из-за которых видимо этот пример и не работает. Вообщем даже интерсно....покопаюсь.

Еще раз огромное спасибо. Похоже дело сдвинулось с мертвой точки
Go to the top of the page
 
+Quote Post
Pasa
сообщение Nov 27 2009, 15:58
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 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 работает отлично, никаких проблем отмечено пока не было.
Все вышесказанное сугубо ИМХО, если ошибся где - поправьте. Надеюсь это поможет остальным избежать граблей,
на которые наступил я.

Еще раз всем спасибо за помощь и внимание.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 05:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.01906 секунд с 7
ELECTRONIX ©2004-2016