Новости про Minix

Вот уже больше года «стабильной» версией Minix остается 3.1.8. 3.2.0 так и не выходит из экспериментальной стадии, хотя сделано там очень и очень много. Наконец появилась поддержка динамических библиотек, основной формат объектных файлов — ELF, а не устаревший a.out, портируется userland из NetBSD, список пакетов наконец-то «перерос» версию 3.1.7. Таненбаум опубликовал вакансию программиста для ARM — Minix будут туда портировать. В общем, жизнь движется.

Интересно, можно ли собрать в нынешнем Minix 3.2.0 библиотеку Qt?

А я тем временем достал с пыльной полки бывший ноутбук брата, поставил там Minix 3.1.8 и решил вернуться к вогоплееру. По собственной же инструкции попытался собрать u-boot, использовал все те же binutils 2-16.1 и gcc 3.4.6. Если сами по себе они собрались нормально, в соответствии с инструкцией, то вот с u-boot произошло что-то непонятное.

Во-первых, он затребовал у меня заголовочные файлы из директории ./gcc/3.4.6/i686-pc-cygwin/includes — или что-то в этом духе. Это происходило еще на этапе сборки «утилит» типа bmp_logo, и занимался этим еще «родной» gcc. Я сначала немного офигел. В Minix 3.1.8 gcc иногда безбожно «тупит», так как прикручен к системе немного нестандартно, но используется все-таки версия 4.1.1, а «старая» 3.4.с чем-то может быть «доустановлена» из пакетов. Я сначала подумал, что возникли какие-то проблемы с «системными» библиотеками и заголовочными файлами — при их сборке ОС думает, что их надо положить в директорию для gcc 4.1.1, а gcc считает, что их надо искать в директории для другой версии.

Правда, посмотрев чуть-чуть повнимательнее, я обнаружил там упоминание cygwin и понял, откуда притащил бяку. Кроме того, слова Missing dependency уже не оставляли сомнений — «корни» ошибки растут из оставшихся в архиве с исходниками u-boot файлов .depend. Добавил в make clean команду на удаление этих файлов — и процесс пошел. В общем, что я там писал?

gmake volans_nand_config
gmake

Да как бы не так! Все остановилось с руганью на 95 строчку файла ./nand_spl/board/volans/start.S — якобы там junk after end of line, недостача скобок, ад и погибель. Строчка сама по себе вполне законная, что-то типа

.word SOMETHING_DEFINED_BEFORE

Пришлось немножко изучить, как gcc вызывает ассемблер. Оказывается, GNU as препроцессора не имеет и файлы с расширением .S сначала обрабатываются встроенным в gcc препроцессором по правилам Си, а затем передаются ассемблеру. Решил просто «препроцессировать» этот файл — как я понял, ассемблер ругается только на свой ввод. Может, там чего криминальное на 95 строке?

Препроцессировал, получил файлик в 50 с чем-то строк — и на что же ругаться? А при попытке ассемблировать его ругань вполне себе была. Правда, в комментариях специального вида было прописано, что и из какого файла взято. 95 строке start.S соответствовала такая, тоже вполне невинная:

.word ((2048==2048)&0xff0000) | ((2048!=512)&0xff00) | ((3==3)&0xff)

Но если эту строку закомментировать — то все работало! Точно так же, «вычеркивая» отдельные конструкции, я обнаружил, что причиной ругани была операция !=. Закомментировав «второй» блок, я получил «законный» start.s — но меня все же мучило, что же должно оказаться на месте (2048!=512), чтобы его можно было применять в побитовых операциях. Начал искать всякие руководства по GNU Assembler — и обнаружил, что операции != там не предусмотрено, а неравенство записывается в виде <>. Если неравенство верно, то на его месте в выражении окажется -1, если неверно — то 0. Заменив в определении SOMETHING_DEFINED_BEFORE != на <>, я получил заведомо правильный ассемблерный код.

Что интересно — при сборке pavo_nand_config ругани не возникало. Скорее всего, в своей инструкции тогда я наврал — либо в версии binutils, либо в том, что собрал работоспособный u-boot для volans. Для pavo — да, а вот вогоплееровский u-boot я не проверял.

В общем, вчера вечером что-то собралось, а сегодня я решил посмотреть, оно вообще запускается или нет. Достал чудо дизайнерской мысли, сдул с него пыль, подключил к компьютеру и даже успешно прошил. Включил, и что удивительно — «оно» заработало, включило экран и даже что-то там написало. А вот в консоль по RS-232 сыпался форменный бред. Правда, «туда» буковки уходили, и даже hello_world из комплекта u-boot оказался рабочим. В общем, явно происходило что-то странное.

Я уж было грешил на компилятор — чего он там мог соптимизировать, тем более, что в подобного рода «низкоуровневых» делах сплошь и рядом встречается, что компилировать надо одним-единственным рекомендованным компилятором, а все остальные попросту «компилируют» какой-то бред. Правда, мне показалось, что наличие и отсутствие бреда как-то связано с «втыканием-вытыканием» разъема. Решил проверить свои подозрения — и обнаружил, что проводок от UART к плате отвалился и лежит на ножках процессора — вот отсюда и идет этот «бред».

