Hello,
I have simple DMA SCI setup where SCI RX side is running as a continous "ring buffer" and TX side is sending data also with DMA. In RX side I am using inside actual application the CTCOUNT-register to determine how many bytes have been received from SCI. This works fine if I trigger a new TX when previous TX is ended (results RX & TX DMA channel switching and thus updating RX channel status registers???).
void dmaGroupANotification(dmaInterrupt_t inttype, uint32 channel)
/* Remarks: ISR: this function is called by HALCoGen code */
{
if( inttype == BTC )
{
if( channel == DMA_CH_SCI_TX )
{
/* Disable SCI TX DMA Interrupt to stop DMA requests, is this really needed because DMA channel should be "dead" */
scilinREG->CLEARINT = SCI_SET_TX_DMA;
bDmaBusy = FALSE;
char* pszString = "Hello!\r\n";
DMA_vSend( (uint8*)pszString, strlen(pszString) );
}
}
}
How ever if I comment out that DMA_vSend() line, also my application stops receiving SCI RX data (CTCOUNT stays in value 0 all the time, also the CFTCOUNT field), if I look the buffer where DMA transfers the data, the data from SCI goes there, so the problem is that status information is _never_ updated. So the problem is that if you have only 1 DMA channel in use, the CTCOUNT register (and CFTCOUNT) does not update at all???
According to technical reference manual, CFTCOUNT does not have any restriction for update but for some reason CETCOUNT-field says that whole CTCOUNT register is not updated
CFTCOUNT: "Current frame transfer count. Returned the current remaining frame counts"
vs
CETCOUNT: "Current element transfer count. These bits return the current remaining element counts. CTCOUNT register is only updated after a channel is arbitrated out of the priority queue."
Really? Is the only option to implement a reliable ring reader (or actually to get any status information from DMA channel) to establish a dummy sw-triggered (with autoinit) DMA channel which for example copies a byte from dummy location to another just to get "primary" channel(s) out of arbitration queue to update its status if you do not have constantly at least 2 DMA channels running?
Here is my SCI RX side definition
#define DMA_CH_SCI_RX DMA_CH0
#define DMA_CH_SCI_TX DMA_CH1
#define DMA_CH_DUMMY_UPDATER DMA_CH15
/* Populate dma control packets structure for RX */
tSciRxCTRLPKT.CHCTRL = 0; /* channel control */
tSciRxCTRLPKT.ELCNT = 1; /* element count */
tSciRxCTRLPKT.ELDOFFSET = 0; /* element destination offset */
tSciRxCTRLPKT.ELSOFFSET = 0; /* element source offset */
tSciRxCTRLPKT.FRDOFFSET = 0; /* frame destination offset */
tSciRxCTRLPKT.FRSOFFSET = 0; /* frame source offset */
tSciRxCTRLPKT.PORTASGN = 4; /* port b */
tSciRxCTRLPKT.RDSIZE = ACCESS_8_BIT; /* read size */
tSciRxCTRLPKT.WRSIZE = ACCESS_8_BIT; /* write size */
tSciRxCTRLPKT.TTYPE = FRAME_TRANSFER; /* transfer type */
tSciRxCTRLPKT.ADDMODERD = ADDR_FIXED; /* address mode read */
tSciRxCTRLPKT.ADDMODEWR = ADDR_INC1; /* address mode write */
tSciRxCTRLPKT.AUTOINIT = AUTOINIT_ON; /* autoinit */
tSciRxCTRLPKT.RDSIZE = ACCESS_8_BIT; /* read size */
tSciRxCTRLPKT.WRSIZE = ACCESS_8_BIT; /* write size */
tSciRxCTRLPKT.SADD = (uint32)(&(scilinREG->RD)); /* source address */
tSciRxCTRLPKT.DADD = (uint32)&au8SciRxBuffer[0]; /* destination address */
tSciRxCTRLPKT.FRCNT = ELEMENTS(au8SciRxBuffer); /* frame count */
/* Setting whole dma control packet for RX */
dmaSetCtrlPacket(DMA_CH_SCI_RX, tSciRxCTRLPKT);
dmaSetPriority( DMA_CH_SCI_RX, HIGHPRIORITY ); /* default is LOW PRIORITY */
dmaSetChEnable(DMA_CH_SCI_RX, DMA_HW); /* Enable DMA channel */
And then I use same structure (to minize the need to config same things again) to start the dummy channel
/* Make dummy channel so SCI_RX status info will be updated if no other DMA transmissions are active */
tSciRxCTRLPKT.ADDMODERD = ADDR_FIXED; /* address mode read */
tSciRxCTRLPKT.ADDMODEWR = ADDR_FIXED; /* address mode write */
tSciRxCTRLPKT.TTYPE = BLOCK_TRANSFER; /* transfer type */
tSciRxCTRLPKT.SADD = (uint32)&au8DmaDummyUpdater[0]; /* source address */
tSciRxCTRLPKT.DADD = (uint32)&au8DmaDummyUpdater[1]; /* destination address */
tSciRxCTRLPKT.FRCNT = 1; /* frame count */
dmaSetCtrlPacket(DMA_CH_DUMMY_UPDATER, tSciRxCTRLPKT);
dmaSetChEnable(DMA_CH_DUMMY_UPDATER, DMA_SW); /* Enable DMA channel */
So looks like that at least technical reference manual has a bug in CFTCOUNT description?