Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Cторожевой таймер
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
sKWO
Чтобы привести в чувство зависший контроллер использую вотчдог.
При сбросе теряются значения переменных
Можно ли сделать так чтобы их не терять и как?
Программа слишком большая и искать причину сложно. sad.gif
SlavaG
Все переменные (глобальные) после сброса инициализируются либо нулями либо указанными значениями. Чтобы их значения не изменялись после сброса по ВД надо объявить их как __noinit (в иаре) или поместить в секцию noinit (в gcc)
sKWO
Цитата(SlavaG @ Apr 19 2007, 18:28) *
Все переменные (глобальные) после сброса инициализируются либо нулями либо указанными значениями. Чтобы их значения не изменялись после сброса по ВД надо объявить их как __noinit (в иаре) или поместить в секцию noinit (в gcc)

А в коде визионе не знаете случайно??
WHALE
Специальной директивы нет sad.gif ,имхо только использовать свой старт-ап.
Курите в сторону HELP-->Using an External Startup File,все более-менее описано.Тока там асм.
Я беру его собственный старт-ап и рихтую руками,вам нужна эта область
;GLOBAL VARIABLES INITIALIZATION.
Откройте map-файл,посмотрите где лежат ваши переменные и грохните обнуление.
Но в общем это борьба с зубной болью с помощью димедрола-надо все-равно побороться с перезапуском программы.
Сергей Борщ
Цитата(WHALE @ Apr 19 2007, 19:36) *
Но в общем это борьба с зубной болью с помощью димедрола-надо все-равно побороться с перезапуском программы.
С этой оценкой согласен, но если это какое-то сверхнадежное_устройство_от_которого_зависит_жизнь, то надо не грохнуть обнуление (как же программа первый раз стартанет с мусором в переменных-то?) а сделать проверку на предмет "а по собаке ли мы сюда попали" и если по собаке - обойти обнуление. В ИАРе для обхода инициализации надо вернуть 0 из __low_level_init() и переделывать cstartup не придется.
Igor26
Как это
Цитата
надо вернуть 0 из __low_level_init()
?

Я хелпе на IAR не нашел ничего про __low_level_init().
Ткнине носом, где искать.
satellite-plus
Цитата(Сергей Борщ @ Apr 19 2007, 22:57) *
С этой оценкой согласен, но если это какое-то сверхнадежное_устройство_от_которого_зависит_жизнь, то надо не грохнуть обнуление (как же программа первый раз стартанет с мусором в переменных-то?) а сделать проверку на предмет "а по собаке ли мы сюда попали" и если по собаке - обойти обнуление. В ИАРе для обхода инициализации надо вернуть 0 из __low_level_init() и переделывать cstartup не придется.


Для исключения лишнего кода я прописываю пустые функции.
void __low_level_init(void){}
void __memclr(void){}
void __flashcpy(void){}
void __segment_init(void){}
Сергей Борщ
Цитата(Igor26 @ Apr 20 2007, 07:42) *
Я хелпе на IAR не нашел ничего про __low_level_init().
Ой! Compiler Reference->System startup and termination или просто поиск по ключевому слову __low_level_init.
Цитата
The value returned by __low_level_init determines whether or not data segments 0, the data should be initialized by the system startup code. If the function returns segments will not be initialized.
В папках \src\lib компилятора находим "рыбу" low_level_init.c, в конце которого также есть комментарий:
Код
  /* Return 1 to indicate that normal segment */
  /* initialization should be performed. If   */
  /* normal segment initialization should not */
  /* be performed, return 0.                  */
  return 1;
Если будете использовать __low_level_init в проектах на С++, не забудьте объявить его как extern "C".

Вот еще нашел в хелпе, в разделе Implementation of system startup code, про рихтовку стартапа:
Цитата
Note: Do not modify the file cstartup.s90 unless required by your application. Your __low_level_init for first option should be to use a customized version of initialization code.


Цитата(satellite-plus @ Apr 20 2007, 08:35) *
Для исключения лишнего кода я прописываю пустые функции.
void __low_level_init(void){}
void __memclr(void){}
void __flashcpy(void){}
void __segment_init(void){}
Интересно. Но буду спорить.
1)__low_level_init должен возвращать число. Объявляя его как void можно как минимум получить жалобу линкера, как максимум - непредсказуемое поведение программы в зависимости от содержимого R16 в момент вызова этой функции. Можно конечно говорить, что он был проициализирован где-то незадолго до этого, ветвлений нет и значение в этой точке всегда одинаково, но это можно гарантировать ровно до перехода на новую версию компилятора и вообще вам повезло что там именно такое значение. Если "жаба душит" на одну команду LDI R16, 0 то надо редактировать cstartup и выбросить оттуда RCALL __low_level_init и проверку, что потянет за собой выбрасывание на этапе линковки всего __low_level_init() в виде оставшегося RET. Во-первых это еще экономия, во-вторых - поведение будет детерменированным без шаманства.
2) __memclr() - обнуляет все глобальные и статические переменные, которым при объявлении явно не присвоено какое-либо значение. Выполнена в виде цикла ST Z+, R? Вам ведь все равно приходится каким-то образом присваивать переменным начальные значения, и сомневаюсь что отдельно для кажой переменной это получится эффективнее чем в цикле всем скопом. Единственный вариант, который приходит в голову - ваша программа не использует глобальных переменных вообще. Но в этом случае скорее всего применение нескольких глобальных переменных может дать выигрыш в коде больший, чем выкидывание __memclr. И опять же правя cstartup вы сэкономите еще один RCALL и RET.
3) __flashcpy() - пропущу, не знаю что она делает.
4) __segment_init() - копирование образов сегментов XXXX_I (инициализированные глобальные и статические переменные) в ОЗУ из флеша из сегментов XXXX_ID. Делается парой вложенных циклов сразу для всех переменных. Сомневаюсь, что вручную вы сделаете ту же работу эффективнее. Аргументы те же, что и в п.2.

Резюме моих возражений - искать где экономить код нужно не здесь а в основной программе.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.