2016-01-09

vak: (Улыбка)
Я уже писал про появившуюся на днях в продаже платку с Wi-Fi по цене $13. Она поставляется с уже предустановленным Линуксом OpenWRT и языками программирования Lua и Python. Это здорово, но объем памяти и наличие карточки microSD позволяют запустить кое-что более серьезное, а именно полный Debian Linux. Чем мы и займемся.

Шаг 1: обновляем ядро. Зачем это нужно - я объясню ниже. Скачиваем файл LinkIt7688-sysupgrade-3.18.23.zip и распаковываем его в корень Flash-диска, имеющего разъем micro-USB. Должен получиться файл с именем lks7688.img. Годится любой диск с файловой системой FAT32, главное, чтобы он втыкался в микро-USB (как на Android-телефоне). Вставляем этот диск в разъем "HOST" платы, и подаем питание на разъем "PWR". Затем держим кнопку "WiFi" и нажимаем-отпускаем кнопку "MPU". Через пять секунд отпускаем кнопку "WiFi". Обновление занимает примерно три минуты, пока красная лампочка не перестанет мигать. После этого USB-диск отключаем, он больше не понадобится. Подробно процесс обновления firmware описан в главе 4.6.1 руководства LinkIt Smart 7688 Developer's Guide (PDF).

Шаг 2: готовим microSD-карточку. Тут понадобится линуксный компьютер. Скачиваем файл debian-jessie-mini.tgz - минимальный вариант корневой файловой системы для Debian 8 (jessie). Вставляем карточку microSD в компьютер, непосредственно (есть есть слот SD) или через USB-адаптер. Карточка будет видна в системе как /dev/mmcblk0 или как /dev/sdc (или sdb или с другой буквой - проверьте). Нужно карточку отмонтировать, переделать таблицу разделов, создать новую файловую систему, заново смонтировать и распаковать туда файлы. Выглядит это примерно так:

    $ sudo umount /dev/mmcblk0p1
    $ sudo fdisk /dev/mmcblk0
    [подробности здесь]
    $ sudo mke2fs /dev/mmcblk0p1
    [...]
    $ sudo mount /dev/mmcblk0p1 /mnt
    $ sudo tar xzf debian-jessie-mini.tgz -C /mnt
    $ sudo umount /mnt


Шаг 3: подсоединяем консольный порт. Используем любой адаптер USB-to-serial, например FT232, CP2102 или CH340. Сигнал GND адаптера соединяем с ножкой GND платы, сигнал TXD - с ножкой P9, RXD - P8. Включаем USB-адаптер в компьютер и подключаемся к консольному порту на скорости 57600. Нажимаем кнопку "MPU" - видим протокол загрузки типа этого.

Шаг 4: настраиваем подключение Wi-Fi. Устанавливаем нужные пакеты, создаем раздел swap. Заметьте: мы никоим образом не портим исходную предустановленную систему OpenWRT. Все имеющиеся функции и методы разработки, описанные в руководстве для платы Linkit Smart, продолжают работать.

    uci set wireless.sta.ssid=Ваша-сеть
    uci set wireless.sta.encryption=psk2
    uci set wireless.sta.key=ваш-пароль
    uci set wireless.sta.disabled=0
    uci commit
    wifi
    [ждем около минуты, когда появится связь]
    opkg update
    opkg install swap-utils block-mount nano
    mkswap /dev/mmcblk0p2
    swapon /dev/mmcblk0p2


Шаг 5: стартуем среду Debian. Для этого мы используем утилиту chroot. Корневая файловая система Debian находится на карточке microSD. Ее всегда можно вынуть и переставить в другой компьютер: переписать нужные файлы, сдублировать, забэкапить и т.п. В принципе, когда заработал Wi-Fi, консольный порт больше не нужен - можно подключаться через ssh (предварительно установив пароль на root).

    root@mylinkit:/# mount --bind /dev /tmp/run/mountd/mmcblk0p1/dev
    root@mylinkit:/# mount --bind /proc /tmp/run/mountd/mmcblk0p1/proc
    root@mylinkit:/# mount --bind /sys /tmp/run/mountd/mmcblk0p1/sys
    root@mylinkit:/# chroot /tmp/run/mountd/mmcblk0p1 /bin/bash
    root@mylinkit:/# _


