8 #include "timer_dma.h"
\r
17 /* Port structure */
\r
21 uint32_t sar; // offset 0x00, Source Address Register
\r
22 uint32_t dar; // offset 0x04, Destination Address Register
\r
23 uint32_t dsr; // offset 0x08, DMA Status Register / Byte Count Register
\r
24 uint32_t dcr; // offset 0x0C, DMA Control Register
\r
29 uint8_t cfg; // offset 0x00, Channel Configuration register
\r
34 uint32_t pcr; // offset 0x00, Pin Control register
\r
42 static tdma_t tdma_ports[TDMA_NUM_CHAN];
\r
44 /* Global timer initialization */
\r
45 void tdma_init(void)
\r
48 SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
\r
49 SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
\r
50 SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
\r
51 SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
\r
52 SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;
\r
54 // Enable timer Clock
\r
55 SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;
\r
61 PIT->CHANNEL[0].LDVAL = 0xFFFFFFFF;
\r
62 PIT->CHANNEL[0].TCTRL = 0;
\r
65 PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;
\r
66 PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK;
\r
69 PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;
\r
70 PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;
\r
74 tdma_t *tdma_open(tdma_chan_t chan, int alt, PinName pin, PinMode mode)
\r
76 int req = pin >= PTD0 ? TDMA_REQ_PTD :
\r
77 pin >= PTC0 ? TDMA_REQ_PTC :
\r
78 pin >= PTA0 ? TDMA_REQ_PTA : 0;
\r
80 int ircq = mode == PullUp ? 2 : 1;
\r
83 tdma_t *port = &tdma_ports[chan];
\r
85 // Setup port pointers
\r
86 port->dma = (void*)&DMA0->DMA[chan];
\r
87 port->mux = (void*)&DMAMUX0->CHCFG[chan];
\r
88 port->pin = (void*)(PORTA_BASE + pin);
\r
90 // Reset DMA channel
\r
91 port->dma->dsr = DMA_DSR_BCR_DONE_MASK;
\r
93 // Configure DMA channel
\r
94 port->dma->dcr = DMA_DCR_SINC_MASK // Source increment
\r
95 | DMA_DCR_DINC_MASK // Dest increment
\r
96 | DMA_DCR_SSIZE(0) // 32-bit access
\r
97 | DMA_DCR_DSIZE(0) // 32-bit access
\r
98 | DMA_DCR_D_REQ_MASK; // Only run once
\r
100 // Setup and enable DMA MUX
\r
101 port->mux->cfg = DMAMUX_CHCFG_SOURCE(req) // Request source
\r
102 | DMAMUX_CHCFG_ENBL_MASK; // Enable DMA mux
\r
104 // Set pin to generate DMA req
\r
105 port->pin->pcr = PORT_PCR_ISF_MASK // Clear ISR flag
\r
106 | PORT_PCR_MUX(alt) // Pin mapping
\r
107 | PORT_PCR_IRQC(ircq) // DMA on falling edge
\r
108 | mode; // Pin pull up/down
\r
116 void tdma_reset(tdma_t *port)
\r
121 // Clear previous time
\r
125 // Freeze DMA channel
\r
126 port->dma->dcr &= ~DMA_DCR_ERQ_MASK;
\r
128 // Reset DMA channel
\r
129 port->dma->dsr = DMA_DSR_BCR_DONE_MASK;
\r
131 // Set addresses and size
\r
132 port->dma->sar = (uint32_t)&PIT->LTMR64H; // Global timer
\r
133 port->dma->dar = (uint32_t)&port->time; // Temp timer buffer
\r
134 port->dma->dsr = DMA_DSR_BCR_BCR(8); // 64-bit timer
\r
136 // Enable port request
\r
137 port->dma->dcr |= DMA_DCR_ERQ_MASK;
\r
140 int tdma_stamp(tdma_t *port, uint64_t *time)
\r
147 if (port->dma->dsr & DMA_DSR_BCR_BCR_MASK)
\r
150 // Read the timestamp
\r
151 clocks = ((uint64_t)~port->time[0]) << 32
\r
152 | ((uint64_t)~port->time[1]) << 0;
\r
154 // Convert to nanoseconds
\r
155 *time = clocks * 1000 / 24;
\r
160 uint64_t tdma_time(void)
\r
162 uint32_t tmh = PIT->LTMR64H;
\r
163 uint32_t tml = PIT->LTMR64L;
\r
165 // Read the timestamp
\r
166 uint64_t clocks = ((uint64_t)~tmh) << 32
\r
167 | ((uint64_t)~tml) << 0;
\r
169 // Convert to nanoseconds
\r
170 return clocks * 1000 / 24;
\r
173 void tdma_debug(tdma_t *port)
\r
175 int dsr = port->dma->dsr;
\r
176 int dcr = port->dma->dcr;
\r
178 printf("dsr: %s %s %s %s %s %s %d\r\n",
\r
179 dsr & DMA_DSR_BCR_CE_MASK ? "CE" : "ce",
\r
180 dsr & DMA_DSR_BCR_BES_MASK ? "BSE" : "bse",
\r
181 dsr & DMA_DSR_BCR_BED_MASK ? "BED" : "bed",
\r
182 dsr & DMA_DSR_BCR_REQ_MASK ? "REQ" : "req",
\r
183 dsr & DMA_DSR_BCR_BSY_MASK ? "BSY" : "bsy",
\r
184 dsr & DMA_DSR_BCR_DONE_MASK ? "DONE" : "done",
\r
185 dsr & DMA_DSR_BCR_BCR_MASK);
\r
187 printf("dcr: %s %s %s %s %s %s %s %s ssize=%d:%d mod=%d:%d link=%d:%d:%d\r\n",
\r
188 dcr & DMA_DCR_EINT_MASK ? "EINT" : "eint",
\r
189 dcr & DMA_DCR_ERQ_MASK ? "ERQ" : "erq",
\r
190 dcr & DMA_DCR_CS_MASK ? "CS" : "cs",
\r
191 dcr & DMA_DCR_AA_MASK ? "AA" : "aa",
\r
192 dcr & DMA_DCR_EADREQ_MASK ? "EADRREQ" : "eadrreq",
\r
193 dcr & DMA_DCR_SINC_MASK ? "SINC" : "sinc",
\r
194 dcr & DMA_DCR_DINC_MASK ? "DINC" : "dinc",
\r
195 dcr & DMA_DCR_D_REQ_MASK ? "DREQ" : "dreq",
\r
196 (dcr & DMA_DCR_SSIZE_MASK ) >> DMA_DCR_SSIZE_SHIFT,
\r
197 (dcr & DMA_DCR_DSIZE_MASK ) >> DMA_DCR_DSIZE_SHIFT,
\r
198 (dcr & DMA_DCR_SMOD_MASK ) >> DMA_DCR_SMOD_SHIFT,
\r
199 (dcr & DMA_DCR_DMOD_MASK ) >> DMA_DCR_DMOD_SHIFT,
\r
200 (dcr & DMA_DCR_LINKCC_MASK) >> DMA_DCR_LINKCC_SHIFT,
\r
201 (dcr & DMA_DCR_LCH1_MASK ) >> DMA_DCR_LCH1_SHIFT,
\r
202 (dcr & DMA_DCR_LCH2_MASK ) >> DMA_DCR_LCH2_SHIFT);
\r