31 июля, 2008

uClinux - установка среды программирования



Почему встраивать Linux?



Linux быстро набирает популярность как ОС для встраиваемых устройств
Вот несколько преимуществ такой ОС:
  • свободное от цены лицензирование
    Для традиционных встраиваемых платформ сумма на лицензии будет внушительная. Включенные в поставку устройств, сторонние ОС способствуют повышению цены на устройства. Linux же свободна.

  • надежный IP стэк и TCP/IP приложения
    Годами Linux может работать на серверах и рабочих станциях. Также Linux будет работать и на встаиваемых устройствах.

  • исходный код ОС открыт
    Сколько раз Вы, разрабатывая ПО, которое опирается на сторонний код, натыкались на баги? При консультации с вендором он даже не заинтересован в этом, тем более не будет отлаживать код неделями или месяцами для того, чтобы выпустить патч. С Linux Вы имеете исходный код на руках. Вы можете отладить баг и отдать код обратно сообществу. Это придаст ядру больше стабильности, и от этого выиграют все участники Linux сообщества.

  • исходные коды средств разработки открыты
    Средства разработки - это набор необходимых пакетов программ для компиляции и генерации выполняемого кода из исходных текстов программ. Они также открыты.

  • время, необходимое на рынке
    В изобилии открытого исходного кода и приложений, нацеленных на Linux, вы заметите, что "время на рынок" сократилось. Возьмем в качестве примера продукты Memory Fax/Modem, которые появились на рынке несколько лет назад. Это факс/модемы со встроенной памятью, которые позволяют получать факсимильные сообщения, когда компьютер выключен. Для размещения такого продукта на рынок будет необходимой разумный объем работы. Вместе с uClinux, разработчик может основывать свои продукты на продуктах с открытым исходным кодом, таких как efax. Она также позволяет включать IP маскарад (с небольшими усилиями), тем самым добавив больше функциональности продукту. Linux также поддерживает широкий спектр периферийных устройств и файловых систем.


Вдобавок, имеется множество целевых платформ и со временем их количество возрастает. Сейчас uClinux поддерживает серию 68328 dragonball, Coldfire, ARM7TDMI, ETRAX, I960.

Дистрибутив uClinux

uClinux - самая распространенная форма встаиваемого linux. uClinux (MicroController Linux) впервые был портирован на серию процессоров Dragonball 68k в 1998. uClinux отличается от mainstream linux тем, что не имеет поддержки MMU (noMMU). Также uClinux имеет малую базовую основу, что важно для микроконтроллеров с малыми ресурсами и BFLT (Binary Flat) Executable Format.

Linux 2.0.38


Ядро uClinux - это то место, где будет производится вся возня. Оно основано на ядре Linux 2.0.38. Оригинальное ядро Вы должны использовать на вашем настольном ПК. Патч uClinux применяется для работы с микроконтроллерами. Обычно патч включает поддержку устройств и убирает опору на MMU. Скачайте тарболы и поместите их в /opt/uClinux. Распакуйте и пропатчите ядро. Делается это так:
mkdir /opt/uClinux
cd /opt/uClinux
tar –xzf linux-2.0.38.tar.gz
gzip –d uClinux-2.0.38.1pre7.diff.gz
cd linux
patch -p1 < ../uClinux-2.0.38.1pre7.diff

Как только Вы это сделаете, то получите основу ядра uClinux. Теперь Вам нужно собрать компилятор, который сможет компилировать код в M68k. Позже, в сборке uC-libc, попробуем включить файлы из linux/include/asm. "asm" - это символическая ссылка, указывающая на папку asm-, где arch - архитектура ядра. Например, если конфигурировать uClinux для m68k с noMMU, папка asm будет указывать на asm-m68knommu. Посему, это хорошее место для начала конфигурирования ядра, которое может быть сделано без компилятора m68k-coff.

