9 #include "serial_irq.h"
22 uint32_t sar; // offset 0x00, Source Address Register
23 uint32_t dar; // offset 0x04, Destination Address Register
24 uint32_t dsr; // offset 0x08, DMA Status Register / Byte Count Register
25 uint32_t dcr; // offset 0x0C, DMA Control Register
30 uint8_t cfg; // offset 0x00, Channel Configuration register
35 uint32_t pcr; // offset 0x00, Pin Control register
47 static tdma_t tdma_ports[TDMA_NUM_CHAN];
49 /* Global timer initialization */
52 static int tdma_init_done = 0;
57 SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
58 SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
59 SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
60 SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
61 SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;
64 SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;
70 PIT->CHANNEL[0].LDVAL = 0xFFFFFFFF;
71 PIT->CHANNEL[0].TCTRL = 0;
74 PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;
75 PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK;
78 PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;
79 PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;
86 tdma_t *tdma_open(tdma_chan_t chan, int alt, PinName pin, PinMode mode)
88 int req = pin >= PTD0 ? TDMA_REQ_PTD :
89 pin >= PTC0 ? TDMA_REQ_PTC :
90 pin >= PTA0 ? TDMA_REQ_PTA : 0;
92 int irqc = mode == PullDown ? 1 : 2;
94 // Initialize global registers
98 tdma_t *port = &tdma_ports[chan];
100 // Setup port pointers
101 port->dma = (void*)&DMA0->DMA[chan];
102 port->mux = (void*)&DMAMUX0->CHCFG[chan];
103 port->pin = (void*)(PORTA_BASE + pin);
106 port->dma->dsr = DMA_DSR_BCR_DONE_MASK;
108 // Configure DMA channel
109 port->dma->dcr = DMA_DCR_SINC_MASK // Source increment
110 | DMA_DCR_DINC_MASK // Dest increment
111 | DMA_DCR_SSIZE(0) // 32-bit access
112 | DMA_DCR_DSIZE(0) // 32-bit access
113 | DMA_DCR_D_REQ_MASK; // Only run once
115 // Setup and enable DMA MUX
116 port->mux->cfg = DMAMUX_CHCFG_SOURCE(req) // Request source
117 | DMAMUX_CHCFG_ENBL_MASK; // Enable DMA mux
119 // Set pin to generate DMA req
120 port->pin->pcr = PORT_PCR_ISF_MASK // Clear ISR flag
121 | PORT_PCR_MUX(alt) // Pin mapping
122 | PORT_PCR_IRQC(irqc) // DMA on falling edge
123 | mode; // Pin pull up/down
125 // Save IRC for later
132 void tdma_start(tdma_t *port)
137 //sirq_printf("isfr2: %08x\r\n", PORTD->ISFR);
139 // Clear previous time
144 port->mux->cfg &= DMAMUX_CHCFG_ENBL_MASK;
146 // Freeze DMA channel
147 port->dma->dcr &= ~DMA_DCR_ERQ_MASK;
150 port->dma->dsr = DMA_DSR_BCR_DONE_MASK;
152 // Set addresses and size
153 port->dma->sar = (uint32_t)&PIT->LTMR64H; // Global timer
154 port->dma->dar = (uint32_t)&port->time; // Temp timer buffer
155 port->dma->dsr = DMA_DSR_BCR_BCR(8); // 64-bit timer
157 // Set pin to generate DMA req
158 port->pin->pcr |= PORT_PCR_ISF_MASK;
159 port->pin->pcr |= PORT_PCR_IRQC(port->irqc);
161 // Enable port request
162 port->dma->dcr |= DMA_DCR_ERQ_MASK;
165 port->mux->cfg = DMAMUX_CHCFG_SOURCE(port->req)
166 | DMAMUX_CHCFG_ENBL_MASK;
168 //sirq_printf("isfr3: %08x\r\n", PORTD->ISFR);
171 void tdma_stop(tdma_t *port, int wait)
176 //sirq_printf("isfr0: %08x\r\n", PORTD->ISFR);
178 for (int i = 0; port->dma->dsr & DMA_DSR_BCR_BCR_MASK; i++)
183 port->mux->cfg &= DMAMUX_CHCFG_ENBL_MASK;
185 // Freeze DMA channel
186 port->dma->dcr &= ~DMA_DCR_ERQ_MASK;
189 port->dma->dsr = DMA_DSR_BCR_DONE_MASK;
191 // Disable pin DMA request
192 port->pin->pcr &= ~PORT_PCR_IRQC_MASK;
193 port->pin->pcr |= PORT_PCR_ISF_MASK;
195 //sirq_printf("isfr1: %08x\r\n", PORTD->ISFR);
198 int tdma_stamp(tdma_t *port, uint64_t *time)
205 if (port->dma->dsr & DMA_DSR_BCR_BCR_MASK)
208 // Read the timestamp
209 clocks = ((uint64_t)~port->time[0]) << 32
210 | ((uint64_t)~port->time[1]) << 0;
212 // Convert to nanoseconds
213 *time = clocks * 1000 / 24;
218 uint64_t tdma_time(void)
220 uint32_t tmh = PIT->LTMR64H;
221 uint32_t tml = PIT->LTMR64L;
223 // Read the timestamp
224 uint64_t clocks = ((uint64_t)~tmh) << 32
225 | ((uint64_t)~tml) << 0;
227 // Convert to nanoseconds
228 return clocks * 125 / 3;
231 void tdma_debug(tdma_t *port)
233 int dsr = port->dma->dsr;
234 int dcr = port->dma->dcr;
236 printf("dsr: %s %s %s %s %s %s %d\r\n",
237 dsr & DMA_DSR_BCR_CE_MASK ? "CE" : "ce",
238 dsr & DMA_DSR_BCR_BES_MASK ? "BSE" : "bse",
239 dsr & DMA_DSR_BCR_BED_MASK ? "BED" : "bed",
240 dsr & DMA_DSR_BCR_REQ_MASK ? "REQ" : "req",
241 dsr & DMA_DSR_BCR_BSY_MASK ? "BSY" : "bsy",
242 dsr & DMA_DSR_BCR_DONE_MASK ? "DONE" : "done",
243 dsr & DMA_DSR_BCR_BCR_MASK);
245 printf("dcr: %s %s %s %s %s %s %s %s ssize=%d:%d mod=%d:%d link=%d:%d:%d\r\n",
246 dcr & DMA_DCR_EINT_MASK ? "EINT" : "eint",
247 dcr & DMA_DCR_ERQ_MASK ? "ERQ" : "erq",
248 dcr & DMA_DCR_CS_MASK ? "CS" : "cs",
249 dcr & DMA_DCR_AA_MASK ? "AA" : "aa",
250 dcr & DMA_DCR_EADREQ_MASK ? "EADRREQ" : "eadrreq",
251 dcr & DMA_DCR_SINC_MASK ? "SINC" : "sinc",
252 dcr & DMA_DCR_DINC_MASK ? "DINC" : "dinc",
253 dcr & DMA_DCR_D_REQ_MASK ? "DREQ" : "dreq",
254 (dcr & DMA_DCR_SSIZE_MASK ) >> DMA_DCR_SSIZE_SHIFT,
255 (dcr & DMA_DCR_DSIZE_MASK ) >> DMA_DCR_DSIZE_SHIFT,
256 (dcr & DMA_DCR_SMOD_MASK ) >> DMA_DCR_SMOD_SHIFT,
257 (dcr & DMA_DCR_DMOD_MASK ) >> DMA_DCR_DMOD_SHIFT,
258 (dcr & DMA_DCR_LINKCC_MASK) >> DMA_DCR_LINKCC_SHIFT,
259 (dcr & DMA_DCR_LCH1_MASK ) >> DMA_DCR_LCH1_SHIFT,
260 (dcr & DMA_DCR_LCH2_MASK ) >> DMA_DCR_LCH2_SHIFT);