2 #include "serial_dma.h"
\r
6 * Devices 1 and 2 synchronize clocks using serial messages.
\r
8 * 1. Each serial message timestamped using the hardware timer capture
\r
9 * registers in both the sender and receiver.
\r
10 * 2. The sender transmits the send timestamp during the next time-sync
\r
12 * 3. The receiver then compares the senders timestamp with it's own
\r
13 * timestamp for the corresponding messages and calculates an offset.
\r
14 * 4. The offset is used to compensate the receivers local clock.
\r
16 * Time synchronization is performed in both directions.
\r
19 * Only port A, C, and D can do aysnc DMA (p. 67)
\r
22 * UART 0 UART 1 UART 2
\r
23 * xmt rcv xmt rcv xmt rcv
\r
24 * --- --- --- --- --- ---
\r
25 * A2 A1 **A19 A18** - -
\r
29 * D7 D6 - - **D3 D2** <<<
\r
31 * E20 E21 E0 E1 E16 E17
\r
45 * D2 C16 E16 P5V-USB
\r
49 * D5 A15 E31 SDA/D5
\r
56 /* Trigger select options */
\r
58 #define TMP_CONF_TRGSEL_EXTRG 0x0 // 0b0000 External trigger pin input (EXTRG_IN)
\r
59 #define TMP_CONF_TRGSEL_CMP0 0x1 // 0b0001 CMP0 output
\r
60 #define TMP_CONF_TRGSEL_PIT0 0x4 // 0b0100 PIT trigger 0
\r
61 #define TMP_CONF_TRGSEL_PIT1 0x5 // 0b0101 PIT trigger 1
\r
62 #define TMP_CONF_TRGSEL_TPM0 0x8 // 0b1000 TPM0 overflow
\r
63 #define TMP_CONF_TRGSEL_TPM1 0x9 // 0b1001 TPM1 overflow
\r
64 #define TMP_CONF_TRGSEL_TPM2 0xA // 0b1010 TPM2 overflow
\r
65 #define TMP_CONF_TRGSEL_RTCA 0xC // 0b1100 RTC alarm
\r
66 #define TMP_CONF_TRGSEL_RTCS 0xD // 0b1101 RTC seconds
\r
67 #define TMP_CONF_TRGSEL_LPTMR 0xE // 0b1110 LPTMR trigger
\r
69 /***********************
\r
70 * Message Definitions *
\r
71 ***********************/
\r
73 #define MSG_HEADER 0x1234
\r
76 MSG_ID_SYNC, // Time synchronization
\r
77 MSG_ID_EVENT, // Event occurred
\r
81 uint32_t seconds; // Seconds since 1970 (without leap seconds)
\r
82 uint32_t nanosec; // Nanoseconds since 'seconds'
\r
86 uint16_t header; // Message Header
\r
87 uint16_t mesgid; // Message ID
\r
88 uint16_t length; // Body length
\r
89 uint16_t cksum; // Body checksum
\r
93 uint16_t seq; // Current sequence counter
\r
94 uint16_t prev; // Sequence of previous message
\r
95 ntime_t time; // Time of previous message
\r
99 uint16_t device; // Device ID
\r
100 uint16_t event; // Event ID
\r
101 ntime_t time; // Timestamp
\r
104 /*******************
\r
105 * Timer functions *
\r
106 *******************/
\r
109 * Generate time stamp for an async event:
\r
110 * time: drift compensated wall-clock time
\r
111 * stamp: event timestamp from Timer/PWM Module
\r
113 void time_stamp(ntime_t *time, uint32_t stamp)
\r
119 * Compensate the Real-Time-Clock oscillator for
\r
120 * temperature and drift errors. Called at 1Hz and
\r
121 * synchronous to the RTC 1Hz output.
\r
123 void time_rtc_comp(void)
\r
129 * Synchronize the timer internal state with updates
\r
130 * from an external time sync message.
\r
131 * ours: our internal timestamp for the event
\r
132 * ref: reference timestamp from the other device
\r
134 void time_ext_sync(ntime_t *ours, ntime_t *ref)
\r
139 /************************
\r
140 * Serial I/O functions *
\r
141 ************************/
\r
144 * Output time sync message
\r
146 void serial_send_sync(void)
\r
151 * Output external event received message
\r
152 * event: id of the received event
\r
153 * time: compensated timestamp of the event
\r
155 void serial_send_event(uint16_t event, ntime_t *time)
\r
160 * Process serial receive messages
\r
162 void serial_receive(void)
\r
166 /***********************
\r
167 * Timestamp functions *
\r
168 ***********************/
\r
173 /********************
\r
174 * Data definitions *
\r
175 ********************/
\r
178 DigitalOut led1(LED1);
\r
179 DigitalOut led2(LED2);
\r
182 Serial uart0(USBTX, USBRX);
\r
183 Serial uart1(PTE0, PTE1);
\r
184 Serial uart2(PTD3, PTD2);
\r
195 void test_tpm_init(void)
\r
197 // EXTRG_IN - PTB8 - alt 3
\r
201 // Setup System Integration Module
\r
202 SIM_Type *sim = SIM;
\r
204 sim->SCGC5 |= SIM_SCGC5_PORTA_MASK
\r
205 | SIM_SCGC5_PORTB_MASK
\r
206 | SIM_SCGC5_PORTC_MASK
\r
207 | SIM_SCGC5_PORTD_MASK
\r
208 | SIM_SCGC5_PORTE_MASK
\r
209 | SIM_SCGC5_LPTMR_MASK;
\r
211 sim->SCGC6 |= SIM_SCGC6_TPM0_MASK
\r
212 | SIM_SCGC6_TPM1_MASK
\r
213 | SIM_SCGC6_TPM2_MASK
\r
214 | SIM_SCGC6_DAC0_MASK
\r
215 | SIM_SCGC6_ADC0_MASK
\r
216 | SIM_SCGC6_PIT_MASK
\r
217 | SIM_SCGC6_DMAMUX_MASK
\r
218 | SIM_SCGC6_RTC_MASK;
\r
220 sim->SOPT2 |= SIM_SOPT2_TPMSRC(1);
\r
222 sim->SOPT4 = SIM_SOPT4_TPM1CLKSEL_MASK
\r
223 | SIM_SOPT4_TPM1CH0SRC(3);
\r
225 printf("SOPT2:%08lx SCGC5:%08lx SCGC6:%08lx\r\n",
\r
226 sim->SOPT2, sim->SCGC5, sim->SCGC6);
\r
227 //SOPT2:05010000 SCGC5:00003f83 SCGC6:07800001
\r
229 //sim->SOPT7 |= SIM_SOPT7_ADC0TRGSEL(TMP_CONF_TRGSEL_EXTRG);
\r
231 // Setup Port Control
\r
232 PORT_Type *port = PORTC;
\r
234 PORTE->PCR[25] = PORT_PCR_ISF_MASK
\r
235 | PORT_PCR_IRQC(0x1)
\r
236 | PORT_PCR_MUX(3) ;
\r
238 port->PCR[0] = PORT_PCR_ISF_MASK
\r
239 | PORT_PCR_IRQC(0x1)
\r
241 | PORT_PCR_PE_MASK;
\r
243 // Setup Timer/PWM Module
\r
244 volatile TPM_Type *tpm = TPM1;
\r
246 tpm->SC = TPM_SC_PS(0x7)
\r
249 tpm->CNT = TPM_CNT_COUNT(0);
\r
251 tpm->MOD = TPM_CNT_COUNT(0xFFFF);
\r
253 tpm->CONTROLS[1].CnV = 0x1234;
\r
254 tpm->CONTROLS[1].CnSC = TPM_CnSC_CHF_MASK
\r
255 | TPM_CnSC_CHIE_MASK
\r
256 | TPM_CnSC_ELSA_MASK;
\r
258 //tpm->CONTROLS[0].CnSC = TPM_CnSC_CHF_MASK
\r
259 // | TPM_CnSC_CHIE_MASK
\r
260 // | TPM_CnSC_MSB_MASK
\r
261 // | TPM_CnSC_MSA_MASK
\r
262 // | TPM_CnSC_ELSB_MASK
\r
263 // | TPM_CnSC_ELSA_MASK;
\r
265 tpm->STATUS = TPM_STATUS_CH0F_MASK
\r
266 | TPM_STATUS_CH1F_MASK
\r
267 | TPM_STATUS_CH2F_MASK
\r
268 | TPM_STATUS_CH3F_MASK
\r
269 | TPM_STATUS_CH4F_MASK
\r
270 | TPM_STATUS_CH5F_MASK
\r
271 | TPM_STATUS_TOF_MASK;
\r
273 tpm->CONF = TPM_CONF_TRGSEL(TMP_CONF_TRGSEL_EXTRG)
\r
274 | TPM_CONF_CSOO_MASK
\r
275 | TPM_CONF_CSOT_MASK
\r
276 | TPM_CONF_GTBEEN_MASK
\r
277 | TPM_CONF_DBGMODE_MASK;
\r
279 tpm->SC = TPM_SC_CMOD(1)
\r
283 printf("test - %02lx %08lx\r\n", tpm->CONTROLS[1].CnSC, tpm->CONTROLS[1].CnV); wait(0.1);
\r
286 void test_tpm_run(void)
\r
288 //static DigitalIn pin(PTC0);
\r
289 //static DigitalIn pin(PTC2);
\r
290 static int pin = 0;
\r
292 printf("%lx - PTC0:%08lx GPCR:%08lx:%08lx - SC:%04lx CNT:%04lx MOD:%04lx STATUS:%04lx CONF:%08lx - CnSC:%02lx CnV:%04lx\r\n",
\r
293 (long)pin, PORTC->PCR[0], PORTC->GPCHR, PORTC->GPCLR,
\r
294 TPM1->SC, TPM1->CNT, TPM1->MOD, TPM1->STATUS, TPM1->CONF,
\r
295 TPM1->CONTROLS[1].CnSC, TPM1->CONTROLS[1].CnV);
\r
296 TPM1->SC |= TPM_STATUS_TOF_MASK;
\r
297 TPM1->STATUS |= TPM_STATUS_TOF_MASK;
\r
300 void test_pit_init(void)
\r
302 //printf("test_pit_init\r\n");
\r
305 SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;
\r
309 PIT->CHANNEL[0].LDVAL = 0xFFFFFFFF;
\r
310 PIT->CHANNEL[0].TCTRL = 0;
\r
313 PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;
\r
314 PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK;
\r
317 PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;
\r
318 PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;
\r
322 void test_pit_run(void)
\r
324 register volatile uint32_t *tmh asm("r4") = &PIT->LTMR64H;
\r
325 register volatile uint32_t *tml asm("r5") = &PIT->LTMR64L;
\r
327 register uint32_t hi0 asm("r0"), lo0 asm("r1");
\r
328 register uint32_t hi1 asm("r2"), lo1 asm("r3");
\r
330 asm("ldr %0, [%4]\n\t" // Two clocks per load
\r
334 : "=r"(hi0), "=r"(lo0), "=r"(hi1), "=r"(lo1)
\r
335 : "r"(tmh), "r"(tml));
\r
337 uint64_t tm0 = ~((uint64_t)hi0 << 32 | lo0);
\r
338 uint64_t tm1 = ~((uint64_t)hi1 << 32 | lo1);
\r
339 double bus = 24E6; // 24 MHz bus clock
\r
341 printf("tick %08lx:%08lx", (uint32_t)(tm0>>32), (uint32_t)tm0);
\r
342 printf( " %08lx:%08lx", (uint32_t)(tm1>>32), (uint32_t)tm1);
\r
343 printf( " %08lx", (uint32_t)(tm1-tm0));
\r
344 printf( " %f\r\n", (double)tm0 / bus);
\r
347 void test_uart(void)
\r
349 char xmt[32] = "hello, world";
\r
352 sdma_write(sdma1, xmt, strlen(xmt));
\r
355 for (int i = 0; xmt[i]; i++)
\r
356 rcv[i] = uart2.getc();
\r
358 printf("xmt: %s ", xmt);
\r
359 printf("rcv: %s ", rcv);
\r
360 printf("tag: dir:%08lx in:%08lx\r\n",
\r
361 FPTD->PDDR, FPTD->PDIR);
\r
364 void test_leds(void)
\r
366 led1 = 1; led2 = 0; wait(0.1);
\r
367 led1 = 0; led2 = 1; wait(0.1);
\r
370 int main(int argc, char **argv)
\r
372 uart0.baud(115200);
\r
373 uart1.baud(115200);
\r
374 uart2.baud(115200);
\r
376 sdma1 = sdma_open(SDMA_UART1, SDMA_CHANNEL1);
\r
377 sdma2 = sdma_open(SDMA_UART2, SDMA_CHANNEL2);
\r