|
stm32 gcc lib printf улетает в HardFault_Handler, Не получается запустить printf улетает в HardFault_Handler |
|
|
|
Nov 26 2015, 20:16
|
Группа: Участник
Сообщений: 11
Регистрация: 26-11-15
Пользователь №: 89 481

|
Здравствуйте. Суть проблемы... Пытаюсь вызвать стандартный printf из stdio и после вызова вылетает в HardFault_Handler. Запускал отладчик смотрел на каком месте падает... На строчке ldrh r2, [r1, #12]Код 862 [1] in ../../../../../../newlib/libc/stdio/vfprintf.c 0x8003934 <+0x0034> 51 46 mov r1, r10 0x8003936 <+0x0036> 8a 89 ldrh r2, [r1, #12] Есть подозрения что что-то с линковкой (адреса путаются)... или флаги линковщику особенные нужно скармливать... Да! Заранее конечно подготовил мин. набор функция для библиотеки _write, _read и другие. Линковка проходит нормально, не ругается это точно. Хочу узнать ваши предположения. Может кто сталкивался с такой проблемой... Кусок из makefile, то что касается линковщика: Код LD =arm-none-eabi-ld
LIB_B =/usr/lib/arm-none-eabi/newlib/armv6-m/ LIB_GCC =/usr/lib/gcc/arm-none-eabi/4.8.2/armv6-m/ LIB_OP =-L$(LIB_B) -lc -lg -L$(LIB_GCC) -lgcc LINKOP =-T link.ld
AFOBJ= \ startup_stm32f0xx.o \ user_io.o \ main.o \ phisic.o
$(LD) $(AFOBJ) $(LINKOP) $(LIB_OP) -o $(PBIN)$(NAMEPROJ).elf Вот скрипт линкера (самописный): CODE MEMORY { FLASH(RX) : ORIGIN = 0x08000000, LENGTH = 64K RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 8K }
_Min_Heap_Size =1; /* required amount of heap */
SECTIONS { .isr_vector : ALIGN(4) { _start_isr_vector = .; KEEP(*(.isr_vector)) _end_isr_vector = .; . = 0xc8 - _end_isr_vector + ALIGN(2); KEEP(*(.loop)) } > FLASH = 0xff
.text : ALIGN(4) { _start_text = .; *(.text) *(.text*) KEEP(*(.data_flash)) _end_text = .; } > FLASH
.rodata : ALIGN(4) { _start_rodata = .; *(.rodata) *(.rodata*) _end_rodata = .; } > RAM AT > FLASH
.data : ALIGN(4) { _start_data = .; *(.data) *(.data*) _end_data = .; } > RAM AT > FLASH
.bss : ALIGN(4) { _start_bss = .; *(.bss) *(.bss*) _end_bss = .; } > RAM
.heap : { . = ALIGN(4); PROVIDE(end = .); KEEP(*(.heap))
. = . + _Min_Heap_Size; } > RAM }
_size_rodata = SIZEOF(.rodata); _size_data = SIZEOF(.data); _size_bss = SIZEOF(.bss);
_start_rodata_copi = _end_text; _start_data_copi = _end_text + _size_rodata; _start_bss_copi = _end_text + _size_rodata + _size_data;
Сообщение отредактировал IgorKossak - Nov 27 2015, 08:42
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
Nov 26 2015, 22:43
|
Участник

Группа: Участник
Сообщений: 50
Регистрация: 31-03-14
Из: Харьков
Пользователь №: 81 165

|
Вероятно проблемы с не выровнянным доступом. В f0 серии этого нельзя делать. Падает на инструкции загрузки полуслова. Если пытаетесь взять полуслово с не четного адреса, то это и есть ваша проблема)
|
|
|
|
|
Nov 27 2015, 08:20
|
Группа: Участник
Сообщений: 11
Регистрация: 26-11-15
Пользователь №: 89 481