make menuconfig
По дефолту конфигурация для uCSimm, поэтому если Вы имеете другие платы необходимо их переконфигурировать ядро. Нет нужды собирать ядро, фактически Вы не можете собрать его из-за отсутствия средств разработки. make config установит ссылку на asm, которая будет необходима позже для сборки стандартной библиотеки с, uC-libc.

Средства разработки (Toolchains)

Имеется два разных набора необходимых пакетов программ для компиляции и генерации исполняемого кода (Toolchains) для uClinux. Один используется для компиляции ядра и производит 32бит M68k фиксированный двоичный объектный код. Другой используется для компиляции кода пользовательского пространства и производит 32бит M68k PIC код (position independent code).

Toolchains ядра - ничего больше как запуск фабрики gcc 2.7.2.3. diff ядра делает одну маленькую модификацию в файле /config/m68k/t-m68kbare, вставляя TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc для предотвращения нужды в libc.

Toolchains пользовательского пространства другой предмет обсуждения. Он имеет весьма обширные изменения. Эти изменения лежат в требовании иметь разрядо-независимый объектный код (PIC). Нет прямых переходов, но взамен они заменены родственными ветвями. Глобальные данные возвращаются родственно в регистр A5.

Есть два варианта для cборки tool chains. Можно скачать uClinuxgcc-kit-160899.tar.gz, который содержит все патчи и makefile для автоматической сборки binutils и gcc для среды ядра и пользвателя. Другой вариант: пропатчить и собрать средства самостоятельно и изучить, что происходит в процессе. Мы рассмотрим оба способы здесь.

Простая сборка Tool Chains

Скачиваем следующее:

Извлекаем uClinuxgcc-kit-160899.tar.gz. Можно собрать в любой директории, не зависимо от, /opt/uClinux

tar -xzf uClinuxgcc-kit-160899.tar.gz
cd uclinuxgcc-kit-160899

Правим Makefile (первая строка). Изменяем INSTALLDIR на подходящее место - лучше в /opt/uClinux. Соберем m68k-coff и m68k-pic-coff tool chains набрав make Комманда создаст исполняемые файлы в /opt/uClinux/bin. Можно добавить /opt/uClinux/bin в path, или связать новые бинарники с /usr/bin:

cd /opt/uClinux/bin
ln -f * /usr/bin

Это было не сложно. Теперь посмотрим что происходит при ручной сборке.

Ручная сборка Tool Chains - m68k-coff

Начнем со сборки инструментов m68k фиксированной разрядности, m68k-coff. Скачаиваем:

Извлекаем binutils из тарболов в подходящую директорию и входим туда:

tar -xzf binutils-2.9.1.tar.gz
cd binutil-2.9.1

Конфигурируем binutils под свою аритектуру. Начнем сначала с m68k-coff так как этот подход не требует патчей.

./configure --prefix=/opt/uClinux --target=m68k-coff

Собираем m68k-coff bin устилиты:

make
make install

make создаст директорию /opt/uClinux/m68k-coff которая будет содержать 5 поддиректорий, включая bin, include, libs, m68k-coff и man. Они будут содержать хэдеры, которые нужны для создания gcc. Вернитесь обратно в директорию с gcc-2.7.2.3.tar.gz.

Извлеките gcc тарбол, пропатчите и войдите в директорию с исходниками gcc:

tar -xzf gcc-2.7.2.3.tar.g
gzip -d gcc-2.7.2.3.kernel.diff.gz
cd gcc-2.7.2.3 patch -p1 < ../gcc-2.7.2.3.kernel.diff

Сконфигурируйте gcc для своей архитектуры. Префикс должен быть таким же как для binutils, так gcc будет искать хэдеры предварительно созданные при установке binutils.

./configure --prefix=/opt/uClinux --target=m68k-coff

Теперь скомпилирйуте C кросс компилятор для m68k-coff. LANGUAGES=c говорит make файлу собрать только С компилятор, а не C++, что может повлечет за собой некоторые излишние проблемы.

