Что произойдет, если в программе будет ошибка во время выполнения? Будет ли остановлено выполнение программы? Есть ли какой-нибудь способ заставить Arduino сказать мне, в чем ошибка?
Сначала давайте рассмотрим несколько примеров того, что может пойти не так.
void setup() {
int status;
pinMode(13, OUTPUT);
digitalWrite(13, status);
}
Как отметил Эдгар Бонет в комментариях, локальные переменные, как status
в коде выше, неявно инициализируются компилятором C ++. Таким образом, результат кода выше является неопределенным. Чтобы избежать этого, убедитесь, что вы всегда присваиваете значения локальным переменным.
С глобальными и статическими переменными все немного по-другому:
Глобальные и статические переменные гарантированно будут установлены в 0 по стандарту C.
Это означает, что вам не нужно беспокоиться об их инициализации в вашем коде. На самом деле, вы должны избегать этого, так как инициализация может тратить память. Инициализируйте их только значениями, отличными от 0.
int array[10];
int v = array[100];
array[-100] = 10;
Первая проблема здесь в том, что вы не знаете, что будет назначено v, но хуже всего то, что вы не знаете, что вы испортили с назначением на позицию -100 of array
.
void doSomething( void ) {
for (int i = 0; i < 1000; i++);
}
void setup ()
{
void (*funcPtr)( void );
funcPtr = &doSomething;
funcPtr(); // calls doSomething();
funcPtr = NULL;
funcPtr(); // undefined behavior
}
Первый вызов на funcPtr()
самом деле будет вызовом doSomething()
. Вызовы, подобные второму, могут привести к неопределенному поведению.
Ну, вы можете исчерпать ОЗУ, например. Что еще. В любом случае, я думаю, что ваша программа будет работать, вероятно, не так, как вы хотели.
В компьютерных системах подобные проблемы обычно решаются на разных уровнях:
Arduinos имеют только ограниченную защиту компилятора и, вероятно, ничего другого. Хорошей новостью является то, что они не являются многозадачными, поэтому затрагивается только ваша программа. В любом случае любая из этих ошибок приведет к ошибочному поведению.
Предположения - это все проблемы, которые я изложил выше, это проблемы времени выполнения.
Что произойдет, если в программе будет ошибка во время выполнения?
Программа продолжится, и то, что произойдет, будет зависеть от побочных эффектов ошибки времени выполнения. Вызов нулевого указателя на функцию, вероятно, заставит программу перейти в неизвестное место.
Будет ли остановлено выполнение программы?
Нет, все будет продолжаться, как будто ничего необычного не произошло, вероятно, делая то, что вы не собирались делать. Это может сбросить или действовать беспорядочно. Он может превратить некоторые входы в выходы и сжечь один или два датчика (но это маловероятно ).
Есть ли какой-нибудь способ заставить Arduino сказать мне, в чем ошибка?
Я так не думаю. Как я уже говорил, механизмов защиты нет. Нет поддержки времени выполнения от языка, нет ОС, нет аппаратных проверок для доступа к памяти за пределами допустимого диапазона (загрузчик также не считается). Вы просто должны быть осторожны с вашей программой и, возможно, установить свои собственные сети безопасности.
Причина отсутствия защиты, вероятно, заключается в том, что контроллеры Arduino слишком дешевы, имеют слишком мало памяти и не должны запускать что-либо слишком важное (да, кажется, что где-то в AVR есть заявление об отказе от использования MCU, обычно используемых Arduino в системах жизнеобеспечения).
Нет никаких исключений времени выполнения. Есть только неопределенное поведение.
На самом деле, нет никаких исключений вообще . Если вы попытаетесь выполнить недопустимую операцию, ее результаты будут неизвестны.
Нет проверки времени выполнения вообще, кроме того, что вы реализуете. Ваша программа работает на железном железе. Это настольный эквивалент работы в ring-0 все время, потому что ATmega не имеет колец .
источник
Есть один механизм, который может вывести MCU из непредсказуемого состояния, и это сторожевой таймер . Если вы реализуете некоторый код, который будет многократно выполняться в цикле, который не будет выполняться в любое время дольше, чем фиксированное время, вы можете установить это время в качестве контрольного периода и включить таймер.
Затем вы должны повторно сбросить таймер в цикле. Если ваш код зависает в каком-то цикле условий, который никогда не закончится, то сторожевой таймер будет считать до нуля и в конечном итоге сбросить MCU.
Таким образом, вы теряете данные, но если вы запускаете AVR WDT в режиме прерывания, вы можете сохранить некоторые данные до сброса MCU.
Таким образом, сторожевой таймер может защитить ваш код от случайных непреднамеренных бесконечных циклов.
Документация: AVR132: использование расширенного сторожевого таймера
источник
Вам понадобится аппаратный отладчик для чего-то вроде этого. Но обычно вы увидите, что программа ведет себя не так, как вы ожидаете, и вам придется взглянуть на этот раздел кода, чтобы определить проблему.
Обычный / быстрый / простой способ сделать это - добавить операторы print для распечатки значений переменных или чего-либо еще, чтобы вы знали, что программа без проблем достигает этой точки в коде. Это поможет вам изолировать проблему дальше.
Я считаю, что VisualMicro имеет некоторые встроенные функции отладки.
источник
Я бы предположил, что процессор AVR не имеет каких-либо инструментов обнаружения ошибок или восстановления. Он может просто остановиться или продолжать игнорировать ошибку и последствия. Как сказал sachleen, вы должны добавить в вашу программу некоторые отладочные операторы, которые выводят данные в середине операции, чтобы проверить, работает ли она. Если вы используете emulaor и устанавливаете точки останова, вы можете легко найти проблему.
источник
Arduino перезагрузится (т.е. перезапустится
setup()
иloop()
).источник