после установки драйвера от AD в системе появились демоны
"ksoftirqd" и "kworker", которые поочерёдно жрут более 70 процентов времени CPU (смотрел через top).
как можно бороться?
Только один метод - править руки драйверописателям AD или смотреть - возможно что-то не так установили/настроили/подключили. В контексте softirq выполняются (в том числе) "нижние половины" (bottom half) обработчиков прерываний, что так долго делают там драйверы AD - надо разбираться. Возможно все нормально с драйверами и настройкой просто объем данных по SPI достаточно большой, например spi emac ks8851 тоже нехило процессор нагружает когда непрерывно данные идут, как известно сетевая подсистема тоже в контексте softirq работает (по крайней мере ф-ция передачи буфера драйвера emac точно в контексте softirq вызывается ядром) и там наблюдается подобная картина.
Решил поднять старую тему, так как сейчас пришлось писать драйвер самому и тема стала актуальна.
Планируется в прерываниях драйвера проделывать приём данных по SPI.
Т.е.:
[обработчик прерывания] {
[забираем 16байт данных по SPI - 128 клоков]
}
Сильно ли это будет тормозить систему и как будет сделать выгоднее с точки зрения накладных расходов?
Может просто в прерывании выставлять флаг готовности данных, а в самом драйвере уже забирать данные? Но как второе проделать незнаю...
в обработчике отключать прерывание и запускать тасклет или рабочую очередь. Если собираетесь использовать стандартные средства Linux для работы с spi типа spi_sync то только рабочая очередь - эти ф-ции (кроме spi_async котрая для вас будет бесполезна скорей всего) требуют контекст который может переходить в состояние ожидания, что недопустимо в контексте прерываний и соответственно в тасклете тоже, рабочие очереди работают в контексте обычного процесса.
спасибо.
Пока всё что вы описали - непревычно немного)
А если сделать так: в обработчике выставлять флаг, который будет опрашиваться в функции, а функция соответственно запустится через kthread_run(...).
Получается создаем в ядре поток, в котором опрашивается бесконечно флаг готовности данных, если флаг выставлен, то запускается приём данных.
P.S. Собирался не использовать стандартные средства Linux, а использовать библиотеку из IAR для прямого доступа к регистрам.
тогда какой смысл прерывания использовать если в этом потоке можно опрашивать то что вы в прерывании делаете - зачем в таком случае нужен левый промежуточный флаг ? тасклеты - это нижние половины, выполняются сразу после того как отработают все верхние половины, т.е. получаете максимально быстрый отклик для обработки события, с поллингом в потоке вы такого никогда не получите, рабочие очереди выполняются после обработчиков прерываний и тасклетов (softirq), но перед обычными процессами - т.е. они тоже предпочтительней отдельных потоков. Если будете использовать регистры напрямую - тасклеты для вас наилучший вариант не угробить отзывчивость системы - я так понимаю у вас кроме приема данных по spi они же обрабываются еще и сохраняются/передаются - иначе вам бы atmega хватило какой-нибуть :)
PS кстати создавать свои потоки в драйверах в пространстве ядра - не рекомендуется и считается плохим стилем.
именно для этого в Linux и созданы специальные средства - tasklets и work queues, первые для максимально быстрого завершения обработки прерываний, второй - используют там где тасклеты невозможно использовать, т.е. требуется контекст обычного процесса или требуется задержка обработки, при этом специальный процесс для каждого драйвера не создается - ф-ции всех драйверов обрабатываются в одном процессе пространства ядра в порядке очереди. Вот хорошие статьи по теме http://www.ibm.com/developerworks/linux/library/l-tasklets/index.html http://www.linuxjournal.com/article/6916
Спасибо за очень полезные советы.
Я если требуетс просто сложить данные в буфер, приняв их по SPI_PDC, может просто прерыванием обойтись?
как думаете исходя из опыта?
Перечитал про PDC - не совсем понятно там с указателями.
т.е. теоретически в прерывании можно перенастраивать указатель/счетчик на следующий буфер чтобы во время обработки прерывания по завершению текущего буфера чтение spi не прекращалось и корректировать указатели откуда читать и сколько для юзерспейс, тогда латентность прерывания будет побоку и процесс будет непрерывным. Можно выделить например 10 буферов одинаковой длины и в обработчике переключать указатели - если буферы будут достачной длины чтобы не сказывалась латентность прерываний Linux то все будет нормально работать. Собственно нижние половины тут вообще не нужны в принципе - все можно делать в самом обработчике.
Возможно я неправильно понял - как внешнее устройство (котрое вроде мастером на шине как вы говорите) передает данные устройству которое должно их принимать - сигнализирует каким-то пином что данные готовы или передает команду или непрерывно отдает данные по шине управляя слейв-устройством посредство CS ? А то мне подозрительны ваши слова стали - "Вообще прерывание нужно использовать для того чтобы понять, что данные готовы. "
Вообще лучше бы сказали что за устройство - как оформить драйвер и частности с управлением буферами - надо исходить из этого, можно сделать кучей разных способов.