器件型号: TMS570LS3137
SCI UART 接收的 DMA 配置丢失。
我在中断模式下遇到 SCI 接收的时序问题。 由于 SCI 没有任何 FIFO、我想使用 DMA 提高性能并避免数据丢失。
UART 可能会接收具有不同字节长度的消息、我没有找到可以定义传输开始时的一种超时的 DMA 通道设置。
我猜是使用多个链入一个环的 DMA 通道、但它无法按预期工作。
这是我的 DMA 初始化和中断代码:
#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
#define SCI_TX_ADDR ((uint32_t)(&(sciREG->TD)))
#define SCI_RX_ADDR ((uint32_t)(&(sciREG->RD)))
#else
#define SCI_TX_ADDR ((uint32_t)(&(sciREG->TD)) + 3)
#define SCI_RX_ADDR ((uint32_t)(&(sciREG->RD)) + 3)
#endif
#define SCI_SET_TX_DMA (1<<16)
#define SCI_SET_RX_DMA (1<<17)
#define SCI_SET_RX_DMA_ALL (1<<18)
#define SCI_TX_DMA_CH DMA_CH0
#define SCI_RX_DMA_COUNT (4u)
#define SCI_RX_DMA_CH_FIRST (SCI_TX_DMA_CH + 1)
#define SCI_RX_DMA_CH_LAST (SCI_RX_DMA_CH_FIRST + SCI_RX_DMA_COUNT)
#define DMA_LIN_RX (28u)
#define DMA_LIN_TX (29u)
#define DMA_SCI_RX (30u)
#define DMA_SCI_TX (31u)
#define SERIAL_DMA_BUFF_SIZE (UART_MAX_MSG_LEN)
uint8_t serial_Rx_buf[SCI_RX_DMA_COUNT];
g_dmaCTRL g_dmaCTRLPKT_Rx[SCI_RX_DMA_COUNT];
void serial_dma_init(void)
{
int i;
g_dmaCTRL *dmactrl = g_dmaCTRLPKT_Rx;
for(i = 0; i < SCI_RX_DMA_COUNT; ++i, ++dmactrl)
{
dmactrl->SADD = SCI_RX_ADDR; /* source address */
dmactrl->DADD = (uint32)(serial_Rx_buf+i); /* destination address */
dmactrl->CHCTRL = (SCI_RX_DMA_CH_FIRST + ((i + 1) % SCI_RX_DMA_COUNT)) + 1; /* next channel to be triggered */
dmactrl->FRCNT = 1; /* frame count */
dmactrl->ELCNT = 1; /* element count */
dmactrl->ELDOFFSET = 0; /* element destination offset */
dmactrl->ELSOFFSET = 0; /* element destination offset */
dmactrl->FRDOFFSET = 0; /* frame destination offset */
dmactrl->FRSOFFSET = 0; /* frame destination offset */
dmactrl->PORTASGN = 4; /* port b */
dmactrl->RDSIZE = ACCESS_8_BIT; /* read size */
dmactrl->WRSIZE = ACCESS_8_BIT; /* write size */
dmactrl->TTYPE = FRAME_TRANSFER; /* transfer type */
dmactrl->ADDMODERD = ADDR_FIXED; /* address mode read */
dmactrl->ADDMODEWR = ADDR_FIXED; /* address mode write */
dmactrl->AUTOINIT = AUTOINIT_OFF; /* autoinit */
dmaSetCtrlPacket(SCI_RX_DMA_CH_FIRST+i, dmactrl);
dmaEnableInterrupt(SCI_RX_DMA_CH_FIRST+i, BTC);
dmaSetChEnable(SCI_RX_DMA_CH_FIRST+i, DMA_HW);
dmaReqAssign(SCI_RX_DMA_CH_FIRST+i, DMA_SCI_RX);
}
sciREG->SETINT |= SCI_SET_RX_DMA | SCI_SET_RX_DMA_ALL;
dmaEnable();
}
void dmaGroupANotification(dmaInterrupt_t inttype, uint32 channel)
{
static portBASE_TYPE xHigherPriorityTaskWoken;
static uint8_t byte;
xHigherPriorityTaskWoken = pdFALSE;
switch(channel)
{
case SCI_TX_DMA_CH:
xSemaphoreGiveFromISR(uart_tx_sema4, &xHigherPriorityTaskWoken);
break;
case SCI_RX_DMA_CH_FIRST:
case SCI_RX_DMA_CH_FIRST+1:
case SCI_RX_DMA_CH_FIRST+2:
case SCI_RX_DMA_CH_FIRST+3:
byte = serial_Rx_buf[channel-SCI_RX_DMA_CH_FIRST];
xQueueSendFromISR(xRxedChars, &byte, &xHigherPriorityTaskWoken );
dmaSetChEnable(channel, DMA_HW);
break;
}
// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
// switch should be requested. The macro used is port specific and
// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
// refer to the documentation page for the port being used.
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
使用 DMA 进行传输可以正常工作、但无法正常接收。 我始终获得第一个接收字节。
有人能告诉我我出了什么问题吗?
