Linux - Доступ к шине SPI из пространства пользователя |
Предыдущая Содержание Следующая |
http://brew-j2me.blogspot.com/
Android Karthik Thursday, May 6, 2010
Должен быть способ общения с вашим оборудованием, чтобы написать сложный драйвер устройства. В этой заметке мы увидим, как можно использовать для связи с устройством из пользовательского пространства шину SPI.
Чтобы включить взаимодействие с SPI из пользовательского пространства, необходимо его разрешить в ядре.
Давайте сначала посмотрим основные настройки ядра, необходимые для включения поддержки SPI.
CONFIG_SPI CONFIG_SPI_MASTER CONFIG_SPI_SPIDEV
CONFIG_SPI_SPIDEV разрешает для нас ядро SPI пользовательского пространства.
Большинство процессоров для увеличения производительности и простоты использования имеют встроенный модуль шины SPI. Если ваша платформа имеет соответствующий драйвер устройства Linux, включите соответствующую опцию.
Например, для платформы OMAP24xx или OMAP34xx необходимо включить CONFIG_SPI_OMAP24XX, чтобы использовать встроенный в процессор модуль McSPI.
Теперь для экспорта шины SPI в пространство пользователя необходимо настроить файл платы.
Добавляем этот кусочек кода в файл board*.c.
/* Structure for configuing McSPI */ static struct spi_board_info board_spi3_board_info[] = { { .modalias = "spidev",/* Представление SPI в пространстве пользователя */ .max_speed_hz = 500000, /* Скорость SPI. */ .bus_num = 3, /* Номер шины McSPI */ .chip_select = 0, /* Выбор кристалла для McSPI */ .mode = 0, /* Режим SPI */ }, };
и добавляем регистрацию шины SPI в функцию board_init файла board*.c.
/* Регистрируем SPI устройство */ spi_register_board_info(board_spi3_board_info, ARRAY_SIZE(board_spi3_board_info));
Теперь после загрузки системы вы должны увидеть в файловой системе ваше SPI устройство в каталоге /dev, например, /dev/spidev2.0 (2 - номер шины SPI, 0 - выбор кристалла).
Для передачи и приёма SPI сообщений устройству /dev/spidevx.y можно использовать стандартные вызовы open, read, write и close.
Открыть устройство SPI можно используя следующий вызов:
int fd = 0; fd = open("/dev/spidev2.0", O_RDWR); if (fd < 0) { printf("SPI : can't open device"); return -1; }
Теперь, используя вызовы ioctl можно настроить SPI.
Установка режима SPI:
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); if (ret == -1) { printf("SPI : can't set spi mode"); return 1; }
Запрос режима SPI
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); if (ret == -1) { printf("SPI : can't get spi mode"); return 1; }
Другими параметрами шины SPI можно управлять аналогичным способом.
Теперь посылаем сообщение через шину SPI, для этого необходимо заполнить структуру сообщения и передать её вниз.
struct spi_ioc_transfer mesg[1] = { 0, };
mesg[0].tx_buf = (unsigned long)out_buffer; mesg[0].len = num_out_bytes;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), mesg); To receive SPI message struct spi_ioc_transfer mesg[1] = { 0, };
mesg[0].rx_buf = (unsigned long)out_buffer; mesg[0].len = num_out_bytes;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), mesg);
Могут быть требования, чтобы запись, следующая за чтением, происходила без переключения сигнала выбора кристалла. Для обработки таких ситуаций можно сформировать 2 сообщения, как показано ниже.
int spidev_if_write_read(unsigned int num_out_bytes, unsigned char *out_buffer, unsigned int num_in_bytes, unsigned char *in_buffer) { struct spi_ioc_transfer mesg[2] = { 0, }; uint8_t num_tr = 0; int ret;
if((out_buffer != NULL) && (num_out_bytes != 0)) { mesg[0].tx_buf = (unsigned long)out_buffer; mesg[0].rx_buf = (unsigned long)NULL; mesg[0].len = num_out_bytes; mesg[0].cs_change = 0; num_tr++; }
if((in_buffer != NULL) && (num_in_bytes != 0)) { mesg[1].tx_buf = (unsigned long)NULL; mesg[1].rx_buf = (unsigned long)in_buffer; mesg[1].len = num_in_bytes; num_tr++; }
if(num_tr > 0) { ret = ioctl(fd, SPI_IOC_MESSAGE(num_tr), mesg); if(ret == 1) { return 1; } }
return 0; }
Переменная cs_change=0 запрещает изменение состояния сигнала CS между двумя транзакциями.
|
Предыдущая Содержание Следующая |