buildroot を見ていたのですが、 レポジトリの中に ESP32 の設定がありました。 昔、MMU のない CPU で Linux を動かす uCLinux というプロジェクトがあったのですが、 今ではメインのカーネルソースに取り込まれていて、簡単にビルドできるようになっているようです。
ESP32 への linux 実装は主にこの方 がやられているようなので、 基本的にこの記述に従います。
ターゲットとして 8MB の PS-RAM がついた、ESP32 が必要です。 秋月電子で売っている、ESP32-S3 (N16R8) を使いました。 元ネタでは 8MB フラッシュ版を使っているので、このままですと 8MB 用のファイルが生成されます。
ビルドには Ubuntu 22.04 LTS を使いますので、 Ubuntu の入ったマシン(VMでOK)を準備します。
ビルド方法については、Docker を使う方法で行けるかと思ったのですが、途中で失敗するので直接ビルドスクリプトを実行します。
前準備として必要なパッケージをインストールします。
$ sudo apt update
$ sudo apt install gperf bison flex texinfo help2man gawk libtool-bin git unzip ncurses-dev rsync zlib1g zlib1g-dev xz-utils cmake wget bzip2 g++ python3 python3-dev python3-pip cpio bc virtualenv python3.10-venv python-is-python3
ビルド用のスクリプトを持ってきて実行します。
$ git clone https://github.com/jcmvbkbc/esp32-linux-build
$ cd esp32-linux-build/
$ ./rebuild-esp32s3-linux-wifi.sh
物理マシンで Ubuntu を実行している場合は、直接 esp32-s3 に書き込めるようですが、 VMで実行していると、書き込みできずに詰まります。
Project build complete. To flash, run this command:
/home/aoki/.espressif/python_env/idf5.1_py3.10_env/bin/python ../esp-idf/components/esptool_py/esptool/esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size 8MB --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/network_adapter.bin
or run 'idf.py -p (PORT) flash'
+ read -p 'ready to flash... press enter'
ready to flash... press enter
なのでファイル一式を Windows に持ってきて Windows から書き込みます。
書き込みに ESP-IDF に含まれる parttool.py
が必要なので、
ESP-IDF がインストールされていない場合はインストールしておきます。
必要なファイルは bootloader が、esp32-linux-build/build/esp-hosted/esp_hosted_ng/esp/esp_driver/network_adapter/
以下の 3 ファイル
linux 本体が esp32-linux-build/build/build-buildroot-esp32s3/images/
以下の 3 ファイル
まずは esptool でブートローダを書き込みます。PORT
は esp32s3 が接続されている COM ポートを指定します。
> esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash 0x0 bootloader.bin 0x8000 partition-table.bin 0x10000 network_adapter.bin
次に linux 本体を書き込みます。
> parttool.py write_partition --partition-name linux --input xipImage
> parttool.py write_partition --partition-name rootfs --input rootfs.cramfs
> parttool.py write_partition --partition-name etc --input etc.jffs2
これで Linux の準備が完了しましたので、リセットして起動します。
[ 4.187268] with arguments:
[ 4.189340] /sbin/init
[ 4.192028] with environment:
[ 4.195988] HOME=/
[ 4.197496] TERM=linux
Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
Starting network: Successfully initialized wpa_supplicant
OK
Starting inetd: OK
Welcome to Buildroot
buildroot login: root
~ # uname -a
Linux buildroot 6.8.0 #1 PREEMPT Sun Apr 7 06:54:17 UTC 2024 xtensa GNU/Linux
~ # df -h
Filesystem Size Used Available Use% Mounted on
mtd:rootfs 4.3M 4.3M 0 100% /
mtd:etc 448.0K 216.0K 232.0K 48% /etc
この Linux は WiFi に対応しているので、WiFi を設定します。 とはいっても一般的な Linux のお作法通りです。
以下の内容のファイルを /etc/wpa_supplicant.conf
という名前で作成します。
network={
ssid="YOUR-SSID-HERE"
psk="YOUR-SSID-PASSWORD-HERE"
}
再起動して、反映させます。
~ # ip a
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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: espsta0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 7c:df:a1:e8:0d:1c brd ff:ff:ff:ff:ff:ff
inet 192.168.1.152/24 brd 192.168.1.255 scope global espsta0
valid_lft forever preferred_lft forever
inet6 2400:2410:b721:f600:7edf:a1ff:fee8:d1c/64 scope global dynamic flags 100
valid_lft 296sec preferred_lft 296sec
inet6 fe80::7edf:a1ff:fee8:d1c/64 scope link
valid_lft forever preferred_lft forever
3: sit0@NONE: <NOARP> mtu 1480 qdisc noop qlen 1000
link/sit 0.0.0.0 brd 0.0.0.0``
~ # ping www.google.com
PING www.google.com (142.250.206.196): 56 data bytes
64 bytes from 142.250.206.196: seq=0 ttl=55 time=45.530 ms
64 bytes from 142.250.206.196: seq=1 ttl=55 time=30.670 ms
64 bytes from 142.250.206.196: seq=2 ttl=55 time=27.081 ms
^C
--- www.google.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 27.081/34.427/45.530 ms
ping も通ります。
この Linux では gpio サブシステムが有効になっているので、
sysfs
で gpio が操作できるということになっているのですが、
操作方法がよくわかりません。
よって、レジスタを直接いじります。
以下のスクリプトで、IO18 に接続された LED をチカチカさせます。
#!/bin/sh
devmem 0x60004020 32 0x40000
while true
do
devmem 0x60004004 32 0x40000
sleep 1
devmem 0x60004004 32 0x00000
sleep 1
done
以上お疲れ様でした。