跳到主要内容

SDK 编译部署

概述​

MTT E300 Software SDK(Software Development Kit)是面向 MTT E300 的软件开发工具包,基于 Yocto Project 构建,提供完整的编译、部署和定制化解决方案。


SDK 开发环境部署组件​

编号文件名说明
1yocto_dev_img_ubuntu20.04:v4.0.tar.gzSDK 运行依赖的 Docker image
2runYoctoDevDock_7.0.shDocker image 配置和运行脚本
3m1000-soc-sw-sdkSDK 编译部署目录
4downloads.tar.gzSDK 编译所依赖的库和中间件
5ubuntu-rootfs.ext4编译 rootfs 镜像需要的基础文件
6generate_wic.shu-boot 编译后更新 wic 的脚本文件
7source code项目开发中需要修改的代码仓库

SDK Repo 目录结构​

m1000-soc-sw-sdk/
├── README # Readme 文档,链接自 meta/base/README
├── .config # 用户配置文件
├── fip-prebuild # fip.bin
├── downloads # SDK 编译依赖库
├── setup_env.sh # 环境配置脚本,链接自 meta/base/setup_env.sh
└── meta/
├── base/ # 基础配置层
│ ├── conf/
│ │ ├── bblayers.conf # 默认 bblayers.conf 模板文件
│ │ └── user_default.conf # 用户默认设置文件
│ └── setup_env.sh # 环境配置脚本
├── meta-test/ # 测试层
├── meta-sample/ # 示例层(应用/demo)
├── meta-midware/ # 中间件集成层
├── meta-bsp/ # BSP 层(Bootloader/TF-A/SCP 固件等)
├── meta-distro/ # 发行版策略层(镜像构建)
├── meta-m1000/ # 硬件抽象层(机器特定配置)
└── meta-oe-layers/ # Yocto 官方 Poky 项目 v(Kirkstone)
├── bitbake/
├── meta-openembedded/
├── poky/
└── openembedded-core/


运行原理​


编译产物说明​

产物名称说明用途
u-boot.binU-Boot 引导程序芯片启动第一阶段
m1000_entry_v1.0.0-oem.binEntry Table 配置芯片启动配置
soc-firmware-image.wic完整固件镜像包含所有启动组件
ImageLinux 内核镜像操作系统内核
*.dtb设备树文件硬件描述
m1000-image-ubuntu-*.wic根文件系统镜像完整系统镜像

部署编译流程​

  1. 安装 Docker
  2. 配置 Docker image 环境
  3. 启动 Docker image
  4. 建立 Yocto 编译所需目录
  5. 配置 SDK 编译环境变量
  6. 添加源码路径
  7. 修改相关模块代码或 rootfs 定制化修改
  8. 执行编译命令,生成 Image,并用运行验证

SDK 编译流程


固件组成说明​

wic 文件结构:

  • wic 包含:firmwares + entrytable(包含在 firmwares 中)+ scp.bin + tfa.bin + u-boot.bin

fip.bin 结构:

  • fip.bin 包含:scp.bin + tfa.bin + u-boot.bin

快速开始​

准备文件​

从 TOS 下载以下文件:

  • yocto_dev_img_ubuntu20.04.tar - Docker 镜像
  • runYoctoDevDock_7.0.sh - Docker 启动脚本
  • downloads.tar.gz - 编译依赖库
  • ubuntu-rootfs.ext4 - 根文件系统基础镜像
  • generate_wic.sh - WIC 打包脚本

TOS 下载路径:

tos://ab100-sw/AI MODULE/AI MODULE UBOOT (平台化版本)/v1.6.0/Docker/Rootfs/
访问说明

如需获取本文中未提供直接下载链接、仅标注为从 TOS 获取的资源,请邮件联系 tao.tao@mthreads.com。我们会协助您完成 NDA 流程,并在签署后提供访问权限。


安装步骤​


步骤 1:安装 Docker​

# 安装 Docker及基础依赖
sudo apt update
sudo apt install -y net-tools docker.io

步骤 2:配置 Docker 权限​

# 配置 Docker 权限
sudo usermod -aG docker $USER
sudo groupadd docker
sudo systemctl restart docker
sudo newgrp docker

# 验证 Docker 权限
sudo reboot
docker ps

步骤 3:加载 Docker 镜像​

# 加载 Docker 镜像
tar xvf yocto_dev_img_ubuntu20.04.tar
gunzip -c yocto_dev_img_ubuntu20.04:v4.0.tar.gz | docker load

步骤 4:启动 Docker 容器​

# 启动 Docker 容器(首次需运行两次)
./runYoctoDevDock_7.0.sh
提示

