|
Драйвер, написать самому |
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 23)
|
Nov 12 2012, 11:20
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
Цитата(Dubov @ Nov 12 2012, 14:21)  Просто ранее я писал только standalone приложения и смущает отсутствие в Linux процедур прямого обращения к регистрам (здесь всё через обёртки какие то мудрёные). Это не так, именно через прямое обращение к регистрам SoC в адресном пространстве и происходит взаимодействие с железом. Цитата(Dubov @ Nov 12 2012, 14:21)  В линукс смущает то что нету так привычных мне *.h файлов где через дефайны описаны адреса всех регистров (по мануалу). Они как правило есть, но не всегда на _все_ регистры. Для написания драйвера _устройства_ подключённого через spi слейвом, обращаться напрямую к железу не надо - это делает драйвер spi контроллера (мастера).
|
|
|
|
|
Nov 12 2012, 12:46
|
Местный
  
Группа: Участник
Сообщений: 408
Регистрация: 28-05-12
Пользователь №: 72 052

|
Цитата(Idle @ Nov 12 2012, 15:20)  Это не так, именно через прямое обращение к регистрам SoC в адресном пространстве и происходит взаимодействие с железом.
Они как правило есть, но не всегда на _все_ регистры.
Для написания драйвера _устройства_ подключённого через spi слейвом, обращаться напрямую к железу не надо - это делает драйвер spi контроллера (мастера). так вот этот драйвер мастера, насколько я могу понять, не может складывать данные в буфер произвольной длины, а только работает через read() или write(). Таким образом считать данные из ацп в пространстве пользователя нельзя, точнее можно, но данные будут не нерпрерывные, а спотреями, ввиду латентности операционки. Выход: написать драйвер "с нуля" на уровне ядра. как? пока сложно себе представляю... увидеть бы пример работы с SPI через DMA в драйвере. Цитата(xor.kruger @ Nov 12 2012, 15:54)  Сначала ознакомьтесь с принципами функционирования подсистемы SPI в ОС GNU/Linux. Инфа есть в каталоге Documentation/spi исходников ядра или например в книге Essential Linux Device Drivers. Также для примера можете подсмотреть как соведуют делать для семейства чипов AT91SAM9X link подсистема iio - мутная вещь. По моему намного проще обращаться к регистрам как в standalone приложении. Как раз для SAM9260 писал именно "напрямую" через SPI DMA, взяв пример кода из проекта плейера (тоже без ос). Получилось просто и быстро: standalone процедура превратилась в драйвер уровня ядра. Тем более, в книге Linux Device drivers написано что на уровне ядра к регистрам можно обращаться напрямую. IIO выдумали якобы для унифицирования, но мне показалось там слишком всё усложнено.Тем более из общения с разработчиками драйверов из AD я так и не смог выяснить зачем они написали софтовое тактирование АЦП из юзерспейс. Это же идиотизм: тактировать промышленный АЦП клоком с непредсказуемым джиттером. Отвлёкся от темы.
|
|
|
|
|
Nov 12 2012, 13:24
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
Цитата(Dubov @ Nov 12 2012, 16:46)  так вот этот драйвер мастера, насколько я могу понять, не может складывать данные в буфер произвольной длины, а только работает через read() или write() а как должно происходить чтение? вот есть, например, spi_w8r16 два байта читает - почему она не подходит?
Сообщение отредактировал Idle - Nov 12 2012, 13:25
|
|
|
|
|
Nov 12 2012, 13:39
|
Местный
  
Группа: Участник
Сообщений: 408
Регистрация: 28-05-12
Пользователь №: 72 052

