关于嵌入式的一些概念
linux启动过程
系统上电—>bootrom—>uboot—>kernel加载—>init—>应用程序
bootrom
电子设备芯片(SoC)内部的一小块固态只读存储器。
在设备开机时,内存(RAM)里是一片空白的,CPU 根本不知道去哪里读系统镜像。这时 CPU 会强制将指针指向 BootROM 的固定地址。
BootROM 的工作流程通常如下:
硬件基本初始化: 设置最基础的时钟、关闭看门狗、初始化芯片内部的微量内存(SRAM)。
检查启动介质(Boot Modes): 检查芯片引脚(如拨码开关、GPIO 电平),判断当前应该从哪里加载下一阶段的代码。常见的启动介质包括:
eMMC / SD 卡
NAND / NOR Flash
USB 接口(用于生产线烧录或救砖)
加载并验证二级引导程序: 将下一阶段的引导程序(如 U-Boot 的 SPL 阶段、或者移动端的 Bootloader)从外部存储介质拷贝到芯片内部的 SRAM 中。
交出控制权: 跳转到该程序运行,BootROM 的使命宣告结束。
U-Boot
常见的 开源引导加载程序,用于嵌入式系统。它支持多种架构,包括 ARM、x86、PowerPC、RISC-V 等。U-Boot 提供了启动嵌入式系统的关键功能,如加载操作系统内核、引导文件系统、硬件初始化和系统调试。
b: Byte 8bit
w: Word 字 16bit(嵌入式)
I: 整型 interge 32bit
BSP
板级支持包(BSP):BSP 是嵌入式系统开发中的一个重要概念,指的是为特定的硬件平台或开发板提供的软件支持包。BSP 包含了针对特定硬件平台的驱动程序、操作系统适配层、外设控制库以及其他必要的软件组件。它的目的是为嵌入式开发人员提供一个统一的接口和工具集,简化针对特定硬件平台的软件开发过程。BSP 可以包括针对处理器、内存、外设(如串口、GPIO、SPI、I2C 等)、中断控制等的底层驱动程序和库。
PS and PL
PS : Processing System
PS端通常指的是处理系统部分,即嵌入式处理器或CPU。这个部分通常运行软件,执行高层次的应用程序代码和控制任务。
在Xilinx的Zynq系列FPGA中,PS端通常指的是内嵌的ARM Cortex-A9处理器。
FATFS文件系统库
f_mount函数
将逻辑驱动器(如 SD 卡、USB 闪存等)挂载到文件系统,通过它可以访问存储设备上的文件。
一般步骤是先将驱动器(sd等)初始化,再将驱动器挂载到文件系统
f_mkfs函数
对物理存储设备(如 SD 卡、eMMC、USB 闪存等)进行格式化操作。
它会在存储设备上创建一个新的 FAT 文件系统(如 FAT12、FAT16 或 FAT32),从而使该设备可以被文件系统管理,并用于读写文件操作。
emmc (embedded multiMediaCard)
通常焊接在主板上
一个嵌入式 Linux 系统可能会将 eMMC 分为多个分区:
Boot 分区:存储启动加载器和内核映像。
RootFS 分区:存储根文件系统。
Data 分区:用于用户数据存储。
lwip
在 lwIP 中,TCP 协议使用两种定时器来处理 TCP 连接的维护:
- 快速定时器 (tcp_fasttmr):
- 触发频率:通常每 250 毫秒触发一次(在默认配置下)。
- 主要职责:用于处理 TCP 的快速任务,比如:
- ACK 确认包的发送。
- 保持活动的连接管理。
- 处理 TCP 重传计时器(当重传定时器超时时会触发重传操作)。
- 调整滑动窗口,处理延迟确认(delayed ACK)。
- 慢速定时器 (tcp_slowtmr):
- 触发频率:通常每 500 毫秒触发一次。
- 主要职责:处理超时重传、连接超时检测和断开连接等操作。
tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv)
提供了一种在应用程序中注册接收数据回调函数的机制。当 TCP 连接上有新数据到达时,系统会调用这个回调函数,以便用户代码可以处理接收到的数据。
- pcb 代表 Protocol Control Block (协议控制块),是 lwIP 中用来维护一个 TCP 连接状态的数据结构。
- tcp_recv_fn 指向接收回调函数的指针
struct tcp_pcb
- struct tcp_pcb 是 lwIP(Lightweight IP)协议栈中的一个数据结构,用于表示一个 TCP 协议控制块(PCB,Protocol Control Block)。
它是 lwIP 中管理 TCP 连接的核心数据结构,包含了 TCP 连接的状态、控制信息、缓冲区和回调函数等。 - 每个 TCP 连接都有一个对应的 tcp_pcb 结构,用来存储连接的相关信息。这些信息包括连接的本地和远程地址、端口号、连接状态
(如 LISTEN、ESTABLISHED、CLOSED 等),以及与 TCP 协议相关的控制参数(如滑动窗口、超时时间、重传计数等)。
xemacif_input
Xilinx 的以太网接口驱动程序中的一个函数,用于处理接收到的以太网数据包。该函数通常在基于 lwIP(Lightweight IP)协议栈的嵌入式系统中使用,
特别是在 Xilinx Zynq 和 Zynq Ultrascale+ 平台上,它负责将接收到的以太网数据包传递给上层协议栈进行处理。
该函数主要用于与 AXI Ethernet 或 Ethernet Lite 这样的硬件接口进行通信,通过 DMA 或中断的方式获取数据包,并将其交给 lwIP 处理。
nagle算法
一个lwip中的优化算法,用于减少网络传输中小包的数量,将小包数据包缓冲起来,等到一定数量后一起发送。关闭后可以让每个数据包尽快发送而不是等待。
tcp_arg(newpcb, (void *)(UINTPTR)conn)
为指定的 TCP 连接设置用户自定义的数据指针。
tcp_err() 注册错误处理回调函数,用于处理连接中的异常情况。
flash type
-flash-type
QSPI-X8 Dual Parallel 是一种 Quad-SPI(QSPI) 闪存模式,在嵌入式系统中经常用于提高存储器的读写速度和带宽.
QSPI-X8 Dual Parallel 模式结合了 Quad-SPI 和 Dual Parallel 的优点:
- Quad-SPI (X4):每个 QSPI 闪存使用 4 条数据线,并通过 I/O 线传输 4 位数据。
- Dual Parallel:两个 QSPI 闪存并行工作,组合成 8 位数据宽度(X8 模式)。
所以每个时钟周期传输 8 位数据。
AXI (Advanced eXtensible Interface)
总线接口协议,广泛用于嵌入式系统和片上系统(SoC)中,特别是在FPGA设计中。AXI作为数据传输协议,负责处理不同设备间的通信,比如处理器、外设、存储器等硬件模块之间的数据传输。
DMA (Direct Memory Access)
- 直接存储访问, 一种在嵌入式系统、计算机系统中用于提高数据传输效率的技术。它允许设备直接访问内存,而不需要经过 CPU 的参与,从而大幅减少 CPU 的工作负荷,特别是在数据传输任务频繁的系统中。
外设协议
总线特性、速率范围、驱动实现要点和常见问题定位方法。
常用外设协议对比
| 协议 | 典型信号线 | 通信方式 | 典型速率范围 | 常见应用 | 软件侧关键词 |
|---|---|---|---|---|---|
| UART(串口) | TX/RX(可选 RTS/CTS) | 异步、点对点 | 9.6 kbps ~ 4 Mbps+ | 调试口、模块控制、日志输出 | 中断接收、DMA、帧解析 |
| Ethernet(网口) | TX/RX 差分对(经 PHY) | 全双工、分层协议栈 | 10/100/1000 Mbps | 联网、远程升级、工业通信 | MAC/PHY、Socket、零拷贝 |
| I2S | BCLK/LRCK/SD(可选 MCLK) | 同步串行(音频) | 与采样率和位宽相关 | 音频编解码器、麦克风、功放 | DMA 双缓冲、时钟主从 |
| I2C | SCL/SDA | 同步串行、多主多从 | 100k/400k/1M/3.4M | 传感器、PMIC、EEPROM | 起止条件、ACK、总线恢复 |
| SPI | SCLK/MOSI/MISO/CS | 同步串行、主从 | 数百 kbps ~ 数十 Mbps | Flash、ADC、LCD、高速传感器 | CPOL/CPHA、片选时序、DMA |
| SDIO | CLK/CMD/D0~D3 | 同步串行(命令+数据) | 25/50 MHz(常见) | SD 卡、Wi-Fi 模块 | 枚举流程、块传输、缓存一致性 |
串口(UART)
基本原理
UART 是异步通信,不传输时钟线,通信双方通过约定波特率来采样数据。典型帧格式是 1 个起始位 + 8 位数据 + 可选校验位 + 1/2 个停止位(常见配置为 8N1)。
软件开发关注点
- 接收路径建议使用“中断 + 环形缓冲区”或“DMA + 空闲中断”以降低 CPU 占用。
- 协议解析通常需要定义帧边界(长度字段、分隔符、超时)避免粘包/拆包问题。
- RS-485 半双工场景要控制 DE/RE 方向脚,发送完成后再切回接收。
常见问题
- 波特率、数据位、停止位不一致会直接导致乱码。
- 高速日志输出阻塞主线程,建议用 DMA 或异步日志缓冲。
- 接地不良、线缆过长会引入误码。
网口(Ethernet)
基本原理
嵌入式系统里网口通常由 MAC + PHY 组成:
- MAC 在 SoC 内部,负责二层帧收发、DMA 描述符管理。
- PHY 负责电信号编解码和链路协商(速率/双工)。
软件开发关注点
- 驱动初始化顺序通常是:时钟/复位 -> MDIO 读写 PHY -> 配置 MAC -> 建立 RX/TX 描述符环。
- lwIP/Socket 场景要关注 pbuf 生命周期、缓存对齐和零拷贝策略。
- 大流量下优先用 DMA + 中断合并/轮询机制,避免频繁中断。
常见问题
- PHY 地址配置错误会导致链路始终 down。
- RMII/RGMII 引脚复用或时钟方向配置错误会导致收发异常。
- Cache 未做 clean/invalidate,常见表现是“偶发丢包或包内容错乱”。
I2S
基本原理
I2S 主要用于音频数据传输,不传输寄存器命令,通常配合 I2C/SPI 去配置音频 codec。常见信号:
- BCLK:位时钟
- LRCK(WS):左右声道选择时钟
- SD:串行音频数据
- MCLK(可选):主时钟
软件开发关注点
- 音频场景建议使用 DMA 双缓冲(ping-pong)保证连续流。
- 需要统一采样率、位宽、通道数,例如 48 kHz/16 bit/2 ch。
- 主从模式要在时钟树层面先确定,避免多个主时钟冲突。
常见问题
- 声音断续通常是 DMA 缓冲过小或任务调度不及时。
- 声道错位常由数据对齐模式(I2S/Left-Justified)配置不一致引起。
I2C(集成电路总线)
基本原理
I2C 是双线开漏总线,SCL(穿行时钟线) 和 SDA(串行数据线) 都需要上拉电阻。通过 7 位或 10 位地址区分从设备,标准通信序列为:
Start -> Address + R/W -> ACK -> Data(多字节) -> ACK/NACK -> Stop
寻址方式:
- 7位地址:0x00~0x7F,其中0x00为广播地址。
- 10位地址:扩展寻址,用于特殊设备。
多主竞争解决: - 通过SDA线的电平检测实现总线仲裁,先检测到SDA线被拉低的主设备退出竞争。
软件开发关注点
- 驱动中必须处理 ACK 失败、超时和仲裁丢失。
- 很多器件读寄存器需要 Repeated Start(重复起始),不是 Stop 后再 Start。
- 出现总线卡死(SDA 被拉低)时,需要做总线恢复(手动打时钟释放)。
常见问题
- 上拉电阻过大导致上升沿慢,高速模式不稳定。
- 地址 7bit/8bit 传参混淆导致访问失败(常见左移一位问题)。
SPI(串行外设接口)
基本原理
SPI 是主从同步全双工总线,常见四线:SCLK、MOSI、MISO、CS。核心参数是模式(CPOL/CPHA),共 4 种。
模式配置:
- 时钟极性(CPOL):0(空闲时SCLK为低)或1(空闲时SCLK为高)。
- 时钟相位(CPHA):0(第一个边沿采样)或1(第二个边沿采样)。
数据位宽:8位或16位。
主从模式区别: - 主模式:控制SCK时钟,负责发起通信。
- 从模式:接收SCK时钟,响应主设备请求。
软件开发关注点
- 同一 SPI 总线挂多个从设备时,每个设备可能有不同 mode 和最大时钟,需要按设备切换配置。
- 大块数据传输建议走 DMA;小控制命令可用轮询提高实时性。
- 片选时序很关键:不少器件要求“CS 拉低后延时再发首字节”。
常见问题
- CPOL/CPHA 配置错会导致读回全 0x00/0xFF 或数据错位。
- 时钟过高超过从设备能力会出现随机位翻转。
SDIO
基本原理
SDIO 用于与 SD 卡或 SDIO 外设(如 Wi-Fi 模块)通信,包含命令线 CMD 和 1-bit/4-bit 数据线。相比 SPI 模式,SDIO 吞吐更高。
软件开发关注点
- 初始化通常包含:CMD0、CMD8、ACMD41、CMD2、CMD3、CMD7 等标准流程。
- 数据传输以块为单位(通常 512B),要关注块大小、块数量和超时设置。
- 带 Cache 的系统中,DMA 缓冲区要做对齐和 cache 维护。
常见问题
- 时钟切换过快(初始化阶段直接高速)会导致枚举失败。
- 文件系统层报错(如 FAT 挂载失败)往往根因在底层读写时序或 CRC 错误。
ADC(模拟-to-数字转换器)
采样时间配置:
- 采样时间越长,转换结果越精确,但转换速度越慢。
- 示例:STM32F4的ADC采样时间可配置为3、15、28、56、84、112、144、480周期。
多通道扫描模式:// 配置ADC1扫描模式,采样通道0、1、2
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 3; // 3个转换通道
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = 2;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = 3;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
协议选型建议(软件视角)
- 低速控制类(寄存器配置、传感器):优先 I2C。
- 中高速短距离外设(Flash、屏、ADC):优先 SPI。
- 音频流:优先 I2S(控制面配 I2C)。
- 大容量存储/无线模块:优先 SDIO。
- 调试、日志、简单控制链路:优先 UART。
- 联网和远程维护:优先 Ethernet。
tcp/ip 协议栈
tcpip模型
| OSI模型层级 | Linux TCP/IP模型 | 常用协议示例 | 典型网络设备/功能 |
|---|---|---|---|
| 7. 应用层 | 应用层 | HTTP, FTP, SSH, DNS, SMTP | 网页服务器、邮件服务器 |
| 6. 表示层 | TLS, SSL, JPEG, GIF | 加密/解密、编码/解码 | |
| 5. 会话层 | RPC, NetBIOS, SMB | 会话管理 | |
| 4. 传输层 | 传输层 | TCP, UDP | 路由器、交换机(L4功能) |
| 3. 网络层 | 网络层 | IP, ICMP, ARP, IGMP | 路由器 |
| 2. 数据链路层 | 链路层 | Ethernet, PPP, VLAN, MAC | 交换机、网卡 |
| 1. 物理层 | 物理层 | RJ45, 光纤, 电缆, 无线信号 | 集线器、网线、无线模块 |
以太网协议
以太网(Ethernet)是最常用的局域网通信协议,主要工作在 OSI 模型的数据链路层和物理层。它定义了数据帧的格式、寻址方式、介质访问控制等内容。
1. 以太网帧结构
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| 前导码 | 7 | 用于同步 |
| 帧开始定界符 | 1 | 标记帧的开始 |
| 目的MAC地址 | 6 | 接收方网卡的物理地址 |
| 源MAC地址 | 6 | 发送方网卡的物理地址 |
| 类型/长度 | 2 | 上层协议类型或帧长度 |
| 数据 | 46-1500 | 负载数据 |
| FCS校验序列 | 4 | 帧校验序列(CRC) |
- 最小帧长64字节,最大帧长1518字节(不含VLAN标签时)。
2. MAC地址
- 每个以太网设备有唯一的48位MAC地址(如 00-1A-2B-3C-4D-5E)。
- 用于局域网内设备寻址。
3. 介质访问控制(CSMA/CD)
- 以太网采用载波监听多路访问/冲突检测(CSMA/CD)机制,避免数据冲突。
- 现代以太网多为全双工模式,已基本不再使用CSMA/CD。
4. 以太网类型
- 10BASE-T:10Mbps,双绞线
- 100BASE-TX:100Mbps,双绞线
- 1000BASE-T:1Gbps,千兆以太网
- 10GBASE-T:10Gbps,万兆以太网
5. 以太网类型字段
- 0x0800:IPv4
- 0x0806:ARP
- 0x86DD:IPv6
6. VLAN(虚拟局域网)
- IEEE 802.1Q 标准为以太网帧增加4字节VLAN标签,实现逻辑分组。
TCP 与 UDP 的区别
| 特性 | TCP(传输控制协议) | UDP(用户数据报协议) |
|---|---|---|
| 连接方式 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠,保证数据顺序和完整性 | 不可靠,可能丢包、乱序 |
| 传输方式 | 字节流,面向流 | 数据报,面向报文 |
| 流量控制 | 有(滑动窗口、拥塞控制等) | 无 |
| 速度 | 较慢(因需保证可靠性) | 较快 |
| 适用场景 | 文件传输、网页、邮件等 | 视频、语音、DNS、广播等 |
| 首部开销 | 20字节(不含选项) | 8字节 |
| 是否有顺序保证 | 有 | 无 |
| 是否有重传机制 | 有 | 无 |
TCP 三次握手(Three-way Handshake)
TCP 连接的建立需要经过三次握手,确保客户端和服务器双方都具备发送和接收数据的能力。过程如下:
第一次握手:客户端发送 SYN
- 客户端向服务器发送一个带 SYN 标志位的数据包(SYN=1,Seq=x),表示请求建立连接。
- 此时客户端进入 SYN_SEND 状态。
第二次握手:服务器应答 SYN+ACK
- 服务器收到 SYN 包后,确认客户端的 SYN(ACK=1,Ack=x+1),同时自己也发送一个 SYN 包(SYN=1,Seq=y)。
- 服务器将 SYN 和 ACK 一起发送(SYN=1,ACK=1,Seq=y,Ack=x+1)。
- 服务器进入 SYN_RCVD 状态。
第三次握手:客户端确认 ACK
- 客户端收到服务器的 SYN+ACK 包后,发送一个确认包(ACK=1,Seq=x+1,Ack=y+1)给服务器。
- 客户端进入 ESTABLISHED 状态,服务器收到后也进入 ESTABLISHED 状态,连接建立完成。
说明
- 三次握手的目的是同步双方的初始序列号(Seq),并确认双方的接收能力。
- 若握手过程中某一步失败,连接不会建立,需重新发起。
- 握手完成后,双方可以开始可靠的数据传输。
TCP 四次挥手(Four-way Handshake)
TCP 连接的断开需要经过四次挥手,确保双方都能完成数据传输并正常释放资源。过程如下:
第一次挥手:客户端发送 FIN
- 客户端向服务器发送一个带 FIN 标志位的数据包(FIN=1,Seq=u),表示客户端没有数据要发送了,请求关闭连接。
- 客户端进入 FIN_WAIT_1 状态。
第二次挥手:服务器应答 ACK
- 服务器收到 FIN 包后,发送一个确认包(ACK=1,Ack=u+1,Seq=v)给客户端,表示已收到关闭请求。
- 服务器进入 CLOSE_WAIT 状态,客户端收到 ACK 后进入 FIN_WAIT_2 状态。
第三次挥手:服务器发送 FIN
- 服务器处理完剩余数据后,向客户端发送一个带 FIN 标志位的数据包(FIN=1,Seq=w),请求关闭连接。
- 服务器进入 LAST_ACK 状态。
第四次挥手:客户端应答 ACK
- 客户端收到服务器的 FIN 包后,发送一个确认包(ACK=1,Ack=w+1)给服务器。
- 客户端进入 TIME_WAIT 状态,等待一段时间后彻底关闭连接;服务器收到 ACK 后立即关闭连接,进入 CLOSED 状态。


