marka 0 26 ноября, 2015 Опубликовано 26 ноября, 2015 (изменено) · Жалоба Здравствуйте. Суть проблемы... Пытаюсь вызвать стандартный 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 Вот скрипт линкера (самописный): 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; Изменено 27 ноября, 2015 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
slavokhire5 0 26 ноября, 2015 Опубликовано 26 ноября, 2015 · Жалоба Вероятно проблемы с не выровнянным доступом. В f0 серии этого нельзя делать. Падает на инструкции загрузки полуслова. Если пытаетесь взять полуслово с не четного адреса, то это и есть ваша проблема) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tarbal 4 27 ноября, 2015 Опубликовано 27 ноября, 2015 · Жалоба Какое содержимое регистров r1, r10 и r2? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
marka 0 27 ноября, 2015 Опубликовано 27 ноября, 2015 · Жалоба Большое спасибо что откликнулись) Вероятно проблемы с не выровнянным доступом. В f0 серии этого нельзя делать. Падает на инструкции загрузки полуслова. Если пытаетесь взять полуслово с не четного адреса, то это и есть ваша проблема) Какое содержимое регистров 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] Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 27 ноября, 2015 Опубликовано 27 ноября, 2015 · Жалоба Стек должен быть выровнен на 8 байт. Проверьте это. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
marka 0 27 ноября, 2015 Опубликовано 27 ноября, 2015 · Жалоба Стек должен быть выровнен на 8 байт. Проверьте это. Я только инициализирую указатель стека (0x20001FFF). Как еще можно его выровнять ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 27 ноября, 2015 Опубликовано 27 ноября, 2015 · Жалоба Я только инициализирую указатель стека (0x20001FFF).Как давно 0x20001FFF стало кратным 8? Вам надо инициализировать числом 0x20002000 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
marka 0 27 ноября, 2015 Опубликовано 27 ноября, 2015 · Жалоба Как давно 0x20001FFF стало кратным 8? Вам надо инициализировать числом 0x20002000 Сделал. Не помогло. Проверил отдельно загрузку полуслова... все работает. В чем еще может быть дело ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 27 ноября, 2015 Опубликовано 27 ноября, 2015 · Жалоба Осей никаких не используете? Ну и покажите, наконец, код. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
marka 0 27 ноября, 2015 Опубликовано 27 ноября, 2015 · Жалоба Осей никаких не используете? Ну и покажите, наконец, код. Оси нет. Вот исходники ....f051r8_test_printf.rar Уже все перепробовал :( Сейчас поставил затычку -lnosys для отладки. Если уходит в HardFault_Handler то зажигает светодиод. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
marka 0 28 ноября, 2015 Опубликовано 28 ноября, 2015 · Жалоба Оси нет. Вот исходники ....f051r8_test_printf.rar Уже все перепробовал :( Сейчас поставил затычку -lnosys для отладки. Если уходит в HardFault_Handler то зажигает светодиод. Что подскажите ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 28 ноября, 2015 Опубликовано 28 ноября, 2015 · Жалоба Да непонятно. Куда у вас должен выводить текст 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 - довольно жирное решение. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
marka 0 28 ноября, 2015 Опубликовано 28 ноября, 2015 · Жалоба Да непонятно. Куда у вас должен выводить текст printf? Откуда выделяется память для кучи? Почему вы вручную указываете пути к библиотекам? Перед началом теста printf делал заглушки _write, _read и остальные (из вышей ссылки (находил раньше когда гуглил)) :) Но до них вызов даже не доходил, сразу падала уже... после вызова printf где то в глубине... Ну а потом просто решил линковать -lnosys. Да, malloc работает корректно с -lnosys Нужно было только end в скрипте линкера дописать. Выделении памяти от end после bss .heap : { . = ALIGN(4); PROVIDE(end = .); KEEP(*(.heap)) . = . + _Min_Heap_Size; . = ALIGN(4); } > RAM Что делает вот эта строчка в линкерном скрипте: . = 0xc8 - _end_isr_vector + ALIGN(2); ? Да, это я эксперименты ставил :) нужно убрать. Что-то странное вы наворотили с bss_init(), я не понял идеи. Очень вероятно, что вылетает не из printf, a отсюда: void bss_init() { void *p = 0x00; while(p++ != pEndIN) *((uint8_t *)pStartIN++) = 0x00; } Ну тот просто заполнение нулями от pStartIN до заранее подсчитанного размера секции bss. Это все работает отлично. Проблем нет. Не где не падает до применения printf. Как только вызываю printf то усе :) упала. ЗЫ. Кстати, для вашего контроллера с 64К флеша и 8К ОЗУ gcc-шный printf - довольно жирное решение. Да, возможно. Но это просто тест printf. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
marka 0 28 ноября, 2015 Опубликовано 28 ноября, 2015 (изменено) · Жалоба Проблема решена :) А дело вот в чем было... В скрипт линкера нужно было добавить секцию: .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) . = ALIGN(8); __exidx_end = .; } > FLASH Для чего она нужна... еще не знаю. Может вы знаете ? И данные для копирования (инициализация секций rodata, data, bss) нужно уже брать с адреса __exidx_end. Вот полный скрипт линкера: 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; Теперь камушек не падает :) Изменено 29 ноября, 2015 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 28 ноября, 2015 Опубликовано 28 ноября, 2015 · Жалоба .rodata класть в ОЗУ не нужно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться