Остановка функции, запущенной в данный момент из обработчика прерываний - PullRequest
3 голосов
/ 20 мая 2019

Допустим, у меня есть две функции в C, a() и b().И скажем, у меня есть два прерывания, соответствующие обеим функциям.Первое прерывание должно запустить запущенную функцию a() и остановить запуск b(), если оно было прервано во время ее выполнения.Аналогично, второе прерывание делает то же самое для функции b().

Если я в данный момент работаю в a(), и я запустил прерывание для b().Как я могу запустить b() и предотвратить завершение a() после завершения обработчика прерываний?

Код выглядит следующим образом:

int main(void)
{
    Init();
    while (true)
    {
    if (run_A)
    {
      a();
      run_A = false;
    }
    if (run_B)
    {
      b();
      run_B = false;
    }   
}

void Handler(void)
{
    IntClear(interruptMask);

    if (INTERRUPT_FOR_A)
    {
        run_A = true;
    }

    if (INTERRUPT_FOR_B)
    {
        run_B = true;
    }
}

Ответы [ 4 ]

4 голосов
/ 20 мая 2019

У меня есть ситуация, когда b () вызывает функцию, которая выполняет некоторую работу, которая мне не нужна, если я хочу вернуться к a ().Я хочу предотвратить это, когда я вызываю (), и минимизировать время, необходимое для запуска ()

В основном такая ситуация произойдет, если произойдет INTERRUPT_FOR_B и очень короткое время спустяINTERRUPT_FOR_A случается, и если b() имеет более длительное время выполнения.

Вам необходимо тщательно обдумать эту ситуацию и выяснить вероятность того, что это произойдет, прежде чем проводить преждевременную оптимизацию.

Но,если вы хотите пойти дальше, вы можете иметь несколько контрольных точек в функции b(), чтобы увидеть, истинно ли run_A.

например,

void b(void)
{
    // some code.
    if (run_A == true) return;
    // some code 
    if (run_A == true) return;
    // etc
}

Обратите внимание, что вам нужно правильно проанализировать и протестировать функцию b со всеми путями возврата, чтобы убедиться, что эта функция работает правильно во всех случаях.

2 голосов
/ 20 мая 2019

В целом не очень важно говорить об этом в общих чертах.Это зависит от ваших требований и от того, какое оборудование генерирует прерывание.

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

Более навязчивым, но простым методом было бы просто отключитьнежелательное прерывание, но это может привести к потере данных.В зависимости от характера прерывания, это может или не может быть хорошо.

И, конечно, есть плохие способы установить ПК вручную с помощью ассемблера или longjmp, но это очень плохая практика и почти наверняканеправильное решение любой проблемы.

0 голосов
/ 23 мая 2019

Похоже, вы ищете функцию, похожую на сопрограммы.Хотя это не поддерживается напрямую в C, вы, возможно, сможете реализовать версию, достаточно подходящую для ваших нужд.Как упомянуто выше, это, вероятно, будет включать setjmp / longjmp или изнурительное «Устройство Даффа», если вы хотите сделать это в переносимом C.

0 голосов
/ 21 мая 2019

Это проблема, для которой setjmp(3) / longjmp(3) функционирует там, где она была разработана в старой UNIX (tm).Вам нужно вызвать setjmp(3) перед входом в функцию, которую вы хотите прервать, и в случае, если прерывание наступит (вы должны убедиться, что прерывание обрабатывается в контексте функции, которую вы собираетесь прервать), затем вы делаете вызов longjmp(3)и восстановить стек в точке вызова.

...