打印
[CC3200]

CC3200 µDMA 应用

[复制链接]
1017|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
概述
µDMA 控制器是一个灵活和高度可配置的 DMA 控制器,它具有微处理器 Cortex-M4 处理
器核心设计的工作效率。它支持多个数据大小和地址增量计划, 多个 DMA 通道的优先级别,
和几个允许复杂的编程数据传输模式。  

使用特权

评论回复
评论
dirtwillfly 2019-7-31 21:03 回复TA
感谢分享 

相关帖子

沙发
gaoke231|  楼主 | 2019-7-31 20:28 | 只看该作者
基本模式:
在基本模式, 只要提出传输请求,有更多的项目要传输, µDMA 控制器就执行传输。 每当
外围设备准备数据传输, 这种模式用来外设断言 µDMA 请求信号。

使用特权

评论回复
板凳
gaoke231|  楼主 | 2019-7-31 20:29 | 只看该作者
自动模式:
自动模式类似于基本模式,除了一旦收到传输请求时, 即使 µDMA 请求删除,也要将传输
运行完成。这种模式适用于软件触发传输。一般来说,自动模式不用在外围设备。

使用特权

评论回复
地板
gaoke231|  楼主 | 2019-7-31 20:35 | 只看该作者
乒乓模式:
乒乓模式是用于支持发送连续数据流给外设或从外设传出连续数据流。使用乒乓球模式,
主要的和备用的数据结构必须实现。结构都是由处理器建立, 用于内存和外围设备的数
据传输。传输开始时使用主控制结构, 当传输使用的主要控制结构完成,µDMA 控制器读
取该通道的备用控制结构继续传输,每次这种情况发生的时候,产生一个中断,并且处理
器为刚完成的传输重新加载控制结构。

使用特权

评论回复
5
gaoke231|  楼主 | 2019-7-31 20:37 | 只看该作者
分散收集模式:
散集模式是一个复杂模式, 当数据被转移到内存中或者在内存的不同位置传输才会被用
到, 不是一组连续的内存缓冲区地址。

使用特权

评论回复
6
gaoke231|  楼主 | 2019-7-31 20:37 | 只看该作者
应用说明
这个应用程序的目的是展示不同的 DMA 传输方式。 演示了使用 uDMA 控制器在内存缓冲
区传输数据,用自动模式和散集模式,使用乒乓模式传输数据到 UART。在自动模式和散集
模式下,一旦数据传输完成,数据传输的正确性就要被验证,在乒乓模式下,传输速率被计
算并且显示。

使用特权

评论回复
7
gaoke231|  楼主 | 2019-7-31 20:39 | 只看该作者
设置一个串行通信程序(超级终端/ TeraTerm)。终端设置如下:

使用特权

评论回复
8
gaoke231|  楼主 | 2019-7-31 20:42 | 只看该作者
运行参考程序(Flashing the bin/IAR/CCS)。观察终端上的状态信息理解应用程序执行的顺序。 运行结果如下图所示:

使用特权

评论回复
9
gaoke231|  楼主 | 2019-7-31 20:45 | 只看该作者
static unsigned long g_ulSrcBuf[MEM_BUFFER_SIZE];
static unsigned long g_ulDstBuf[MEM_BUFFER_SIZE];

// Task List used in Scatter Gather DMA Transfer
static tDMAControlTable TaskList[2];

extern volatile unsigned char iDone;

// The transmit and receive buffers used for the UART transfers.  There is one
// transmit buffer and a pair of recieve ping-pong buffers.
static unsigned char g_ucTxBuf[UART_TXBUF_SIZE];
static unsigned char g_ucRxBufA[UART_RXBUF_SIZE];
static unsigned char g_ucRxBufB[UART_RXBUF_SIZE];

// The count of UART buffers filled, one for each ping-pong buffer.
static unsigned long g_ulRxBufACount = 0;
static unsigned long g_ulRxBufBCount = 0;

