iMX287 за 60 минут

Очень быстрый старт с платами на основе процессора iMX287 (семейство MX28 компании Freescale).

Описанную ниже виртуальную машину можно загрузить с Yandex диска (размер файла 9 Гбайт). Для работы с ней необходим VMPlayer, который можно загрузить с сайта www.vmware.com. Для программирования через USB понадобится утилита MFGTools, которую можно загрузить с Yandex диска. Архив также содержит собранные файлы загрузчика, ядра и файловой системы.

__________________________________________________________________

ОБНОВЛЕНИЕ от 28 февраля 2015 года

Виртуальная машина VMWare с

  • linux-3.10.20
  • u-boot 2014.01
  • imx-bootlets
  • buildroot-2014

Руководство пользователя к виртуальной машине.

__________________________________________________________________

 

Виртуальная машина о которой пойдет речь ниже предназначена для сборки загрузчика u-boot, ядра Linux и файловой системы (rootfs) для использования совместно с платами на процессоре MCIMX287 (Freescale):

  • EV-iMX287
  • EV-iMX287-Mini
  • EV-iMX287-Micro
  • EV-iMX287-NANO
  • EV-iMX287-SODIMM

Также в виртуальной машине присутствует системы для сборки:

  • LTIB
  • Buildroot
  • OpenWRT

В виртуальной машине запущены tftp сервер для возможности загрузки платы по сети и NFS сервер для организации сетевой файловой системы, которая может быть примонтирована к плате.

Загрузка процессора

Внутренний загрузчик процессора iMX287 умеет грузиться со следующих источников:

  • SPI Flash
  • NAND Flash
  • SD/MMC карта
  • USB (в режиме Device)

Непременным условием загрузки является специальный формат загружаемого фала *.sb. Проще говоря, к файлу загрузчика u-boot или ядра Linux uImage добавляется заголовок, в котором находятся настройки DDR2 контроллера и подсистемы питания процессора. При считывании загружаемого файла ROM загрузчик сначала считывает заголовок и инициализирует контроллер памяти и систему питания. Из этого следует, что для систем на процессоре iMX287 использование загрузчика u-boot является необязательным. Можно создать ядро Linux в sb формате и напрямую загружать его. Далее мы рассмотрим все варианты, и с загрузчиком u-boot и без него. Для упрощения работы в системе находятся исполняемые скрипты, которые запускают основные операции по сборке.

Виртуальная машина

В виртуальной машине все необходимое находится по пути /home/user/Projects:

/buildroot-2013.11 - система для сборки файловой системы (rootfs)

/linux-3.9.11 - исходники ядра версии 3.9.11

/ltib - система для сборки загрузчика u-boot-2009, ядра Linux 2.6.35  и файловой системы

/openwrt - популярная система сборки, в основном используется для сборки исходников для сетевых устройств (роутеров и т.п.)

/rootfs-buildroot - распакованная файловая система, сгенерированная с помощью buildroot, также содержит скрипты для записи на SD карту

/rootfs-debian - распакованная файловая система Debian (ARMEL версия), также содержит скрипты для записи на SD карту

/u-boot-2013.4 - исходники загрузчика u-boot

Необходимое

Для практических занятий потребуется плата на процессоре iMX287, компьютер с установленным VMPlayer, картридер для записи SD карт, любимая терминальная программа.

Подключаем кабель RS-232 к плате и компьютеру,  подключаем сетевой кабель к роутеру или напрямую к компьютеру. Также к компьютеру подключаем картридер.

Сборка u-boot-2013.4
Доступно три варианта конфига для сборки:
mx28evk - сохранение переменных на SD карту (или микросхему eMMC)
mx28evk_nand - сохранение переменных в микросхему NAND Flash
mx28evk_spi - сохранение переменных в микросхему SPI Flash

В виртуальной машине переходим в папку /home/user/Projects/u-boot-2013.4 и запускаем скрипт make_uboot_sb.sh. Результатом его сборки будет файл загрузчика u-boot в sb формате - u-boot.sb. Теперь запишем его на SD карту и попробуем загрузить плату. Как указывалось выше, в папке rootfs-buildroot находятся скрипты, которые позволяют записать на карточку u-boot, ядро и файловую систему. Для успешной записи файл загрузчика или ядра должны быть помещены в папку rootfs-buildroot/rootfs/boot под именами imx28_ivt_uboot.sb для загрузчика u-boot и imx28_ivt_linux.sb для ядра Linux.

