Безопасное "переключение задач" на чипах ATmega
Я начал реализовывать нечто похожее на переключение задач в моем приложении на atmega8. Основная идея заключается в том, что есть указатель на структуру "текущего экрана". "Текущий экран" содержит обработчики для обновления экрана, обработки кнопок и прерываний.
К сожалению, я обнаружил, что изменение указателя на функцию выполняется за 2 операции. Это означает, что какое-то прерывание может попытаться сделать current_screen->handle_signal(...);
в то время как current_screen
частично изменен Из-за обработки точного времени я не могу просто отключить и включить прерывания во время этого изменения. Установка флага об изменяемом обработчике может помочь, так как меня не волнует пропуск некоторых прерываний в середине изменения задачи (но затем обработка тех, которые я не могу пропустить, становится немного сложнее).
Я думал о копировании current_screen
в current_screen_old
во время изменения и установки флага, вот так:
current_screen_old = current_screen; // safe to call current_screen->handler
during_update = 1; // safe to call current_screen_old->handler
current_screen = new_value;
during_update = 0; // safe to call current_screen->handler again
Но я не уверен на 100%, что в нем нет других хитростей, если обработчик хочет изменить current_screen
тоже.
Есть ли лучший способ приблизиться к этому? Некоторые хорошие идиомы?
1 ответ
Вы можете использовать двойную буферизацию.
То есть используйте массив из двух указателей на функции и индекс для текущего. Установите нетоковый указатель на новое значение, затем переключите индекс. Поскольку индекс мал (0 или 1), он является атомарным.
Вы должны убедиться, что ни одна задача, обращающаяся к указателю во время изменения, не может быть приостановлена на достаточно длительное время, чтобы ее могли помешать следующие изменения.