0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何用AXI-DMA批量发送数据到DMA

电子设计 ? 来源:电子设计 ? 作者:电子设计 ? 2022-01-21 14:08 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1.1 主函数
int main(void)

{

XGpio_Initialize(&Gpio, AXI_GPIO_DEV_ID);

XGpio_SetDataDirection(&Gpio, 1, 0);

init_intr_sys();

XGpio_DiscreteWrite(&Gpio, 1, 1);

axi_dma_test();

}

1.2 三个简单函数
(1)、XGpio_Initialize(&Gpio, AXI_GPIO_DEV_ID);

本语句对GPIO进行初始化,对实例数据进行配置。

(2)、XGpio_SetDataDirection(&Gpio, 1, 0);

设置GPIO的方向,向通道1写0,0:输出,1:输入。

(3)、XGpio_DiscreteWrite(&Gpio, 1, 1);

设置GPIO的输出为1。

一、 init_intr_sys函数分析
1、DMA_Intr_Init(&AxiDma,0);
DMA中断实例化函数,将要配置的DMA信息先lookupConfig再进行CfgInitialize,DMA采用块模式(Block mode),如果是Sg模式,则配置失败。

2、Timer_init(&Timer,TIMER_LOAD_VALUE,0);
定时器初始化函数,传入参数有定时器结构、加载值,设备ID。初始化过程为先进行lookupConfig再进行CfgInitialize,实现实例结构的配置,Timer定时器的基本地址:0xf8F00600,然后通过XScuTimer_LoadTimer(TimerPtr, Load_Value);将要设定的定时时间设定值写入(0xf8F00600+XSCUTIMER_LOAD_OFFSET(0x00))寄存器设定加载值。最后设置定时器为自动加载模式,方法是在(0xf8F00600+XSCUTIMER_CONTROL_OFFSET(0x08))的bit2置一,将定时器成功设置为AutoLoad(自动加载)模式。

3、Init_Intr_System(&Intc);
初始化中断系统,将要配置的系统中断信息先lookupConfig再进行CfgInitialize,实现系统中断结构的配置。

4、Setup_Intr_Exception(&Intc);
4.1、注册中断处理函数
4.1.1 注册中断
建立中断函数,传入参数是XscGic系统控制中断结构体,然后通过Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,

(Xil_ExceptionHandler)XScuGic_InterruptHandler,

(void *)IntcInstancePtr);

中断函数注册,第一个参数是中断号,#5,中断号为5,第二个参数为中断处理函数的指针地址,第三个参数为对调用中断处理程序时传递给中断处理程序的数据的引用,函数原型为

Xil_ExceptionRegisterHandler(u32 Exception_id,

Xil_ExceptionHandler Handler,

void *Data),

该函数将对应中断ID的处理函数进行存储,并将对应中断ID的传入数据传入中断处理表中进行存储。

4.1.2 中断处理函数
在本函数中,中断处理函数为(Xil_ExceptionHandler)XScuGic_InterruptHandler,该函数的定义是:void XScuGic_InterruptHandler(XScuGic *InstancePtr),此函数是驱动程序的主要中断处理程序。他必须连接到中断源,以便在中断控制器中断额中断激活时调用中断处理程序,他将解析那些中断是激活启用的,并调用适当的中断处理程序,使用中断类型来信息确定合适确定中断,最高优先级的中断优先得到中断服务。

4.2 中断使能函数
#define Xil_ExceptionEnable() /

Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ)

在中断使能控制寄存器中写入中断使能,使能通用系统中断。

5、DMA_Setup_Intr_System();
5.1 整体说明
语句函数DMA_Setup_Intr_System(&Intc,&AxiDma,TX_INTR_ID,RX_INTR_ID);作用是建立DMA系统中断,第一个参数是系统中断实例结构,第二个参数是AxiDma引擎实例的指针,第三个参数是发送中断的ID号(61),第四个参数是接收中断的ID号(62)。

此函数设置中断系统,以便发生DMA中断,假定在硬件系统中存在中断组成。

函数原型为:

int DMA_Setup_Intr_System(XScuGic * IntcInstancePtr,XAxiDma * AxiDmaPtr, u16 TxIntrId, u16 RxIntrId)

{

int Status;

XScuGic_SetPriorityTriggerType(IntcInstancePtr, TxIntrId, 0xA0, 0x3);

XScuGic_SetPriorityTriggerType(IntcInstancePtr, RxIntrId, 0xA0, 0x3);

/*

* Connect the device driver handler that will be called when an

* interrupt for the device occurs, the handler defined above performs

* the specific interrupt processing for the device.

*/

Status = XScuGic_Connect(IntcInstancePtr, TxIntrId,

(Xil_InterruptHandler)DMA_TxIntrHandler,

AxiDmaPtr);

if (Status != XST_SUCCESS) {

return Status;

}

Status = XScuGic_Connect(IntcInstancePtr, RxIntrId,

(Xil_InterruptHandler)DMA_RxIntrHandler,

AxiDmaPtr);

if (Status != XST_SUCCESS) {

return Status;

}

XScuGic_Enable(IntcInstancePtr, TxIntrId);

XScuGic_Enable(IntcInstancePtr, RxIntrId);

return XST_SUCCESS;

}

5.2 设置中断优先级与触发方式
XScuGic_SetPriorityTriggerType(IntcInstancePtr, TxIntrId, 0xA0, 0x3);

XScuGic_SetPriorityTriggerType(IntcInstancePtr, RxIntrId, 0xA0, 0x3);

该函数将AxiDma实例结构的中断优先级重新配置,同时设置中断触发方式,TxIntrId:61,RxIntrId:62。函数原型:

XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id,

u8 Priority, u8 Trigger)

参数1:要处理的系统中断实例的指针

参数2:要设置的中断源的中断ID

参数3:中断的新优先级,0是最高优先级,0xF8最低。一共有32个优先级,每8个为一级,0,8,16,32,40,…..248,共32个。

参数4:定时器中断触发方式 0x01:定时器高电平触发 0x03:PPI(定时器)上升沿触发。

5.2.1 函数定义
void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id,

u8 Priority, u8 Trigger)

{

u32 RegValue;

u8 LocalPriority;

LocalPriority = Priority;

Xil_AssertVoid(InstancePtr != NULL);

Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

Xil_AssertVoid(Int_Id

Xil_AssertVoid(Trigger

Xil_AssertVoid(LocalPriority

/*

使用int-id确定要写入的寄存器,读取的地址是0xf8f00100+(0x0400+0x3c),该寄存器为ICDIPR15,中断优先级控制寄存器,每个寄存器为GIC(通用中断控制寄存器)提供8位的优先级字段,每个字段只有高5位是可读写的,低5位总是0,一共32个优先级,ICDIPR0到ICDIPR7存储着连接的每个处理器的中断优先级。

*/

RegValue = XScuGic_DistReadReg(InstancePtr,

XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id));

LocalPriority = LocalPriority & (u8)XSCUGIC_INTR_PRIO_MASK;

/*

*移位并屏蔽寄存器中优先级和触发器的正确位

*/

RegValue &= ~(XSCUGIC_PRIORITY_MASK

RegValue |= (u32)LocalPriority

/*

* 再将中断优先号写回寄存器

*/

XScuGic_DistWriteReg(InstancePtr, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id),

RegValue);

}

5.3、 XScuGic_Connect()
中断连接,XScuGic_Connect(IntcInstancePtr, TxIntrId,

(Xil_InterruptHandler)DMA_TxIntrHandler,

AxiDmaPtr);

连接当设备发生中断时将调用的设备驱动程序处理程序,上面定义的中断处理程序执行设备的特定中断处理。中断处理函数是(Xil_InterruptHandler)DMA_TxIntrHandler,中断函数的传入参数是Axidma类型的实例结构指针AxiDmaPtr,

函数原型:

s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id,

Xil_InterruptHandler Handler, void *CallBackRef)

{

/*

* Assert the arguments

*/

Xil_AssertNonvoid(InstancePtr != NULL);

Xil_AssertNonvoid(Int_Id

Xil_AssertNonvoid(Handler != NULL);

Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

/*

* The Int_Id is used as an index into the table to select the proper

* handler

*/

InstancePtr->Config->HandlerTable[Int_Id].Handler = Handler;

InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = CallBackRef;

return XST_SUCCESS;

}

函数功能:

在int_id中断源对应的中断源和要运行的中断处理程序之间建立连接,Callback提供参数。

*@param instanceptr是指向xscugic实例的指针。

*@param int_id包含中断源的id,应该在0到xscugic_max_num_intr_inputs-1的范围内

*@该中断的处理程序的param handler。

5.3.1、中断处理函数
函数功能:从硬件中获取中断状态并确认中断,如果发生任何错误则重置硬件,否则,如果存在中断,则设置中断标志(本函数中对应的是接收中断标志,所以会设置rxdone标志)。 callback是指向dma引擎的rx通道的指针

static void DMA_RxIntrHandler(void *Callback)

{

u32 IrqStatus;

int TimeOut;

/*

获取中断状态,查看输入的结构指针中的中断位

*/

XAxiDma *AxiDmaInst = (XAxiDma *)Callback;

/* Read pending interrupts */

IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DEVICE_TO_DMA);

/* Acknowledge pending interrupts */

XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DEVICE_TO_DMA);

/*

* If no interrupt is asserted, we do not do anything

*/

if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) {

return;

}

