Я уже использовал внутренние аппаратные сторожевые таймеры в нескольких встроенных приложениях без ОС (со статическими планировщиками).
Что я делаю:
Я думаю, что это минималистский, но безопасный подход.
Есть ли лучшая практика? (личный опыт или проверенные источники)
Я слышал/видел, как люди делают разные вещи, например, пинают собаку более одного раза в разных задачах или пинают только в том случае, если все задачи были вызваны в течение тайм-аута,...
У вашего подхода есть проблема, которую вы не можете гарантировать, запустив самую медленную задачу, которую выполняли все остальные задачи.
И в качестве расширения в многозадачной среде вы обычно получаете какую-то задачу с высоким приоритетом, которая необходима для обеспечения функциональности и других задач (IO, аппаратный мониторинг и т. д.), о которых вы действительно не заботитесь.
Таким образом, ваш сторожевой таймер нужен только для важных, но вы должны наблюдать за ними всеми. чтобы убедиться, что вам нужно как очень простое решение, работающая структура состояния, подобная этой:
struct{
bool task1HaRun;
bool task2HasRun;
bool task3HasRun;
};
с мьютексом вокруг него. Каждая задача устанавливает свой собственный hasRunFlag и проверяет, установлены ли все остальные. Если все остальные установлены, он сбрасывает все и запускает сторожевые таймеры. Если вы не позволите каждой задаче проверять себя, вы можете пропустить заблокированные задачи.
Есть более элегантные способы решения этой проблемы, но этот портативный и дает вам представление о том, что делать.
@Guillaume D извините, исправил.
«запустив самую медленную задачу, которую выполняли все остальные задачи». Фактически, при запуске самой медленной задачи в совместном планировщике все задачи вызываются последовательно, поэтому, если выполняется самая медленная задача, выполняется любая задача ... Это можно сделать, как сказал @Lundin, в основном цикле.
@Guillaume D Я предполагал, что вы используете какую-то RTOS, и большинство из них являются упреждающими. Или, чтобы быть более правильным, чтобы обеспечить возможность работы в реальном времени, они должны.
Я сказал "без ОС" и "голое железо"
@Guillaume D Вы сказали планировщик и задачи. Во встраиваемых системах RTOS больше ничего не делала, и кстати. если у вас чистая кооперативная система, вам не нужны задачи. Они не покупают ничего, кроме большей сложности.
Ваш вопрос немного субъективен, но есть что-то вроде отраслевого стандарта де-факто для приложений реального времени, который выглядит следующим образом:
Это самое жесткое требование — в идеале собака ничего не знает о ваших различных задачах, но держится подальше от логики приложения.
На практике это может быть трудно сделать для некоторых систем - предположим, у вас есть загрузчики флэш-памяти и тому подобное, которые по своей природе просто должны занимать много времени. Затем вам, возможно, придется делать грязные вещи, например, размещать сторожевые таймеры внутри определенного драйвера. Но это лучшая практика, к которой нужно стремиться.
Так что в идеале у вас есть это на самом верхнем уровне вашего приложения:
void main (void)
{
/* init stuff */
for(;;)
{
kick_dog();
result = execute();
error_handler(result);
}
}
Как побочный эффект этой политики, она устраняет риск того, что «талантливые» люди в конечном итоге будут пинать собаку внутри ISR.
делая это, вы не можете сказать, пропустила ли одна задача свой крайний срок ... Вызов удара в основном цикле, но в конце был бы лучшим решением, не так ли?
@GuillaumeD Зависит от того, позволяете ли вы системе пропускать сроки или нет. Для системы реального времени пропущенный крайний срок является ошибкой. Но во время отладки может быть целесообразно отключить wdog и вместо этого использовать таймер.
но отключение wdg во время отладки — это одно. Удар wdg до или после выполнения основного цикла - это другое. Что вы думаете о вызове удара после выполнения основного цикла, а не перед выполнением основного цикла?
@GuillaumeD «Ударьте wdg до или после выполнения основного цикла». Это цикл ... он повторяется. Но если у вас есть требования в реальном времени, которые значительно сложнее, чем тайм-аут wdog, в любом случае может иметь смысл использовать таймер, чтобы производить диагностику и изящно обрабатывать ошибки - зависит от характера приложения. Некоторые приложения должны сбрасываться при ошибках, другим этого делать нельзя. Для критичных к безопасности систем тайм-аут wdog является последним средством — в идеале они должны вместо этого вернуться в безопасное состояние, прежде чем это произойдет.
"не могу гарантировать"?