make LANGUAGES=c
make LANGUAGES=c install

Сейчас вы должны иметь компилятор m68k-pic-gcc для сборки ядра. Исполняемый файлы должны лежать в /opt/uClinux/m68k-coff/bin. Чтобы продолжить и собрать инструментальные средства pic-coff мы должны удалить рабочие директории или переименовать их. Лучше переименовать их, потому как Вы собираете исходники с нуля, не скачивая RPM, поэтому Вы можете позже исправить ошибки и применить патчи. Переименуйте binutil-2.9.1 в binutil-2.9.1.kernel и gcc-2.7.2.3 в gcc-2.7.2.3.kernel

Ручная сборка Tool Chains - m68k-pic-coff (разрядно-независимый код, Position Independent Code)


Теперь повторим те же процедуры для компилятора m68k-pic-coff. В этот раз binutils должны быть пропатчены

tar -xzf binutils-2.9.1.tar.gz
gzip -d binutils-2.9.1.pic.diff.gz
cd binutils-2.9.1
patch -p1 < ../binutils-2.9.1.pic.diff

в этот раз конфигурируем средства разработки для m68k-pic-coff

./configure --prefix=/opt/uClinux --target=m68k-pic-coff

затем делаем бинарные утилиты m68k-coff.

make
make install

Теперь мы готовы собрать gcc компилятор. Извлекаем тарболы с исходными кодами, патчим и входим в директорию с gcc

tar -xzf gcc-2.7.2.3.tar.gz
gzip -d gcc-2.7.2.3.pic.diff.gz
cd gcc-2.7.2.3 patch -p1 < ../gcc-2.7.2.3.pic.diff

Конфигурируем gcc для своей архитектуры. Префикс должен быть таким же как и для binutils, так как gcc будет просматривать те хэдеры с которыми создавались binutils

./configure --prefix=/opt/uClinux --target=m68k-pic-coff

Делаем m68k-coff C кросс компилятор

make LANGUAGES=c
make LANGUAGES=c install

m68k-pic-coff и m68k-coff можно поместить в path, или создать жесткую ссылку в /usr/bin.

cd /opt/uClinux/bin
ln -f * /usr/bin

Жесткие ссылки созданы взамен мягким. Если была попытка создать мягкую ссылку, gcc/evecvp пожалуется на большое количество символических ссылок ("too many levels of symbolic links"). /opt/uClinux/bin содержит мягкие ссылки, которые указывают на директории bin отдельного компилятора.

На данной ступени мы имеем С компилятор, который делает разрядно-независимые COFF бинарники. Чего у нас пока что нет, это стандартной С и стандартных математических библиотек. uClinux также зависит от плоских бинарников (flat binaries), а не только coff (Common Object File Format). Поэтому мы должны добавть конвертер из coff во flat (coff2flt), который конвертирует модули coff, которые генерирует компилятор, во flat бинарники, которые мы сможем запускать на uClinux.

coff2flt (COFF - Common Object File Format to Flat Binary конвертер)

В порядке создавать плоские бинарники одной коммандой, линковщик (LD) заменен скриптом, который сначала запускает линковщик, который генерирует .coff файл, затем запускает утилиту coff2flt для генерации плоского бинарника.

Скачиваем и распаковываем утилиту

tar -xzf coff2flt-0.5.tar.gz
cd coff2flt-0.5
make

make соберет coff2flt. В тарболе скрипт, линковщик. Мы должны заменить pic-coff-ld этим скриптом, в который возвращаются вызовы coff2flt для создания flat бинарника из coff бинарника. Однако перед тем как мы это сделаем, отредактируем строку в LD для установки %prefix% в /opt/uClinux/m68k-pic-coff

