M5Stack CoreMP135に早速最新のLinux 6.9を移植した & Arch Linuxもついでに

![PXL_20240516_180104198.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631316/1d8d24db-efb3-456b-1b0e-cfd8f98bd7e6.jpeg)

12日にLinux 6.9リリースされましたね。
Linuxはいつも新機能ばかりで面白いです。

それと(ほぼ)同時にM5Stack CoreMP135という名のSTM32が乗ったいい感じのものが発売されたらしい。
(これって、カテゴリ的にPCなのかマイコンなのかよくわからない)

https://www.switch-science.com/products/9650

とにかく、普通のM5とは違ってLinuxが動くらしい。面白そう。
CPUはSTM32MP135(armv7 1C1T)でRAMは512MiB。

まあ、すでにいろいろな人が取り上げているので初回時の動作とかは省きます。
起動音がかなりデカいのが注意点ぐらいかな。

## 1. Buildroot
公式のGitHubにbuildrootの外部参照のものがあるので借用。
buildrootは埋め込みLinux用のビルドツール。

M5のGitHubにbuildroot自体のフォークもあるがこれは何もコミットがないし数年遅れている。
このbuildrootでビルドしようとするとエラーになるので最新のbuildrootを使った。

## 2. USART
早速移植するためにシリアルコンバーターをGrove Port Cにつなぎました。
マニュアルにはUSART6と書いてあるためDTSをいじってUSARTにつながるように変更。

なぜかLinuxカーネルのログしか出てこない。

内部ピンヘッダにUSART2があるらしいのでそれに繋ぎ変えてビルドし直す。
なぜかTF-A、Optee、U-BootともにLinuxカーネルのログが出てくる。謎。
なのでUSART2でやることに。

こんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631316/b1f37342-6d1c-accf-b81c-d7ad1bfd7279.png)

最初気づいたのが`Hit any key to stop autoboot:  0`的な表示が出てこない。

他のシリアルを使ってるっぽい。一旦TF-A、OpteeとU-bootのDTSからUSART2以外を取り除くことで出てきた。

```
NOTICE:  CPU: STM32MP135D Rev.Y
NOTICE:  Model: STMicroelectronics STM32MP135F-DK Discovery Board
NOTICE:  BL2: v2.8-stm32mp1-r1.0(release):custom()
NOTICE:  BL2: Built : 19:54:41, May 14 2024
NOTICE:  BL2: Booting BL32
I/TC: DTB enables console (non-secure)
E/TC:0 0 call_initcalls:43 Initcall __text_start + 0x00079008 failed
I/TC: Primary CPU switching to normal world boot
optee optee: OP-TEE: revision 3.19


U-Boot 2022.10-stm32mp-r1 (May 15 2024 - 02:45:03 +0900)

CPU: STM32MP135D Rev.Y
Model: STMicroelectronics STM32MP135F-DK Discovery Board
Board: stm32mp1 in trusted mode (st,stm32mp135f-dk)
DRAM:  512 MiB
optee optee: OP-TEE: revision 3.19
Clocks:
- MPU : 650 MHz
- AXI : 266.500 MHz
- PER : 24 MHz
- DDR : 533 MHz
Core:  252 devices, 31 uclasses, devicetree: board
WDT:   Started watchdog@5a002000 with servicing (32s timeout)
NAND:  0 MiB
MMC:   STM32 SD/MMC: 0
Loading Environment from MMC... OK
In:    serial
Out:   serial
Err:   serial
invalid MAC address 0 in OTP 00:00:00:00:00:00
Net:
Error: eth2@5800e000 address not set.

Error: eth1@5800a000 address not set.

Error: eth2@5800e000 address not set.
No ethernet found.

Hit any key to stop autoboot:  0
STM32MP>
```

いい感じ。

## 3. ビルド
Arch Linux + 最新カーネルにしたいのでクロスコンパイルできるLinuxカーネルのPKGBUILDを作成かつビルド。
クロスコンパイラはご丁寧にbuildrootがDLかつコンパイルしてくれたGCC、G++を使用。

`config`はbuildrootの`.config`出力を6.9で`oldconfig`したもの。

DTSもちゃんとコピー。エラーになった存在しないノードの参照は削除/他のdtsiに追加なりしてコンパイル通った。

buildrootでビルドしたSDのイメージからrootfsをフォーマットし直して`ArchLinuxArm-armv7-latest.gz`を展開。