// The number of seconds elapsed since the start of the program.  This value is
// maintained by the SysTick interrupt handler.
static unsigned long g_ulSeconds = 0;
static unsigned long g_ulTxCount = 0;

unsigned long ulBytesTransferred[100];
unsigned int uiCount=0;
volatile int Done=0;
int UARTDone=0;

使用特权

评论回复
10
gaoke231|  楼主 | 2019-7-31 20:50 | 只看该作者
#if defined(ewarm)
    extern uVectorEntry __vector_table;
#endif

#if defined(ccs)
    extern void (* const g_pfnVectors[])(void);
#endif

使用特权

评论回复
11
gaoke231|  楼主 | 2019-7-31 20:54 | 只看该作者
unsigned long
StartAndCompleteSWTransfer(unsigned long ulChannel)
{
    unsigned long ulIdx;
    //
    // Clear interrupt status
    //
    MAP_uDMAIntClear(0xffffffff);
    MAP_uDMAChannelRequest(ulChannel);
    //
    // Wait for the mode to change to stopped
    //
    ulIdx = 0;
    while(MAP_uDMAChannelModeGet(ulChannel) != UDMA_MODE_STOP)
    {
        ulIdx++;
        if(ulIdx > 200000)
        {
            break;
        }
    }
    if(MAP_uDMAChannelIsEnabled(ulChannel))
    {
        UART_PRINT("Error, channel was enabled at end of transfer\n");
        return 1;
    }
    UART_PRINT("Transfer complete \n\r");
    return(0);
}

使用特权

评论回复
12
gaoke231|  楼主 | 2019-7-31 20:59 | 只看该作者
void
InitSWTransfer(void)
{
    unsigned int uIdx;

    //
    // Fill the source memory buffer with a simple incrementing pattern.
    //
    for(uIdx = 0; uIdx < MEM_BUFFER_SIZE; uIdx++)
    {
        g_ulSrcBuf[uIdx] = uIdx;
    }

    //
    // Configure the control parameters for the SW channel.  The SW channel
    // will be used to transfer between two memory buffers, 32 bits at a time.
    // Therefore the data size is 32 bits, and the address increment is 32 bits
    // for both source and destination.  The arbitration size will be set to 8,
    // which causes the uDMA controller to rearbitrate after 8 items are
    // transferred.  This keeps this channel from hogging the uDMA controller
    // once the transfer is started, and allows other channels cycles if they
    // are higher priority.
    //

    UDMASetupTransfer(UDMA_CH0_SW, UDMA_MODE_AUTO, MEM_BUFFER_SIZE,
                      UDMA_SIZE_32, UDMA_ARB_8,g_ulSrcBuf, UDMA_SRC_INC_32,
                                            g_ulDstBuf, UDMA_DST_INC_32);

    if(StartAndCompleteSWTransfer(UDMA_CH0_SW))
    {
      UART_PRINT("Memory to Memory Transfer Error \n\r");
    }
    //
    // Verifying the transfered Data
    //
    for(uIdx = 0; uIdx < MEM_BUFFER_SIZE; uIdx++)
    {
      if(uIdx!=g_ulDstBuf[uIdx])
        {
          UART_PRINT("Data transfered in Auto mode is Incorrect at %d th "
                        "location \n\r\n\r",uIdx);
          Done=1;
          return;

        }
    }
    UART_PRINT("Data transfered in Auto mode is verified \n\r\n\r");
    Done=1;

}

使用特权

