Суть:
Есть девайс который непрерывно шлет данные по SPI на линукс-плату (девайс - мастер, линукс - слейв), а на линуксе нужно эти данные принять.
Есть самописный драйвер для работы с SPI, который через прерывания работает ОК. Однако, учитывая, что прерывания нагружают проц, требуется перейти на DMA, чтобы перенос данных из FIFO буфера SPI проводился без отвлечения процессора.
Проблема:
я скопипастил с небольшими коррекциями все, что касается инициализации DMA из mxc_uart.c, который шел вместе со стартеркитным ядром 2.6.35. Вот получившийся исходник моего драйвера: http://pastebin.com/0Jj4hGVc
В итоге имею, что read callback не вызывается вообще.
А счетчик байт в буфере FIFO (SPI) все время остается на максимуме (64 б), т.е. выходит что он вообще никогда не опустошается, а следовательно DMA не выполняет свою обязанность - переносить из FIFO в заданную область памяти (буфер).
Вопросы:
1. Правильно я понимаю, что прерывания самого SPI можно отключить, т.к. для работы DMA они не нужны ?
2. Почему не вызывается callback ?
3. Есть ли какие-то утилитки, которыми можно посмотреть чем занимается DMA и какие на него повешены устройства?
Да, прерывания от самого SPI не нужны для работы через DMA. Надо вместо этого разрешить запрос DMA, когда FIFO будет на грани заполнения. Как я понял, у вас это сделано.
У меня есть предположение: что если вы выбрали не тот канал DMA? В dma.h определены вроде такие каналы:
Как я понял, в контроллере один модуль CSPI (MXC_DMA_CSPI1?) и 2 модуля ECSPI (MXC_DMA_CSPI2 и MXC_DMA_CSPI3?). Так что может вам попробовать канал MXC_DMA_CSPI3?
Кстати при формировании такого типа канала (конкретный модуль периферии -> память) указывать src_addr насколько я понял необязательно, т.к. он уже задан при выборе канала.
По-моему в /proc/interrupts можно видеть только общее количество прерываний от SDMA, соотвественно от всех модулей, что через него работают.
Я делал собственный драйвер для SSI и по /proc/interrupts прикидывал количество прерываний в секунду от ПДП.
1. Нашел у себя небольшую ошибку в настройке DMА, исправление которой, впрочем, не помогло.
/arch/arm/mach-mx5/dma.c
(до этого было ошибочно emi_2_per, хотя нужно направление "периферия->память")
2. Начал копать SDMA и наткнулся на следующую проблему.
Не могу понять каким образом скрипты SDMA определяют с какого адреса в какой сливать.
Насколько я вижу, эти скрипты описаны в файле /arch/arm/mach-mx5/sdma_script_code_mx53.h
Из кода выше видно, что для SPI используется адрес sdma_script_addrs.mxc_sdma_app_2_mcu_addr
который в свою очередь равен некому "загадочному" числу 683:
также указан размер (скрипта?)
Полагаю, что 683 это номер байта в бинарном коде, откуда начинается скрипт. Данный бинарный код приведен в том же файле:
И вот квинт-эссенция проблемы:
Как понять работу этого SDMA скрипта - неужто надо заниматься реверс-инжениренгом и деассемблировать эту последовательность? ...