【以太网摄像头采集存储终端】项目简介
1. 引言
项目来自 B 站 UP 主:<技术探索者>
这是一个基于 STM32H757XIH6 的双核摄像头采集终端:CM7(Cortex-M7,480 MHz)作为主核运行 FreeRTOS,驱动 OV5640 摄像头连续采集 800×480 图像;图像一路送 RGB LCD 本地预览,一路经硬件 JPEG 压缩后通过 HTTP 推流,在浏览器中直接观看;同时支持 SD 卡抓拍、USB 读卡器导出,以及双核 A/B 槽位 OTA 升级。CM4(Cortex-M4,240 MHz)作为从核,通过 OpenAMP 与 CM7 协作。

当前项目实现的功能:
- 本地预览:OV5640 经 DCMI 连续采集,三缓冲换帧,LTDC 直接送显 RGB LCD。
- 网络推流:硬件 JPEG 编码后以 MJPEG over HTTP 推流,浏览器打开页面即可观看,支持两个观看连接。
- 抓拍导出:按键短按将当前画面保存为 BMP 到 SD 卡,长按切换 USB 读卡器模式,由电脑直接读卡导出。
- 双核 OTA:固件经 HTTP 分块上传到空闲槽位,重启后试运行,失败自动回退,CM7 与 CM4 独立升级。
- 双核协作:CM4 日志经 OpenAMP 回传 CM7,与 CM7 日志一起从 USART1 输出。
2. 功能总览
按功能域分组,每个域对应固件中一组相对独立的任务与驱动。
采集与显示。摄像头任务完成 OV5640 的输出格式、分辨率与图像质量配置后启动连续采集:DCMI DMA 先把像素写入 D2 SRAM 中的双行缓冲,再由 DMA2D 逐行搬运到 SDRAM 帧三缓冲;LTDC 在消隐期切换显示帧地址,画面更新不撕裂。采集链路出现 DMA 错误或长时间无新帧时,任务会停止采集并自动重启,恢复流程见系列 MJPEG 文章。
网络推流。HTTP 服务提供预览主页、/stream 图像流和 /status 状态查询三个入口。推流采用"一次编码、多端共享"的结构:一个编码任务持有完整 RGB565 帧完成颜色转换与硬件 JPEG 压缩,发布到三块输出缓冲;两个发送任务各自维护独立的观看连接,较慢的连接会跳过中间帧,只发送最新 JPEG。满员或 OTA 期间新的观看请求返回 503。
抓拍与导出。抓拍任务监听 KEY0(PA8):短按松开时把一帧完整画面复制到独立抓拍缓冲,编码为 0:/CAM0001.BMP~CAM9999.BMP 保存到 SD 卡;长按两秒在本地 FatFs 与 USB 读卡器模式间切换。两种模式由存储所有权机制保证互斥:卸载 FatFs 后才开放 USB,USB 停止后才重新挂载,避免主机与固件同时访问同一张卡。
OTA 升级。升级镜像经 HTTP 分块上传(每块最大 8192 字节),写入目标核当前未运行的槽位,CRC32 校验通过后在 EEPROM 登记 pending;复位后由 Bootloader 试启动新槽,试运行成功由应用提交 confirmed,失败自动回退旧槽。两核各自独立执行这套流程。
双核协作与日志。CM4 的全部应用逻辑围绕 IPC 展开:周期轮询 OpenAMP 消息、响应 CM4 槽位擦写握手、启动时发布运行槽报告。CM4 的 printf 输出经 rpmsg 回传 CM7,由 CM7 统一从 USART1 打印,双核日志在同一个串口终端里按前缀区分。
一帧 800×480 JPEG 平均约 70 KB,颜色转换加硬件编码合计约 52 ms(数据来自《HTTP MJPEG 浏览器推流》的串口日志实测,画面内容不同会有差异)。按编码耗时折合单端约 19 帧/秒。

