DMA-330是ARM CoreLink系列中的第三代DMA控制器IP核,采用AMBA 4 AXI总线协议,专为高性能SoC设计优化。其核心架构包含三个关键子系统:
通道控制器:管理最多32个独立DMA通道,每个通道可配置为:
微引擎(Microcode Engine):执行DMA指令集的32位RISC处理器,支持:
AXI接口单元:包含两个64位AXI主端口:
实际项目中,我们通常将主端口0连接至紧耦合存储器(TCM)或L2缓存,主端口1连接至主存控制器,这种设计可确保实时性要求高的数据传输获得最低延迟。
DMA-330支持以下配置环境:
安装AMBA Designer时需特别注意:
设置环境变量:
bash复制export AMBA_HOME=/opt/arm/amba_designer
export PATH=$AMBA_HOME/bin:$PATH
验证安装:
bash复制adcanvas --version
应输出类似:AMBA Designer 2.3.0 (build 5421)
常见问题排查:
bash复制sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt install libstdc++6
通过AMBA Designer配置DMA-330的典型步骤:
创建新工程:
tcl复制create_project -name dma_demo -path ./projects
添加DMA-330 IP:
tcl复制add_ip -name DMA330 -version r1p2
关键参数配置:
| 参数项 | 推荐值 | 说明 |
|---|---|---|
| NUM_CHANNELS | 8 | 根据实际需求调整 |
| DATA_WIDTH | 64 | 匹配AXI总线位宽 |
| SECURE_ACCESS | Enabled | 启用TrustZone安全支持 |
| IRQ_ENABLE | Level-sensitive | 中断触发方式 |
生成RTL:
tcl复制generate -format verilog -output ./rtl
c复制// 设置256字节突发传输
DMAC->CCR |= (0x7 << 12); // 设置ARLEN=7(8拍突发)
DMAC->CCR |= (1 << 15); // 使能固定突发模式
c复制// 启用预取机制
DMAC->CFG |= (1 << 3); // 设置PREFETCH_EN
配置DMA-330实现1080p图像采集:
c复制void dma_config_image_transfer(uint32_t src, uint32_t dst, uint32_t size) {
DMAC->SAR = src; // 传感器数据寄存器地址
DMAC->DAR = dst; // 帧缓冲区地址
DMAC->CTRL = size / 8; // 按64位宽度计算传输次数
DMAC->CCR |= (1 << 0); // 通道使能
}
c复制void DMA_IRQHandler(void) {
if(DMAC->ISR & (1 << 0)) { // 通道0中断标志
frame_ready_flag = 1;
DMAC->ISR = (1 << 0); // 清除中断
}
}
实现I2S音频流传输配置:
c复制void config_audio_dma(uint32_t buf_addr, uint32_t block_size) {
DMAC->SAR = I2S_DATA_REG;
DMAC->DAR = buf_addr;
DMAC->CTRL = block_size / 4; // 32位音频数据
DMAC->CCR |= (3 << 1); // 循环模式
DMAC->CCR |= (1 << 5); // 自动重载
}
DMA-330内置的OVL断言分为四个级别:
| 级别 | 颜色标识 | 典型场景 | 处理建议 |
|---|---|---|---|
| INFO | 蓝色 | 带宽利用率提示 | 参考优化建议 |
| WARNING | 黄色 | 安全域访问冲突 | 检查TrustZone配置 |
| ERROR | 橙色 | 非法通道访问 | 修正DMA程序 |
| FATAL | 红色 | RTL内部错误 | 联系ARM技术支持 |
启用OVL监控:
tcl复制# 在仿真脚本中添加
set_ovl_mode -mode all -severity {info warning error fatal}
bash复制axi_monitor -dma DMAC -out perf.log
传输字节数 / (时钟周期 × 总线宽度)ARREADY到RVALID的周期数实现视频编解码器中的YUV分离处理:
c复制void config_yuv_split(uint32_t y_addr, uint32_t uv_addr) {
// 通道0传输Y分量
DMAC->CH[0].SAR = VIDEO_SRC;
DMAC->CH[0].DAR = y_addr;
DMAC->CH[0].CTRL = FRAME_SIZE / 2;
// 通道1传输UV分量
DMAC->CH[1].SAR = VIDEO_SRC + FRAME_SIZE / 2;
DMAC->CH[1].DAR = uv_addr;
DMAC->CH[1].CTRL = FRAME_SIZE / 2;
// 同步启动
DMAC->CH[0].CCR |= (1 << 0);
DMAC->CH[1].CCR |= (1 << 0);
}
在TrustZone环境中配置安全通道:
c复制// 通道0为安全通道
DMAC->CH[0].SCR |= (1 << 0);
// 通道1为非安全通道
DMAC->CH[1].SCR &= ~(1 << 0);
c复制DMAC->SAR_SEC = 0x10000000; // 安全区域起始
DMAC->EAR_SEC = 0x1FFFFFFF; // 安全区域结束
当DMA传输停止时,按以下步骤检查:
查看状态寄存器:
c复制uint32_t status = DMAC->SR;
检查AXI总线状态:
c复制if(status & (1 << 2)) {
uint32_t axi_err = DMAC->AXI_ERR;
// 解析AXI协议错误码
}
典型性能问题及解决方法:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 带宽利用率<50% | 突发长度设置过小 | 增大ARLEN/ARLEN参数 |
| 延迟波动大 | 总线仲裁优先级低 | 调整QoS参数 |
| 频繁中断 | 传输块大小不合理 | 增大块大小或使用循环模式 |
我在实际项目中发现,当DMA传输大量小数据块时,适当增大AXI总线的outstanding能力可以显著提升性能:
c复制// 设置最大outstanding数为8
DMAC->AXI_CFG |= (7 << 4);