С помощью скрипта copy_uboot_sb.sh, который находится в папке u-boot-2013.4 копируем и одновременно переименовываем файл u-boot.sb в папку rootfs-buildroot/rootfs/boot. Теперь вставляем карточку в картридер и запускаем скрипт write_uboot.sh находящийся в rootfs-buildroot. Поскольку скрипт запускается от имени суперпользователя (root) вам придется ввести пароль "123456" и ответить yes на запрос о записи на карту.

Сообщение Done! Plug the SD/MMC card into the i.MX board and power-on говорит нам о том, что процесс записи успешно завершен. Вытягиваем карточку, устанавливаем ее в плату, выбираем с помощью дип-переключателя режим загрузки с SD/MMC карты и подаем питание. Если все сделано правильно, в терминальной программе наблюдаем лог запуска загрузчика u-boot:

Нажатием любой кнопки прерываем загрузку.

Сборка ядра Linux версии 3.9.11

В виртуальной машине переходим в папку linux-3.9.11 и запускаем скрипт make_uImage_dtb.sh. Если необходимо внести какие-то изменения в конфигурацию ядра, предварительно запускаем скрипт make_menuconfig. Скрипт make_uImage_dtb.sh запустить процесс сборки ядра и файла конфигурации imx28-evk.dtb. После успешной сборки, созданные файлы uImage и imx28-evk.dtb c помощью скрипта copy_to_tftpboot.sh (или вручную) копируем в папку tftp сервера /tftpboot. Для загрузки файлов в плату нам также потребуется выяснить адрес tftp сервера, чтобы затем прописать его в плате. В виртуальной машине выполняем команду ifconfig и смотрим IP адрес адаптера

В моем случае это 192.168.0.2.

Опять включаем плату с уже собранным u-boot, нажатием любой кнопки прерываем загрузку и вводим переменные окружения (в вашем случае IP адреса могут отличаться):

MX28EVK U-Boot > setenv serverip 192.168.0.2  (указываем IP адрес сервера)
MX28EVK U-Boot > setenv ipaddr 192.168.0.115 (назначаем IP адрес нашей плате)
MX28EVK U-Boot > setenv ethaddr 00:11:22:33:44:55  (придумаем плате MAC адрес)
MX28EVK U-Boot > setenv bootcmd 'tftp 0x42000000 uImage; tftp 0x41000000 imx28-evk.dtb; bootm 0x42000000 - 0x41000000' (укажем командную строку, какие файлы и по какому адресу грузить)
MX28EVK U-Boot > saveenv (сохраняем введенные параметры)

Нажимаем кнопку сброса или вводим команду res для перезагрузки платы. Кнопки не нажимаем, наблюдаем процесс загрузки файлов по сети и старт ядра Linux:

Сейчас процесс загрузки закончится Kernel Panic, поскольку в u-boot не указано где находится файловая система и не найдя ее ядро выведет ошибку.

Файловая система это набор программ, утилит и т.п. Для пользователя OS Windows это почти тоже самое, что находится в папке /Program Files :)

Файловую систему можно собрать используя Buildroot, LTIB, OpenWRT и кучей других подобных систем. Но мы сборку отложим на потом, а пока воспользуемся сетевой файловой системой NFS.  В папке /tftpboot есть папка /rootfs (она кстати была создана с помощью Buildroot). Ее то мы и примонтируем. Для этого, нажмем кнопку сброс на плате и прервем запуск загрузки нажатием любой кнопки и введем строку аргументов:

MX28EVK U-Boot > setenv bootargs console=ttyAMA0,115200 fec_mac=00:08:02:6B:A3:1A root=/dev/nfs

nfsroot=192.168.0.2:/tftpboot/rootfs rw ip=dhcp rootwait gpmi (вместо 192.168.0.2 укажите свой адрес сервера) MX28EVK U-Boot > saveenv (сохраним переменные)

Перегружаем плату, наблюдаем процесс загрузки u-boot, загрузку файла ядра по сети

Файловая система примонтирована, вводим логин root и вы в системе.

