我想用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