|
Подключение libc (из состава arm-kgp-eabi) на STM32, Необходимо подключит стандартную библиотеку к проекту |
|
|
|
Feb 26 2011, 12:11
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(gba @ Feb 17 2011, 07:18)  Пытаюсь подключить стандартную библиотеку к проекту для STM32. Использую Eclipse + тулчейн от KGP.
Насколько я понимаю, линкер должен выдать мне десяток сообщений о том, что не найдены системные вызовы типа sbrk, read, write и т.д., но ничего подобного не происходит все компилится на ура. Однако при попытке вызова printf() проц вываливается в HardFault. Если я правильно понимаю это может происходить из-за проблем с адресацией(?). Т.е., например, указатель указывает на область данных? А куда printf() будет выводить? Наверное, через UART. Но стандартные библиотеки не могут знать особенностей железа в смысле как отправить символ через железо процессора. Как это у Вас решено?
|
|
|
|
|
Feb 26 2011, 13:51
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 21-01-11
Пользователь №: 62 381

|
Цитата(KnightIgor @ Feb 26 2011, 15:11)  А куда printf() будет выводить? Наверное, через UART. Но стандартные библиотеки не могут знать особенностей железа в смысле как отправить символ через железо процессора. Как это у Вас решено? А вот для этого как раз и необходима своя реализация системных вызовов (system calls) - sbrk(), write(), read() и т.д. Вообще говоря необходима реализация минимального набора системных вызовов, половина из которых может быть просто заглушками. Если же даже заглушек не будет, то при линковке линкер выдаст ошибки. В системный вызов write() можно запихнуть вызов функции, которая выводит символ через UART, а реализацию этой функции можно разместить в модуле программы, где происходит работа с железом. Пример описанного выше давал AHTOXA здесь
|
|
|
|
|
Feb 26 2011, 15:06
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(gba @ Feb 26 2011, 14:51)  А вот для этого как раз и необходима своя реализация системных вызовов (system calls) - sbrk(), write(), read() и т.д. Вообще говоря необходима реализация минимального набора системных вызовов, половина из которых может быть просто заглушками. Если же даже заглушек не будет, то при линковке линкер выдаст ошибки. В системный вызов write() можно запихнуть вызов функции, которая выводит символ через UART, а реализацию этой функции можно разместить в модуле программы, где происходит работа с железом. Пример описанного выше давал AHTOXA здесьЭто все правильно. И Вы сделали соответствующую реализацию? Может быть в ней причина вылета в Hardware Fault?
|
|
|
|
|
Feb 26 2011, 19:47
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 21-01-11
Пользователь №: 62 381

|
Цитата(KnightIgor @ Feb 26 2011, 18:06)  Это все правильно. И Вы сделали соответствующую реализацию? Может быть в ней причина вылета в Hardware Fault? Реализацию взял из работающего проекта, который выложил АНТОХА. При вызове printf() в моем проекте, проц сразу же вываливается в HardFault, в sbrk() вообще не заходит - пробовал и через дебаггер смотреть и светодиодом моргать без дебаггера. Сейчас пытаюсь вкурить как размотать стек, чтобы точно определить какая команда провоцирует HardFault. Пользуюсь методом, предложенным здесь. Но получаю какую-то ерунду: Код stacked_r0 0x2000085c stacked_r1 0x2000085c stacked_r2 0x20000864 stacked_r3 0x20000864 stacked_r12 0x2000086c stacked_lr 0x2000086c stacked_pc 0x20000874 stacked_psr 0x20000874 Обработчик HardFault'а (взят по ссылке выше): Код void HardFault_Handler(){ // start of user stack extern unsigned int _susrstack;
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; u32* hardfault_args = (u32*) _susrstack;
__asm( "TST LR, #4 \n" "ITE EQ \n" "MRSEQ R0, MSP \n" "MRSNE R0, PSP \n");
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]);
while(1){} } Из моих изменений здесь только указатель на стек. Может в этом и косяк?
|
|
|
|
|
Feb 26 2011, 21:26
|

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

|
Вот за это я и не люблю отладчики. Они зачастую сбивают с мысли. При возникновении проблемы, человек с отладчиком, вместо того, чтобы сесть и подумать, в чём может быть проблема, сразу же лезет отлаживаться. У вас есть работающий пример, сравните со своим, найдите отличия. Или возьмите его за основу и добавляйте что надо понемножку. Отладочная выдача там уже работает. А вы уже столько времени воюете с отладчиком. Ну да ладно, это я так, поворчал просто  Насчёт HardFault. Вот тут я постил рабочий пример, может поможет.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 28 2011, 07:08
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 21-01-11
Пользователь №: 62 381

|
Можно не любить калькулятор, но он тем не менее ускоряет работу  Честно говоря, я первый раз сталкиваюсь с таким глюкаловом при отладке. Хотя может это специфика отладки железок? Спасибо за работающий обработчик HardFault. К сожалению он ясности не добавил, вот что в регистрах: Код r0 = 0x08018238 r1 = 0x000000FF r2 = 0x00000001 r3 = 0x200008F0 r12 = 0xFFEFFBFF lr = 0x08000829 pc = 0x0800128C psr = 0x21000000 По адресу 0x0800128C вызов printf(): Код 287 printf("New DBGU enabled %d!\n", 0xff); 08001280: movw r0, #33336; 0x8238 08001284: movt r0, #2049 ; 0x801 08001288: mov.w r1, #255 ; 0xff 0800128c: blx 0x800e050 <printf> Соответственно по адресу 0x0800e050 printf() и лежит: Код printf: 0800e050: push {r0, r1, r2, r3} 0800e054: push {lr} ; (str lr, [sp, #-4]!) 0800e058: ldr r3, [pc, #44] ; 0x800e08c <printf+60> 0800e05c: sub sp, sp, #12 0800e060: ldr r0, [r3] 0800e064: add r12, sp, #20 0800e068: ldr r1, [r0, #8] 0800e06c: ldr r2, [sp, #16] 0800e070: mov r3, r12 0800e074: str r12, [sp, #4] 0800e078: bl 0x800e1a4 <_vfprintf_r> ... ... ... Принципиальных отличий с Вашим примером не смог пока найти... пробовал даже подсовывать в свой проект Ваши sysinit.c и syscalls.c толку ноль. Скрипт линкера тоже такой же. Единственное, что может еще отличаться это Standard Peripheral Library - я качал где-то месяц назад с сайта ST.
|
|
|
|
|
Feb 28 2011, 09:46
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 21-01-11
Пользователь №: 62 381

|
Цитата(AHTOXA @ Feb 28 2011, 12:08)  Меня смутило blx. Насколько я понимаю, это вызов с переключением режима. Причём, поскольку операнд имеет сброшенный нулевой бит, то переключение в ARM-моде, которого в кортексах нет. Вот и HardFault... Вы случаем не потеряли ключик -mthumb или что-то типа того? Это фейл... Я думал архитектуру только компилятору надо указывать, а оказывается еще и линкеру. Спасибо в очередной раз! PS Всегда всем говорил, что программить надо начинать с ассемблера, а сам до армового ассемблера так и не добрался
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|