|
Большое спасибо что откликнулись) Цитата(slavokhire5 @ Nov 27 2015, 01:43)  Вероятно проблемы с не выровнянным доступом. В f0 серии этого нельзя делать. Падает на инструкции загрузки полуслова. Если пытаетесь взять полуслово с не четного адреса, то это и есть ваша проблема) Цитата(Tarbal @ Nov 27 2015, 04:45)  Какое содержимое регистров r1, r10 и r2? Да, вы правы. младший бит установлен. Подскажите как это исправить ? Может в скрипте линкера я не правильно применяю ALIGN(4) ? Код 862 [1] in ../../../../../../newlib/libc/stdio/vfprintf.c 0x800392c <+0x0034> 51 46 mov r1, r10 // r1 = 0x80000c9 r10 = 0x80000c9 0x800392e <+0x0036> 8a 89 ldrh r2, [r1, #12] Спасибо.
|
|
|
|
|
Nov 27 2015, 10:08
|
Группа: Участник
Сообщений: 11
Регистрация: 26-11-15
Пользователь №: 89 481

|
Цитата(AHTOXA @ Nov 27 2015, 13:50)  Стек должен быть выровнен на 8 байт. Проверьте это. Я только инициализирую указатель стека (0x20001FFF). Как еще можно его выровнять ?
|
|
|
|
|
Nov 27 2015, 16:24
|
Группа: Участник
Сообщений: 11
Регистрация: 26-11-15
Пользователь №: 89 481

|
Цитата(Сергей Борщ @ Nov 27 2015, 14:13)  Как давно 0x20001FFF стало кратным 8? Вам надо инициализировать числом 0x20002000 Сделал. Не помогло. Проверил отдельно загрузку полуслова... все работает. В чем еще может быть дело ?
|
|
|
|
|
Nov 27 2015, 18:11
|
Группа: Участник
Сообщений: 11
Регистрация: 26-11-15
Пользователь №: 89 481

|
Цитата(AHTOXA @ Nov 27 2015, 20:40)  Осей никаких не используете? Ну и покажите, наконец, код. Оси нет. Вот исходники ....
f051r8_test_printf.rar ( 950.65 килобайт )
Кол-во скачиваний: 32Уже все перепробовал  Сейчас поставил затычку -lnosys для отладки. Если уходит в HardFault_Handler то зажигает светодиод.
|
|
|
|
|
Nov 28 2015, 14:15
|
Группа: Участник
Сообщений: 11
Регистрация: 26-11-15
Пользователь №: 89 481

|
Цитата(marka @ Nov 27 2015, 21:11)  Оси нет. Вот исходники ....
f051r8_test_printf.rar ( 950.65 килобайт )
Кол-во скачиваний: 32Уже все перепробовал  Сейчас поставил затычку -lnosys для отладки. Если уходит в HardFault_Handler то зажигает светодиод. Что подскажите ?
|
|
|
|
|
Nov 28 2015, 17:00
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Да непонятно. Куда у вас должен выводить текст printf? Откуда выделяется память для кучи? Почему вы вручную указываете пути к библиотекам? Что делает вот эта строчка в линкерном скрипте: Код . = 0xc8 - _end_isr_vector + ALIGN(2); ? Что-то странное вы наворотили с bss_init(), я не понял идеи. Очень вероятно, что вылетает не из printf, a отсюда: Код void bss_init() { void *p = 0x00; while(p++ != pEndIN) *((uint8_t *)pStartIN++) = 0x00; } Советую вам взять какой-нибудь готовый пример, и допилить его под свои нужды. Например, тот, что я выкладывал здесь. ЗЫ. Кстати, для вашего контроллера с 64К флеша и 8К ОЗУ gcc-шный printf - довольно жирное решение.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Nov 28 2015, 17:45
|
Группа: Участник
Сообщений: 11
Регистрация: 26-11-15
Пользователь №: 89 481