|
Цитата(Idle @ Nov 12 2012, 17:24)  а как должно происходить чтение? вот есть, например, spi_w8r16 два байта читает - почему она не подходит? Вообще планировалось сделать так: завести на уровне ядра большущий буфер(около 1 МБ), а чтение происходит в самом драйвере, пусть по 2 байта, но складываться всё должно тоже в буфер на уровне ядра (в тот самый большой буфер). В приложении же отобразить буфер в юзерспейс и читать указатель, который возвращает драйвер. Иными словами: User mode SPI device driver support - не подходит. P.S. Возможно я чего-то не понимаю. Все реализации что я до этого видел предлагают править файл борды и активировать User mode SPI device driver support. Но это не подходит. Цитата(Idle @ Nov 12 2012, 17:24)  а как должно происходить чтение? вот есть, например, spi_w8r16 два байта читает - почему она не подходит? и это как я понял, не DMA чтение
|
|
|
|
|
Nov 12 2012, 14:04
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
Цитата(Dubov @ Nov 12 2012, 17:39)  Вообще планировалось сделать так: завести на уровне ядра большущий буфер(около 1 МБ), а чтение происходит в самом драйвере, пусть по 2 байта, но складываться всё должно тоже в буфер на уровне ядра (в тот самый большой буфер). тогда можно выделить в драйвере буфер, периодически дёргать (через таймер, например) чтение по spi, складывать полученные данные в буфер создать в драйвере chardev и отдавать буфер при чтении из созданного файла как такой вариант?
|
|
|
|
|
Nov 12 2012, 15:25
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
Цитата(Dubov @ Nov 12 2012, 18:56)  Насколько я понял мне все пытаются объяснить что линукс предоставляет независимость от платформы даже в таких задачах (чтиение зSPI по DMA в модуле ядра). нет, пишу как я бы это делал Цитата(Dubov @ Nov 12 2012, 18:56)  А мне нужно потоковое накопление в буфере и периодическая отдача в юзерспейс. ну вот и накапливайте в буфере периодически читая при помощи дравера мастера, а в чём разница при чтении из полностю своего кода и при использовании драйвера? updя понял - вы хотите зарядить dma на чтение по spi  тогда линуксовая подсистема spi тут не нужна совсем, смотрите на реализацию мастера для своего SoC и пишите что нужно работа с регистрами происходит так же как и на bare metal - они в памяти работа с dma - через линуксовый api, с ним мне работать не приходилось
Сообщение отредактировал Idle - Nov 12 2012, 15:26
|
|
|
|
|
Nov 12 2012, 19:17
|
Местный
  
Группа: Участник
Сообщений: 408
Регистрация: 28-05-12
Пользователь №: 72 052

|
Цитата(Idle @ Nov 12 2012, 19:25)  ну вот и накапливайте в буфере периодически читая при помощи дравера мастера, а в чём разница при чтении из полностю своего кода и при использовании Я думал всегда что в скорости. Если считывать из юзерспейс то можно пропустить данные. Частота дисркетизации АЦП 100kSps. В модуле же ядра, если считывать по DMA можно напихать большой буфер без пропусков и потом из юзерспеейс потихонечку грести. Как вариант, можно на ПЛИС сделать буфер, чтобы просто из юзерспейс забирать даные, но это за рамками топика. Вот и пытаюсь: 1) найти примеры для OMAP DMA SPI без ОС (standalone), чтобы оформить как модуль ядра. либо 2) какие-то средства линукса (api для DMA на уровне ядра) Цитата(Idle @ Nov 12 2012, 19:25)  работа с регистрами происходит так же как и на bare metal - они в памяти я пока даже *.h-файл описания регистров для OMAP не нашёл. Настолько всё запутано в исходниках. Эх, у Atmela в этом было много проще и нагляднее (AT91SAM9260.h - и всё)
Сообщение отредактировал Dubov - Nov 13 2012, 10:26
|
|
|
|
|
Nov 13 2012, 12:03
|

Местный
  
Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091

|
Цитата(Dubov @ Nov 13 2012, 00:17)  Я думал всегда что в скорости. Если считывать из юзерспейс то можно пропустить данные. Частота дисркетизации АЦП 100kSps. В модуле же ядра, если считывать по DMA можно напихать большой буфер без пропусков и потом из юзерспеейс потихонечку грести. Вам Idle так и предлагает - создать большой ядерный буфер и пихать туда данные непрерывно без пропусков. А потом из юзерспейса через read() накопленные в ядерном буфере данные выгребать. Вы говорили, что Вам не нравится получать данные путем чтения файла устройства. Почему? Фактически, такое чтение - просто копирование данных из одного участка памяти в другой...
--------------------
Всего наилучшего, Alex Mogilnikov
|
|
|
|
|
Nov 13 2012, 12:08
|
Местный
  
Группа: Участник
Сообщений: 408
Регистрация: 28-05-12
Пользователь №: 72 052

