PDA

Просмотр полной версии : Перехват/обработка прерываний на C(++)



Oscar
15.10.2007, 14:14
Под платформу Gumstix (http://docwiki.gumstix.org/Verdex) пишу драйвер Bluetooth (BT) для проприетарной ОС.

Для общения с контроллером есть доступ через UART, который работает через процессор PXA270 (Marvell/Intel) (http://pubs.gumstix.com/documents/PXA%20Documentation/PXA270/) (который что-то последовательное превращает во что-то паралельное, а потом обратно .. но это не важно)

UART имеет FIFO, через который драйвер читал, писал байты контроллеру, всё было нормально, пока не пошли "большие" обьёмы данных. Т.к. FIFO имеет размер буфера 64 байта, остальная информация просто обрезается. А в спецификации BT сказано, что драйвер должен обеспечивать отсылку/приём данных минимум 255 байт.

Появилась идея написать собственный программный FIFO и по прерываниям процессора заполнять его приходящими байтами.

В спецификации процессора (http://pubs.gumstix.com/documents/PXA%20Documentation/PXA270/PXA270%20Processor%20Developer's%20Manual%20%5b280 000-002%5d.pdf) все регистры прекрасно описаны, и есть интерфейс для работы с ними, но я что-то никак не могу понять, как это делать.

Может кто подкинет общую идею?

Вопрос первый: что такое прерывание? ))))
что происходит с программой, когда оно случается?

Я представляю себе это так: бежит Thread (язык программирования C++, так что я могу позволить себе такую роскошь), который проверяет регистр прерываний, сравнивая его с бит-маской того, что программа ожидает.

Отступление: в регистре Interrupt Enable Register прерывания я "включил".

И когда бит прерывания установлен, программа считывает байт из регистра данных.

Может я что-то неправильно понимаю?

Ибо при такой конструкции в регистре статуса появляется Overrun и приходит лишь последний (допустим из 4-х) байт.

Кроме того вопрос, ну бежит себе Thread,
(с приоритетом выше, чем остальная программа, которая работает с клавиатурой/консолью),
но ведь кроме него мне нужны ещё ресурсы и для самой программы,
потому внутри него я делая sleep на одну милисекунду.

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

В общем у меня есть чувство, что я что-то делаю не правильно ..

Подскажите, кто знает, как это правильно делать?
Наставьте, плиз, на путь истенный :-)

somewhere
15.10.2007, 14:50
Прерывание - оно на то и прерывание, что прерывает любой Thread. Ловить его не надо - оно само приходит. В процессоре есть таблица IDT (Interrupt description table) в котором адресса всех обработчиков каждого прерывания расписаны. Работу (maskable interrupts) обеспечивает флаг IF (в вашем случае Interrupt enable register). Работа NMI этим флагом не затрагивается. По приходу пр. процессор заканчивает выполнение текущих инструкций, сохраняет адресс и переходит в нужную точку для его обработки. Если не устраивает чем-то UART можно построить общение на прерываниях организуя свой буффер и получение данных через порт. Здесь основной вопрос - синхронизация. Предварительно передачу через UART необходимо отключить путем записи нужных бит в нужный порт, иначе эффекта не будет. Спецификацию для проца не читал, но смысл остается тот же. Тем более что поменять адрес обработчика в IDT под PXA270 будет проще чем под Intel x86

Примерный ход:
1. Отключить UART буффер
2. Включить прерывания.
3. Подписаться в IDT на обработчик нужного прерывания, записав туда адрес обработчика.
3.1. (в обработчике) проверить от кого пришло, т.к. прерывание с одним номером могут придти с разных устройств
3.2. [обработка] - чтение данных из порта, ставим какой-нить флаг, что буффер заполняется ну еще разную статистику
3.3. говорим контроллеру прерываний что мы закончили, делаем IRET, ставим флаг что буффер заполнен
4. (Фоновая обработка сообщений и пр.)

Причем под обработчик Thread лучше не создавать, т.к. толку не будет никакого, только если проц имеет >1 ядер

Oscar
15.10.2007, 20:45
somewhere, спасибо большое за подробное описание.

Оказалось, что ребята, которые писали ОС предоставляют более удобный интерфейс для работы с прирываниями, так что попробую реализовать обработчик через него. Но всегда полезно знать, что происходит внутри.