评论回复
13
gaoke231|  楼主 | 2019-7-31 21:00 | 只看该作者
void
UART0IntHandler(void)
{
    unsigned long ulStatus;
    unsigned long ulMode;
    //
    // Read the interrupt status of the UART.
    //
    ulStatus = MAP_UARTIntStatus(UARTA0_BASE, 1);
    //
    // Clear any pending status, even though there should be none since no UART
    // interrupts were enabled.  
    //
    MAP_UARTIntClear(UARTA0_BASE, ulStatus);
    if(uiCount<6)
    {
    //
    // Check the DMA control table to see if the ping-pong "A" transfer is
    // complete.  The "A" transfer uses receive buffer "A", and the primary
    // control structure.
    //
    ulMode = MAP_uDMAChannelModeGet(UDMA_CH8_UARTA0_RX | UDMA_PRI_SELECT);

    //
    // If the primary control structure indicates stop, that means the "A"
    // receive buffer is done.  The uDMA controller should still be receiving
    // data into the "B" buffer.
    //
    if(ulMode == UDMA_MODE_STOP)
    {
        //
        // Increment a counter to indicate data was received into buffer A.  
        //
        g_ulRxBufACount++;

        //
        // Set up the next transfer for the "A" buffer, using the primary
        // control structure.  When the ongoing receive into the "B" buffer is
        // done, the uDMA controller will switch back to this one.  
        //
        UDMASetupTransfer(UDMA_CH8_UARTA0_RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG,
                          sizeof(g_ucRxBufA),UDMA_SIZE_8, UDMA_ARB_4,
                          (void *)(UARTA0_BASE + UART_O_DR), UDMA_SRC_INC_NONE,
                                            g_ucRxBufA, UDMA_DST_INC_8);
    }

    //
    // Check the DMA control table to see if the ping-pong "B" transfer is
    // complete.  The "B" transfer uses receive buffer "B", and the alternate
    // control structure.
    //
    ulMode = MAP_uDMAChannelModeGet(UDMA_CH8_UARTA0_RX | UDMA_ALT_SELECT);

    //
    // If the alternate control structure indicates stop, that means the "B"
    // receive buffer is done.  The uDMA controller should still be receiving
    // data into the "A" buffer.
    //
    if(ulMode == UDMA_MODE_STOP)
    {
        //
        // Increment a counter to indicate data was received into buffer A.
        //
        g_ulRxBufBCount++;

        //
        // Set up the next transfer for the "B" buffer, using the alternate
        // control structure.  When the ongoing receive into the "A" buffer is
        // done, the uDMA controller will switch back to this one.
        //
        UDMASetupTransfer(UDMA_CH8_UARTA0_RX | UDMA_ALT_SELECT,
                          UDMA_MODE_PINGPONG, sizeof(g_ucRxBufB),UDMA_SIZE_8,
                          UDMA_ARB_4,(void *)(UARTA0_BASE + UART_O_DR),
                          UDMA_SRC_INC_NONE, g_ucRxBufB, UDMA_DST_INC_8);
    }

    //
    // If the UART0 DMA TX channel is disabled, that means the TX DMA transfer
    // is done.
    //
    if(!MAP_uDMAChannelIsEnabled(UDMA_CH9_UARTA0_TX))
    {
        g_ulTxCount++;
        //
        // Start another DMA transfer to UART0 TX.
        //
        UDMASetupTransfer(UDMA_CH9_UARTA0_TX| UDMA_PRI_SELECT, UDMA_MODE_BASIC,
           sizeof(g_ucTxBuf),UDMA_SIZE_8, UDMA_ARB_4,g_ucTxBuf, UDMA_SRC_INC_8,
                          (void *)(UARTA0_BASE + UART_O_DR), UDMA_DST_INC_NONE);
        //
        // The uDMA TX channel must be re-enabled.
        //
        MAP_uDMAChannelEnable(UDMA_CH9_UARTA0_TX);
    }
    }
    else
    {
        UARTDone=1;
        MAP_UARTIntUnregister(UARTA0_BASE);
    }
}

使用特权

评论回复
14
gaoke231|  楼主 | 2019-7-31 21:00 | 只看该作者
void
InitUART0Transfer(void)
{
    unsigned int uIdx;

    //
    // Fill the TX buffer with a simple data pattern.
    //
    for(uIdx = 0; uIdx < UART_TXBUF_SIZE; uIdx++)
    {
        g_ucTxBuf[uIdx] = 65;
    }
    MAP_PRCMPeripheralReset(PRCM_UARTA0);
    MAP_PRCMPeripheralClkEnable(PRCM_UARTA0,PRCM_RUN_MODE_CLK);

    MAP_UARTConfigSetExpClk(CONSOLE,SYSCLK, UART_BAUD_RATE,
                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                        UART_CONFIG_PAR_NONE));
    MAP_uDMAChannelAssign(UDMA_CH8_UARTA0_RX);
    MAP_uDMAChannelAssign(UDMA_CH9_UARTA0_TX);
    MAP_UARTIntRegister(UARTA0_BASE,UART0IntHandler);
   
    //
    // Set both the TX and RX trigger thresholds to 4.  This will be used by
    // the uDMA controller to signal when more data should be transferred.  The
    // uDMA TX and RX channels will be configured so that it can transfer 4
    // bytes in a burst when the UART is ready to transfer more data.
    //
    MAP_UARTFIFOLevelSet(UARTA0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);

    //
    // Enable the UART for operation, and enable the uDMA interface for both TX
    // and RX channels.
    //
    MAP_UARTEnable(UARTA0_BASE);

    //
    // This register write will set the UART to operate in loopback mode.  Any
    // data sent on the TX output will be received on the RX input.
    //
    HWREG(UARTA0_BASE + UART_O_CTL) |= UART_CTL_LBE;

    //
    // Enable the UART peripheral interrupts. uDMA controller will cause an
    // interrupt on the UART interrupt signal when a uDMA transfer is complete.
    //
   
    MAP_UARTIntEnable(UARTA0_BASE,UART_INT_DMATX);
    MAP_UARTIntEnable(UARTA0_BASE,UART_INT_DMARX);

    //
    // Configure the control parameters for the UART TX.  The uDMA UART TX
    // channel is used to transfer a block of data from a buffer to the UART.
    // The data size is 8 bits.  The source address increment is 8-bit bytes
    // since the data is coming from a buffer.  The destination increment is
    // none since the data is to be written to the UART data register.  The
    // arbitration size is set to 4, which matches the UART TX FIFO trigger
    // threshold.
    //
    UDMASetupTransfer(UDMA_CH8_UARTA0_RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG,
            sizeof(g_ucRxBufA),UDMA_SIZE_8, UDMA_ARB_4,
            (void *)(UARTA0_BASE + UART_O_DR), UDMA_SRC_INC_NONE,
                                            g_ucRxBufA, UDMA_DST_INC_8);

    UDMASetupTransfer(UDMA_CH8_UARTA0_RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG,
            sizeof(g_ucRxBufB),UDMA_SIZE_8, UDMA_ARB_4,
              (void *)(UARTA0_BASE + UART_O_DR), UDMA_SRC_INC_NONE,
                                            g_ucRxBufB, UDMA_DST_INC_8);

    UDMASetupTransfer(UDMA_CH9_UARTA0_TX| UDMA_PRI_SELECT,
               UDMA_MODE_BASIC,sizeof(g_ucTxBuf),UDMA_SIZE_8, UDMA_ARB_4,
               g_ucTxBuf, UDMA_SRC_INC_8,(void *)(UARTA0_BASE + UART_O_DR),
                                                    UDMA_DST_INC_NONE);
   
    MAP_UARTDMAEnable(UARTA0_BASE, UART_DMA_RX | UART_DMA_TX);
}

使用特权

评论回复
15
gaoke231|  楼主 | 2019-7-31 21:03 | 只看该作者
void
DisplayBanner()
{
    UART_PRINT("\n\n\n\r");
    UART_PRINT("\t\t   *******************************************\n\r");
    UART_PRINT("\t\t        CC3200 %s Application        \n\r", APP_NAME);
    UART_PRINT("\t\t   *******************************************\n\r");
    UART_PRINT("\n\n\n\r");

}

使用特权

评论回复
16
gaoke231|  楼主 | 2019-7-31 21:08 | 只看该作者
static void
BoardInit(void)
{
/* In case of TI-RTOS vector table is initialize by OS itself */
#ifndef USE_TIRTOS
  //
  // Set vector table base
  //
#if defined(ccs)
    MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
#endif
#if defined(ewarm)
    MAP_IntVTableBaseSet((unsigned long)&__vector_table);
#endif
#endif
  //
  // Enable Processor
  //
  MAP_IntMasterEnable();
  MAP_IntEnable(FAULT_SYSTICK);

  PRCMCC3200MCUInit();
}

