Перейти к содержанию
    

stm32 проблемы в обьявлении глобальных переменных

Всем привет.

Возникла странная проблема с которой я не могу разобратся.

 

Контроллер - 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) или еще из-за чего-то происходит неправильное размещение переменных в оперативной памяти. (и они как-то накладываются) Если это так, то как решается? Если нет:

Подскажите, в чем проблема и как с ней бороться. Буду очень признателен.

 

Заранее благодарен за помощь.

Изменено пользователем ierofant

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня есть подозрения, что из-за различности типов (char, uint) или еще из-за чего-то происходит неправильное размещение переменных в оперативной памяти. (и они как-то накладываются) Если это так, то как решается?
Нет, это не так. Исходите из того, что компилятор вас не обманывает. Сколько ОЗУ у вас занято под переменные? Сколько памяти выделено под стеки? Эти переменные глобальные или локальные? Симптомы указывают на нехватку стека - стек налезает на переменные. И надо смотреть- если есть куда, то увеличивать стек. Если некуда - урезать осетра, т.е. оптимизировать программу, избавляясь от лишних переменных.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

До входа в главную функцию (main) выполняется загрузчик, который и заполняет инициализировнные в коде переменные их значениями, а остальные нулями.

Вообще похоже на неверный скрипт линкера и/или загрузчик.

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

Изменено пользователем Flexz

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет, это не так. Исходите из того, что компилятор вас не обманывает. Сколько ОЗУ у вас занято под переменные? Сколько памяти выделено под стеки? Эти переменные глобальные или локальные? Симптомы указывают на нехватку стека - стек налезает на переменные. И надо смотреть- если есть куда, то увеличивать стек. Если некуда - урезать осетра, т.е. оптимизировать программу, избавляясь от лишних переменных.

 

Если считать с массивами - до 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 элементов? Почему так коряво работает?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почему так коряво работает?
Давайте посмотрим .map

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну поскольку у вас IAR то скорее всего стартап и скрипт линкера правильные (если, конечно, вы их не меняли руками), предположение об их корявости скорее относится к GCC, там каждый их или подбирает готовые на просторах инета или пишет свои.

Действительно надо map смотреть.

PS а процессором в настройках не ошиблись?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нашел ошибку.

 

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

 

Инициализировал так :

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 все нормально, потому и начал искать в других местах промах. Ошибка глупая такая, стыдно.

 

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

 

 

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Обычно она "предусморена" в голове прогграммиста, который вместо:

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++;}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Allregia, Сергей Борщ спасибо за полезные паттерны, буду использовать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

HardFault - это кстати и есть такая защита. Процессор вообще-то мог бы молча записать по заданным адресам и ничего не сказать. Вот тогда бы намучались вы в поисках ошибки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...