Наш магазин на eBay Наш магазин на AliExpress Наш канал в telegram

Обзор микрокомпьютера skw92 и сборка альтернативной прошивки для него на базе OpenWRT

Обзор микрокомпьютера skw92a

Микрокомпьютер SKW92, производимый китайской фирмой Skylab — это, на сегодняшний день, одна из самых дешёвых на рынке железок, на которую можно установить Linux OpenWRT. Тем не менее, этот микрокомпьютер построен на базе достаточно мощного и очень популярного SOC от Mediatek — MT7688AN (на базе процессора MT7628).
К слову, ровно на этом же самом чипе сделаны многие известные роутеры: Asus (RT-N10p, RT-N11p), TP-Link (TL-WR84xN, TL-MR3x20), ZyXEL (Keenetic Extra II), Xiaomi (MiWiFi Nano, Mi Router 4A), а также рассмотренный ранее на нашем сайте микрокомпьютер Onion Omega2 (просто откройте исходники, перейдите в папку /target/linux/ramips/dts и посмотрите список файлов, чьё имя начинается с mt7628an_).

Да, все эти устройства отличаются размерами флеша и ОЗУ, на каких-то не используется часть поддерживаемых чипом интерфейсов, тем не менее, повторюсь, все они базируются на одном SOC-контроллере.

Итак, что же мы имеем конкретно в skw92a:

  • Архитектура: MIPS32
  • Частота: 580 МГц
  • RAM: 64 Мбайт
  • Flash: 8 Мбайт (подключена через SPI-master)
  • Ethernet: 1 WAN, 4 LAN (мультиплексированы с SD-картой)
  • Поддержка SD-карты: есть (мультиплексирована с LAN)
  • Поддержка USB 2.0: есть
  • Поддержка Wi-Fi: есть
  • UART: UART0, UART1 (мультиплексирован с GPIO 45,46)
  • I2C: 1 шт (мультиплексирован с GPIO 4,5)
  • SPI: нет
  • I2S: 1 шт (мультиплексирован с GPIO 0,1,2,3)
  • GPIO: до 30 шт (в зависимости от конфигурации других интерфейсов)

Из очевидных недостатков можно отметить во-первых, довольно маленький объём флеша (даже у простой Омеги, без плюса, он равен 16 Мб), отсутствие выведенного наружу интерфейса SPI, хотя ноги CS1, CS2, позволяют легко разделить интерфейс SPI на два канала (чтобы не пересекаться с flash-памятью), а также мультиплексирование LAN-портов и SD-карты. Недостатки, к слову сказать, вовсе не фатальные, — скажем, объём флеша можно попытаться восполнить за счёт SD-карты или USB-флешки, spi можно реализовать на gpio через bit-banging, а с LAN-портами… ну так в Омеге их вообще нет, а здесь можно по крайней мере «налету» переключаться между LAN и SD-картой.

Качаем исходники OpenWRT и исправляем основные косяки

Начальные этапы подготовки системы к сборке OpenWRT из исходников выполняются ровно также, как это было описано в статье о сборке альтернативных прошивок для Омеги.

Первым делом, после того, как исходники скачаны с гитхаба командой

git clone https://github.com/openwrt/openwrt.git

(или скачаны оттуда же в виде zip-архива и распакованы), — нужно обновить и скачать фиды (коллекции исходников разных пакетов и предварительно сконфигуренные «рецепты» по их сборке). Подробнее про фиды читаем здесь. Для этого переходим в папку со скачанными исходниками OpenWRT и выполняем в командной строке следующие команды:

./scripts/feeds update -a
./scripts/feeds install -a

Теперь, прежде чем переходить к сборке, — исходники нужно немного исправить.

Открываем файл /target/linux/ramips/image/mt76x8.mk, находим строку define Device/skylab_skw92a и в разделе IMAGE_SIZE меняем максимальный размер образа с 16064k на 7872k. У нас размер флеша всего 8 Мб, из них первые 3 блока по 64К занимает bootloader, ещё 1 блок 64К — конфигурация и ещё один блок 64К — factory settings. На прошивку остаётся 123 блока по 64К, что как раз и составляет 7872К.

