Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: YAGARTO и math
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
Атмег
Здравствуйте, уважаемые, помогите советом!

Начинаю работать с ARM, установил YAGARTO.
Как только пытаюсь использовать функции типа sin, cos - линкер выдает undefined reference to `sin'
в math.h они объявлены external:

extern double cos _PARAMS((double));
extern double sin _PARAMS((double));

То есть в стандартной библиотеке не реализованы матфункции? Что я не понимаю?
klen
Цитата(Атмег @ Jul 24 2009, 21:41) *
Здравствуйте, уважаемые, помогите советом!

Начинаю работать с ARM, установил YAGARTO.
Как только пытаюсь использовать функции типа sin, cos - линкер выдает undefined reference to `sin'
в math.h они объявлены external:

extern double cos _PARAMS((double));
extern double sin _PARAMS((double));

То есть в стандартной библиотеке не реализованы матфункции? Что я не понимаю?


добавте при линковке ключик -lm
AHTOXA
Надо указать линкеру, чтоб линковал математическую библиотеку. Ключ -lm.
Genadi Zawidowski
Гарантировать правильную работу floating point должен адеквтный стартап, но для того, чтобы перестал ругаться линкер отредактируйте в мэйкфайле строчку

MCFLAGS = -mcpu=$(MCU) -lm

Это заставит компилятор добавить к списку библиотечных файлов еще
arm-elf\lib\libm.a


ps: ой, уже натовечали... А вопрошавший может сказать про то, заработало ли без поддержки стартапа?
Как я понял, при компиляции для freestanding environment приходится свой собственный стартап подсовывать (я, во всяком случае, поступил именно так).

pps: успел сам проверить... коллосаль! у меня с моим стартапом заработало! Во всяком случае, функция sin (не в прерывании) работает... Правда, добавило 10 килобайт.
klen
стартап то тут причем?
Genadi Zawidowski
Скорее всего стартап в данном случае непричем... Просто во всех остальных компиляторах, что я встречал (и использовал для embedded) стартап участвовал в настройках FP калькулятора и/или режимов сопроцессора где он был (в x86).
С тем как это в gcc для arm устроено я еще не успел разобраться.
_Pasha
Цитата(Genadi Zawidowski @ Jul 25 2009, 04:21) *
Скорее всего стартап в данном случае непричем... 

Если для плавучки использовать коды операции из множества undefined instruction, то в стартапе надо прописАть адрес обработчика соотв. исключения. А более стартап никаким макаком... 
SergeiCh
Цитата(klen @ Jul 25 2009, 01:22) *
добавте при линковке ключик -lm
Причем ключик должен быть обязательно после, а не до объектных файлов, в которых используются библиотечные функции.
Атмег
Огромное спасибо!
С ключом -lm все линкуется как надо.
И, действительно, только когда ключ стоит после объектных файлов. (Если не сложно, объясните, почему так? Ведь если поменять порядок объектных файлов при линковке ничего не меняется?..)

Остался, правда, еще один непонятный момент еще на этапе компиляции:
main.c: In function 'main':
main.c:550: warning: implicit declaration of function 'sin'
main.c:550: warning: incompatible implicit declaration of built-in function 'sin'

такая реакция на вызов функции, хотя я ее не определяю, просто вызываю, x=sin(y);
MrYuran
Цитата(Атмег @ Jul 27 2009, 11:23) *
такая реакция на вызов функции, хотя я ее не определяю, просто вызываю, x=sin(y);

а math.h сверху подключен?
etoja
Используйте Rowley Crosstudio. Это оболочка + gcc.
Оболочка формирует нужные ключи.

30-дневная версия здесь: http://www.rowley.co.uk/arm/
Ну и местные закрома, ясное дело.
Атмег
да, туплю, закомментирован был)
Сергей Борщ
Цитата(Атмег @ Jul 27 2009, 10:23) *
И, действительно, только когда ключ стоит после объектных файлов. (Если не сложно, объясните, почему так? Ведь если поменять порядок объектных файлов при линковке ничего не меняется?..)
потому что библиотека - это не объектный файл, а архив объектных файлов. И именно такой порядок описан в документации:
Цитата
-lnamespec
--library=namespec
...
The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.
...
Атмег
Понятно, спасибо
Атмег
Появился еще ряд вопросов)

Увеличиваю частоту на выходе фапч с 200 до 240 МГц. Ожидаю, что время выполнения моего кода должно пропорционально сократиться. Однако сокращается оно не на 20, а на доли процента... Рассчитывается преобразование фурье, работа алгоритма с периферией никак не связана.