使用特权

评论回复
17
gaoke231|  楼主 | 2019-7-31 21:09 | 只看该作者
void
SysTickHandler(void)
{
    static unsigned long ulTickCount = 0;
   
    //
    // Increment the tick counter.
    //
    ulTickCount++;
   
    //
    // If the number of ticks per second has occurred, then increment the
    // seconds counter.
    //
    if(!(ulTickCount % SYSTICKS_PER_SECOND))
    {
        g_ulSeconds++;
    }

}

使用特权

评论回复
18
gaoke231|  楼主 | 2019-7-31 21:09 | 只看该作者
static void  
SetupSGMemTransfer(unsigned long ulChannel,void *pvSrcBuf0,
                             void *pvSrcBuf1,void *pvDstBuf,unsigned long size)
{
    //
    // Create task0
    //
    tDMAControlTable task0=uDMATaskStructEntry(size, UDMA_SIZE_8,
                            UDMA_SRC_INC_8, pvSrcBuf0,
                             UDMA_DST_INC_8,pvDstBuf,
                            UDMA_ARB_8, UDMA_MODE_MEM_SCATTER_GATHER);

    //
    // create task1
    //
    tDMAControlTable task1=uDMATaskStructEntry(size, UDMA_SIZE_8,
                            UDMA_SRC_INC_8, pvSrcBuf1,
                             UDMA_DST_INC_8, (char *)pvDstBuf+size,
                            UDMA_ARB_8, UDMA_MODE_AUTO);

    //
    // Copy to TaskList
    //
    memcpy(&TaskList[0],&task0,sizeof(tDMAControlTable));
    memcpy(&TaskList[1],&task1,sizeof(tDMAControlTable));
    memset(pvDstBuf,0,size);
    //
    // Setup Scatter Gather with two tasks
    //
    MAP_uDMAChannelScatterGatherSet(ulChannel, 2,TaskList,0);
    MAP_uDMAChannelEnable(ulChannel);
}

使用特权

评论回复
19
gaoke231|  楼主 | 2019-7-31 21:10 | 只看该作者
void
InitSGTransfer()
{
    int i;
    char * pvSrcBuf,*pvDstBuf;
   
    //
    // Source Buffer
    //
    pvSrcBuf=malloc(BUFF_SIZE);
    if(pvSrcBuf == NULL)
    {
        UART_PRINT("Failed to allocate Src buffer\n\r");
        return ;
    }
    for(i=0;i<BUFF_SIZE;i++)
        *(pvSrcBuf+i)=i;

    MAP_uDMAChannelAssign(UDMA_CH0_SW);
    MAP_uDMAChannelAttributeDisable(UDMA_CH0_SW,UDMA_ATTR_ALTSELECT);
    iDone=0;

    pvDstBuf=malloc(BUFF_SIZE);
    if(pvDstBuf == NULL)
    {
        UART_PRINT("Failed to allocate Dst buffer\n\r");
        return ;
    }
   
    //
    // Call to Set Up Scatter Gather Mode Transfer
    //
    SetupSGMemTransfer(UDMA_CH0_SW,pvSrcBuf,pvSrcBuf+BUFF_SIZE/2,
                       pvDstBuf,BUFF_SIZE/2);
    MAP_uDMAChannelRequest(UDMA_CH0_SW);
   
    //
    // Checking for the Completion
    //
    while(!iDone);
   
    //
    // Checking Correctness of SG Transfer
    //
    if(memcmp(pvSrcBuf,pvDstBuf,BUFF_SIZE)==0)
        UART_PRINT("SG Mode Memory to Memory Transfer Completed \n\r\n\r");
    else
        UART_PRINT("SG Mode Memory to Memory Transfer Failed! \n\r\n\r");

    free(pvDstBuf);

}

