Jump to content

    

STM32L151 падает при выделении памяти

Контроллер STM32L151RB, CoIDE. Создаю проект, добавляю из репозитория cmsis_boot и CMSIS_core. Собирается, отладка запускается без проблем. Добавляю строку:

uint8_t * ptr = malloc(4);

Не собирается, ругается что не определена функция _sbrk(). Добавляю из репозитория C Library. Собирается. Запускаю отладку. Дохожу до вызова malloc(), и программа падает в Default_Handler(). Если определить все обработчики ошибок, то сваливается в HardFault.

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

Что я делаю не так? Или может какая-то особенность есть с динамическим выделением памяти у этих STM32L151? Если все-же я что-то не так делаю, буду очень благодарен, если кто-то поделится пустой заготовкой проекта в CoIDE, чтобы нормально память выделялась.

Share this post


Link to post
Share on other sites

Ну какая особенность при выделении памяти? Не выдумывайте ужастики.

1. Стандартная процедура выделения памяти сравнивает запрошенный объём с доступным. Если памяти в куче достаточно, то выдаёт указатель на начало, а если нет, то 0. То есть падать при этой процедуре ничего не может. Упасть может, если она выдаёт 0 (недостаточно памяти) а вы это используете как указатель.

2. Перейдите на ассемблер и выясните полную картину.

3. В опциях проекта, где-то, задаётся размер памяти, выделенный на кучу. Я CoIDE не пользуюсь, поэтому подсказать где именно не могу. Поищите.

Share this post


Link to post
Share on other sites

Разница между Cortex-M0(+) и Cortex-M3,M4 (STM32F407) - последний умеет невыровненный доступ. И если область памяти, которую вы отдаете менеджеру памяти, не выровнена - вполне возможно падение (ибо менеджер наверняка ожидает выровненную область). Фигню написал, у 151 ядро M3, умеет невыровненный доступ.

 

Как реализован конкретно ваш менеджер - понятия не имею. Можно туп сделать возврат из HardFault_Handler() и поставить в него точку останова. Выйдя попадете на команду, вызвавшую исключение и исходя из команды и ее аргументов можно думать дальше.

 

У вас же есть отладчик - неужели сложно пройти по дизассемблерному коду до места падения?

Share this post


Link to post
Share on other sites

Так в том то и дело, что специально для проверки создал пустой проект, в котором только одна вышеупомянутая строка. И именно на ней падает.

Share this post


Link to post
Share on other sites

посмотрите ld-файлы для STM32F407 и для STM32L151 - может, у вас ссылки на heap в скриптах по-разному заданы? может, для 151 размер кучи = 0?

Share this post


Link to post
Share on other sites
Так в том то и дело, что специально для проверки создал пустой проект, в котором только одна вышеупомянутая строка. И именно на ней падает.

Вы читать умеете? Перечитайте ещё раз мой пост. Перечитайте несколько раз, если с первого не доходит.

Share this post


Link to post
Share on other sites
посмотрите ld-файлы для STM32F407 и для STM32L151 - может, у вас ссылки на heap в скриптах по-разному заданы? может, для 151 размер кучи = 0?

Совпадают слово в слово. Разве что в 407 еще ram1 есть.

 

Все-таки посмотрел ассемблер и память, и стало более понятно.

Нашел в startup файле 151го такую особенность:

void Default_Reset_Handler(void)
{
  /* Initialize data and bss */
//  unsigned long *pulSrc, *pulDest;

  /* Copy the data segment initializers from flash to SRAM */
//  pulSrc = &_sidata;
//
//  for(pulDest = &_sdata; pulDest < &_edata; )
//  {
//    *(pulDest++) = *(pulSrc++);
//  }
//
//  /* Zero fill the bss segment. */
//  for(pulDest = &_sbss; pulDest < &_ebss; )
//  {
//    *(pulDest++) = 0;
//  }

  /* Setup the microcontroller system. */
  SystemInit();
    
  /* Call the application's entry point.*/
  main();
}

Из-за этого в начале SRAM находился какой-то мусор и в процессе работы функции malloc в один момент происходило деление на 0.

Раскомментировал этот кусок. Мусор стал более системотизированным, но остался мусором (в сравнении с 407). Куда дальше копать?

И еще заметил особенность. Во всех других ARMах и не только, при инициализации структуры таким вот образом:

static type struct_name = {};

все поля структуры инициализируются нулями. А тут почему-то в них тоже какой-то мусор находится.

Share this post


Link to post
Share on other sites
Нашел в startup файле 151го такую особенность:

void Default_Reset_Handler(void)
...

Удивительная штука эти кокосы...

Либо этот файл не используется, либо никто никогда не пробовал с этими исходниками работать.

 

Вопросы:

этот кусок вызывается? (проще всего проверить - поставить внутрь брекпоинт).

чему равны адреса _sdata, _edata, _sbss, _ebss, _sidata ? Можно посмотреть в map-файле. Заодно можно посмотреть их объявления в скрипте линкера.

 

 

PS а вообще - давно пора самый минимальный пример куда-нибудь на гугл-диск выложить...

 

Share this post


Link to post
Share on other sites

Ещё раз попробую.

1. По умолчанию размер кучи равен 0. Динамическая память не всем нужна. Вы должны настроить размер кучи в опциях проекта.

2. У вас отладчик есть? Но в принципе можно и симулятором, наверное. Пройдите по шагам и посмотрите.

3. Покажите листинг malloc. Зачем там деление? Не верю.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this