Официальный форум СВД Встраиваемые Системы
28 Март, 2024, 22:03:21 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.

Войти
 
 
 Сайт СВД ВС  Начало   Помощь Поиск Войти Регистрация  
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как InterruptWait узнаёт от какого прерывания вернулся sigevent?  (Прочитано 1380 раз)
KA3AKOB
Пользователь

Сообщений: 54


« : 13 Июнь, 2019, 18:09:42 »

При написании Resource Managera возможны разные комбинации в обработке прерываний. Судя по Кртену правильный подход заключается в создании подпрограммы обработчика прерываний, которая работает на высоком приоритете процессора, по возможности коротка, осуществляет минимальные действия с внешней аппаратурой (например) на шине ISA, разбирается от какого устройства пришло прерывание, если на одно прерывание навешано несколько устройств, и сбрасывает триггер готовности в нужном устройстве. При этом из этой подпрограммы обработки прерывания нельзя вызывать почти никакие системные функции, в том числе MsgSend/MsgReceive/MsgReply. Если никаких других действий в подпрограмме обработчика прерываний не требуется, то она возвращает нулевой указатель return (struct sigevent *)(NULL); если же требуется ещё что-то сделать по обработке данных после прерывания, то возвращаем ненулевой указатель на struct sigevent. Ненулевой указатель означает, что система должна произвести передиспетчеризацию потоков и передать управление некоему потоку, ответственному за постобработку прерывания. Функция этого потока должна в пределе выглядеть так:
void* interrupt_thread (void* arg)
{
       sigEvent.sigev_notify = SIGEV_INTR;
       while(1) {
              InterruptWait(NULL, NULL);  // здесь поток затормозился и ждёт передачи управления от обработчика прерываний
              /* далее, все действия и вызовы, которые возможны в обычных потоках */
              printf(...);
              MsgSend(...);
       }
}
// собственно обработчик прерывания
const struct sigevent * Td04Driver::main_isr (void *arg, int id)
{
    extern sigevent sigEvent;
    out8(addr, 0);// сброс прерывания по в триггере готовности
    return (struct sigevent *)&sigEvent;
}

 Суть вопроса:
как система узнаёт, что управление надо передать именно этому потоку, затормозившемуся на ожидании именно от этого обработчика прерывания? Как-то через 3 и 4 параметры функции InterruptAttach()?
С уважением,
Казаков С.А.
Записан
Андрей Докучаев
Сотрудник СВД ВС
Легенда

Сообщений: 1075



WWW
« Ответ #1 : 13 Июнь, 2019, 18:19:26 »

как система узнаёт, что управление надо передать именно этому потоку

Получить event вида SIGEV_INTR может только тот поток, который зарегистрировал обработчик.
Записан

KA3AKOB
Пользователь

Сообщений: 54


« Ответ #2 : 14 Июнь, 2019, 11:21:58 »

Спасибо за ответ.
Правильно ли я понимаю, что именно поток с InterruptWait должен проводить регистрацию обработчика прерывания (isr) путём вызова функции InterruptAttach? То есть, код потока постобработки прерывания выглядит примерно так:
void* interrupt_thread (void* arg)
{
        // привязка isr к данному потоку
   intr_id = InterruptAttach (intRQ,   // номер прерывания
          isr,           //функция обработчика прерывания
          NULL,        // A pointer to a communications area in your process, or
                   // NULL if you don't want a communications area.
          0,        //The size of the communications area; this should be 0
                   //if area is NULL.
          _NTO_INTR_FLAGS_END ); //realtime interrupt
      
        sigEvent.sigev_notify = SIGEV_INTR;
       while(1) {
              InterruptWait(NULL, NULL);  // здесь поток затормозился и ждёт передачи управления от обработчика прерываний (isr)
              /* далее, все действия и вызовы, которые возможны в обычных потоках */
              printf(...);
              MsgSend(...);
       }
}

Дополнительный вопрос: "Если в функции main() Resource Managera вызываем сначала ThreadCtl( _NTO_TCTL_IO, 0 ); а потом pthread_create(NULL, NULL, interrupt_thread, area);, то в interrupt_thread уже не надо вызывать  ThreadCtl( _NTO_TCTL_IO, 0 );, поскольку управление наследуется дочерними потоками? Или всё же в инициирующей части interrupt_thread (до while) вызвать ThreadCtl( _NTO_TCTL_IO, 0 ); ибо кашу маслом не испортишь? Или испортишь?". В main() ThreadCtl( _NTO_TCTL_IO, 0 ) нужен потому, что функция io_write принадлежит основному потоку, а в io_write есть вызовы in/out. И в isr in/out тоже есть.
С уважением,
Казаков С.А.
« Последнее редактирование: 14 Июнь, 2019, 11:42:03 от KA3AKOB » Записан
Андрей Докучаев
Сотрудник СВД ВС
Легенда

Сообщений: 1075



WWW
« Ответ #3 : 14 Июнь, 2019, 12:07:25 »

Правильно ли я понимаю, что именно поток с InterruptWait должен проводить регистрацию обработчика прерывания (isr) путём вызова функции InterruptAttach?

Да.

уже не надо вызывать ThreadCtl( _NTO_TCTL_IO, 0 );

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

KA3AKOB
Пользователь

Сообщений: 54


« Ответ #4 : 14 Июнь, 2019, 18:18:50 »

Да, спасибо, способность работать командами in/out унаследована от родительского потока main().
С уважением,
Казаков С.А.
Записан
Василий Дмитриев
Ветеран

Сообщений: 363



« Ответ #5 : 16 Июнь, 2019, 11:25:49 »

Как вариант можно использовать эвенты типа SIGEV_PULSE и ловить их обычным MsgReceive. Актуально при переписывании софта из под qnx4 (proxy-Receive)
Записан

Санкции! Запрещаю Бараку Обаме и членам конгресса США читать мои посты!
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP © 2002-2020 СВД Встраиваемые Системы.
При использовании материалов сайта ссылка на forum.kpda.ru обязательна.

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines | © Aiwan. Kolobok smiles | Sitemap
Valid XHTML 1.0! Valid CSS!
Сайт СВД ВС

В последний раз google посещал эту страницу 28 Март, 2024, 13:29:42