Cấu hình Device Tree (DTS) cho NPU trên Raspberry Pi CM5
Bạn cần chỉnh sửa file device-tree-source (.dts) để định nghĩa vị trí vật lý, địa chỉ bus và các tài nguyên phần cứng của chip NPU (Neural Processing Unit) gắn trên CM5.
Thao tác này giúp Kernel nhận diện thiết bị mới và tạo nút thiết bị tương ứng trong /sys để driver có thể đăng ký.
Ta sẽ bổ sung node cho NPU vào file rpi5-4gb.dts hoặc file DTS cụ thể của board CM5 của bạn.
Đường dẫn file: /boot/firmware/config/device-tree/dts/overlays/npu-cm5-overlay.dts
Đây là nội dung hoàn chỉnh của file overlay để định nghĩa NPU trên bus I2C (giả định địa chỉ 0x48) với interrupt và clock:
/d/ {
fragment@0 {
target-path = "/soc/i2c@7d500000";
#address-cells = <1>;
#size-cells = <0>;
__overlay__ {
npu@48 {
compatible = "vendor,ai-accelerator-v1";
reg = <0x48>;
interrupt-parent = <&gpio1>;
interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
clocks = <&clk_24mhz>;
clock-names = "core";
power-domains = <&pmu 1>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
};
};
};
};
Kết quả mong đợi: File được lưu, không lỗi cú pháp. Khi biên dịch, nó sẽ tạo ra file .dtbo tương ứng.
Để verify cấu hình này trước khi biên dịch toàn bộ, chạy lệnh kiểm tra cú pháp bằng công cụ dtc:
dtc -I dts -O dtb -o /tmp/npu-cm5-overlay.dtb /boot/firmware/config/device-tree/dts/overlays/npu-cm5-overlay.dts && echo "Syntax OK"
Kết quả mong đợi: Xuất hiện dòng "Syntax OK" trên terminal, không có cảnh báo về lỗi node hay property.
Cấu hình Clock và Power Management cho NPU
Chip NPU cần nguồn điện ổn định và xung nhịp (clock) chính xác để đạt hiệu năng tính toán AI tối đa. Ta phải định nghĩa trong Device Tree để Kernel quản lý việc bật/tắt nguồn và điều chỉnh tần số.
Thao tác này tránh tình trạng NPU treo hoặc reset ngẫu nhiên do thiếu nguồn, đồng thời hỗ trợ tính năng Dynamic Voltage and Frequency Scaling (DVFS).
Sửa file cấu hình clock controller của CM5, thường nằm trong file DTS chính của SoC (Broadcom BCM2712) hoặc file overlay clock.
Đường dẫn file: /boot/firmware/config/device-tree/dts/overlays/npu-clock-pm-overlay.dts
Nội dung hoàn chỉnh để cấu hình clock source và power domain:
/d/ {
fragment@0 {
target-path = "/soc/clk@7d500000";
#address-cells = <1>;
#size-cells = <0>;
__overlay__ {
clk_npu_core: clock-npu-core {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1000000000>; /* 1GHz max */
clock-output-names = "npu-core";
};
};
};
fragment@1 {
target-path = "/soc/pmu@7d900000";
#address-cells = <1>;
#size-cells = <0>;
__overlay__ {
power-domain-npu: power-domain-npu {
compatible = "vendor,power-domain";
#power-domain-cells = <0>;
reg = <1>; /* Domain ID 1 for NPU */
clocks = <&clk_npu_core>;
clock-names = "bus";
};
};
};
};
Kết quả mong đợi: Kernel sẽ nhận diện clock mới và domain điện năng, cho phép driver điều chỉnh tốc độ khi load cao.
Để verify việc clock và power domain đã được nạp vào hệ thống, kiểm tra thông báo khởi động và thư mục sysfs:
dmesg | grep -i "npu.*clock\|npu.*power" && ls -l /sys/class/power_supply/
Kết quả mong đợi: Xuất hiện dòng log xác nhận clock source được register và xuất hiện node power supply mới trong /sys.
Viết Driver I2C/SPI cho cảm biến đầu vào AI
Để AI Edge hoạt động, dữ liệu từ camera hoặc cảm biến môi trường phải được đọc nhanh qua bus I2C hoặc SPI. Ta cần viết một driver đơn giản (platform driver hoặc I2C driver) để thu thập dữ liệu này.
Thao tác này tạo cầu nối giữa phần cứng cảm biến và framework AI (TensorFlow/ONNX) ở user-space thông qua ioctl hoặc sysfs.
Ta sẽ tạo một driver I2C cho cảm biến giả lập (ví dụ: Camera Sensor AI) để minh họa quy trình register device và read data.
Đường dẫn file: /boot/firmware/src/drivers/i2c/sensor-ai-driver.c
Nội dung hoàn chỉnh của file driver C (chỉ bao gồm phần logic chính):
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/of.h>
static int sensor_ai_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
dev_info(&client->dev, "Sensor AI detected at 0x%x\n", client->addr);
/* Initialize hardware here */
i2c_smbus_write_byte(client, 0x00, 0x01); /* Enable power */
dev_info(&client->dev, "Sensor AI initialized successfully\n");
return 0;
}
static int sensor_ai_remove(struct i2c_client *client)
{
dev_info(&client->dev, "Sensor AI removed\n");
return 0;
}
static const struct i2c_device_id sensor_ai_id[] = {
{ "vendor-sensor-ai", 0 },
{ }
};
static struct i2c_driver sensor_ai_driver = {
.driver = {
.name = "sensor-ai",
.of_match_table = of_match_ptr(sensor_ai_of_match),
},
.probe = sensor_ai_probe,
.remove = sensor_ai_remove,
.id_table = sensor_ai_id,
};
static const struct of_device_id sensor_ai_of_match[] = {
{ .compatible = "vendor,ai-sensor-v1", },
{ }
};
module_i2c_driver(sensor_ai_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SysAdmin");
Kết quả mong đợi: File .c được biên dịch thành .ko module không lỗi.
Để build module này vào kernel hoặc load riêng, sử dụng lệnh make với cấu hình Kbuild hiện có:
cd /boot/firmware/src/drivers/i2c && make -C /boot/firmware/src M=$(pwd) modules && insmod sensor-ai.ko
Kết quả mong đợi: Không có lỗi biên dịch. Sau khi chạy insmod, chạy dmesg | tail -n 5 sẽ thấy dòng "Sensor AI detected at 0x..." và "initialized successfully".
Kiểm tra tính toàn vẹn của Device Tree sau khi biên dịch
Sau khi đã chỉnh sửa DTS, cấu hình clock và viết driver, bước cuối cùng là biên dịch toàn bộ Device Tree và nạp vào Kernel để đảm bảo không có xung đột giữa các node.
Thao tác này xác minh rằng các node mới thêm vào (NPU, Clock, Sensor) không vi phạm quy tắc cú pháp hoặc gây xung đột với các thiết bị mặc định của CM5.
Chúng ta sẽ sử dụng công cụ dtc để biên dịch file .dts thành .dtb và kiểm tra bằng devicetree-overlays hoặc boot thử nghiệm.
Đường dẫn file cấu hình overlay để kích hoạt: /boot/firmware/config/device-tree/overlays/npu-cm5-overlay.dtbo
Thực hiện lệnh biên dịch file DTS đã chỉnh sửa thành file DTB binary:
dtc -I dts -O dtb -o /boot/firmware/config/device-tree/overlays/npu-cm5-overlay.dtbo /boot/firmware/config/device-tree/dts/overlays/npu-cm5-overlay.dts
Kết quả mong đợi: File .dtbo được tạo ra, kích thước lớn hơn 0 byte.
Để verify tính toàn vẹn, sử dụng lệnh fdtdump hoặc dtc -I dtb -O dts để reverse lại file binary và so sánh với source, hoặc kiểm tra cấu trúc bằng dtc -I dts -O s -o /tmp/npu.dts /boot/firmware/config/device-tree/overlays/npu-cm5-overlay.dtb:
dtc -I dtb -O dts -o /tmp/verify-npu.dts /boot/firmware/config/device-tree/overlays/npu-cm5-overlay.dtbo && grep -A 5 "npu@48" /tmp/verify-npu.dts
Kết quả mong đợi: Xuất hiện lại cấu trúc node npu@48 với đầy đủ các property (reg, clocks, interrupts) giống như trong file source ban đầu, chứng tỏ quá trình biên dịch và nạp đã thành công.
Điều hướng series:
Mục lục: Series: Tối ưu hóa Linux Kernel cho Raspberry Pi CM5 để chạy AI Edge
« Phần 2: Cấu hình Kernel cho tính năng AI và NPU
Phần 4: Tích hợp Framework AI (TensorFlow Lite / ONNX Runtime) »