Lichee Nano
Lichee Nano は Allwinner F1C100s を搭載した開発ボードです.
Lichee Nano
公式サイトの方法では, USB が認識できない等の問題があったため Linux 5.2 のビルドを行い USB の認識及び Wi-Fi 接続までの方法とクロスコンパイルしたプログラムの実行までを記載.
ビルド環境 (uboot, Linux 5.2, buildroot)
公式サイトでも記されている通り, ビルド環境は Ubuntu 16.04 LTS 64bit
の使用をおすすめします.
使用している環境が Arch Linux であったため, Docker で Ubuntu 16.04 イメージを使用してビルドを行いました.
Ubuntu 16.04 のイメージの取得, 実行は下記リンクを参照してください.
DockerでUbuntu 16.04 LTSのイメージを利用してみよう
また, Docker を利用した方法ではビルドしたファイルの転送を事前に考えておく必要があります. docker run
コマンドでコンテナを作成する際に -v
オプションを使用してホストディレクトリをコンテナ内にマウントする方法が一番楽かもしれません.
ちなみに私は, すべてビルドし終えたあとにファイル転送が必要なことに気づいたため sshd
, scp
を使用してファイルの送受信を行いました.
uboot, Linux, buildroot のビルド
各ビルド対象ビルド時にエラーが発生する場合, 表示される内容を確認して問題の対処を行ってください.
Ubuntu 16.04 LTS を使用している場合, ビルドに必要なパケージがインストールされていないことをはじめに疑ってください.
Toolchain のインストール
下記の方法より Toolchain のダウンロードと展開, /opt
ディレクトリへの移動を行います.
wget http://releases.linaro.org/components/toolchain/binaries/7.2-2017.11/arm-linux-gnueabi/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi.tar.xz
tar -vxJf gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi.tar.xz
sudo cp -r ./gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi /opt/
次に, /opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabi/bin
へのパスを通します.
export PATH=$PATH:/opt/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi/bin
~/.bashrc
への書き込みを行う方法でも問題ありません. 書き込み後設定の反映を行ってください.
source ~/.bashrc
uboot
uboot のクローンを作成
Lichee-Pi/u-boot.git
プロジェクトから nano-v2018.01
ブランチのクローンを作成.
git clone https://github.com/Lichee-Pi/u-boot.git -b nano-v2018.01
Micro SD(TF Card) より開始する u-boot のビルド
ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make licheepi_nano_defconfig
boot.scr
生成のため, 下記 boot.cmd
を保存.
setenv bootargs console=tty0 console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 rw
load mmc 0:1 0x80C00000 suniv-f1c100s-licheepi-nano.dtb
load mmc 0:1 0x80008000 zImage
bootz 0x80008000 - 0x80C00000
u-boot/tools/mkimage
より boot.scr
の生成.
tools/mkimage -C none -A arm -T script -d boot.cmd boot.scr
Linux
Linux(nano-5.2-tf) のクローンを作製
git clone https://github.com/Lichee-Pi/linux.git --depth=1 -b nano-5.2-tf
デフォルト構成ファイルのダウロードと名称の変更
# wget http://nano.lichee.pro/_static/step_by_step/lichee_nano_linux.config
wget https://raw.githubusercontent.com/sipeed/Nano-Doc-Backup/master/_static/step_by_step/lichee_nano_linux.config
mv lichee_nano_linux.config .config
もしくは
#curl -L http://nano.lichee.pro/_static/step_by_step/lichee_nano_linux.config > .config
curl -L 'https://raw.githubusercontent.com/sipeed/Nano-Doc-Backup/master/_static/step_by_step/lichee_nano_linux.config' > .config
コンパイル
ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make
任意: USB デバイスを認識させる
コンパイルを実行する前に, USB デバイスを認識させるためのパッチを当てる必要があります.
USBデバイスを認識させる方法は, 下記の記事に詳細が記載されています.
LicheePi NanoでUSBデバイスを認識させる - Qiita
whycna.com
[v2,5/5] ARM: suniv: f1c100s: enable USB on Lichee Pi Nano - Patchwork
ここで提示されているパッチは, 上記の中に含まれていますので参考まで.
diff --git a/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts b/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts
index ca644541a..890a57717 100644
--- a/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts
+++ b/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts
@@ -20,7 +20,7 @@
};
panel: panel {
- compatible = "lg,lb070wv8", "simple-panel";
+ compatible = "qiaodian,qd43003c0-40", "simple-panel";
#address-cells = <1>;
#size-cells = <0>;
enable-gpios = <&pio 4 6 GPIO_ACTIVE_HIGH>;
@@ -79,3 +79,17 @@
pinctrl-0 = <&uart0_pe_pins>;
status = "okay";
};
+
+&otg_sram {
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpio = <&pio 4 2 GPIO_ACTIVE_HIGH>; /* PE2 */
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/suniv-f1c100s.dtsi b/arch/arm/boot/dts/suniv-f1c100s.dtsi
index 26d8e5577..437bdf7d9 100644
--- a/arch/arm/boot/dts/suniv-f1c100s.dtsi
+++ b/arch/arm/boot/dts/suniv-f1c100s.dtsi
@@ -221,6 +221,31 @@
resets = <&ccu RST_BUS_UART2>;
status = "disabled";
};
+ usb_otg: usb@1c13000 {
+ compatible = "allwinner,suniv-musb";
+ reg = <0x01c13000 0x0400>;
+ clocks = <&ccu CLK_BUS_OTG>;
+ resets = <&ccu RST_BUS_OTG>;
+ interrupts = <26>;
+ interrupt-names = "mc";
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ extcon = <&usbphy 0>;
+ allwinner,sram = <&otg_sram 1>;
+ status = "disabled";
+ };
+
+ usbphy: phy@1c13400 {
+ compatible = "allwinner,suniv-usb-phy";
+ reg = <0x01c13400 0x10>;
+ reg-names = "phy_ctrl";
+ clocks = <&ccu CLK_USB_PHY0>;
+ clock-names = "usb0_phy";
+ resets = <&ccu RST_USB_PHY0>;
+ reset-names = "usb0_reset";
+ #phy-cells = <1>;
+ status = "disabled";
+ };
fe0: display-frontend@1e00000 {
compatible = "allwinner,suniv-f1c100s-display-frontend";
reg = <0x01e00000 0x20000>;
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 856927382..3cd9e946a 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -98,6 +98,7 @@
#define POLL_TIME msecs_to_jiffies(250)
enum sun4i_usb_phy_type {
+ suniv_phy,
sun4i_a10_phy,
sun6i_a31_phy,
sun8i_a33_phy,
@@ -859,6 +860,14 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
return 0;
}
+static const struct sun4i_usb_phy_cfg suniv_cfg = {
+ .num_phys = 1,
+ .type = suniv_phy,
+ .disc_thresh = 3,
+ .phyctl_offset = REG_PHYCTL_A10,
+ .dedicated_clocks = true,
+};
+
static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = {
.num_phys = 3,
.type = sun4i_a10_phy,
@@ -973,6 +982,7 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
};
static const struct of_device_id sun4i_usb_phy_of_match[] = {
+ { .compatible = "allwinner,suniv-usb-phy", .data = &suniv_cfg },
{ .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg },
{ .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg },
{ .compatible = "allwinner,sun6i-a31-usb-phy", .data = &sun6i_a31_cfg },
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index 832a41f9e..83f3fa5b0 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -714,14 +714,17 @@ static int sunxi_musb_probe(struct platform_device *pdev)
INIT_WORK(&glue->work, sunxi_musb_work);
glue->host_nb.notifier_call = sunxi_musb_host_notifier;
- if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb"))
+ if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb") ||
+ of_device_is_compatible(np, "allwinner,suniv-musb")) {
set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
+ }
if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb") ||
- of_device_is_compatible(np, "allwinner,sun8i-h3-musb")) {
+ of_device_is_compatible(np, "allwinner,sun8i-h3-musb") ||
+ of_device_is_compatible(np, "allwinner,suniv-musb")) {
set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags);
}
@@ -812,6 +815,7 @@ static int sunxi_musb_remove(struct platform_device *pdev)
}
static const struct of_device_id sunxi_musb_match[] = {
+ { .compatible = "allwinner,suniv-musb", },
{ .compatible = "allwinner,sun4i-a10-musb", },
{ .compatible = "allwinner,sun6i-a31-musb", },
{ .compatible = "allwinner,sun8i-a33-musb", },
任意: MT7601U チップが搭載された Wi-Fi 子機の認識
はじめに, Raspberry Pi 対象の記事であるが MT7601U 対象の記事.
Raspberry Piでmt7601uの無線LAN子機が認識されない問題を解決 | クソざこCoding
私の対処に問題があったのか, 上記の方法では解決できなかった. 出典は失念してしまいましたがエラーメッセージを検索して成功した例を下記のパッチに記します.
このパッチを当てた状態で再度ビルドを行ってください.
最後に MT7601U を動作させるためにドライバが必要となります. Meditek 社の MT7601U のページよりダウンロードを行います.
MediaTek | MT7601U
ダウンロードしたファイル DPO_MT7601U_LinuxSTA_3.0.0.4_20130913.tar.bz2
を展開し, DPO_MT7601U_LinuxSTA_3.0.0.4_20130913/mcu/bin/MT7601_formal_1.7.bin
を Lichee Nano の /lib/firmware/mt7601u.bin
として保存を行います.
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 2dc67e6..63bb552 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -136,11 +136,13 @@ static const struct ieee80211_ops mt76x0u_ops = {
.release_buffered_frames = mt76_release_buffered_frames,
};
-static int mt76x0u_init_hardware(struct mt76x02_dev *dev)
+//static int mt76x0u_init_hardware(struct mt76x02_dev *dev)
+static int mt76x0u_init_hardware(struct mt76x02_dev *dev, bool reset)
{
int err;
- mt76x0_chip_onoff(dev, true, true);
+ //mt76x0_chip_onoff(dev, true, true);
+ mt76x0_chip_onoff(dev, true, reset);
if (!mt76x02_wait_for_mac(&dev->mt76))
return -ETIMEDOUT;
@@ -173,7 +175,8 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev)
if (err < 0)
goto out_err;
- err = mt76x0u_init_hardware(dev);
+ //err = mt76x0u_init_hardware(dev);
+ err = mt76x0u_init_hardware(dev, true);
if (err < 0)
goto out_err;
@@ -309,7 +312,8 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
if (ret < 0)
goto err;
- ret = mt76x0u_init_hardware(dev);
+ //ret = mt76x0u_init_hardware(dev);
+ ret = mt76x0u_init_hardware(dev, false);
if (ret)
goto err;
変更部分をコメントアウトして修正したため, 多少変なパッチファイルとなっています.
buildroot
buildroot のダウンロードと展開
wget https://buildroot.org/downloads/buildroot-2017.08.tar.gz
tar xvf buildroot-2017.08.tar.gz
cd buildroot-2017.08/
ルートファイルシステムのコンパイル でデフォルト構成ファイルがダウンロードする指示がありますがアクセスができないため, make menuconfig
より構成を行ってください.
最小の構成は, 上記のページに記されているもののみです. 一応これだけでも動作の確認は行なえます.
buildroot のコンパイルには時間がかかります.
Target options --->
Target Architecture Variant (arm926t) --->
[ ] Enable VFP extension support
Target ABI (EABI) --->
Floating point strategy (Soft float) --->
System configuration --->
(Lichee Pi) System hostname
(licheepi) Root password
[*] remount root filesystem read-write during boot
menuconfig より buildroot の構成を編集.
make menuconfig
ビルドの実行
make
ビルド成功後, buildroot-2017.08/output/images/roots.tar
が作成されます.
SD カードへのインストール.
下記のビルドしたファイル及び必要なファイルをホスト環境に複製します.
- u-boot/u-boot-sunxi-with-spl.bin
- u-boot/boot.scr
- linux/arch/arm/boot/zImage
- linux/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dtb
- buildroot-2017.08/output/images/rootfs.tar
SDカードのパーティション設定とフォーマット
認識順序によって sdX
の X
部分の名称が固定でないため, ここでは X
としています. USBメモリ等記憶メディアが認識されていない場合, sdb
が SDカードになると思われます.
パーディション sdX1
はビルドしたカーネルとデバイスツリーを格納できる容量で設定を行ってください.
残りのパーティションは任意に設定を行うことができます. パーティション sdX2
に残りすべてを割り当てても問題ありません.
パーティション sdX1
は vfat, パーティション sdX2
は ext4 のファイルシステムでフォーマットを行います.
# fdisk /dev/sdX
# mkfs.vfat /dev/sdX1
# mkfs.ext4 /dev/sdX2
u-boot の書き込み
# dd if=u-boot-sunxi-with-spl.bin of=/dev/sdX bs=1024 seek=8
Kernel, rootfs のインストール
マウントポイントの作製とマウント
NOTE: ここで現在のディレクトリに対してマウントポイントとなるディレクトリの作製を行っていますが, 特別な意味は存在しません. SDカードのパーティションをマウントできれば良いのです. 好みの問題です.
# mkdir -pv mnt/rootfs mnt/boot
# mount /dev/sdX1 mnt/boot
# mount /dev/sdX2 mnt/rootfs
カーネル, ブートファイルのコピー
# cp -v zImage mnt/boot
# cp -v boot.scr mnt/boot
# cp -v u-boot-sunxi-with-spl.bin mnt/boot
rootfs の展開と umount
# tar xvf roots.tar -C mnt/rootfs
# sync
# umount mnt/rootfs
# umount mnt/boot
Wi-Fi への接続
Wi-Fi への接続は, wpa_supplicant
を使用した方法を記載します.
wpa_supplicant
や wpa_passphrase
を有効にするには buildroot
ビルド時に構成より指定する必要があります.
Target packages --->
Networking applications -->
[*] wpa_supplicant
[*] Enable nl80211 support
[*] Install wpa_cli binary
[*] Install wpa_client shaed library
[*] Install wpa_passphrage
デバイスの確認
ip
コマンドより認識されているネットワークデバイスの確認を行う. ここで使用想定するデバイス名は wlan0
とします.
# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: usb0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop qlen 1000
link/ether 82:6a:7e:xx:xx:xx brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop qlen 1000
link/ether 1c:bf:ce:8a:ee:17 brd ff:ff:ff:ff:ff:ff
# ip link set dev wlan0 up
wpa_supplicant の実行
はじめに wpa_supplicant
の設定ファイルを作成します.
# mkdir -v /etc/wpa_supplicant
# wpa_passphrage [SSID] [PASSWORD] >> /etc/wpa_supplicant/wlan0.conf
wpa_supplicant
の実行及び動的 IP を割り当てる場合ならば dhcpcd
も実行.
# wpa_supplicant -Dnl80211 -i wlan0 -c /etc/wpa_supplicant/wlan0.conf -B
Successfully initialized wpa_supplicant
rfkill: Cannot open RFKILL control device
[ 132.223615] wlan0: authenticate with a4:71:74:xx:xx:xx
[ 132.292065] wlan0: send auth to a4:71:74:xx:xx:xx (try 1/3)
[ 132.301098] wlan0: authenticated
[ 132.308490] wlan0: associate with a4:71:74:xx:xx:xx (try 1/3)
[ 132.321067] wlan0: RX AssocResp from a4:71:74:xx:xx:xx (capab=0x431 status=0 aid=3)
[ 132.373016] wlan0: associated
[ 132.380301] random: wpa_supplicant: uninitialized urandom read (4096 bytes read)
# dhcpcd
all: IPv6 kernel autoconf disabled
all: IPv6 kernel autoconf disabled
DUID 00:01:00:01:c7:92:bd:27:1c:bf:ce:8a:ee:17
wlan0: IAID ce:8a:ee:17
wlan0: adding address fe80::662:94eb:4379:d8ca
[ 139.879676] random: dhcpcd: uninitialized urandom read (120 bytes read)
if_addaddress6: Operation not supported
usb0: waiting for carrier
wlan0: rebinding lease of 192.168.100.154
wlan0: probing address 192.168.100.154/24
wlan0: leased 192.168.100.154 for 604800 seconds
wlan0: adding route to 192.168.100.0/24
wlan0: adding default route via 192.168.100.1
forked to background, child pid 214
接続状態の確認
ip
コマンドを使用して wlan0
に IP アドレスが割り当てられていることを確認します.
ネットワークの導通確認は任意の方法で行ってください. 一例 ping -c 3 www.example.com
等
# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: usb0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 82:6a:7e:8b:2f:83 brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
link/ether 1c:bf:ce:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 192.168.100.154/24 brd 192.168.100.255 scope global wlan0
valid_lft forever preferred_lft forever
Hello, World!
Arch User Repository に存在する arm-linux-gnueabi-gcc のクロスコンパイラで生成された実行ファイルは, Lichee Nano 環境においてはエラーが発生する.
また, u-boot 及び Linux カーネルビルド時に使用した Toolchain でも同様な現象が発生する.
#include <stdio.h>
int main(
int argc,
char *argv[]) {
fprintf(stderr, "Hello, World!\n");
return 0;
}
ホスト側でコンパイル.
$ arm-linux-gnueabi-gcc -o hello src/main.c \
-march=armv5te \
-mfloat-abi=soft \
-mabi=aapcs-linux \
-marm \
-mtls-dialect=gnu \
-mtune=arm926ej-s
Lichee Nano 側で実行.
$ ./hello
Segmentation fault
解決策
buildroot ビルド時に生成された buildroot-2017.08/output/host/bin/arm-buildroot-eabi-gcc
を使用する. これが正攻法なのかわかりませんが, 今の所うまく行っています.
arm-buildroot-linux-gnueabi-gcc \
-o hello src/main.c \
-march=armv5te \
-mfloat-abi=soft \
-mabi=aapcs-linux \
-marm \
-mtls-dialect=gnu \
-mtune=arm926ej-s
$ ./hello
Hello, World!
$ /lib/ld-linux.so.3 --list `pwd`/hello
libc.so.6 => /lib/libc.so.6 (0xb6dea000)
/lib/ld-linux.so.3 (0xb6f2f000)
認識及びネットワークに接続できた Wi-Fi 子機
メーカ | 名称 | チップセット |
---|---|---|
TP-Link | TL-WN823N v2/v3 | Realtek RTL8192EU |
BUFFALO INC. | WLI-UC-GNM2 | Ralink RT3070 |
Ralink Technology, Corp. | MT7601U Wireless Adapter | MediaTek MT7601U |