amiller 2 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба Пришлось срочно сделать маленькую поделку на STM32F103CBT6 (Maplemini). Готового шаблона под этот камень у меня не было, но есть несколько рабочих проектов под STM32F105. Скопировал проект, выбросил лишнее, заменил файлы конфигурации и стартап. Работаю в ИАРе, одна из последних версий. Процессор стирается, шьется. Но после выполнения первой команды улетает в HardFault. В памяти вижу, что там, где должен лежать Reset_Handler - всегда нечетный адрес. Вероятно в этом и есть причина такого поведения. Но как я этого добился, не могу понять. Попытки тасовать модули в памяти не помогают, адрес меняется, но всегда нечетный. Ничего нечётного в памяти нет, да и с чего компилятор так располагает в памяти main, совершенно не понимаю. Может кто подскажет идею? В опциях проекта вроде уже всё просмотрел... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Johnny81 0 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба Младший бит - это признак STUB, он и должен быть установлен Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 33 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба "после выполнения первой команды" чего? Стартап кода или main()? Reset_Handler это точка входа __iar_program_start, а не точка входа в main(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
amiller 2 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба Младший бит - это признак STUB, он и должен быть установлен Странно, а на других проектах (рабочих) адрес чётный. Смотрел в двух вариантах. "после выполнения первой команды" чего? Стартап кода или main()? Reset_Handler это точка входа __iar_program_start, а не точка входа в main(). Вероятно всё же стартап кода, но здесь трудно сказать. Я говорил как раз про адрес Reset_Handler, т.е. тот адрес, который находится сразу за адресом стека. Местоположение - 0x08000004. После открытия окна отладки указатель естественно находится на main(). При любой попытке шагнуть всё зависает на выполнении кода. После принудительной остановки отладчик обнаруживает себя уже по вектору HardFault. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Johnny81 0 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба Странно, а на других проектах (рабочих) адрес чётный. Смотрел в двух вариантах. а где вы адрес смотрите? Прямо в бинарнике? После принудительной остановки отладчик обнаруживает себя уже по вектору HardFault. Так если у вас есть отладчик - то чего мы гадаем? Считайте содержание регистров с данными об ошибке и разберите их - поймете, что не так Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
amiller 2 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба а где вы адрес смотрите? Прямо в бинарнике? На рабочих проектах только в *.hex, а в этом тестовом и в *.hex и в отладчике IAR и читал память через ST-LINK Utility. После адреса 0х08000000 первые 4 байта адрес стека, дальше обработчик по ресету. Порядок байт в памяти учитывал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 33 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба Странно, а на других проектах (рабочих) адрес чётный. Смотрел в двух вариантах. Вероятно всё же стартап кода, но здесь трудно сказать. Я говорил как раз про адрес Reset_Handler, т.е. тот адрес, который находится сразу за адресом стека. Местоположение - 0x08000004. После открытия окна отладки указатель естественно находится на main(). При любой попытке шагнуть всё зависает на выполнении кода. После принудительной остановки отладчик обнаруживает себя уже по вектору HardFault. Вот как раз в main() косяк, а стартап, к которому идёт обращение из 0x08000004, уже благополучно отработал. У вас же в настройках IAR-а: Debugger->Setup->RunTo main() - птичка стоит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
amiller 2 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба Так если у вас есть отладчик - то чего мы гадаем? Считайте содержание регистров с данными об ошибке и разберите их - поймете, что не так А подскажите, где смотреть? Как то до сих пор всё идеально работало. А если и были вылеты, то причины были очевидными. А подскажите, где смотреть? Как то до сих пор всё идеально работало. А если и были вылеты, то причины были очевидными. Вроде как стоят следующие флаги в SCB_CFSR Imprecise data bus error During exception stacking Буду разбираться чего это такое. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Johnny81 0 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба А подскажите, где смотреть? Как то до сих пор всё идеально работало. А если и были вылеты, то причины были очевидными. Есть хорошая книжка 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; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
amiller 2 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба Есть хорошая книжка 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. Вроде относится к области внутренней периферии кортекса, но идентифицировать адрес не смог. Похоже ещё есть вероятность, что просто процессор дохлый, или спалили статикой при пайке модуля. У него ноги выведены прямо с платы на разъём. Это если с адресом вектора всё нормально... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
novikovfb 17 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба Похоже ещё есть вероятность, что просто процессор дохлый, или спалили статикой при пайке модуля. У него ноги выведены прямо с платы на разъём. дохлый процессор или не будет стартовать вообще (нечему стартовать) или будет получать неправильную информацию с внешних выводов, что при корректно написанной программе не должно приводить к сбоям и HardFault (может зависнуть на ожидании готовности, получить некорректную посылку из одних "0" или "1" и т.п., но не вылетать по недопустимому коду команды или передаче управления на несуществующий адрес). Битый статикой драйвер ввода/вывода на ядро влиять не должен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
amiller 2 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба дохлый процессор или не будет стартовать вообще (нечему стартовать) или будет получать неправильную информацию с внешних выводов, что при корректно написанной программе не должно приводить к сбоям и HardFault (может зависнуть на ожидании готовности, получить некорректную посылку из одних "0" или "1" и т.п., но не вылетать по недопустимому коду команды или передаче управления на несуществующий адрес). Битый статикой драйвер ввода/вывода на ядро влиять не должен. Да это я уже так, версии кидаю. Похоже дело всё же где то в коде. Выбросил из проекта все файлы, кроме того, где main(), и процессор задышал, стал в отладчике адекватно шагать по командам. Сейчас по очереди подключаю файлы с различным функционалом и пока всё работает. Я сам заинтригован, как найду причину, отпишусь. Версия с нечетным адресом не прокатила. Адрес по прежнему нечетный, но код работает. Видимо здесь выравнивание не обязательно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 33 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба Адрес по прежнему нечетный, но код работает. Видимо здесь выравнивание не обязательно. Адрес чётный, а младший бит в PC == 1 - признак набора команд Tumb2, поскольку кортекс-М другую не умеет. И выравнивание обязательно, только это компилятор с линкером автоматически организуют. Выбросил из проекта все файлы, кроме того, где main() Получается, что первая команда из main() не виновата (: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
amiller 2 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба Получается, что первая команда из main() не виновата (: Нашел причину, извиняюсь за беспокойство. В спешке взял другой *.icf, перепутал буковки. А в программе выделил под одну переменную оперативной памяти больше, чем есть в наличии в этом кристалле. Итог - HardFault с симптомами, что описывал ранее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 33 10 марта, 2017 Опубликовано 10 марта, 2017 · Жалоба Нашел причину, извиняюсь за беспокойство. В спешке взял другой *.icf, перепутал буковки. А в программе выделил под одну переменную оперативной памяти больше, чем есть в наличии в этом кристалле. Итог - HardFault с симптомами, что описывал ранее. Ну чё, беги за красненьким (: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться