📝 docs(openspec): 新增 DVP-DMA-IR 检查的文档和规范
- 在 openspec/changes/archive/ 下新增 2026-03-13-check-dvp-dma-ir 归档目录
- 新增设计文档 (design.md),包含背景、目标、决策和风险评估
- 新增提案文档 (proposal.md),说明变更原因、内容和影响
- 新增功能规范 (spec.md),定义 DVP 配置验证、DMA 内存传输正确性和诊断输出要求
- 新增任务清单 (tasks.md),列出代码审查、中断处理和诊断验证的具体步骤
- 更新 openspec/config.yaml,添加上下文注释
- 在 openspec/specs/ 下新增 dvp-dma-ir-capture 功能规范
🐛 fix(dvp): 修复 DVP 任务中的竞态条件并增强调试输出
- 在 DVP_Task() 中访问 Line_Ready_Flag 和 Ready_Line_Ptr 前禁用 DVP 中断,操作后重新启用,防止数据竞争
- 增强第0行的调试打印,每秒计算并输出帧率 (fps)
- 新增打印第0行前8个字节的原始数据,用于验证数据有效性
- 使用外部定义的 sys_tick_ms 进行时间计算,确保时间基准一致
This commit is contained in:
parent
621ab220ef
commit
82d672a2d3
@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-03-13
|
||||
@ -0,0 +1,27 @@
|
||||
## Context
|
||||
|
||||
目前项目采用 CH32V30x 微控制器的 DVP (Digital Video Port) 外设,结合 DMA 进行红外图像数据的采集。
|
||||
为保证后续的图像处理或网络传输顺利进行,必须确认目前的 DVP 和 DMA 的配置是正确的,能够稳定、及时、无损地将红外图像帧搬运到 RAM 区,并正确处理帧中断。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- 验证 DVP 引脚配置、时序极性和中断设置是否符合所搭配红外传感器输出时序要求。
|
||||
- 验证 DMA 数据搬运目标地址是否正确分配且对齐,大小是否匹配一帧红外数据。
|
||||
- 确认 DMA/DVP 中断服务程序(ISR)中能有效判断帧结束和 DMA 传输完成,不发生漏帧或混乱。
|
||||
- 添加必要的轻量级日志或断点测试方法来确认取到的数据。
|
||||
|
||||
**Non-Goals:**
|
||||
- 不涉及深度的图像识别或处理算法的开发。
|
||||
- 不涉及改变传感器本身的输出模式配置(除非影响获取数据的基础正确性)。
|
||||
|
||||
## Decisions
|
||||
|
||||
- **检查代码而不是立即重写**: 首先静态走查相关的配置(如 `dvp.c`, `dvp.h`),与 CH32 参考手册进行比对。
|
||||
- **内存块分配策略验证**: 确定 DVP DMA 配置的两块(双缓冲或单缓冲)地址机制,确认没有指针越界风险。
|
||||
- **测试方法**: 在帧结束中断或主循环中计算短时间内获取的有效帧数,并提取部分像素输出串口打印。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] 数据量大可能引起总线或者处理迟滞 → 中断处理要足够短小,不能阻塞下一次 DMA。
|
||||
- [Risk] 直接修改中断服务可能会影响原有稳定的网络栈通信延时 → 在验证阶段避免添加过多阻塞的 printf 等操作。
|
||||
@ -0,0 +1,23 @@
|
||||
## Why
|
||||
|
||||
The current project utilizes the DVP peripheral along with DMA to acquire infrared image data. It is crucial to verify that this configuration operates normally, correctly buffers the frames without corruption, and properly handles interrupts. Ensuring this functionality is fundamental to any downstream vision processing or data transmission.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Comprehensive review of the DVP and DMA initialization configuration.
|
||||
- Verification of memory allocation, frame buffer sizes, and alignment for IR data.
|
||||
- Validation of the DMA complete/error interrupts and data handling routines.
|
||||
- If necessary, adding or enabling diagnostic outputs (logs) or tests to confirm data integrity.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `dvp-dma-ir-capture`: Verifying and ensuring the reliable capture of infrared image data via the CH32V30x DVP peripheral and DMA channels.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
## Impact
|
||||
|
||||
- DVP and DMA initialization code (`prj/TCPClient/Debug/dvp.c`, `prj/TCPClient/Debug/dvp.h`).
|
||||
- Interrupt service routines for DMA/DVP (`prj/TCPClient/User/ch32v30x_it.c`, `prj/TCPClient/User/main.c`).
|
||||
- System memory and buffering allocations.
|
||||
@ -0,0 +1,22 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: DVP configuration verification
|
||||
系统必须具备按预期传感器时序要求正确初始化的外设 DVP,并在捕捉时确保引脚映射和控制极性符合期望。
|
||||
|
||||
#### Scenario: DVP Peripheral correctly starts capture
|
||||
- **WHEN** 系统启动且开启红外捕捉模式
|
||||
- **THEN** DVP 能够捕捉到有效场同步和行同步信号并进行同步
|
||||
|
||||
### Requirement: DMA memory transport correctness
|
||||
DMA 通道必须绑定至 DVP 数据寄存器,并以与图像帧空间匹配(甚至双缓冲)的配置分配目的内存区域,地址不得非法越界。
|
||||
|
||||
#### Scenario: Frame mapped successfully to RAM buffer
|
||||
- **WHEN** DVP 传输满一整帧
|
||||
- **THEN** DMA 完整将其写入指定的 RAM buffer 并生成 DMA 满完成中断。
|
||||
|
||||
### Requirement: Diagnostic outputs for infrared data validation
|
||||
应当包含不阻塞中断流的轻微日志来输出当前捕捉到的前 N 个像素或帧计数,以在运行时供检查验证。
|
||||
|
||||
#### Scenario: User checks IR camera status from terminal
|
||||
- **WHEN** 持续采集数据
|
||||
- **THEN** 主循环能够根据完成标志打印当前帧率及简易采集信息进行调试。
|
||||
@ -0,0 +1,17 @@
|
||||
## 1. 代码配置静态走查
|
||||
|
||||
- [x] 1.1 审查 `prj/TCPClient/Debug/dvp.c` 中的 DVP GPIO 引脚初始化,验证时钟/数据/同步极性设定。
|
||||
- [x] 1.2 审查 `dvp.c` 中相关的 DMA (通常是 DMA2) 源地址和宿地址的初始化是否将 DVP R13 数据正确搬移到 RAM 中。
|
||||
- [x] 1.3 确认定义的 Frame Buffer 内存大小和对齐方式能够完整装载设定的红外单帧尺寸。
|
||||
|
||||
## 2. 检查中断处理和运行时行为
|
||||
|
||||
- [x] 2.1 审查 `prj/TCPClient/User/ch32v30x_it.c` 中的 DMA 中断服务函数和 DVP 帧完成中断,评估是否能可靠地设置标志位。
|
||||
- [x] 2.2 审查主循环 `main.c` 中关于采集标志位的判定清除以及 Buffer 锁机制。
|
||||
- [x] 2.3 (如果原存在)确保代码不存在意外清除或漏检标志位的竞态条件。
|
||||
|
||||
## 3. 添加初步的诊断验证方法
|
||||
|
||||
- [x] 3.1 在主循环成功获取完整一帧处,添加一个基于计数的帧率和帧数调试 `printf` 打印输出。
|
||||
- [x] 3.2 打印接收到的图像数据的前几个字节,用于人工核对同步字或者数据有效性。
|
||||
- [x] 3.3 编译并运行工程,监控终端输出以给出当前 DVP 和 DMA 是否能正常获取红外数据的测试结论。
|
||||
@ -4,10 +4,11 @@ schema: spec-driven
|
||||
# This is shown to AI when creating artifacts.
|
||||
# Add your tech stack, conventions, style guides, domain knowledge, etc.
|
||||
# Example:
|
||||
# context: |
|
||||
# Tech stack: TypeScript, React, Node.js
|
||||
# We use conventional commits
|
||||
# Domain: e-commerce platform
|
||||
context: |
|
||||
使用中文
|
||||
# Tech stack: TypeScript, React, Node.js
|
||||
# We use conventional commits
|
||||
# Domain: e-commerce platform
|
||||
|
||||
# Per-artifact rules (optional)
|
||||
# Add custom rules for specific artifacts.
|
||||
|
||||
22
openspec/specs/dvp-dma-ir-capture/spec.md
Normal file
22
openspec/specs/dvp-dma-ir-capture/spec.md
Normal file
@ -0,0 +1,22 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: DVP configuration verification
|
||||
系统必须具备按预期传感器时序要求正确初始化的外设 DVP,并在捕捉时确保引脚映射和控制极性符合期望。
|
||||
|
||||
#### Scenario: DVP Peripheral correctly starts capture
|
||||
- **WHEN** 系统启动且开启红外捕捉模式
|
||||
- **THEN** DVP 能够捕捉到有效场同步和行同步信号并进行同步
|
||||
|
||||
### Requirement: DMA memory transport correctness
|
||||
DMA 通道必须绑定至 DVP 数据寄存器,并以与图像帧空间匹配(甚至双缓冲)的配置分配目的内存区域,地址不得非法越界。
|
||||
|
||||
#### Scenario: Frame mapped successfully to RAM buffer
|
||||
- **WHEN** DVP 传输满一整帧
|
||||
- **THEN** DMA 完整将其写入指定的 RAM buffer 并生成 DMA 满完成中断。
|
||||
|
||||
### Requirement: Diagnostic outputs for infrared data validation
|
||||
应当包含不阻塞中断流的轻微日志来输出当前捕捉到的前 N 个像素或帧计数,以在运行时供检查验证。
|
||||
|
||||
#### Scenario: User checks IR camera status from terminal
|
||||
- **WHEN** 持续采集数据
|
||||
- **THEN** 主循环能够根据完成标志打印当前帧率及简易采集信息进行调试。
|
||||
@ -12,6 +12,7 @@ volatile uint32_t current_line_idx = 0;
|
||||
static uint32_t frame_count = 0;
|
||||
|
||||
extern u8 socket[];
|
||||
extern volatile uint32_t sys_tick_ms;
|
||||
|
||||
void DVP_Init(void)
|
||||
{
|
||||
@ -51,9 +52,11 @@ void DVP_Task(void)
|
||||
{
|
||||
if (!Line_Ready_Flag) return;
|
||||
|
||||
NVIC_DisableIRQ(DVP_IRQn);
|
||||
uint8_t *line = (uint8_t *)Ready_Line_Ptr;
|
||||
uint32_t idx = current_line_idx;
|
||||
Line_Ready_Flag = 0;
|
||||
NVIC_EnableIRQ(DVP_IRQn);
|
||||
|
||||
/* 仅发送图像行,跳过参数行,且 socket 已连接 */
|
||||
if (idx < SENSOR_HEIGHT && socket[0] != 0xFF)
|
||||
@ -68,9 +71,21 @@ void DVP_Task(void)
|
||||
len = BYTES_PER_LINE;
|
||||
WCHNET_SocketSend(socket[0], line, &len);
|
||||
|
||||
/* 每帧第0行打印一次,确认帧号和socket状态 */
|
||||
if (idx == 0)
|
||||
printf("[DVP] frame=%lu socket=%d\r\n", frame_count, socket[0]);
|
||||
/* 每帧第0行打印一次,确认帧率、帧号和socket状态与数据 */
|
||||
if (idx == 0) {
|
||||
static uint32_t last_fps_tick = 0;
|
||||
static uint32_t last_frame_count = 0;
|
||||
uint32_t now = sys_tick_ms;
|
||||
|
||||
if (now - last_fps_tick >= 1000) {
|
||||
uint32_t fps = frame_count - last_frame_count;
|
||||
printf("[DVP] frame=%lu fps=%lu socket=%d tick=%lu\r\n", frame_count, fps, socket[0], now);
|
||||
printf(" Row0 Data: %02X %02X %02X %02X %02X %02X %02X %02X\r\n",
|
||||
line[0], line[1], line[2], line[3], line[4], line[5], line[6], line[7]);
|
||||
last_fps_tick = now;
|
||||
last_frame_count = frame_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (idx == 0 && socket[0] == 0xFF)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user