8 #include "serial_dma.h"
\r
12 #define SDMA_LEN 1024
\r
14 /* Port structure */
\r
18 uint32_t sar; // offset 0x00, Source Address Register
\r
19 uint32_t dar; // offset 0x04, Destination Address Register
\r
20 uint32_t dsr; // offset 0x08, DMA Status Register / Byte Count Register
\r
21 uint32_t dcr; // offset 0x0C, DMA Control Register
\r
26 uint8_t cfg; // offset 0x00, Channel Configuration register
\r
29 /* Data buffering */
\r
31 int length[SDMA_NUM];
\r
32 uint8_t queue[SDMA_NUM][SDMA_LEN];
\r
39 /* DMA Request Sources */
\r
40 static int sdma_req_rx[] = {
\r
45 static int sdma_req_tx[] = {
\r
52 static sdma_t sdma_ports[SDMA_NUM_UART];
\r
55 sdma_t *sdma_open(sdma_uart_t uart, sdma_dma_t dma)
\r
57 int rxreq = sdma_req_rx[uart]; (void)rxreq;
\r
58 int txreq = sdma_req_tx[uart]; (void)txreq;
\r
61 sdma_t *port = &sdma_ports[uart];
\r
63 port->dma = (void*)&DMA0->DMA[dma];
\r
64 port->mux = (void*)&DMAMUX0->CHCFG[dma];
\r
67 SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
\r
68 SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;
\r
71 port->dma->dsr = DMA_DSR_BCR_DONE_MASK;
\r
73 // Configure DMA transfer
\r
74 port->dma->dar = (uint32_t)&UART1->D;
\r
75 port->dma->dcr = DMA_DCR_CS_MASK |
\r
81 // Configure DMA Mux
\r
82 port->mux->cfg = DMAMUX_CHCFG_SOURCE(txreq) |
\r
83 DMAMUX_CHCFG_ENBL_MASK;
\r
85 // Configure UART for DMA Channel 0
\r
88 UART0->C5 |= UART0_C5_TDMAE_MASK;
\r
92 UART1->C2 = UART_C2_TIE_MASK
\r
95 UART1->C4 = UART_C4_TDMAS_MASK;
\r
99 UART2->C2 = UART_C2_TIE_MASK
\r
102 UART2->C4 = UART_C4_TDMAS_MASK;
\r
108 /* Write binary data out the DMA output queue */
\r
109 void sdma_write(sdma_t *port, void *data, int len)
\r
111 if (port->length[port->index] + len > SDMA_LEN) {
\r
114 int pos = port->length[port->index];
\r
115 void *dst = &port->queue[port->index][pos];
\r
116 memcpy(dst, data, len);
\r
117 port->length[port->index] += len;
\r
121 /* Write ASCII data to the output queue */
\r
122 void sdma_vprintf(sdma_t *port, const char *fmt, va_list ap)
\r
124 int pos = port->length[port->index];
\r
125 void *dst = &port->queue[port->index][pos];
\r
126 port->length[port->index] +=
\r
127 vsnprintf((char*)dst, SDMA_LEN-pos, fmt, ap);
\r
130 void sdma_printf(sdma_t *port, const char *fmt, ...)
\r
134 sdma_vprintf(port, fmt, ap);
\r
138 /* Trigger DMA transmit of the current output queue
\r
139 * and swap buffers so we can write into unused space */
\r
140 void sdma_flush(sdma_t *port)
\r
142 if (port->length[port->index] == 0)
\r
145 // Wait for transmit complete
\r
146 while (port->dma->dsr & DMA_DSR_BCR_BCR_MASK)
\r
150 port->dma->dsr = DMA_DSR_BCR_DONE_MASK;
\r
152 // Set source address and length
\r
153 port->dma->sar = (uint32_t)&port->queue[port->index];
\r
154 port->dma->dsr = DMA_DSR_BCR_BCR(port->length[port->index]);
\r
156 // Enable DMA transmit
\r
157 port->dma->dcr |= DMA_DCR_ERQ_MASK;
\r
160 port->length[port->index] = 0;
\r
161 port->index = (port->index + 1) % SDMA_NUM;
\r