Итак, мне нужно откомпилировать Linux для Системы-на-Кристалле на базе проекта Amber ARM. Для этого мне потребуются красные глаза вот этого пингвина.
На первый взгляд, компиляция не должна быть проблемой, ведь есть оригинальная инструкция автора, как это сделать. И инструкция надо сказать совсем простая. Она находится в файле sw/vmlinux/README.txt:
# Download the kernel source
wget http://www.kernel.org/pub/linux/kernel/v2.4/linux-2.4.27.tar.gz
tar zxf linux-2.4.27.tar.gz
ln -s linux-2.4.27 linux
cd ${LINUX_WORK_DIR}/linux
#Apply 2 patch files
cp ${AMBER_BASE}/sw/vmlinux/patch-2.4.27-vrs1.bz2 .
cp ${AMBER_BASE}/sw/vmlinux/patch-2.4.27-amber2.bz2 .
bzip2 -d patch-2.4.27-vrs1.bz2
bzip2 -d patch-2.4.27-amber2.bz2
patch -p1 < patch-2.4.27-vrs1
patch -p1 < patch-2.4.27-amber2
# Build the kernel
make dep
make vmlinux
Сам Linux можно выкачать с kernel.org. Патчи есть в проекте. Я думал это работа так, минут на тридцать. Но не тут-то было. Признаюсь честно – для меня это было не просто.
Так в чем же проблема?
Собственно сам kernel скачать действительно не трудно – командой wget.
Разархивировать так же просто:
tar zxf linux-2.4.27.tar.gz
Первый патч patch-2.4.27-vrs1 от ARM накладывается легко. А вот второй patch-2.4.27-amber2, собственно патч для проекта Amber – у меня гладко не пошел...
Патч споткнулся, пришлось отвечать “yes” и теперь я уже не уверен, что дальше все пойдет просто... Так и вышло.
Следующая команда из инструкции make dep провалилась. Не найдена команда arm-uclinuxeabi-gcc. Ну с этим понятно. Это не связано с «испоренным» патчем. Просто используемый компилятор называется не так. У меня сейчас установлен довольно новый CodeSourcery CodeBench от компании Mentor. Его компилятор называется arm-none-linux-gnueabi-gcc. Ладно, не большая беда. Нашел в файле Makefile где имя компилятора задается явно. Изменил его. Пробую опять:
Вот тут уже я сильно задумался. Видно, что проблема серьезная. За полчаса ничего не получится и придется очень долго разбираться. Я честно не знаю как у автора проекта Amber получилось написать такую инструкцию. И как он ею пользовался? Остается думать, что, возможно, у него была более другая версия Линукс на рабочей машине и, конечно, у него был другой компилятор (какой-то arm-uclinuxeabi-gcc). Как-то все это видимо влияло. Не знаю.
Я разбирался очень долго. Собственно исходных данных было несколько:
- Мне нужна минимальная конфигурация ядра с минимальным количеством установленных драйверов, так как памяти мало, да и вообще система очень простая.
- Мне нужно, чтоб ядро понимало, что мой процессор – это ранний ARM v2a и что у него адресное пространство не 32бита, а только 26.
- Мне нужно сказать ядру, что у меня только 8 Мб памяти.
- Мне нужно, чтобы в системе был установлен специальный драйвер последовательного порта, аппаратно совместимый с SoC Amber.
Пришлось долго «гуглить» и «яндексить». Так я понял, что по большому счету сперва хорошо бы выбрать необходимую конфигурацию системы.
В папке arch/arm/def-configs ядра Linux есть множество файлов, которые описывают уже предопределенные конфигурации для разных систем. Ни в одном файле нет слова «amber». Файла конфигурации с именем «amber» так же нет. Я подумал, что можно попробовать выбрать из имеющихся конфирураций ту, что наиболее ближе к моей системе. Пришлось просто просматривать глазами все эти конфигурационные файлы от начала до конца, изучая возможные опции конфигурации. После многочасовых просматриваний всех этих конфигураций, когда в глазах уже рябило, я подумал, что наверное, самая подходящая конфигурация будет a5k. В ней я нашел вот такие строки:
# CONFIG_CPU_32 is not set
CONFIG_CPU_26=y
Вот это то, что нужно. По крайней мере это задает нужный тип процессора - ведь в нашем раннем ARM проецессоре как раз адресное пространство ограничено 26 линиями адреса.
Значит попробую выбрать эту конфигурацию:
make a5k_config
Эта команда похоже сработала. В ответ я получил что-то вроде «*** Default configuration for a5k installed». После этого даже команда «make dep» сработала без ошибок. Счастье было так близко...
Начинаю собственно компилировать Linux:
Хм.. какие-то ошибки в драйверах i2c…
Не знаю в чем тут проблема. Как такое вообще может быть? Повлиял ли битый патч? Но и неиспользовать его я не могу, так как он похоже вносит и много нужных изменений в код и настройки. Тут я подумал, что нужно повыключать почти все неиспользуемые драйвера – это сведет количество возможных проблем к минимуму. Запускаю команду
make menuconfig
Она дает вот такую замечательную менюшку, в которой можно задавать все-все настройки ядра.
Справедливости ради нужно сказать, что все настройки могли бы быть в нужном мне файле конфигурации arch/arm/def-configs/a5k или в каком-то другом. Пока я думаю удобнее будет нащупать все нужные опции с помощью «make menuconfig», а уже позже сделать простой файл конфигурации.
Вот начались мои поиски всевозможных полезных и не очень полезных настроек ядра Linux. Какие дравера оставить? Какие драйвера включать? Файловые системы и настройки сети? Слишком много степеней свободы. Повыключал floppy, ATA, framebuffer, i2c и много еще чего. Нашел опцию командной строки, с которой запускается Linux:
Добавил в командную строку «mem=8M». Надеюсь теперь Линукс поймет, сколько у меня в системе памяти на самом деле. Потом сохраняю настройки и повторяю все сначала: «make dep» и «make vmlinux».
И снова ошибки. Теперь уже в заголовочных файлах как-то связанных с сетью. Это какой-то ужас и кошмар. Мне кажется, что я иду куда-то не туда, совершенно в неверном направлении. Но что делать? Другого пути нет или я его не вижу. Сеть – это не то, что можно запросто выключить в настройке ядра. Точнее выключить то можно, но поддержка сети – это одно из важнейших свойств ядра Linux. Я не могу от нее отказаться. Может я когда нибудь подключу к системе ethernet..
Исправляю два файла в исходниках ядра include/net/icmp.h и include/net/ipv6.h, добавляю в них строку
#include <net/snmp.h>
После этого исправления компилирую «make vmlinux» и, теперь другая напасть:
Почему-то оказываются неопределенными несколько функций низкоуровневой записи/чтения: outsw, insw. Посмотрел внимательнее. Получается вот что. В папке arch/arm/lib есть несколько ассемблерных файлов под разные типы процессоров ARM. В них описаны функции доступа к портам аппаратуры: чтение или запись полуслов, слов, байт. Это файлы вроде io-readsl-armv3.S или io-writesw-armv4.S. Эти и подобные им файлы выбираются в зависимости от установленной опции в конфигурации ядра CONFIG_CPU_32v3 или CONFIG_CPU_32v4 или других. В моем случае этих опций не установлено, поэтому никаких ассемблерных файлов не подключается к проекту. Пришлось создать свой файл io-sw.S по аналогии с процессором CPU_32v3 и добавить его в ядро путем исправления соответствующего Makefile в папке arch/arn/lib.
Еще одна серьезная проблема – мне нужно, чтобы в системе работал наверное не очень стандартный последовательный порт системы на кристалле Amber.
В папке ядра Линукс drivers/serial я обнаружил файл amba.c в котором есть строки:
#define AMBER_UART0_BASE 0x16000000
#define AMBER_UART1_BASE 0x17000000
Тут ключевое слово “AMBER” и еще важно, что 0x16000000 – это и есть реальный физический адрес последовательного порта в системе.
Видимо amba.c и есть исходный тескт драйвера последовательного порта. Но вот беда: невозможно включить поддержку последовательного порта AMBA в меню программы «make menuconfig». Такой опции про AMBA serial просто нет в наличии в меню.
После долгих поисков понял, что опция AMBA serial зависит от включенной опции CONFIG_ARCH_INTEGRATOR. А я то ведь выбрал себе базовую платформу совсем другую - A5K.
Исправил файл driver/serial/Config.in, теперь там будет моя строка:
dep_tristate ‘ARM AMBA serial port support’ CONFIG_SERIAL_AMBA $CONFIG_ARCH_ARCA5K
Теперь, если запустить make menuconfig, то опция AMBA serial становится вполне доступной:
Вот после этого, после всего этого шаманства я смог откомпилировать ядро и получить исполняемый образ vmlinux.
Теперь нужно испытать его в плате Марсоход2. Заработает или нет?
Подключаю плату Марсоход2 к моему ноутбуку USB кабелем. Из среды Altera Quartus II программатором загружаю образ SoC AMBER в ПЛИС Cyclone III. Программой TeraTerm открываю последовательный порт, ведущий к плате и с помощью XMODEM загружаю мой собственный образ ядла Linux. Запускаю его командой «j 80000» и вот:
Нельзя сказать, что не работает совсем. Во-первых, в консоли я вижу процесс запуска – это уже хорошо, значит драйвер последовательного порта в Линукс установлен и работает правильно. В консоли я вижу, что это именно моя сборка по начальной строке «Linux version 2.4.27-vrs1 (nick@ubuntu)» и дата создания образа ядра моя. Вторая хорошая новостьв том, что теперь образ Линукс знает сколько у меня в системе памяти и правильно пишет 8M total. Если помните, я задал размер памяти в командной строке запуска ядра через строку «mem=8M».
А вот плохо то, что сразу после Starting kswapd ядро банально виснет. С этим нужно отдельно разбираться.
Это значит, что продолжение истории нашей санта-барбары скоро будет.
PS: пока линукс нормально не стартует я не буду делать важные комиты в наш проект SoC Amber на github. Чуть позже будет и полная инструкция и метод сборки.
Подробнее...