3. 硬件平台
3.1 器件组成
整机的器件选型围绕"图像通路 + 网络通路 + 存储"三条线展开:
| 部分 | 器件 / 配置 | 用途 |
|---|---|---|
| MCU | STM32H757XIH6 | 双核 Cortex-M7 + Cortex-M4,2 MB Flash(双 Bank)、864 KB 各类 RAM |
| 摄像头 | OV5640 模块 | DCMI 并口采集,SCCB(I2C4)配置,输出 800×480 RGB565 |
| 显示 | RGB 接口 LCD | LTDC + DMA2D 驱动,工作分辨率 800×480 |
| 以太网 | LAN8720A | RMII PHY,配合 LwIP 提供 HTTP 服务 |
| SDRAM | FMC 外接 32 MB | 帧缓冲与 JPEG 工作缓冲,基地址 0xD0000000 |
| 存储 | SD 卡 + 板载 EEPROM | SD 卡(SDMMC2 + FatFs)保存抓拍;EEPROM 保存启动槽元数据 |
| USB | OTG_FS | 读卡器(MSC)模式导出 SD 卡 |
| 调试与监控 | ST-Link、USART1、IWDG1 | 烧录调试、日志输出、看门狗保活 |
3.2 时钟配置
时钟树由 CubeMX 配置生成,关键频率如下:
| 时钟 | 频率 | 说明 |
|---|---|---|
| CM7 主频(SYSCLK) | 480 MHz | PLL1 输出 |
| CM4 主频 | 240 MHz | 与 HCLK 同源 |
| AHB(HCLK) | 240 MHz | SYSCLK 二分频 |
| APB1 / APB2 | 120 MHz | HCLK 二分频 |
双 Bank 前提:CM7 与 CM4 的应用槽分别放在 Bank1 与 Bank2,两核各自独立擦写自己的 Bank,是双核 A/B 升级方案的基础。
4. 软件架构与数据流
4.1 双核分工
两个核的角色从一开始就定得比较清楚:CM7 独占所有高速外设与网络协议栈,CM4 保持轻量,只做通信配合。
| 核 | 角色 | 承担的工作 |
|---|---|---|
| CM7(主核) | 业务核心 | 摄像头采集与恢复、DMA2D/LTDC 显示、硬件 JPEG 编码、ETH + LwIP + HTTP、SD 抓拍、USB 导出、OTA 接收、看门狗喂狗 |
| CM4(从核) | 协作 | OpenAMP 通信、CM4 槽位擦写时的 RAM 等待握手、运行槽报告、日志回传 |
4.2 任务组织
CM7 的任务在 Core/Src/freertos.c 中创建,汇总如下:
| 任务 | 职责 |
|---|---|
| defaultTask | 初始化 LwIP、启动 HTTP 服务,之后周期喂 IWDG 并翻转 LED |
| 串口接收任务 | 响应串口输入,回报 CM7 / CM4 当前运行槽 |
| IPC 任务 | 维护 OpenAMP 端点,把 CM4 回传的日志从串口打印 |
| 摄像头任务 | OV5640 配置、采集监控与故障自动重启 |
| 抓拍任务 | 按键抓拍、SD 保存与 USB 模式的所有权切换 |
| HTTP 主任务 | 接收连接、路由分发、状态查询、OTA 上传接收 |
| MJPEG 编码任务 | 首次推流时创建:取帧 → 颜色转换 → 硬件 JPEG → 发布 |
| 发送任务 ×2 | 首次推流时创建:各自观看连接的独立发送与超时退出 |
CM4 只有一个 IPC 任务:启动时发布运行槽报告,之后每 100 ms 轮询一次 OpenAMP 消息并服务 OTA 握手。
4.3 从摄像头到浏览器的数据流
下图是整个终端的主数据通路,也是理解工程的最好入口。
图像自上而下经过采集、缓冲、显示与编码发送两条支路;抓拍支路从帧缓冲取完整画面走 SD/USB;CM4 不参与图像通路,只经 SRAM4 共享内存与 CM7 交换消息。
4.4 软件栈
从 RTOS 到板级支撑,各层选用的组件如下:
| 层 | 组件 |
|---|---|
| RTOS | FreeRTOS(CMSIS-RTOS2 封装) |
| 网络 | LwIP + LAN8720A(RMII) |
| 双核通信 | OpenAMP / rpmsg(VirtIO Mailbox + HSEM) |
| 文件系统 | FatFs |
| 图像与显示 | DCMI、DMA2D、LTDC、硬件 JPEG + MDMA、TJpgDec(软件解码备用) |
| 板级支撑 | STM32H7 HAL(STM32Cube FW_H7 V1.13.0,CubeMX 生成) |
5. 启动链与 OTA 升级
5.1 双核启动链
上电后由固定 Bootloader 完成选槽,再把两个核分别引到各自的应用槽,链路如下:
几条关键约定:
- EEPROM 双备份:启动元数据在 EEPROM 的
0x0000/0x0100各存一份 256 字节,读取时取合法且序号较大的一份,保存时轮换写入并读回校验。 - 试启动与回退:pending 槽最多试启动 3 次,每次跳转前先扣减并保存计数;应用正常运行后主动提交 confirmed,用完次数仍未提交则回退旧槽。
- CM4 由应用侧选择:Bootloader 只选 CM7 应用槽;CM7 应用启动后读 EEPROM 决定 CM4 槽位,经 SRAM4 的 handoff 区域(magic + 入口地址)通知固定 Stub 跳转,EEPROM 不可用时默认 CM4 A 槽。
- 本地重刷登记:经 ST-Link 重刷 CM7 镜像后旧元数据 CRC 可能失配,按住 KEY0(PA8)两秒可重新登记当前镜像。
选槽校验、回退细节与本地升级协议在系列《双核系统 Bootloader》中展开。
5.2 OTA 升级链路
OTA 把"上位机上传 → 固件接收 → 擦写 → 重启确认"串成一条链,贯穿 qt-ota 上位机、HTTP 服务、OTA 模块和 Bootloader 四个部分:
两点值得注意:
擦写前先停业务:OTA 先取得存储占用,再停止 MJPEG 推流并等待发送任务退出、暂停摄像头,之后才开始擦写;失败或取消路径会恢复业务并释放占用。
CM4 擦写需要握手:CM4 从 Bank2 取指运行,擦写其空闲槽前必须让 CM4 经握手协议在 RAM 中关中断等待,全程由
.RamFunc函数完成,结束后再恢复。
固件侧的 HTTP 入口如下,上传类接口均通过 X-Ota-Core 头区分目标核:
| 路由 | 用途 |
|---|---|
/ |
预览主页,含图像标签与帧率轮询脚本 |
/stream |
MJPEG multipart 图像流,最多两个观看连接 |
/status |
JSON 状态:网络、运行槽、推流帧率 |
/ota/status |
查询 OTA 状态与目标槽 |
/ota/begin /ota/chunk /ota/end /ota/abort |
上传会话:开始、分块传输、结束、取消 |
上位机是一个 Qt 编写的 Windows 小工具,支持会话内断点续传与本地任务保存,具体实现见各专项文章。
5.3 内存布局
内存布局是这个项目里约束最多的一块:双核要隔离、DMA 要非缓存、A/B 槽链接地址不同。以下四张表覆盖了全部关键区域,数值均来自链接脚本、MPU 配置与源码常量。
Flash 分区(2 MB 双 Bank)
| 分区 | 地址范围 | 大小 | 内容 |
|---|---|---|---|
| CM7 Bootloader | 0x08000000~0x0801FFFF |
128 KB | 固定引导程序,尾部 16 字节保留给本地升级描述符 |
| CM7 应用 A 槽 | 0x08020000~0x0807FFFF |
384 KB | CM7 应用镜像 |
| 预留 | 0x08080000~0x0809FFFF |
128 KB | — |
| CM7 应用 B 槽 | 0x080A0000~0x080FFFFF |
384 KB | CM7 应用镜像 |
| CM4 Stub | 0x08100000~0x0811FFFF |
128 KB | 固定跳转程序 |
| CM4 应用 A 槽 | 0x08120000~0x0817FFFF |
384 KB | CM4 应用镜像 |
| 预留 | 0x08180000~0x0819FFFF |
128 KB | — |
| CM4 应用 B 槽 | 0x081A0000~0x081FFFFF |
384 KB | CM4 应用镜像 |
A/B 镜像不能混用:两核的 A、B 槽链接地址不同,镜像与槽位一一对应;两核各自使用核内槽索引 A=0、B=1。
内部 RAM(CM7 视角,含 MPU 缓存属性)
| 区域 | 地址 | 大小 | 缓存 | 用途 |
|---|---|---|---|---|
| ITCM | 0x00000000 |
64 KB | — | 指令 RAM(链接脚本保留) |
| DTCM | 0x20000000 |
128 KB | 开 | CM7 私有数据,DMA 不可达 |
| AXI SRAM(D1) | 0x24000000 |
320 KB(链接脚本按 512 K 上限配置) | 开 | CM7 主 RAM:data / bss / 堆栈 |
| D2 SRAM | 0x30000000 |
288 KB | 关 | DMA 专用区,见下文细分 |
| SRAM4(D3) | 0x38000000 |
64 KB | 关(共享) | OpenAMP 共享内存与双核交接区 |
D2 SRAM 细分(地址从低到高):0x30000000 起 20 KB 内是 ETH DMA 描述符与 Rx 池,随后到 0x30025000 为 LwIP 堆(合计 148 KB);0x30025000 起是摄像头行缓冲(上限 12 KB);0x30028000 起的 128 KB 划给 CM4 作主 RAM,CM4 侧以别名地址 0x10028000 访问。ETH 与摄像头 DMA 区域关闭缓存,避免 DMA 与 CPU 缓存不一致。
SRAM4 细分布(64 KB)
| 地址 | 大小 | 内容 |
|---|---|---|
0x38000000 |
1 KB | OpenAMP resource_table(NOLOAD) |
0x38000400 |
59 KB | OpenAMP 共享内存(rpmsg 缓冲) |
0x3800F000~0x3800FFFF |
4 KB | CM4 启动 handoff(magic + 入口)、CM4 OTA 握手、运行槽报告 |
CM7 的 MPU 把整个 SRAM4 配置为共享、不可缓存;改这一段布局时必须同时核对两核的 OpenAMP 配置、四份链接脚本与 MPU。
SDRAM 关键区域(FMC 32 MB,0xD0000000 起,可缓存)
| 地址 | 大小 | 内容 |
|---|---|---|
0xD0000000 |
768000 B | 显示帧,LTDC 直接读取 |
0xD0100000 |
— | JPEG 解码工作区(MCU、RGB、输入缓冲) |
0xD0300000 |
768000 B ×2 | 采集帧与待显示帧,两块连续 |
0xD0600000 |
— | 编码用 YCbCr420 MCU 工作区 |
0xD0700000 |
512 KiB ×3 | JPEG 输出三缓冲,至 0xD087FFFF |
0xD0900000 |
768000 B | 抓拍帧,独立于采集三缓冲 |
一帧 RGB565 为 800×480×2 = 768000 字节。采集帧安排在 0xD0300000 起的独立区域,避开 0xD0100000 起的 JPEG 工作缓冲;所有 CPU 与 DMA 交接处都保留了缓存维护操作。
6. 工程结构
仓库包含四个独立构建单元,没有根级统一构建入口:
| 子工程 | 内容 |
|---|---|
Bootloader/ |
CM7 Bootloader 与 CM4 Stub,出厂烧录后一般不再更新 |
BaseProject/ |
双核 A/B 应用固件,本系列的主角 |
qt-ota/ |
Windows 端 OTA 上传上位机(Qt) |
qt-camare/ |
Qt + OpenCV 的相机预览客户端,带 YuNet 人脸检测与 MobileFaceNet 表情识别,计划后续单独成文 |
BaseProject/ 内部按"生成代码 / 应用逻辑 / 板级驱动 / 共享代码"分层:
| 目录 | 说明 |
|---|---|
Makefile/ |
两核各自的构建目录与四份 Flash 链接脚本,产物分 build/(A 槽)与 build_B/(B 槽) |
CM7/Core/、CM4/Core/ |
CubeMX 生成的外设初始化代码,修改保留 USER CODE 区域 |
CM7/APP/ |
CM7 应用逻辑:BOOT(EEPROM 选槽)、CAMERA(采集 / 抓拍 / 存储 / USB)、JPEG、NET/HTTP(服务器与 MJPEG)、OTA、IPC |
CM7/BSP/ |
板级驱动:CAMERA、EEPROM、ETH、LCD、MPU、SDRAM 等 |
CM7/OPENAMP/、CM4/OPENAMP/ |
OpenAMP / HSEM mailbox 通信 |
CM4/APP/ |
CM4 应用逻辑,当前仅 IPC |
Common/ |
双核共享代码:槽位元数据、CM4 启动交接、OTA 握手、RAM 擦写、日志 |
Drivers/、Middlewares/ |
ST HAL、FreeRTOS、LwIP、FatFs、OpenAMP 等,不随意改动 |
tests/ |
升级脚本模拟测试、JPEG 色彩回归、HTTP 实机测试 |
构建在 Windows PowerShell 中进行,使用 GNU Make 与 arm-none-eabi-* 工具链:make -C Makefile 默认构建双核 A 槽(先 CM4 后 CM7),make -C Makefile/CM7 APP_SLOT=B 构建指定核与槽位。四个 make_flash_cm*_slot*.ps1 脚本会构建、烧录指定槽并登记 pending 后复位。
7. 系列文章导航
系列按"通信 → 引导 → 采集 → 网络 → 升级 → 推流 → 存储"的顺序展开,建议按发布顺序阅读:
- 【STM32H757XIH6 双核】IPC 进程间通信 —— OpenAMP 多核异构处理器间通信框架配置:从零配置 OpenAMP,建立双核 rpmsg 通信。
- 【STM32H757XIH6 双核】IPC 进程间通信 —— CM7 printf 重定向到 OpenAMP 发送:CM4 日志经 OpenAMP 回传,双核日志同口输出。
- 【STM32H757XIH6 双核】双核系统 Bootloader:EEPROM 元数据、A/B 选槽、试启动与回退的完整引导方案。
- 【STM32H757XIH6 双核】驱动 OV5640 摄像头模块 + 三缓冲采集 + 双缓冲 DMA2D 搬运:摄像头采集链路与三缓冲显示机制。
- 【STM32H757XIH6 双核】驱动 LAN8720A 实现基础的 HTTP 服务:ETH、LwIP 与基础 HTTP 服务器的搭建。
- 【STM32H757XIH6 双核】HTTP AB 槽位 OTA:HTTP 分块上传与双核 A/B 槽升级确认。
- 【STM32H757XIH6 双核】HTTP MJPEG 浏览器推流:multipart 推流、双观看连接与慢端跳帧。
- 【STM32H757XIH6 双核】SD 抓拍存储以及 USB 设备导出:FatFs 抓拍与 USB 读卡器导出的所有权切换。
博客导航
本文来自博客园,作者:膝盖中箭卫兵,转载请注明原文链接:https://www.cnblogs.com/hai-feng-dev/p/23450734

浙公网安备 33010602011771号
https://orcid.org/0000-0001-5102-772X