На данный момент у меня на 200Мгц на вычисление sin тратится в среднем 50 мкс, то есть 10000 циклов... Не много ли это? От чего зависит скорость работы с fp помимо оптимизации самого кода, что бы почитать на эту тему? В документации на Newlib (http://sources.redhat.com/newlib/) ничего интересного не нашел =/

Главное, чтоб знать в каком направлении двигаться: может быть Newlib не самая лучшая библиотека для работы с fp или переход на другую ничего не даст?
aaarrr
Цитата(Атмег @ Jul 27 2009, 20:07) *
Увеличиваю частоту на выходе фапч с 200 до 240 МГц. Ожидаю, что время выполнения моего кода должно пропорционально сократиться. Однако сокращается оно не на 20, а на доли процента... Рассчитывается преобразование фурье, работа алгоритма с периферией никак не связана.

А измеритель времени не от тех же клоков запитан случайно?

Цитата(Атмег @ Jul 27 2009, 20:07) *
На данный момент у меня на 200Мгц на вычисление sin тратится в среднем 50 мкс, то есть 10000 циклов... Не много ли это? От чего зависит скорость работы с fp помимо оптимизации самого кода, что бы почитать на эту тему? В документации на Newlib (http://sources.redhat.com/newlib/) ничего интересного не нашел =/

Это похоже на нормальное значение, хотя библиотеки RVCT работают примерно вдвое быстрее. Просто sin/cos по определению тормозные и мало подходят для работы в реальном времени.
AndrewN
Цитата(aaarrr @ Jul 27 2009, 20:16) *
Это похоже на нормальное значение, хотя библиотеки RVCT работают примерно вдвое быстрее.

А я, кажется, догадываюсь почему: в newlib-е libm раздваивается
(в math и mathfp) и вызов sin() считает синус два раза, очевидно для
проверки, что бы не ошибиться :)

10,000 клоков не предел, в DM6446 sin() (из DDR2, cache off,
release, no dbg info) считает здак 45,000 клоков и ничего,
только чип горячий и дым из эмулятора...
Атмег
Цитата(aaarrr @ Jul 27 2009, 20:16) *
А измеритель времени не от тех же клоков запитан случайно?

нет, от RTC

Цитата(aaarrr @ Jul 27 2009, 20:16) *
Это похоже на нормальное значение, хотя библиотеки RVCT работают примерно вдвое быстрее. Просто sin/cos по определению тормозные и мало подходят для работы в реальном времени.

А есть ли способ ускорить работу, пожертвовав точностью? (Есть еще мысль таблицей задать, но уж больно некрасивое решение).

Цитата(AndrewN @ Jul 28 2009, 03:28) *
в newlib-е libm раздваивается (в math и mathfp) и вызов sin() считает синус два раза

ээ.. то есть??
aaarrr
Цитата(Атмег @ Jul 28 2009, 10:30) *
А есть ли способ ускорить работу, пожертвовав точностью? (Есть еще мысль таблицей задать, но уж больно некрасивое решение).

Есть, и использование таблицы - один из наиболее распространенных. Что же в ней некрасивого?
AndrewN
Цитата(Атмег @ Jul 28 2009, 10:30) *
А есть ли способ ускорить работу, пожертвовав точностью? (Есть еще мысль таблицей задать, но уж больно некрасивое решение).

Можно, например, ограничится одним битом и считать что синус на [0, pi) равен 1, а на [pi,2*pi) равен 0. Но это путь скорби. Обычно, всё-же, сначала задаются необходимым значением точности, а потом ищут вычислитель, который зту точность обеспечит вместе с заданным временем вычисления - т.е. жертвуют деньгами вместо точности.

Табличный синус это, конечно, хорошо, но останутся скалярные произведения в вычислении преобразования, и они тоже будут симулироваться вызовами подпрограмм.

Мой вчерашний эксперимент с DM6446 показал удивительные результаты: огромное количество тактов тратится на всевозможные варианты переходов и на обращение к ОЗУ, тогда как обычные арифметические инструкции завершаются за 3-5 тактов.

Что, конечно, неудивительно само по себе, но что бы так много - 95 на переход, от 125 до 250 на LDM-ы в эпилогах (STM-ы в прологах укладываются за около 20 тактов). Понятно, что тайминг операций с памятью прямо пропорционален отношению частоты ЦПУ и частоты памяти и если включить кэш (я пока не научился работать с CP15) то времена должны улучшиться (в том числе и скорость переходов, так как она косвенно зависит от скорости обмена с памятью), но пока не знаю на сколько.

Вот эти операции и определяют, в итоге, скорость (точнее, медленность) симуляции плавающей точки, где на каждый чих (e.g. целое -> вещественное) свой вызов подпрограммы, т.е. переход, пролог и эпилог. Суммируя, ARM без аппаратной плавающей точки для вычисленений с этой самой точкой можно использовать только от отчаяния. Более подходящее применение - целочисленное преобразование.

Цитата(Атмег @ Jul 28 2009, 10:30) *
ээ.. то есть??

Как-так само-собой получилось, ни причины, ни логики не смог увидеть. Может быть, экпериментирование с разными способами. Только вот в math некоторые функции (kf_...) проектировал явно бухгалтер. Еще одна спорная вещь - использование полиномиальной аппроксимации для тангенса. В C&W используется дробно-рациональная аппроксимация, т.е. меньше коэффициентов (6) плюс деление, что м.б. быстрее чем Хорнер с 13-ю коэффициентами, - как сделано в mathfp.
Атмег
Спасибо, информацию принял к сведению. У меня правда уже есть сомнения относительно моих 10000 циклов на sin, проверю. Не уверен, что частота была действительно 200 МГц, еще не научился правильно ей управлять..
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.