Ошибка Шредингера исчезает при установке точки останова - PullRequest
8 голосов
/ 08 февраля 2012

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

В моем прерывании по таймеру (всегда работает системный тикер) у меня есть что-то вроде этого:

 if (a && lot && of && conditions)
 {
     some_global_flag = 1;                   // breakpoint 2
 }

в моем основном цикле у меня есть

 if (some_global_flag)
 {
     some_global_flag = 0;
     do_something_very_important();   // breakpoint 1
 }

Это условие в основном цикле никогда не вызывается, когда условия в таймере (я думаю) выполнены. Условия внешние (порты, результаты АЦП и т. Д.). Сначала я ставлю точку останова на позицию 1, и она никогда не срабатывает.

Чтобы проверить это, я поставил точку останова nr. 2 в строке some_global_flag = 1;, и в этом случае код работает: обе точки останова срабатывают при выполнении условий.

Обновление 1:

Чтобы выяснить, отвечает ли какое-либо условие синхронизации, и никогда не вводится if в таймере, если он работает без отладки, я добавил в свой таймер следующее:

 if (a && lot && of && conditions)
 {
     some_global_flag = 1;                   // breakpoint 2
 }


 if (some_global_flag)
 {
     #asm("NOP");    // breakpoint 3
 }

Флаг не используется нигде в коде. Он находится в ОЗУ, и ОЗУ в начале очищается до нуля.

Теперь, когда все точки останова отключены (или включена только точка останова 1 в главном), код работает некорректно, функция не выполняется. Однако, если я включаю только точку останова 3 на NOP, код работает! Точка останова срабатывает, и после продолжения функция выполняется. (Имеет видимый и слышимый вывод, поэтому очевидно, если он работает)

Обновление 2:

Прерывание таймера было прервано с помощью «SEI» в его начале. Я удалил эту строку, но поведение не изменилось каким-либо заметным образом.

Обновление 3:

Я не использую внешнюю память. Поскольку я очень близок к пределу во флэш-памяти, у меня максимальная оптимизация размера в компиляторе.

Может ли компилятор (CodeVision) быть ответственным или я сделал что-то очень неправильное?

Ответы [ 5 ]

5 голосов
/ 08 февраля 2012

Это, вероятно, типичная ошибка оптимизации / отладки.Убедитесь, что some_global_flag помечен как энергозависимый.Это может быть int uint8 uint64, как вам угодно ...

volatile int some_global_flag

Таким образом, вы говорите компилятору не делать никаких предположений о значении some_global_flag.Вы должны сделать это, потому что компилятор / оптимизатор не может видеть никаких вызовов вашей подпрограммы прерывания, поэтому он предполагает, что some_global_flag всегда равен 0 (начальное состояние) и никогда не изменяется.

Извините, неправильно прочитал ту часть, где вы уже пыталисьэто ...

Вы можете попробовать скомпилировать код с помощью avr-gcc и посмотреть, есть ли у вас такое же поведение ...

5 голосов
/ 08 февраля 2012

Отладчики могут / могут изменять способ работы процессора и выполнения кода, так что это не удивительно.

разделяй и властвуй. Начните удалять вещи, пока это не работает. Параллельно с этим начните с нуля, добавьте только прерывание по таймеру и несколько строк кода в главном цикле с do_something_very_important (), что-то простое, например мигание светодиода или выплевывание чего-либо из uart. если это не сработает, вы не получите большее приложение для работы. Если это сработает, начните добавлять код инициализации и больше условий в ваше прерывание, но не усложняйте основной цикл больше, чем несколько описанных строк. Увеличьте условия обработчика прерываний, добавляя больше кода обратно, пока он не завершится неудачей.

Когда вы достигнете границы, где вы можете добавить одну вещь и потерпеть неудачу и удалить ее, а не потерпеть неудачу, тогда выполните некоторую дизассемблирование, чтобы увидеть, является ли это компилятором. это может оправдать другой SO билет, если не очевидно, «почему мой обработчик прерываний avr прерывается, когда я добавляю ...»

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

4 голосов
/ 08 февраля 2012

Это может показаться странным, но в конечном итоге оказалось, что оно вызвано сильными переходными процессами в одной из входных линий (которая питает систему, но ее измерение АЦП также используется в качестве условия).

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

Я не опубликовал это в вопросе, потому что я тестировал эту часть системы и работал отлично, поэтому я не хотел сбивать вас с курса.

В конце я выяснил, что в среде, которая создает очень сильные переходные процессы, была использована новая функция, и одно из условий в моем вопросе зависело от состояния, которое зависело от одной из этих переменных в «постоянном» RAM ", и, наконец, использование точки останова спасло меня от последствий этого переходного процесса.

Наконец проблема была решена с корректировками во времени.

Редактировать: что помогло мне определить местонахождение проблемы, так это то, что я записал значения своих наиболее важных переменных в область «постоянной памяти» и увидел, что некоторые из них были повреждены.

1 голос
/ 09 сентября 2014

Это написано в предположении, что процессор ARM.

использование точки останова (точка bk ОЗУ или ПЗУ) заставляет процессор переключаться из режима запуска в режим отладки в точке останова (либо в режим остановки, либо в режим мониторинга) и заставляет его работать на скорости отладки или для запуска обработчика прерывания и, следовательно, Отладка на основе JTAG - это в основном навязчивая отладка.

ETM (встроенный Trace Macrocell), в частности, в ARM (или других типах шинных контрольно-измерительных приборов), разработан таким образом, чтобы он не был навязчивым и мог записывать инструкции и данные в режиме реального времени, чтобы мы могли проверить, что на самом деле произошло.

1 голос
/ 08 февраля 2012

Я могу ошибаться, но если вы используете отладчик для подключения к рассматриваемой плате и отладки программы на оборудовании, на котором она должна была работать, я думаю, что это может изменить поведение микроконтроллера, когда он выполняет присоединение.... Кроме того, что это и ключевое слово volatile, предложенное выше, у меня нет никаких подсказок.

...