Процессор Atmel сбрасывается, но в MCUSR не указан источник сброса - PullRequest
0 голосов
/ 11 декабря 2011

Краткий рассказ:

Каковы условия сброса, которые не устанавливают бит в MCUSR процессора ATmega, но все же вызывают сброс?

Длинная история:

Я использую обнаружение отключения в ATmega168, и в моем коде есть место для его обработки.Если моя система теряет мощность, конденсатор удерживает ее выше уровня отключения примерно полсекунды, а когда я восстанавливаю питание, процедура обработки отключения отключается успешно.(Я проверяю бит отключения в MCUSR.)

Однако, когда я медленно уменьшаю напряжение в системе и медленно возвращаю его обратно, процессор перезагружается, и процедура обработки отключения вызываетне работает: MCUSR равен нулю !!!(Я использую внешний отладчик через DebugWire, чтобы проверить его.)

Что может вызвать это?Если бы это было что-то еще, например, если сторожевой таймер был случайно включен (я не использую его, и отключаю его при запуске), в MCUSR.

было бы по крайней мере что-то, но это не былони сброса сторожевого таймера (бит 3), сброса отключения (бит 2), внешнего сброса (бит 1) или сброса при включении питания (бит 0), поэтому что не вызвало сброса, если нииз вышеизложенного ??

Еще одна странная вещь: после такого условия в некоторых случаях периодически происходит сброс, всегда со значением ноль в MCUSR.

В противном случае, когда этоне происходит, система работает всегда идеально.

Редактировать:

В другом месте я не смог найти окончательного ответа, какой сброс приводит к переполнению стека, илипохожая ошибка программного обеспечения приводит к?Может быть, это те условия, которые могут перезагрузить процессор и оставить MCUSR в покое?Я думал, что такие условия просто повреждают ОЗУ или, возможно, даже счетчик программ, но не вызывают сброса.

Ответы [ 3 ]

3 голосов
/ 12 декабря 2011

Переполнение стека не вызывает сброса. Переполнение стека является чисто программным условием, которое, вероятно, приведет к неопределенному поведению. Есть много, много симптомов, которые могут возникнуть в результате переполнения стека. Например:

  1. Нет видимых изменений в поведении
  2. Повреждение смежной памяти приводит к неожиданному или неопределенному поведению, такому как отсылка нулевого указателя или выполнение недействительных инструкций

Переполнение стека может появиться , чтобы вызвать сброс, если процессор выполняет недопустимую инструкцию, а исключение не обрабатывается. Это опять-таки программно-определяемое поведение в зависимости от программного обработчика исключений. То же самое может произойти с разыменованием указателя NULL или указателя на недопустимое пространство памяти.

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

Вы упомянули, что понижаете напряжение, а затем повышаете его. Переходит ли в сброс, если просто понизить напряжение? У вас есть код, который контролирует напряжение? Интересно, почему вы подозреваете ошибку состояния программного обеспечения как причину при изменении состояния оборудования.

1 голос
/ 12 декабря 2011

Вы пробовали поиграть с предохранителем BODLEVEL, если это что-то меняет?

Однако это может быть легко вызвано переполнением стека или другими проблемами программного обеспечения. Особенно, если вы работаете с указателями на функции - это может быть просто скачок до 0. У меня были такие проблемы в прошлом.

На самом деле никогда не делал этого, но я полагаю, что вы могли бы легко различить сброс и «скачок», если вы проверите значение какого-либо другого регистра, который вы изменили в своем программном обеспечении. Если это действительно регистры сброса, их тоже нужно инициализировать. Например. установите PORTB в 0x55 где-нибудь в вашем коде. Затем при загрузке проверьте его значение. Если это был сброс, он должен быть 0x00, если нет - 0x55.

0 голосов
/ 22 декабря 2012

Если вы используете avrgcc, попробуйте это:

volatile char mcusr __attribute__ ((section (".noinit")));
void main(void){
  mcusr=MCUSR;
  ...
  if(mcusr&0x01)printf("WD");
  if(mcusr&0x02)printf("EX");
  if(mcusr&0x04)printf("BO");
  if(mcusr&0x08)printf("PO");
  ...
}
...