Итак, загрузчик u-boot, ядро Linux собрано, файловая система примонтирована. Вот несколько подсказок для других случаев:

Если в папке rootfs-buildroot запустить скрипт write_uboot_rootfs.sh, то на карточку будет записан не только u-boot, но и файловая система (в раздел sdb3).

Для того чтобы ядро нашло и примонтировало файловую систему в данном случае, необходимо изменить строку аргументов в u-boot на следующую:

MX28EVK U-Boot > setenv bootargs console=ttyAMA0,115200 root=/dev/mmcblk0p3 rw rootwait ip=dhcp gpmi
MX28EVK U-Boot > saveenv

Ядро uImage и файл imx28-evk.dtb можно не только загружать по сети, а также например с USB Flash Drive, в этом случае командная строка выглядит так:

MX28EVK U-Boot > setenv bootcmd 'usb start; fatload usb 0:1 0x42000000 uImage; fatload usb 0:1 0x41000000 imx28-evk.dtb; bootm 0x42000000 - 0x41000000'
MX28EVK U-Boot > saveenv

или, если скопировать файлы uImage и файл imx28-evk.dtb на нашу SD карту в раздел sdb1 то можно загружать их с карты:

MX28EVK U-Boot > setenv bootcmd 'mmc dev 0; fatload mmc 0 0x42000000 uImage; fatload mmc 0 0x41000000 imx28-evk.dtb; bootm 0x42000000 - 0x41000000'
MX28EVK U-Boot > saveenv
Файловая система Debian

Кому-то может оказаться удобным использование стандартной файловой системы Debian. В виртуальной машине есть папка rootfs-debian, в которой находится минимальная файловая  система Debian. Скрипты находящиеся в данной папке полностью аналогичны вышеописанным.  Собранные вами u-boot или ядро должно быть размещено в rootfs-debian/boot,  обязательно в sb формате и с именами imx28_ivt_uboot.sb или imx28_ivt_linux.sb

Система без u-boot

Задача состоит в создании файла ядра в sb формате. Результатом запуска скрипта make_uImage_dtb.sh является создание файлов uImage и imx28-evk.dtb. Но кроме этого, также создается файл zImage (linux-3.9.11/arch/arm/boot), который нам и нужен. Итак, после сборки, запускаем скрипт make_zImage_dtb.sh. Он объединит два файла (zImage и imx28-evk.dtb) в один файл zImage_dtb.  Теперь запускаем скрипт make_sb_file.sh. C помощью утилиты elftosb он превратит zImage_dtb в файл imx28_ivt_linux.sb. Следующий скрипт copy_linuxsb_rootfs_buildroot.sh (или copy_linuxsb_rootfs_debian.sh) скопирует файл в нужную вам файловую систему  (rootfs-buildroot/boot или rootfs-debian/boot). Записать на SD карту созданное ядро и файловую систему можно с помощью скрипта write_SD.sh

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

Но что делать, если файловая система должна быть в другом месте (NAND Flash, SPI Flash, NFS)? u-boot у нас нет, куда вводить строку аргументов? На самом деле, строка есть, она вписана прямо в ядре, в том самом sb заголовке. И чтобы ее изменить, нам необходимо пересобрать, так называемый imx-bootlets, который генерирует код инициализации контроллера памяти и подсистемы питания. Поскольку imx-bootlets стандартно входят в систему сборки LTIB именно там и будем его пересобирать. Путь к imx-bootlets выглядит так /ltib/rpm/BUILD/imx-bootlets-src-2.6.35.3-1.1.0. Там можно найти четыре папки:

boot_prep

linux_prep

power_prep

mach-mx28

Нас интересует папка linux_prep, в которой имеется папка cmdlines и в ней файл iMX287_EVK.txt. Именно в нем хранится строка, которую нужно изменить в любом текстовом редакторе (или F4 в mc). На самом деле там четыре строки, но править нужно первую. Дело в том, что в imx-bootlets предусмотрена возможность при старте платы, нажимаю аппаратные кнопки подключенные к плате выбрать одну из четырех строк загрузки. Поскольку на наших платах данные кнопки отключены, то используется только самая первая, верхняя строка. После правки данного файла, необходимо пересобрать imx-bootlets запустив скрипт ltib/make_imx_bootlets.sh. Скомпилированные файлы boot_prep, linux_prep, power_prep надо скопировать в папку с исходниками ядра (linux-3.9.11/tools/elf2sb) заменив находящиеся там ранее такие же файлы. После чего выполнив скрипт linux-3.9.11/make_sb_file.sh создать новый файл imx28_ivt_linux.sb с новой строкой аргументов. Процесс записи на карточку, такой же ка и раньше.