mv /opt/uClinux/m68k-pic-coff/bin/ld /opt/uClinux/m68k-pic-coff/bin/gld
install -m 755 coff2flt /opt/uClinux/m68k-pic-coff/bin
cp ld /opt/uClinux/m68k-pic-coff/bin
chmod 755 /opt/uClinux/m68k-pic-coff/bin/ld

Стандартная Библиотека C


При компиляции бинарников пользовательского пространства используются две библиотеки. Это стандартная библитека С и стандартная математическая библиотека. Это статические библиотеки, которые линукются во время компиляции.

Стандартная С библиотека uC всегда имела беду с ошибками. В частности они имеют плохую манеру утечки памяти из-за их функций выделения памяти. Некоторые индивидуумы имеют патчи для malloc функций, которые можно вручную применить и собрать.

uC-libc испытавает очень радикальные изменения в данный момент. Эти экспериментальные изменения доступны через uClinux CVS хранилище. Стабильная библиотека должна быть доступна скоро, она заменит старые версии uC-libc и предоставит наиболее стабильную платформу. На позитивной ноте, должен сказать, что математическая библиотека имеет маленькие проблемы.

Извлекаем тарбол uC-libc в /opt/uClinux

tar -xzf uC-libc-310899.tar.gz

Библиотека uC-libc имеет две символические ссылки (include/linux и include/net), которые должны указывать на хэдеры ядра uClinux. Эти ссылки требуют, чтобы директория linux находилась в том же дереве, что и директория uC-libc. Если одной не существует из-за различных мест инсталляции, Вы можете создать ссылку.

Библиотека uC-libc в нынешнем состоянии не имеет функций setjmp и longjmp, которые позже потребуются sh. Простейший путь поправить это, переместить uC-libc/machine/setjmp.S в uC-libc/sysdeps/ и включить это (setjmp.o) в uC-libc/sysdeps/makefile.objs

cd uC-libc
make

Если Вы получите сообщения об ошибках о пропавших файлах(скорее всего в директориях asm, linux или net) такую как "/asm/types.h - No such file or directory," тогда проверьте сконфигурировали ли Вы ядро (/include/asm ссылки на месте) и что здесь находятся исходный код ядра linux и ссылка на linux в той же директории что и uC-libc оба.

make скомпилирует библиотеку uC-libc (libc.a) и оставит ее в директории uClibc. Теперь мы должны сделать ее доступной для средств m68k-pic-coff. Каждая ссылка может быть создана, а файлы скопированы

cp libc.a /opt/uClinux/m68k-pic-coff/lib/libc.a
cp crt0.o /opt/uClinux/m68k-pic-coff/lib/crt0.o

Хэдеры также должны быть доступны. Chaintool уже поместил assert.h в /opt/uClinux/m68k-pic-coff/include, поэтому можно переименовать текущую директорию

mv /opt/uClinux/m68k-pic-coff/include /opt/uClinux/m68k-pic-coff/include.old
ln -sf include /opt/uClinux/m68k-pic-coff/include

Стандартные математические библиотеки


Стандартные математические библиотеки не такие проблематичные как С библиотеки. Просто извлеките их в /opt/uClinux и соберите

tar -xzf uC-libm-0.9.1.tar.gz
cd uC-libm
make

затем создайте ссылки в m68k-pic-coff/lib для указания на библиотечные файлы и хэдеры. Эти хэдеры будут обычно находится по их пути в директорию uC-libc/include символической ссылкой.

ln -f libmf.a /opt/uClinux/m68k-pic-coff/lib/libmf.a
ln -f libmf.a /opt/uClinux/m68k-pic-coff/lib/libm.a
ln -f mathf.h /opt/uClinux/m68k-pic-coff/include/mathf.h
ln -f mathf.h /opt/uClinux/m68k-pic-coff/include/math.h

genromfs - ROM FileSystem Generation Utility


Genromfs генерирует ФС с постоянной памятью (ROM Filesystem). Извлеките, пропатчите и соберите так:

tar -xzf genromfs-0.3.tar.gz
gzip -d genromfs-0.3.diff.gz

