# Raspberry PI + cross compile & build kernel
* https://www.raspberrypi.com/documentation/computers/linux_kernel.html
* recommend: use another micro SD card for this lab!
# topic 1. build kernel
## 先準備VM (ubuntu 20, 64bit)
* 使用virtualbox + Ubuntu 20 (64bit)
* https://releases.ubuntu.com/focal/ubuntu-20.04.6-desktop-amd64.iso
* https://ubuntu.cs.nycu.edu.tw/ubuntu-release/20.04.6/ubuntu-20.04.6-desktop-amd64.iso
* 官方文件: https://www.raspberrypi.com/documentation/computers/linux_kernel.html#cross-compiling-the-kernel
## virtualbox setting
1. Install VirtualBox Guest Additions
```
sudo apt update
sudo apt upgrade
sudo apt install build-essential dkms linux-headers-$(uname -r)
```
* 重開機後, 再執行 Insert Guest Additional CD image


* 裝完之後, 再重開機
## Dependencies and Toolchain
* Install Required Dependencies and Toolchain
`sudo apt install git bc bison flex libssl-dev make libc6-dev libncurses5-dev`
* Install the 64-bit Toolchain for a 64-bit Kernel
`sudo apt install crossbuild-essential-arm64`
* Get the Kernel Sources
`git clone --depth=1 https://github.com/raspberrypi/linux`
* Omitting the --depth=1 will download the entire repository, including the full history of all branches, but this takes much longer and occupies much more storage.
## Load kernel config and build
* Load 64-bit default configs (For Raspberry Pi 3, 3+, 4, 400 and Zero 2 W, and Raspberry Pi Compute Modules 3, 3+ and 4:)
```
cd linux
KERNEL=kernel8
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
```
* Build image for all 64-bit Builds with default config
* 第一次跑大約要1小時 (看電腦的性能, 我花了77min)
```
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs
```
### Configuring the Kernel by menuconfig
* Preparing to make menuconfig
```sudo apt install libncurses5-dev```
* cross-compiling a 64-bit kernel
```make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig```
* Go to “General setup” -> Select “Local version” -> Put your local version (student id number)

* save and exit, then start to build kernel
```make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs```
* After building, your image locates: arch/arm64/boot/
## Install the new kernel
* 把micro sd卡連接到虛擬機裡面, 系統會自動掛載磁區, 可以用df -h檢查before/after 的變化
* 下圖例子, 是/media/pi/bootfs 與 /media/pi/rootfs

* install the kernel modules onto the SD card
```sudo make PATH=$PATH ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=/media/pi/rootfs modules_install```
* back up old kernel
```
KERNEL=kernel8
sudo cp /media/pi/bootfs/$KERNEL.img /media/pi/bootfs/$KERNEL-backup.img
```
* copy the kernel and Device Tree blobs onto the SD card
```
KERNEL=kernel8
sudo cp arch/arm64/boot/Image /media/pi/bootfs/$KERNEL-new.img
sudo cp arch/arm64/boot/dts/broadcom/*.dtb /media/pi/bootfs/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* /media/pi/bootfs/overlays/
```
* edit the /media/pi/bootfs/config.txt file, add the following setting
```kernel=kernel8-new.img```
* To restore the original kernel, remove the above setting
* remove SD card on VM
```
sudo umount /dev/sdX1
sudo umount /dev/sdX2
```
* Insert SD card to PI and boot!! check your kernel version
```uname -r ```

---
---
# topic 2. cross compile
0. 準備一個c code
````
#include <stdio.h>
int main()
{
printf("hello, world\n");
return 0;
}
````
1. 建立流程
````
nano hello.c // write your code
gcc hello.c -o hello.o // compile it, the output file is hello.o
./hello.o // execute hello.o
````
2. Cross compile, then copy it to PI and execute
````
(@VM) aarch64-linux-gnu-gcc hello.c -o hello.arm
(@VM) sudo cp hello.arm /media/pi/rootfs/home/pi/
// 複製hello.arm到PI裡面的家目錄
(@PI) chmod +x hello.arm
(@PI) ./hello.arm
````
---
---
## topic 3. cross compile Tensorflow lite for PI
* Install docker on Ubuntu (VM) or WSL
* WSL = Windows Subsystem for Linux
* Target: Raspberry PI4 (bookworm 64bit) + python 3.11
* 編譯時, 會自動下載相關套件, 建議在網路穩定的地方進行
### download source code
```
git clone https://github.com/tensorflow/tensorflow.git tensorflow_src
cd tensorflow_src
git checkout v2.15.1
```
### 修改Makefile
```nano tensorflow/lite/tools/pip_package/Makefile```
* 修改: BASE_IMAGE ?= ubuntu:20.04
* 調整為: BASE_IMAGE ?= ubuntu:22.04

### 修改Dockerfile
``` nano tensorflow/lite/tools/pip_package/Dockerfile.py3```
* 新增參數: `ENV DEBIAN_FRONTEND=noninteractive`
* 移除舊有cmake安裝指令, 改由apt安裝

### 開始cross compile
```
make -C tensorflow/lite/tools/pip_package docker-build \
TENSORFLOW_TARGET=aarch64 PYTHON_VERSION=3.11
```

* 編譯完產生的檔案路徑: `tensorflow/tensorflow/lite/tools/pip_package/gen/tflite_pip/python3.11/dist/tflite_runtime-2.15.1-cp311-cp311-linux_aarch64.whl`
#### troubleshooting
* If you see "Killed signal terminated program cc1plus",
it usually means WSL/Docker ran out of memory.
Try BUILD_NUM_JOBS=1 or increase WSL memory/swap.

### 複製檔案到PI
* 如果使用WSL, 可於本機端使用網路芳鄰進入WSL資料夾
`檔案總管路徑: \\wsl$\Ubuntu\root\tensorflow_src
`
* 將編譯完的*.whl複製到PI, 然後在新的虛擬環境安裝
```
python -m venv tflite_vmtest
source tflite_vmtest/bin/activate
pip install ./tflite_runtime…..whl
pip list
```
