KnightIgor 2 26 февраля, 2011 Опубликовано 26 февраля, 2011 · Жалоба Пытаюсь подключить стандартную библиотеку к проекту для STM32. Использую Eclipse + тулчейн от KGP. Насколько я понимаю, линкер должен выдать мне десяток сообщений о том, что не найдены системные вызовы типа sbrk, read, write и т.д., но ничего подобного не происходит все компилится на ура. Однако при попытке вызова printf() проц вываливается в HardFault. Если я правильно понимаю это может происходить из-за проблем с адресацией(?). Т.е., например, указатель указывает на область данных? А куда printf() будет выводить? Наверное, через UART. Но стандартные библиотеки не могут знать особенностей железа в смысле как отправить символ через железо процессора. Как это у Вас решено? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gba 0 26 февраля, 2011 Опубликовано 26 февраля, 2011 · Жалоба А куда printf() будет выводить? Наверное, через UART. Но стандартные библиотеки не могут знать особенностей железа в смысле как отправить символ через железо процессора. Как это у Вас решено? А вот для этого как раз и необходима своя реализация системных вызовов (system calls) - sbrk(), write(), read() и т.д. Вообще говоря необходима реализация минимального набора системных вызовов, половина из которых может быть просто заглушками. Если же даже заглушек не будет, то при линковке линкер выдаст ошибки. В системный вызов write() можно запихнуть вызов функции, которая выводит символ через UART, а реализацию этой функции можно разместить в модуле программы, где происходит работа с железом. Пример описанного выше давал AHTOXA здесь Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 26 февраля, 2011 Опубликовано 26 февраля, 2011 · Жалоба А вот для этого как раз и необходима своя реализация системных вызовов (system calls) - sbrk(), write(), read() и т.д. Вообще говоря необходима реализация минимального набора системных вызовов, половина из которых может быть просто заглушками. Если же даже заглушек не будет, то при линковке линкер выдаст ошибки. В системный вызов write() можно запихнуть вызов функции, которая выводит символ через UART, а реализацию этой функции можно разместить в модуле программы, где происходит работа с железом. Пример описанного выше давал AHTOXA здесь Это все правильно. И Вы сделали соответствующую реализацию? Может быть в ней причина вылета в Hardware Fault? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gba 0 26 февраля, 2011 Опубликовано 26 февраля, 2011 · Жалоба Это все правильно. И Вы сделали соответствующую реализацию? Может быть в ней причина вылета в 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){} } Из моих изменений здесь только указатель на стек. Может в этом и косяк? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 26 февраля, 2011 Опубликовано 26 февраля, 2011 · Жалоба Вот за это я и не люблю отладчики. Они зачастую сбивают с мысли. При возникновении проблемы, человек с отладчиком, вместо того, чтобы сесть и подумать, в чём может быть проблема, сразу же лезет отлаживаться. У вас есть работающий пример, сравните со своим, найдите отличия. Или возьмите его за основу и добавляйте что надо понемножку. Отладочная выдача там уже работает. А вы уже столько времени воюете с отладчиком. Ну да ладно, это я так, поворчал просто:) Насчёт HardFault. Вот тут я постил рабочий пример, может поможет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gba 0 28 февраля, 2011 Опубликовано 28 февраля, 2011 · Жалоба Можно не любить калькулятор, но он тем не менее ускоряет работу :) Честно говоря, я первый раз сталкиваюсь с таким глюкаловом при отладке. Хотя может это специфика отладки железок? Спасибо за работающий обработчик 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 28 февраля, 2011 Опубликовано 28 февраля, 2011 · Жалоба Можно не любить калькулятор, но он тем не менее ускоряет работу :) Посчитать 2+2 быстрее в уме:) 0800128c: blx 0x800e050 <printf> Меня смутило blx. Насколько я понимаю, это вызов с переключением режима. Причём, поскольку операнд имеет сброшенный нулевой бит, то переключение в ARM-моде, которого в кортексах нет. Вот и HardFault... Вы случаем не потеряли ключик -mthumb или что-то типа того? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gba 0 28 февраля, 2011 Опубликовано 28 февраля, 2011 · Жалоба Меня смутило blx. Насколько я понимаю, это вызов с переключением режима. Причём, поскольку операнд имеет сброшенный нулевой бит, то переключение в ARM-моде, которого в кортексах нет. Вот и HardFault... Вы случаем не потеряли ключик -mthumb или что-то типа того? Это фейл... Я думал архитектуру только компилятору надо указывать, а оказывается еще и линкеру. Спасибо в очередной раз! PS Всегда всем говорил, что программить надо начинать с ассемблера, а сам до армового ассемблера так и не добрался Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 28 февраля, 2011 Опубликовано 28 февраля, 2011 · Жалоба Да ерунда всё это. Нормальный процесс начального вхождения. Дальше всё легче пойдёт. ЗЫ. Ассемблер для АРМ я тоже не знаю, так, читаю со словарём :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться