Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: arm-eabi-gcc
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
Drozd2
Здравствуйте!
Загвоздка с самосборным компилятором arm-eabi-gcc. Собирал этим скриптом. Простейшая скомпилированная программа работает корректно. После добавления ряда математических вычислений и соответствующих sprintf программа начала зависать, причем в разных местах, в зависимости от того, какую строку закомментировать. Иногда вываливается в data и prefetch abort. В итоге дошло до того, что если удачно раскидать по тексту программы разный хлам типа uart_write("###########") и while(1>5), то можно добиться, чтобы она отрабатывала успешно. Причем если скомпилировать ту же программу в IAR, то работает корректно без дополнительных вставок. Но IAR ломаный, для этого проекта не годится. В чем может быть причина? В скрипте или в исходниках?

P.S. build.sh загрузить не дали, даже после убирания расширения. Пришлось сделать rar.
AHTOXA
Похоже на то, что у вас стек не выровнен на 8 байт.
Drozd2
Прикрепил Startup. Стек определяю в нем. Если не ошибаюсь, стек выровнен. Возможно чего-то не догоняю.
SyncLair
не доверяю я этому sprintf (
AHTOXA
Цитата(Drozd2 @ Mar 14 2013, 16:43) *
Если не ошибаюсь, стек выровнен.

Да, значит дело не в этом. Ещё вариант - не хватает кучи (она в последнее время требуется для printf).
Если всё же грешите на компилятор, попробуйте собрать каким-нибудь проверенным.
Drozd2
Готовый компилятор от Codesourcery работает только с порядком liitle-endian. Отпадает. Нужен big-endian.
Перепробовал довольно много сочетаний разных версий пакетов для сборки. Скомпилированные бинарники работают по разному, но правильно не заработал ни один. На всякий случай прикрепляю скрипт линкера. Может в нем погрешность?
И насчет кучи. Задавался таким вопросом, бродил по форуму, по интернету, пробовал объявлять секцию, но куча так и осталась незадействованной. Malloc нормально работает без кучи, а больше ничего и не надо было. Если есть, дайте, пожалуйста, ссылки на толковые источники информации по кучам.
AHTOXA
Цитата(Drozd2 @ Mar 21 2013, 15:38) *
На всякий случай прикрепляю скрипт линкера. Может в нем погрешность?

Какая-то странная секция - "CONSTRUCTORS". Современные компиляторы помещают конструкторы в секцию ".init_array". Хотя у вас всё равно конструкторы не вызываются из стартапа.
Посмотрите ещё вот этот скрипт для примера, может быть что-то там найдёте полезного.
Цитата(Drozd2 @ Mar 21 2013, 15:38) *
Malloc нормально работает без кучи, а больше ничего и не надо было.

Так не бывает. Malloc как раз выдаёт память из кучи. Куча обычно начинается с позиции _end, определённой в скрипте линкера.
Чтобы контролировать это, попробуйте собрать свой проект с ключом линкера -nostartfiles. Линкер должен будет заругаться на неопределённые имена типа _sbrk() и проч. Тут вы ему подсунете свои заглушки для системных функций, примерно как здесь.
Drozd2
Я имел в виду не нужно специально объявлять кучу. Написал по идиотски.
-nostartfiles и так указано. Вот после -nostdlib начинает ругаться именно так. Только счастья не прибавляется. Заглушки, в том числе отдельный printf.c, помогают избежать зависаний, но на вопрос не отвечают. Хочется в полной мере использовать newlib.
Добавил в начало программы такие строки:
Цитата
extern int end;

sprintf(str, "end=%X\r\n", &end);
INFO(str);

res_sbrk=sbrk(0);
sprintf(str, "res_sbrk=%p\r\n", res_sbrk);
INFO(str);

res_sbrk=sbrk(10*1024);
sprintf(str, "res_sbrk=%p\r\n", res_sbrk);
INFO(str);

res_sbrk=sbrk(10*1024);
sprintf(str, "res_sbrk=%p\r\n", res_sbrk);
INFO(str);

и получил такой результат:
Цитата
end=41FD8
res_sbrk=0x41fd8
res_sbrk=0x41fd8
res_sbrk=0x447d8

Но непонятно, как "подключить" результат sbrk к sprintf в плане использования им этой кучи. Вообще sbrk выполняет очень сложную задачу по складыванию двух чисел и возврату результата из внутренней переменной. Я так понял, что для задания кучи, которую будет использовать newlib, нужно вызывать другую функцию, которая уже сама вызовет sbrk. Только не нашел какую.
AHTOXA
Цитата(Drozd2 @ Mar 27 2013, 11:31) *
Хочется в полной мере использовать newlib.

Так заглушки как раз и позволяют использовать newlib. Они реализуют, скажем так, платформенно-зависимые вещи. _sbrk() - выделение кусочка памяти для malloc(), _write() - вывод символов на устройство вывода для printf().
Просто у вас откуда-то подцепляются умолчательные реализации этих заглушек.
Если ключ -nostdlib отключает эти умолчательные реализации - то именно он и нужен. Он не отключит возможность использовать newlib.
Цитата(Drozd2 @ Mar 27 2013, 11:31) *
Я так понял, что для задания кучи, которую будет использовать newlib, нужно вызывать другую функцию, которая уже сама вызовет sbrk. Только не нашел какую.

Не нужно ничего больше вызывать. malloc() вызывает _sbrk(). Вы пишете свою реализацию _sbrk(), и всё начинает работать.
alx2
Цитата(Drozd2 @ Mar 27 2013, 10:31) *
Но непонятно, как "подключить" результат sbrk к sprintf в плане использования им этой кучи.

Ничего не надо подключать. Все уже подключено до нас. Где-то в процессе выполнения sprintf() будут вызваны malloc()/free(), которые и работают с кучей. От Вас лишь требуется предоставить sbrk().

Цитата(Drozd2 @ Mar 27 2013, 10:31) *
Я так понял, что для задания кучи, которую будет использовать newlib, нужно вызывать другую функцию, которая уже сама вызовет sbrk. Только не нашел какую.

Нет никакой функции, которую надо вызвать "для задания кучи". Все, что от Вас требуется - это предоставить функцию sbrk(). Когда newlib'у нужен кусок памяти из кучи, он вызывает вашу sbrk(), передавая ей требуемый размер. Если у Вас в куче есть кусок такого размера, sbrk возвращает адрес этого куска. Таким образом, использоваться будет та область памяти, на которую укажет ваша sbrk().
Drozd2
Контора больше ждать не захотела и купила IAR EWARM. Землю носом рыть теперь не надо, но интерес остался. На досуге буду дальше копать. Спасибо всем откликнувшимся.
Drozd2
Тема давняя, но точку поставлю. Пришлось разобраться после очередной смены местожительства и, соответственно, вывески. Скрипты для сборки компилятора вполне рабочие. Подсовываем новые пакеты и получаем новые версии. Не давал спокойно работать скрипт линкера. Для запуска программы из ОЗУ оказалось вполне достаточно такого скрипта:
Код
OUTPUT_ARCH(arm)
ENTRY(_startup)
SECTIONS
{
    . = 0x40000000;
    . = ALIGN(4);
    .text : { *(.text) }
    PROVIDE(_etext = .);
    .data : { *(.data) }
    PROVIDE(_bss_start = .);
    .bss  : { *(.bss) }
    PROVIDE(_bss_end = .);

    . = . + 4096;            /* define heap size */
    PROVIDE(end = .);        /* allocate heap */
}
PROVIDE(_top_stack = 0x44000000);

Куча размером 4096 байт появляется после строчки . = . + 4096;. Можно явно указать секцию .heap, задать ее размер, назвать как угодно, главное в конце указакть PROVIDE(end = .);. Этим и определяется размер кучи. Куча появляется в просвете между адекватными секциями и end. Секцию data в этом случае копировать не нужно.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.