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

Пришлось срочно сделать маленькую поделку на STM32F103CBT6 (Maplemini).

Готового шаблона под этот камень у меня не было, но есть несколько рабочих проектов под STM32F105.

Скопировал проект, выбросил лишнее, заменил файлы конфигурации и стартап.

Работаю в ИАРе, одна из последних версий. Процессор стирается, шьется.

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

В памяти вижу, что там, где должен лежать Reset_Handler - всегда нечетный адрес.

Вероятно в этом и есть причина такого поведения. Но как я этого добился, не могу понять.

Попытки тасовать модули в памяти не помогают, адрес меняется, но всегда нечетный.

Ничего нечётного в памяти нет, да и с чего компилятор так располагает в памяти main, совершенно не понимаю.

Может кто подскажет идею? В опциях проекта вроде уже всё просмотрел...

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


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

"после выполнения первой команды" чего? Стартап кода или main()?

Reset_Handler это точка входа __iar_program_start, а не точка входа в main().

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


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

Младший бит - это признак STUB, он и должен быть установлен

Странно, а на других проектах (рабочих) адрес чётный. Смотрел в двух вариантах.

 

 

"после выполнения первой команды" чего? Стартап кода или main()?

Reset_Handler это точка входа __iar_program_start, а не точка входа в main().

Вероятно всё же стартап кода, но здесь трудно сказать.

Я говорил как раз про адрес Reset_Handler, т.е. тот адрес, который находится сразу за адресом стека.

Местоположение - 0x08000004.

После открытия окна отладки указатель естественно находится на main().

При любой попытке шагнуть всё зависает на выполнении кода.

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

 

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


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

Странно, а на других проектах (рабочих) адрес чётный. Смотрел в двух вариантах.

 

а где вы адрес смотрите? Прямо в бинарнике?

 

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

 

Так если у вас есть отладчик - то чего мы гадаем? Считайте содержание регистров с данными об ошибке и разберите их - поймете, что не так

 

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


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

а где вы адрес смотрите? Прямо в бинарнике?

На рабочих проектах только в *.hex, а в этом тестовом и в *.hex и в отладчике IAR и читал память через ST-LINK Utility.

После адреса 0х08000000 первые 4 байта адрес стека, дальше обработчик по ресету.

Порядок байт в памяти учитывал.

 

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


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

Странно, а на других проектах (рабочих) адрес чётный. Смотрел в двух вариантах.

 

 

 

Вероятно всё же стартап кода, но здесь трудно сказать.

Я говорил как раз про адрес Reset_Handler, т.е. тот адрес, который находится сразу за адресом стека.

Местоположение - 0x08000004.

После открытия окна отладки указатель естественно находится на main().

При любой попытке шагнуть всё зависает на выполнении кода.

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

 

Вот как раз в main() косяк, а стартап, к которому идёт обращение из 0x08000004, уже благополучно отработал.

У вас же в настройках IAR-а: Debugger->Setup->RunTo main() - птичка стоит.

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


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

Так если у вас есть отладчик - то чего мы гадаем? Считайте содержание регистров с данными об ошибке и разберите их - поймете, что не так

А подскажите, где смотреть? Как то до сих пор всё идеально работало. А если и были вылеты, то причины были очевидными.

 

 

А подскажите, где смотреть? Как то до сих пор всё идеально работало. А если и были вылеты, то причины были очевидными.

Вроде как стоят следующие флаги в SCB_CFSR

Imprecise data bus error

During exception stacking

Буду разбираться чего это такое.

 

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


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

А подскажите, где смотреть? Как то до сих пор всё идеально работало. А если и были вылеты, то причины были очевидными.

 

Есть хорошая книжка The definitive guide to the ARM Cortex-M3 / Joseph Yiu

 

SCB->CFSR: Confgurable Fault Status register

SCB->HFSR: Hard Fault Status register

SCB->DFSR: Debug Fault Status register

SCB->AFSR: Auxiliary Fault Status register

SCB->MMAR: MemManage Fault Address

SCB->BFAR: Bus Fault Address register

 

Вот оттуда пример обработчика

 

