dmatest 代码分析

2 篇文章 0 订阅
本文详细解读了Linux内核中dmatest模块的编译加载、模块注册过程、通道申请、资源管理和测试执行。重点介绍了`dmatest_info`和`dmatest_params`结构,以及如何通过echo命令控制模块行为。
摘要由CSDN通过智能技术生成

dmatest 代码分析

dmatest是内核的一个测试dma模块的代码,代码位置位于内核的./drivers/dma/dmatest.c,关于dmatest模块的使用可以参考内核提供的文档./Documentation/dmaengine/dmatest.txt,这里只简单地介绍一下。

编译加载模块

配置支持位置:

Device Drivers -> DMA Engine support -> DMA Test client

或者直接修改配置文件CONFIG_DMATEST=m,编译成模块。

可以直接加载dmatest.ko,然后echo相关参数到/sys/module/dmatest/parameters/下,echo 1 > /sys/module/dmatest/parameters/run驱动就会执行测试过程。

在这里插入图片描述

代码分析

模块注册

先看模块的初始化过程:

在这里插入图片描述

初始过程里面用到了两个结构体,我们来看一下。

struct dmatest_info

在这里插入图片描述

struct dmatest_params

在这里插入图片描述

相关的模块参数就一开始有定义,具体就不多说了,是何上面的结构体基本对应的。

在这里插入图片描述
在这里插入图片描述

这里的run参数指定加载模块时知否直接执行测试:

在这里插入图片描述

这里的wait参数指定加载模块执行测试用例时是否需要等待测试线程执行结束:

在这里插入图片描述

通道申请

注册过程中,会调用run_threaded_test()进行通道申请,海思的hiedmacv310.c中只注册了DMA_MEMCPYDMA_SLAVEDMA_CYCLIC,所以这个模块在这里只能测试DMA_MEMCPY。至于各种传输类型的dma,可以查看内核的文档./Documentation/dmaengine/,后面有机会再介绍一下,这里略过。

在这里插入图片描述

run_threaded_test()调用具体的request_channels()函数进行通道申请 :

在这里插入图片描述

申请通道附加资源

上面申请通道完成后,调用dmatest_add_channel(),这里申请资源来保存申请成功的dma通道指针,并将申请的资源保存到相关链表中:

在这里插入图片描述

创建线程

dmatest_add_channel()调用dmatest_add_threads来创建工作线程,设置线程任务为dmatest_func()后唤醒线程:

在这里插入图片描述

工作任务

dmatest_func()函数比较长:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

回头看一下回调函数的内容,也比较简单,就是设置变量donetrue之后唤醒等待队列wait

在这里插入图片描述

停止传输

协助模块时会调用stop_threaded_test()将传输停止,看一下具体代码实现,遍历链表将所有链表资源进行释放,通道资源进行释放:

在这里插入图片描述

再调用dmatest_cleanup_channel()进行资源清理:

在这里插入图片描述

至此,整个dmatest的代码基本分析完成了。

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F103是一款强大的32位微控制器,它集成了DMA控制器,可以实现高速数据传输。当DMA传输完成后,会触发DMA空闲中断,以下是针对这一中断的代码解析。 首先,在使用DMA之前需要初始化DMA控制寄存器,设置DMA通道、DMA数据传输方向、传输数据长度等参数。接下来需要使能DMA中断和空闲中断。 ```c DMA_InitStructure.DMA_Channel = DMA_Channel_x; //DMA通道 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_Addr; //源地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DST_Addr; //目的地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向 DMA_InitStructure.DMA_BufferSize = Data_Num; //传输数据长度 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址自增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据宽度 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存数据宽度 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //普通模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止内存到内存传输 DMA_Init(DMAx_Channelx, &DMA_InitStructure); //DMA初始化 DMA_ITConfig(DMAx_Channelx, DMA_IT_TC, ENABLE); //使能DMA传输完成中断 DMA_ITConfig(DMAx_Channelx, DMA_IT_TE | DMA_IT_FE, ENABLE); //使能DMA传输错误中断 DMA_ITConfig(DMAx_Channelx, DMA_IT_HT, ENABLE); //使能DMA传输一半中断 DMA_ITConfig(DMAx_Channelx, DMA_IT_GL, ENABLE); //使能DMA全局中断 NVIC_InitStructure.NVIC_IRQChannel = DMAx_Channelx_IRQn; //DMA通道中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; //抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //响应优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能DMA通道中断 NVIC_Init(&NVIC_InitStructure); ``` 当DMA空闲中断触发后,会执行以下中断服务函数: ```c void DMAx_Channelx_IRQHandler(void) { if(DMA_GetITStatus(DMAx_IT_TCx)) { DMA_ClearITPendingBit(DMAx_IT_TCx); //清除传输完成中断标志 } if(DMA_GetITStatus(DMAx_IT_HTx)) { DMA_ClearITPendingBit(DMAx_IT_HTx); //清除传输一半中断标志 } if(DMA_GetITStatus(DMAx_IT_TEx)) { DMA_ClearITPendingBit(DMAx_IT_TEx); //清除传输错误中断标志 } if(DMA_GetITStatus(DMAx_IT_FEx)) { DMA_ClearITPendingBit(DMAx_IT_FEx); //清除传输错误中断标志 } } ``` 在中断服务函数中,首先需要判断哪个中断标志被触发,然后清除标志位。在实际使用中,可以根据需要在中断服务函数中添加相应的数据处理代码。 总之,通过以上代码解析,我们可以更深入地理解STM32F103的DMA空闲中断功能,并在实际应用中更好地利用它。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值