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

stm32 gcc lib printf улетает в HardFault_Handler

Здравствуйте.

 

Суть проблемы...

 

Пытаюсь вызвать стандартный 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;

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!

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


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

Вероятно проблемы с не выровнянным доступом. В f0 серии этого нельзя делать. Падает на инструкции загрузки полуслова. Если пытаетесь взять полуслово с не четного адреса, то это и есть ваша проблема)

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


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

Большое спасибо что откликнулись)

 

Вероятно проблемы с не выровнянным доступом. В 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]

 

Спасибо.

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


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

Стек должен быть выровнен на 8 байт. Проверьте это.

 

Я только инициализирую указатель стека (0x20001FFF). Как еще можно его выровнять ?

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


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

Я только инициализирую указатель стека (0x20001FFF).
Как давно 0x20001FFF стало кратным 8? Вам надо инициализировать числом 0x20002000

 

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


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

Как давно 0x20001FFF стало кратным 8? Вам надо инициализировать числом 0x20002000

 

Сделал. Не помогло.

 

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

В чем еще может быть дело ?

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


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

Осей никаких не используете?

Ну и покажите, наконец, код.

 

Оси нет. Вот исходники ....f051r8_test_printf.rar

 

Уже все перепробовал :(

 

Сейчас поставил затычку -lnosys для отладки. Если уходит в HardFault_Handler то зажигает светодиод.

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


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

Оси нет. Вот исходники ....f051r8_test_printf.rar

 

Уже все перепробовал :(

 

Сейчас поставил затычку -lnosys для отладки. Если уходит в HardFault_Handler то зажигает светодиод.

 

Что подскажите ?

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


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

Да непонятно.

Куда у вас должен выводить текст 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 - довольно жирное решение.

 

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


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

Да непонятно.

Куда у вас должен выводить текст 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.

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


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

Проблема решена :)

А дело вот в чем было...

В скрипт линкера нужно было добавить секцию:

    .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;

 

Теперь камушек не падает :)

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

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


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

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

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

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

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

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

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

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

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

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