функция выхода при прерывании - PullRequest
1 голос
/ 26 сентября 2011

У меня есть вызываемая функция прерывания, interrupt_Foo() {...}, которая включает флаг по истечении 1 секунды, и пользовательская функция foo_calling() {...}, которая вызывает другую функцию foo_called() {...}. Я хочу остановить процесс в foo_called() по истечении 1 секунды.

Приведенный ниже фрагмент кода может прояснить мою потребность:

void interrupt interrupt_foo() {
   ...
   if(1 second has elapsed) {
      flag1s = 1;
   } else {
      flag1s = 0;
   }
}

void foo_calling() {
   // need something here to stop the process of foo_called()
   ...
   (*fptr_called)(); // ptr to function which points to foo_called
   ...
}

void foo_called() {
   // or something here to stop the process of this function
   ...
   // long code
   ...
}

Это операционная система реального времени, поэтому опрос 1-секундного флага внутри foo_called () в некоторой части кода нежелателен. Пожалуйста, помогите.

Ответы [ 2 ]

2 голосов
/ 27 сентября 2011

Если вы готовы написать непереносимый код и проверить его перед его развертыванием, и если процессор его поддерживает, возможно, существует решение.

Когда вызывается обработчик прерываний, адрес возврата должен где-то храниться. Если это местоположение, к которому может обращаться ваш код - например, фиксированное смещение вниз по стеку - тогда вы можете сравнить этот адрес с диапазоном, занятым вашей функцией, чтобы определить, выполняется ли 'foo_called'. Вы можете получить адрес функции, сохранив фиктивный адрес, скомпилировав, проанализировав файл карты, затем обновив адрес и перекомпилировав.

Затем, если ваш процессор поддерживает его, вы можете заменить адрес возврата на адрес последней инструкции (инструкций) foo_called. (убедитесь, что вы включили очистку стека и зарегистрировали код восстановления.). Затем выйдите из прерывания как обычно, и логика обработки прерываний вернет код до конца вашей прерванной функции.

Если адрес возврата хранится не в стеке, а в незаписываемом регистре, вы все равно сможете принудительно завершить свою функцию - если исполняемый код находится в записываемой памяти. Просто сохраните инструкцию по адресу возврата прерывателя, затем перезапишите ее инструкцией перехода, которая переходит к концу функции. В коде вызывающего абонента добавьте детектор, который восстановил перезаписанную инструкцию.

1 голос
/ 27 сентября 2011

Я ожидаю, что ваша ОСРВ имеет какой-то сигнал / прерывание по таймеру, который вы можете использовать, чтобы уведомить вас, когда пройдет одна секунда.Например, если это UNIX / Linux в реальном времени, вы должны установить обработчик сигнала для SIGALRM на одну секунду.В RT-варианте Linux этот сигнал будет иметь большую детализацию и лучшие гарантии, чем в не-RT-варианте.Но все же будет хорошей идеей установить сигнал на чуть менее секунды и «занято» (цикл), пока не достигнете одной секунды.

...