Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: stm32 проблемы в обьявлении глобальных переменных
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
ierofant
Всем привет.
Возникла странная проблема с которой я не могу разобратся.

Контроллер - STM32F100RB. Компилятор - IAR for ARM 6.21

Есть обьявление глобальных переменных:

Код
uint16_t b[50]; //тест
uint16_t b1[50]; //тест
unsigned char time_to_break=0;
unsigned int counter=0;
unsigned char ban=0;
unsigned char push_button=0;
....
еще несколько переменных
....
unsigned char test[100];


В этом случае еще до входа в главную функцию массив test заполнен символами "я".

Если записать к примеру unsigned char test[]="hello my sweety"; , то остальные переменные будут содержать неверные и произвольные значения + контроллер зависает в B HardFault_Handler.

Если обьявление массивов b1 и b2 разместить после обьявления всех остальных переменных, то будет та же ситуация. - неверные значения остальных переменных и зависание B HardFault_Handler.

В общем от перестановки местами строчек обьявления переменных конечная работа устройства очень меняется и в большинстве случаев имеет какую-то проблему.

У меня есть подозрения, что из-за различности типов (char, uint) или еще из-за чего-то происходит неправильное размещение переменных в оперативной памяти. (и они как-то накладываются) Если это так, то как решается? Если нет:
Подскажите, в чем проблема и как с ней бороться. Буду очень признателен.

Заранее благодарен за помощь.
Сергей Борщ
QUOTE (ierofant @ Nov 11 2011, 03:29) *
У меня есть подозрения, что из-за различности типов (char, uint) или еще из-за чего-то происходит неправильное размещение переменных в оперативной памяти. (и они как-то накладываются) Если это так, то как решается?
Нет, это не так. Исходите из того, что компилятор вас не обманывает. Сколько ОЗУ у вас занято под переменные? Сколько памяти выделено под стеки? Эти переменные глобальные или локальные? Симптомы указывают на нехватку стека - стек налезает на переменные. И надо смотреть- если есть куда, то увеличивать стек. Если некуда - урезать осетра, т.е. оптимизировать программу, избавляясь от лишних переменных.
Flexz
Цитата(ierofant @ Nov 11 2011, 03:29) *
В этом случае еще до входа в главную функцию массив test заполнен символами "я".

До входа в главную функцию (main) выполняется загрузчик, который и заполняет инициализировнные в коде переменные их значениями, а остальные нулями.
Вообще похоже на неверный скрипт линкера и/или загрузчик.
Один раз был похожий косяк, правда с gcc: в зависимости от размеров переменных или даже перетаскивания их по коду программа работал или валилась в Hard Fault, уже грешил на компилятор. В итоге оказалось что вектора прерывания сремапленные в оперативку были выровнены по неверному значению (0x100, а надо было по 0x400) Старый код работал на stmf100, где прерываний меньше и выравнивания 0x100 было достаточно, при переносе на stm32f2 используемых прерываний оказалось больше и некоторые не срабатывали.
ierofant
Цитата(Сергей Борщ @ Nov 11 2011, 10:57) *
Нет, это не так. Исходите из того, что компилятор вас не обманывает. Сколько ОЗУ у вас занято под переменные? Сколько памяти выделено под стеки? Эти переменные глобальные или локальные? Симптомы указывают на нехватку стека - стек налезает на переменные. И надо смотреть- если есть куда, то увеличивать стек. Если некуда - урезать осетра, т.е. оптимизировать программу, избавляясь от лишних переменных.


Если считать с массивами - до 1кБ занято переменными.
Под стеки было выделенно 1кБ, я увеличил это значение до 3кБ - ничего не изменилось все те же лишние значения в переменных и HardFault. Кучу на всякий тоже до 3 кБ увеличил - никакого эффекта.
Все переменные глобальные. По тексту программы есть и локальные, но уже до их обьявления и инициализации уже появляются какие-то проблемы.

Цитата
До входа в главную функцию (main) выполняется загрузчик, который и заполняет инициализировнные в коде переменные их значениями, а остальные нулями.
Вообще похоже на неверный скрипт линкера и/или загрузчик.
Один раз был похожий косяк, правда с gcc: в зависимости от размеров переменных или даже перетаскивания их по коду программа работал или валилась в Hard Fault, уже грешил на компилятор. В итоге оказалось что вектора прерывания сремапленные в оперативку были выровнены по неверному значению (0x100, а надо было по 0x400) Старый код работал на stmf100, где прерываний меньше и выравнивания 0x100 было достаточно, при переносе на stm32f2 используемых прерываний оказалось больше и некоторые не срабатывали.

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



Открыл новую зависимость :
Если обьявляется 2 массива :
Код
uint16_t b[50];
uint16_t b1[50];

То начинаются такие проблемы.
Если же обьявлять только один массив - все ок:
Код
uint16_t b[1000];
//uint16_t b1[50];

Можно что угодно местами переставлять и не будет проблем.
Причем величину этого массива можно установить хоть 1000 элементов, все отлично работает.
Вообще не понятно, какая разница в обьявлении двух массивов по 50 или одного на 100 элементов? Почему так коряво работает?

Сергей Борщ
QUOTE (ierofant @ Nov 11 2011, 11:29) *
Почему так коряво работает?
Давайте посмотрим .map
Flexz
Ну поскольку у вас IAR то скорее всего стартап и скрипт линкера правильные (если, конечно, вы их не меняли руками), предположение об их корявости скорее относится к GCC, там каждый их или подбирает готовые на просторах инета или пишет свои.
Действительно надо map смотреть.
PS а процессором в настройках не ошиблись?
ierofant
Нашел ошибку.

Была она в некорректном применении созданых тестовых массивов.

Инициализировал так :
Код
uint16_t b[50];
uint16_t b1[50];


А так обрабатывались( i<99):
Код

for(int i=0; i<99; i++)
{b[i]= *p1;
p1++;}


Значение 99 перекочевало с предыдущей функции, когда использовался 100 элементный массив.
Исправил на 49 - все работает нормально.
А в .map все нормально, потому и начал искать в других местах промах. Ошибка глупая такая, стыдно.

Кстати, нигде не предусмотренна защита от превышения количества обьявленных элементов массива?


Всем большое спасибо за участие и помощь!

Allregia
Цитата(ierofant @ Nov 11 2011, 16:30) *
Кстати, нигде не предусмотренна защита от превышения количества обьявленных элементов массива?


Обычно она "предусморена" в голове прогграммиста, который вместо:
Код
uint16_t b[50];
uint16_t b1[50];

for(int i=0; i<99; i++)
{b[i]= *p1;
p1++;}


пишет так:
Код
#define ARRAY_SIZE  50

uint16_t b[ARRAY_SIZE];
uint16_t b1[ARRAY_SIZE];

for(int i=0; i<ARRAY_SIZE-1; i++)
{b[i]= *p1;
p1++;}
Сергей Борщ
QUOTE (Allregia @ Nov 11 2011, 17:57) *
#define ARRAY_SIZE 50


CODE
for(unsigned int i=0; i<sizeof(b)/sizeof(b[0]); i++)
ierofant
Allregia, Сергей Борщ спасибо за полезные паттерны, буду использовать.
andrewlekar
HardFault - это кстати и есть такая защита. Процессор вообще-то мог бы молча записать по заданным адресам и ничего не сказать. Вот тогда бы намучались вы в поисках ошибки.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.