当前位置: 首页 > news >正文

嵌入式开发实战:为Android设备交叉编译mmc-utils工具集

1. 为什么需要交叉编译mmc-utils

在嵌入式开发中,我们经常需要与eMMC存储设备打交道。mmc-utils就是这样一套专门用于管理eMMC存储设备的实用工具集,它提供了读取extcsd、修改分区配置、设置写保护等强大功能。但问题来了——Android设备通常没有预装这些工具,而直接在设备上编译又几乎不可能,这就是交叉编译技术大显身手的时候了。

交叉编译简单说就是在PC上编译出能在ARM架构Android设备上运行的程序。我最近在调试一块基于Rockchip SoC的开发板时就遇到了这个问题:需要修改eMMC的boot分区配置,但设备上缺少必要的工具。通过交叉编译mmc-utils,最终成功解决了这个问题。

2. 搭建编译环境

2.1 获取源码

第一步当然是获取mmc-utils的源代码。官方仓库托管在GitHub上,我们可以直接克隆:

git clone https://github.com/mhei/mmc-utils.git cd mmc-utils

建议使用最新release版本而非master分支,因为主分支可能包含未经验证的改动。我上次就踩过坑,用了master分支导致编译出的工具在设备上运行崩溃。

2.2 准备交叉编译工具链

Android环境下有两种主要编译方式:

  1. AOSP完整编译环境:适合已经在做系统级开发的团队
  2. Android NDK独立工具链:更适合单独编译某个工具

对于大多数开发者,我推荐使用NDK方式,因为它更轻量。下载NDK后,需要生成独立的工具链:

# 假设NDK安装在/opt/android-ndk /opt/android-ndk/build/tools/make-standalone-toolchain.sh \ --arch=arm \ --platform=android-21 \ --install-dir=/opt/ndk-standalone

这里有几个关键参数需要注意:

  • --arch:必须匹配目标设备的CPU架构(arm/arm64/x86等)
  • --platform:Android API级别,建议不低于设备系统版本
  • --install-dir:工具链安装路径

3. 解决编译问题

3.1 头文件缺失问题

直接编译通常会遇到第一个错误:找不到endian.h头文件。这是因为Android的C库与标准Linux有所不同。解决方法是在mmc_cmds.c文件开头添加:

#include <endian.h>

如果仍然报错,可以尝试使用Android提供的替代方案:

#include <sys/endian.h>

3.2 结构体初始化问题

第二个常见问题是结构体未完全初始化导致的编译错误。在mmc.c文件中,需要补全commands数组的所有字段。原始代码可能像这样:

{ do_read_extcsd, -1, "extcsd read", "<device>\n" "Print extcsd data from <device>.", NULL }

需要修改为:

{ do_read_extcsd, -1, "extcsd read", "<device>\n" "Print extcsd data from <device>.", NULL, NULL, 0 }

这个修改确保了结构体的所有字段都被正确初始化。我在第一次编译时忽略了这个问题,导致工具运行时出现段错误,排查了很久才发现是这个原因。

4. 编译与部署

4.1 使用Android.mk编译

如果你使用AOSP环境,可以创建一个Android.mk文件:

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := mmc_utils LOCAL_SRC_FILES := mmc.c mmc_cmds.c LOCAL_CFLAGS := -Wall -Werror LOCAL_MODULE_TAGS := optional include $(BUILD_EXECUTABLE)

然后在AOSP根目录下执行:

source build/envsetup.sh lunch <你的设备配置> mmma external/mmc-utils

编译完成后,可执行文件会生成在out/target/product/<设备>/system/bin目录下。

4.2 使用NDK独立编译

如果使用NDK工具链,需要修改Makefile:

CC = /opt/ndk-standalone/bin/arm-linux-androideabi-gcc CFLAGS = -Wall -Werror -pie -fPIE LDFLAGS = -pie -fPIE all: mmc_utils mmc_utils: mmc.o mmc_cmds.o $(CC) $(LDFLAGS) -o $@ $^ clean: rm -f *.o mmc_utils

编译命令很简单:

make

4.3 部署到设备

无论哪种方式编译出的二进制文件,都需要推送到设备上:

adb push mmc_utils /data/local/tmp/ adb shell chmod +x /data/local/tmp/mmc_utils

如果需要永久安装,可以推送到/system/bin(需要root权限):

adb remount adb push mmc_utils /system/bin/ adb shell chmod 755 /system/bin/mmc_utils

5. 实际使用案例

5.1 读取eMMC信息

最基本的用法是读取eMMC的extcsd信息:

mmc_utils extcsd read /dev/block/mmcblk0

这个命令会输出eMMC的所有配置参数,包括:

  • 设备容量
  • 分区大小
  • 支持的命令集
  • 当前工作模式

我在调试一个启动问题时,就是通过这个命令发现boot分区大小配置不正确导致的。

5.2 修改boot分区配置

如果需要修改boot分区设置,可以使用:

mmc_utils bootpart enable 1 1 /dev/block/mmcblk0

这个命令:

  • 启用第一个boot分区(参数1)
  • 设置需要ACK确认(第二个参数1)
  • 操作设备/dev/block/mmcblk0

