驱动、bootloader、文件系统

嵌入式 SoC 与接口 11:DSP:滤波、FFT、定点数与饱和

展开合集目录
  1. 嵌入式 SoC 与接口 01:从摄像头框图认识 SoC
  2. 嵌入式 SoC 与接口 02:电平、地与逻辑阈值
  3. 嵌入式 SoC 与接口 03:差分、阻抗、端接与信号完整性
  4. 嵌入式 SoC 与接口 04:PMIC、供电时序与掉电行为
  5. 嵌入式 SoC 与接口 05:晶振、PLL、时钟树与跨时钟域
  6. 嵌入式 SoC 与接口 06:复位域、看门狗与故障恢复
  7. 嵌入式 SoC 与接口 07:ADC、DAC、参考电压与采样
  8. 嵌入式 SoC 与接口 08:MCU、MPU、SoC 与操作系统
  9. 嵌入式 SoC 与接口 09:CPU、异常、中断与多核
  10. 嵌入式 SoC 与接口 10:GPU:并行计算、图形与数据搬运
  11. 嵌入式 SoC 与接口 11:DSP:滤波、FFT、定点数与饱和
  12. 嵌入式 SoC 与接口 12:NPU:张量计算、片上存储与 TOPS
  13. 嵌入式 SoC 与接口 13:ISP:从传感器 RAW 到可用图像
  14. 嵌入式 SoC 与接口 14:视频编解码器与图像加速器
  15. 嵌入式 SoC 与接口 15:Boot ROM、Bootloader 与系统启动
  16. 嵌入式 SoC 与接口 16:NOR、NAND、擦写与 ECC
  17. 嵌入式 SoC 与接口 17:eMMC:总线模式、内部管理与分区
  18. 嵌入式 SoC 与接口 18:安全启动、固件签名与 A/B 升级
  19. 嵌入式 SoC 与接口 19:寄存器、地址空间与 MMIO
  20. 嵌入式 SoC 与接口 20:SRAM、DDR、带宽与延迟
  21. 嵌入式 SoC 与接口 21:Cache、一致性与可见性
  22. 嵌入式 SoC 与接口 22:DMA、描述符与环形缓冲
  23. 嵌入式 SoC 与接口 23:MMU、IOMMU 与三种地址
  24. 嵌入式 SoC 与接口 24:AXI、AHB、APB 与片内互连
  25. 嵌入式 SoC 与接口 25:零拷贝、dma-buf 与缓冲生命周期
  26. 嵌入式 SoC 与接口 26:共享内存、Mailbox 与核间通信
  27. 嵌入式 SoC 与接口 27:GPIO、Pinmux、上下拉与引脚状态
  28. 嵌入式 SoC 与接口 28:UART、RS-232 与 RS-485
  29. 嵌入式 SoC 与接口 29:I²C:地址、ACK、重复起始与上拉
  30. 嵌入式 SoC 与接口 30:SPI、QSPI 与 Flash 访问
  31. 嵌入式 SoC 与接口 31:定时器、PWM、输入捕获与编码器
  32. 嵌入式 SoC 与接口 32:I²S、PCM、TDM 与音频时钟
  33. 嵌入式 SoC 与接口 33:CAN 与 CAN FD:仲裁、帧和错误状态
  34. 嵌入式 SoC 与接口 34:USB:角色、端点、传输类型与 UVC
  35. 嵌入式 SoC 与接口 35:SD 与 SDIO:存储卡和外设功能
  36. 嵌入式 SoC 与接口 36:Ethernet:MAC、PHY、MDIO 与吞吐
  37. 嵌入式 SoC 与接口 37:PCIe:链路、枚举、BAR、中断与 DMA
  38. 嵌入式 SoC 与接口 38:MIPI 全景:CSI、DSI 与 PHY
  39. 嵌入式 SoC 与接口 39:摄像头接入:供电、复位、MCLK 与配置
  40. 嵌入式 SoC 与接口 40:CSI-2:数据类型、虚拟通道与带宽预算
  41. 嵌入式 SoC 与接口 41:显示链路:DSI、RGB、LVDS 与 HDMI
  42. 嵌入式 SoC 与接口 42:设备树、probe、IRQ 与资源生命周期
  43. 嵌入式 SoC 与接口 43:实时性、中断延迟与优先级反转
  44. 嵌入式 SoC 与接口 44:万用表、示波器、逻辑分析仪与 JTAG
  45. 嵌入式 SoC 与接口 45:综合排障:无图、花屏、丢帧与 NPU 慢
  46. 嵌入式 SoC 与接口 46:选修:Wi-Fi、Bluetooth 与蜂窝通信
  47. 嵌入式 SoC 与接口 47:选修:工业以太网、EtherCAT 与 TSN
  48. 嵌入式 SoC 与接口 48:选修:FPGA、流水线与时序约束
  49. 嵌入式 SoC 与接口 49:选修:长距离视频 SerDes 与 A-PHY
  50. 嵌入式 SoC 与接口 50:选修:温度、功耗、EMC 与长期可靠性
