2 #include "serial_dma.h"
\r
3 #include "timer_dma.h"
\r
7 * Devices 1 and 2 synchronize clocks using serial messages.
\r
9 * 1. Each serial message timestamped using the hardware timer capture
\r
10 * registers in both the sender and receiver.
\r
11 * 2. The sender transmits the send timestamp during the next time-sync
\r
13 * 3. The receiver then compares the senders timestamp with it's own
\r
14 * timestamp for the corresponding messages and calculates an offset.
\r
15 * 4. The offset is used to compensate the receivers local clock.
\r
17 * Time synchronization is performed in both directions.
\r
20 * Only port A, C, and D can do aysnc DMA (p. 67)
\r
22 * DMA Channel Allocation:
\r
23 * Ch Trigger Description
\r
24 * 0 gpio timestamp (async event)
\r
26 * 2 uart2 tx timestamp (time sync xmt)
\r
27 * 3 uart2 rx timestamp (time sync rcv)
\r
30 * UART 0 UART 1 UART 2
\r
31 * xmt rcv xmt rcv xmt rcv
\r
32 * --- --- --- --- --- ---
\r
33 * A2 A1 --A19 A18-- - -
\r
37 * D7 D6 - - **D3/3 D2/3** <<<
\r
38 * - - - - **D5/3 D4/3**
\r
39 * E20 E21 E0 E1 E16 E17
\r
53 * D2 C16 E16 P5V-USB
\r
64 /* Trigger select options */
\r
66 #define TMP_CONF_TRGSEL_EXTRG 0x0 // 0b0000 External trigger pin input (EXTRG_IN)
\r
67 #define TMP_CONF_TRGSEL_CMP0 0x1 // 0b0001 CMP0 output
\r
68 #define TMP_CONF_TRGSEL_PIT0 0x4 // 0b0100 PIT trigger 0
\r
69 #define TMP_CONF_TRGSEL_PIT1 0x5 // 0b0101 PIT trigger 1
\r
70 #define TMP_CONF_TRGSEL_TPM0 0x8 // 0b1000 TPM0 overflow
\r
71 #define TMP_CONF_TRGSEL_TPM1 0x9 // 0b1001 TPM1 overflow
\r
72 #define TMP_CONF_TRGSEL_TPM2 0xA // 0b1010 TPM2 overflow
\r
73 #define TMP_CONF_TRGSEL_RTCA 0xC // 0b1100 RTC alarm
\r
74 #define TMP_CONF_TRGSEL_RTCS 0xD // 0b1101 RTC seconds
\r
75 #define TMP_CONF_TRGSEL_LPTMR 0xE // 0b1110 LPTMR trigger
\r
77 /***********************
\r
78 * Message Definitions *
\r
79 ***********************/
\r
81 #define MSG_HEADER 0x1234
\r
84 MSG_ID_SYNC, // Time synchronization
\r
85 MSG_ID_EVENT, // Event occurred
\r
89 uint32_t seconds; // Seconds since 1970 (without leap seconds)
\r
90 uint32_t nanosec; // Nanoseconds since 'seconds'
\r
94 uint16_t header; // Message Header
\r
95 uint16_t mesgid; // Message ID
\r
96 uint16_t length; // Body length
\r
97 uint16_t cksum; // Body checksum
\r
101 uint16_t seq; // Current sequence counter
\r
102 uint16_t prev; // Sequence of previous message
\r
103 ntime_t time; // Time of previous message
\r
107 uint16_t device; // Device ID
\r
108 uint16_t event; // Event ID
\r
109 ntime_t time; // Timestamp
\r
112 /*******************
\r
113 * Timer functions *
\r
114 *******************/
\r
117 * Generate time stamp for an async event:
\r
118 * time: drift compensated wall-clock time
\r
119 * stamp: event timestamp from Timer/PWM Module
\r
121 void time_stamp(ntime_t *time, uint32_t stamp)
\r
127 * Compensate the Real-Time-Clock oscillator for
\r
128 * temperature and drift errors. Called at 1Hz and
\r
129 * synchronous to the RTC 1Hz output.
\r
131 void time_rtc_comp(void)
\r
137 * Synchronize the timer internal state with updates
\r
138 * from an external time sync message.
\r
139 * ours: our internal timestamp for the event
\r
140 * ref: reference timestamp from the other device
\r
142 void time_ext_sync(ntime_t *ours, ntime_t *ref)
\r
147 /************************
\r
148 * Serial I/O functions *
\r
149 ************************/
\r
152 * Output time sync message
\r
154 void serial_send_sync(void)
\r
159 * Output external event received message
\r
160 * event: id of the received event
\r
161 * time: compensated timestamp of the event
\r
163 void serial_send_event(uint16_t event, ntime_t *time)
\r
168 * Process serial receive messages
\r
170 void serial_receive(void)
\r
174 /***********************
\r
175 * Timestamp functions *
\r
176 ***********************/
\r
181 /********************
\r
182 * Data definitions *
\r
183 ********************/
\r
186 DigitalOut led1(LED1);
\r
187 DigitalOut led2(LED2);
\r
190 Serial uart0(USBTX, USBRX);
\r
191 Serial uart1(PTE0, PTE1);
\r
192 Serial uart2(PTD3, PTD2);
\r
209 void test_tpm_init(void)
\r
211 // EXTRG_IN - PTB8 - alt 3
\r
215 // Setup System Integration Module
\r
216 SIM_Type *sim = SIM;
\r
218 sim->SCGC5 |= SIM_SCGC5_PORTA_MASK
\r
219 | SIM_SCGC5_PORTB_MASK
\r
220 | SIM_SCGC5_PORTC_MASK
\r
221 | SIM_SCGC5_PORTD_MASK
\r
222 | SIM_SCGC5_PORTE_MASK
\r
223 | SIM_SCGC5_LPTMR_MASK;
\r
225 sim->SCGC6 |= SIM_SCGC6_TPM0_MASK
\r
226 | SIM_SCGC6_TPM1_MASK
\r
227 | SIM_SCGC6_TPM2_MASK
\r
228 | SIM_SCGC6_DAC0_MASK
\r
229 | SIM_SCGC6_ADC0_MASK
\r
230 | SIM_SCGC6_PIT_MASK
\r
231 | SIM_SCGC6_DMAMUX_MASK
\r
232 | SIM_SCGC6_RTC_MASK;
\r
234 sim->SOPT2 |= SIM_SOPT2_TPMSRC(1);
\r
236 sim->SOPT4 = SIM_SOPT4_TPM1CLKSEL_MASK
\r
237 | SIM_SOPT4_TPM1CH0SRC(3);
\r
239 printf("SOPT2:%08lx SCGC5:%08lx SCGC6:%08lx\r\n",
\r
240 sim->SOPT2, sim->SCGC5, sim->SCGC6);
\r
241 //SOPT2:05010000 SCGC5:00003f83 SCGC6:07800001
\r
243 //sim->SOPT7 |= SIM_SOPT7_ADC0TRGSEL(TMP_CONF_TRGSEL_EXTRG);
\r
245 // Setup Port Control
\r
246 PORT_Type *port = PORTC;
\r
248 PORTE->PCR[25] = PORT_PCR_ISF_MASK
\r
249 | PORT_PCR_IRQC(0x1)
\r
250 | PORT_PCR_MUX(3) ;
\r
252 port->PCR[0] = PORT_PCR_ISF_MASK
\r
253 | PORT_PCR_IRQC(0x1)
\r
255 | PORT_PCR_PE_MASK;
\r
257 // Setup Timer/PWM Module
\r
258 volatile TPM_Type *tpm = TPM1;
\r
260 tpm->SC = TPM_SC_PS(0x7)
\r
263 tpm->CNT = TPM_CNT_COUNT(0);
\r
265 tpm->MOD = TPM_CNT_COUNT(0xFFFF);
\r
267 tpm->CONTROLS[1].CnV = 0x1234;
\r
268 tpm->CONTROLS[1].CnSC = TPM_CnSC_CHF_MASK
\r
269 | TPM_CnSC_CHIE_MASK
\r
270 | TPM_CnSC_ELSA_MASK;
\r
272 //tpm->CONTROLS[0].CnSC = TPM_CnSC_CHF_MASK
\r
273 // | TPM_CnSC_CHIE_MASK
\r
274 // | TPM_CnSC_MSB_MASK
\r
275 // | TPM_CnSC_MSA_MASK
\r
276 // | TPM_CnSC_ELSB_MASK
\r
277 // | TPM_CnSC_ELSA_MASK;
\r
279 tpm->STATUS = TPM_STATUS_CH0F_MASK
\r
280 | TPM_STATUS_CH1F_MASK
\r
281 | TPM_STATUS_CH2F_MASK
\r
282 | TPM_STATUS_CH3F_MASK
\r
283 | TPM_STATUS_CH4F_MASK
\r
284 | TPM_STATUS_CH5F_MASK
\r
285 | TPM_STATUS_TOF_MASK;
\r
287 tpm->CONF = TPM_CONF_TRGSEL(TMP_CONF_TRGSEL_EXTRG)
\r
288 | TPM_CONF_CSOO_MASK
\r
289 | TPM_CONF_CSOT_MASK
\r
290 | TPM_CONF_GTBEEN_MASK
\r
291 | TPM_CONF_DBGMODE_MASK;
\r
293 tpm->SC = TPM_SC_CMOD(1)
\r
297 printf("test - %02lx %08lx\r\n", tpm->CONTROLS[1].CnSC, tpm->CONTROLS[1].CnV); wait(0.1);
\r
300 void test_tpm_run(void)
\r
302 //static DigitalIn pin(PTC0);
\r
303 //static DigitalIn pin(PTC2);
\r
304 //static int pin = 0;
\r
306 printf("PTC0:%08lx GPCR:%08lx:%08lx - SC:%04lx CNT:%04lx MOD:%04lx STATUS:%04lx CONF:%08lx - CnSC:%02lx CnV:%04lx\r\n",
\r
307 PORTC->PCR[0], PORTC->GPCHR, PORTC->GPCLR,
\r
308 TPM1->SC, TPM1->CNT, TPM1->MOD, TPM1->STATUS, TPM1->CONF,
\r
309 TPM1->CONTROLS[1].CnSC, TPM1->CONTROLS[1].CnV);
\r
310 TPM1->SC |= TPM_STATUS_TOF_MASK;
\r
311 TPM1->STATUS |= TPM_STATUS_TOF_MASK;
\r
314 void test_pit_init(void)
\r
316 //printf("test_pit_init\r\n");
\r
319 SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;
\r
323 PIT->CHANNEL[0].LDVAL = 0xFFFFFFFF;
\r
324 PIT->CHANNEL[0].TCTRL = 0;
\r
327 PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;
\r
328 PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK;
\r
331 PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;
\r
332 PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;
\r
336 void test_pit_run(void)
\r
338 register volatile uint32_t *tmh asm("r4") = &PIT->LTMR64H;
\r
339 register volatile uint32_t *tml asm("r5") = &PIT->LTMR64L;
\r
341 register uint32_t hi0 asm("r0"), lo0 asm("r1");
\r
342 register uint32_t hi1 asm("r2"), lo1 asm("r3");
\r
344 asm("ldr %0, [%4]\n\t" // Two clocks per load
\r
348 : "=r"(hi0), "=r"(lo0), "=r"(hi1), "=r"(lo1)
\r
349 : "r"(tmh), "r"(tml));
\r
351 uint64_t tm0 = ~((uint64_t)hi0 << 32 | lo0);
\r
352 uint64_t tm1 = ~((uint64_t)hi1 << 32 | lo1);
\r
353 double bus = 24E6; // 24 MHz bus clock
\r
356 printf(" %08lx:%08lx", (uint32_t)(tm0>>32), (uint32_t)tm0);
\r
357 printf(" %08lx:%08lx", (uint32_t)(tm1>>32), (uint32_t)tm1);
\r
358 printf(" %08lx", (uint32_t)(tm1-tm0));
\r
359 printf(" %f", (double)tm0 / bus);
\r
362 void test_sdma_init(void)
\r
364 sdma0 = sdma_open(SDMA_UART0, SDMA_CHANNEL0, SDMA_CHANNEL1);
\r
365 sdma1 = sdma_open(SDMA_UART1, SDMA_CHANNEL0, SDMA_CHANNEL1);
\r
366 sdma2 = sdma_open(SDMA_UART2, SDMA_CHANNEL2, SDMA_CHANNEL3);
\r
368 sdma_pinmap(sdma1, PTE0, PTE1);
\r
369 sdma_pinmap(sdma2, PTD3, PTD2);
\r
372 void test_sdma_run(void)
\r
374 char xmt[32] = "hello, world";
\r
379 sdma_write(sdma1, xmt, strlen(xmt));
\r
380 sdma_flush(sdma1, &tm1);
\r
382 sdma_read(sdma2, rcv, strlen(xmt));
\r
383 sdma_wait(sdma2, &tm2);
\r
385 printf("send: [%s] -> [%s] ", xmt, rcv);
\r
386 printf("time: %08lx / %08lx ", (uint32_t)tm1, (uint32_t)tm2);
\r
387 printf("tag: dir:%08lx in:%08lx\r\n",
\r
388 FPTD->PDDR, FPTD->PDIR);
\r
390 (void)xmt; (void)rcv;
\r
391 (void)tm1; (void)tm2;
\r
394 void test_tdma_init(void)
\r
398 tdma0 = tdma_open(TDMA_CHAN0, PTA1, PullNone);
\r
399 tdma1 = tdma_open(TDMA_CHAN1, PTC1, PullNone);
\r
400 tdma2 = tdma_open(TDMA_CHAN2, PTD3, PullUp);
\r
401 tdma3 = tdma_open(TDMA_CHAN3, PTD2, PullUp);
\r
404 void test_tdma_run(void)
\r
406 static uint32_t time0[2];
\r
407 static uint32_t time1[2];
\r
408 static uint32_t time2[2];
\r
409 static uint32_t time3[2];
\r
411 tdma_stamp(tdma0, (uint64_t*)&time0);
\r
412 tdma_stamp(tdma1, (uint64_t*)&time1);
\r
413 tdma_stamp(tdma2, (uint64_t*)&time2);
\r
414 tdma_stamp(tdma3, (uint64_t*)&time3);
\r
421 printf(" - timer:");
\r
422 printf(" %08lx:%08lx", time0[1], time0[0]);
\r
423 printf(" %08lx:%08lx", time1[1], time1[0]);
\r
424 printf(" %08lx:%08lx", time2[1], time2[0]);
\r
425 printf(" %08lx:%08lx", time3[1], time3[0]);
\r
426 //printf(" do:%08lx", FPTD->PDOR);
\r
427 //printf(" di:%08lx", FPTD->PDIR);
\r
428 //printf(" dd:%08lx", FPTD->PDDR);
\r
431 void test_leds(void)
\r
433 led1 = 1; led2 = 0; wait(0.1);
\r
434 led1 = 0; led2 = 1; wait(0.1);
\r
437 int main(int argc, char **argv)
\r
439 uart0.baud(115200);
\r
440 uart1.baud(115200);
\r
441 uart2.baud(115200);
\r
443 printf("init\r\n");
\r
446 //test_sdma_init();
\r
450 for (int i = 0; true; i++) {
\r