реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Защита памяти, Нужно защитить переменную в памяти
Sergio66
сообщение Apr 27 2010, 19:28
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Доброго вечера!
Есть программа, для Меги32.
Уже пол-года в тестовой эксплуатации.
Возникает следующая проблема - иногда, (из 50 приборов за 4 месяца круглосуточной эксплуатации) 3 или 4 раза произошел сбой системного времни
Системные часы организованы по таймеру от задающего генератора (16МГц).
CStack программы выбран в соответствии с МАР файлом, RStack - аналогично. Однако, в программе используется ф-я printf.
И у меня есть подозрение, что для нее компиллер не может правильно оценить размер CStack, и она, при своей работе выходит за границы объявленного стека и портит рабочие переменные.
переменная системного времени (__no init) расположена, естесственно в ОЗУ.
Внимание вопрос - есть ли какие нибудь мысли, как расположить данную переменную так, чтобы никакая функция, вышедшая за границы стека ее не могла испортить.
Отловить ошибку средствами отладчика не представляется возможным. Ошибка довольно редкая.
И еще.
что происходит с CStack, когда он достигает дна. Где после этого будут размещаться локальные переменные?
Заранее благодарю.
Go to the top of the page
 
+Quote Post
Александр Куличо...
сообщение Apr 28 2010, 04:19
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017



Цитата
что происходит с CStack, когда он достигает дна.

Если не меняли xcl-файл, то налезет на RSTACK. Дальнейшее поведение непредсказуемо.

Вы точно уверены, что сбой времени был следствием нарушения границ стека? Может, из-за банального пропадания питания?
Если компиллер неверно оценивает CStack, сделайте это за него. При наличии свободной памяти накиньте 30..50..100% на стек.


P.S. Что дает Вам __no_init по отношению к системному времени? Или у Вас имеется кнопка/внешний сигнал сброса / используется собака ?
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Apr 28 2010, 05:20
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(Александр Куличок @ Apr 28 2010, 08:19) *
Если не меняли xcl-файл, то налезет на RSTACK. Дальнейшее поведение непредсказуемо.

Странно, RStack находится в более старших адресах, а CStack развивается в сторону уменьшения адреса (если я правильно понимаю).

Цитата(Александр Куличок @ Apr 28 2010, 08:19) *
Вы точно уверены, что сбой времени был следствием нарушения границ стека? Может, из-за банального пропадания питания?

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

Цитата(Александр Куличок @ Apr 28 2010, 08:19) *
Если компиллер неверно оценивает CStack, сделайте это за него. При наличии свободной памяти накиньте 30..50..100% на стек.

Уже некуда
CStack = 0х300
Памяти в обрез!

Цитата(Александр Куличок @ Apr 28 2010, 08:19) *
P.S. Что дает Вам __no_init по отношению к системному времени? Или у Вас имеется кнопка/внешний сигнал сброса / используется собака ?

Есть и ресет, есть и функция обновления версии ПО (bootloader)управляемый основной программой. Оттого и __no_init.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 28 2010, 06:34
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(Sergio66 @ Apr 27 2010, 22:28) *
Внимание вопрос - есть ли какие нибудь мысли, как расположить данную переменную так, чтобы никакая функция, вышедшая за границы стека ее не могла испортить.

biggrin.gif

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

Мне трудно судить о вашей программе, но, исходя из вероятности сбоя, мне кажется у вас проблемы с атомарностью доступа к переменной, достаточно редко используемой. Это можно проверить, блокируя участки кода запретом прерывания. Так можно локализовать "место порчи". Ну и классический способ: взять исходник, и думать, как машина. smile.gif
Go to the top of the page
 
+Quote Post
Александр Куличо...
сообщение Apr 28 2010, 06:58
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017



Цитата
Странно, RStack находится в более старших адресах, а CStack развивается в сторону уменьшения адреса (если я правильно понимаю)

Понимаете правильно. Это я не учел, что настройки линковщику можно передать не только из xcl-файла. Видимо, у Вас они как раз задаются из диалогового окна свойств проекта.
А в xcl по-умолчанию (для модели small )расположение стеков такое, как я говорил выше - CSTACK после RSTACK:
Код
-Z(DATA)TIYNY_I,TINY_Z,TINY_N=60-FF
-Z(DATA)NEAR_I,NEAR_Z=60-85F
-Z(DATA)RSTACK+_..X_RSTACK_SIZE=60-85F
-Z(DATA)CSTACK+_..X_CSTACK_SIZE=60-85F
-Z(DATA)HEAP+_..X_HEAP_SIZE=60-85F
-Z(DATA)IOSTREAM_N#60-85F
-Z(DATA)NEAR_HEAP+_..X_NEAR_HEAP_SIZE=60-85F

Если памяти в обрез, то можете переместить сист. время в область TINY, подальше от стека. Но это не спасает ситуацию, так как будут портится другие данные.
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Apr 28 2010, 08:05
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(SasaVitebsk @ Apr 28 2010, 10:34) *
biggrin.gif

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

1. Все другие переменные восстанавливаемы. Все, кроме времени. Они восстанавливаются из контекста программы.
2. Вопрос ставился именно КАК защитить определенную область памяти от всяких случайных переполнений. Чтобы ВСЕ переменные не портились. Ну, на крайний случай - критические данные, типа времени.
Цитата(SasaVitebsk @ Apr 28 2010, 10:34) *
Мне трудно судить о вашей программе, но, исходя из вероятности сбоя, мне кажется у вас проблемы с атомарностью доступа к переменной, достаточно редко используемой. Это можно проверить, блокируя участки кода запретом прерывания. Так можно локализовать "место порчи". Ну и классический способ: взять исходник, и думать, как машина. smile.gif