嵌入式 SoC 与接口 11:DSP:滤波、FFT、定点数与饱和的封面

第 11 / 50 课 · 核心课程。返回课程合集。

DSP 是任务,也可能是一类处理器

数字信号处理包括采样序列上的滤波、频谱分析、调制等运算;DSP 处理器则常针对乘加、循环、数据寻址和实时流设计。CPU 也可以带 DSP 指令扩展,因此看到“支持 DSP”需要继续问:独立核、指令扩展还是软件库?

FIR 滤波把有限段输入与系数相乘累加。长度 L、每秒 Fs 个样本,单通道直接实现大约需要 L×Fs 次乘加;多通道要继续乘通道数。FFT 将信号转为频率表示,采样率和窗口长度决定频率格点,补零不会凭空增加原始观测信息。

定点需要明确缩放与溢出

有符号 Q15 常把整数除以 32768 解释为实数,范围为 [-1,1)。乘法结果通常需要更宽累加器,最后按约定舍入、移位和饱和。直接让整数回绕会把大的正数变成负数,造成明显失真。

浮点不等于无限精度;定点也不等于低质量。应先建立浮点参考,再测量定点误差、峰值余量和最坏执行时间。整个音频帧的截止时间还包括 DMA、缓存同步与调度。

DSP:滤波、FFT、定点数与饱和:采样与滤波、定点乘加、误差与时限

练习与参考结论

代码实现四点滑动平均和 Q15 饱和加法。检查 0.75+0.75 在饱和下接近 1,而在 16 位回绕下成为 -0.5。

把输入改为阶跃,观察滤波延迟;把采样率翻倍但保留系数,解释为什么对应的物理频率响应改变。实际 DSP 上还需测量每块处理周期和缓冲欠载,PC 上的 Python 时间不是 DSP 性能。

配套代码

下载包包含独立运行所需文件,使用 Python 标准库;这里验证机制和计算,不代表开发板测量结果。

运行本课机制与计算示例

查看完整代码:main.py
import math, cmath


def saturate_q15(value):
    return max(-32768, min(32767, value))


def fir(values, coefficients):
    return [
        sum(
            coefficient * values[n - k]
            for k, coefficient in enumerate(coefficients)
            if n >= k
        )
        for n in range(len(values))
    ]


def main():
    values = [0.0] * 4 + [1.0] * 8
    filtered = fir(values, [0.25] * 4)
    assert filtered[4:8] == [0.25, 0.5, 0.75, 1.0]
    raw = 24576 + 24576
    saturated = saturate_q15(raw) / 32768
    wrapped = ((raw + 32768) % 65536 - 32768) / 32768
    assert saturated == 32767 / 32768 and wrapped == -0.5
    count = 64
    signal = [math.sin(2 * math.pi * 8 * n / count) for n in range(count)]
    # 小规模直接 DFT 是频谱计算参考,不是快速 FFT 实现。
    spectrum = [
        abs(
            sum(
                value * cmath.exp(-2j * math.pi * k * n / count)
                for n, value in enumerate(signal)
            )
        )
        for k in range(count // 2)
    ]
    peak = max(range(len(spectrum)), key=spectrum.__getitem__)
    assert peak == 8
    print(
        "step response:",
        filtered,
        "Q15 saturation/wrap:",
        saturated,
        wrapped,
        "DFT peak bin:",
        peak,
    )


if __name__ == "__main__":
    main()
下载代码

在项目根目录执行;下载包解压后,在解压目录执行 python3 main.py。

cd 'content/posts/驱动、bootloader、文件系统/嵌入式SoC与接口/11-DSP:滤波、FFT、定点数与饱和/code' && python3 main.py

延伸阅读

上一课:GPU:并行计算、图形与数据搬运 · 下一课:NPU:张量计算、片上存储与 TOPS