Чемпион в легком весе. Практическое руководство по поселению GNU/Linux на микроконтроллереЕвгений «Vshmuk» Бейсембаев (diver@edu.ioffe.ru, ICQ 308229460) Цель проста - научиться ставить ОС на базе Linux на что-то, отличное от вездесущей архитектуры IBM PC. Полагаю, у тебя есть такое устройство, бывшее совсем недавно маршрутизатором или каким-нибудь промышленным компьютером. Либо ты потратился и купил полноценный одноплатник, чтобы использовать его в качестве отдельного файл-сервера. Для таких функций писать с нуля прошивку не имеет смысла, а вот поставить специальный дистрибутив Linux – самое то. В предыдущем номере, напомню, была освещена теоретическая сторона вопроса и проведен обзор популярных архитектур и дистрибутивов для встраиваемых устройств. Сегодня займемся собственно установкой Линукса. Понятно, что в твоем случае может быть совершенно другая плата с другим контроллером. Но программирование встраиваемых устройств всегда проходит по одним и тем же шагам, поэтому, научившись все делать на моем примере, нетрудно перенести полученный опыт на твой девайс, чуток подправив алгоритм. Отличия будут, но чаще всего – несущественные, причем все тонкости прошивки отдельно взятого устройства подробно описываются в Datasheet к контроллеру и на сайте производителя. Также, для успешного завершения миссии, неплохо бы иметь базовые знания по процессу загрузки Linux и знать, что есть «периферия», «контроллер», «файловая система». Перед тем, как что-либо прошивать, получи максимум информации о подопытном устройстве: перепиши маркировки микросхем, узнай объем и типы памяти, почитай официальный сайт и форумы. Наверняка, ты не первый, кто устанавливает Linux на подобный девайс – и учиться лучше на чужих ошибках, чем на своих. Капризный монстрУ меня есть промышленный компьютер sh27cnc1, при проектировании которого был взят за основу Atmel'овский отладочный набор AT91SAM9260-EK и добавлено несколько узлов типа ПЛИС (программируемые логические интегральные схемы) от компании Altera, а также пара параллельных портов. Вот его ключевые компоненты:
Надо помнить, что AT91SAM9260 уже не совсем микроконтроллер в том смысле, который мы привыкли вкладывать в это понятие. Ведь внутри у него ну очень много всякой разнообразной периферии, начиная с ЦАПа для вывода звука и заканчивая контроллерами локалки (EMAC - уровень Ethernet) и Flash-памяти. В этом смысле 9260 – самый, что ни на есть, компьютер-на-кристалле. Но с другой стороны, оперативной памяти у него внутри - всего 8 Кб, из которых тебе доступно только 4, а энергонезависимой там нет вообще. Этот недостаток приходится компенсировать напайкой внешней памяти. И все же, как запускать такого капризного монстра? Тем, кто не читал мою прошлую статью, напомню. В самом начале работы процессора первым делом стартует встроенный в ROM загрузчик. У того хватает интеллекта только на то, чтобы высосать 4 Кб (одну страницу) кода из микросхемы Data- или NAND-flash памяти, скопировать их во внутреннюю оперативку (которой как раз 4 Кб) и передать на нее управление. В эти 4 Кб мы должны впихнуть код инициализации большой и взрослой оперативки SDRAM, определить напаянные микросхемы Flash-памяти, скопировать оттуда остальной код в уже работающую оперативку и передать на него управление. С этого момента уже можно говорить о том, что устройство запущено. В общем, это не так страшно (мы не в рубрике Coding), и наша задача сведется к компиляции уже готовых исходников (да и то не всегда). Общаться с Линуксом первое время будем через так называемый отладочный интерфейс DBGU. С точки зрения использования, это обыкновенный UART-порт с обрезанными возможностями. На моей плате он выведен через RS-232-интерфейсную микросхему на 9-пиновый COM-разъем, который уже подключается к компу.
Вбей эти параметры в свою терминальную программу на стороне PC. Не лезь на рожон. Заставь устройство запуститься хотя бы с дефолтовыми ядром и файловой системой, идущими в комплекте с отладочной платой, а потом уже на заведомо рабочем Линуксе затачивай девайс под свои нужды. Поехали. ЗаливкаКак уже неоднократно говорилось, AT91SAM9, когда не находит подходящих прошивок по нулевым адресам Data- и NAND-флеш памяти, запускает живущую в ROM программу SAM Boot Agent (SAM-BA). На устройстве САМ-Бу можно вызвать закороткой особого пина (смотри документацию) или просто бросанием SPI Slave Output ножки на землю. Подключаем девайс к USB-порту и проверяем, как он определился:
Далее, по ссылке www.linux4sam.org/twiki/bin/view/Linux4SAM/SoftwareTools, качаем софт для прошивки. Оттуда же узнаем наши следующие шаги:
Что ж, у нас есть виртуальный COM-порт, к которому подключаемся софт-программатором. Бинарник после распаковки называется sam-ba_cdc_2.8.linux_01, его и вызываем. При запросе указываем порт /dev/ttyUSB0 и плату AT91SAM9260-EK. Теперь, выбирая вкладками нужную периферию, можно заливать код. Не забывай вызывать скрипты типа Enable Flash и нажимать Execute, иначе при попытке обратиться к неинициализированной микросхеме устройство повиснет вместе с программатором. Первичный 4-килобайтный загрузчик лучше заливать через скрипт Send Boot File, а все остальное - через диалог посередине окна и указание адреса вручную. Если загрузчик ругается и не хочет копировать данные, убедись, что адрес кратен размеру блока (0x10000 байт для NAND). Возможно, тебе еще понадобится компилятор arm-elf-gcc под архитектуру ARM. Берется он с сайта gnuarm.com. Загрузчик первого уровня, AT91 BootstrapКачаем его по адресу www.linux4sam.org/twiki/bin/view/Linux4SAM/AT91Bootstrap. Если твоя микросхема Dataflash живет на Chip Select 1, то сразу можешь взять скомпилированный бинарник, иначе придется мучить исходники. Распаковываем. Следуя мануалу по тому же адресу, выбираем нужную нам конфигурацию путем использования соответствующего Makefile. Имея 8-мегабитный Dataflash на плате, загрузчики я запихивал именно туда, а ядро с ФС - уже на 256-мегабайтный NAND-Flash. Значит, в моем случае проект компилируется вот так:
Загрузчик простенький, в его кодах не составит труда разобраться, но следи, чтобы размер итогового бинарника не превышал 4096 байт. Мне еще пришлось раскомментировать «драйвер» моей Dataflash-микросхемы AT45DB041B в файле driver/dataflash.c. Функция df_init не совпадала с установленной на референсном отладочном наборе. Она была подложена в проект, просто закомментирована для уменьшения размера. Чтобы быть уверенным, что загрузчик честно отрабатывает свою часть и передает управление дальше, раскомментируй строчку «#undef CFG_DEBUG» в заголовочном файле at91sam9260ek.h. Тогда загрузчик сможет плеваться сообщениями на отладочный порт, и, если что-то не заработает, ты найдешь проблему быстрее. После компиляции заливай получившийся .bin в выбранный тобой Flash через SAM-BA Boot, используя скрипт «Send Boot File». Перезагружай устройство и смотри на отладочные сообщения, чтобы быть уверенным в этом этапе. Загрузчик второго уровня, U-BootТаковым его можно назвать лишь с натяжкой. Этот монстр разве что в тетрис не играет. Умеет загружать ОСь откуда угодно, в том числе и по сети (TFTP и BOOTP), тестировать и копировать RAM и Flash память. Кроме того, поддерживает простые скрипты. В общем, забираем с прилагаемого к журналу диска архив с исходниками u-boot-1.3.4.tar.bz2, распаковываем, добавляем экспериментальный патч u-boot-1.3.4-exp.diff и собираем:
Теперь определимся, куда заливать u-boot.bin. Если ты смотрел исходники загрузчика первого уровня (4-килобайтный Bootstrap), то мог заметить несколько любопытных дефайнов:
Это именно те адреса, откуда Bootstrap берет прошивку (в нашем случае, U-Boot) и куда ее копирует. Если ты не менял эти дефайны, то лей образ в Dataflash по адресу 0x8400. Так называемый Environment, а, по сути, конфигурационный блок загрузчика, тоже должен где-то жить. Его место - между самим U-Boot'ом и первичным загрузчиком по адресу 0x4200 (смотри /include/configs/at91sam9g20ek.h), поэтому в будущем не трогай этот блок, если не хочешь настраивать все заново. Перегружаемся и смотрим результаты. U-boot должен определить имеющуюся память, обломаться с загрузкой ядра и вывалиться в командную строку. Пиши help и изучай возможности. Ядро LinuxПоигравшись с командной строкой U-Boot, переходи к собственно загрузке ядра. Откуда его брать? По адресу www.linux4sam.org/twiki/bin/view/Linux4SAM/LinuxKernel можно скачать прекомпилированное ядро, заточенное под отладочную плату. Предлагаю начать именно с него, так оно гарантировано работает. Ядро у меня живет в NAND-Flash памяти по адесу 0x42000. Этот адрес посоветовал мануал, хотя я имел полное право грузить его куда угодно; надо только следить, чтобы оно не пересекалось с другими данными. Итак, берем ядро посвежее (2.6.27), на будущее скачиваем с той же странички исходники с патчем и, вызвав SAM-BA Boot, заливаем в выбранный флеш по выбранному адресу. После перезагрузки снова оказываемся в командной строке U-Boot. Пишем такие команды:
Опция setenv задает переменные окружения. Bootcmd - особая переменная, через которую описывают команды (в данном случае – «nboot 0x22000000 0x0 0x42000; bootm»), которые требуется выполнить после 3-секундного таймаута в начале загрузки U-Boot. Команда nboot копирует данные из NAND-Flash по указанному адресу, а bootm - запускает программу, упакованную утилитой mkimage (смотри ниже). Если же клавиша была нажата, и ты оказался в командной строке, то дефолтовая загрузка выполняется командой boot. В общем, если все сделано правильно, то сначала появится небольшая статистика о ядре, а потом начнется его распаковка (строчка «Uncompressing Linux»). Затем должно завестись само ядро, радостно возвещая об этом множеством сообщений на отладочный порт. Читай их внимательно, там сообщается об удачных и не очень фактах подключения периферии. В дальнейшем это может помочь при перекомпиляции и заточке. Как только ядро выскажет все, что думает об окружающем его мире, произойдет самое логичное, что может случиться - оно запаникует! Файловой системы ведь нет. Это нормально, – прикручиванием ФС мы займемся чуть позже. Скомпилировать ядро, если в этом будет необходимость, также несложно. Качаем ванильное ядро, а с linux4sam.org утягиваем патч для платы и дефолтный конфиг. Накладывание патча Конфигурирование и компиляция Дожидаемся окончания компиляции и «обертываем» ядро в понятный U-Boot'у формат:
Параметр '-a' сообщает в оперативной памяти, куда загружать ядро, а '-e' - откуда его стартовать. Естественно, этот адрес не должен пересекаться с тем, куда U-Boot изначально копировал образ (0x2200_0000). Файловая системаТеперь, когда у нас есть полноценное рабочее ядро Linux, сумевшее подцепить периферию и Flash-карту, неплохо бы на эту флешку скинуть ФС. Но начальная часть носителя уже занята, а никакой таблицы разделов, которую мы привыкли видеть в начале каждого IBM-совместимого диска, у нас нет и не будет. Разработчики Evaluation Kit, не мудрствуя лукаво, просто записали список разделов внутрь ядра Linux (смотри В общем, файловую систему грузим по адресу 0x400000 (/dev/mtdblock1). Для начала можно взять предлагаемую на linux4sam.org. Их там две - это дистрибутивы OpenEmbedded/Angstrom и более легковесный BuildRoot на базе uClibc. Готовые базовые образы тоже можно скачать, они уже упакованы в jffs2-образ для флеш.
Надеюсь, все прошло успешно, и у тебя затребовали авторизацию. Пиши логин root, а пароль оставляй пустым. Поздравляю, мы в системе! Осматривайся, проверяй, все ли на месте :). А если возможностей предустановленного дистрибутива тебе показалось мало, то читай дальше. Emdebian (emdebian.org)Этот дистрибутив, как нетрудно догадаться, базируется на Debian и затачивается под легковесные встраиваемые устройства путем выкидывания из пакетов всего лишнего, типа документации и локализации. С Дебиан на двух моих машинах, Emdebian был для меня логичным выбором. В настоящий момент в рамках проекта представлено два релиза - Grip и Crush, оба бинарно совместимы с Debian GNU/Linux 5.0 «Lenny». Я ставил Grip, как более полновесный на базе coreutils и glibc. Подробнее о различиях читай на сайте. Устанавливается Emdebian с помощью стандартного пакета debootstrap или набора скриптов emdebian-tools. Оба варианта примерно одинаковы по функционалу, выбирай любой. Далее ставим все, что найдется по команде «apt-cache search emdebian», – в хозяйстве пригодится. Следующий шаг: создаем файл packages.conf с таким содержимым:
И запускаем emsandbox:
На выходе - запакованный архив с файловой системой. Только она пока что нерабочая. Суть в том, что скрипт не смог довыполнить настройку дистрибутива, так как архитектура, на которой он выполнялся (x86), отличается от целевой. В любом случае, в корне получившегося образа будет лежать скрипт emsecondstage, который надо всеми правдами и неправдами запустить уже на самом девайсе. Как это сделать - дело твое. Можешь скинуть образ на usb-флешку и воткнуть ее в девайс, либо примонтировать образ по сети. После chroot'а накати пакеты, живущие в /var/cache/apt/archives, начиная с libc6 и sysvinit, и ты получишь настоящий Debian. Куда дальше?Тут все зависит от наличия у тебя энтузиазма, свободного времени и девушки. Делай с еще одним появившимся в твоем доме компьютером все, что пожелаешь, используй мощь установленного на него Линукса по максимуму! Для начала, оптимизируй ядро и ФС по размеру и эффективности, например, выбрось из него поддержку HID-устройств и всего прочего, что никогда не будет подключено к девайсу. Потом можешь попробовать избавиться от монстрообразного U-Boot. Операционка-загрузчик - это, конечно, хорошо, но и 4-килобайтный AT91 Bootstrap после некоторой допилки вполне может подготовить контроллер к загрузке ядра. Далее – подари своему одноплатнику внешний USB-винчестер и научи его качать торренты и раздавать файлы по Сети. Вырубив 400-ваттный файл-сервер, можно неплохо сэкономить на электроэнергии. Потом воткни веб-камеру, поставь легкий http-сервер и следи за территорией через страничку, выведенную сквозь файрвол в интернет. Короче, непаханое поле для экспериментов, лишь бы скорости хватало, да времени. DVDНа прилагаемом к журналу диске можно найти исходники ядра и U-Boot с наложенными патчами, образы файловых систем OpenEmbedded/Angstrom и BuildRoot, а также немного документации по железу. WWW
|