8 #include "timer_dma.h"
\r
9 #include "serial_irq.h"
\r
18 /* Port structure */
\r
22 uint32_t sar; // offset 0x00, Source Address Register
\r
23 uint32_t dar; // offset 0x04, Destination Address Register
\r
24 uint32_t dsr; // offset 0x08, DMA Status Register / Byte Count Register
\r
25 uint32_t dcr; // offset 0x0C, DMA Control Register
\r
30 uint8_t cfg; // offset 0x00, Channel Configuration register
\r
35 uint32_t pcr; // offset 0x00, Pin Control register
\r
47 static tdma_t tdma_ports[TDMA_NUM_CHAN];
\r
49 /* Global timer initialization */
\r
50 void tdma_init(void)
\r
53 SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
\r
54 SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
\r
55 SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
\r
56 SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
\r
57 SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;
\r
59 // Enable timer Clock
\r
60 SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;
\r
66 PIT->CHANNEL[0].LDVAL = 0xFFFFFFFF;
\r
67 PIT->CHANNEL[0].TCTRL = 0;
\r
70 PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;
\r
71 PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK;
\r
74 PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;
\r
75 PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;
\r
79 tdma_t *tdma_open(tdma_chan_t chan, int alt, PinName pin, PinMode mode)
\r
81 int req = pin >= PTD0 ? TDMA_REQ_PTD :
\r
82 pin >= PTC0 ? TDMA_REQ_PTC :
\r
83 pin >= PTA0 ? TDMA_REQ_PTA : 0;
\r
85 int irqc = mode == PullUp ? 1 : 2;
\r
88 tdma_t *port = &tdma_ports[chan];
\r
90 // Setup port pointers
\r
91 port->dma = (void*)&DMA0->DMA[chan];
\r
92 port->mux = (void*)&DMAMUX0->CHCFG[chan];
\r
93 port->pin = (void*)(PORTA_BASE + pin);
\r
95 // Reset DMA channel
\r
96 port->dma->dsr = DMA_DSR_BCR_DONE_MASK;
\r
98 // Configure DMA channel
\r
99 port->dma->dcr = DMA_DCR_SINC_MASK // Source increment
\r
100 | DMA_DCR_DINC_MASK // Dest increment
\r
101 | DMA_DCR_SSIZE(0) // 32-bit access
\r
102 | DMA_DCR_DSIZE(0) // 32-bit access
\r
103 | DMA_DCR_D_REQ_MASK; // Only run once
\r
105 // Setup and enable DMA MUX
\r
106 port->mux->cfg = DMAMUX_CHCFG_SOURCE(req) // Request source
\r
107 | DMAMUX_CHCFG_ENBL_MASK; // Enable DMA mux
\r
109 // Set pin to generate DMA req
\r
110 port->pin->pcr = PORT_PCR_ISF_MASK // Clear ISR flag
\r
111 | PORT_PCR_MUX(alt) // Pin mapping
\r
112 | PORT_PCR_IRQC(irqc) // DMA on falling edge
\r
113 | mode; // Pin pull up/down
\r
115 // Save IRC for later
\r
122 void tdma_start(tdma_t *port)
\r
127 //sirq_printf("isfr2: %08x\r\n", PORTD->ISFR);
\r
129 // Clear previous time
\r
134 port->mux->cfg &= DMAMUX_CHCFG_ENBL_MASK;
\r
136 // Freeze DMA channel
\r
137 port->dma->dcr &= ~DMA_DCR_ERQ_MASK;
\r
139 // Reset DMA channel
\r
140 port->dma->dsr = DMA_DSR_BCR_DONE_MASK;
\r
142 // Set addresses and size
\r
143 port->dma->sar = (uint32_t)&PIT->LTMR64H; // Global timer
\r
144 port->dma->dar = (uint32_t)&port->time; // Temp timer buffer
\r
145 port->dma->dsr = DMA_DSR_BCR_BCR(8); // 64-bit timer
\r
147 // Set pin to generate DMA req
\r
148 port->pin->pcr |= PORT_PCR_ISF_MASK;
\r
149 port->pin->pcr |= PORT_PCR_IRQC(port->irqc);
\r
151 // Enable port request
\r
152 port->dma->dcr |= DMA_DCR_ERQ_MASK;
\r
155 port->mux->cfg = DMAMUX_CHCFG_SOURCE(port->req)
\r
156 | DMAMUX_CHCFG_ENBL_MASK;
\r
158 //sirq_printf("isfr3: %08x\r\n", PORTD->ISFR);
\r
161 void tdma_stop(tdma_t *port, int wait)
\r
166 //sirq_printf("isfr0: %08x\r\n", PORTD->ISFR);
\r
168 for (int i = 0; port->dma->dsr & DMA_DSR_BCR_BCR_MASK; i++)
\r
173 port->mux->cfg &= DMAMUX_CHCFG_ENBL_MASK;
\r
175 // Freeze DMA channel
\r
176 port->dma->dcr &= ~DMA_DCR_ERQ_MASK;
\r
178 // Reset DMA channel
\r
179 port->dma->dsr = DMA_DSR_BCR_DONE_MASK;
\r
181 // Disable pin DMA request
\r
182 port->pin->pcr &= ~PORT_PCR_IRQC_MASK;
\r
183 port->pin->pcr |= PORT_PCR_ISF_MASK;
\r
185 //sirq_printf("isfr1: %08x\r\n", PORTD->ISFR);
\r
188 int tdma_stamp(tdma_t *port, uint64_t *time)
\r
195 if (port->dma->dsr & DMA_DSR_BCR_BCR_MASK)
\r
198 // Read the timestamp
\r
199 clocks = ((uint64_t)~port->time[0]) << 32
\r
200 | ((uint64_t)~port->time[1]) << 0;
\r
202 // Convert to nanoseconds
\r
203 *time = clocks * 1000 / 24;
\r
208 uint64_t tdma_time(void)
\r
210 uint32_t tmh = PIT->LTMR64H;
\r
211 uint32_t tml = PIT->LTMR64L;
\r
213 // Read the timestamp
\r
214 uint64_t clocks = ((uint64_t)~tmh) << 32
\r
215 | ((uint64_t)~tml) << 0;
\r
217 // Convert to nanoseconds
\r
218 return clocks * 1000 / 24;
\r
221 void tdma_debug(tdma_t *port)
\r
223 int dsr = port->dma->dsr;
\r
224 int dcr = port->dma->dcr;
\r
226 printf("dsr: %s %s %s %s %s %s %d\r\n",
\r
227 dsr & DMA_DSR_BCR_CE_MASK ? "CE" : "ce",
\r
228 dsr & DMA_DSR_BCR_BES_MASK ? "BSE" : "bse",
\r
229 dsr & DMA_DSR_BCR_BED_MASK ? "BED" : "bed",
\r
230 dsr & DMA_DSR_BCR_REQ_MASK ? "REQ" : "req",
\r
231 dsr & DMA_DSR_BCR_BSY_MASK ? "BSY" : "bsy",
\r
232 dsr & DMA_DSR_BCR_DONE_MASK ? "DONE" : "done",
\r
233 dsr & DMA_DSR_BCR_BCR_MASK);
\r
235 printf("dcr: %s %s %s %s %s %s %s %s ssize=%d:%d mod=%d:%d link=%d:%d:%d\r\n",
\r
236 dcr & DMA_DCR_EINT_MASK ? "EINT" : "eint",
\r
237 dcr & DMA_DCR_ERQ_MASK ? "ERQ" : "erq",
\r
238 dcr & DMA_DCR_CS_MASK ? "CS" : "cs",
\r
239 dcr & DMA_DCR_AA_MASK ? "AA" : "aa",
\r
240 dcr & DMA_DCR_EADREQ_MASK ? "EADRREQ" : "eadrreq",
\r
241 dcr & DMA_DCR_SINC_MASK ? "SINC" : "sinc",
\r
242 dcr & DMA_DCR_DINC_MASK ? "DINC" : "dinc",
\r
243 dcr & DMA_DCR_D_REQ_MASK ? "DREQ" : "dreq",
\r
244 (dcr & DMA_DCR_SSIZE_MASK ) >> DMA_DCR_SSIZE_SHIFT,
\r
245 (dcr & DMA_DCR_DSIZE_MASK ) >> DMA_DCR_DSIZE_SHIFT,
\r
246 (dcr & DMA_DCR_SMOD_MASK ) >> DMA_DCR_SMOD_SHIFT,
\r
247 (dcr & DMA_DCR_DMOD_MASK ) >> DMA_DCR_DMOD_SHIFT,
\r
248 (dcr & DMA_DCR_LINKCC_MASK) >> DMA_DCR_LINKCC_SHIFT,
\r
249 (dcr & DMA_DCR_LCH1_MASK ) >> DMA_DCR_LCH1_SHIFT,
\r
250 (dcr & DMA_DCR_LCH2_MASK ) >> DMA_DCR_LCH2_SHIFT);
\r