В общем, паять лучше надо. Ну а в целом — я более-менее восстановил toolchain на ноутбуке с Миниксом, так что можно и дальше «играть» с плейбоеплеером, не заморачиваясь неудобствами cygwin (потому что он действительно ужасен).

PS В cygwin u-boot компилируется полчаса, в Minix — за минуту.

Собираем toolchain для MIPS

Как конченый китаефоб, я попросту не доверяю тем toolchain-ам, которые можно скачать с сайта Ingenic. А как вымирающий миниксовод, просто-таки обязан использовать для разработки Minix.

На самом деле, правда, я решил использовать ноутбук с миниксом как машину для разработки по одной простой причине — Minix 3 сейчас представляет собой довольно странную систему с точки зрения набора средств разработки. Например, make в миниксе — это вариация на темы BSD make, а входящий в Cygwin (под которым я хотел работать сначала) GNU make не понимает «позаимствованные» из NetBSD makefile-ы ядра Minix. Собрать BSD make в Cygwin у меня не получилось, там есть какие-то нюансы, так что я решил портированием миникса заниматься на нем самом.

Естественно, что фирма Ingenic не подозревает о существовании такой ОС и «готовый» toolchain для него не выкладывает. Тем хуже для них, потому как компилятор и утилиты для MIPS ничего особо страшного не представляют. Я решил действовать по инструкции с linux-mips.org. Пока что я собрал только binutils и GCC, перспективы использования отладчика пока туманные (так что все дальнейшее превращается в некую авантюру). Успокаиваю себя тем, что в Minix 3 приличного отладчика тоже никогда не было, и ничего, живут люди.

Итак, для начала скачиваем рекомендованные на сайте версии binutils (2-16.1) и GCC (3.4.4). Думаю, что binutils можно и посвежее, а вот с выбором GCC лучше не торопиться. То, что другие называют «бета-версией», разработчики компилятора GNU считают самостоятельным релизом. Например, в магистерской работе Ингмара Альтинга про портирование Minix 3 на PowerPC специально обращается внимание, что GCC 3.4.6 нормально компилирует MinixPPC, а 4 версия (4.x.x) жестко косячит.

Перед сборкой определим некоторые переменные окружения.

export WDIR=/tmp
export TARGET=mipsel-unknown-linux-gnu
export PREFIX=/usr/local/mipseltools
export PATH="${PATH}":${PREFIX}/bin

Говорят, что в качестве $TARGET можно безболезненно использовать сокращенную запись того же самого — а именно, mipsel-linux, но я не проверял. Вообще, эта строка строится по правилу архитектура-компания-ядро-ОС или иногда — архитектура-компания-ОС, например, mips-sgi-irix6.

Для начала собираем binutils. Тут все без сюрпризов. Распаковываем, конфигурируем, собираем, устанавливаем.

tar xjf binutils-2.16.1.tar.bz2
mkdir build-binutils && cd build-binutils
../binutils-2.16.1/configure --target=$TARGET --prefix=$PREFIX
gmake
gmake install
cd ..

Обращу внимание, что вместо make надо вызывать gmake, в случае с binutils все прокатывает, а с gcc возможны ошибки из-за различия синтаксиса Makefile-ов.

C gcc придется немного повозиться. Во-первых, configure неверно определяет возможности системы, во-вторых, встроенные типы Minix конфликтуют с некоторыми локальными для gcc определениями. Итак, распаковываем и конфигурируем.

tar xjf gcc-3.4.4.tar.bz2
mkdir build-gcc-bootstrap && cd build-gcc-bootstrap
../gcc-3.4.4/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c --without-headers --with-gnu-ld --with-gnu-as --disable-shared --disable-threads

В файле gcc/auto-host.h убираем определения HAVE_GETRLIMIT и HAVE_MMAP_FILE. Кроме того, надо временно закомментировать в файле /usr/include/minix/types.h определение типа block_t. В одном из модулей gcc определяется собственный тип с таким же названием, не имеющий никакого отношения к блокам файловой системы Minix. После этого —

gmake
gmake install
cd ..

Работоспособность всей получившейся хрени можно проверить, собрав u-boot. Все очень просто — скачиваем его с VoGeeky (а можно, кстати, поставить git). Правда, придется поправить Makefile. Вместо конструкции

ifeq ($(ARCH),mips)
CROSS_COMPILE = mipsel-linux-
endif

пишем

ifeq ($(ARCH),mips)
CROSS_COMPILE = mipsel-unknown-linux-gnu-
endif

Теперь можно собирать (естественно, не забыв, что путь к тулчейну был добавлен в $PATH):

gmake volans_nand_config
gmake

После этого компилятор поработает-поработает и выплюнет вполне работоспособный загрузчик. Правда, придется перекинуть его на другую машину, чтобы засунуть в плату — дело в том, что в Minix то ли нет поддержки USB, то ли она в зачаточном состоянии. Соответственно, jzboot запустить не удастся. Ну а как перекидывать файлы — прекрасно написано в руководстве по сетевым возможностям Minix 3.

Vogue, U-Boot и дисплей

Сумел добавить поддержку дисплея в U-Boot для вогоплеера. Подробности потом, а пока объясните, как пользоваться git :)

