AI嵌入式K210项目(9)-DMA

文章介绍了K210芯片的DMA控制器,阐述了DMA工作原理,包括DMA请求、响应和传输过程,以及如何在内存与外设间高效传输数据,以减少CPU负担。实验示例展示了如何通过DMA进行UART数据传输,优化CPU性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

本章我们来介绍K210的DMA控制器,大家应该都知道在大数据量传输时,如果CPU全程参与,是非常浪费资源的,于是芯片内置了DMAC用做传输控制,CPU仅仅在输出传输开始和结束时参与,这样大大降低了CPU的负载,同时也可以加快传输的速率,一举两得,本章我们一起来学习下;


一、DMA是什么?

MA 传输将数据从一个地址空间复制到另外一个地址空间。当CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存区。像是这样的操作并没有让处理器工作拖延,反而可以被重新排程去处理其他的工作。

在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题。即DMA传输前,CPU要把总线控制权交给DMA控制器,而在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU。一个完整的DMA传输过程必须经过DMA请求、DMA响应、DMA传输、DMA结束4个步骤。

请求:CPU对DMA控制器初始化,并向I/O接口发出操作命令,I/O接口提出DMA请求。

响应:DMA控制器对DMA请求判别优先级及屏蔽,向总线裁决逻辑提出总线请求。当CPU执行完当前总线周期即可释放总线控制权。此时,总线裁决逻辑输出总线应答,表示DMA已经响应,通过DMA控制器通知I/O接口开始DMA传输。

传输:DMA控制器获得总线控制权后,CPU即刻挂起或只执行内部操作,由DMA控制器输出读写命令,直接控制RAM与I/O接口进行DMA传输。

在DMA控制器的控制下,在存储器和外部设备之间直接进行数据传送,在传送过程中不需要中央处理器的参与。开始时需提供要传送的数据的起始位置和数据长度。

结束:当完成规定的成批数据传送后,DMA控制器即释放总线控制权,并向I/O接口发出结束信号。当I/O接口收到结束信号后,一方面停止I/O设备的工作,另一方面向CPU提出中断请求,使CPU从不介入的状态解脱,并执行一段检查本次DMA传输操作正确性的代码。最后,带着本次操作结果及状态继续执行原来的程序。

由此可见,DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,使CPU的效率大为提高。

辅助大家理解的话,也可以参考我的这篇博客 STM32开发(16)----CubeMX配置DMA

二、K210的DMA

直接存储访问 (Direct Memory Access, DMA) 用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据,从而提高了 CPU 的效率。

DMA 模块具有以下功能:
• 自动选择一路空闲的 DMA 通道用于传输
• 根据源地址和目标地址自动选择软件或硬件握手协议
• 支持 1、2、4、8 字节的元素大小,源和目标大小不必一致
• 异步或同步传输功能
• 循环传输功能,常用于刷新屏幕或音频录放等场景

DMAC 具有高度可配置化,高度可编程,在总线模式下传输数据具有高效率,DMAC 控制器具有多主机,
多频道等特点。DMAC 具有如下特点:
多达八个通道,每路通道都有源和目的地对
每个通道数据传输数据时每个时刻只能有一个方向传输,不同通道则不受影响
• 内存-内存,内存-外设,外设-内存,外设-外设的 DMA 传输
• 具有独立的核心,主接口和从接口独立时钟
• 当所有外设不活动时主接口可以关闭其时钟来省电
• 输入管脚可以动态选择大小端制式
• 通道锁支持,支持内部通道仲裁,根据数据传输的优先级来使用主接口总线的特权
• DMAC 状态输出,空闲/忙指示
• DMA 传输分配成传输中,被中断,传输完成等传输等级

对应的头文件 dmac.h
为用户提供以下接口
• dmac_init
• dmac_set_single_mode
• dmac_is_done
• dmac_wait_done
• dmac_set_irq
• dmac_set_src_dest_length
• dmac_is_idle
• dmac_wait_idle

实验过程

