Безопасное "переключение задач" на чипах 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), он является атомарным.

Вы должны убедиться, что ни одна задача, обращающаяся к указателю во время изменения, не может быть приостановлена ​​на достаточно длительное время, чтобы ее могли помешать следующие изменения.

Другие вопросы по тегам