(六)ASCLIN_UART模块串口DMA模式


DMA简介

DMA(Direct Memory Access,直接存储器访问)是一种在不需要CPU干预的情况下,实现外设与存储器之间 或 存储器与存储器之间高速数据传输的技术。DMA的主要目的是减轻CPU的负担,使其能够专注于更复杂的计算和控制任务

简单理解:俩地址之间进行数据搬运,不需要CPU干涉

可以有软件触发DMA进行搬运,也可以硬件触发DMA搬运,取决于配置。

比如:(五)ASCLIN_UART模块串口中断模式 中采用的是借助串口的接收发送中断进行数据传输的。这里可以配置DMA硬件触发,将串口的接收/发送中断,路由到DMA上,每一次触发串口的中断,就触发一次DMA搬运即可。

当然DMA配置很复杂,可以直接借助iLLD库函数进行配置,应用为王。直接分析代码。

采用DMA完成串口收发

mydma.c文件:

#include "IfxAsclin_Asc.h"

#include "IfxDma_Dma.h"
#include "IfxDma.h"

#include "Bsp.h"
#include "string.h"

/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/
#define UART_BAUDRATE           460800                                  /* UART baud rate in bit/s                  */

#define UART_PIN_RX             IfxAsclin2_RXE_P33_8_IN                 /* UART receive port pin                    */
#define UART_PIN_TX             IfxAsclin2_TX_P33_9_OUT                 /* UART transmit port pin                   */

#define DMA_CHANNEL_RX             INTPRIO_ASCLIN2_RX
#define DMA_CHANNEL_TX             INTPRIO_ASCLIN2_TX

IfxDma_Dma_Channel g_rxchn;                                             /* DMA channel handle                       */
IfxDma_Dma_Channel g_txchn;

/* Definition of the interrupt priorities */
#define INTPRIO_ASCLIN2_TX      11                                       /* Triggered when AscLin transmits         */
#define INTPRIO_ASCLIN2_RX      12                                       /* Triggered when AscLin receives          */

#define INTPRIO_DMA_TX          13                          /* Triggered when a DMA transaction is finished         */
#define INTPRIO_DMA_RX          14                          /* Triggered when a DMA transaction is finished         */

#define UART_RX_BUFFER_SIZE     16                                      /* Definition of the receive buffer size    */
#define UART_TX_BUFFER_SIZE     16                                      /* Definition of the transmit buffer size   */


/* Declaration of the ASC handle */
static IfxAsclin_Asc g_ascHandle;

/* Declaration of the FIFOs parameters */
_Alignas(16) static  uint8 g_ascTxBuffer[UART_TX_BUFFER_SIZE];//只要开启了自增+循环,必须保证与循环范围保持一致!!!!!!
_Alignas(16) static  uint8 g_ascRxBuffer[UART_RX_BUFFER_SIZE];

/* Definition of txData  */
_Alignas(16) uint8 g_txData[] = "Hello World!";//只要开启了自增+循环,必须保证与循环范围保持一致!!!!!!

/* Size of the message */
Ifx_UReg_32Bit g_count = sizeof(g_txData)-1;

int rxcnt = 0;
int txcnt = 0;
IFX_INTERRUPT(prio_DMA_RX, 0, INTPRIO_DMA_RX);
void prio_DMA_RX(void)
{
   
    rxcnt++;
    IfxDma_clearChannelInterrupt(&MODULE_DMA, g_rxchn.channelId);
}

/* Interrupt triggered when the DMA finishes a transaction*/
IFX_INTERRUPT(prio_DMA_TX, 0, INTPRIO_DMA_TX);
void prio_DMA_TX(void)
{
   
    txcnt++;
    IfxDma_clearChannelInterrupt(&MODULE_DMA, g_txchn.channelId);
}

/* This function initializes the ASCLIN UART module */
void init_asclin_uart(void)
{
   
    /* Initialize an instance of IfxAsclin_Asc_Config with default values */
    IfxAsclin_Asc_Config ascConfig;
    IfxAsclin_Asc_initModuleConfig(&ascConfig, &MODULE_ASCLIN2);

    /* Set the desired baud rate */
    ascConfig.baudrate.baudrate = UART_BAUDRATE;

    /* ISR priorities and interrupt target */
    ascConfig.interrupt.txPriority = INTPRIO_ASCLIN2_TX;
    ascConfig.interrupt.rxPriority = INTPRIO_ASCLIN2_RX;
    ascConfig.interrupt.typeOfService = IfxSrc_Tos_cpu0 ;

    /* FIFO configuration */  //没用到串口接收/发送的缓存可以不绑定,直接删除即可(如出现问题,可以直接删除)
    ascConfig.txBuffer = &g_ascTxBuffer;
    ascConfig.txBufferSize = UART_TX_BUFFER_SIZE;
    ascConfig.rxBuffer = &g_ascRxBuffer;
    ascConfig.rxBufferSize = UART_RX_BUFFER_SIZE;

    /* Pin configuration */
    const IfxAsclin_Asc_Pins pins =
    {
   
        NULL_PTR,       IfxPort_InputMode_pullUp,     /* CTS pin not used */
        &UART_PIN_RX,   IfxPort_InputMode_pullUp,     /* RX pin           */
        NULL_PTR,       IfxPort_OutputMode_pushPull,  /* RTS pin not used */
        &UART_PIN_TX,   IfxPort_OutputMode_pushPull,  /* TX pin           */
        IfxPort_PadDriver_cmosAutomotiveSpeed1
    };
    ascConfig.pins = &pins;

    IfxAsclin_Asc_initModule(&g_ascHandle, &ascConfig); /* Initialize module with above parameters */

    /* Modification of the TOS for the Rx related interruption */
    /* Change from CPU0 (previously defined above) to DMA */
    volatile Ifx_SRC_SRCR *src;
    src = IfxAsclin_getSrcPointerTx(ascConfig.asclin);

    /* Assign DMA as Service Provider when INTPRIO_ASCLIN2_TX is triggered */
    IfxSrc_init(src, IfxSrc_Tos_dma, INTPRIO_ASCLIN2_TX);
    IfxAsclin_enableTxFifoFillLevelFlag(ascConfig.asclin, TRUE);
    IfxSrc_enable(src);

    /* Modification of the TOS for the Rx related interruption */
    /* Change from CPU0 (previously defined above) to DMA */
    src = IfxAsclin_getSrcPointerRx(ascConfig.asclin);
    /* Assign DMA as Service Provider when INTPRIO_ASCLIN2_RX is triggered */
    IfxSrc_init(src, IfxSrc_Tos_dma, INTPRIO_ASCLIN2_RX);
    IfxAsclin_enableRxFifoFillLevelFlag(ascConfig.asclin, TRUE);
    IfxSrc_enable(src);
}

