AIGlasses OS Pro Linux系统开发:从入门到实战

📅 发布时间:2026/7/12 19:48:44 👁️ 浏览次数:
AIGlasses OS Pro Linux系统开发:从入门到实战
AIGlasses OS Pro Linux系统开发从入门到实战最近有不少做嵌入式开发的朋友问我现在那些能实时识别、对话的智能眼镜挺火的它们背后的系统到底是怎么开发的特别是基于Linux的定制系统听起来门槛很高。正好我最近花了不少时间研究AIGlasses OS Pro这套系统它就是一个跑在智能眼镜上的深度定制Linux。今天我就把自己从零开始摸索的整个过程包括环境怎么搭、驱动怎么写、应用怎么跑都整理出来。如果你对嵌入式Linux开发感兴趣或者想了解智能硬件背后的软件世界这篇文章应该能给你一个清晰的路线图。整个过程其实没有想象中那么神秘核心就是理解一个为特定硬件“量身定做”的Linux系统是如何构建和运行的。我们不用从零造轮子而是学会如何在已有的框架上让硬件“活”起来并跑上我们自己的程序。1. 开发环境搭建打好地基在开始写任何代码之前一个稳定、高效的开发环境是重中之重。AIGlasses OS Pro的开发主要围绕交叉编译进行也就是说我们在性能强大的电脑宿主机上编写和编译代码生成能在眼镜上目标机运行的二进制文件。1.1 宿主机系统准备我强烈推荐使用Ubuntu 22.04 LTS作为宿主机系统这是大多数嵌入式开发社区的主流选择软件包兼容性最好。你可以在物理机上安装也可以使用虚拟机如VMware或VirtualBox。安装好系统后第一件事就是更新软件源并安装一系列基础工具sudo apt update sudo apt upgrade -y sudo apt install -y git curl wget build-essential \ libssl-dev libncurses-dev bc flex bison \ u-boot-tools device-tree-compiler \ python3 python3-pip python3-venv这些工具里build-essential提供了GCC编译器bc,flex,bison是编译内核和某些库时需要的u-boot-tools和device-tree-compiler则是处理引导程序和设备树的关键。1.2 获取SDK与工具链AIGlasses OS Pro的软件开发套件SDK和交叉编译工具链通常由设备厂商提供。你需要从官方渠道获取。假设我们拿到的是一个名为aiglasses-os-pro-sdk.tar.xz的压缩包和对应的工具链gcc-arm-11.2.tar.xz。我们创建一个专门的工作目录来存放这一切mkdir -p ~/aiglasses-dev cd ~/aiglasses-dev将下载的SDK和工具链复制到这个目录然后解压# 解压SDK它可能包含内核源码、根文件系统、预编译库等 tar -xf aiglasses-os-pro-sdk.tar.xz # 解压交叉编译工具链到/opt目录方便系统全局调用 sudo tar -xf gcc-arm-11.2.tar.xz -C /opt解压后需要将工具链的路径加入到系统的环境变量中这样我们才能在终端里直接使用arm-none-linux-gnueabihf-gcc这样的命令。编辑你的shell配置文件比如~/.bashrcecho export PATH/opt/gcc-arm-11.2/bin:$PATH ~/.bashrc echo export CROSS_COMPILEarm-none-linux-gnueabihf- ~/.bashrc echo export ARCHarm ~/.bashrc source ~/.bashrc现在你可以通过运行arm-none-linux-gnueabihf-gcc --version来验证工具链是否安装成功。1.3 配置开发板连接智能眼镜通常通过USB调试接口ADB或串口与电脑通信。串口常用于查看系统启动日志和进行底层调试而ADB则用于文件传输和应用程序安装。串口连接你需要一个USB转TTL串口模块。连接时注意模块的TX接眼镜调试口的RX模块的RX接眼镜调试口的TXGND对接在电脑上使用minicom或screen工具连接串口sudo apt install minicom sudo minicom -D /dev/ttyUSB0 -b 115200ADB连接确保眼镜的系统设置中已开启“开发者选项”和“USB调试”。用USB线连接电脑后执行sudo apt install adb adb devices如果看到设备列表中出现你的眼镜序列号后面跟着device字样说明连接成功。2. 系统构建与定制深入核心拿到了SDK我们就可以一窥这个定制Linux系统的全貌并尝试进行一些修改。2.1 内核配置与编译内核是操作系统的核心负责管理硬件资源。SDK中的内核源码目录通常命名为linux-5.x.x。我们进入目录进行配置cd ~/aiglasses-dev/sdk/linux-5.10内核有成千上万个配置项。厂商通常会提供一个默认配置文件.config。我们可以直接使用它或者基于它进行微调。# 加载默认配置假设存在 make ARCHarm CROSS_COMPILEarm-none-linux-gnueabihf- defconfig # 如果需要图形化界面调整配置可选 make ARCHarm CROSS_COMPILEarm-none-linux-gnueabihf- menuconfig在menuconfig界面中你可以浏览和修改配置。例如如果你想为眼镜增加对某个新型USB摄像头的支持就需要在Device Drivers - Multimedia support - Video capture adapters下找到并启用对应的驱动。配置完成后开始编译内核和内核模块# 编译内核镜像zImage和设备树二进制文件.dtb make ARCHarm CROSS_COMPILEarm-none-linux-gnueabihf- -j$(nproc) # 编译内核模块 make ARCHarm CROSS_COMPILEarm-none-linux-gnueabihf- modules -j$(nproc)编译成功后在arch/arm/boot/目录下会生成zImage内核镜像在arch/arm/boot/dts/目录下会生成对应的.dtb设备树文件。2.2 根文件系统初探根文件系统包含了系统启动后运行的所有应用程序、库和配置文件。AIGlasses OS Pro可能使用Buildroot或Yocto这类工具构建了一个精简的根文件系统。在SDK中它可能是一个预编译的镜像文件如rootfs.img也可能是可以解压和修改的目录。理解它的结构很重要/bin,/sbin: 存放系统必备的可执行文件。/lib: 存放系统库尤其是我们交叉编译程序时链接的glibc或musl库。/etc: 配置文件如网络配置、启动脚本。/usr/app: 智能眼镜上用户应用程序的常见安装位置。如果你想在根文件系统中添加一个自己编写的系统服务通常需要将编译好的可执行文件放入合适目录如/usr/bin。在/etc/init.d/或通过systemd创建一个启动脚本。修改根文件系统镜像并重新烧录到设备。不过在开发初期我们可以通过ADB直接推送文件到设备的对应目录进行测试。3. 驱动开发实战让硬件说话驱动是内核与硬件之间的翻译官。假设我们要为AIGlasses OS Pro开发一个简单的LED指示灯驱动。3.1 理解硬件与设备树首先需要查阅眼镜的硬件原理图或数据手册找到控制LED的GPIO通用输入输出引脚编号比如是GPIO5的第12号引脚。在Linux ARM体系下硬件信息通过设备树Device Tree来描述。我们需要在SDK的设备树源文件.dts或.dtsi中添加对这个LED节点的描述。找到对应的文件例如aiglasses-pro.dtsi添加如下内容/ { led-controller { compatible gpio-leds; status okay; user-led { label aiglasses:user:led; gpios gpio5 12 GPIO_ACTIVE_HIGH; // 引用GPIO控制器和引脚 linux,default-trigger heartbeat; // 默认让它心跳式闪烁 default-state off; }; }; };修改设备树后需要重新编译设备树文件make dtbs并将新的.dtb文件烧录或更新到设备。3.2 编写最简单的字符设备驱动虽然对于LED内核已有成熟的leds-gpio驱动框架我们可以直接通过设备树配置使用。但为了理解驱动开发流程我们写一个最简单的字符设备驱动它通过/sys/class/下的文件节点来控制LED。创建一个文件my_led_driver.c#include linux/module.h #include linux/kernel.h #include linux/fs.h #include linux/gpio.h #include linux/uaccess.h #define LED_GPIO 124 // 假设GPIO5_12对应的系统全局GPIO编号是124 #define DEVICE_NAME my_led #define CLASS_NAME my_led_class static int major_number; static struct class* led_class NULL; static struct device* led_device NULL; // 当用户向设备文件写入时调用 static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset) { char val; if (copy_from_user(val, buffer, 1)) { // 从用户空间拷贝数据 return -EFAULT; } if (val 1) { gpio_set_value(LED_GPIO, 1); // 点亮LED printk(KERN_INFO LED ON\n); } else if (val 0) { gpio_set_value(LED_GPIO, 0); // 熄灭LED printk(KERN_INFO LED OFF\n); } return len; } static struct file_operations fops { .owner THIS_MODULE, .write dev_write, }; // 模块初始化函数 static int __init led_init(void) { printk(KERN_INFO Initializing my LED driver\n); // 1. 申请GPIO if (gpio_request(LED_GPIO, my-led)) { printk(KERN_ALERT Failed to request GPIO %d\n, LED_GPIO); return -1; } // 2. 设置GPIO方向为输出 if (gpio_direction_output(LED_GPIO, 0)) { printk(KERN_ALERT Failed to set GPIO direction\n); gpio_free(LED_GPIO); return -1; } // 3. 动态申请一个主设备号 major_number register_chrdev(0, DEVICE_NAME, fops); if (major_number 0) { printk(KERN_ALERT Failed to register char device\n); gpio_free(LED_GPIO); return major_number; } // 4. 在/sys/class下创建设备类 led_class class_create(THIS_MODULE, CLASS_NAME); if (IS_ERR(led_class)) { unregister_chrdev(major_number, DEVICE_NAME); gpio_free(LED_GPIO); return PTR_ERR(led_class); } // 5. 在/dev下创建设备节点 led_device device_create(led_class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME); if (IS_ERR(led_device)) { class_destroy(led_class); unregister_chrdev(major_number, DEVICE_NAME); gpio_free(LED_GPIO); return PTR_ERR(led_device); } return 0; } // 模块退出函数 static void __exit led_exit(void) { device_destroy(led_class, MKDEV(major_number, 0)); class_destroy(led_class); unregister_chrdev(major_number, DEVICE_NAME); gpio_set_value(LED_GPIO, 0); gpio_free(LED_GPIO); printk(KERN_INFO Goodbye from LED driver\n); } module_init(led_init); module_exit(led_exit); MODULE_LICENSE(GPL); MODULE_AUTHOR(Your Name); MODULE_DESCRIPTION(A simple LED driver for AIGlasses OS Pro);编写对应的Makefile使用交叉编译工具链进行编译KERNEL_DIR ? ~/aiglasses-dev/sdk/linux-5.10 ARCH ? arm CROSS_COMPILE ? arm-none-linux-gnueabihf- obj-m : my_led_driver.o all: $(MAKE) -C $(KERNEL_DIR) M$(PWD) ARCH$(ARCH) CROSS_COMPILE$(CROSS_COMPILE) modules clean: $(MAKE) -C $(KERNEL_DIR) M$(PWD) ARCH$(ARCH) CROSS_COMPILE$(CROSS_COMPILE) clean编译后会生成my_led_driver.ko内核模块文件。通过ADB将其推送到眼镜的/lib/modules/目录下然后使用insmod命令加载模块。加载成功后你会看到/dev/my_led设备节点。通过echo 1 /dev/my_led就可以控制LED点亮了。4. 应用程序开发与部署实现功能驱动为硬件提供了访问接口最终的用户功能还需要应用程序来实现。我们开发一个简单的C语言程序调用V4L2Video for Linux 2接口捕获摄像头图像。4.1 交叉编译应用程序首先编写一个基础的图像捕获程序capture.c。为了简化我们只完成打开摄像头设备、设置格式、捕获一帧并保存为文件的功能。#include stdio.h #include stdlib.h #include string.h #include fcntl.h #include unistd.h #include sys/ioctl.h #include linux/videodev2.h #define DEVICE /dev/video0 #define WIDTH 640 #define HEIGHT 480 #define FILE_NAME capture.raw int main() { int fd; struct v4l2_format fmt {0}; struct v4l2_buffer buf {0}; void* buffer; // 1. 打开摄像头设备 fd open(DEVICE, O_RDWR); if (fd 0) { perror(Failed to open device); return 1; } // 2. 设置图像格式 fmt.type V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width WIDTH; fmt.fmt.pix.height HEIGHT; fmt.fmt.pix.pixelformat V4L2_PIX_FMT_YUYV; // 常用格式 fmt.fmt.pix.field V4L2_FIELD_NONE; if (ioctl(fd, VIDIOC_S_FMT, fmt) -1) { perror(Failed to set format); close(fd); return 1; } // 3. 申请缓冲区这里简化只申请一帧 // ... (实际项目需要使用VIDIOC_REQBUFS, VIDIOC_QUERYBUF等) // 为了示例我们假设直接读取 buffer malloc(WIDTH * HEIGHT * 2); // YUYV格式每个像素2字节 if (!buffer) { perror(Failed to allocate buffer); close(fd); return 1; } // 4. 读取一帧数据简化方式生产环境应用内存映射或用户指针 if (read(fd, buffer, WIDTH * HEIGHT * 2) -1) { perror(Failed to read frame); free(buffer); close(fd); return 1; } // 5. 保存到文件 FILE* fp fopen(FILE_NAME, wb); fwrite(buffer, 1, WIDTH * HEIGHT * 2, fp); fclose(fp); printf(Frame captured and saved to %s\n, FILE_NAME); // 6. 清理 free(buffer); close(fd); return 0; }使用交叉编译工具链编译这个程序arm-none-linux-gnueabihf-gcc -o capture capture.c编译后会生成一个名为capture的ARM架构可执行文件。4.2 部署与远程调试将编译好的应用程序和可能依赖的库如果使用动态链接推送到眼镜上。通常可以放在/data目录或/usr/app目录下。adb push capture /data/ adb shell chmod x /data/capture然后通过ADB shell在眼镜上运行它adb shell cd /data ./capture如果程序运行失败可以使用strace工具跟踪系统调用或者查看/var/log/messages内核日志来排查问题。对于更复杂的应用可以在宿主机上使用gdbserver在眼镜上启动调试服务然后在宿主机上用交叉编译版本的gdb进行远程连接和调试这是嵌入式开发中非常高效的调试手段。5. 总结走完这一趟从环境搭建到应用部署的完整流程你应该对AIGlasses OS Pro这类嵌入式Linux系统的开发有了一个比较实在的感受。它不像在x86电脑上写程序那么直接多了交叉编译、设备树、内核模块这些概念但核心的编程思想和问题排查方法依然是相通的。最大的体会是嵌入式开发非常依赖文档和社区。硬件原理图、芯片数据手册、内核文档是你最好的朋友。遇到问题多去搜索相关的内核邮件列表和开源社区很可能已经有人遇到过类似的情况。对于想深入下去的开发者我建议在掌握这个基础流程后可以去研究一下系统启动的完整过程从Bootloader到内核再到用户空间学习如何使用Buildroot或Yocto从头构建一个自己的根文件系统以及探索如何为眼镜集成更复杂的AI推理框架比如TensorFlow Lite。这条路很长但每一步都能让你对“智能”硬件背后的“软件”有更深的理解看着自己写的代码在小小的眼镜上跑起来解决实际问题那种成就感是非常独特的。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。