DMA支持的使用方式非常多,如内存-内存,内存-外设,外设-内存,外设-外设的 DMA 传输,我们这个实验做一个从外设->内存读取数据,然后将数据再使用DMA将数据从内存->外设传输出去;
新建dma文件夹,在其中新建main.c文件
在这里插入图片描述
本示例使用UART3外设,代码实现如下,其实和之前的UART实验很类似,只是在发送和接收的时候使用了uart_receive_data_dma() , uart_send_data_dma()这两个API,其实各种外设基本都支持DMA,可以到对应外设的API部分去查找使用,这里注意的是,发送和接收使用了两根不同的DMA通道,不要重复了
代码实现如下:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "uart.h"
#include "sysctl.h"
#include "fpioa.h"

// 硬件IO口,与原理图对应
#define PIN_UART_USB_RX       (4)
#define PIN_UART_USB_TX       (5)

/*****************************SOFTWARE-GPIO********************************/
// 软件GPIO口,与程序对应
#define UART_USB_NUM           UART_DEVICE_3

/*****************************FUNC-GPIO************************************/
// GPIO口的功能,绑定到硬件IO口
#define FUNC_UART_USB_RX       (FUNC_UART1_RX + UART_USB_NUM * 2)
#define FUNC_UART_USB_TX       (FUNC_UART1_TX + UART_USB_NUM * 2)


/**
* Function       hardware_init
* @brief         硬件初始化,绑定GPIO口
* @param[in]     void
* @param[out]    void
* @retval        void
* @par History   无
*/
void hardware_init(void)
{
    // fpioa映射
    fpioa_set_function(PIN_UART_USB_RX, FUNC_UART_USB_RX);
    fpioa_set_function(PIN_UART_USB_TX, FUNC_UART_USB_TX);
}

/**
* Function       main
* @brief         主函数,程序的入口
* @param[in]     void
* @param[out]    void
* @retval        0
* @par History   无
*/
int main(void)
{
    hardware_init();
    // 初始化串口3,设置波特率为115200
    uart_init(UART_USB_NUM);
    
    uart_configure(UART_USB_NUM, 115200, UART_BITWIDTH_8BIT, UART_STOP_1, UART_PARITY_NONE);

    char *hello = {"hello world!\n"};
    
    uart_send_data_dma(UART_USB_NUM, DMAC_CHANNEL0, (uint8_t *)hello, strlen(hello));

    uint8_t recv = 0;

    while (1)
    {
        /* 通过DMA通道1接收串口数据,保存到recv中 */
        uart_receive_data_dma(UART_USB_NUM, DMAC_CHANNEL1, &recv, 1);
         /* 通过DMA通道0发送数据到串口 */
        uart_send_data_dma(UART_USB_NUM, DMAC_CHANNEL0, &recv, 1);
       
    }
    return 0;
}

代码写好后,我们开始编译,注意:如果你编译过程中出现错误,可以先make clean掉之前生成的过程文件,重新生成

cd build
//注意这里的目标文件目录改成dma,和刚才新建的文件夹名称一致
cmake .. -DPROJ=dma  -G "MinGW Makefiles"
make

编译完成后,在build文件夹下会生成dma.bin文件。

使用type-C数据线连接电脑与K210开发板,打开kflash,选择对应的设备,再将程序固件烧录到K210开发板上。
在这里插入图片描述
实验现象如下:
在这里插入图片描述


总结

DMAC是可以提高CPU效率,直接通过DMA在设备和内存之间传输数据,而CPU只需要启动dma传输就可以,等待完成即可,直接内存存取控制器DMAC需要搭配其他的设备,如串口、I2C或者I2S通讯来使用,发送和传输使用不同的通道;

