一次被尊重的面试之后:重新梳理我的 AGV 系统
感谢一位给予我尊重与建议的面试官。从更新博客和 GitHub 开始,重新梳理 AGV 的 Linux 感知、STM32 底盘、传感器融合、多线程邮箱、CAN 通信与地图任务协作。
感谢一位给予我尊重与建议的面试官。从更新博客和 GitHub 开始,重新梳理 AGV 的 Linux 感知、STM32 底盘、传感器融合、多线程邮箱、CAN 通信与地图任务协作。
嵌入式开发工程师面试知识手册 适用对象:零基础起步、目标是通过嵌入式软件/驱动/BSP 方向面试的读者 编写依据:赵哲简历全部知识点 + 智能车 AGV 控制平台完整项目代码(i.MX6ULL Linux 端 + STM32F407 固件)+ Linux 驱动练习代码包 + embedded-agent 嵌入式开发智能体仓库 + 真实面试手撕代码与追问记录 使用方法:每篇按"通俗解释 → 原理细节 → 命令/API → 代码实例 → 项目结合 → 记忆口诀 → 面试问答"组织;口诀用于快速记忆,问答用于自测。第9篇是讲项目的演练场,第10篇是手撕代码实战题库。 总目录 * 第1篇 C语言与数据结构 * 1.1 编译链接全过程 * 1.2 数据类型与内存
这是 Linux 驱动小系列的总结篇。前三篇把 LED 驱动从内核模块写到 misc 设备,属于“会用”;这篇把背后的架构讲透:驱动到底怎么编译、内核树内和树外两种方式的区别、以及驱动里每个操作在系统跑起来之后到底产生了什么效果。内容整理自我的学习笔记(note.pdf)和实际工程 code/2026/20260803。 1. 驱动代码到底怎么编译的? 不管哪种方式,最终都靠内核的 kbuild 系统。核心就三个文件的关系: * Kconfig:定义 menuconfig 里的选项(如 CONFIG_MYMODULE),三态 y/m/n——y 编进内核,m 编成模块,n 不编; * .config:menuconfig 的选择结果,保存在源码顶层; * Makefile:
上两篇分别用手动 mknod 和 class_create+device_create 注册字符设备,调用链一长串。这篇用 misc(混杂)设备 一步搞定。代码来自实际工程 code/2026/20260803/05_misc_led,已验证可用。 1. 完成什么实验? 用 misc_register 重写 LED 驱动:一步完成设备号分配、字符设备注册、/dev/myled0 节点创建,同时保留上一篇的 sysfs 属性 led_status。 2. 什么是 misc 设备? misc(混杂)设备是 Linux 给“不好归类的小字符设备”
上一篇的 LED 驱动还要手动 mknod 才能用。这篇在同一驱动上加两步:用 class_create + device_create 让内核自动生成 /dev 节点,再挂一个 sysfs 属性文件,用 cat/echo 就能看灯、控灯。代码来自实际工程 code/2026/20260803/04_led_sys,已验证可用。 1. 完成什么实验? 在 LED 字符设备驱动基础上:insmod 后自动生成 /dev/myled0(不再手动 mknod);同时在 /sys/class/LED/myled0/ 下挂出 led_status 属性文件,
系统跑起来之后,这篇开始写第一个 Linux 驱动。代码全部来自实际工程 code/2026/20260803(01_drv_template、02_drv_led、03_drv_beep),在开发板上验证通过:先写最简单的内核模块,再升级成能控制 LED 的字符设备驱动,最后照同样套路驱动蜂鸣器。 1. 完成什么实验? 编写并加载一个 LED 字符设备驱动(.ko):insmod 后生成设备号、ioremap 映射 GPIO 寄存器,应用程序通过 /dev/myled0 设备节点 write 控制灯亮灭、read 读回灯状态;蜂鸣器驱动完全复用同一框架。 2. 内核模块是什么? 内核模块(.ko)是可以动态加载到正在运行的内核中的代码。和裸机编程最大的区别:
这篇笔记开始进入 Linux 部分:在正点原子 I.MX6ULL MINI 开发板上完成系统移植——从源码编译 U-Boot、Linux 内核和 busybox 根文件系统,让开发板从裸机状态跑起完整的 Linux。内容整理自我的学习笔记(note.pdf),每一步都实际跑通过。 1. 完成什么实验? 从源代码出发,分别编译出三个系统组件:U-Boot(引导程序)、zImage+dtb(内核与设备树)、busybox rootfs(根文件系统),并通过 SD 卡烧录 + tftp 下载内核 + NFS 挂载根文件系统的方式,把开发板启动到 Linux 命令行。 2. U-Boot、Kernel、rootfs 各是什么?
这篇笔记继续正点原子 I.MX6ULL MINI 开发板裸机学习,主题是GT9147 电容触摸屏驱动。代码来自实际工程 /home/zhao/code/2026/touch_screen,通过 I2C2 + 中断读取触摸坐标。 1. 完成什么实验? 驱动 GT9147 电容触摸芯片,通过 I2C2 读取触摸点坐标,并用 GPIO1_IO09 中断触发读取。 2. 电容屏和电阻屏有什么区别? 电容屏靠人体感应电荷工作,支持多点触控,表面覆盖玻璃,寿命长、手感好;电阻屏靠压力使两层导电膜接触,通常只支持单点,表面为软屏,容易磨损。 3. GT9147 使用什么接口? GT9147 使用 I2C 通信,同时需要 INT 中断引脚和
这篇笔记继续正点原子 I.MX6ULL MINI 开发板裸机学习,主题是LCD 显示屏与 Framebuffer。代码来自实际工程 /home/zhao/code/2026/touch_screen,实现 800x480 RGB LCD 的驱动。 1. 完成什么实验? 驱动 800x480 分辨率的 RGB LCD,配置 I.MX6ULL 的 LCDIF 控制器,通过 Framebuffer 实现画点、清屏、显示字符等基本绘图功能。 2. 什么是 LCDIF? LCDIF(LCD Interface)是 I.MX6ULL 内置的显示控制器,负责把 Framebuffer
这篇笔记继续正点原子 I.MX6ULL MINI 开发板裸机学习,主题是PWM 脉冲宽度调制。代码来自实际工程 /home/zhao/code/2026/touch_screen,主要用 PWM1 控制 LCD 背光亮度。 1. 完成什么实验? 使用 PWM1 输出可调占空比的方波,用于控制 LCD 背光亮度。通过改变占空比,实现屏幕背光从暗到亮的连续调节。 2. 什么是 PWM? PWM(Pulse Width Modulation,脉冲宽度调制)是一种通过改变高电平在一个周期内的占比,来控制平均电压或输出功率的技术。频率不变时,占空比越大,平均电压越高。 3. 什么是占空比? 占空比 = 一个周期内高电平时间 / 周期时间,范围 0~100%
这篇笔记继续记录在正点原子 I.MX6ULL MINI 开发板上的学习过程,主题是 SPI 总线与 ADXL345 三轴加速度采集。内容基于实际工程 /home/zhao/code/2026/7.28SPI/spi 中的验证代码。 1. 什么是 SPI? SPI(Serial Peripheral Interface,串行外设接口)是一种高速、全双工、同步的串行通信协议。它由 Motorola 提出,广泛用于 MCU/SoC 与各种外设(传感器、Flash、显示屏等)之间的短距离通信。 SPI 没有复杂的寻址机制,主机通过一根专门的片选线(CS)来选择从机,通信时主机提供时钟,数据在时钟边沿同步收发。 2. 四线制
这篇笔记记录在正点原子 I.MX6ULL MINI 开发板上完成的一次小实验——光敏电阻 ADC 采集。内容涉及采样、量化、编码、逐次逼近法等知识点,尽量用图文结合的方式讲清楚。 1. 什么是 ADC? ADC(Analog-to-Digital Converter,模数转换器)的作用就是把连续的模拟信号转换成离散的数字信号,让 CPU 能够读取和处理。 举个例子:光敏电阻两端的电压会随着光线强弱连续变化,这个电压是模拟量;而 CPU 只认识 0 和 1,所以我们需要 ADC 把这个电压变成一串数字,比如 0~4095 之间的整数。 2. 我所使用的 ADC 分辨率是多少? I.MX6ULL 片上集成的 ADC
I.MX6ULL
这篇笔记继续正点原子 I.MX6ULL MINI 开发板裸机学习,主题是LM75 温度传感器采集。这是 I2C 总线的第一个实际应用。代码来自实际工程 /home/zhao/code/2026/touch_screen。 1. 完成什么实验? 通过 I2C1 读取 LM75 温度传感器的温度寄存器,把原始数据换算成摄氏度并通过串口打印。注意:正点原子 MINI 开发板 I2C1 上板载的是 AP3216C,并没有板载 LM75——本实验用的是外接 LM75 模块,SDA/SCL 接 I2C1 的复用引脚(UART4_RX/UART4_TX),地址 0x48。 2. LM75
I.MX6ULL
这篇笔记继续正点原子 I.MX6ULL MINI 开发板裸机学习,主题是I2C 总线协议与控制器。I2C 是传感器、触摸屏、EEPROM 等芯片最常用的总线之一。代码来自实际工程 /home/zhao/code/2026/touch_screen。 1. 完成什么实验? 实现 I.MX6ULL I2C1/I2C2 控制器的初始化,以及基于 I2C 协议的字节写和字节读函数,为后续 LM75 温度传感器、GT9147 触摸屏驱动做准备。 2. 什么是 I2C? I2C(Inter-Integrated Circuit)是飞利浦提出的半双工串行总线,只需要两根线:SCL(时钟)和 SDA(数据)。它采用主从架构,
I.MX6ULL
这篇笔记继续正点原子 I.MX6ULL MINI 开发板裸机学习,主题是UART 串口通信与 printf 输出。有了串口,开发板就能向 PC 打印调试信息,这是裸机调试最重要的手段。代码来自实际工程 /home/zhao/code/2026/touch_screen。 1. 完成什么实验? 配置 I.MX6ULL 的 UART1,实现单字符发送 putc()、字符串发送 puts(),并把标准库 printf 底层对接上去,让程序可以通过 printf() 向串口助手输出信息。 2. 什么是 UART? UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是一种异步串行通信协议。它只需要两根数据线:TX(
I.MX6ULL
这篇笔记继续正点原子 I.MX6ULL MINI 开发板裸机学习,主题是GPT 定时器与软件延时。代码来自实际工程 /home/zhao/code/2026/touch_screen。 1. 完成什么实验? 配置 I.MX6ULL 的 GPT1 定时器作为自由运行的计数器,实现微秒级和毫秒级软件延时函数 delay_us() / delay_ms(),供 LED 闪烁、I2C 时序等模块调用。 2. GPT 与 EPIT 有什么区别? 特性EPITGPT 计数方向递减递增 主要用途周期中断自由运行计数、输入捕获、输出比较 重载可自动重载自由运行,溢出后从 0 继续 延时实现中断方式轮询 CNT 差值 3.
I.MX6ULL
这篇笔记继续正点原子 I.MX6ULL MINI 开发板裸机学习,主题是EPIT 定时器。定时器是嵌入式系统里最常用的外设之一,用来产生精确延时和周期性中断。代码来自实际工程 /home/zhao/code/2026/touch_screen。 1. 完成什么实验? 配置 I.MX6ULL 的 EPIT1 定时器,使其以固定周期产生中断,在中断服务函数里翻转 LED,实现周期闪烁。 2. 什么是 EPIT 定时器? EPIT(Enhanced Periodic Interrupt Timer)是 I.MX6ULL 内部的增强型周期中断定时器。它是一个 32 位递减计数器,从装载值 LR 开始减,减到比较值 CMPR 时产生比较中断;
I.MX6ULL
这篇笔记继续正点原子 I.MX6ULL MINI 开发板裸机学习,主题是ARM Cortex-A7 的中断系统。代码来自实际工程 /home/zhao/code/2026/touch_screen。 1. 完成什么实验? 理解 ARM Cortex-A7 中断响应流程,掌握 GIC(Generic Interrupt Controller)的初始化和中断注册方法。后续按键、EPIT、GPT、PWM、触摸屏等都依赖这套中断机制。 2. 什么是中断? 中断是外设或内部事件主动通知 CPU 的一种机制。当事件发生时,CPU 会暂停当前程序,跳转到预先设置好的中断处理函数执行;处理完后再返回原程序。相比轮询,中断能大大提高 CPU 效率。 3. ARM
I.MX6ULL
这篇笔记继续正点原子 I.MX6ULL MINI 开发板裸机学习,主题是I.MX6ULL 的时钟系统。如果把 SoC 比作一台机器,时钟就是它的“心跳”,所有模块都靠时钟驱动。代码来自实际工程 /home/zhao/code/2026/touch_screen。 1. 完成什么实验? 配置 I.MX6ULL 的系统时钟:把 ARM 内核时钟跑到约 528MHz,同时配置 528MHz/480MHz PLL 的 PFD,并打开所有外设的时钟门控,为后续 UART、I2C、SPI、LCD 等外设提供时钟。 2. SoC 为什么需要时钟系统? SoC 内部有 CPU、
I.MX6ULL
这篇笔记继续正点原子 I.MX6ULL MINI 开发板的 GPIO 学习,主题是GPIO 输入——按键检测和蜂鸣器控制。代码来自实际工程 /home/zhao/code/2026/touch_screen。 1. 完成什么实验? 把 GPIO1_IO18 配置为输入模式,检测按键是否被按下;按下时通过中断翻转 LED 状态。同时把 GPIO5_IO01 配置为输出,控制蜂鸣器响/停。 2. GPIO 输入和输出有什么区别? * 输出模式:CPU 通过 DR 寄存器控制引脚电平,如点灯、驱动蜂鸣器。 * 输入模式:CPU 通过 PSR 寄存器读取引脚真实电平(注意:I.
I.MX6ULL
这篇笔记记录在正点原子 I.MX6ULL MINI 开发板上完成的最基础实验——GPIO 输出控制 LED 点灯。内容来自实际工程 /home/zhao/code/2026/touch_screen 中的验证代码,适合作为裸机学习的第一站。 1. 完成什么实验? 通过配置 I.MX6ULL 的 GPIO1_IO03 引脚为输出模式,控制板载 LED 的亮灭和翻转。 2. 什么是 GPIO? GPIO(General Purpose Input/Output,通用输入输出)是 SoC 上最基础的可编程引脚。每个 GPIO 引脚可以被配置为输入或输出:输出时 CPU 可以控制引脚电平(高/低)
硬件
更新于 2026 年 10 月 13 日,按当前实机配置整理。 这台 N100 小主机现在已经成了我的家庭服务器:底层运行 Proxmox VE,里面分开部署飞牛、Debian 和两台 Ubuntu 虚拟机,承担 NAS、博客和视频服务。几轮调整下来,我更看重的是把服务分清楚,让访问和维护都有固定入口。 硬件:N100、16GB 内存和 512GB SSD 处理器是 Intel N100,四核四线程,支持硬件虚拟化;内存为 16GB,系统识别约 15.4GiB,配一块标称 512GB 的 SSD。目前宿主机运行 PVE 9.1.1。