LINUX.ORG.RU

IIO ADC: не стартует циклическое преобразование по триггеру sysfs

 


0

3

Ку. Вступление: есть драйвер АЦП ADS8638 чере IIO, в нем обработчик прерывания с проталкиванием данных от SPI в кольцевой буфер iio. Запуск сбора от триггера sysfs (sysfstrig1): echo 1 > /sys/bus/iio/devices/iio_sysfs_trigger/trigger1/trigger_now. Чтение данных примером generic_buffer.c из устройства /dev/iio:device1 с блокировкой через вызов poll. Пример:

/* Обработчик */
static irqreturn_t ads8638_trigger_handler(int irq, void *p)
{
	struct iio_poll_func *pollfunc = p;
	struct iio_dev *idev = pollfunc->indio_dev;
	struct ads8638_state *state = iio_priv(idev);
	ssize_t ts_offset;
	u16 buf;
	int ret;

	ret = spi_read(state->spi, (u8 *)&state->rx_buf[0], 2);

	if (idev->scan_timestamp) {
		ts_offset = idev->scan_bytes / sizeof(s64) - 1;
		((s64 *)state->rx_buf)[ts_offset] = pollfunc->timestamp;
	}

	iio_push_to_buffers(idev, (u8 *)state->rx_buf);
	iio_trigger_notify_done(idev->trig);

	return IRQ_HANDLED;
}

/* Настройка в probe */
ret = iio_triggered_buffer_setup(idev, &iio_pollfunc_store_time, \
			&ads8638_trigger_handler, &ads8638_ring_setup_ops);

static const struct iio_buffer_setup_ops ads8638_ring_setup_ops = {
	.preenable = &ads8638_ring_preenable,
	.postenable = &iio_triggered_buffer_postenable,
	.predisable = &iio_triggered_buffer_predisable,
	.postdisable = &ads8638_ring_postdisable,
};
Платформа: встраиваемая с ядром 3.8.13.

Вопрос: почему при запуске сбора прерывание происходит только один раз после команды echo 1 > /sys/bus/iio/devices/iio_sysfs_trigger/trigger1/trigger_now, в остальное время процесс generic_buffer висит в ожидании poll? Если повторно дать команду echo, то снова происходит прерывание и generic_buffer успешно завершается независимо от переданной при его запуске длине данных.


Прерывание происходит один раз, потому что trigger_now так и задумывался, название какбы намекает: http://wiki.analog.com/software/linux/docs/iio/iio-trig-sysfs

Процесс крутится в цикле и на каждой итерации ждет следующего срабатывания триггера. Количество итераций никак не зависят от размера буфера. В сорсах generic_buffer всё есть.

unsigned long num_loops = 2;
...
for (j = 0; j < num_loops; j++) {
    ...
}
oh-la-la
()
Последнее исправление: oh-la-la (всего исправлений: 1)
Ответ на: комментарий от oh-la-la

Благодарю

Спасибо. Принял buf_len за кол-во данных, теперь понятно. Неясно тогда как реализовать циклический сбор данных? По прерыванию таймера разве, т.к. выходов IRQ у АЦП нет.

mikuka
() автор топика
Ответ на: Благодарю от mikuka

заводишь таймер, который тебе будет тикать с нужной частотой. Желательно в ядре всё это сделать, если частота уже порядка килогерц, иначе рискуешь нарваться на то, что не выдерживается интервал и ты об этом узнаешь далеко не сразу.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от mikuka

ИМХО тут уже стоит раскуриться с темой RT linux типа xenomai. иначе упаришься разбираться, кто, где и когда невовремя вытеснил твой опрашивающий код.

Может я не прав и можно значительно проще, с удовольствием послушаю.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от Dark_SavanT

Ну вроде подсистема iio и создавалась для вот этих целей, качать данные со всяких ацп на дохлых железках. По крайней мере трансиверы от Analog Devices на Zynq-e без проблем выдают 80-100 MSPS.

Надо смотреть как сделаны похожие драйверы и сколько они могут прокачать.

oh-la-la
()

Частота дискретизации для такого АЦП пропорциональна частоте работы spi. Нужно использовать spi+dma, при этом по прерыванию от dma выгружать уже принятый блок в кольцевой буфер и запускать новые измерения. Ну или использовать spi+fifo, если у процессора есть такая возможность.

zudwa
()
Ответ на: комментарий от zudwa

У Analog Devices есть реализация для мегавыборок на базе IIO, но там реализация обмена через DMA с представлением устройства как блочного. В ядре подобные как у меня АЦП реализованы через побайтовый опрос SPI в прерыванием с побайтовым проталкиванием в кольцевой буфер, а оттуда в userspace. Возникла идея посмотреть, может DMA поддерживает старт передачи напрямую от железного таймера, тогда будет проще.

mikuka
() автор топика
Ответ на: комментарий от mikuka

не очень понятно, что требуется от драйвера: считывать по команде мгновенное значение и помечать его timestamp, либо оцифровывать непрерывной сигнал с определенной частотой дискретизации.

zudwa
()
Ответ на: комментарий от zudwa

Оцифровывать непрерывный сигнал с частотой 200 кГц в течение небольшого промежутка времени менее 1с. с запуском по внешнему событию.

mikuka
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.