Что касается доступа - то системное время мнеяется только в обработчике прерывания таймера, а во всех остальных случаях, только читается и переностится в лог.
Конфликт доступа исключен.
Причем, сбивается оно случайным образом - не предсказуемо на какое значение, а в обработчике прерывания оно меняется только на 1 (+1). Т.е. конфликт доступа, если бы он и был, то не приводил бы к таким последствиям.

И, возвращаясь к вопросу стека - при настройках из xcl-файла, CStack развивается в сторону младших или старших адресов? Судя по тому, как задан стек, мне кажется, что в сторону младших. Т.о., при выходе за 0х60 адрес, стек что будет портить? регистровый файл? Старшие адреса области данных? Старшие адреса RStack?
Go to the top of the page
 
+Quote Post
GDI
сообщение Apr 28 2010, 08:57
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Ну переместите вашу переменную в другое месть или жестко задайте ей другой адрес по дальше от границы стека или просто измените порядок объявления переменных в исходнике. Если уверены что дело в стэке, то почему бы вам чисто для отладки не уменьшить его значение, тогда по идее должна увеличится частота возникновения ошибок. В ИАРе (вы ведь им пользуетесь?) в настройках проекта можно включить показ дополнительной информации в мап-файле, в частности можно включить показ рекомендуемого/расчетного размера стека.
P.S. А защитить что-либо при порче стека, конечно же невозможно, по крайней мере в архитектуре АВР.


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Apr 28 2010, 09:14
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(GDI @ Apr 28 2010, 12:57) *
Ну переместите вашу переменную в другое месть или жестко задайте ей другой адрес по дальше от границы стека или просто измените порядок объявления переменных в исходнике. Если уверены что дело в стэке, то почему бы вам чисто для отладки не уменьшить его значение, тогда по идее должна увеличится частота возникновения ошибок. В ИАРе (вы ведь им пользуетесь?) в настройках проекта можно включить показ дополнительной информации в мап-файле, в частности можно включить показ рекомендуемого/расчетного размера стека.
P.S. А защитить что-либо при порче стека, конечно же невозможно, по крайней мере в архитектуре АВР.


Да, я пользуюсь именно ИАРом. И стек я выбираю именно по рекомендациям из МАР файла.
Скажите, а вот для такой конструкции ИАР корректно может вычислить размер стека:
printf("трали вали %u", f(x));
где f(x) возвращает int ???
Есть у меня именно такие конструкции, грешу на них.
Есть мысли по этому поводу?

А чтобы переместить критическую переменную подальше от границ стека, я и задавал вопрос - куда будут писаться локальные переменные при нарушениии границ CStack?
в RStack? в регистовый файл? или в область старших адресов SRAM?
Go to the top of the page
 
+Quote Post
GDI
сообщение Apr 28 2010, 09:50
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



По моему мнению он выдаст вам максимальный размер стека которой захочет занять printf в вашей программе, если у вас система не многозадачная и не вызывается одновременно несколько printf (а выполнять printf из прерываний категорически не рекомендуется), то предсказанного размера стека должно хватить с лихвой. В реальной программе очень редко выполняется условие максимального стека, для этого надо одновременно запустить по одному экземпляру всех функций. Другое дело, если у вас где-то есть утечка памяти, вот в этом случае и возникают чудеса со стеком.

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


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 28 2010, 10:11
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



1) Да не может происходить сбой 1 раз в месяц по причине стэка. У вас бы непрерывно были бы проблемы.
2) Не имеет значения восстанавливается переменная или нет - при порче стэка, в общем случае поведение непредсказуемо.
3) Не имеет значения, что портится ячейка часов - проблема может быть с любой ячейкой (в плане атомарного доступа). Например с указателем.
Приведу пример. Идёт работа с массивом. Смещение(индекс) - 2 байта. При вычислении текущего индекса, приходит прерывание, а операция ещё не завершена. Например только первый байт индекса занесён. Далее в прерывании производится операция с этим же массивом. В качестве адреса берётся уже неверное значение - и выполняется операция доступа (записи). В результате портится ячейка.
То есть ошибка, например, при работе с USART, а портится время.
Go to the top of the page
 
+Quote Post
ar__systems
сообщение Apr 29 2010, 12:10
Сообщение #11


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



Цитата(Sergio66 @ Apr 27 2010, 14:28) *
И у меня есть подозрение, что для нее компиллер не может правильно оценить размер CStack, и она, при своей работе выходит за границы объявленного стека и портит рабочие переменные.


А тупо протестировать вы эту гипотезу не можете? Вызвать вашу принтф из самой глубокой функции в дереве вызовов с самым большим кол-во параметров, и посмотреть симуляторе, что произошло с памятью.

Цитата(Sergio66 @ Apr 28 2010, 04:14) *
Скажите, а вот для такой конструкции ИАР корректно может вычислить размер стека:
printf("трали вали %u", f(x));

А чего тут вычислять? Для компилятора это все равно что
Код
tmp = f(x);
printf("трали вали %u", tmp);

Вот если ваша f(x) рекурсивная, тады конешно ОЙ!

Сообщение отредактировал ar__systems - Apr 29 2010, 12:12
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 21:17
Рейтинг@Mail.ru


Страница сгенерированна за 0.01484 секунд с 7
ELECTRONIX ©2004-2016