Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

AURIX™ Forum Discussions

User22621
Level 1
Level 1
First solution authored First reply posted First question asked
hi,
I am using ASCLIN module for standard ASC communication with DMA transmission. But now I met some problems.
My DMA initialization code as following:
void Dma_Init(void)
{
pDmaChn_t pDmaChn = NULL;
/********************TX***********************/
/* Create module configuration */
IfxDma_Dma_initModuleConfig(&rs_uartDma.dmaMod.dmaCfg, &MODULE_DMA);

/* Initialize module */
IfxDma_Dma_initModule(&rs_uartDma.dmaMod.dmaHdl, &rs_uartDma.dmaMod.dmaCfg);

/* Initial configuration for the channel */
pDmaChn = &rs_uartDma.dmaChns[DMA_CHN_UART0_TX];
IfxDma_Dma_initChannelConfig(&pDmaChn->dmaChnCfg, &rs_uartDma.dmaMod.dmaHdl);

pDmaChn->dmaChnCfg.transferCount = 16u; /* Number of transfers per transaction */
pDmaChn->dmaChnCfg.requestMode = IfxDma_ChannelRequestMode_completeTransactionPerRequest; /* Complete a full transaction on request*/
pDmaChn->dmaChnCfg.moveSize = IfxDma_ChannelMoveSize_8bit; /* Size of the data to be moved*/
pDmaChn->dmaChnCfg.operationMode = IfxDma_ChannelOperationMode_continuous; /* DMA channel stays enabled after one request*/
pDmaChn->dmaChnCfg.hardwareRequestEnabled = TRUE; /* DMA as Interrupt Service Provider */

/* Source and destination addresses */
pDmaChn->dmaChnCfg.sourceCircularBufferEnabled = FALSE; /* Enable the source circular buffering */
pDmaChn->dmaChnCfg.sourceAddressCircularRange = IfxDma_ChannelIncrementCircular_none; /* Source address remains the same after transfer*/
pDmaChn->dmaChnCfg.destinationCircularBufferEnabled = TRUE; /* Enable the destination circular buffering*/
pDmaChn->dmaChnCfg.destinationAddressCircularRange = IfxDma_ChannelIncrementCircular_none;/* Destination address remains the same after transfer*/

/* Interrupt generated after transactions */
pDmaChn->dmaChnCfg.channelInterruptEnabled = TRUE; /* Enable the interrupt generation */
pDmaChn->dmaChnCfg.channelInterruptControl = IfxDma_ChannelInterruptControl_thresholdLimitMatch; /* DMA triggers an interrupt once the full transaction is done */
pDmaChn->dmaChnCfg.channelInterruptTypeOfService = IfxSrc_Tos_cpu0; /* CPU0 is the Interrupt Service Provider of this interrupt */
pDmaChn->dmaChnCfg.channelInterruptPriority = UART0_TX_DMA_ISR_PRIO; /* Assign a priority to the interrupt */

/* Channel specific configurations */
pDmaChn->dmaChnCfg.channelId = (IfxDma_ChannelId) UART0_TX_DMA_CHN; /* Select the Channel 1 */

pDmaChn->dmaOpStatus = DmaCh_Op_stop; /* Mark the DMA channel as stop status. */

/* Initialize the DMA channel */
IfxDma_Dma_initChannel(&pDmaChn->dmaChn, &pDmaChn->dmaChnCfg);
}

Init function just copy the example and do some modification.
My ASCLIN module 0 TX ISR source code :
void dmaUart0TxISR(void)
{
uint16 startPos = 0U;
uint16 txLen = 0;
uint8 hwFifoFilLvl = 0u;
uint8 sendEnable = 0u;
uint16 remainingBytes = 0u;
pDmaChn_t pDmaChn = &rs_uartDma.dmaChns[DMA_CHN_UART0_TX];

/* Get and clear the DMA channel interrupt state */
if(TRUE != IfxDma_getAndClearChannelInterrupt(rs_uartDma.dmaMod.dmaHdl.dma, (IfxDma_ChannelId)UART0_TX_DMA_CHN))
{
TEST_LINE;
}

/* Check the ASCLIN module transmission finish */
if(rs_uartRuntime[0u].uartHdl.asclin->FLAGS.B.TC)
{
rs_uartRuntime[0u].uartHdl.asclin->FLAGSCLEAR.B.TCC = 1;
sendEnable = 1u;
}
else if(DmaCh_Op_stop == pDmaChn->dmaOpStatus)
{
sendEnable = 2u;
}
else
{

}
remainingBytes = Ifx_Fifo_getFifoCount(rs_uartRuntime[0u].uartHdl.tx); //get TX fifo counter

if((remainingBytes > 0u) && (0u != sendEnable))
{
if(TRUE == IfxAsclin_Asc_initiateTxParam(&rs_uartRuntime[0u].uartHdl, &startPos, &txLen))
{
hwFifoFilLvl = (16u - IfxAsclin_getTxFifoFillLevel(rs_uartRuntime[0].uartHdl.asclin));
if(hwFifoFilLvl > 0u) /* If ASCLIN channel FIFO has space, then start the next DMA transaction */
{
pDmaChn->dmaChnCfg.sourceAddress = (uint32)&((uint8*)rs_uartRuntime[0u].uartHdl.tx->buffer)[startPos];
pDmaChn->dmaChnCfg.destinationAddress = (uint32)&rs_uartRuntime[0u].uartHdl.asclin->TXDATA.U;
txLen = (hwFifoFilLvl < txLen) ? hwFifoFilLvl : txLen;
pDmaChn->dmaChnCfg.transferCount = txLen;
pDmaChn->dmaOpStatus = DmaCh_Op_start;

IfxDma_Dma_initChannel(&pDmaChn->dmaChn, &pDmaChn->dmaChnCfg);
IfxDma_Dma_startChannelTransaction(&pDmaChn->dmaChn);
}
}
}
else
{
if(remainingBytes == 0u)
{
IfxDma_disableChannelTransaction(rs_uartDma.dmaMod.dmaHdl.dma, rs_uartDma.dmaChns[DMA_CHN_UART0_TX].dmaChn.channelId);
pDmaChn->dmaOpStatus = DmaCh_Op_stop;
}
}
}


Every time when the ASCLIN send function is called, software will put the send data into software TxFIFO and set the corresponding DMA channel interrupt flag and trigger a interrupt, all the data transmission is processed in DMA interrupt service routine.
But with source code above, the receiver gets only 17 bytes even my txFIFO has 32 bytes.

My question is:
1. What's the relationship between DMA interrupt and ASCLIN channel Tx interrupt?
2. During the DMA ISR, I got TxFifoOverflow error and the data cannot be send completely. Why is this happen?


For my understanding about ASCLIN DMA transmission interrupt, it means "specified number of bytes have been transmitted complete". But DMA transfer complete does not mean all the data in ASCLIN FIFO has been send out complete.
Then what and how should I do to avoid the ASCLIN TxFifoOverflow error and get the success of data transmission?

Thanks~
0 Likes
0 Replies