вторник, 16 ноября 2010 г.

Пакет средств разработки для ARM Cortex-M3


На работе решили осваивать и внедрять процессоры STM32F103x, поэтому я решил создать собственный "велосипед" - скомпилировать набор средств разработки под эту архитектуру.
Для ситуации, когда никакой операционной системы нет, а используется только "голое" железо, используется, как пишут, варианты gcc с префиксом arm-elf-* и arm-none-eabi-*. В чем разница между этими двумя вариантами, мне пока не удалось понять. Но поскольку мой проект удалось успешно скомпилировать только с помощью бесплатного CodeSorcery G++ Lite, а он использует вариант arm-none-eabi-gcc, то, видимо, и мне нужно пробовать идти этим путем.


Сборка компилятора и утилит

Для простоты я взял binutils и gcc в виде файлов src.rpm с репозитория Fedora 14. Newlib загрузил с ftp://sources.redhat.com/pub/newlib/index.html.
Порядок и параметры сборки я в основном взял отсюда:
http://www.eluaproject.net/en_tc_cortex.html,
в качестве примеров spec-файлов использовал файлы с сайтов:
http://frank.harvard.edu/~coldwell/toolchain/,
http://www.eluaproject.net/en_tc_cortex.htmlhttp://home.comcast.net/~mcatudal/,
http://mes.sourceforge.jp/mes24/linux.html,
http://www.ethernut.de/arc/,
http://michaldemin.wordpress.com/2010/02/09/arm-toolchain-newlib-part1/,
http://blog.nutaksas.com/2009/05/installing-gnuarm-arm-toolchain-on.html,
и еще кучи других мест.
Необходимо, чтобы перед сборкой в системе были установлены пакеты:
flex, flex-static, bison, mpfr, mpfr-devel, texinfo, rpm-build, gmp, gmp-devel,
libmpc, libmpc-devel. Может быть, понадобится еще что-то , но я этого не знаю, поскольку многое в системе уже было установлено по умолчанию.

1. binutils
Во всех spec-файлах я указал стандартный путь установки и цель сборки:
%define _prefix /usr/arm
%define _target arm-none-eabi
В готовом spec-файле заменил строчку конфигурирования:
../configure --target=%{_target} --prefix=%{_prefix} \
 --enable-interwork --enable-multilib \
 --with-gnu-as --with-gnu-ld \
 --with-float=soft 2>&1 | tee configure.out
"--enable-interwork" я вписал на всякий случай, для cortex-m3 этого не нужно, но вдруг придется работать с другим процессором.
"--enable-multilib" - добавил, чтобы не ошибиться, вдруг разные библиотеки потребуются.
"--with-float=soft" - вынужден был добавить, иначе получались библиотеки с поддержкой VFP-команд для операций с плавающей запятой.

2. gcc
Про компилятор везде пишут, что собирать его нужно в два этапа. Сначала собирают "начальный" вариант, чтобы можно было собрать с его помощью newlib. Для сборки начального gcc используются такие параметры:
../configure --target=%{_target} --prefix=%{_prefix} \
    --enable-languages="c,c++" \
    --with-newlib \
    --without-headers \
    --disable-nls \
    --with-gnu-as --with-gnu-ld \
    --disable-shared \
    --with-float=soft 2>&1 | tee configure.out
"--without-headers" - потому что пока еще нет библиотеки newlib,
"--disable-nls" - пока еще не нужна поддержка различных человеческих языков.
Для того, чтобы появилась поддержка cortex-m3 и soft-варианта библиотек для операций с плавающей запятой, необходимо внести изменения в файл config/gcc/arm/t-arm-elf:
--- gcc/config/arm/t-arm-elf.orig    2010-09-21 18:33:40.000000000 +0400
+++ gcc/config/arm/t-arm-elf    2011-03-05 08:21:48.000000000 +0300
@@ -36,22 +36,22 @@
 MULTILIB_EXCEPTIONS  =
 MULTILIB_MATCHES     =
 
