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

    文章

    561

    浏览量

    100553
收藏 人收藏

    评论

    相关推荐

    DMA是什么?详细介绍

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

    经验分享 | DMA助力实时控制

    直接存储器访问(DMA,DirectMemoryAccess)的优点·提高系统效率:通过绕过CPU,DMA显著减少了数据传输对CPU资源的占用,使得CPU能够专注于其他计算任务,提升了系统整体
    的头像 发表于 07-18 08:18 793次阅读
    经验分享 | <b class='flag-5'>DMA</b>助力实时控制

    做I2S/SPI DMA发送数据的时候,遇到DMA fifo传输错误的原因?

    在做I2S/SPI DMA发送数据的时候,遇到DMA fifo传输错误,不确定是软件问题还是芯片问题,有做出来的兄弟可以给个最简单的工程参考参考吗,先谢谢了。
    发表于 04-30 08:08

    STM32H7使用DMA方式读取SD卡,DMA缓冲是否只能处于AXI SRAM?

    除了512K的 AXI SRAM,还有没有其他的SRAM 区域能访问到? 因为我想这整个512K 的AXI SRAM 做其他用途,变量都定义其它的SRAM 区域。但这样SD卡 DMA
    发表于 04-18 06:00

    STM32CubeMX用FreeRTOS+DMA操纵usart发送数据为什么失败?

    不用用FreeRTOS时,DMA操纵usart可以正常发送数据; 用FreeRTOS,不用DMA直接用usart也可以正常发送
    发表于 04-15 08:16

    STM32 DMA双缓冲发送不定长数据怎么解决?

    STM32 DMA双缓冲发送不定长数据,假如我需要发送100010个数据,开辟了2块1000数据
    发表于 04-11 06:58

    使用F334的USART+DMA进行发送数据遇到的疑问求解

    最近在使用F334的USART+DMA进行发送数据的时候,遇到了一个很奇怪的问题。 在调用HAL_UART_Transmit_DMA(UART_HandleTypeDef *hua
    发表于 04-10 08:08

    STM32F407在HAL库下使用SPI通过DMA发送数据时,如何获取DMA发送计数?

    ●关于STM32F407在HAL库下使用SPI通过DMA发送数据如何获取DMA发送计数,变量名DMA
    发表于 03-26 06:07

    STM32F405 DMA+空闲中断接收,DMA_GetCurrDataCounter(DMA1_Stream1)与实际发送数据不符怎么解决?

    ,且继续发送数据,偶尔会触发中断,但是接收DMA可正常工作,但是DMA_GetCurrDataCounter(DMA1_Stream1)与实
    发表于 03-07 08:28

    STM32F407串口DMA发送卡死在HAL_DMA_GetState怎么解决?

    使用五路串口DMA收发数据,但是在发送的时候,到了while(HAL_DMA_GetState( hdma_usart3_tx) != HAL_DM
    发表于 03-06 08:29

    Xilinx高性能PCIe DMA控制器IP,8个DMA通道

    Scather Gather DMA,提供FIFO/AXI4-Stream用户接口。 基于PCI Express Integrated Block,Multi-Channel PCIe RDMA
    的头像 发表于 02-22 11:11 1439次阅读
    Xilinx高性能PCIe <b class='flag-5'>DMA</b>控制器IP,8个<b class='flag-5'>DMA</b>通道

    什么是DMADMA究竟有多快!

    直接内存访问(Direct Memory Access,DMA):在计算机体系结构中,DMA 是一种数据传输方式,允许外部设备直接访问计算机的内存,而无需通过中央处理单元(CPU)的干预。这有
    的头像 发表于 02-22 10:43 2011次阅读
    什么是<b class='flag-5'>DMA</b>?<b class='flag-5'>DMA</b>究竟有多快!

    何用DMA的方式读写串口数据

    串口接收(或者发送)的数据比较大,如果用中断逐字节从FIFO读数据太耗时了,光盘里的找不到有关DMA读写串口的demo
    发表于 01-17 07:35

    dma和串口直接发送的区别

    DMA(Direct Memory Access)和串口直接发送是两种不同的数据传输方式,它们在实现上有着明显的区别和优劣势。本文将详细介绍DMA和串口直接
    的头像 发表于 01-07 17:43 2879次阅读

    dma和通道技术的区别

    DMA(Direct Memory Access)和通道技术是计算机系统中用来优化数据传输和处理的重要技术。尽管它们都与数据传输相关,但它们在实现方法、特点和应用场景等方面存在一些重要的区别
    的头像 发表于 01-04 14:31 2562次阅读