|
Цитата(alx2 @ Nov 13 2012, 16:03)  Вам Idle так и предлагает - создать большой ядерный буфер и пихать туда данные непрерывно без пропусков. А потом из юзерспейса через read() накопленные в ядерном буфере данные выгребать. Вы говорили, что Вам не нравится получать данные путем чтения файла устройства. Почему? Фактически, такое чтение - просто копирование данных из одного участка памяти в другой... хорошо, чтение - это просто метод забрать данные. Мне нужен метод положить данные в буфер. Причём в большой буфер. пока нашёл вот что: spi-omap2-mcspi.c как настроить на приём по DMA ума не приложу(
Сообщение отредактировал Dubov - Nov 13 2012, 12:09
|
|
|
|
|
Nov 13 2012, 16:14
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
Цитата(alx2 @ Nov 13 2012, 16:03)  Вам Idle так и предлагает - создать большой ядерный буфер и пихать туда данные непрерывно без пропусков. А потом из юзерспейса через read() накопленные в ядерном буфере данные выгребать. Вы говорили, что Вам не нравится получать данные путем чтения файла устройства. Почему? Фактически, такое чтение - просто копирование данных из одного участка памяти в другой... ему надо опрашивать ацп со скоростью 100KS/s т.е. каждые 10 мкс программно через таймеры или delayed work это не получится т.к. слишком часто вопрос тут - как написать свой драйвер spi мастера для конкретного железа под эти нужды
|
|
|
|
|
Nov 13 2012, 17:59
|
Местный
  
Группа: Участник
Сообщений: 408
Регистрация: 28-05-12
Пользователь №: 72 052

|
Цитата(Idle @ Nov 13 2012, 20:14)  ему надо опрашивать ацп со скоростью 100KS/s т.е. каждые 10 мкс программно через таймеры или delayed work это не получится т.к. слишком часто вопрос тут - как написать свой драйвер spi мастера для конкретного железа под эти нужды Именно так. Например подобное делал для SAM9, взяв пример из проекта wav-плейера. Там по DMA с флешки по SPI считывание происходило. CODE //------------------------------------------------------------------------------ /// Use PDC for SPI data transfer. /// Return 0 if no error, otherwise return error status. /// \param pSdSpi Pointer to a SdSpi instance. /// \param pData Data pointer. /// \param size Data transfer byte count. //------------------------------------------------------------------------------ unsigned char SDSPI_PDC_read(SdSpi *pSdSpi, unsigned char *pData, unsigned int size) { AT91PS_SPI pSpiHw = pSdSpi->pSpiHw; unsigned int spiIer;
// Enable the SPI clock AT91C_BASE_PMC->PMC_PCER = (1 << pSdSpi->spiId);
// Disable transmitter and receiver pSpiHw->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
// Receive Pointer Register pSpiHw->SPI_RPR = (unsigned long)pData; // Receive Counter Register pSpiHw->SPI_RCR = size; // Transmit Pointer Register pSpiHw->SPI_TPR = (unsigned long)dummy_ff_block; // Transmit Counter Register pSpiHw->SPI_TCR = size;
// spiIer = AT91C_SPI_RXBUFF;
// Enable transmitter and receiver pSpiHw->SPI_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN; while(! (pSpiHw->AT91C_SPI_SR & AT91C_SPI_ENDRX)); pSpiHw->AT91C_SPI_PTCR = AT91C_PDC_RXTDIS; pSpiHw->AT91C_SPI_PTCR = AT91C_PDC_TXTDIS; // Interrupt enable shall be done after PDC TXTEN and RXTEN // pSpiHw->SPI_IER = spiIer;
return 0; } вобщем там свелось всё к умелому обращение с регистрами SPI_RPR, SPI_RCR, SPI_TPR, SPI_TCR. Для OMAP не думаю что сложнее, но, зараза, не могу понять... Другой вопрос: почему в Linux драйверах всё так сложно? никогда не увидишь имён регистров прямых, всё через структуры структур структур и т.д. ? безопасность? универсальность?
Сообщение отредактировал Dubov - Nov 13 2012, 18:01
|
|
|
|
|
Nov 13 2012, 20:00
|
Частый гость
 
Группа: Участник
Сообщений: 167
Регистрация: 15-08-07
Пользователь №: 29 803