NAND Flash, SPI Flash

Записать ядро (imx28_ivt_linux.sb) и файловую систему в NAND Flash можно разными способами. Компания Freescale имеет утилиту MfgTool.exe для операционной системы Windows, с помощью которой можно записать ядро и файловую систему через интерфейс USB. Плата подключается к компьютеру с помощью USB кабеля (на плате обязательно в порт USB0), с помощью дип-переключателя устанавливается режим загрузки с USB (0000) и далее с помощью утилиты MfgTool.exe происходит загрузка и запись в NAND Flash (можно адаптировать и для записи в SPI Flash).  В самом u-boot также имеются команды для работы с микросхемами памяти NAND Flash, SPI Flash. Ниже приведены команды для записи в микросхемы памяти в u-boot:

В u-boot-2013.4 есть встроенный скрипт для записи ядра или загрузчика в NAND Flash. Сначала необходимо задать имя файла который будем записывать в NAND Flash в переменной окружения

MX28EVK U-Boot > setenv update_nand_firmware_filename imx28_ivt_linux.sb  (будем писать ядро, обязательно в sb формате!)
MX28EVK U-Boot > saveenv
run update_nand_firmware  (эта команда загрузить по tftp файл imx28_ivt_linux.sb и запишет его в NAND Flash)

Для загрузки с NAND Flash устанавливаем дип-переключатель в положение (0010)

Для записи ядра в микросхему SPI Flash, в u-boot необходимо выполнить следующие команды:

MX28EVK U-Boot > sf probe 2 (подготавливаем SPI интерфейс)
MX28EVK U-Boot > sf erase 0x0 0x800000 (стираем память)
MX28EVK U-Boot > tftp 0x42000000 imx28_ivt_linux.sb (загружаем по tftp файл )
MX28EVK U-Boot > sf write 0x42000000 0x0 0x42000 (записываем в SPI Flash)

Для загрузки с SPI Flash устанавливаем дип-переключатель в положение (0100)

Удобно создать загрузочную SD карту с файловой системой,  после загрузки  которой будет вызываться скрипт реализующий запись ядра и файловой системы пользователя в NAND Flash. Вот пример данного скрипта (с созданием файловой системы в формате UBIFS), файл imx28_ivt_linux.sb и архив с файловой системой rootfs.tar находятся на обычной USB флешке:

mount /dev/sda1 /mnt   (монтируем USB флешку)
flash_eraseall /dev/mtd0 (стираем партицию 0, в ней будет находится ядро)
flash_eraseall /dev/mtd1 (стираем партицию 1, в ней будет находиться файловая система)
kobs-ng init /mnt/imx28_ivt_linux.sb (записываем ядро,  файл с флешки, примонтированной к /mnt)
ubiattach /dev/ubi_ctrl -d 0 -m 1
ubimkvol /dev/ubi0 -N rootfs0 -m
mkdir -p /mnt/ubi0
mount -t ubifs ubi0_0 /mnt/ubi0
tar xf /mnt/rootfs.tar -C /mnt/ubi0
sync
sync
umount /mnt/ubi0
Buildroot-2013.11

чтобы запустить меню конфигурации выполняем

make menuconfig

Выбираем пакеты которые необходимо собрать. Для запуска процесса сборки набираем

make

В результате  сборки будут созданы два архива rootfs.tar и rootfs.tar.gz в папке /buildroot-2013.11/output/images. Оба они являются запакованной файловой системой. Использовать можно любой из архивов.  В папке /buildroot-2013.11/output/target будет находиться распакованная файловая система.

OpenWrt

Аналогично, чтобы запустить меню конфигурации выполняем

make menuconfig

Выбираем пакеты которые необходимо собрать. Для запуска процесса сборки набираем

make

Если в процессе сборки возникнут ошибки, можно запустить сборку с выводом дополнительной информации

