![]() |
|
Нашим было нечего делать во время кризиса... мы занимались разработкой электроники и программного обеспечения, которое нам самим интересно. Обычно такие некоммерческие разработки составляют основу для будующих коммерческих продуктов. На них мы учимся и осваиваем что-то новое. Одна из таких разработок, котороая в результате увидела свет, одноплатный промышленный компьютер sh27cnc1 на базе процессора ARM 926. Данная разработка позиционируется как основа построения ситсем сбора данных и систем управления технологическим оборудованием. При проектировании устройства за основу был взята документация на отладочный набор Atmel AT91SAM9260-EK и добавлено несколько узлов, в т.ч. программируемая логика ПЛИС Altera и множество портов и интерфейсов сбора данных RS-485.
Вот основные параметры устройства:Хотим поделиться опытом развертывания ОС GNU/Linuх. До этого мы только сказки слушали, что на контроллер вроде нашего можно поставить полноценную пользовательскую ОС, а тут решили попробовать.
Всё начинается с загрузчика. Железо вдруг не оживает. Сначала по аппаратно предусмотренной процедуре нужно загрузить хоть что-то в кеш, что сможет дальше вызвать хоть какие-то осмысленные действия. В данном случае из SPI DataFlash должен загрузиться маленький загрузчик (Bootstrap), который помещается в страницу кЭша, 4кБайта. Маленький загрузчик должен загрузить большой загрузчик (Bootloader), который уже выполнит загрузку ядра ОС. Первый загрузчик должен включить и настроить память SDRAM, чтобы образовалось место под код и данные, потом уже загрузить загрузчик побольше.
Дело загрузчика настроить связь с внешним миром, хотябы одно терминальное устройствож; настроить перефирию процессора; загрузить с сети, из флеш, с диска или из другого подходящего носителя ядро ОС и передать управление ядру. Терминальное устройство предоставляет возможность повлиять на процесс загрузки. Обычно в таких случаях, когда нет ни монитора ни клавиатуры в качестве терминального устройства используется COM порт.
Что загрузчики, что Linux по умолчанию используют такие настройки COM порта:Процессор AT91SAM9260, когда не находит подходящих прошивок по нулевым адресам Data- и NAND-флеш памяти, запускает живущую в ROM программу SAM Boot Agent (SAM-BA). Агент - это ещё один встроенный загрузчик, который можно использовать для первоначальной прошивки образа во Флеш или для восстановления после сбоя. Агент умеет прошивать флеш через DBGU (интерфейс отладки к которому можно подключиться через COM порт) или через USB.
Сначала нам необъодимо записать во флеш образ маленького загрузчика (Bootstrap), образ большого загрузчика (U-Boot), а затем и само ядро GNU/Linux.
Мы выполняли процедуру загрузки с компьютера под управлением GNU/Linux. Ниже приводится список команд вызываемых из командной строки GNU/Linux. Список достаточно подробный чтобы объяснить новичку как на промышленный компьютер ставится с нуля уважаемая ОС.
Подключаем наше устройство к USB-порту компьютера и смотрим, как он определился в системе:
$ lsusb $ Bus 002 Device 060: ID 03eb:6124 Atmel Corp. at91sam SAMBA bootloaderИз этой строчки мы взяли Идентификатор устройства и идентификатор производителя.
Софт для прошивки, SAM Boot Assistant (SAM-BA) для Linux, качаем отсюда. SAM-BA использует USB через драйвер виртуального COM-порта.
Наши следующие шаги -- подгрузить драйвер usbserial:
# modprobe usbserial vendor=0x03eb product=0x6124Этой командной мы создали соединение через USB посредством драйвера виртуального COM-порта.
Теперь у нас есть виртуальный COM-порт, через который с контроллером общается программатор. Бинарный образ ядра системы называется sam-ba_cdc_2.8.linux_01, его и пытаемся загрузить. В запросе указываем порт /dev/ttyUSB0 и параметр AT91SAM9260-EK. Конфигурации прошивок выбираются по названию набора разработчика, для которого эти конфигурации создавались. Наша плата по парамаетрам загрузки совместима с данным набором. Основные показатели выбора конфигурации загрузки -- разрядность SDRAM и тип процессора.
Теперь, выбирая вкладками нужную периферию, можно заливать код. Не забываем вызывать скрипты типа Enable Flash и нажимать Execute, иначе при попытке обратиться к неинициализированной микросхеме устройство повиснет вместе с программатором. Стартовый 4-х килобайтный загрузчик (Bootstrap) лучше заливать через скрипт Send Boot File, а всё остальное - через диалог посередине окна и указание адреса вручную. Если загрузчик ругается и не хочет копировать данные, проверяем, чтобы адрес был кратен размеру блока записи (0x1000 байт для NAND, 2112 для DataFlash).
Для тех, кто хочет скомпилировать самостоятельно ядро и загрузчики, понадобится компилятор arm-elf-gcc под архитектуру ARM. Кросс-компилятор берётся с сайта http://gnuarm.com. Теперь всё должно быть готово к прошивке и отладке.
Качаем его. Если микросхема DataFlash выбирается сигналом Chip Select 1, то можно взять стандартный скомпилированный бинарник от комплекта разработчика. Иначе придётся мучать исходники и настраивать сигналы выбора периферии.
Нужно раскомментировать подходящий "драйвер" DataFlash-микросхемы AT45DB041B в файле driver/dataflash.c (функция df_init). Эти микросхемы бывают разной емкости, в нашем случае микросхема отличалась по емкости от использованой в отладочном наборе. Следуя инструкциям, выбираем нужную нам конфигурацию путём использования нужного Makefile:
$cd board/at91sam9260ek/dataflash $make CROSS_COMPILE=arm-elf-Чтобы быть уверенным в том, что загрузчик честно выполняет свою задачу, можно разрешить вывод отладочных сообщений, заменив строчку #undef CFG_DEBUG в главном конфиге at91sam9260ek.h:
//#undef CFG_DEBUG #define CFG_DEBUGТогда загрузчик будет выводить сообщения на COM-порт, и проблема, если она есть, найдётся быстрее.
После компиляции заливаем получившийся бинарный файл (.bin) в DataFlash через SAM-Ba Boot, используя скрипт "Send Boot File". Перезагружем устройство и изучаем лог отладочных сообщений.
Качаем исходники, добавляем экспериментальный патч, распаковываем и собираем:
$ make at91sam9260ek_dataflash_cs0_config $ make CROSS_COMPILE=arm-elf-
Определимся теперь, куда заливать u-boot.bin. Из исходников загрузчика первого уровня (4-х килобайтный Bootstrap) узнаём несколько любопытных подробностей: #define IMG_ADDRESS 0x8400 /* Image Address in DataFlash */ #define IMG_SIZE 0x33900 /* Image Size in DataFlash */ #define JUMP_ADDR 0x23F00000 /* Final Jump Address */ Это именно те адреса, откуда Bootstrap берёт прошивку (в нашем случае U-Boot) и куда копирует её. То есть, льём образ в Dataflash по адресу 0x8400. Так называемый Environment, параметры окружения, а по сути, конфигурационный блок загрузчика, тоже должен где-то жить. Его место - между самим U-Boot'ом и первичным загрузчиком по адресу 0x4200 (см. /include/configs/at91sam9g20ek.h), поэтому в будущем не трогаем этот блок. Перегружаемся и смотрим на результат в журнале сообщений. U-boot должен определить имеющуюся память, обломаться с загрузкой ядра и вывалиться в командную строку.
Здесь можно скачать прекомпилированное ядро, заточенное под отладочную плату. Предлагаю начать именно с него, гарантированно работающего. Итак, берём ядро поновее (2.6.27), на будущее скачиваем с той же странички исходники с патчем и, вызвав SAM-BA Boot, заливаем в NAND-Flash по адесу 0x42000. После перезагрузки снова оказываемся в командной строке U-Boot. Пишем такие команды:
U-Boot> setenv bootcmd nboot 0x22000000 0x0 0x42000 \; bootm U-Boot> saveenvКоманда setenv ставит переменные окружения. Bootcmd - особая переменная, выполняющаяся в виде скрипта по умолчанию. Теперь, если ничего не нажимать 3 секунды в начале загрузке U-Boot, он автоматически выполнит этот скрипт:
U-Boot> nboot 0x22000000 0x0 0x42000; U-Boot> bootmКоманда nboot копирует данные из NAND-Flash по указанному адресу, а bootm - запускает программу, упакованую утилитой mkimage (см. ниже). Если же клавиша была нажата и мы снова оказались в командной строке, то продолжение загрузки можно вызвать комадой boot.
В общем, если всё сделано правильно, то сначала появится небольшая статистика о ядре, а потом начнётся его распаковка (строчка "Uncompressing Linux"). После распаковки должно завестись само ядро, радостно сообщая об этом множством сообщений на отладочный порт. Читать сообщения надо внимательно, там сообщается об удачных и не очень фактах подключения периферии, это может в будущем помочь при перекомпиляции и настройке ядра. Как ядро выскажет всё, что думает об окружающем его мире, произойдёт самое логичное, что может случиться - оно запаникует. Файловой системы-то ведь нет! Это нормально, прикручиванием ФС займёмся попозже.
Компилировать ядро, если понадобится, также несложно. Качаем стандартное ядро с kernel.org, а с сайта linux4sam.org скачиваем патч для отладочного набора и конфигурацию ядра:
$ cd linux-2.6.27/ $ wget http://maxim.org.za/AT91RM9200/2.6/2.6.27-at91.patch.gz $ zcat 2.6.xx-at91.patch.gz | patch -p1Конфигурирование и компиляция:
$ wget http://www.linux4sam.org/twiki/pub/Linux4SAM/LinuxKernel/at91sam926yek_defconfig $ cd linux-2.6.27/ $ cp at91sam926yek_defconfig .config $ make ARCH=arm oldconfig $ make ARCH=arm menuconfig $ make ARCH=arm CROSS_COMPILE=arm-elf-Дожидаемся окончания компиляции и "обёртываем" ядро в понятный U-Boot'у формат:
$ mkimage -A arm -O linux -C none -T kernel -a 20008000 -e 20008000 -n linux-2.6 -d arch/arm/boot/zImage uImageПараметр -a сообщает место в оперативной памяти, куда загружать ядро, а -e - откуда его "стартовать". Естественно, этот адрес не должен пересекаться с местом, куда U-Boot изначально копировал образ (0x2200_0000).
Теперь, когда у нас есть полноценное рабочее ядро Linux, сумевшее подцепить периферию и даже микросхему NAND Flash установленную на плате контроллера. Неплохо бы на эту флэшку установить файловую систему. Но начальная часть её уже занята, а никакой таблицы разделов, которую мы привыкли видеть в начале каждого жесткого диска, у нас нет и не будет. Разработчики Evaluation Kit поступили мудро: они тупо записали список разделов внутрь ядра Linux (см. linux-2.6.27/arch/arm/mach-at91/board-sam9260ek.c)! Особо внимательные увидели этот список ещё на этапе загрузки ядра.
В общем, файловую систему грузим по адресу 0x400000 (/dev/mtdblock1). Для начала можно взять предлагаемую на linux4sam.org. Их там две - это дистрибутивы OpenEmbedded/Angstrom и более легковесный BuildRoot на базе uClibc. Готовые базовые образы там тоже можно скачать, они уже упакованы в jffs2 образ для флэш. Не забываем обновить переменную bootargs в меню u-boot, её значение подставляется в качестве параметров командной строки ядра:
U-Boot> setenv bootargs root=/dev/mtdblock1 rootfstype=jffs2 rw U-Boot> saveenv
Официальный сайт - http://emdebian.org. Этот дистрибутив, как нетрудно догадаться, базируется на Debian и затачивается под легковесные встраиваемые устройства путём выкидывания из пакетов всякого лишнего, типа документации и локализации. Имея Дебиан на двух моих машинах и зная его довольно хорошо, Emdebian был моим логичным выбором. "Ветвей" у него два, это Grip и Crush. Я ставил Grip, как более полновесный на базе coreutils и glibc. Подробнее о различиях можно почитать на сайте.
Устанавливается Emdebian с помощью стандартного пакета debootstrap или набора скриптов emdebian-tools, могущих то же самое, плюс ещё кое-что. Я выбрал второе:
$ apt-cache search emdebian emdebian-archive-keyring - GnuPG archive keys for the emdebian repository emdebian-buildsupport - emdebian crossbuilding support emdebian-grip - support for the Grip flavour of Emdebian emdebian-grip-server - server-side support for Emdebian Grip emdebian-qa - emdebian quality assurance support emdebian-rootfs - emdebian root filesystem support emdebian-tdeb - transition package for TDeb handling scripts emdebian-tools - emdebian crossbuilding tool setСтавим всё, что есть, в хозяйстве пригодится. Далее нужен файл packages.conf с таким содержимым:
SCRIPT=/usr/share/debootstrap/scripts/lenny MIRROR=http://www.emdebian.org/grip/ PROXY=http://www.emdebian.org/grip/ SUITE=stableИ запускаем emsandbox:
# emsandbox -a arm -v ./ -m ./ --machine-path .На выходе - запакованный архив с файловой системой. Только она пока что нерабочая. Суть в том, что скрипт не смог довыполнить настройку дистрибутива, так как архитектура, на которой он выполнялся (x86), отличается от целевой. В любом случае, в корне получившегося образа будет лежать скрипт emsecondstage, который надо всеми правдами и неправдами запустить уже на самом устройстве. Скрипт emsandbox, кстати, не создаёт устройство /dev/console, поэтому перед запаковкой создаём его вручную:
# mknod dev/console c 5 1Пакуем ФС в образ jffs2:
# mkdir emdebian-1; cd emdebian-1 # tar xvzf emdebian-arm.tgz # rm emdebian-arm.tgz; cd .. # mkfs.jffs2 -d emdebian-1 -n -v -o emdebian-1.jffs2И заливаем по адресу 0x400000, указав в качестве параметра загрузки "init=/bin/bash". Если загрузиться удалось, выполняем скрипт emsecondstage и ставим пакеты, живущие в /var/cache/apt/archives, начиная с libc6 и sysvinit, после чего у нас настоящий Debian.
Поздравляю.