cd genromfs-0.3
patch -p1 <../genromfs-0.3.diff
make
make install

make install инсталирует genromfs в /usr/bin + положит свою документацию в usr/man/man8 Genromfs теперь может быть вызвана из коммандной строки для генерации своей romfs.

genromfs -v -V "ROM Disk" -f romdisk.img -d romdisk 2> romdisk.map


Genromfs имеет несколько багов относительно нодов устройства (device nodes). Если Ваша romfs не корректна, ядро сообщит об этом (can't open the device node) и тогда запаникует (panics). Чаще всего полезней монтировать Вашу снова сгенерированную romfs чтобы посмотреть все ли корректно. Делается это так:

mount -r -o loop -t romfs romdisk.img /mnt/romfs

Диск с ROM ФС и бинарники пользовательского пространства



Диск с постоянной памятью (romdisk-0.9.1.tar.gz) - сжатый тарбол, который содержит ноды устройства (device nodes). В итоге файл должен быть распакован (от root'а) в /opt/uClinux

tar -xzf romdisk-0.9.1.tar.gz


Диски romdisk образуют базис ФС встаиваемых (embedded) систем. Утслита genromfs создаст romfs.img из данного дерева, таким образом любые изменения в дереве будут отображены в ФС uClinux. Диск romdisk имеет следующие директории и файлы:

bin dev etc htdocs lib proc ramfs.img sbin tmp usr var


Вы заметите, что при входе в каталог bin предварительно скомпилированные бинарники будут видны. Их исходные коды устанавливаются так:

tar -xzf uC-src-0.9.2.tar.gz
cd src
make

Если Вы испытываете проблемы со сборкой из sh - неопределенный указатель на 'setjmp' или 'longjmp', проверьте включили ли Вы setjmp.S в сборку uC-libc.

Запуск make соберет все исходные коды перечисленные в SUBDIR определенные Makefile. Поэтому если вы добавляете экстра код сюда, то должны влкючить их в Makefile. По завершении процедуры сборки, бинарники будут в находится в директориях src/bin. Скрипт deftemplate.sh скопирует необходимые бинарники из /src в /romdisk/bin или sbin.

cp deftemplate.sh /opt/uClinux/


Нужен еще последний файл. buildenv.sh установит среду сборки из чистой директории, копируя необходимый код устанавливая Makefile. Скопируйте buildenv.sh в /opt/uClinux/bin и создайте ссылку на /usr/bin.

cp buildenv.sh /opt/uClinux/bin/
ln /opt/uClinux/bin/buildenv.sh /usr/bin/buildenv


и всё. Теперь если Вы создадите пустую директорию где-либо и введете buildenv, таинственно появится Makefile. Затем введите make, чтобы увидеть исходные коды пространства пользователя, romdisk etc копируется поверх и соберется.

PIC32 патч - 32-битный PIC патч для m68k-pic-coff 2.7.2.3


С текущим компилятором m68k-pic-coff, будет ограничение на сборку исполняемого кода размером свыше 32k. Размер исходит из использования 16-битного знакового сдвига. Эрвин Отрайд (Erwin Authried) выпустил некоторые патчи для m68k-pic-coff-gcc для генерации 32-битных сдвигов, которые снимают эти ограничения. Код может ббыть собран нормально с 16-битными сдвигами без указания дополнительных специфик. Если Ваша программа превышает 32k, тогда можно вызвать компилятор с флагами -fPIC, которые генерируют 32-битные сдвиги.

Код скомпилированный с -fPIC больше размером. В дополнении к патчу компилятора, нужен новый файл запуска C (C startup file, crt0.S). Он дожен быть скомпилирован и добавлен в m68k-pic-coff/lib. Файл запуска не содержит функции _cleanup(), поэтому должен быть включЕн из другого места.

Отладка


Отладка является необязательным дополнением для "башковитых" uClinux программистов. Состоит она из двух компонентов: gdb-4.18, запускаемый на хост машине, сконфигурированной для m68k-coff, и gdbserver, запускаемый на uClinux платформе. Вместе они общаются через сеть (IP). Пока gdb клиент компилирует с небольшими усилиями, gdb сервер нуждается не только в пропатчивании, но также из библиотеки uClibc, библиотеке отладки uClibc и поддержку из ядра uClinux - но это еще не всё.

gdbserver требует прерывание в ядре uClinux для работы. Хорошие новости в том, что это было включено в поздние ядра, и поэтому не требует внимания. Ядро uClinux-2.0.38.1pre7, описанное здесь, уже имеет эту поддержку.

Скачайте и распакуйте gdb-4.18

tar -xzf gdb-4.18.tar.gz
gzip -d gdb-4.18-gdbserver.diff.gz
cd gdb-4.18
patch -p1 <../gdb-4.18-gdbserver.diff

Сконфигурируйте gdb клиент запустив на хосте для отладки m68k-coff кода и соберите

./configure --target=m68k-unknown-coff
make

Для сборки gdbserver потребуются некоторые дополнительные фкнкции, которых нет в стандартной библиотеке uC-Libc. Исходный код есть в библиотеке, но не задан для сборки по дефолту. Зайдем в /uC-libc/sysdeps/m68k и отредактируем ptrace.c так чтобы путь к ptrace.h был корректен. Заменим #include <sys/ptrace.h> на #include<linux/ptrace.h>.

Теперь добавим исходный код для сборки, редактируя /uC-libc/sysdeps/makefile.objs добавив m68k/ptrace.o в конец списка OBJS, чтобы это смотрелось так

waitpid.o \
write.o \
m68k/ptrace.o


Затем пересоберем библиотеку uC-libc и довавим новый libc.a в /m68k-pic-coff/lib

cd gdb-4.18/gdb/gdbserver
../../configure --target=m68k-linux-coff


Затем отредактируем Makefile, изменив CC = gcc на CC = m68k-pic-coff-gcc

make gdbserver
coff2flt -s 32768 -o gdbserver gdbserver.coff

Запуская make, Вы создаете плоский flat бинарный код gdbserver'а, размер стэка которого по умолчанию составляет около 4k. В результате gdbserver может рухнуть или отказать при соединении. Поэтому рекомендуется линковать с размером стэка в 32k

CVS – Concurrent Version System

Хранилище uClinux доступно на http://cvs.uclinux.org. Отсюда можно отслеживать обновления исходного кода и смотреть какие изменения были сделаны и зачем.

Если вы хотите скачать полную версию исходных кодов, тогда это может быть сделано регистрацией в CVS используя CVS клиент. uClinux предоставляет анонимный доступ только для чтения к своему хранилищу.

Чтобы начать, Вы должны зарегистрироваться. Используйте следующую комманду:

echo anonymous > cvs –d:pserver:anonymous@cvs.uclinux.org:/var/cvs login

Тем сымым Вы войдете в CVS хранилище, используя имя anonymous и пароль anonymous.

cvs –z3 –d:pserver:anonymous@cvs.uclinux.org:/var/cvs co –P <dir>


где <dir> - одна из актуальных директорий,

uClibc The uClinux Userland C Library
uClinux-2.0.x 2.0.38 uClinux Kernel
uClinux-2.4.x 2.4.0 uClinux Kernel
userland uClinux Userland Binaries


Используется спецификатор -z3 для сжатия. Это максимальное сжатие. co необходимо для прекращения связи, -P конкретизирует отсеченные директории (убирает пустые директории).

Позже можно обновить исходные коды используя следующую комманду команду в соответствующей директории

cvs -z3 update -d -P


Ссылки:
GNU GCC
Linux
wiki: uClinux
wiki: binary file

1 комментарий:

JAZz комментирует...

Отличный материал, спасибо брат