/*

* If error interrupt is asserted, raise error flag, reset the

* hardware to recover from the error, and return with no further

* processing.

*/

if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {

Error = 1;

/* Reset could fail and hang

* NEED a way to handle this or do not call it??

*/

XAxiDma_Reset(AxiDmaInst);

TimeOut = RESET_TIMEOUT_COUNTER;

while (TimeOut) {

if(XAxiDma_ResetIsDone(AxiDmaInst)) {

break;

}

TimeOut -= 1;

}

return;

}

/*

* If completion interrupt is asserted, then set RxDone flag

*/

if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) {

RxDone = 1;

}

}

5.4、中断使能函数
XScuGic_Enable(IntcInstancePtr, TxIntrId);

XScuGic_Enable(IntcInstancePtr, RxIntrId);

该函数就是两句,

Mask = 0x00000001U

/*

* Enable the selected interrupt source by setting the

* corresponding bit in the Enable Set register.

*/

XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_ENABLE_SET_OFFSET +

((Int_Id / 32U) * 4U), Mask);

先根据中断号识别使能该中断的寄存器位置,在使能该中断在该寄存器上对应的位。

6、Timer_Setup_Intr_System(&Intc,&Timer,29u);
6.1、定时器中断建立
参数1:通用中断实例结构

参数2:定时器实例结构

参数3:定时器中断号

步骤一、在Gic中根据中断号注册定时器中断,将中断处理函数储存进入中断向量处理表。

步骤二、在Gic中使能定时器中断。

步骤三、在定时器控制器中设置允许中断

7、 DMA_Intr_Enable(&Intc,&AxiDma);
7.1 DMA中断使能