Далее там же, в раздел DEVICE_PACKAGES дописываем в конце через пробел пакеты uboot-envtools (правка параметров загрузки бутлоадера) и kmod-sdhci-mt7620 (поддержка sd-карт). Последний пакет можно не включать как обязательный именно в этом месте, но тогда для работы с SD-картами его придётся добавить в сборку на этапе конфигурирования (как включенный по-умолчанию или собираемый отдельным модулем).

После этого переходим в папку /openwrt/target/linux/ramips/dts. Здесь, в файле mt7628an_skylab_skw92a.dts прописаны включенные по-умолчанию интерфейсы (можно подглядеть какие включены в омеге и включить такие же), а в файле mt7628an.dtsi перечислен полный список интерфейсов, которые в принципе можно включить. Давайте включим sd-карту и uart1, а интерфейсы i2c, i2s, spis переключим по-умолчанию в режим gpio, для этого в конец файла mt7628an_skylab_skw92a.dts нужно добавить следующее:

&sdhci {
	status = "okay";
	mediatek,cd-low;
};

&uart1 {
	status = "okay";
};

В этом же файле, в секции &state_default, в раздел gpio дописываем через запятую «i2c», «i2s», «spis». Должно получиться вот так:

&state_default{
	gpio {
		groups = "wdt", "refclk", "wled_an", "i2c", "i2s", "spis";
		function = "gpio";
	};
};

Кроме того, в секции &spi0 нужно исправить размер флеша (по-умолчанию размер указан для 16-мегабайтной флешки, но в скайлабе только 8 мегабайт):

&spi0 {
        status = "okay";

        flash@0 {
                compatible = "jedec,spi-nor";
                ...
                partitions {
                        ...
                        firmware: partition@50000 {
                                reg = <0x50000 0xfb0000>;  <--- заменить 0xfb0000 на 0x7b0000
                                ...
                        };
                };
         };
};

Добавляем в OpenWRT сторонние пакеты (на примере omega2-ctrl)

Следующее, что нужно сделать - это добавить в наши исходники удобные сторонние инструменты.

Скажем, в оригинальной сборке для микрокомпьютера Omega2 присутствует удобный инструмент для управления мультиплексированными линиями - omega2-ctrl. Его исходники свободно лежат на гитхабе, но по-умолчанию в исходниках OpenWRT этого инструмента нет. Сейчас мы это исправим и добавим его, например, в секцию Utilities.