/* This function is called from main in order to initialize the DMA module */
void init_dma(void)
{
   
    /* Initialize an instance of IfxDma_Dma_Config with default values */
    IfxDma_Dma_Config dmaConfig;
    IfxDma_Dma_initModuleConfig(&dmaConfig, &MODULE_DMA);

    /* Initialize module */
    IfxDma_Dma dma;
    IfxDma_Dma_initModule(&dma, &dmaConfig);

    /* Initial configuration for all channels */
    IfxDma_Dma_ChannelConfig cfg;
    IfxDma_Dma_initChannelConfig(&cfg, &dma);

    /* Following configuration is used by the DMA channel */
    cfg.moveSize = IfxDma_ChannelMoveSize_8bit;
    cfg.blockMode = IfxDma_ChannelMove_1;

    /*********************************************** TX部分**************************************************************/

    cfg.transferCount = 0;//一次触发搬运多少个字节数据(后面写入的时候会修改)
    /* DMA completes a full transaction on requests */
    cfg.requestMode = IfxDma_ChannelRequestMode_oneTransferPerRequest;  //一个请求触发一个单一DMA传输 即请求启动单个事务

    /* DMA as Interrupt Service Provider */
    cfg.hardwareRequestEnabled = TRUE;                         //  使能UART发送中断触发Dma(硬件触发)
    /* DMA channel stays enabled after one request */
    cfg.operationMode = IfxDma_ChannelOperationMode_single;   //DMA单次搬运

    /*************** Source and destination addresses ***************/
    cfg.sourceCircularBufferEnabled = TRUE;                           //开启源地址自增
    cfg.sourceAddressIncrementStep = IfxDma_ChannelIncrementStep_1;  //源地址自增加+1
    cfg.sourceAddressCircularRange = IfxDma_ChannelIncrementCircular_16; //源地址16字节循环

    cfg.destinationCircularBufferEnabled = TRUE;                     //开启目的地址自增
    cfg.destinationAddressCircularRange = IfxDma_ChannelIncrementCircular_none; //目的地址循环范围为0(就是原地不动,即使上面开启了也是在原地踏步)等同于上面FALSE

    /*************** Channel specific configurations ***************/
    /* Select the Channel 11, related to the interruption on AscLin TX */
    cfg.channelId = (IfxDma_ChannelId) DMA_CHANNEL_TX;
    /* Address of the UART TX FIFO */
    cfg.sourceAddress = (uint32)&g_ascTxBuffer;
    cfg.destinationAddress = (uint32) &g_ascHandle.asclin->TXDATA.U;

    /*  DMA中断部分(如果采用环形缓存区,就没必要开启了哈)           */
    cfg.channelInterruptEnabled = TRUE;
    /* DMA triggers an interrupt once the full transaction is done */
    cfg.channelInterruptControl = IfxDma_ChannelInterruptControl_thresholdLimitMatch;
    /* Priority of the channel interrupt trigger */
    cfg.channelInterruptPriority = INTPRIO_DMA_TX;
    /* Interrupt service provider */
    cfg.channelInterruptTypeOfService = IfxSrc_Tos_cpu0;

    IfxDma_Dma_initChannel(&g_txchn, &cfg);


    /********************************************************* RX部分***********************************************************/
    cfg.transferCount = 1;   //一次触发搬运多少个字节数据
    /* DMA completes a full transaction on requests */
    cfg.requestMode = IfxDma_ChannelRequestMode_completeTransactionPerRequest;  //一个请求触发一个完整事务 即请求启动完整的事务

    /* DMA as Interrupt Service Provider */
    cfg.hardwareRequestEnabled = TRUE;                         // UART接收中断触发Dma

    /* DMA channel 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小爪.exe

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

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

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

打赏作者

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

抵扣说明:

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

余额充值