<think>好的,用户想了解K210芯片在眼球追踪项目中的实现方案。首先,我需要回忆一下K210的基本特性。K210是一款基于RISC-V架构的低功耗AI芯片,具备双核处理能力,支持卷积神经网络加速,适合边缘计算场景。眼球追踪通常需要实时图像处理和机器学习模型,所以K210的KPU(神经网络处理器)和图像处理单元可能派上用场。 接下来,用户提到的眼球追踪项目需要具体实现方案。我需要考虑硬件和软件两方面的设计。硬件部分,可能需要摄像头模块来捕捉眼部图像,比如OV2640,因为K210支持这类摄像头。同时,可能还需要LCD显示屏来实时显示追踪结果,以及足够的存储空间来存放模型和数据。 软件方面,首先需要图像采集和预处理。K210的DVP接口可以连接摄像头,使用MicroPython或C SDK进行开发。预处理步骤可能包括灰度化、直方图均衡化等,以减少计算量。然后是特征提取,比如瞳孔检测,可能需要使用OpenMV的库函数,或者自行实现边缘检测算法,比如Canny算子。 模型部署是关键部分。由于K210的KPU支持量化后的模型,可能需要将训练好的眼球追踪模型(比如基于CNN的)转换为K210支持的格式,比如.kmodel。这里可能需要使用NNCase这样的工具进行模型转换和量化。需要注意的是,模型的大小和复杂度必须适应K210的内存限制,256KB的片上内存可能限制模型规模,因此可能需要简化模型结构或采用轻量级网络。 算法优化方面,可能需要结合传统图像处理方法和机器学习模型。例如,先通过阈值分割或轮廓检测定位眼球区域,再使用小型CNN进行瞳孔坐标回归。此外,可以考虑使用卡尔曼滤波来平滑追踪结果,减少抖动。 另外,用户可能需要了解现有项目或开源资源。比如在GitHub上搜索K210 eye tracking,可能会有相关的代码库或教程。OpenMV社区也可能有类似的案例,因为OpenMV H7 Plus也使用K210,可能有可借鉴的代码。 最后,需要考虑实际应用中的挑战,比如光照变化对图像处理的影响,可能需要动态调整摄像头参数或增加补光。实时性方面,K210的主频为400MHz,足够处理中等复杂度的任务,但需优化代码避免延迟。此外,数据集的获取和模型训练可能需要使用公开的眼球追踪数据集,或者在实验室环境下自行采集数据。 总结下来,实现方案应包括硬件选型、图像采集与预处理、模型训练与部署、算法优化以及实时处理与调试等步骤。需要综合运用K210的硬件特性和软件工具,同时结合实际应用场景进行调整和优化。</think>### K210眼球追踪项目实现方案 K210芯片凭借其低功耗、AI加速特性,在嵌入式视觉领域(如眼球追踪)具有显著优势[^1]。以下是基于K210的眼球追踪实现方案: #### 一、硬件架构设计 1. **核心组件** - K210开发板(如Maixduino或Sipeed M1) - OV2640摄像头(支持最高1600x1200分辨率) - 2.4英寸LCD显示屏(用于实时显示追踪结果) - 外接存储模块(如MicroSD卡,存放模型文件) 2. **硬件连接** ```python # 摄像头初始化示例 import sensor sensor.reset() sensor.set_pixformat(sensor.RGB565) sensor.set_framesize(sensor.QVGA) ``` #### 二、算法实现流程 1. **图像采集与预处理** - 使用DVP接口获取30fps视频流 - 预处理步骤: $$ \text{灰度化} \rightarrow \text{直方图均衡化} \rightarrow \text{高斯滤波}(σ=1.5) $$ 2. **特征提取** - Haar级联检测器定位人脸区域 - 基于阈值分割的瞳孔定位算法: $$ I_{binary}(x,y) = \begin{cases} 1 & \text{if } I_{gray}(x,y) < \theta \\ 0 & \text{otherwise} \end{cases} $$ 3. **模型部署** - 使用YOLOv5-Tiny量化模型(转换为.kmodel格式) - KPU加速推理实现实时处理: ```python kpu.load("/sd/eye_track.kmodel") fmap = kpu.forward(aimg) ``` #### 三、性能优化策略 1. **内存管理** - 采用双缓冲机制处理图像数据 - 限制模型输入尺寸为224x224像素 2. **算法加速** - 固定点运算替代浮点运算 - 使用FFT加速卷积运算: $$ \mathcal{F}\{f*g\} = \mathcal{F}\{f\} \cdot \mathcal{F}\{g\} $$ 3. **实时性保障** - 算法耗时控制在30ms/帧以内 - 通过DMA实现零拷贝数据传输 #### 四、典型应用场景 1. 智能眼镜的注视点交互系统 2. 残疾人辅助设备的眼控接口 3. 驾驶员疲劳检测系统[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶与花语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值