|
Цитата(AHTOXA @ Nov 28 2015, 20:00)  Да непонятно. Куда у вас должен выводить текст printf? Откуда выделяется память для кучи? Почему вы вручную указываете пути к библиотекам? Перед началом теста printf делал заглушки _write, _read и остальные (из вышей ссылки (находил раньше когда гуглил))  Но до них вызов даже не доходил, сразу падала уже... после вызова printf где то в глубине... Ну а потом просто решил линковать -lnosys. Да, malloc работает корректно с -lnosys Нужно было только end в скрипте линкера дописать. Выделении памяти от end после bssКод .heap : { . = ALIGN(4); PROVIDE(end = .); KEEP(*(.heap)) . = . + _Min_Heap_Size; . = ALIGN(4); } > RAM Цитата(AHTOXA @ Nov 28 2015, 20:00)  Что делает вот эта строчка в линкерном скрипте: Код . = 0xc8 - _end_isr_vector + ALIGN(2); ? Да, это я эксперименты ставил  нужно убрать. Цитата(AHTOXA @ Nov 28 2015, 20:00)  Что-то странное вы наворотили с bss_init(), я не понял идеи. Очень вероятно, что вылетает не из printf, a отсюда: Код void bss_init() { void *p = 0x00; while(p++ != pEndIN) *((uint8_t *)pStartIN++) = 0x00; } Ну тот просто заполнение нулями от pStartIN до заранее подсчитанного размера секции bss. Это все работает отлично. Проблем нет. Не где не падает до применения printf. Как только вызываю printf то усе  упала. Цитата(AHTOXA @ Nov 28 2015, 20:00)  ЗЫ. Кстати, для вашего контроллера с 64К флеша и 8К ОЗУ gcc-шный printf - довольно жирное решение. Да, возможно. Но это просто тест printf.
|
|
|
|
|
Nov 28 2015, 21:32
|
Группа: Участник
Сообщений: 11
Регистрация: 26-11-15
Пользователь №: 89 481

|
Проблема решена  А дело вот в чем было... В скрипт линкера нужно было добавить секцию: Код .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) . = ALIGN(8); __exidx_end = .; } > FLASH Для чего она нужна... еще не знаю. Может вы знаете ? И данные для копирования (инициализация секций rodata, data, bss) нужно уже брать с адреса __exidx_end. Вот полный скрипт линкера: CODE MEMORY { FLASH(RX) : ORIGIN = 0x08000000, LENGTH = 64K RAM(RWX) : ORIGIN = 0x20000000, LENGTH = 8K }
__ram_end = 0x20000000 + 8K;
/* .text — скомпилированный машинный код; .rodata — аналог .data для неизменяемых данных; .data — глобальные и статические переменные; .bss — глобальные и статические переменные, которые при старте содержат нулевое значение.
.comment — информация о версии компилятора; .ARM.attributes — ARM-специфичные атрибуты файла. */
_Min_Heap_Size =1; /* required amount of heap */
SECTIONS { .isr_vector : { . = ALIGN(4); _start_isr_vector = .; KEEP(*(.isr_vector)) _end_isr_vector = .; . = ALIGN(4); _start_loop = .; KEEP(*(.loop)) . = ALIGN(4); _end_loop = .; } > FLASH = 0xff
.text : { . = ALIGN(4); _start_text = .; *(.text) *(.text*) . = ALIGN(4); _start_data_flash = .; KEEP(*(.data_flash)) . = ALIGN(8); _end_data_flash = .; _end_text = .;
} > FLASH
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) . = ALIGN(8); __exidx_end = .; } > FLASH
.rodata : { . = ALIGN(4); _start_rodata = .; *(.rodata) *(.rodata*) . = ALIGN(4); _end_rodata = .; } > RAM AT > FLASH
.data : { . = ALIGN(4); _start_data = .; *(.data) *(.data*) . = ALIGN(4); _end_data = .; } > RAM AT > FLASH
.bss : { . = ALIGN(4); _start_bss = .; *(.bss) *(.bss*) . = ALIGN(4); _end_bss = .; } > RAM
.heap : { . = ALIGN(4); _start_heap = .; PROVIDE(end = .); KEEP(*(.heap)) . = . + _Min_Heap_Size; . = ALIGN(4); _end_heap = .; } > RAM }
_size_rodata = SIZEOF(.rodata); _size_data = SIZEOF(.data); _size_bss = SIZEOF(.bss);
_start_rodata_copi = __exidx_end; _start_data_copi = __exidx_end + _size_rodata; _start_bss_copi = __exidx_end + _size_rodata + _size_data; Теперь камушек не падает
Сообщение отредактировал IgorKossak - Nov 29 2015, 18:28
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|