DMA buffer to Tx UART on K10DN512

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

DMA buffer to Tx UART on K10DN512

2,265 Views
gerrieheath
Contributor I

I am using a K10DN512VLQ10 chip in the older Kinetis Design Studio V3.2.0. I am not using any libraries and the drivers are self developed. 

I want to start using the DMA controller to transmit variable length messages over UART2. I have tried everything and cannot get it to work. It is either a case of only the first cycle of the minor loop is execute and stops there, or all data is dumped immediately to the UART thereby overrunning it. 

Only the first character of the buffer is seen on the UART. The DMA done bit is set.

To test I have written this code. The transfer is software triggered and transmits 8 bytes from a 'str' buffer (type char str[]). Only 1 major loop and no linkage.  

UART2_BASE_PTR->C2 = 0;


// Enable clock for DMAMUX and DMA
SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;

//disable request channels
DMA0->ERQ = 0u;
DMA0->EEI = 0u;
DMA0->SEEI = 0u;

// Clear pending errors and/or the done bit
DMA0->ES = 0u;

//set source addr
DMA0->TCD[0].SADDR = (__IO uint32_t)str;
DMA0->TCD[0].NBYTES_MLNO = 8;
DMA0->TCD[0].ATTR = DMA_ATTR_SSIZE(0) | DMA_ATTR_DSIZE(0); //8-bit transfer
DMA0->TCD[0].DADDR = (__IO uint32_t)&UART2_BASE_PTR->D;
DMA0->TCD[0].CSR = DMA_CSR_BWC(3) | DMA_CSR_DREQ_MASK

// Adjustment value used to restore the source and destiny address to the initial value
DMA0->TCD[0].SLAST = 0;//(-1 * size_of_tx); // Source address adjustment
DMA0->TCD[0].DLAST_SGA = 0;//(-1); // Destination address adjustment
// Set an offset for source and destination address
DMA0->TCD[0].SOFF = 0x00; // Source address offset
DMA0->TCD[0].DOFF = 0x00; // Destination address

// Current major iteration count (a single iteration of 'size_of_tx' bytes)
DMA0->TCD[0].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(1);
DMA0->TCD[0].BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(1);

UART_C1_REG(m_uart) = UART_C1_UARTSWAI_MASK | UART_C1_ILT_MASK;

UART_PFIFO_REG(m_uart) = 0u;
UART_TWFIFO_REG(m_uart) = 0u;

SetSpeed(baud);   //sets baud

UART2_BASE_PTR->C2 = UART_C2_TIE_MASK;
UART2_BASE_PTR->C5 = UART_C5_TDMAS_MASK;

SetIrqStatus(irq, priority);
m_configured = true;
uint8_t temp_val = UART2_BASE_PTR->S1;
UART2_BASE_PTR->C2 |= (UART_C2_TE_MASK | UART_C2_RE_MASK);


DMA0->CERR = DMA_CERR_CAEI_MASK;
DMA0->CERQ = DMA_CERQ_CAER_MASK;

// Enable request signal for channel 0
DMAMUX->CHCFG[0] = DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(7);    //UART2 TX


DMA0->ERQ = 1;
DMA0->TCD[0].CSR |= DMA_CSR_START_MASK;

//wait for DMA to complete

while(!(DMA0->TCD[0].CSR & DMA_CSR_DONE_MASK)); //DMA_CSR_DREQ_MASK

Labels (1)
0 Kudos
Reply
7 Replies

1,963 Views
mjbcswitzerland
Specialist V

Hi

You can use the open source uTasker project as reference for UART (it supports Rx and Tx DMA on all parts - LPUARTs, UART with eDMA or the simpler DMA in KL parts, for example, on all UART instances). It allows the UART, its DMA and interrupt operation to be accurately simulated in Visual Studio to analyse the internal operation and then adjust your solution accordingly.

Some ideas/notes:

1. Enable Tx DMA by setting
UART_C5_TDMAS in UARTx_C5

2. DMA_TCD_SOFF will normally be 1 when transmitting from a buffer to the output

3. DMA_TCD_NBYTES_ML should be 1 (and not 8) to transfer a single byte on each trigger

4. DMA_TCD_CITER_ELINK and DMA_TCD_BITER_ELINK should be 8 to transfer 8 bytes, one on each trigger

5. Don't use the SW start bit to enable the DMA transfer since this is controlled by the Tx interrupt flag in the correct mode

6. Generally a DMA interrupt is used to signal when the buffer transmission has completed. In the meantime SW can queue further data to be sent that can then be started in the driver so that the user can add data whenever required and it will be sent continuously.

7. If using low power modes that can change dynamically such switching should be disabled until complete UART transmission has terminated (plus waiting for the final end of transmission interrupt after the final byte transfer) in order to avoid premature transmission freeze.

The uTasker project includes a complete solution (industrially proven in many Kinetis based products since 2011) so can be used to avoid needing to redevelop the wheel or its suported version is available for mission critical requirements. It can also be used inside FreeRTOS with undefined UART reception lengths for very high speed, loss-free DMA based reception. The code and project is compatible with KDS, MCUXpresso, CW, IAR, Keil, Rowley, CooCox, Atollic, GreenHills, Visual Studio, GCC makefile.

