4月30日,领导突然交给我一个任务,在Hikey970开发板上搭建录音环境。我只想说另请高明吧。我实在……我也不是谦虚,我一个上层应用开发怎么突然做起嵌入式来了呢?但是,领导讲“已经研究决定了”,后来我就念了两首诗,叫“苟利国家生死以,岂因祸福避趋之”。
准备
领导还在跟我讨论买什么样的麦克风的时候,我突然在论坛中看到,Hikey970开发板默认不支持USB AUDIO
,需要修改内核配置开启。好嘛,还买个啥麦克风,先把音频输入调通再说吧。
根据Android usb audio录音这篇博文的介绍,打开USB AUDIO
配置还是比较容易的,只需要修改/kernel-4.9/sound/usb/Kconfig
文件中的SND_USB_AUDIO
块即可。
下载AOSP源码
还好我不是从零开始,前人已经总结了源码编译AOSP详细步骤。
用repo下载AOSP源码
首先需要安装repo
我使用WSL用apt
命令安装,报错。
最后使用博客windows环境下repo下载Android源代码中推荐的人修改好的repo客户端,点此下载。
初始化repo仓库
使用如下命令,以清华大学AOSP镜像仓库初始化repo:
1 | repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-9.0.0_r8 --no-repo-verify --repo-branch=stable |
开始下载源码
论坛中使用如下命令进行repo仓库同步:
1 | repo sync -j4 |
-j4
的含义为使用四线程进行仓库同步。
但由于AOSP源码过多,常常由于网络原因导致同步中断,报如下错误:
1 | error: error: Exited sync due to fetch errors |
因此需要加上强制同步的选项:
1 | repo sync -j4 -f --force-sync |
下载过程中遇到的坑
aux.h
文件无法创建
开始我是在PowerShell环境进行的源码下载,但每当下载到aux.h
文件时,就会报错文件无法被创建。经查资料,发现aux
是Windows平台的保留文件名,无法被用户使用。不信你可以创建一个aux.txt
试试。
其实除aux之外,Windows还有许多预留文件名不能用,这篇文章做了很好的总结。
具体如下:
1 | CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9 |
在WSL环境进行repo sync
,可以解决这个问题。
大小写不敏感导致的文件丢失
AOSP源码中,有许多源文件是除大小写外相同的,这样在Windows系统clone仓库时可能导致其中一个文件被当作重名文件丢失,或者在编译时会导致错误包含头文件 (坑爹的Windows)。
可通过如下python脚本批量设置目录下所有文件夹的文件大小写敏感:
1 | import os |
也可在WSL下使用如下命令设置或获取目录是否大小写敏感(需要apt install attr
):
1 | 设置 |
可以通过上述方式先创建一个大小写敏感的目录,然后将代码仓库解压到该目录下,则新生成的目录都是大小写敏感的了。
下载并编译Hikey 970内核源码
本地clone
根据论坛的建议,原生的kernel不能boot这个版本的AOSP,会导致各种问题,需要重新clone linaro官方针对hikey970的kernel源码。
1 | git clone https://github.com/96boards-hikey/linux.git -b hikey970-v4.9 linux |
但国内的网络环境,clone github仓库只有20KBps的速度,下载这三四个GB的仓库要到猴年马月。
于是首先尝试挂代理,我的计算机上部署有V2ray的socks5代理,代理端口号为10808,于是使用如下命令进行git全局代理设置:
1 | 开启全局代理 |
但设置代理后,像内核源码这么大的仓库,还是会失败。
VPS clone
在经历无数次的失败后,我直接使用VPS clone源码,然后用FTP协议将仓库打包传送到了本地。
修改USB AUDIO配置
整个任务就是围绕这一步进行的,前文说过,打开USB AUDIO配置的方法为,只需要修改/kernel-4.9/sound/usb/Kconfig
文件中的SND_USB_AUDIO
块。
1 | config SND_USB_AUDIO |
内核编译
使用如下命令进行编译,注意需要目录大小写敏感。
1 | cd $AOSP_ROOT/kernel/linux |
生成的目标为:
1 | AOSP_ROOT/kernel/linux/arch/arm64/boot/dts/hisilicon/kirin970-hikey970.dts |
生成系统镜像
其实,本次任务并不需要完整的编译整个AOSP,我们可以使用96boards官方提供的AOSP系统镜像,只是替换其中的内核即可。
AOSP/bootloader编译
我们跳过了AOSP编译这一步,实属无奈,120GB的硬盘都沾满了,实在放不下那么多目标文件。
同样,bootloader
获取也跳过,直接用官方镜像。
AOSP编译生成的目标文件为:
1 | 即使是编译生成的boot.img,也需要手动替换其内核 |
bootloader编译的产物为:
1 | AOSP_ROOT/bootloader/l-loader/ptable-aosp-64g.img |
而我们下载的官方镜像目录下的文件如下:
1 | hikey970 |
可以看到,所有目标文件都是存在的。
重新打包boot.img
解包boot.img
在$AOSP_ROOT/system/core/mkbootimg
目录下,有着unpack_bootimg
可执行程序,可以在WSL中运行,它可以将boot.img
解包:
1 | unpackbootimg -i ./boot.img -o ./output |
则会生成output目录,目录下有boot
、ramdisk
、second
三个文件。其中,boot
就是我们要替换的内核,而ramdisk
包含了Andoroid系统的文件系统信息,这里不展开了。
生成新boot
其实就是将内核编译的两个产物合并为一个:
1 | cat $AOSP_ROOT/kernel/linux/arch/arm64/boot/Image $AOSP_ROOT/kernel/linux/arch/arm64/boot/dts/hisilicon/kirin970-hikey970.dtb > $AOSP_ROOT/Image-dtb |
打包boot.img
将刚刚生成的Image-dtb
也拷贝到output
目录下,然后执行:
1 | mkbootimg --kernel ./output/Image-dtb --ramdisk ./output/ramdisk --cmdline "androidboot.hardware=hikey970 firmware_class.path=/system/etc/firmware loglevel=15 buildvariant=userdebug androidboot.selinux=permissive clk_ignore_unused=true initrd=0xBE19D000,0x16677F earlycon=pl011,0xfff32000,115200 console=ttyAMA6 androidboot.serialno=54DA9CD5022525E4 clk_ignore_unused=true" -o boot.img |
则生成了全新的boot.img
。
烧写
Windows环境下,执行update_Hikey970.bat
即可。
验证
以cat /proc/asound/cards
命令查看设备,果然有了USB AUDIO设备,成功~