Итак:

  • Открываем папку с исходниками OpenWRT, переходим в папку /package/utils/ и качаем в неё исходники инструмента omega2-ctrl. Для этого просто выполняем в терминалке:
    git clone https://github.com/OnionIoT/omega2-ctrl.git

    или скачиваем с гитхаба zip-архив и распаковываем. Так или иначе, после этого у нас в папке utils появится папка omega2-ctrl, в которой будут исходники соответствующего инструмента.

  • Заходим в папку с исходниками и удаляем всё, кроме /include (содержит необходимые хидеры) и /src (исходники на си), в том числе и makefile (он содержит инструкции по сборке, но они какие-то кривые, так что мы напишем новые).
  • Переносим папку /include внутрь папки /src.
  • Открываем все си-шные файлы в папке /src и везде, где видим попытки проинклюдить хидеры из папки /include заменяем имя файла в треугольных скобках на папку + имя файла в двойных кавычках (в этом случае путь будет определяться от корня папки, в которой расположен файл, в который делается инклюд). То есть, например, если было вот так:
    #include <gpiomux.h>

    то должно стать вот так:

    #include "include/gpiomux.h"
  • Теперь заходим в папку /include, открываем в ней все файлы хидеров и если видим инклюд другого файла хидеров из этой же папки (у остальных инклюдов треугольные скобки на кавычки менять не нужно!), то аналогично заменяем треугольные скобки на двойные кавычки. Тут уже дополнительно имя папки указывать не нужно, поскольку эти файлы и так в одной папке. То есть в случае, если было вот так:
    #include <omega2_ctrl_types.h>

    то должно стать вот так:

    #include "omega2_ctrl_types.h"
  • Далее нам нужно создать адекватный Makefile, даже два (в Midnight Commander для этого можно использовать сочетание клавиш Shift+F4).
    Первый создаётся по правилам, описанным для утилиты make и располагается в папке с сишными файлами (/src). В нём у нас всего две цели, описывающие как всё скомпилить и как удалить всё, что мы накомпилили:
    Содержимое первого Makefile

    all: omega2-ctrl
    
    omega2-ctrl:
    		$(CC) $(CFLAGS) -o $@ refclk.c gpiomux.c main.c $(LDFLAGS)
    
    clean:
    		rm -f omega2-ctrl

    [свернуть]

    Знакомство с утилитой make лучше начинать со статьи на хабре, после чего можно переходить и к официальной доке. А вот здесь, в частности, описаны переменные, используемые неявными правилами: $(CC), $(CFLAGS), $LDFLAGS...

    Второй Makefile располагается прямо в папке omega2-ctrl, создаётся по правилам, описанным вот здесь и представляет собой объектно-ориентированный шаблон, описывающий создаваемый нами пакет (в котором, в том числе, описано как его собирать и куда устанавливать после того, как всё соберётся).

    Содержимое второго Makefile

    include $(TOPDIR)/rules.mk
    
    PKG_NAME:=omega2-ctrl
    PKG_RELEASE:=1
    PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
    
    include $(INCLUDE_DIR)/package.mk
    
    define Package/omega2-ctrl
        SECTION:=utils
        CATEGORY:=Utilities
        TITLE:=Utility to control multiplexed pin's
    endef
    
    
    define Package/omega2-ctrl/description
        Utility to control multiplexed pin's (to choose between uart1/gpio, i2c/gpio, i2s/gpio, etc.)
    endef
    
    define Build/Compile
    	$(MAKE) -C $(PKG_BUILD_DIR) \
    		CC="$(TARGET_CC)" \
    		CFLAGS="$(TARGET_CFLAGS) -Wall" \
    		LDFLAGS="$(TARGET_LDFLAGS)"
    endef
    
    define Package/omega2-ctrl/install
    	$(INSTALL_DIR) $(1)/usr/bin
    	$(INSTALL_BIN) $(PKG_BUILD_DIR)/omega2-ctrl $(1)/usr/bin/
    endef
    
    $(eval $(call BuildPackage,omega2-ctrl))

    [свернуть]

Теперь если мы в корне папки с исходниками openwrt выполним make menuconfig, то в списке пакетов (в секции utils) мы увидим нашу утилитку omega2-ctrl.

Совершенно аналогичным образом можно было бы добавить в сборку любой другой пакет, в том числе и какой-нибудь самописный.

Собираем прошивку

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

Первым делом конфигурируем исходники под наше «железо». Для этого переходим в папку с исходниками openwrt и выполняем в терминале команду:

make menuconfig

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

  • Target System (Mediatek Ralink MIPS) - выбираем архитектуру ядра микроконтроллера на базе которого сделана омега
  • Subtarget (MT76x8 based boards) - выбираем семейство, в которое входит микроконтроллер модуля Omega2
  • Target Profile (Skylab SKW92A) - выбираем конкретное устройство

Сохраняем установленную конфигурацию ( < Save > ), выходим ( < Exit > ) и выполняем в командной строке команду:

make defconfig

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

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

make tools/install
make toolchain/install

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

make menuconfig

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

После того как все необходимые пакеты выбраны - сохраняем всё, что мы наконфигурировали ( < Save > ) и выходим ( < Exit > ).

Всё, теперь можно переходить к сборке прошивки. Для этого выполняем в командной строке:

make -jN

N - число ядер вашего процессора + 1

Можно, кстати, не заморачиваться и написать просто make, но так будет дольше.

После окончания процесса сборки готовую прошивку в виде бинарника можно будет найти в папке bin/targets/ramips/mt76x8.

Компилируем отдельный пакет для отладки