Кстати, оценил то, как написан U-Boot и китайские дополнения к нему. Разобраться с тем, что и как наворотили наши узкоглазые друзья — еще та задачка.

Нашел багу

Немного поковырял китайский U-Boot, адаптированный для процессоров Ingenic. Помните, я писал, что там некорректно отрабатывает утилита bmp_logo?

Так вот, дело — в типично китайском коде. Как вы думаете, что напечатает программа?

int main(void){
    int l;
    FILE *in;
/* skipped some code */
    fread(&l, sizeof(uint16_t), 1, in);
    printf("l = %d\n", l);
/* skipped some code */
    return 0;
}

Естественно, что на всех более-менее современных машинах sizeof(int) > sizeof(uint16_t), то есть переменная l окажется просто неопределена — проинициализируются только первые два байта. На little-endian системах программа будет «корректно» работать, если l «автоматически» инициализируется нулем.

Несмотря на то, что в стандарте C ничего не сказано про инициализацию нулем локальных переменных, иногда такое происходит. Когда ОС выделяет память для новой программы, назначенные для нее страницы обнуляются — чтобы никакие вирусы-трояны не искали там логины-пароли. Как бы не было больно знатокам стандарта языка C, main — далеко не та функция, с которой начинается выполнение программы. Сначала вызывается библиотечная функция _start или аналогичная ей по назначению, специфичная для каждого компилятора и инициализирующая необходимые для работы стандартной библиотеки вещи (подумайте, например, как будет работать без инициализации malloc()).

Так вот, в Linux-системах можно надеяться на то, что локальные для main переменные окажутся на еще нетронутой части стека. Происходящее в Windows — гораздо более неясно, но там локальные переменные main «инициализируются» чем-то непонятным.

Кто виноват — ясно. А что делать? Нет, не надо писать int l = 0;. Хочу лишний раз напомнить о существовании big-endian систем. В них после вызова fread() шестнадцатибитное значение запишется не в два младших, а в два старших байта — и нетрудно догадаться, что мы хотели несколько другого.

К сожалению, описанные у Кернигана и Ритчи типы int, short и long имеют нерегламентированную длину. Гарантируются какие-то минимальные значения, и ничего более. int может запросто оказаться двух-, четырех- и даже восьмибайтовым. И как тут жить? Керниган и Ритчи придумали один возможный подход. Например, во всех Unix-системах принято, что «время» — это 32-битовое целое без знака. В time.h с помощью typedef определяется тип time_t, который в реальности может быть int (на 32-битных машинах) или long (на 16-битных). На 64-битной экзотике он вполне может оказаться и short. Определено несколько таких «стандартных типов» — и все.

Естественно, если подходить таким образом, то очень скоро мы начнем определять типы наподобие bmp_file_data_length_t — целое, соответствующее тому типу, в который помещается «длина данных» из bmp-файла. Не очень весело, правда? В современных реализациях C, стандарте C99 и C++0x предусмотрен заголовочный файл stdint.h, в котором определяются целые типы фиксированного размера. Например, uint16_t — это 16-битное беззнаковое целое.

Хорошим тоном считается использовать именно тот тип, который нужен в конкретном случае, особенно, когда речь идет о полях структур или других данных, размер которых четко определен. При переносе на другую платформу не придется биться с тем, что int внезапно стал вдвое длиннее :)

В общем, если бы безвестный китаец знал про типы фиксированного размера, он не стал бы использовать четырехбайтный int для хранения 16-битного значения и все были бы счастливы.

PS А вот еще вопрос. Что произойдет, если l объявить не в теле функции main(), а вне нее, как глобальную для данного файла?

Настоящее радиолюбительское

Сегодня речь пойдет о том, как писать свои (вах!) программы для быдлодевайса, более известного, как вогоплеер. Внимательные читатели моего блога помнят, что я обещал продолжить ковырять его в феврале, так что пора бы и написать что-то осмысленное.

Итак, я съездил на Митино, купил MAX3232, и даже два раза сделал небольшую платку-адаптер. Стандартная схема включения микросхемы MAX232 и ей подобных хорошо известна, и останавливаться на этом я не буду.

Немножко больше я напишу про местонахождение выводов UART на воговской плате. Если Tx хорошо виден и находится на контактной площадке между процессором и флешкой, то Rx нашли не все и не сразу. Как оказалось, эта нога UART-а объединена с левым контактом кнопки K1. Но это еще не все! Для нормальной работы последовательного порта надо еще и демонтировать конденсатор над кнопкой K3. Про это все подробно написано на гуглосайте VoGeeky в специальном разделе, посвященном UART.

Запаяв все соединения между платой плеера и адаптером, и вдоволь наругавшись на говенный спиртоканифольный флюс (все остальное, как назло, закончилось), я приступил к более приятным занятиям. Да, сидеть за компьютером и с умным видом пялиться в экран гораздо лучше, чем согнувшись в три погибели с лупой пытаться припаять провод в полтора квадрата к малюсенькой площадке сорокаваттным паяльником :)

Первым делом надо собрать U-Boot и примеры для него под нашу плату. К сожалению, редакция журнала Vogue не озаботилась тем, чтобы выложить где-нибудь конфиги U-Boot для этой платы, поэтому приходится использовать версию для китайской демо-платы Volans. Итак, используя настроенный toolchain, выполняем в директории с исходниками U-Boot (а где его взять, все уже знают) команды