注意:首次执行需要运行两次,第一次用于生成用户目录。


步骤 5:准备 SDK 工作环境​

# 创建工作目录
mkdir -p ~/sdk
cd ~/sdk

# 克隆 SDK 源码
git clone git@gitee.com:MooreThreadsNDA/m1000-soc-sw-sdk.git
cd m1000-soc-sw-sdk

# 解压依赖
tar zxvf ../downloads.tar.gz

# 如果下载 ext4 文件,直接解压放在 downloads 下
tar zxvf ubuntu-rootfs_basic_20250626_32G.ext4.tgz

步骤 6:配置编译参数(非RT linux)​

  1. 进入工作目录

    cd m1000-soc-sw-sdk
  2. menuconfig配置

    务必执行 menuconfig 进行配置(通常保持默认即可):

    配置界面 1

    配置界面 2

    配置界面 3

    如果对配置文件有修改,必须重新执行source命令。

  3. source使配置生效

    cd m1000-soc-sw-sdk
    source setup_env.sh build

(可选)步骤 7:配置编译参数(RT linux)​

RTLinux 是面向实时场景的 Linux 实时扩展,适用于工业控制、机器人、汽车控制、低延迟音视频、高频数据采集和电机控制等场景。它重点关注从事件发生到任务开始执行的最坏延迟是否可控,而不只是平均性能。 相较于通用 Linux 更侧重吞吐量、公平性和平均响应时间,实时 Linux 通过实时调度、增强内核抢占、中断线程化及优先级继承等机制,降低调度与锁竞争带来的延迟抖动。 实时性通常以部分吞吐量、缓存局部性和系统开销为代价。现代 Linux 的实时化方案通常指 PREEMPT_RT。

如果需要开启RT-kernel请在步骤 6:配置编译参数 (非RT linux)基础上增加配置 :

  1. 进入工作目录

    cd m1000-soc-sw-sdk
  2. 在6.2的基础上增加配置RT linux

    配置界面 4

    配置界面 5

  3. source使配置生效

    cd m1000-soc-sw-sdk
    source setup_env.sh build

注意: 在首次安装RT kernel之前, 需要手动重新安装RT kernel适配的acdev/npu驱动:

  1. 卸载旧的驱动

    sudo dpkg -P kernel-module-m1000-npu
    sudo dpkg -P kernel-module-m1000-actool
  2. 参考对应章节:更新 Kernel

  3. 重新安装acdev/npu驱动 RTK专用驱动下载路径:

    # 注意: 以下acdev/npu驱动deb名为示例,最终以实际RTLinux目录下deb文件为准.
    cd ./RTLinux
    sudo dpkg -i ./kernel-module-m1000-actool_2.13+gitAUTOINC+476c4cc747_aarch64.deb
    sudo dpkg -i ./kernel-module-m1000-npu_1.6.0-r20260729031608-472cf65_all.deb

RT kernel测试示例:

  1. 负载,隔离场景,cpu07为 housekeeping 且 cpu811 为被隔离cpu,在被隔离核cpu8~11 开启优先级90的实时任务,运行12小时
#Uboot env
setenv bootextraarg 'quiet splash isolcpus=managed_irq,domain,8-11 rcu_nocbs=8-11 irqaffinity=0-7 cpuidle.off=1'

#系统测试
sudo su
./isolcpus_rtlinux.sh 90 12 --stress

参考脚本: isolcpus_rtlinux.sh

#!/bin/bash

check_running_as_root() {
uid="$(id -u 2>/dev/null)"

if [ "$uid" = "0" ]; then
echo "pass: running as root"
else
echo "fail: not running as root"
echo "info: please run with <sudo su> first"
exit
fi
}

check_running_as_root
echo