Добавлять в сборку свои пакеты - это отлично, но сначала эти пакеты нужно отладить. А для отладки очень неудобно пересобирать все исходники openwrt целиком (это заняло бы очень много времени). Гораздо проще собирать один единственный пакет, который мы хотим отладить, заливать его на нашу железку и тестировать. Сейчас мы разберёмся как это сделать (экспериментировать продолжим с нашим пакетом omega2-ctrl).

Если мы просто перейдём в папку с исходниками пакета omega2-ctrl и выполним команду make, то у нас всё скомпилится, но при переносе скомпилированной программы в skw92 ничего работать не будет. Почему? Потому что вместо кроссплатформенной компиляции под mips-архитектуру процессора MT7628AN, программа скомпилировалась под архитектуру x86 нашего компьютера. Это легко увидеть, если просмотреть скомпилированный файл в текстовом редакторе (например, выбираем файл в Midnight Commander и жмём F3). Где-то в начале нашего файла мы увидим примерно такое:

...ELF 64-bit LSB shared object, x86-64...

Как видите, архитектура x86, 64 бита.

Как же так вышло? А помните, мы в Makefile написали вот такую инструкцию по сборке:

$(CC) $(CFLAGS) -o $@ refclk.c gpiomux.c main.c $(LDFLAGS)

Так вот, когда этот Makefile последовательно обрабатывался в процессе компиляции всех исходников openwrt, у нас при его вызове была определена переменная окружения $(CC), содержащая путь к кроссплатформенному компилятору gcc под mips32, который, в свою очередь, собирается на этапе сборки тулчейна. А когда мы попытались выполнить make из папки с исходниками omega2-ctrl - у нас переменная окружения $(CC) оказалась неопределённой и утилита make просто не знала, что компилить нашу прогу нужно кроссплатформенным компилятором под другую платформу.

Как решить вопрос? Кроссплатформенный компилятор можно найти вот здесь: /путь_к_папке_с_исходниками_openwrt/staging_dir/toolchain_mipsel_24kc_gcc-8.4.0_musl/bin, он называется mipsel-openwrt-linux-gcc. То есть, в принципе, для сборки нашей простенькой программы достаточно перейти в папку с её исходниками и выполнить в терминале такую команду:

/путь_к_папке_с_исходниками_openwrt/staging_dir/toolchain_mipsel_24kc_gcc-8.4.0_musl/bin/mipsel-openwrt-linux-gcc -I ./include gpiomux.c refclk.c main.c -o omega2-ctrl

Теперь всё скомпилится под нужную архитектуру. Если снова открыть в текстовом редакторе скомпилированный файл, то в начале мы увидим:

...ELF 32-bit LSB executable, MIPS, MIPS32...

Здорово, но всё ещё не совсем удобно, - слишком долго набирать команду в командной строке. Можно сделать ещё удобнее. Давайте в папке с исходниками программы (/src) omega2-ctrl создадим bash-скрипт, назовём его, скажем, make-debug.sh и наполним следующим содержанием:

#! /bin/sh
#

export STAGING_DIR="/путь_к_папке_с_исходниками_openwrt/staging_dir/toolchain_mipsel_24kc_gcc-8.4.0_musl"

MIPS_COMPILER=$STAGING_DIR/bin/mipsel-openwrt-linux-gcc \

$MIPS_COMPILER -I ./include gpiomux.c refclk.c main.c -o omega2-ctrl

Пришлось отдельно вынести переменную окружения STAGING_DIR, поскольку без неё компилятор выдавал несколько ворнингов, но это так, детали.

Всё, теперь мы можем пересобирать наш пакет, просто выполнив bash-скрипт (кстати, не забудьте поставить ему права на исполнение: chmod +x make-dubug.sh).

Ещё раз обращу ваше внимание, что собирать и отлаживать какие-либо пакеты имеет смысл только после сборки тулчейна, так как при его сборке собирается в том числе и кроссплатформенный компилятор!

На этом на сегодня всё. Дополнительную информацию про skw92 можно найти на нашем форуме

Кстати, в нашем интернет-магазине вы можете купить док-плату для микрокомпьютера skw92

Добавить комментарий