Я уже писал про появившуюся на днях в продаже платку с 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 она не попала.
Шаг 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 она не попала.