|
Простейший способ "в лоб" - это char device, внутри которого 2 буфера, в один пишем, другой готов к чтению из приложения через read(). При заполнении одного буфера DMA перезапускается на другой буфер. Либо "дмашить" в кольцевой буфер. Как сделать лучше - см. спеки на железо. Есть нюансы  Во-первых, вам нужно перезапустить DMA за 10мкс (по прерыванию, например). Не факт, что вы успеете, т.к. если обращение к регистру занимает (к примеру) 1мкс, а вам нужно перезаписать 5шт - это уже 10мкс. Некоторые DMA умны настолько, что могут сами брать дескрипторы из памяти и закольцовываться по их списку. В этом случае перезапускать DMA нет необходимости. Если это не так и терять данные нельзя вообще - то вы близки к теоретическому пределу железа - опять же, см. спеки на железо. Во-вторых, при использовании своего char dev нужно убедиться, что никто через линуксовый SPI-фреймворк не обращается к SPI контроллеру (и через DMA фреймворк тоже). Что касается "сложности" драйверов в linux - это нормально  На самом деле там все довольно просто - почти все разбито на слои и фреймворки для облегчения портируемости и расширения. Фактически, там используется ООП подход, со всеми вытекающими. В итоге вход в это хозяйство усложняется (и кажется странным для людей работавших до этого с МК осями/bare metal), но иначе никак. Вообще, такой подход характерен для всех не-tiny мультиплатформенных ОС. P.S. Есть фреймворк comedi, все еще стандарт де-факто для data acquisition. Но 100К семплов/с - немалая величина, и с ней оверхед фреймворка может стать неприемлемым.
|
|
|
|
|
Nov 14 2012, 04:50
|

Местный
  
Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091

|
Цитата(Idle @ Nov 13 2012, 21:14)  ему надо опрашивать ацп со скоростью 100KS/s т.е. каждые 10 мкс программно через таймеры или delayed work это не получится т.к. слишком часто Опросы с нужной скоростью может обеспечить контроллер SPI. Если размер сэмпла, допустим, 16 бит, то установив скорость шины SPI 1600 кбит/с, автоматически получим скорость опроса 100 kS/s. Насколько я понял, проблема в том, что не допускается появление джиттера. А это IMHO скорее железо-специфичная чем linux-специфичная проблема. vshemm об этом уже все сказал. Если требуется за 10 мкс "вручную" по прерыванию перезаряжать DMA, то напрашивается мысль о реализации своего SPI-контроллера со встроенной буферизацией на ПЛИС...
--------------------
Всего наилучшего, Alex Mogilnikov
|
|
|
|
|
Nov 14 2012, 05:37
|
Местный
  
Группа: Участник
Сообщений: 408
Регистрация: 28-05-12
Пользователь №: 72 052

|
Цитата(vshemm @ Nov 14 2012, 00:00)  Простейший способ "в лоб" - это char device, внутри которого 2 буфера, в один пишем, другой готов к чтению из приложения через read(). При заполнении одного буфера DMA перезапускается на другой буфер. Либо "дмашить" в кольцевой буфер. так я и хотел делать! как работать с DMA на OMAP?! Ищу примеры, а пока курю даташит, но это путь через пустыню... Цитата(alx2 @ Nov 14 2012, 08:50)  Опросы с нужной скоростью может обеспечить контроллер SPI. Если размер сэмпла, допустим, 16 бит, то установив скорость шины SPI 1600 кбит/с, автоматически получим скорость опроса 100 kS/s. Насколько я понял, проблема в том, что не допускается появление джиттера. А это IMHO скорее железо-специфичная чем linux-специфичная проблема. vshemm об этом уже все сказал. Если требуется за 10 мкс "вручную" по прерыванию перезаряжать DMA, то напрашивается мысль о реализации своего SPI-контроллера со встроенной буферизацией на ПЛИС... А вот и нет. Без Linux в standalone всё делается просто и быстро. Из изерспейс просто нельзя так быстро дёргать SPI. Из юерспейс можно, например, неспешно опрашивать датчик температуры. ГОСПОДА! Прошу посмотреть намётаным глазом статью: http://habrahabr.ru/post/123266/там в разделе "4.Разработка протокольного SPI драйвера уровня ядра" упоминается DMA. Никак не могу понять. Они применяют какой-то DMA API? неужели то что мне надо...
Сообщение отредактировал Dubov - Nov 14 2012, 05:49
|
|
|
|
|
Nov 14 2012, 06:31
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
Цитата(Dubov @ Nov 14 2012, 09:37)  А вот и нет. Без Linux в standalone всё делается просто и быстро. Из изерспейс просто нельзя так быстро дёргать SPI. Из юерспейс можно, например, неспешно опрашивать датчик температуры. Тут дело не в юзерспейс, из ядра (kernel space) тоже нельзя так быстро дёргать программно. Просто в ядре можно настроить dma на приём. Цитата(Dubov @ Nov 14 2012, 09:37)  Прошу посмотреть намётаным глазом статью: http://habrahabr.ru/post/123266/там в разделе "4.Разработка протокольного SPI драйвера уровня ядра" упоминается DMA. Никак не могу понять. Они применяют какой-то DMA API? неужели то что мне надо... нет, там описана разравботка драйвера устройства, подключённого к spi слейвом этот драйвер использует драйвер мастера через стандартный набор функций я не думаю, что вы найдёте похожий пример т.к. то, что вам надо к линуксовой подсистеме spi отношения не имеет посмотрите в вашем драйвере spi omap работу с регистрами и dma (если используется) - а дальше сами
|
|
|
|
|
Nov 14 2012, 06:53
|
Местный
  