make volans_nand_config
make

Пока U-Boot собирается, держим пальцы крестиком или пьем кофе — в общем, развлекаемся, как можем. По окончании «сборки» получаем все в той же директории файл u-boot-nand.bin, который надо «прошить» в устройство.

Для прошивки можно воспользоваться швейной машинкой Зингера, а можно — прошивальщиком USBboot китайского производства. И что характерно, прошивальщик работает только под Windows, да еще и 32-битным. Кто там советовал поставить «для разработки» Linux? Берем прошивальщик все на том же VoGeeky, в разделе «Прошивка ядра».

Теперь — физкультминутка! Одной рукой берем плату плеера и зажимаем на ней кнопку K1, второй рукой (помогая себе ногами и другими конечностями) подключаем USB-кабель к плееру. Получилось? Windows обнаружила неизвестное устройство с названием типа JZ4750 Boot Device? Молодцы!

После небольшой разминки устанавливаем драйвер. Если вы — пресловутый «опытный пользователь» Windows, то укажите установщику драйверов путь к файлу Usb_Boot_Driver.inf из комплекта USBboot. Если вы не понимаете, что написано в предыдущем предложении — зачем вы досюда дочитали? Дальнейшее можно смело прокручивать :)

Теперь, когда установлен драйвер устройства, можно смело запускать Test_jz4740_usb.exe, подкинув к нему в папку u-boot-nand.bin. Откроется окошко для ввода команд, в котором ничтоже сумнящеся вводим следующее:

boot 0
nerase 0 4096 0 0
fconfig USBBoot_nand.cfg 0
nprog 0 u-boot-nand.bin 0 0 -n

После успешного завершения прошивки подключаем вогоплеер к COM-порту, запускаем терминальную программу (лучше Hyper Terminal, настройки порта — 57600 бод, 8 бит данных, 1 стоповый бит, без проверки четности и управления потоком) и «перезагружаем» его передергиванием питания.

Если все настроено правильно, то в терминал вывалится вот такая «простыня» текста:

NAND Secondary Program Loader
Starting U-Boot ...
U-Boot 1.1.6 (Feb 1 2011 - 22:13:18)
Board: Ingenic VOLANS (CPU Speed 336 MHz)
DRAM: 32 MB
Flash: 0 kB
NAND:1024 MiB
*** Warning - bad CRC or NAND, using default environment
In: serial
Out: serial
Err: serial
Net: No ethernet found.
Hit any key to stop autoboot: 0
NAND read: device 0 offset 0x400000, size 0x300000
3145728 bytes read: OK
## Booting image at 80600000 ...
Bad Magic Number
VOLANS #

Все заканчивается приглашением к вводу. U-Boot — очень мощная программа, фактически — небольшая однозадачная операционная система, типа DOS или CP/M. Список команд можно посмотреть, набрав help, он достаточно велик, но сейчас нас больше всего интересует запуск «самописного» софта. При компиляции U-Boot автоматически «собрался» небольшой пример. Для его загрузки набираем команду loads, а затем загружаем текстовый файл hello_world.srec из поддиректории examples, находящейся там, где мы собирали U-Boot.

VOLANS # loads
## Ready for S-Record download ...
S705802000005A012080B00120804D03208080012080E6
## First Load Addr = 0x80200000
## Last Load Addr = 0x802003A7
## Total Size = 0x000003A8 = 936 Bytes
## Start Addr = 0x80200000
VOLANS #

Пользователи PuTTY, видимо, оказались в пролете. Самописный софт для U-Boot может использовать небольшую часть стандартной библиотеки C, реализованную в U-Boot. Этого хватает, например, для вполне осмысленного Hello, World. Запускаем его командой go 80200000.

VOLANS # go 80200000 Hello Ingenic World from shura@luberetsky.ru
## Starting application at 0x80200000 ...
Example expects ABI version 3
Actual U-Boot ABI version 3
Hello World
argc = 6
argv[0] = "80200000"
argv[1] = "Hello"
argv[2] = "Ingenic"
argv[3] = "World"
argv[4] = "from"
argv[5] = "shura@luberetsky.ru"
argv[6] = ""
Hit any key to exit ...
## Application terminated, rc = 0x0
VOLANS #

Думаю, теперь не составит труда написать что-то вроде 99 bottles of beer, ну а я более плотно займусь Minix-ом. Во всяком случае, теперь у девайса есть boot monitor в лице U-Boot’а и нормальная консоль в виде Hyper Terminal :) Что еще надо для запуска Unix-образной операционки?

Не выходит каменный цветок

MAX232 завелась от пониженного напряжения, но…

Как и предупреждал DI HALT и другие комментаторы в [info]ru_radio_electr, работать на высоких скоростях отказалась. А для меня это означает, что плюющийся отладочной инфой на адской скорости в 57600 бод вогоплеер так и останется «немым». Ехать на Митино мне по-прежнему лень, так что ближайший месяц буду платонически любить pavo через эмулятор.

Про U-Boot