-#MULTILIB_OPTIONS      += march=armv7
-#MULTILIB_DIRNAMES     += thumb2
-#MULTILIB_EXCEPTIONS   += march=armv7* marm/*march=armv7*
-#MULTILIB_MATCHES      += march?armv7=march?armv7-a
-#MULTILIB_MATCHES      += march?armv7=march?armv7-r
-#MULTILIB_MATCHES      += march?armv7=march?armv7-m
-#MULTILIB_MATCHES      += march?armv7=mcpu?cortex-a8
-#MULTILIB_MATCHES      += march?armv7=mcpu?cortex-r4
-#MULTILIB_MATCHES      += march?armv7=mcpu?cortex-m3
+MULTILIB_OPTIONS      += march=armv7
+MULTILIB_DIRNAMES     += thumb2
+MULTILIB_EXCEPTIONS   += march=armv7* marm/*march=armv7*
+MULTILIB_MATCHES      += march?armv7=march?armv7-a
+MULTILIB_MATCHES      += march?armv7=march?armv7-r
+MULTILIB_MATCHES      += march?armv7=march?armv7-m
+MULTILIB_MATCHES      += march?armv7=mcpu?cortex-a8
+MULTILIB_MATCHES      += march?armv7=mcpu?cortex-r4
+MULTILIB_MATCHES      += march?armv7=mcpu?cortex-m3
 
 # Not quite true.  We can support hard-vfp calling in Thumb2, but how do we
 # express that here?  Also, we really need architecture v5e or later
 # (mcrr etc).
-MULTILIB_OPTIONS       += mfloat-abi=hard
-MULTILIB_DIRNAMES      += fpu
-MULTILIB_EXCEPTIONS    += *mthumb/*mfloat-abi=hard*
+#MULTILIB_OPTIONS       += mfloat-abi=hard
+#MULTILIB_DIRNAMES      += fpu
+#MULTILIB_EXCEPTIONS    += *mthumb/*mfloat-abi=hard*
 
 # MULTILIB_OPTIONS    += mcpu=ep9312
 # MULTILIB_DIRNAMES   += ep9312
@@ -61,9 +61,9 @@
 # MULTILIB_DIRNAMES    += le be
 # MULTILIB_MATCHES     += mbig-endian=mbe mlittle-endian=mle
 #
-# MULTILIB_OPTIONS    += mhard-float/msoft-float
-# MULTILIB_DIRNAMES   += fpu soft
-# MULTILIB_EXCEPTIONS += *mthumb/*mhard-float*
+ MULTILIB_OPTIONS    += mfloat-abi=hard/mfloat-abi=soft
+ MULTILIB_DIRNAMES   += fpu soft
+ MULTILIB_EXCEPTIONS += *mthumb/*mfloat-abi=hard*
 #
 # MULTILIB_OPTIONS    += mno-thumb-interwork/mthumb-interwork
 # MULTILIB_DIRNAMES   += normal interwork

После сборки начального пакета gcc его нужно установить перед сборкой newlib.

3. Newlib
Здесь я использовал такие параметры сборки:
../configure --target=%{_target} --prefix=%{_prefix} \
    --enable-interwork --enable-multilib \
    --disable-newlib-supplied-syscalls \
    --with-float=soft 2>&1 | tee configure.out
"--disable-newlib-supplied-syscalls" - этот параметр отключает целый набор стандартных системных вызовов (обращение к файлу, выделение памяти и т.д.). Поскольку зачастую эти функции очень специфичны для конкретной реализации оборудования, то нужно использовать свои вызовы или ставить хотя бы заглушки.
Еще можно вставить параметр "--disable-libgloss", тогда не будет создаваться, например, библиотека crt0.o, на что будет ругаться компоновщик, и придется реализовать ее функции самостоятельно, а затем использовать при сборке программ параметры "-nostartfiles" или "-nodefaultlibs", "-nostdlib".
После сборки newlib ее нужно установить и переходить к этапу сборки полной версии gcc.

4. Полный gcc
Для этого я использовал такую конфигурацию сборки:
../configure --target=%{_target} --prefix=%{_prefix} \
     --enable-interwork --enable-multilib \
    --enable-languages="c,c++" --with-newlib \
    --with-headers=%{_prefix}/%{_target}/include \
    --disable-shared \
    --with-gnu-as --with-gnu-ld \
    --with-float=soft 2>&1 | tee configure.out

Здесь я указал путь к заголовкам уже установленной newlib. Но я пробовал собирать и без этого параметра, разницы не заметил.
Если установить этот пакет, то набор средств для разработки уже почти готов, осталось только собрать отладчик.

5. gdb
Тут все совсем просто:
../configure                                            \
    --target=%{target}                 \
    --prefix=%{_prefix}                             \
    --enable-interwork --enable-multilib
Возможно, два последних параметра и не нужны, но мне они и не помешали пока. Можно было бы собрать gdb-tui или insight, но поскольку используемая мною IDE (Code::Blocks) отлично работает именно с gdb, к тому же мне удалось с ним поработать и непосредственно в терминальном окошке, то я ограничился простым добрым gdb.



Немного о вариантах сборки пакетов

Почему-то gcc и newlib, собранные с префиксом arm-elf- при тех же параметрах и патче t-arm-elf в моем проекте ругались на плавающую запятую. Компоновщик говорил, что собранные библиотеки поддерживают формат VFP, а проект нет. В общем, надо разбираться.

Информацию о получившихся библиотеках или файлах можно получить с помощью команды arm-none-eabi-readelf -a имя_файла.
Еще можно воспользоваться командой: arm-none-eabi-objdump -p файл




3 комментария:

  1. Tnx! Интересно было почитать, как другие эмбеддеры решают
    те же задачи. Я под Убунтой все это дело готовил... пока в репозиториях Canonical не появился готовый arm-none-eabi.

    Не сочтите за рекламу, вот мои наработки: http://forum.e-lug.ru/viewtopic.php?id=397. Может в чем и сгодятся.

    ОтветитьУдалить
  2. Хоть и с большим опозданием, но увидел этот комментарий, на форум тоже заглянул.

    ОтветитьУдалить
  3. Вот здесь описан ещё один вариант сборки тулчейна для Cortex-m3 под Убунту. Я им пользовался.
    http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/471/t/65137.aspx

    ОтветитьУдалить