У меня есть встроенная платформа Linux (Beagleboard, работающая под управлением Angstrom Linux) с двумя подключенными устройствами:
- Лазерный дальномер (Hokuyo UTM 30), подключенный через USB
- пользовательская внешняя плата, подключенная через SPI
У нас написан модуль ядра Linux, который отвечает за передачу данных SPI. Он имеет обработчик IRQ, в котором вызывается spi_async , что в свою очередь вызывает асинхронный метод обратного вызова.
Мое приложение на C ++ состоит из трех потоков:
- основной поток для обработки данных
- нить для лазерного опроса
- поток опроса SPI
У меня возникли проблемы, которые, по-видимому, вызваны взаимодействием описанных выше модулей.
- Когда я выключаю устройство USB (лазерный дальномер), я получаю все сообщения SPI правильно (1 сообщение каждые 3 мс, длина сообщения, деленная на скорость передачи данных <1 мс), независимо от планирования потока </li>
- Когда я включаю устройство USB и запускаю свою программу с обычным планированием потоков (SCHED_OTHER, приоритет 0, не установлен хороший уровень), около 1% сообщений «теряется», потому что метод обратного вызова spi_async выполняется, когда следующий IRQ (я мог бы обработать этот случай по-другому, чтобы не потерять сообщения, так что это не большая проблема.)
При включенном устройстве USB и запуске программы с SCHED_RR и
- приоритет = 10 для основного потока
- приоритет = 10 для потока чтения SPI
- приоритет = 4 для потока USB / лазерного опроса
тогда я теряю 40% сообщений, потому что IRQ снова запускается до вызова метода spi-callback! (Возможно, я все еще могу найти обходной путь, но проблема в том, что мне нужно быстрое время отклика, которого в этом случае уже нельзя достичь). Мне нужно использовать планирование потоков и лазерное устройство, поэтому я ищу способ решить этот случай.
Вопрос 1:
Я предполагал, что обработчики IRQ и обратные вызовы, запускаемые spi_async в пространстве ядра, имеют более высокий приоритет, чем любой поток, работающий в пространстве пользователя (независимо от того, является ли SCHED_RR или SCHED_OTHER). Это означало бы, что обращение к SCHED_RR в моем приложении не должно замедлять передачу SPI, но это кажется очень неправильным. Это так?
Вопрос 2:
Как я могу определить, что здесь происходит? Какие средства отладки существуют? (Или, может быть, вам не нужна дополнительная информация?) Главный вопрос для меня: почему я испытываю проблемы только при включенном лазерном устройстве. Может ли драйвер USB занимать так много времени?
----- РЕДАКТИРОВАТЬ:
Я сделал следующее наблюдение:
Обратный вызов spi_async вызывает wake_up_interruptible(&mydata->readq);
(с wait_queue_head_t readq;
). Из пользовательского пространства (моего приложения) я вызываю функцию, которая приводит к poll_wait(file, &mydata->readq, wait);
Когда опрос возвращает пользовательское пространство, вызывает read()
.
- Когда мое приложение работает с
SCHED_OTHER
, я вижу, что метод обратного вызова сначала завершается до того, как в моем модуле ядра введен метод read()
.
- Когда мое приложение запускается с
SCHED_RR
, чтение вводится до выхода из обратного вызова.
Это кажется доказательством того, что приоритет потоков пространства пользователя выше, чем приоритет контекста метода обратного вызова. Есть ли способ изменить это поведение, и у меня все еще есть SCHED_RR
для потоков моего приложения?