Hello again,
DMA chaining does not look to work at all with SCI TX, simple one shot DMA works without problems. I would like send data from ring buffer to avoid unncessary data copying & wasting space for TX slots and the data should be also sent as a continuous stream so first sending the end of buffer -- waiting for BTC interrupt and then continuing from beginning of the buffer is not an option.
I am out of ideas, except making separate transmit buffer where the whole data is copied and use basic one shot DMA, is this the only option???
According to techical manual the other DMA channel should be started after all frames are sent. In my understanding you have to map SCI TX DMA requests to both of the DMA channels but only start the first one manually with HW trigger (if for some reason both channels would be active at same time, both would try to put data to SCI TX which of course won't work).
Questions (see register status in the end):
- why DMA_CH1 is pending even it has sent all bytes?
- why DMA_CH2 is not triggered (no bytes to console) even though SCI driver is ready and CH2 is pending
PEND register has quite interesting text:
"The pending bit is automatically cleared for the following conditions:
• At the end of a frame or a block transfer depending on how the channel is triggered as programmed in the TTYPE bit field of CHCTRL"
- Does this really mean that you can sent to peripheral only 1 byte after the chaining (well, where is even that byte then?), because you cannot use block type transfer to peripheral and I also assume that you cannot simultaneously active more than 1 channel to TX.
I have also tried various other methods/configurations to trigger these 2 channels but no luck, and this method (see code below) looks to be rational and correct one.
Below is an example which shows that basic TX works, but if trying to chain, the previously worked channel does not work any more. Same results is received if code from the interrupt is moved to vSciDmaStartSending(), it prints only "wrap".
#define DMA_CH_SCI_TX DMA_CH2
#define DMA_CH_SCI_TX_CHAINING DMA_CH1
INIT:
{
g_dmaCTRL tSciTxCTRLPKT;
/* Enable DMA */
dmaEnable();
/* Enable Interrupt after sending all data */
dmaEnableInterrupt(DMA_CH_SCI_TX, BTC);
/* Assigning dma requests for SCI, Refer Data sheet - Default DMA Request Map section */
dmaReqAssign( DMA_CH_SCI_TX,29U ); /* SCI2/LIN TX */
dmaReqAssign( DMA_CH_SCI_TX_CHAINING,29U ); /* SCI2/LIN TX */
/* Populate dma control packets structure for TX */
tSciTxCTRLPKT.CHCTRL = 0; /* channel control */
tSciTxCTRLPKT.ELCNT = 1; /* element count */
tSciTxCTRLPKT.ELDOFFSET = 0; /* element destination offset */
tSciTxCTRLPKT.ELSOFFSET = 0; /* element source offset */
tSciTxCTRLPKT.FRDOFFSET = 0; /* frame destination offset */
tSciTxCTRLPKT.FRSOFFSET = 0; /* frame source offset */
tSciTxCTRLPKT.PORTASGN = 4; /* port b */
tSciTxCTRLPKT.RDSIZE = ACCESS_8_BIT; /* read size */
tSciTxCTRLPKT.WRSIZE = ACCESS_8_BIT; /* write size */
tSciTxCTRLPKT.TTYPE = FRAME_TRANSFER; /* transfer type */
tSciTxCTRLPKT.ADDMODERD = ADDR_INC1; /* address mode read */
tSciTxCTRLPKT.ADDMODEWR = ADDR_FIXED; /* address mode write */
tSciTxCTRLPKT.AUTOINIT = AUTOINIT_OFF; /* autoinit */
tSciTxCTRLPKT.DADD = (uint32)(&(scilinREG->TD));
/* Following items needs to be set when transferring */
tSciTxCTRLPKT.SADD = 0U; /* source address */
tSciTxCTRLPKT.FRCNT = 0U; /* frame count */
/* setting dma control packet for TX */
dmaSetCtrlPacket(DMA_CH_SCI_TX, tSciTxCTRLPKT); /* Now basic settings are ready */
tSciTxCTRLPKT.CHCTRL = DMA_CH_SCI_TX + 1U; /* Triggers this channel (ring buffer usage) */
dmaSetCtrlPacket(DMA_CH_SCI_TX_CHAINING, tSciTxCTRLPKT); /* Now basic settings are ready */
dmaSetPriority( DMA_CH_SCI_TX, HIGHPRIORITY ); /* default is LOW PRIORITY */
dmaSetPriority( DMA_CH_SCI_TX_CHAINING, HIGHPRIORITY ); /* default is LOW PRIORITY */
char* pszString = "Hello testing!\r\n";
vSciDmaStartSending((uint8*)pszString, strlen(pszString) );
}
USAGE:
static void vSciDmaStartSending( uint8* pu8Buffer, uint16 u16Len )
{
/* Updated required dma control packet information for TX */
dmaRAMREG->PCP[DMA_CH_SCI_TX].ISADDR = (uint32)pu8Buffer; /* source address */
dmaRAMREG->PCP[DMA_CH_SCI_TX].ITCOUNT = SET_LOWORD_U32(dmaRAMREG->PCP[DMA_CH_SCI_TX].ITCOUNT) |
SET_HIWORD_U32( u16Len ); /* frame count */
dmaSetChEnable(DMA_CH_SCI_TX, DMA_HW); /* Enable DMA channel */
}
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 )
{
char* pszString = "Wrap";
char* pszString2 = "End!\r\n";
/* Updated required dma control packet information for TX */
dmaRAMREG->PCP[DMA_CH_SCI_TX_CHAINING].ISADDR = (uint32)pszString; /* source address */
dmaRAMREG->PCP[DMA_CH_SCI_TX_CHAINING].ITCOUNT = SET_LOWORD_U32(dmaRAMREG->PCP[DMA_CH_SCI_TX].ITCOUNT) |
SET_HIWORD_U32( strlen(pszString) ); /* frame count */
/* Updated required dma control packet information for TX */
dmaRAMREG->PCP[DMA_CH_SCI_TX].ISADDR = (uint32)pszString2; /* source address */
dmaRAMREG->PCP[DMA_CH_SCI_TX].ITCOUNT = SET_LOWORD_U32(dmaRAMREG->PCP[DMA_CH_SCI_TX].ITCOUNT) |
SET_HIWORD_U32( strlen(pszString2) ); /* frame count */
dmaSetChEnable(DMA_CH_SCI_TX_CHAINING, DMA_HW); /* Enable DMA channel - starts other channel after this is ready */
//dmaREG->HWCHENAS = DMA_CH_SCI_TX_CHAINING | DMA_CH_SCI_TX;
}
}
}
RECEIVED OUTPUT:
Hello testing!<CR><LF>
Wrap
Register content after pausing the program execution when no more characters comes out:
Dma_GlbCtrl
00010300
Lin1_SetInt (TX_DMA bit request is active (I have set also rx bits elsewhere)
00070000
Lin1_Flr (TX RDY & TX EMPTY bits active)
00000900
Dma_ChnPnd (CH1 & CH2 is pending (why1 CH1), it has sent everything ("wrap")
00000006 00000505
from 0xFFF80000 (why CCS studio memory browser does not show these as a "registers"?:
00000000 00000000 00000000
00000000 00000000 00000000
00000000 00000000 0000B2B4
FFF7E438 00040001 00000000 //length IFTCOUNT is ok "wrap"
00030008 00000000 00000000 // chain to 3-1=2 channel
00000000 0000B2BC FFF7E438 //length IFTCOUNT is ok "End!\r\n"
00060001 00000000 00000008
00000000 00000000 00000000
00000000 00000000 00000000
00000000 00000000 00000000
00000000 00000000 00000000
00000000 00000000 00000000
00000000 00000000 00000000
from =0xFFF80800: all zeroes
I have also tried by activating both channels (which must be wrong, because then peripheral makes request to both)
- disabled chaining
/* setting dma control packet for TX */
dmaSetCtrlPacket(DMA_CH_SCI_TX, tSciTxCTRLPKT); /* Now basic settings are ready */
//tSciTxCTRLPKT.CHCTRL = DMA_CH_SCI_TX + 1U; /* Triggers this channel (ring buffer usage) */
dmaSetCtrlPacket(DMA_CH_SCI_TX_CHAINING, tSciTxCTRLPKT); /* Now basic settings are ready */
- replaced single channel start by starting them both
dmaREG->HWCHENAS = BIT_n(DMA_CH_SCI_TX_CHAINING) | BIT_n(DMA_CH_SCI_TX);
//dmaSetChEnable(DMA_CH_SCI_TX_CHAINING, DMA_HW); /* Enable DMA channel - starts other channel after this is ready */
This results to print which is expected as now both channels tries to put data simultaneously to TX and this also does not leave any PEND bits actifve as expected
Wnd!<CR><LF>