8 #include "serial_dma.h"
34 uint32_t sar; // offset 0x00, Source Address Register
35 uint32_t dar; // offset 0x04, Destination Address Register
36 uint32_t dsr; // offset 0x08, DMA Status Register / Byte Count Register
37 uint32_t dcr; // offset 0x0C, DMA Control Register
42 uint8_t cfg; // offset 0x00, Channel Configuration register
47 uint32_t pcr; // offset 0x00, Pin Control register
52 uint8_t bdh; // offset 0x00, Baud Rate Register High
53 uint8_t bdl; // offset 0x01, Baud Rate Register Low
54 uint8_t c1; // offset 0x02, Control Register 1
55 uint8_t c2; // offset 0x03, Control Register 2
56 uint8_t s1; // offset 0x04, Status Register 1
57 uint8_t s2; // offset 0x05, Status Register 2
58 uint8_t c3; // offset 0x06, Control Register 3
59 uint8_t d; // offset 0x07, Data Register
65 uint8_t queue[SDMA_NUM][SDMA_LEN];
76 /* DMA Request Sources */
77 static int sdma_req_rx[] = {
78 [SDMA_UART0] SDMA_REQ_U0RX,
79 [SDMA_UART1] SDMA_REQ_U1RX,
80 [SDMA_UART2] SDMA_REQ_U2RX,
82 static int sdma_req_tx[] = {
83 [SDMA_UART0] SDMA_REQ_U0TX,
84 [SDMA_UART1] SDMA_REQ_U1TX,
85 [SDMA_UART2] SDMA_REQ_U2TX,
87 static int sdma_uart[] = {
88 [SDMA_UART0] UART0_BASE,
89 [SDMA_UART1] UART1_BASE,
90 [SDMA_UART2] UART2_BASE,
94 static sdma_t sdma_ports[SDMA_NUM_UART];
97 sdma_t *sdma_open(sdma_uart_t uart, sdma_dma_t tx_chan, sdma_dma_t rx_chan)
99 int rxreq = sdma_req_rx[uart]; (void)rxreq;
100 int txreq = sdma_req_tx[uart]; (void)txreq;
103 sdma_t *port = &sdma_ports[uart];
105 port->uart = (void*)sdma_uart[uart];
106 port->dma_xmt = (void*)&DMA0->DMA[tx_chan];
107 port->dma_rcv = (void*)&DMA0->DMA[rx_chan];
108 port->mux_xmt = (void*)&DMAMUX0->CHCFG[tx_chan];
109 port->mux_rcv = (void*)&DMAMUX0->CHCFG[rx_chan];
112 SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
113 SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
114 SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
115 SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
116 SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;
119 port->dma_xmt->dsr = DMA_DSR_BCR_DONE_MASK;
121 // Configure DMA transfer
122 port->dma_xmt->dar = (uint32_t)&port->uart->d;
123 port->dma_xmt->dcr = DMA_DCR_CS_MASK
127 | DMA_DCR_D_REQ_MASK;
130 port->mux_xmt->cfg = DMAMUX_CHCFG_SOURCE(txreq)
131 | DMAMUX_CHCFG_ENBL_MASK;
133 // Configure UART for DMA Channel 0
136 UART0->C5 |= UART0_C5_TDMAE_MASK;
140 UART1->C2 = UART_C2_TIE_MASK
143 UART1->C4 = UART_C4_TDMAS_MASK;
147 UART2->C2 = UART_C2_TIE_MASK
150 UART2->C4 = UART_C4_TDMAS_MASK;
156 /* Map port to pins - for now, just save for timing */
157 void sdma_pinmap(sdma_t *port, PinName tx, PinName rx)
159 port->pin_xmt = (void*)(PORTA_BASE+tx);
160 port->pin_rcv = (void*)(PORTA_BASE+rx);
163 /* Write binary data out the DMA output queue */
164 void sdma_write(sdma_t *port, void *data, int len)
166 if (port->length[port->index] + len > SDMA_LEN) {
169 int pos = port->length[port->index];
170 void *dst = &port->queue[port->index][pos];
171 memcpy(dst, data, len);
172 port->length[port->index] += len;
176 /* Read binary data from the channel */
177 void sdma_read(sdma_t *port, void *data, int len)
179 for (int i = 0; i < len; i++) {
181 while (!(port->uart->s1 & UART_S1_RDRF_MASK))
182 if (port->uart->s1 & UART_S1_OR_MASK)
183 port->uart->s1 |= UART_S1_OR_MASK;
186 ((uint8_t*)data)[i] = port->uart->d;
190 /* Trigger DMA transmit of the current output queue
191 * and swap buffers so we can write into unused space */
192 void sdma_flush(sdma_t *port, uint64_t *time)
194 if (port->length[port->index] == 0)
197 // Wait for transmit complete
198 while (port->dma_xmt->dsr & DMA_DSR_BCR_BCR_MASK)
202 port->dma_xmt->dsr = DMA_DSR_BCR_DONE_MASK;
204 // Set source address and length
205 port->dma_xmt->sar = (uint32_t)&port->queue[port->index];
206 port->dma_xmt->dsr = DMA_DSR_BCR_BCR(port->length[port->index]);
208 // Enable DMA transmit
209 port->dma_xmt->dcr |= DMA_DCR_ERQ_MASK;
212 port->length[port->index] = 0;
213 port->index = (port->index + 1) % SDMA_NUM;
216 /* Wait for DMA receive complete */
217 void sdma_wait(sdma_t *port, uint64_t *time)
219 int req = (void*)port->pin_rcv > (void*)PORTD ? SDMA_REQ_PTD :
220 (void*)port->pin_rcv > (void*)PORTC ? SDMA_REQ_PTC :
221 (void*)port->pin_rcv > (void*)PORTA ? SDMA_REQ_PTA : 0;
224 port->dma_rcv->dsr = DMA_DSR_BCR_DONE_MASK;
227 port->dma_rcv->dcr = DMA_DCR_SINC_MASK
231 | DMA_DCR_D_REQ_MASK;
234 port->mux_rcv->cfg = DMAMUX_CHCFG_SOURCE(req)
235 | DMAMUX_CHCFG_ENBL_MASK;
237 // Set address and size
238 port->dma_rcv->sar = (uint32_t)&PIT->LTMR64H;
239 port->dma_rcv->dar = (uint32_t)&port->time_rcv;
240 port->dma_rcv->dsr = DMA_DSR_BCR_BCR(sizeof(uint64_t));
242 // Enable DMA transmit
243 port->dma_rcv->dcr |= DMA_DCR_ERQ_MASK;
245 // set pin to generate DMA req
246 port->pin_rcv->pcr = PORT_PCR_ISF_MASK
251 // Wait for transmit complete
252 while ((port->dma_rcv->dsr & DMA_DSR_BCR_BCR_MASK))
256 *time = ((uint64_t)~port->time_rcv[0]) << 32
257 | ((uint64_t)~port->time_rcv[1]) << 0;
259 // pcr:00030302 dsr:41000008
260 printf(" - pcr:%08lx dsr:%08lx time:%08lx:%08lx",
261 port->pin_rcv->pcr, port->dma_rcv->dsr,
262 (uint32_t)(*time >> 32), (uint32_t)*time);
265 /* Write ASCII data to the output queue */
266 void sdma_vprintf(sdma_t *port, const char *fmt, va_list ap)
268 int pos = port->length[port->index];
269 void *dst = &port->queue[port->index][pos];
270 port->length[port->index] +=
271 vsnprintf((char*)dst, SDMA_LEN-pos, fmt, ap);
274 void sdma_printf(sdma_t *port, const char *fmt, ...)
278 sdma_vprintf(port, fmt, ap);