TI中文支持网
TI专业的中文技术问题搜集分享网站

关于tm4c123gh6pm的dma的ping-pong模式的疑问。

我想用dma将数据直接发送到GPIO上。但在执行以下代码是出了点问题。两次pingpong后。无法进入中断。dma通道失能。

#include <stdint.h>
#include <stdbool.h>

#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"

#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/udma.h"

#define uDMADSTADDRESSS GPIO_PORTF_BASE

// Error counter
static uint32_t DMAErrCount = 0;
static uint32_t BadISR=0;
// Transfer counters
static uint32_t  PingCount = 0;
static uint32_t  PongCount = 0;

// uDMA control table aligned to 1024-byte boundary
#pragma  DATA_ALIGN(ucControlTable, 1024)
uint8_t ucControlTable[1024];

// Library error routine
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

#define MEM_BUFFER_SIZE         2
static uint8_t SinPingBuf[MEM_BUFFER_SIZE]={0XFF,0XFF};
static uint8_t SinPongBuf[MEM_BUFFER_SIZE]={0XFF,0XFF};

void uDMAInit()
{    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    ROM_IntEnable(INT_UDMAERR);
    ROM_uDMAEnable();
    ROM_uDMAControlBaseSet(ucControlTable);
      ROM_IntEnable(INT_UDMA);
         ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_SW,
                                    UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT |
                                    UDMA_ATTR_HIGH_PRIORITY |
                                    UDMA_ATTR_REQMASK);
         ROM_uDMAChannelControlSet(UDMA_CHANNEL_SW | UDMA_PRI_SELECT,
                              UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE |
                               UDMA_ARB_1024);
         ROM_uDMAChannelControlSet(UDMA_CHANNEL_SW | UDMA_ALT_SELECT,
                              UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE |
                              UDMA_ARB_1024);
        ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SW | UDMA_PRI_SELECT,
                               UDMA_MODE_PINGPONG,
                                SinPingBuf,
                            (void *)( uDMADSTADDRESSS+GPIO_O_DATA),sizeof(SinPingBuf));

   ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SW | UDMA_ALT_SELECT,
                               UDMA_MODE_PINGPONG,
                               SinPongBuf,
                            (void *)( uDMADSTADDRESSS+GPIO_O_DATA),sizeof(SinPongBuf));
         ROM_uDMAChannelEnable(UDMA_CHANNEL_SW);   }

// uDMA error handler

void uDMAErrorHandler(void)
{
    uint32_t ui32Status;

    ui32Status = ROM_uDMAErrorStatusGet();

    if(ui32Status)
    {
        ROM_uDMAErrorStatusClear();
        DMAErrCount++;
    }
                 }

void uDMAIntHandler(void)
{
    uint32_t ui32Mode;
    // Check for the primary control structure to indicate complete.
    ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_SW| UDMA_PRI_SELECT);
    if(ui32Mode == UDMA_MODE_STOP)
    {
        // Increment the count of completed transfers.
          PingCount++;
        // Configure it for another transfer.
       ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SW | UDMA_PRI_SELECT,
                               UDMA_MODE_PINGPONG,
                                SinPingBuf,
                           (void *)( uDMADSTADDRESSS+GPIO_O_DATA),sizeof(SinPingBuf));
        // Initiate another transfer.
        ROM_uDMAChannelEnable(UDMA_CHANNEL_SW);
    }      ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_SW| UDMA_ALT_SELECT);        if(ui32Mode == UDMA_MODE_STOP)
    {
        // Increment the count of completed transfers.
          PongCount++;

        // Configure it for another transfer.
       ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SW | UDMA_PRI_SELECT,
                               UDMA_MODE_PINGPONG,
                                SinPingBuf,
                           (void *)( uDMADSTADDRESSS+GPIO_O_DATA),sizeof(SinPongBuf));
        // Initiate another transfer.
      ROM_uDMAChannelEnable(UDMA_CHANNEL_SW);
    }
                    else
    {
        BadISR++;
    }           
    if(!ROM_uDMAChannelIsEnabled(UDMA_CHANNEL_SW))
    {

        ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART1TX | UDMA_PRI_SELECT,
                                   UDMA_MODE_BASIC,SinPingBuf,
                                   (void *)( uDMADSTADDRESSS+GPIO_O_DATA),
                                   sizeof(SinPingBuf));

          ROM_uDMAChannelEnable(UDMA_CHANNEL_SW);         
    }               
}

int main()
{
     SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
    uDMAInit();
     while(1){
    ROM_uDMAChannelRequest(UDMA_CHANNEL_SW);
     ROM_SysCtlDelay(SysCtlClockGet()/300);
    }
       }
   同时还有以下疑问。

1.dma的单次请求和猝发请求是怎样识别的。数据手册上似乎没有说过有只响应单次请求模式。

2.ping-pong模式的地址自增是ping、pong各算各的。还是一起算。如果用ping-pong共同传输一个数组应该怎样配置dma

liangmao Jiang:

回复 step by step:

谢谢您。我还想问一个问题。请问一次猝发所发送的数据的数据个数应该在哪个库函数中配置?

Wellin Zhang:

回复 liangmao Jiang:

Liangmao

使用uDMAChannelTransferSet进行配置

Sets the transfer parameters for a uDMA channel control structure.

uDMAChannelTransferSet(uint32_t ui32ChannelStructIndex,uint32_t ui32Mode,void *pvSrcAddr,void *pvDstAddr,uint32_t ui32TransferSize)

最后一个参数为传输的item的个数,注意并不是Bytes数。因为Item的size可以设置为Bytes,half word,和Word。

具体各个参数的额含义,请参考Dirverlib use guide

赞(0)
未经允许不得转载:TI中文支持网 » 关于tm4c123gh6pm的dma的ping-pong模式的疑问。
分享到: 更多 (0)