审核编辑:何安

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • dma
    dma
    +关注

    关注

    3

    文章

    576

    浏览量

    103727
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    串口DMA发送失败的原因?怎么解决?

    我想使用DMA发送,但是出现了发送不出去,但是发送完成回调函数它是能进去的,打印出里面的内容,接收数据是没问题,这是为什么呢?有大佬指点一下
    发表于 08-15 06:21

    FPGA利用DMA IP核实现ADC数据采集

    本文介绍如何利用FPGA和DMA技术处理来自AD9280和AD9708 ADC的数据。首先,探讨了这两种ADC的特点及其与FPGA的接口兼容性。接着,详细说明了使用Xilinx VIVADO环境下
    的头像 发表于 07-29 14:12 ?2476次阅读

    NVMe IP高速传输却不依赖XDMA设计之五:DMA 控制单元设计

    DMA 控制单元负责控制 DMA 传输事务, 该单元承担了 DMA 事务 NVMe 事务的转换任务, 使用户对数据传输事务的控制更加简单快
    的头像 发表于 07-02 19:47 ?1671次阅读
    NVMe IP高速传输却不依赖XDMA设计之五:<b class='flag-5'>DMA</b> 控制单元设计

    如何使用EXIT0来触发DMA实现SPI发送数据

    请问一下,我想使用EXIT0来触发DMA实现SPI发送数据。我现在使用PB0作为EXIT0的触发源,我把PB0配置为外部中断模式,DMAMUX同步模式使能,选择EXIT0作为同步信号源,这种情况下
    发表于 04-23 07:31

    一文详解AXI DMA技术

    ,SG)功能还可以将数据移动任务从位于于处理器系统中的中央处理器(CPU)中卸载出来。可以通过一个AXI4-Lite从接口访问初始化、状态和管理寄存器。如图4. 8展现了DMA IP的功能构成核心。
    的头像 发表于 04-03 09:32 ?1219次阅读
    一文详解<b class='flag-5'>AXI</b> <b class='flag-5'>DMA</b>技术

    stm32 DMA串口接收到数组,数组元素顺序错乱怎么解决?

    配置DMA循环模式,使用HAL_UART_Receive_DMA(&huart1,buffer,4)函数将串口数据循环发送到4个元素的buffer数组内,上位机20ms
    发表于 03-12 08:02

    HAL库SPI DMA批量传输数据量最大为2^16,有没有办法改成上限为2^32?

    HAL库SPI DMA批量传输数据量最大为2^16,有没有办法改成上限为2^32
    发表于 03-07 13:02

    CKS32F107xx系列的DMA控制器简介

    直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。两个
    的头像 发表于 02-18 17:24 ?979次阅读
    CKS32F107xx系列的<b class='flag-5'>DMA</b>控制器简介

    如何使用DMA进行USART不定长度接收

    在上一讲中,我们对USART进行了简单介绍,并讲解了如何在不使用DMA的情况下进行不定长度数据接收,本讲将着重讲解如何使用DMA进行USART不定长度接收。
    的头像 发表于 02-18 17:01 ?1012次阅读
    如何使用<b class='flag-5'>DMA</b>进行USART不定长度接收

    ZYNQ基础---AXI DMA使用

    前言 在ZYNQ中进行PL-PS数据交互的时候,经常会使用到DMA,其实在前面的ZYNQ学习当中,也有学习过DMA的使用,那就是通过使用自定义的IP,完成HP接口向内存写入和读取数据
    的头像 发表于 01-06 11:13 ?2671次阅读
    ZYNQ基础---<b class='flag-5'>AXI</b> <b class='flag-5'>DMA</b>使用

    EE-116:SHARC简词DMA

    电子发烧友网站提供《EE-116:SHARC简词DMA.pdf》资料免费下载
    发表于 01-05 09:56 ?0次下载
    EE-116:SHARC简词<b class='flag-5'>DMA</b>

    AT32F407在USART2 DMA发送数据时,接包接到了要发送数据,程序还是处于等待传输完成的标识判断中,为什么?

    型号AT32F407,在USART2DMA发送数据时,接包已经接到了要发送数据,但是程序还是处于等待传输完成的标识判断中,卡死了。请教一下
    发表于 12-19 06:48

    雅特力AT32F402/F405 DMA使用指南

    DMA简介DMA控制器的作用不仅在增强系统性能并减少处理器的中断生成,而且还针对32位MCU应用程序专门优化设计。DMA控制器为存储器存储器,存储器到外设和外设到存储器的传输提供了7
    的头像 发表于 11-20 01:03 ?1096次阅读
    雅特力AT32F402/F405 <b class='flag-5'>DMA</b>使用指南

    DMA是什么?详细介绍

    DMA(Direct Memory Access)是一种允许某些硬件子系统直接访问系统内存的技术,而无需中央处理单元(CPU)的介入。这种技术可以显著提高数据传输速率,减轻CPU的负担,并提高整体
    的头像 发表于 11-11 10:49 ?2w次阅读

    用于ADC的DMA乒乓

    电子发烧友网站提供《用于ADC的DMA乒乓.pdf》资料免费下载
    发表于 09-07 11:27 ?1次下载
    用于ADC的<b class='flag-5'>DMA</b>乒乓