VDMA工作機(jī)制
詳細(xì)解釋VDMA(Video Direct Memory Access)在Zynq平臺上的工作機(jī)制,特別是在照相機(jī)系統(tǒng)中的應(yīng)用。VDMA是Xilinx提供的一個(gè)IP核,用于在內(nèi)存(DDR)和視頻流設(shè)備(如攝像頭、顯示器)之間高效傳輸視頻數(shù)據(jù)。
VDMA核心架構(gòu)
// 配置VDMA
run_vdma_frame_buffer(&vdma, VDMA_ID, 1280, 720,frame_buffer_addr, 0, 0, BOTH);
此代碼配置:
分辨率:1280×720
幀緩沖區(qū)地址:0x1000000
雙通道使能
2. 視頻采集(寫通道 S2MM)
3. 視頻顯示(讀通道 MM2S)
DisplayStart(&dispCtrl); // 啟動(dòng)顯示控制器
VDMA的核心功能
VDMA在視頻系統(tǒng)中扮演“數(shù)據(jù)搬運(yùn)工”的角色,其主要功能包括:
1. 實(shí)現(xiàn)視頻流與內(nèi)存之間的高速數(shù)據(jù)傳輸
2. 支持多幀緩沖管理(Frame Buffering)
3. 提供可編程的幀同步機(jī)制
VDMA在照相機(jī)系統(tǒng)中的工作流程
以OV5640+HDMI系統(tǒng)為例,VDMA的工作分為兩個(gè)通道:
-寫通道(S2MM, Stream to Memory Map):將來自攝像頭的視頻流數(shù)據(jù)寫入DDR
-讀通道(MM2S, Memory Map to Stream):將DDR中的視頻數(shù)據(jù)讀出并發(fā)送給顯示器
關(guān)鍵機(jī)制詳解
1. 多幀緩沖(Frame Buffering)
VDMA使用環(huán)形緩沖區(qū)(Ring Buffer)管理多個(gè)幀:
配置了3個(gè)幀緩沖(`FRAME_BUFFER_NUM=3`)
每個(gè)幀緩沖區(qū)大?。?span>`1280x720x3 = 2.63MB`
緩沖區(qū)地址連續(xù)存儲(chǔ):
// 幀緩沖區(qū)基地址
unsigned int const frame_buffer_addr = ...;
// 第n幀地址計(jì)算
rd_fram_addr = frame_buffer_addr + vd_mode.height*vd_mode.width*3 * rd_index;
```
VDMA通過乒乓操作(Ping-Pong Buffering)實(shí)現(xiàn)無縫傳輸:
當(dāng)攝像頭寫入幀N時(shí),VDMA可同時(shí)將幀N-1發(fā)送給顯示器
三緩沖設(shè)計(jì)避免讀寫沖突:
幀0:正在被攝像頭寫入(S2MM)
幀1:正在被顯示器讀?。?span>MM2S)
幀2:空閑(可被處理/保存)
2. 同步機(jī)制(Synchronization)
VDMA通過幀同步信號協(xié)調(diào)數(shù)據(jù)傳輸:
寫通道同步:使用OV5640的VSYNC(幀同步)信號
讀通道同步:使用VTC(Video Timing Controller)生成的時(shí)序
關(guān)鍵寄存器控制:
VSIZE:設(shè)置每幀行數(shù)(720)
HSIZE:設(shè)置每行像素?cái)?shù)(1280×4字節(jié),32位總線)
STRIDE:行跨度(1280×3=3840字節(jié))
3. 中斷與狀態(tài)管理
VDMA提供可編程中斷:
幀結(jié)束中斷(Frame Complete Interrupt)
寫通道:完成一幀寫入時(shí)觸發(fā)
讀通道:完成一幀讀取時(shí)觸發(fā)
在拍照功能中利用中斷替代輪詢:
// 凍結(jié)當(dāng)前幀(代碼示例)
XAxiVdma_StartParking(&vdma, rd_index, XAXIVDMA_READ);
4. 數(shù)據(jù)格式轉(zhuǎn)換
VDMA在AXI協(xié)議間轉(zhuǎn)換:
S2MM方向:
`AXI4-Stream`(無地址)→ `AXI4-Memory Map`(帶DDR地址)
MM2S方向:
`AXI4-Memory Map` → `AXI4-Stream`
```mermaid
graph TB
subgraph PL端
A[OV5640] -- Video Stream --> B[VDMA S2MM]
D[VDMA MM2S] -- Video Stream --> E[HDMI]
end
subgraph PS端
B -- AXI HP接口 --> C[DDR控制器]
C --> D
end
```
5. 性能優(yōu)化技術(shù)
突發(fā)傳輸(Burst Transfer):
VDMA使用INCR突發(fā)模式,單次突發(fā)長度=128(Zynq最大值)
數(shù)據(jù)對齊:
幀起始地址128字節(jié)對齊(避免Cache一致性問題)
異步時(shí)鐘域:
攝像頭時(shí)鐘(PCLK)和VDMA工作時(shí)鐘獨(dú)立,通過FIFO跨時(shí)鐘域
在代碼中的具體體現(xiàn)
// VDMA初始化配置
run_vdma_frame_buffer(&vdma,
VDMA_ID,
vd_mode.width, // 1280
vd_mode.height, // 720
frame_buffer_addr,
0, 0, BOTH); // 啟用讀寫通道
// 拍照時(shí)凍結(jié)幀
XAxiVdma_StartParking(&vdma, rd_index, XAXIVDMA_READ);
常見問題解決方案
1. 圖像撕裂問題:
- 原因:讀寫指針同時(shí)訪問同一幀
- 解決:使用三緩沖+精確幀同步
2. 帶寬不足:
- 現(xiàn)象:VDMA的TREADY信號頻繁置低
優(yōu)化:提升總線寬度(32→64位)或時(shí)鐘頻率(100→150MHz)
3. 時(shí)序違例:
- 現(xiàn)象:HDMI顯示錯(cuò)位
- 解決:在Vivado中添加時(shí)序約束:
set_false_path -from [get_clocks cam_clk] -to [get_clocks vdma_clk]