Кстати, посмотрел документацию сабжа. Весьма кошерная тулза, ничуть не хуже USBBoot, прошитого в Ingenic-овские процессоры «по умолчанию». Если зашить во флешку только U-Boot, то можно вполне прилично работать с вогоплеером через COM-порт (например, «зашить» туда Linux). Вот только одна вещь пока мешает — я не уверен, можно ли использовать в качестве конвертера «логических» уровней MAX232 — эта микросхема согласно даташиту работает от 5В, а у нас на плате только 3,7В. Переться на Митино за повышающим преобразователем или MAX3232 (те же яйца, только трехвольтовые) мне неохота, так что буду экспериментировать.

toolchain для Ingenic’овских плат

Я уже успел рассказать людям, что занимаюсь портированием Minix 3 на Ingenic’овские процессоры, поэтому мне не удастся сделать вид, что я «пальцы крестиком держал» и ничего толком не делал. Надеюсь, что читающие этот пост не по диагонали уже прочитали всю китайскую документацию, и им не надо объяснять, где искать файл mips_toolchain_guide_EN.pdf. Больших откровений не будет, пишу я скорее для себя, чтобы не забыть последовательность правильных действий.

Итак, первоочередная задача — получить работающий кросс-компилятор, способный собрать исполняемые файлы для «китайского» MIPS. Задача осложнена тем, что занимается этим закоренелый виндузятник. Впрочем, для закоренелых виндузятников имеется такая замечательная вещь, как Cygwin.

Итак, начинаем с установки Cygwin-а. Это аналогичный MSYS «эмулятор» POSIX-совместимой системы, чем-то приглянувшийся китайцам — все утилиты из «комплекта разработчика» для Ingenic’а скомпилированы для Cygwin. Установка довольно проста, внесу от себя лишь одно дополнение — сразу же поставьте пакеты make и gcc. Они понадобятся при компиляции U-Boot.

Второй шаг — установка кросс-компилятора. Берем файл mipsel-gcc4.1-cygwin-nopic.tar.bz2 и распаковываем его в какую-нибудь директорию. Дальше добавляем ее в PATH:

export PATH='/some/path/mipseltools-v-1-2-3/bin':$PATH

После этого можно проверить его работоспособность «китайским» методом, с помощью компиляции helloworld.c — и наверное, даже нужно, подробнее читайте в mips_toolchain_guide_EN.pdf, а мы сделаем один шаг дальше — попробуем собрать U-Boot. Последняя его версия с правками от китайцев и «наших» разработчиков лежит в файловом архиве VoGeeky.

Я буду собирать версию всей этой гадости для pavo, поэтому выполняем команды

make pavo_nand_config
make

По какой-то мне пока непонятной причине некорректно работает утилита, создающая заголовочный файл с картинкой. make вываливается с ошибкой, если после нее попытаться продолжить, то ошибка возникнет в файле lcd.c. У меня не было желания разбираться с глюком, поэтому я пока обошел его так — добавил в конец файла include/bmplogo.h забытый #endif (и убрал оттуда сообщение об ошибке), а в файле common/lcd.c закомментировал все тело функции bitmap_plot().

После всех этих извращений U-Boot успешно собрался, а файл uboot-nand.bin прекрасно запустился в эмуляторе Pavo (только вот логотип не показал, что и логично).

Итак, я получил работающий toolchain, который может собирать софт для «голого» железа. Удивительно, но особых «подводных камней» не возникло. Дальше я немного поизвращаюсь на C для «голого» железа, без ОС, а затем вплотную займусь Minix’ом. Прежде всего придется продумать его загрузку. Я не хочу писать «вторичный загрузчик», работающий после U-Boot, но не хочу и переделывать «загрузочный образ» Minix. Наверное, это можно решить с помощью скрипта для U-Boot. Ну и bmp_logo.c подправлю, куда без него.

Про важность звукового сопровождения

Вот и я стал счастливым обладателем вкладыша от журнала Vogue с видеорекламой, за что безмерная благодарность отправляется в адрес тов. [info]dlinyj. Первым делом вкладыш был выдран из журнала, а затем и полностью разорван — ИМХО, гораздо удобнее «работать» с ним в таком виде.

На пустующие места вдоль края платы были запаяны более-менее подходящие кнопки, вместо датчика открывания страницы впаял перемычку. Включение-выключение девайса осуществляется кнопкой с подписью Power — крайней справа. Плату и аккумулятор прикрутил к дисплею синей изолентой. Для полного счастья надо заменить динамик на разъем для наушников. На штатное место в плате подходят разъемы из ассортимента «Бурого медведя», но ехать за ними до Нового Года неохота, а после — это уже очень отдаленное будущее, учитывая, что вся страна будет пить аж десять дней. В общем, получилось некое подобие видеоплеера, которым это чудо и было до попадания в лапы Americhip.

«Порадовало» то, что при включении плеера явно слышны наводки на звуковой тракт от цифровой части. Правда, звуки немного напоминают «шуршание» жесткого диска и вызывают ностальгические воспоминания про мой первый писюк (Pentium 120 MHz, 16 Mb RAM, 800 Mb HDD). За неимением версии Windows 95 для MIPS буду портировать туда Minix, а потом — Equinox Desktop Environment :)

PS Плата у меня Ылитного синего цвета :)