make V=s

В результате сборки в папке /openwrt/staging_dir/target-arm_v5te_uClibc-0.9.33.2_eabi/root-mx28  будет находится собранная файловая система, которую можно записать на карточку (запустив скрипт /openwrt/staging_dir/target-arm_v5te_uClibc-0.9.33.2_eabi/mk_mx28_sd) или в микросхему NAND Flash.

LTIB

Процесс сборки загрузчика u-boot-2009, ядра 2.6.35 и файловой системы был достаточно подробно описан в разделе Wiki. Напомним основные команды:

Все команды выполняются в папке /ltib. Запустить меня конфигурации и сборки:

./ltib -c

Создать sb файлы imx28_ivt_linux.sb и imx28_ivt_uboot.sb

./ltib -p boot_stream.spec -f

В результате сборки в папке /ltib/rootfs/boot будут созданы файлы загрузчика и ядра в sb формате imx28_ivt_linux.sb и imx28_ivt_uboot.sb. В зависимости от настроек создания файловой системы в /ltib будут находиться файлы rootfsext2.gz, rootfs.jfss2, rootfs.tar.gz представляющие собой запакованную файловую систему в разных форматах.

Использование утилиты MFG Tools для записи собранных файлов в целевую плату.

1.На плате устанавливаем режим загрузки с USB.

2.Подключаем кабель USB A-A к компьютеру и в порт USB0 платы

3.Подаем питание на плату

4.Запускаем утилиту MFG Tools

(для модуля EV-iMX287-NANO у которого нет дип переключателей для выбора режима загрузки,  подключаем пинцетом контакт RE на землю и подаем питание).

В MFG Tools заходим в Options -> Configuration и щелкнув по крайнему правому столбцу выбираем что и куда записать.

Все стратегии режимов записи можно посмотреть и создать собственные в файле ucl.xml

Файлы находящиеся в \Profiles\MX28 Linux Update\OS Firmware\files\ можно заменять на собственные и записывать.

кратко о именах файлов:

...uboot_mmc - загрузчик с переменными на SD карте

...uboot_nand - загрузчик с переменными в NAND Flash

...uboot_spi - загрузчик с переменными в SPI Flash

...linux3.sb - ядро версии 3.xx  (в inittab должно быть указано ttyAMA0)

...linux.sb - ядро версии 2.6.35 (в inittab должно быть указано ttyAM0)

Утилиту MFGTools с собранными файлами можно загрузить здесь.

Изменение MAC адреса платы

Для хранения байт 2-5 MAC адреса предназначен регистр HW_OCOTP_CUST0. Изначально в нем находится значение 0x00000000. Байты 0-1 заполняются в борд файле значениями 00:04. Можно просто изменить значения в борд файле загрузчика или ядра. Например в борд файле ядра 3.9.11 (mach-mxs.c)

Или же, с помощью утилиты BitBurner запрограммировать их в области efuse процессора. Ниже описывается данный процесс:

С сайта Freescale загружаем саму утилиту, называется она у них IMX_OTP_TOOLS, распаковываем архив на компьютере, подключаем плату, переводим ее в режим загрузки по USB (DIPSWITCH = 0000) и запускаем саму утилиту BitBurner. В выпадающем списке слева перебираем устройства HID пока не наткнемся на плату. Разработчики утилиты не сильно напрягались, здраво рассудив, что перебрать пару десятков устройств - дело 5 минут. Вот так выглядит утилита с найденной платой.

Теперь слева, в списке регистров выбираем нужный нам HW_OCOTP_CUST0. Его значение в незапрограммированной плату равно 0x00000000. Вписываем нужный нам MAC адрес и нажимаем кнопку Write.

Крайне категорически не рекомендуется что-либо менять в других регистрах без понимания процесса. Настроек там очень много и неосторожным движением очень легко заблокировать процессор или перевести его в режим, когда он перестанет грузиться так как надо. Закрываем утилиту, выставляем нужный нам режим загрузки и запускаем плату. После загрузки ядра, командой "ifconfig -a" смотрим наши настройки сетевых интерфейсов. Из картинки видно, что интерфейс ETH0 имеет вписанный нами MAC адрес, а ETH1 имеет увеличенный на единицу.