Для работы нам потребуется:
- подготовленная виртуальная linux машина
- исходники ядра (а вот тут есть варианты : либо репозитарий с repo.or.cz либо с диска в комплекте - подробности в теме про сборку ядра )
- полный комплект проводов подключения (Serial, USB, Ethernet)
- по желанию карту SD
особенности rootfs на flash
Особенность размещения корневой файловой системы на устройствах flash (как NAND встроенная так и SD внешняя) заключается в том, что файловая система должна быть особой - она должна понимать что флешки записываются кратными блоками, а стираются вообще страницами.
Если файловая система будет обычной (ext2,ext3,raiserfs), то для записи одной страницы флеша она сделает количество обращений по числу блоков, тем самым в десятки раз уменьшив срок службы микросхемы от возможного.
Учитывая что количество циклов перезаписи не очень велико ~100000 то убивание флешки за месяц интенсивной работы близко к 100%
Я лично убил NAND на одном из ранее разрабатываемых устройств за одну неделю разместив своп файл на обычной файловой системе
Другой особенностью является факт того что на NAND нормой является наличие BAD блоков, и файловая система должна уметь их обходить. Поскольку обход бэдов изначально проводился по цепочке в момент каждого подключения файловой системы и занимал много времени (так было в jffs) были придуманы методы сохранения информации о статусе файловой системы - вроде как она проверена по цепочке и новых сбойных секторов не обнаружено. Инфа о статусе появилось в jffs2.
У jffs2 есть ещё ряд интересных фишек навроде сжатия на лету, но это предмет отдельной статьи.
Есть ещё более современная файловая система для флешек - yaffs, она немного по другому работает и её есть смысл применять на объёмах от 64MB NAND и выше.
По сути применение yaffs для нас более предпочтительно НО, пока этой файловой системы нету в официальной ветке ядра, я не буду её рассматривать, тем не менее помнить о ней нужно. Вероятно скоро она станет стандартом и войдет в ядро.
Краткое описание действий
В статье я опишу каким образом мы можем подготовить файловую систему jffs2 и разместить её на mini2440
Рассматривать кросс сборку файловой системы здесь не буду, это отдельная тема.
Предлагаю экспериментировать с имеющимся на диске контролера архивом файловой системы для qtopia ( linux/arm-qtopia-20100108.tar.gz)
Я буду рассматривать самый сложный случай когда нам потребуется разместить rootfs.jffs2 на максимально возможное место в NAND разделе rootfs (или root в некоторых версиях u-boot)
Сложность заключается в том что писать с какого либо порта непосредственно в NAND не позволяет функционал загрузчика, а объем свободной оперативной памяти для загрузки блока под запись в несколько раз меньше объёма NAND.
Следовательно подготовленный файл образа корневой системы мы будем дробить на куски и писать частями, тчательно рассчитав смещения
Итак приступим
Начнем издалека...
Подготовка linux машины для работы с mtd блочными устройствами.
Для сборки образа файловой системы на хостовой x86 машине нам потребуется съэмулировать флешку в оперативке.
для этого ядро должно иметь соответствующие модули:
# modprobe block2mtd
# modprobe mtdblock
# lsmod
если в выводе есть что то типа
mtdblock 4224 0
mtd_blkdevs 6272 1 mtdblock
block2mtd 5888 0
mtdpart 7168 1 block2mtd
mtdcore 5252 4 mtd_blkdevs,block2mtd,mtdpart
то они у нас имеются, но вероятнее всего их нету
поэтому пересобираем модули ядра для включения соответствующей поддержки:
(это прямая! не кросс компиляция)
# cd /usr/src/linux
# zcat /proc/config.gz > .config # здесь мы получам конфигурацию текущего ядра, эта возможность может не поддерживаться ядром или вы и так знаете что текущий конфиг ядра актуален - тогда пропускаем
# make menuconfig
нужно включить следующие опции:
1) MTD
mtd support
CONFIG_MTD
2) MTD
caching block device access to MTD devices
CONFIG_MTD_BLOCK
mtdblock
3) MTD/Self-contained MTD device drivers
emulation using block device
CONFIG_MTD_BLKMTD
blkmtd
4) File systems
Journalling Flash File System v2 (JFFS2) support
CONFIG_JFFS2_FS
jffs2
у меня это как то так:
ну и после сохранения новой конфигурации собираем новые модули и ставим их в систему
# make -j 3 modules
# make modules_install
ещё нам потребуются утилиты для работы с mtd
на gentoo это делается так:
# emerge sys-fs/mtd-utils
на других линуксах нужно будет поискать соответствующий пакет самостоятельно (вроде тут
подготовка хостовой машины закончена,
переходим к расчётам адресов и смещений
MINI2440 # mtdparts
device nand0 <mini2440-nand>, # parts = 5
#: name size offset mask_flags
0: u-boot 0x00060000 0x00000000 0
1: u-boot_env 0x00020000 0x00060000 0
2: kernel 0x00500000 0x00080000 0
3: splash 0x00020000 0x00580000 0
4: rootfs 0x07a60000 0x005a0000 0
здесь важными явлеются начало рутовой файловой системы и её размер
свободного места в NAND меньше заявленного на BAD — блоки
MINI2440 # nand info
Device 0: NAND 128MiB 3,3V 8-bit, page size 2048, sector size 128 KiB
а здесь мы узнаем какими блоками ведется запись на NAND (2048=0x800) и какими размерами страницы происходит стирание (128k=131072=0x20000)
MINI2440 # nand bad show
Device 0 bad blocks:
04d20000
07f80000
07fa0000
07fc0000
07fe0000
здесь 4 сбойных блока приходится на rootfs это 4* 0x20000 = 0x80000
значит реальный размер rootfs = 0x7a60000 — 0x80000 = 0x79E0000 = 124800k
подготовим чистый образ jffs2 нужного размера
# cd /tftproot # я сразу работаю в этом каталоге чтобы потом загружать с tftp без лишнего переписывания
# dd if=/dev/zero bs=1k count=124800 | tr '\000' '\377' > ./root_qtopia.jffs2 # это такой линуксовый трюк для эмуляции свежеформатированной jffs2
далее смонтируем полученный образ в систему
# losetup /dev/loop0 root_qtopia.jffs2
# mkdir rootfs # здесь будет смонтирован образ
# modprobe block2mtd # здесь ядро должно иметь модули
# modprobe mtdblock # для работы с mtd устройствами
# echo /dev/loop0,131072 > /sys/module/block2mtd/parameters/block2mtd # здесь 131072 = 128k (sector size)
# cat /proc/mtd # проверяем
dev: size erasesize name
mtd0: 07a60000 00020000 "block2mtd: /dev/loop0"
# mount -t jffs2 /dev/mtdblock0 ./rootfs # и наконец собственно монтируем
# mount # проверка
/dev/mtdblock0 on /tftproot/rootfs type jffs2 (rw)
далее производим
перенос имеющихся файлов рутовой файловой системы в смонтированый образ
копируем и разворачиваем архив linux/arm-qtopia-20100108.tar.gz с диска контроллера (или подготавливаем свою сборку):
# tar -xvzf ./arm-qtopia-20100108.tar.gz -C /tftproot/root_qtopia
делаем перенос файловой структуры с сохранением прав:
# cd /tftproot/root_qtopia
# tar cpjf - ./* | (cd /tftproot/rootfs/ ;tar xvjpf - )
здесь желательно добавить в готовую файловую систему все модули от вашего ядра
они должны лечь в каталог lib/modules/{номер ядра}...
# umount /tftproot/rootfs
теперь файл /tftproot/root_qtopia.jffs2 содержит требуемую нам файловую систему
прежде чем его писать на NAND проверим его работоспособность по сети:
загрузка образа jffs2 через NFS
подготовим подсистему экспорта NFS на хост машине:
# echo "/tftproot 192.168.0.0/16(rw,no_root_squash,sync,no_subtree_check,nohide,crossmnt,insecure_locks)" > /etc/exports
# exportfs -a
# /etc/init.d/nfs restart
MINI2440 # setenv ipaddr 192.168.150.33
MINI2440 # setenv serverip 192.168.150.65
MINI2440 # setenv bootargs console=ttySAC0,115200 noinitrd init=/sbin/init mini2440=3tbc nfsroot=192.168.150.65:/tftproot/root_qtopia.jffs2 root=/dev/nfs rw rootfstype=jffs2 ip=192.168.150.33
разумеется вам нужно поставить свои параметры для ip контроллера и сервера (хост машины)
отдельное внимание параметру mini2440=3tbc здесь говорится использовать LCD 3го типа (T35), активировать тачскрин, включить подсветку, включить CMOS камеру
MINI2440 # setenv bootcmd 'nboot.e kernel ; bootm'
MINI2440 # saveenv
перегружаем контроллер...
если всё загрузилось - можно резать на кусочки и записывать на устройство
не буду вас мучать математикой, и так статья тяжелая для понимания
просто поделюсь скритом который сделал для себя
он разрезает на кусочки образ файловой системы
split_rootfs.sh
- Код: Выделить всё
#!/bin/bash
IF=root_qtopia.jffs2 # входной файл
OF=qtopia # общее имя кусочков
dd if=$IF of=$OF.1 skip=0 bs=1k count=24576
dd if=$IF of=$OF.2 skip=24576 bs=1k count=24576
dd if=$IF of=$OF.3 skip=49152 bs=1k count=24576
dd if=$IF of=$OF.4 skip=73728 bs=1k count=24576
dd if=$IF of=$OF.5 skip=98304 bs=1k count=24576
dd if=$IF of=$OF.6 skip=122880 bs=1k count=24576
так проводится прошивка NAND кусочками:
скрипт требует внимательной доработки, он для примера
можно оптимизировать задержку времени оставленное на операцию записи NAND
так же внимательно проверяйте соответствие таблицы разделов NAND тому что у вас определено в u-boot
если убрать параметр mtdparts= то разбивка будет той что по умолчанию принята в ядре, это может отличаться от реального (смотри логи запуска ядра)
/dev/mtdblock4 у меня потому что введен раздел splash (по умолчанию его нету и этот параметр root=/dev/mtdblock3)
- Код: Выделить всё
#!/bin/bash
MINI2440_TTY=/dev/ttyUSB0
PARTNAME="qtopia"
echo "nand erase rootfs" > $MINI2440_TTY
sleep 30
dfu-util -a 0 -D $PARTNAME.1
echo "nand write.e 0x32000000 0x005a0000 \${filesize}" > $MINI2440_TTY
sleep 30
dfu-util -a 0 -D $PARTNAME.2
echo "nand write.e 0x32000000 0x1DA0000 \${filesize}" > $MINI2440_TTY
sleep 30
dfu-util -a 0 -D $PARTNAME.3
echo "nand write.e 0x32000000 0x35A0000 \${filesize}" > $MINI2440_TTY
sleep 30
dfu-util -a 0 -D $PARTNAME.4
echo "nand write.e 0x32000000 0x4DA0000 \${filesize}" > $MINI2440_TTY
sleep 30
dfu-util -a 0 -D $PARTNAME.5
echo "nand write.e 0x32000000 0x65A0000 \${filesize}" > $MINI2440_TTY
sleep 30
dfu-util -a 0 -D $PARTNAME.6
echo "nand write.e 0x32000000 0x7DA0000 \${filesize}" > $MINI2440_TTY
sleep 30
echo "setenv bootargs console=ttySAC0,115200 noinitrd init=/sbin/init mini2440=3tbc root=/dev/mtdblock4 rootfstype=jffs2 mtdparts=s3c2440-nand:384k@0(u-boot),128k(u-boot_env),5m(kernel),128k(splash),-(rootfs)" > $MINI2440_TTY
sleep 1
echo "setenv bootcmd 'nboot.e kernel ; bootm'" > $MINI2440_TTY
sleep 1
echo "saveenv" > $MINI2440_TTY
sleep 1
echo "reset" > $MINI2440_TTY
вообще этот скрипт в первый раз лучше запускать руками построчно и с секундомером ...
ну и кратко про выгрузку с SD на NAND
SD карта, раздел один большой FAT32
заливаем туда наши кусочки
переносим на mini2440
MINI2440 # mmcinit
MINI2440 # fatls mmc 0:1
MINI2440 # nand erase rootfs
MINI2440 # fatload mmc 0:1 0x32000000 qtopia.1
MINI2440 # nand write.e 0x32000000 0x005a0000 ${filesize}
MINI2440 # fatload mmc 0:1 0x32000000 qtopia.2
MINI2440 # nand write.e 0x32000000 0x1DA0000 ${filesize}
MINI2440 # fatload mmc 0:1 0x32000000 qtopia.3
MINI2440 # nand write.e 0x32000000 0x35A0000 ${filesize}
MINI2440 # fatload mmc 0:1 0x32000000 qtopia.4
MINI2440 # nand write.e 0x32000000 0x4DA0000 ${filesize}
MINI2440 # fatload mmc 0:1 0x32000000 qtopia.5
MINI2440 # nand write.e 0x32000000 0x65A0000 ${filesize}
MINI2440 # fatload mmc 0:1 0x32000000 qtopia.6
MINI2440 # nand write.e 0x32000000 0x7DA0000 ${filesize}
MINI2440 # setenv bootargs console=ttySAC0,115200 noinitrd init=/sbin/init mini2440=3tbc root=/dev/mtdblock4 rootfstype=jffs2 mtdparts=s3c2440-nand:384k@0(u-boot),128k(u-boot_env),5m(kernel),128k(splash),-(rootfs)
MINI2440 # setenv bootcmd 'nboot.e kernel ; bootm'
MINI2440 # saveenv
вот такая статейка получилась на 10 строчек ...
---
добавлено 8.09.10
перенос работающей файловой системы на SD
- Код: Выделить всё
mini2440 / # mkfs.reiserfs /dev/mmcblk0p1
mini2440 / # mkdir /mnt/sd
mini2440 / # mount /dev/mmcblk0p1 /mnt/sd/
mini2440 / # cd / <-- для линукс хоста здесь перейти в рут каталог
mini2440 / # tar cpf - ./bin ./dev ./etc ./home ./lib ./media ./opt ./packages ./root ./sbin ./usr ./var | (cd /mnt/sd; tar xvpf - )
mini2440 / # rm -rf /mnt/sd/dev/.udev
mini2440 / # mkdir /mnt/sd/proc
mini2440 / # mkdir /mnt/sd/sys
mini2440 / # mkdir /mnt/sd/tmp
mini2440 / # mkdir /mnt/sd/mnt
в uboot:
- Код: Выделить всё
MINI2440 # setenv bootargs console=ttySAC0,115200 noinitrd init=/sbin/init mini2440=3tbc root=/dev/mmcblk0p1 rootdelay=2 rootfstype=reiserfs
MINI2440 # saveenv