特别注意:很多eMMC操作是一次性编程(OTP)的,修改后无法恢复,操作前务必确认参数正确。

5.3 RPMB安全区域操作

对于安全要求高的场景,可能需要操作RPMB区域:

# 写入RPMB密钥 echo -n "32字节密钥内容" > rpmb_key.bin mmc_utils rpmb write-key /dev/block/mmcblk0rpmb rpmb_key.bin # 读取RPMB计数器 mmc_utils rpmb read-counter /dev/block/mmcblk0rpmb

RPMB操作需要特别注意权限问题,普通应用通常无法直接访问这些设备节点。

6. 常见问题排查

6.1 权限问题

在非root设备上,可能会遇到权限不足的错误:

error: could not open device /dev/block/mmcblk0

解决方法:

  1. 使用root权限运行
  2. 修改设备节点权限(需要root)
  3. 使用已经有权访问的组(如system组)

6.2 版本兼容性问题

不同eMMC版本支持的指令可能不同。如果遇到"invalid command"错误,可以先检查extcsd中的eMMC版本:

mmc_utils extcsd read /dev/block/mmcblk0 | grep "eMMC Version"

6.3 工具运行崩溃

如果工具运行直接崩溃,可能是:

  1. 编译时架构不匹配(如用ARMv7工具链编译但设备是ARMv8)
  2. 缺少必要的库文件(可以用NDK静态编译解决)
  3. 内核版本不兼容

7. 进阶技巧

7.1 静态编译

为避免依赖问题,可以静态链接所有库。在Makefile中添加:

LDFLAGS += -static

这样编译出的二进制文件会稍大,但可以在任何同架构设备上运行。

7.2 调试符号

遇到问题时,可以保留调试符号:

CFLAGS += -g

编译后用ndk-stack工具分析崩溃日志:

adb logcat | ndk-stack -sym ./obj/local/armeabi-v7a/

7.3 自动化脚本

对于需要频繁执行的操作,可以编写shell脚本:

#!/system/bin/sh # 备份当前extcsd配置 mmc_utils extcsd read /dev/block/mmcblk0 > /sdcard/extcsd_backup.txt # 修改boot配置 mmc_utils bootpart enable 1 1 /dev/block/mmcblk0 # 验证修改 mmc_utils extcsd read /dev/block/mmcblk0 | grep "BOOT_CONFIG"

记得给脚本执行权限:

chmod +x /sdcard/emmc_config.sh
http://www.jsqmd.com/news/624305/

相关文章:

  • 2026精选记事软件前五名轻松管理日常待办事项
  • 模型热回滚失败率高达63%?揭秘TensorRT引擎+ONNX Runtime双栈下3类不可逆版本污染场景
  • 三步实现Navicat Mac版试用期无限重置:开源脚本全攻略
  • 积分增值模式的技术逻辑:双动态调节 + 营销蓄水池,无需人工控盘
  • Harness Engineering:为什么最强的 AI 也需要一个操作系统
  • VSCode插件党福音:实测阿里通义灵码的代码续写与注释生成到底有多香
  • RPG Maker解密终极指南:3步解锁游戏加密资源
  • 告别人工看图:用Python+STFT实现雷达信号自动分类(附LFM/相位编码等6种信号代码)
  • 误删 Windows 文件不用慌,保姆级恢复教程
  • 破译 Intellij IDEA 2025.3.4 (windows) -
  • virtio系列-从规范到实践:深入解析virtqueue设计与性能优化
  • Python连接Access数据库避坑指南:从驱动安装到连接字符串的完整配置流程
  • SukiUI实战指南:构建现代化Avalonia桌面应用的三大核心策略
  • GitHub中文界面全解析:技术实现与使用指南
  • 归一化vs标准化:用sklearn代码示例告诉你何时该用哪个
  • 大模型RAG落地失败率高达67%?2026奇点大会首次公开12家头部企业RAG成熟度评估矩阵(限时领取PDF版)
  • 终极批量文本处理指南:FNR工具的高效使用秘籍
  • 小白程序员必看!收藏这份AI大模型入门指南,带你轻松入门人工智能世界!
  • 从单点技能到流程编排:在 Anything LLM 中构建可复用的 AI 智能体工作流
  • 工业五官:10 未来的传感器会自己发电、自己联网、自己判断
  • PIDtoolbox架构方案:基于黑盒日志分析的工业控制系统参数优化实现
  • 如何打破OBS视频输出限制?4路虚拟摄像头解决方案完全指南
  • 终极指南:如何在Linux上开发微信小程序?告别Windows依赖的完整方案
  • ACL访问控制列表(Access Control List)
  • 3分钟免费搞定APA第7版:Word参考文献格式终极完整指南
  • 基于Python的农产品销售系统毕业设计源码
  • 记一次Webshell流量分析 | 添柴不加火琶
  • DCT-Net人像卡通化WebUI定制化:添加水印/自动裁剪/格式转换
  • LG1300L_IMU驱动库:LEGO专用IMU的I²C裸机驱动与协议逆向实现
  • 【技术解析】MAMBA架构:如何通过选择性状态空间模型革新长序列处理