Еще про Pavo и ее эмулятор

На этой неделе не было времени особо разбираться, что же там косячит в эмуляторе Pavo, заметил только одну интересную вещь.

В настройках линуксового драйвера для NAND флешек есть возможность задать размер «логической» страницы. Например, в ядре Linux с сайта Ingenic он равен 4096 байтам + 128 байт «служебной информации», или OOB — out of band. «Физическая» страница используемой в Pavo флешки — это 2048 байт + 64 байта OOB, то есть «логическая» страница состоит из двух физических. Так вот, в ядре с сайта qemu-JZ размер логической страницы равен размеру физической и никаких «косяков» на данном этапе загрузки не происходит. Если подкинуть этому ядру ФС, собранную Ingenic-овцами, то ядро паникует на другом этапе — ФС не монтируется, и, соответственно, не находятся конфигурационные файлы.

Можно попробовать собирать файловую систему «напрямую» из tar, не «распаковывая» архив в локальную файловую систему (я пробовал — получается фигня, именно поэтому у konst.cranky не получилось «работающих» ФС). Времени у меня все равно мало, так что дальнейшие извращения с Ingenic-овскими чипами ждите после Нового Года.

В планах: собрать работающую ФС для тамошнего Linux и разобраться с toolchain-ом — как минимум, вывести в UART Hello, world!

Как я разобрался с эмулятором

В общем, в этот четверг я разобрался, почему не работал эмулятор qemu-JZ. К сожалению, мне так и не удалось запустить на нем Linux. U-Boot и ядро загружаются, но не удается получить работоспособную файловую систему. На некоторых из них с ошибкой валится стартовая проверка целостности флешки (это относится к ФС с сайта Ingenic), в сборках konst.cranky странным образом пропадают некоторые файлы (причем необходимые для запуска системы — в одном случае нет /bin/sh, в другом — /dev/console). Кроме того, удалось заставить китайскую утилиту для создания образа флешки работать в MinGW (а также написать свою, практически аналогичную) — надо явным образом добавить ко всем вызовам open() флаг O_BINARY.

Выложу, что ли, подправленные архивы с исходниками, желающие могут поковыряться. Qemu надо собирать, как описано на форуме qemu:

1. Установить MSYS, msysDTK, MinGW.
2. В MinGW установить или скомпилировать из исходников библиотеки directx-devel, SDL, zlib
3. Затем распаковать архив с qemu-JZ, выполнить ./configure --static --target-list=mipsel-softmmu, затем make.

После этого забираем из директории mipsel-softmmu готовый файл qemu-mipsel-softmmu.exe.

С поправленным jz-tools все еще проще. Распаковываем и собираем make-ом.

Файлы лежат у меня:

http://shura.luberetsky.ru/tools/qemu-JZ.rar
http://shura.luberetsky.ru/tools/jz_tools.rar

Кто хочет «поковырять» — берите. Подозреваю, что в qemu-JZ не совсем адекватно эмулируется флешка, оттого и глюки ядра Linux при ее проверке.

Кстати, насчет глюков на уровне ядра операционки. Если в любой нормальной ОС вылет драйвера файловой системы — это «тушите свет, сливайте воду» и полный kernel panic (в общем, что я и наблюдал), то в кошерном Minix паникеров расстреливает и заменяет свежими заградотряд, почему-то названный Reincarnation Server. Вчера «добился» сбоя драйвера VFS (Virtual File System) в Minix 3.1.8 — представьте себе, это совершенно незаметно, заглючивший драйвер моментально перезапустился. Все-таки микроядерность имеет свои преимущества.

Кроме того, в документации на процессорное ядро MIPS32 4Kc (оно совместимо с XBurst, но китайцы этого не афишируют, чтобы не платить лицензионные отчисления) написано о том, что предусмотрен специальный механизм, позволяющий не выгружать из MMU (Memory Management Unit) страницы, соответствующие ядру. Это позволяет избежать «дорогостоящего» переключения контекста, которое в более традиционных системах возникает при каждом вызове ядра и возврате в «пользовательский» процесс (а они у микроядер происходят часто). Надо поиграться, а то и сравнить производительность в обоих случаях.

Немножко закрытой документации

Нашел Ingenic-овский даташит на JZ4740. Не те жалкие две странички с «открытой» части FTP, а полное описание всей периферии на 70 с лишним страниц. Читать интересно. Не хватает только описания процессорного ядра (XBurst или JZ-RISC), пользуюсь таковым от MIPS32-4Kc. Придется, наверное, поэкспериментировать в плане поддержки MIPS-овских команд, или посмотреть, как некоторые вещи сделаны в коде эмулятора.

Про менеджеры закачек

Сегодня выкачал все с Ingenic-овского FTP. Есть несколько наблюдений по разным программам для закачки с FTP.

Первое. Качать большие файлы с плохого FTP браузером (любым) — себя не уважать. Все «современные» браузеры научились так ловко скрывать, за что же FTP-шник дал отлуп, что нельзя понять — или это произошло из-за необходимости ввода пароля, или из-за ограничения на число соединений.

