#c #c #c 98 #vxworks
#c #c #c 98 #vxworks
Вопрос:
В VxWorks 6.9 вы можете создавать таймеры, которые на самом деле являются просто оболочками для сторожевого таймера. Вы предоставляете этим ребятам указатель на функцию, задержку и до одного параметра, и после задержки функция вызывается с параметром. Однако он вызывается в контексте прерывания. Это (по какой-то причине) означает, что вы не можете вызвать какие-либо «блокирующие» функции или система буквально вылетает. Вы не можете вызывать printf
и вы не можете вызывать общедоступную функцию объекта, т. Е. Вы не можете этого сделать:
void Foo::WdCallback(Foo *foo){
foo->DoThing();
}
wdStart(wd, 16, (FUNCPTR)Foo::WdCallback, (_Vx_usr_arg_t)my_foo_ptr);
поскольку это также приведет к сбою по причинам, которые я не понимаю.
Каким другим способом мы можем создать таймер / тайм-аут в VxWorks, чтобы мы действительно могли сделать что-то полезное с обратным вызовом? Один из методов, который я видел, — это использование очереди сообщений — функция watchdog вызовет функцию отправки очереди сообщений. Однако это означает, что необходимо создать задачу для удаления этой очереди сообщений из очереди в другом месте. Я также читал, что обратный вызов сторожевого таймера может выдавать семафор, позволяющий продолжить выполнение задачи, но это означает, что мы должны создать задачу для каждой отдельной функции на основе таймера, которую мы хотим..
Похоже, что независимо от того, какой путь мы выбираем со сторожевыми псами или таймерами в VxWorks, мы должны создать целую задачу только для того, чтобы иметь возможность обрабатывать обратный вызов сторожевого пса из-за контекста прерывания. Должен быть менее нелепый способ сделать это. Есть ли чисто C способ написать таймер? Или более простая реализация VxWorks?
Комментарии:
1. функции-члены имеют неявный параметр для
this
, но расположение этого параметра в упорядочении зависит от реализации AFAIK.2. «это означает, что мы должны создать задачу для каждой отдельной функции на основе таймера, которую мы хотим», нет, вы этого не делаете. Вам нужна только одна задача, которая поддерживает список структур тайм-аута, упорядоченных по времени ожидания. Эта задача настраивает таймер прерывания на срабатывание после ближайшего тайм-аута из начала списка. Структуры могут иметь указатели на функции или экземпляры, производные от класса ‘timeout’, который имеет метод irtual timeout.
3. «но как я могу безопасно добавлять / удалять / любые элементы в списке, если поток тайм-аута может в любой момент выгрузить и удалить элемент во главе списка, время ожидания которого только что истекло» — вы запрашиваете задачу тайм-аута для выполнения этого, помещая экземпляры тайм-аута в потокобезопасную очередь команд и сигнализируя семафору. Когда выполняется задача тайм-аута, она теперь выполняет две вещи: проверяет очередь команд на наличие любых новых запросов на тайм-аут и проверяет заголовок списка тайм-аута, чтобы узнать, истекло ли время ожидания. Если да, обработайте это, если нет, пересчитайте оставшееся время, установите таймер прерывания и дождитесь семафора.
Ответ №1:
C не должен использоваться для функции, выполняемой в контексте прерывания. Сторожевой таймер здесь выполняется в контексте прерывания системного тика.
Если вы хотите сохранить код C , убедитесь, что не будет выполнена операция создания / удаления, и вам потребуется скомпилировать код с флагами добавления (это должно быть задокументировано в Руководстве программиста VxWorks в разделе C => -fno-rtti -fno-exceptions).