Последнее приглашение - это уже bash из окружения Debian. Здесь при первом запуске имеет смысл сгенерировать нужные локали и установить полезные пакеты:

    echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen
    locale-gen
    apt-get update
    apt-get install locales bison byacc flex libelf-dev libfuse-dev \
        build-essential make autoconf automake libtool gdb fuse man-db \
        groff less ed bmake git byacc flex exuberant-ctags libfuse-dev \
        bmake git byacc flex exuberant-ctags libfuse-dev dialog \
        openssh-client subversion le vim gettext iputils-ping locate procps


Теперь у нас имеется полноценный Debian Linux, со всеми наворотами, и Wi-Fi подключением к интернету. Можно скачивать, компилировать и запускать любой софт. И все это на платке размером 2x5.5 сантиметров. В следующем посте я напишу про измерение скорости процессора посредством стандартного теста Dhrystone.

Чтобы освободить карточку перед тем как вынуть, надо будет выполнить:

    umount /tmp/run/mountd/mmcblk0p1/dev
    umount /tmp/run/mountd/mmcblk0p1/proc
    umount /tmp/run/mountd/mmcblk0p1/sys
    umount /tmp/run/mountd/mmcblk0p1
    swapoff /dev/mmcblk0p2


Зачем надо было обновлять ядро на шаге 1? Дело в том, что версия ядра, предустановленная на плате, не позволяет выполнять программы непосредственно с SD-карточки. Не то чтобы запрещает, но такие программы не работают. Это связано с особенностями работы кэша на этом чипе. Когда драйвер SD-карточки читает сектор кода программы, часть данных оседает в D-кэше и не успевает попасть в память. Когда процессор начинает выполнять эту страницу, он получает старое содержимое памяти. То есть код из D-кэша не попадает в I-кэш. Это не ошибка, а особенность функционирования данного типа кэша. Просто ядро должно об этом знать и в нужный момент сбросить содержимое кэша, соответствующего конкретной странице. В системе команд MIPS даже есть специальная инструкция для этого (SYNCI). Чтобы исправить ситуацию, надо в одном их файлов ядра Linux, а именно arch/mips/include/asm/cacheflush.h, пустую функцию flush_icache_page() заменить на:

static inline void flush_icache_page(struct vm_area_struct *vma, struct page *page)
{
    if (cpu_has_dc_aliases || ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc)) {
        __flush_dcache_page(vma, page);
    }
}


После этого все отлично работает. Эта правка есть в очереди на внесение в ядро версии 4.x, но в 3.18 она не попала.
vak: (Улыбка)
Установив Debian, скачиваем исходники теста Dhrystone и измеряем скорость процессора MediaTek MT7688, установленного на плате LinkIt Smart.


(mylinkit) ~ # svn checkout https://subversion.assembla.com/svn/vak-opensource/trunk/utilities/dhrystone
A dhrystone/Makefile
A dhrystone/RATIONALE
A dhrystone/README
A dhrystone/README_C
A dhrystone/VARIATIONS
A dhrystone/dhry.h
A dhrystone/dhry_1.c
A dhrystone/dhry_2.c
A dhrystone/dhry_c.dif
A dhrystone/submit.frm
Checked out revision 30.
(mylinkit) ~ # cd dhrystone/
(mylinkit) dhrystone # make
cc -O3 -DNRUNS=100000000 -Wall -Werror -c -o dhry_1.o dhry_1.c
cc -O3 -DNRUNS=100000000 -Wall -Werror -c -o dhry_2.o dhry_2.c
cc -o dhrystone dhry_1.o dhry_2.o
(mylinkit) dhrystone # ./dhrystone

Dhrystone Benchmark, Version 2.1 (Language: C)

Execution starts, 100000000 runs through Dhrystone
Execution ends
[...]
Nanoseconds for one run through Dhrystone: 896.8
            Million Dhrystones per Second: 1.115
                                    DMIPS: 634.7


Сравнивая с таблицей результатов в интернете и интерполируя, можно видеть, что процессор MT7688 580MHz работает примерно со скоростью Pentium II 400MHz. Некоторая "отсталость" объясняется тем, что MT7688 имеет 16-битную шину памяти DRAM, а Pentium II - 64-битную. Ну и потребление отличается на два порядка.
vak: (Улыбка)
Измерил скорость записи и чтения карточки microSD на плате Linkit MT7688: получилась запись 6.5 Мбайт/сек и чтение 14 Мбайт/сек. Это примерно на уровне хорошего жесткого диска конца 90-х.

# ./diskspeed -m 512
Testing 4-kbyte block size.
Write speed: 512 Mbytes in 78.771 seconds = 6655 kbytes/sec
 Read speed: 512 Mbytes in 36.733 seconds = 14272 kbytes/sec