Второе. Менеджеры закачек импортного пошиба, наподобие Offline Explorer — громадные и толстые «монстры», в которых можно делать буквально все — от обычного «веб-серфинга» до скачивания сайтов целиком — недалеко ушли от обычных браузеров. Я даже не говорю о том, что это чудо с интерфейсом в стиле MS Office 2007 не поддерживает такую функцию, как «докачка» или скачивание файла в несколько секций. То же самое касается и старенького Teleport Pro.

Третье. Равных не менее старенькому Reget Deluxe по «настойчивости» долбежки в сервер просто нет. Совершенно замечательная программа, а отдельно радует то, что наконец-то сделали полностью бесплатную «персональную» версию. Из ограничений — жестко вшитый русский язык и отсутствие «скинов».

Про qemu под Minix

Кстати, нашел среди миниксовских пакетов qemu версии 0.12.2. Может, попробовать собрать под ним qemu-JZ? В принципе, можно даже попытаться перенести все портирование миникса на JZ47xx в сам миникс. Где-то у меня валялся «ненужный» винчестер, так что можно и попробовать.

Извращение, конечно, но нынешним линуксом, по слухам, пользоваться реально скучно, примерно как 98 виндой.

Маленькое объявление

Похоже, делиться радостью по поводу успешного запуска эмулятора PAVO я буду не раньше пятницы — как-то настроения сейчас нет описывать его сборку.

Я люблю китайских программистов

Дело было не в бобине — раздолбай сидел в кабине :)

В общем, указанным в одном из предыдущих постов методом собирается вполне работоспособный qemu-JZ. Несмотря на то, что в нем «поломана» поддержка MIPS Malta, не говоря уже о других платформах, эмуляция PAVO получается «правильной». А теперь — как я это выяснил.

Прикрутить файлы от qemu-JZ к текуцей версии эмулятора получилось, но радости от этого было мало — черный экран и не более того. Даже U-Boot ничего не выводил в консоль. «Нехорошо» — подумал я и начал изучать образ флешки. Оказалось, что там от загрузчика, ядра и ФС присутствовала лишь первая страница, но повторенная много-много раз. Я удивился еще больше, посмотрел на код pavo_nandflash.c и понял — эта утилитка не может работать от слова «совсем». Большей кривости я не видел и за 20 минут написал практически аналогичную программу, создающую правильный образ флешки.

После этого увиделся U-Boot, стало грузиться и работать ядро — все замечательно, за исключением того, что собранная konst.cranky файловая система почему-то оказалась неполной — там напрочь отсутствует, например, директория /bin и все ее содержимое %)

Подробности и скриншоты — вечером :)

Китайский эмулятор

Кстати, выяснил, что «китайский» QEMU «совсем» испорчен и по крайней мере в Windows не умеет эмулировать MIPS — вообще никакой. Вчера пытался «с наскока» прикрутить файлы от «китайца» к более работоспособному QEMU, но неудачно. Буду тыкаться дальше. Больших результатов не обещаю — времени сейчас маловато, так что могу лишь порадоваться за людей из гугл-группы VoGeeky, которым удалось запустить на плате из Вога Linux.

Кстати, а не даст ли кто ссылку на документацию по «внутренностям» QEMU?

Выкачиваю Ingenic-овский FTP

Вчера поставил один граббер выкачивать все с FTP с документацией Ingenic-а. Как в известном анекдоте про китайских хакеров, со стопиццотой попытки, сервер согласился, что пароль — «Мао Цзе Дун». А если серьезно — тамошний FTP иногда в припадках безумия все-таки не спрашивает пароль на доступ к планой части документации и отдает ее «за так». Если долго и настойчиво долбиться — можно скачать много интересного. Например, на том сервере есть что-то про Android, файлы пока не скачались, но, чувствую, будет интересно.

Неудачный результат — тоже результат

Так и не выходит запустить эмулятор PAVO, скомпилированный под MinGW. Сам эмулятор, видимо, работает, но ничего, кроме черного экрана от него добиться не удалось. Как предлагает Библия, седьмой день недели надо посвятить Богу своему, поэтому, как русский православный человек, ничего делать в воскресенье я уже не буду (есть, конечно, те, кто начинает отсчет дней недели с воскресенья, по-американски, и посвящяет своему Б-гу субботу, но таких мы единогласно осуждаем). Для очистки совести напишу, с чем конкретно я столкнулся. Все это делалось в MinGW под Windows 7, так что «костыли и подпорки» касаются только этого «build environment».

Для компиляции QEMU я воспользовался пошаговой инструкцией с qemu-forum.ipi.fi, творчески ее модифицировав. Шаги с первого по пятый выполняем без изменений. Проблемой может стать поиск старой версии MinGW. Я нашел MinGW 3.1.0-1 на сайте Kudzu World.

Затем я установил пакет directx-devel, как описано на седьмом шаге, а при установке SDL столкнулся с трудностями — он не компилировался, какие-то странные глюки возникали при копировании файлов. Поэтому вместо восьмого шага руководства я скачал уже готовую библиотеку SDL 1.2.1.14 для MinGW с официального сайта. Распаковываем архив и выполняем make install.