Группа: Участник
Сообщений: 408
Регистрация: 28-05-12
Пользователь №: 72 052

|
Цитата(Idle @ Nov 14 2012, 10:31)  посмотрите в вашем драйвере spi omap работу с регистрами и dma (если используется) гдеж эти примеры взять  яж толкьо с SAM9 работал
Сообщение отредактировал Dubov - Nov 14 2012, 06:53
|
|
|
|
|
Nov 14 2012, 11:01
|
Местный
  
Группа: Участник
Сообщений: 408
Регистрация: 28-05-12
Пользователь №: 72 052

|
Господа! Вопрос на засыпку: если 100кГц частота дискретизации АЦП для Linux - слишком быстро, то как понять такое: http://wiki.analog.com/resources/tools-sof.../iio-adc/ad7998как они собираются успевать данные забирать?
|
|
|
|
|
Nov 14 2012, 12:42
|
Местный
  
Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874

|
Цитата(Dubov @ Nov 14 2012, 10:53)  гдеж эти примеры взять  а вы дайте ссылку на исходники драйвера вашего spi мастера, я думаю народ подскажет какие макросы там используются для чтения-записи регистров и где лежат определения регистров Цитата(Dubov @ Nov 14 2012, 15:01)  Господа! Вопрос на засыпку: если 100кГц частота дискретизации АЦП для Linux - слишком быстро, то как понять такое: http://wiki.analog.com/resources/tools-sof.../iio-adc/ad7998как они собираются успевать данные забирать? я так понят тут вот чего - есть т.н. software triggers и hardware triggers последние(timer counter или внешний источник) вызывают прерывания с нужной частотой и успеть можно частота софтовых триггеров ограничена
|
|
|
|
|
Nov 14 2012, 20:53
|
Частый гость
 
Группа: Участник
Сообщений: 167
Регистрация: 15-08-07
Пользователь №: 29 803

|
Цитата(Dubov @ Nov 14 2012, 09:37)  так я и хотел делать! как работать с DMA на OMAP?! Ищу примеры, а пока курю даташит, но это путь через пустыню... Совершенно нормальный путь  Цитата(Dubov @ Nov 14 2012, 09:37)  А вот и нет. Без Linux в standalone всё делается просто и быстро. Из изерспейс просто нельзя так быстро дёргать SPI. Из юерспейс можно, например, неспешно опрашивать датчик температуры. Дергать SPI не надо, нужно запускать DMA как уже сказал Idle. Цитата(Dubov @ Nov 14 2012, 15:01)  Господа! Вопрос на засыпку: если 100кГц частота дискретизации АЦП для Linux - слишком быстро, то как понять такое: ... 100КГц быстро не для линукса, а для железа, если данные читать процессором ("дергать SPI"). Если же есть нормальный DMA, то тот же linux держит десятки и сотни МГц через iio или comedi.
|
|
|
|
|
Nov 15 2012, 11:27
|
Знающий
   
Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464

|
Цитата(vshemm @ Nov 15 2012, 00:53)  100КГц быстро не для линукса, а для железа, если данные читать процессором ("дергать SPI"). Если же есть нормальный DMA, то тот же linux держит десятки и сотни МГц через iio или comedi. как он может тянуть сотни мегагерц, если через IIO я запускал родной драйвер от AnalogDevices и при частоте 100кГц загрузка процессора была более 50%. А ещё они зачем-то software trigger придумали (дураки чтоли?), который, например, при обновлении экрана файлового менеджера MC просто переставал генерить меандр. Ну и нафиг тако тригер нужен спрашивается? Железный другое дело, но всё равно прерывания 100 000 раз в секунду - слишком много для Linux. Для AT91 был вариант без прерываний (на двух таймерах) на DMA - другое дело.
Сообщение отредактировал Zelepuk - Nov 15 2012, 11:51
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|