if [ $# -lt 2 ];then
echo "./isolcpus_rtlinux.sh <优先级> <测试时长:小时> [--stress:否则为空载]"
exit
fi

# Disable powercapping:
echo "read power capping enable[0]/disable[2]: $(ac_tool register r32 -a 0x280fd2c0)"
echo "read hwmon power capping enable[0]/disable[1]: $(cat /sys/devices/platform/soc@0/75b000.i2c/i2c-18/18-0040/hwmon/hwmon*/powercapping_disable)"
#echo "disable power capping: $(ac_tool register w32 -a 0x280fd2c0 -v 2)"
echo "disabling power capping $(echo 1 > /sys/devices/platform/soc@0/75b000.i2c/i2c-18/18-0040/hwmon/hwmon*/powercapping_disable) ..."
echo "read power capping enable[0]/disable[2]: $(ac_tool register r32 -a 0x280fd2c0)"
echo "read hwmon power capping enable[0]/disable[1]: $(cat /sys/devices/platform/soc@0/75b000.i2c/i2c-18/18-0040/hwmon/hwmon*/powercapping_disable)"
echo

# Enable VPU performance
echo "read VPU devfs governor: $(cat /sys/devices/platform/soc@0/200000.vpu/devfreq/200000.vpu/governor)"
echo "enabling VPU performance $(echo performance > /sys/devices/platform/soc@0/200000.vpu/devfreq/200000.vpu/governor) ..."
echo "read VPU devfs governor: $(cat /sys/devices/platform/soc@0/200000.vpu/devfreq/200000.vpu/governor)"
echo

# Disable cpuidle state0: CONFIG_ARM_PSCI_CPUIDLE 已默认关闭, 无以下节点
#echo -e "cpuidle state0 enable[0]/disable[1]: \n$(cat /sys/devices/system/cpu/cpu*/cpuidle/state0/disable)"
#echo "disabling cpuidle state0 on core 8~11 ..."
##echo 1 > /sys/devices/system/cpu/cpu0/cpuidle/state0/disable
##echo 1 > /sys/devices/system/cpu/cpu1/cpuidle/state0/disable
##echo 1 > /sys/devices/system/cpu/cpu2/cpuidle/state0/disable
##echo 1 > /sys/devices/system/cpu/cpu3/cpuidle/state0/disable
#echo 1 > /sys/devices/system/cpu/cpu4/cpuidle/state0/disable
#echo 1 > /sys/devices/system/cpu/cpu5/cpuidle/state0/disable
#echo 1 > /sys/devices/system/cpu/cpu6/cpuidle/state0/disable
#echo 1 > /sys/devices/system/cpu/cpu7/cpuidle/state0/disable
#echo 1 > /sys/devices/system/cpu/cpu8/cpuidle/state0/disable
#echo 1 > /sys/devices/system/cpu/cpu9/cpuidle/state0/disable
#echo 1 > /sys/devices/system/cpu/cpu10/cpuidle/state0/disable
#echo 1 > /sys/devices/system/cpu/cpu11/cpuidle/state0/disable
#echo -e "cpuidle state0 enable[0]/disable[1]: \n$(cat /sys/devices/system/cpu/cpu*/cpuidle/state0/disable)"
#echo

# Disable cpuidle state1: CONFIG_ARM_PSCI_CPUIDLE 已默认关闭, 无以下节点
#echo -e "cpuidle state1 enable[0]/disable[1]: \n$(cat /sys/devices/system/cpu/cpu*/cpuidle/state1/disable)"
#echo "disabling cpuidle state1 on core 8~11 ..."
##echo 1 > /sys/devices/system/cpu/cpu0/cpuidle/state1/disable
##echo 1 > /sys/devices/system/cpu/cpu1/cpuidle/state1/disable
##echo 1 > /sys/devices/system/cpu/cpu2/cpuidle/state1/disable
##echo 1 > /sys/devices/system/cpu/cpu3/cpuidle/state1/disable
#echo 1 > /sys/devices/system/cpu/cpu4/cpuidle/state1/disable
#echo 1 > /sys/devices/system/cpu/cpu5/cpuidle/state1/disable
#echo 1 > /sys/devices/system/cpu/cpu6/cpuidle/state1/disable
#echo 1 > /sys/devices/system/cpu/cpu7/cpuidle/state1/disable
#echo 1 > /sys/devices/system/cpu/cpu8/cpuidle/state1/disable
#echo 1 > /sys/devices/system/cpu/cpu9/cpuidle/state1/disable
#echo 1 > /sys/devices/system/cpu/cpu10/cpuidle/state1/disable
#echo 1 > /sys/devices/system/cpu/cpu11/cpuidle/state1/disable
#echo -e "cpuidle state1 enable[0]/disable[1]: \n$(cat /sys/devices/system/cpu/cpu*/cpuidle/state1/disable)"
#echo

# Disable cpu_manage on acdev:
echo "cpu manage enable[1]/disable[0]: $(cat /sys/kernel/cpu_manage/enable)"
echo "disabling cpu manage on acdev $(echo 0 > /sys/kernel/cpu_manage/enable) ..."
echo "cpu manage enable[1]/disable[0]: $(cat /sys/kernel/cpu_manage/enable)"
echo

if [ $# -eq 3 ] && [ "$3"x == "--stress"x ];then
echo "12 cpus stress:"
stress --cpu 12 &
#taskset -c 1-7 stress --cpu 11 &
sleep 2
echo
fi

date
echo

# Housekeeping cpu : core 0~7
# Isolated cpus : core 8~11
echo "time taskset -c 8-11 sudo cyclictest -m -Sp$1 -i200 -D$2h -b50"
echo

#sudo sh -c 'echo 0 > /proc/sys/kernel/timer_migration'

time taskset -c 8-11 sudo cyclictest -m -Sp$1 -i200 -D$2h -b50
#time taskset -c 0,8-11 sudo cyclictest \
# -m -p90 -i200 -d0 -D24h -b50 \
# -t4 -a8-11 \
# --mainaffinity=0 \
# --tracemark

#sudo sh -c 'echo 1 > /proc/sys/kernel/timer_migration'

echo
date
  1. 模型,隔离场景,cpu07为 housekeeping 且 cpu811为被隔离cpu,在被隔离核cpu8~11 开启优先级90的实时任务
#Uboot env
setenv bootextraarg 'quiet splash isolcpus=managed_irq,domain,8-11 rcu_nocbs=8-11 irqaffinity=0-7 cpuidle.off=1'

#被隔离实时任务启动
time taskset -c 8-11 sudo cyclictest -m -Sp90 -i200 -D12h -b50

步骤 8:生成用户签名​

# 生成用户签名
fip-prebuild/cert_create -n -k --key-alg rsa --key-size 2048 \
--nt-fw-key fip-prebuild/pri_user.pem
提示

重要:同一家公司,请使用同一签名,否则混刷 soc.wic 可能会导致不开机。


编译​


添加源码路径​

# 克隆源码
cd m1000-soc-sw-sdk
git clone git@gitee.com:MooreThreadsNDA/m1000-entrytable.git
git clone --recurse-submodules git@gitee.com:MooreThreadsNDA/m1000-uboot.git -b release_M1000_1.6.0
git clone git@gitee.com:MooreThreadsNDA/m1000-linux-kernel.git
cd m1000-linux-kernel
git checkout release_M1000_1.6.0
cd ../m1000-entrytable
git checkout release_M1000_1.6.0
# 使用 devtool 添加源码路径
devtool modify -n m1000-entry-table-tool ../m1000-entrytable
devtool modify -n u-boot-mt ../m1000-uboot
devtool modify -n linux-mthreads ../m1000-linux-kernel

如果需要修改路径或删除路径,可使用 devtool reset <module>,然后重新执行 devtool modify -n 命令进行更新。


编译步骤概述​

  1. 编译 u-boot 源码,生成 u-boot.bin
  2. 编译 entry-table 源码,生成 m1000_entry_v1.0.0-oem.bin
  3. 打包生成 soc-firmware-image.wic
  4. 如果 u-boot 代码有更新:
    • 执行 generate_wic.sh 脚本,快速替换 fip.bin 中的原始 u-boot.bin wic 文件
  5. 如果重新编译了 m1000_entry_v1.0.0-oem.bin,请替换 fip-prebuild/firmware 下的相应文件,并重新编译 soc-firmware-image.wic
  6. 对最终生成的 soc-firmware-image.wic 文件进行签名
  7. 编译 image & dtb
  8. 编译 rootfs.wic

编译 U-Boot​

# 执行环境配置脚本
source setup_env.sh build
# 使用 devtool modify 创建 u-boot 源码路径
devtool modify -n u-boot-mt ../m1000-uboot/

# 执行成功后会自动进入 build 目录
# 编译 u-boot
bitbake u-boot-mt

查看编译输出目录:

# 查看编译输出目录
ls tmp/deploy/images/aimodule/

u-boot-aimodule-2025.04-r0.bin
u-boot-mt-initial-env
u-boot-aimodule.bin
u-boot-mt-initial-env-aimodule
u-boot.bin
u-boot-mt-initial-env-aimodule-2025.04-r0

如果编译成功,会在上述目录中生成 u-boot.bin 文件。

如果编译失败,可执行以下命令清除并重新编译:

# 清除并重新编译
bitbake u-boot-mt -c cleanall

cleanall 也适用于清除其他镜像的编译缓存。


编译 Entry-Table​

如果修改了 GPIO 配置,需要重新编译 entry-table:

source setup_env.sh build
devtool modify -n m1000-entry-table-tool /home/xxx/m1000-entrytable
bitbake m1000-entry-table-tool
ls tmp/deploy/images/aimodule/firmwares
m1000_entry_oem.bin
m1000_entry_v1.0.0-oem.bin

编译 soc-firmware-image.wic​

wic 包含:firmwares + entrytable(包含在 firmwares 中)+ scp.bin + tfa.bin + u-boot.bin。fip.bin 包含:scp.bin + tfa.bin + u-boot.bin。

默认情况下,build/tmp/deploy/images/aimodule/ 目录下没有 .wic 文件。

初次编译 soc-firmware-image.wic 时,直接按照下述流程编译:

source setup_env.sh build
cp ../fip-prebuild/fip.bin ./tmp/deploy/images/aimodule/.
bitbake soc-firmware-image
ls tmp/deploy/images/aimodule/
soc-firmware-image-aimodule.rootfs-xxx.rootfs.manifest
soc-firmware-image-aimodule.rootfs-xxx.testdata.json
soc-firmware-image-aimodule.rootfs-xxx.rootfs.wic

如果 entrytable 有改动,编译完成后替换 build/tmp/deploy/images/aimodule/firmwares 目录下对应文件 m1000_entry_v1.0.0-oem.bin,再重新编译 wic,并替换 fip-prebuild/firmware/ 下的对应文件。

如果修改了 u-boot 源码,重新编译的 bin 可以通过脚本 generate_wic.sh 方便地替换旧的 u-boot.bin,并且重新打包成新的 soc-firmware-image.wic。


替换 wic 中的 u-boot.bin 并重新打包​

修改 u-boot 代码后,按照下面步骤编译打包 wic 文件:

# 进入m1000-soc-sw-sdk路径
cd m1000-soc-sw-sdk
# 测试 fiptool 是否可用
fiptool version

# 此脚本针对修改 u-boot 源码后,重新打包 wic
./generate_wic.sh

generate_wic.sh 脚本替换 fip.bin 中的 u-boot.bin,并且重新打包 soc-firmware-image.wic。


编译 Kernel Image 和 DTB​

在 m1000-soc-sw-sdk 目录下执行:

# 执行环境配置脚本
source setup_env.sh build

# 指定内核源码路径(使用绝对路径)
devtool modify -n linux-mthreads ../m1000-linux-kernel/

# 执行成功后会自动进入 build 目录
# 编译 kernel image 和 dtb
bitbake linux-mthreads

在 build/tmp/deploy/images/aimodule/ 目录下会生成对应 Image 和 DTB 文件:

ls tmp/deploy/images/aimodule/

Image
Image-aimodule.bin
Image.gz
Image.gz-aimodule.bin
m1000-aimodule-aimodule.dtb
m1000-aimodule.dtb
modules-aimodule.tgz

编译 Kernel Image 和对应的 debs​

在 m1000-soc-sw-sdk 目录下执行:

# 执行环境配置脚本
source setup_env.sh build

# 执行成功后会自动进入 build 目录
bitbake linux-mthreads -c cleanall

# 编译 Kernel Image & debs
build-linux-deps.sh

在 build/tmp/deploy/images/aimodule/ 目录下会生成对应 Image 和 deb 文件:

ls tmp/deploy/images/aimodule/debs
linux-headers-7.0.14-xxx_arm64.deb
linux-image-7.0.14-xxx_arm64.deb
linux-libc-dev_7.0.14-xxx_arm64.deb

编译 Rootfs​

请先确认执行脚本 build-linux-deps.sh 编译了包含 kernel image、linux headers、ko 的 deb 包。 即 build/tmp/deploy/images/aimodule/debs 目录下的 deb 包。

将 musa 等包移入 m1000-soc-sw-sdk/musa-debs 目录下,编译 rootfs 时自动安装 musa 包。

如果宿主机和 rootfs 的架构不一致,执行下列命令:

# 在宿主机
sudo apt update
sudo apt install qemu-user-static binfmt-support
sudo update-binfmts --enable qemu-aarch64

在 m1000-soc-sw-sdk 目录下执行:

# 执行环境配置脚本
source setup_env.sh build

# 执行成功后会自动进入 build 目录
# 编译 rootfs
bitbake m1000-image-ubuntu

在 build/tmp/deploy/images/aimodule/ 目录下会生成对应 rootfs 文件:

ls build/tmp/deploy/images/aimodule/
m1000-image-ubuntu-aimodule-xxx.rootfs.ext4
m1000-image-ubuntu-aimodule-xxx.rootfs.wic
m1000-image-ubuntu-aimodule-xxx.rootfs.manifest
m1000-image-ubuntu-aimodule-xxx.rootfs.testdata.json

编译 U 盘启动 iso 镜像​

cd m1000-soc-sw-sdk/udisk-upgrade-aimodule
chmod 755 *.sh
sudo ./env_init.sh
sudo ./mk_all.sh
ll m1000-soc-sw-sdk/udisk-upgrade-aimodule/out/m1000-aimodule-ubuntu-xxx.iso

使用此 iso 镜像制作 U 盘启动盘,参考系统烧录和系统安装指南进行系统烧录。