Девятый шаг — установка zlib, там все нормально и соответствует инструкции. Дальше начинаются пляски с бубном. Скачиваем с jz-hacking исходники qemu-jz. Распаковываем, запускаем ./configure --target=mipsel-softmmu. Если теперь попытаться выполнить make, вылетит ошибка — используемая версия gcc не знает об одном из параметров командной строки. Поэтому в файлах config-host.mak и mipsel-softmmu\Makefile надо убрать параметр компилятора -Wendif-labels. Заодно в файле qemu-sockets.c на 155 и 273 строках надо заменить вызов функции gai_strerror на любую строку — этой функции почему-то нет в MinGW, да и не пригодится нам ее выдача. После этого делаем make. На этом qemu готов, перемещаем файлик qemu-system-mipsel.exe в какое-нибудь более пристойное место и подкладываем к нему SDL.dll.

Кстати, иногда configure «на ровном месте» спотыкается при определении наличия zlib. Не паникуем, а просто запускаем еще раз. Иногда просветление настигает железного болвана на третий-четвертый раз.

Теперь займемся изготовлением прошивки для флешки. Она состоит из трех частей — загрузчик на основе u-boot, ядро Linux и файловая система. Загрузчик и ядро Linux уже «собраны», их достаточно только скачать.

Файл u-boot-nand-pavo-20090207.bin переименовываем в u-boot-nand.bin, uImage-pavo-20090207 — в uImage.

Файловую систему предлагают построить из ее же, но заархивированной, с помощью утилиты mkyaffs2image, но не оригинальной версии, а чуть-чуть модифицированной. В MinGW собрать работающую версию мне не удалось, но konst.cranky любезно поделился собственноручно сделанным файлом, скачать его можно отсюда — http://files.mail.ru/6DBIGD.

Так или иначе, разжившись файлами u-boot-nand.bin, uImage и rootfs.yaffs2 складываем их в одно место и готовимся делать образ флешки. Для этого надо скомпилировать утилиту pavo_nandflash. Как водится, начнем продираться через dependency hell. Для утилиты требуется библиотека libconfuse. Займемся ее сборкой. Китайцы советовали версию 2.5, скачиваем ее в архиве и распаковываем. Дальше, казалось бы, все просто — ./configure, make — и тут спотыкаемся. В исходниках не предусмотрено, что бывают Win32-системы без dllimport — а конкретно, MinGW. Лезем в файл confuse.h и заменяем там конструкцию

# ifdef BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
# else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
# endif /* Not BUILDING_DLL */

на кошерную

#ifndef __GNUC__ /* Not MINGW */
# ifdef BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
# else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
# endif /* Not BUILDING_DLL */
#else /* MINGW */
# define DLLIMPORT
#endif /* MINGW */

Кроме того, надо отредактировать examples/Makefile — примеры использования библиотеки кривые и не компилируются. Заменяем all: all-am на

all:
  echo "foo"

В начале второй строки должен стоять Tab. Теперь с чистой совестью выполняем make и make install.

Теперь можно попытаться собрать утилиту от братьев-китайцев. Скачиваем архив, распаковываем, чистим от мусора.

wget http://jz-hacking.googlecode.com/files/jz_tools_20090207.tar.gz
tar zxvf jz_tools_20090207.tar.gz
cd jz_tools/nand_flash
make clean

В файле pavo_nandflash.c после всех define-ов добавляем typedef unsigned int uint32_t;. Теперь make моментально соберет pavo_nandflash.exe. Перекидываем его в директорию с «частями» прошивки и пишем файл pavo_nandflash.conf, примерно такой:

#
# pavo board nand flash configuration file.
# Copyright (C) 2008 yajin(yajin@vm-kernel.org)
#

# comment the unwanted part
flash_image = pavo-nand.bin

uboot_image = u-boot-nand.bin
uboot_start = 0x00000000
uboot_end = 0x00400000
uboot_add_ecc = 0

kernel_image = uImage
kernel_start = 0x00400000
kernel_end = 0x00800000
kernel_add_ecc = 0

rootfs_image = rootfs.yaffs2
rootfs_start = 0x00800000
rootfs_end = 0x08000000
rootfs_oob = 1
rootfs_add_ecc = 0

Запускаем исполняемый файл, получаем гигабайтный образ флешки — pavo-nand.bin. Подкладываем его к эмулятору и пытаемся запустить командой

qemu-system-mipsel -M pavo -mtdblock pavo-nand.bin

К сожалению, мне удалось получить лишь черный экран. С помощью Ctrl+Alt+(цифры) можно переключаться между несколькими «консолями» — в том числе и «монитором». Дамп памяти показывает, что u-boot загружается, а вот ядро Linux — уже нет.

Если кто-то будет более удачлив — то после загрузки ядра надо набрать в консоли runqpe, тогда запустится qtopia.

В общем, предлагаю желающим опробовать китайский рецепт на «полноценном» линуксе.

Просьба к товарищам линуксоидам

Извращаюсь с PAVO, благополучно собрав эмулятор. Точнее, пытаюсь извращаться — у меня не запускается собранный для него Linux. Я скачал u-boot и образ ядра, но не могу сделать файловую систему — MinGW не поддерживает symlink-ов и утилитка mkyaffs2image не хочет работать правильно. Может кто-нибудь выполнить описанные в Make the yaffs2 image шаги и выложить куда-нибудь получившийся файл rootfs.yaffs2?