使用特权

评论回复
20
gaoke231|  楼主 | 2019-7-31 21:10 | 只看该作者
void
main()
{
    static unsigned long ulPrevSeconds;
    static unsigned long ulPrevUARTCount = 0;
    unsigned long ulXfersCompleted;
    unsigned long ulBytesAvg=0;
    int iCount=0;
   
        //
    // Initailizing the board
    //
    BoardInit();
    //
    // Muxing for Enabling UART_TX and UART_RX.
    //
    PinMuxConfig();
   
    //
    // Initialising the Terminal.
    //
    InitTerm();
   
    //
    // Display Welcome Message
    //
    DisplayBanner();
   
    //
    // SysTick Enabling
    //
    SysTickIntRegister(SysTickHandler);
    SysTickPeriodSet(SYSTICK_RELOAD_VALUE);
    SysTickEnable();

    //
    // uDMA Initialization
    //
    UDMAInit();
   
    //
    // Register interrupt handler for UART
    //
    MAP_UARTIntRegister(UARTA0_BASE,UART0IntHandler);
   
    UART_PRINT("Completed DMA Initialization \n\r\n\r");
   
    //
    // Auto DMA Transfer
    //
    UART_PRINT("Starting Auto DMA Transfer  \n\r");
    InitSWTransfer();
   
    //
    // Scatter Gather DMA Transfer
    //
    UART_PRINT("Starting Scatter Gather DMA Operation\n\r");
    InitSGTransfer();
    while(!Done){}
    MAP_UtilsDelay(80000000);
   
    //
    // Ping Pong UART Transfer
    //
    InitUART0Transfer();
   
    //
    // Remember the current SysTick seconds count.
    //
    ulPrevSeconds = g_ulSeconds;

    while(1)
    {
        //
        // Check to see if one second has elapsed.  If so, the make some
        // updates.
        //
        if(g_ulSeconds != ulPrevSeconds)
        {

            uiCount++;
   
            //
            // Remember the new seconds count.
            //
            ulPrevSeconds = g_ulSeconds;
            
            //
            // Calculate how many UART transfers have occurred since the last
            // second.
            //
            ulXfersCompleted = (g_ulRxBufACount + g_ulRxBufBCount -
                                ulPrevUARTCount);

            //
            // Remember the new UART transfer count.
            //
            ulPrevUARTCount = g_ulRxBufACount + g_ulRxBufBCount;
            
            //
            // Compute how many bytes were transferred by the UART.
            //
            ulBytesTransferred[iCount] = (ulXfersCompleted * UART_RXBUF_SIZE );
            iCount++;
            
            //
            // Print a message to the display showing the memory transfer rate.
            //
            if(UARTDone)
            {
                MAP_PRCMPeripheralReset(PRCM_UARTA0);
                MAP_PRCMPeripheralClkEnable(PRCM_UARTA0,PRCM_RUN_MODE_CLK);
                UARTConfigSetExpClk(CONSOLE,SYSCLK, UART_BAUD_RATE,
                                    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                                        UART_CONFIG_PAR_NONE));
            }

        }
        
        //
        // See if we have run long enough and exit the loop if so.
        //
        if(g_ulSeconds >= 6 && UARTDone)
        {
            break;
        }
    }
   
    //
    // Compute average Bytes Transfer Rate for the past 5 seconds
    //
    for(iCount=1;iCount<=5;iCount++)
    {
        ulBytesAvg += ulBytesTransferred[iCount];
    }
    ulBytesAvg=ulBytesAvg/5;

    UART_PRINT("\n\r");
    UART_PRINT("\n\r");

    UART_PRINT("\n\rCompleted Ping Pong Transfer from Memory to UART "
                "Peripheral \n\r");
    UART_PRINT(" \n\rTransfer Rate is %lu Bytes/Sec \n\r", ulBytesAvg);
    UART_PRINT("\n\rTest Ended\n\r");
    return ;

}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

54

主题

1310

帖子

5

粉丝