`pacman --sysroot /path/to/mount -S *.tar.zst` (あの被害を受けてxzじゃなくなったらしい)
でマウントポイント上でパッケージ展開。

起動！

autobootは失敗するので手動でコマンドをちまちま入れましょう。

## 4. 起動

起動はOK、gettyまで動いている。
ただディスプレイ、HDMI、イーサネットは全部だめ。

イーサネットは`compatible`を`"st,stm32mp1-dwmac"`に変えると動いた。ただギガビットなのに100Mbpsしか出ないのは内緒。

## 5. ディスプレイ

ディスプレイは厄介だった。
ILI9342Cというディスプレイ+ICを使っているそう。SPI通信のTFT。
ILI9341というドライバはすでにあるものの、ILI9242Cはない。

M5のbuildrootのパッチを見るとそのままILI9341ドライバを改造したILI9341_M5というのを使っている。
diffを取ると色反転、描画方法周りが変わっている。

そして下部にバックライトのドライバも引っ付けてある。
あまりお世辞にもきれいとは言えないかんじ。
これに関しては後述。

一旦バックライトの部分を消してILI9342CドライバとしてLinuxカーネルに追加。
`disply@0`というスペルミスを犯しているノードの`compatible`を`ilitek,ili9342c`として登録。

起動するとSPIエラー。`-110` (-ETIMEDOUT) だってよ。

これの原因を探るのに数日割いてしまった。問題はLinux 6.9にマージされたコミットが原因だった。
コミット`52b62e7`。`spi: stm32: enable controller before asserting CS`とのこと。
メーリングリストを除くとテスターを募集していたものの見つからず、`STM32F746`というCPUでしかテストできなかったとのこと。
やむなしって感じ。実際こんな変なCPUを持ってるのは限られた人のみだしなあ。

Revertすると動いた。バックライトに関してはU-Bootで`show_logo`をすればU-Boot側でバックライトをつけてくれるので、一旦それで回避。
つまりLinux自体はバックライトをつけれない、という感じ。

## 5. バックライト
M5のパッチを見るとわかるのだが、すごく実装が雑。
I2Cのバス番号、レジスタ番号も直書で、CoreMP135にしか使えない感じ。

全部I2Cドライバとして書き直した。

`of_match`で`compatible`を`m5stack,axp2101`に仮で設定したので、`i2c3`にノードを追加。

```dts
backlight@34 {
	compatible = "m5stack,axp2101";
	reg = <0x34>;
	status = "okay";
};
```
んー 綺麗。最高。

言い忘れていたが、バックライトの制御はAXP2101(電源管理IC)がやっていてI2C3の0x34にいる。
AXP2101のDLDO1にバックライトがつながっていてこのAXP2101のレジスタをいじってDLDO1の出力ONにする。

DLDO1は0.5V~3.5Vを100mV刻みで調整できる。

ひとつ気になったのがM5のパッチでは3.3V以上出さないようになってる。ただIC側では3.5V出せるので、ドライバの実装をミスると0.2V過大に印加することになる。
0.2Vくらいだから大丈夫なのか...?

## 6. 今現在
USBは動くこと確認。

~~タッチパネルはまだ。
ドライバはあたっているので多分動く。~~

動いた。
```
[alarm@alarm ~]$ sudo libinput debug-events
-event0   DEVICE_ADDED            EP0110M09                         seat0 default group1  cap:t ntouches 2 calib
 event0   TOUCH_DOWN              +2.629s       0 (0) 84.17/31.56 (202.00/101.00mm)
 event0   TOUCH_FRAME             +2.629s
 event0   TOUCH_MOTION            +2.684s       0 (0) 80.00/31.56 (192.00/101.00mm)
 event0   TOUCH_FRAME             +2.684s
 event0   TOUCH_MOTION            +2.702s       0 (0) 75.83/31.56 (182.00/101.00mm)
 event0   TOUCH_FRAME             +2.702s
 event0   TOUCH_UP                +2.719s       0 (0)
 event0   TOUCH_FRAME             +2.719s
```

やることは:
    * イーサネットがギガビットじゃない
    * HDMI出力できない
    * シャットダウン実装
かな。

それより先に一旦すべてまとめてGitHubに上げようと思う。

## 感想
やはり1コア1スレッドは遅い。

以上。