// hard fault handler wrapper in assembly
// it extract the location of stack frame and pass it
// to handler in C as pointer.
__asm void hard_fault_handler_asm(void)
{
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B __cpp(hard_fault_handler_c )
}
The second part of the handler is in C. Here, we demonstrate how the stacked register contents and the Fault Status registers can be accessed.
// hard fault handler in C,
// with stack frame location as input parameter
void hard_fault_handler_c(unsigned int * hardfault_args)
{
unsigned int stacked_r0;
unsigned int stacked_r1;
unsigned int stacked_r2;
unsigned int stacked_r3;
unsigned int stacked_r12;
unsigned int stacked_lr;
unsigned int stacked_pc;
unsigned int stacked_psr;
stacked_r0 = ((unsigned long) hardfault_args[0]);
stacked_r1 = ((unsigned long) hardfault_args[1]);
stacked_r2 = ((unsigned long) hardfault_args[2]);
stacked_r3 = ((unsigned long) hardfault_args[3]);
stacked_r12 = ((unsigned long) hardfault_args[4]);
stacked_lr = ((unsigned long) hardfault_args[5]);
stacked_pc = ((unsigned long) hardfault_args[6]);
stacked_psr = ((unsigned long) hardfault_args[7]);
printf ("[Hard fault handler]\n");
printf ("R0 = %x\n", stacked_r0);
printf ("R1 = %x\n", stacked_r1);
printf ("R2 = %x\n", stacked_r2);
printf ("R3 = %x\n", stacked_r3);
printf ("R12 = %x\n", stacked_r12);
printf ("LR = %x\n", stacked_lr);
printf ("PC = %x\n", stacked_pc);Cortex-M3 Troubleshooting Guide 425
printf ("PSR = %x\n", stacked_psr);
printf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));
printf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));
printf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));
printf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));
printf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));
exit(0); // terminate
return;
}

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


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

Есть хорошая книжка The definitive guide to the ARM Cortex-M3 / Joseph Yiu

 

SCB->CFSR: Confgurable Fault Status register

SCB->HFSR: Hard Fault Status register

SCB->DFSR: Debug Fault Status register

SCB->AFSR: Auxiliary Fault Status register

SCB->MMAR: MemManage Fault Address

SCB->BFAR: Bus Fault Address register

Ещё в двух регистрах BFAR и MMFAR находится одинаковый адрес: 0xE000EDF8. Вроде относится к области внутренней периферии кортекса, но идентифицировать адрес не смог.

Похоже ещё есть вероятность, что просто процессор дохлый, или спалили статикой при пайке модуля. У него ноги выведены прямо с платы на разъём.

Это если с адресом вектора всё нормально...

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


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

Похоже ещё есть вероятность, что просто процессор дохлый, или спалили статикой при пайке модуля. У него ноги выведены прямо с платы на разъём.

дохлый процессор или не будет стартовать вообще (нечему стартовать) или будет получать неправильную информацию с внешних выводов, что при корректно написанной программе не должно приводить к сбоям и HardFault (может зависнуть на ожидании готовности, получить некорректную посылку из одних "0" или "1" и т.п., но не вылетать по недопустимому коду команды или передаче управления на несуществующий адрес). Битый статикой драйвер ввода/вывода на ядро влиять не должен.

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


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

дохлый процессор или не будет стартовать вообще (нечему стартовать) или будет получать неправильную информацию с внешних выводов, что при корректно написанной программе не должно приводить к сбоям и HardFault (может зависнуть на ожидании готовности, получить некорректную посылку из одних "0" или "1" и т.п., но не вылетать по недопустимому коду команды или передаче управления на несуществующий адрес). Битый статикой драйвер ввода/вывода на ядро влиять не должен.

Да это я уже так, версии кидаю.

Похоже дело всё же где то в коде. Выбросил из проекта все файлы, кроме того, где main(), и процессор задышал, стал в отладчике адекватно шагать по командам.

Сейчас по очереди подключаю файлы с различным функционалом и пока всё работает.

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

 

 

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


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

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

Адрес чётный, а младший бит в PC == 1 - признак набора команд Tumb2, поскольку кортекс-М другую не умеет. И выравнивание обязательно, только это компилятор с линкером автоматически организуют.

Выбросил из проекта все файлы, кроме того, где main()

Получается, что первая команда из main() не виновата (:

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


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

Получается, что первая команда из main() не виновата (:

Нашел причину, извиняюсь за беспокойство.

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

Итог - HardFault с симптомами, что описывал ранее.

 

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


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

Нашел причину, извиняюсь за беспокойство.

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

Итог - HardFault с симптомами, что описывал ранее.

Ну чё, беги за красненьким (:

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


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

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

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

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

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

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

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

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

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

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