Regards

Mark

Open Source Version: https://github.com/uTasker/uTasker-Kinetis

Complete Kinetis solutions for professionals, training and support: http://www.utasker.com/kinetis.html
Kinetis K60/K10:
- http://www.utasker.com/kinetis/TWR-K60N512.html
- http://www.utasker.com/kinetis/TWR-K60D100M.html
- http://www.utasker.com/kinetis/TWR-K60F120M.html
- http://www.utasker.com/kinetis/ELZET80_NET-KBED.html
- http://www.utasker.com/kinetis/ELZET80_NET-K60.html

UART: http://www.utasker.com/docs/uTasker/uTaskerUART.PDF
UART videos:
- https://www.youtube.com/watch?v=89sZ4nW-mgw&list=PLWKlVb_MqDQFZAulrUywU30v869JBYi9Q&index=2
- https://www.youtube.com/watch?v=dNZvvouiqis&list=PLWKlVb_MqDQFZAulrUywU30v869JBYi9Q&index=10
- https://www.youtube.com/watch?v=GaoWE-tMRq4&list=PLWKlVb_MqDQFZAulrUywU30v869JBYi9Q&index=11

0 Kudos
Reply

1,963 Views
radomir_kozub
Contributor I

Hello, 

in such configuration described above, the I got interrupt after 8 bytes are transfered to UART tx buffer, but DMA continues to feed UART TX buffer.  How to ensure that DMA stops feeding UART tx without software intervention.

Thanks

0 Kudos
Reply

1,963 Views
mjbcswitzerland
Specialist V

Hi

DMAx_TCD_BITER_ELINK and DMAx_TCD_CITER_ELINK must be set to the number of bytes to be sent.
Then
DMAx_TCD_CSR |= DMA_TCD_CSR_DREQ;
is required so that the DMA activity stops after the number of characters has been sent, otherwise it will keep repeating.

Regards

Mark
[uTasker project developer for Kinetis and i.MX RT]

0 Kudos
Reply

1,963 Views
prashantdev
Contributor III

Hi Mark,

I am also trying to send 8 bytes of data with uart0. As soon as i write below line in configuration my 8 byte data is sent.

DMAMUX0_CHCFG(channel) = DMAMUX_CHCFG_ENBL_MASK;

I don't know what is triggering the dma transfer. But I wanna know how should I initiate another transfer.

0 Kudos
Reply

1,963 Views
radomir_kozub
Contributor I

Hi, my UART "flush" function is this

/***********************************************************************

*

  • Function Name : UDMASendData

  • Description : Sends (transmits) data out through the UART-DMA module

  • with resource control

*

  • resource control - waits till PREVIOUS operation is finished. So once

you call uart66SendBuf

  • and module is not actually sending data, function takes semaphore and

starts UART-DMA sending

  • and function returns immediatelly. Consequent calling will block the

task (wait for semaphore)

  • till previous message is sent out, or semaphore timeout.

*

***************************************************************************/

uint32_t uart66SendBuf(const uint8_t * txBuff, uint32_t txSize, uint32_t

timeout)

{

portBASE_TYPE semaphoreStat;

if (uart66.txIrqSync == NULL)

{

LOGM66P(6, logmDebug, "M66portuart66SendBuf() semaphore NULL\n");

return kStatus_UART_NullParameter;

}

semaphoreStat = xSemaphoreTake(uart66.txIrqSync, timeout);

if(semaphoreStat == pdFALSE) // timeout

{

LOGM66P(7, logmDebug, "M66portuart66SendBuf() semaphore take

FAIL\n");

return (kStatus_UART_Timeout);

}

/* Update txBuff and txSize. */

DMA0->TCD[TXDMACH].SADDR = (uint32_t)txBuff;

DMA0->TCD[TXDMACH].BITER_ELINKNO = txSize;

DMA0->TCD[TXDMACH].CITER_ELINKNO = txSize;

/* Enable DMA major loop interrupt */

DMA0->TCD[TXDMACH].CSR = DMA_CSR_INTMAJOR_MASK | DMA_CSR_DREQ_MASK;

/* Start DMA channel */

DMA0->SERQ = 1;

LOGM66P(8, logmDebug, "M66portuart 66SendBuf() UART Tx started\n");

return (kStatus_UART_Success);

}

Radomir

po 25. 5. 2020 v 8:36 odesílatel prashantdev <admin@community.nxp.com>

napsal:

NXP Community

<https://community.freescale.com/resources/statics/1000/35400-NXP-Community-Email-banner-600x75.jpg>

Re: DMA buffer to Tx UART on K10DN512

reply from prashantdev

<https://community.nxp.com/people/prashantdev?et=watches.email.thread> in *Kinetis

Microcontrollers* - View the full discussion

<https://community.nxp.com/message/1316554?commentID=1316554&et=watches.email.thread#comment-1316554>

0 Kudos
Reply

1,963 Views
prashantdev
Contributor III

thanx for the help.

0 Kudos
Reply

1,963 Views
radomir_kozub
Contributor I

That works, thank you

0 Kudos
Reply