]> Pileus Git - ~andy/csm213a-hw/blob - hw2/main.cpp
Add dma timestamper
[~andy/csm213a-hw] / hw2 / main.cpp
1 #include "mbed.h"\r
2 #include "serial_dma.h"\r
3 #include "timer_dma.h"\r
4 \r
5 /**\r
6  * Mode of operation:\r
7  *   Devices 1 and 2 synchronize clocks using serial messages.\r
8  *\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
12  *      message.\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
16  *\r
17  *   Time synchronization is performed in both directions.\r
18  *\r
19  *\r
20  * Only port A, C, and D can do aysnc DMA (p. 67)\r
21  *\r
22  * DMA Channel Allocation:\r
23  *     Ch  Trigger    Description\r
24  *     0   gpio       timestamp (async event)\r
25  *     1   uart1      transmit\r
26  *     2   uart2 tx   timestamp (time sync xmt)\r
27  *     3   uart2 rx   timestamp (time sync rcv)\r
28  *\r
29  * Uart Sources:\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
34  *     A14  A15   -    -     -    -\r
35  *     B17  B16   -    -     -    -\r
36  *     -    -   **C4   C3--  -    -\r
37  *     D7   D6    -    -   **D3/3 D2/3** <<<\r
38  *     -    -     -    -   **D5/3 D4/3**\r
39  *     E20  E21   E0   E1    E16  E17\r
40  *     -    -     -    -     E22  E23\r
41  *\r
42  * Pinout\r
43  *     A1    B18        E30  C1\r
44  *     A2    B19        B20  C2\r
45  *     D3    C0         E23  B3\r
46  *     A12   C4         E22  B2\r
47  *     A4    C6         E21  B1\r
48  *     A5    C7         E20  B0\r
49  *     C8    C10\r
50  *     C9    C11        E2   P5-9V\r
51  *                      E3   GND\r
52  *     A13   C13        E6   GND\r
53  *     D2    C16        E16  P5V-USB\r
54  *     D4    A7         E17  P3V3\r
55  *     D6    A6         E18  RST\r
56  *     D7    A14        E19  P3V3\r
57  *     D5    A15        E31  SDA/D5\r
58  *     GND   A15\r
59  *     VREFH A17\r
60  *     E0    B9\r
61  *     E1    --\r
62  */\r
63 \r
64 /* Trigger select options */\r
65 \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
76 \r
77 /***********************\r
78  * Message Definitions *\r
79  ***********************/\r
80 \r
81 #define MSG_HEADER 0x1234\r
82 \r
83 typedef enum {\r
84         MSG_ID_SYNC,       // Time synchronization\r
85         MSG_ID_EVENT,      // Event occurred\r
86 } msgid_t;\r
87 \r
88 typedef struct {\r
89         uint32_t seconds;  // Seconds since 1970 (without leap seconds)\r
90         uint32_t nanosec;  // Nanoseconds since 'seconds'\r
91 } ntime_t;\r
92 \r
93 typedef struct {\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
98 } header_t;\r
99 \r
100 typedef struct {\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
104 } sync_msg_t;\r
105 \r
106 typedef struct {\r
107         uint16_t device;   // Device ID\r
108         uint16_t event;    // Event ID\r
109         ntime_t  time;     // Timestamp\r
110 } event_msg_t;\r
111 \r
112 /*******************\r
113  * Timer functions *\r
114  *******************/\r
115 \r
116 /**\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
120  */\r
121 void time_stamp(ntime_t *time, uint32_t stamp)\r
122 {\r
123         // todo\r
124 }\r
125 \r
126 /**\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
130  */\r
131 void time_rtc_comp(void)\r
132 {\r
133         // todo\r
134 }\r
135 \r
136 /**\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
141  */\r
142 void time_ext_sync(ntime_t *ours, ntime_t *ref)\r
143 {\r
144         // todo\r
145 }\r
146 \r
147 /************************\r
148  * Serial I/O functions *\r
149  ************************/\r
150 \r
151 /**\r
152  * Output time sync message\r
153  */\r
154 void serial_send_sync(void)\r
155 {\r
156 }\r
157 \r
158 /**\r
159  * Output external event received message\r
160  *   event: id of the received event\r
161  *   time:  compensated timestamp of the event\r
162  */\r
163 void serial_send_event(uint16_t event, ntime_t *time)\r
164 {\r
165 }\r
166 \r
167 /**\r
168  * Process serial receive messages\r
169  */\r
170 void serial_receive(void)\r
171 {\r
172 }\r
173 \r
174 /***********************\r
175  * Timestamp functions *\r
176  ***********************/\r
177 \r
178 //void stamp() {\r
179 //}\r
180 \r
181 /********************\r
182  * Data definitions *\r
183  ********************/\r
184 \r
185 // LEDs\r
186 DigitalOut led1(LED1);\r
187 DigitalOut led2(LED2);\r
188 \r
189 // UARTs         tx      rx\r
190 Serial     uart0(USBTX,  USBRX);\r
191 Serial     uart1(PTE0,   PTE1);\r
192 Serial     uart2(PTD3,   PTD2);\r
193 \r
194 // Serial DMA\r
195 sdma_t    *sdma0;\r
196 sdma_t    *sdma1;\r
197 sdma_t    *sdma2;\r
198 \r
199 // Timer DMA\r
200 tdma_t    *tdma0;\r
201 tdma_t    *tdma1;\r
202 tdma_t    *tdma2;\r
203 tdma_t    *tdma3;\r
204 \r
205 /********\r
206  * Main *\r
207  ********/\r
208 \r
209 void test_tpm_init(void)\r
210 {\r
211         // EXTRG_IN - PTB8 - alt 3\r
212         //            PTC0 - alt 3\r
213         //            PTC6 - alt 3\r
214 \r
215         // Setup System Integration Module\r
216         SIM_Type *sim = SIM;\r
217 \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
224 \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
233 \r
234         sim->SOPT2 |= SIM_SOPT2_TPMSRC(1);\r
235 \r
236         sim->SOPT4  = SIM_SOPT4_TPM1CLKSEL_MASK\r
237                    |  SIM_SOPT4_TPM1CH0SRC(3);\r
238 \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
242 \r
243         //sim->SOPT7 |= SIM_SOPT7_ADC0TRGSEL(TMP_CONF_TRGSEL_EXTRG);\r
244 \r
245         // Setup Port Control\r
246         PORT_Type *port = PORTC;\r
247 \r
248         PORTE->PCR[25] = PORT_PCR_ISF_MASK\r
249                        | PORT_PCR_IRQC(0x1)\r
250                        | PORT_PCR_MUX(3) ;\r
251 \r
252         port->PCR[0]   = PORT_PCR_ISF_MASK\r
253                        | PORT_PCR_IRQC(0x1)\r
254                        | PORT_PCR_MUX(3)\r
255                        | PORT_PCR_PE_MASK;\r
256 \r
257         // Setup Timer/PWM Module\r
258         volatile TPM_Type *tpm = TPM1;\r
259 \r
260         tpm->SC               = TPM_SC_PS(0x7)\r
261                               | TPM_SC_TOF_MASK;\r
262 \r
263         tpm->CNT              = TPM_CNT_COUNT(0);\r
264 \r
265         tpm->MOD              = TPM_CNT_COUNT(0xFFFF);\r
266 \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
271 \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
278 \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
286 \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
292 \r
293         tpm->SC               = TPM_SC_CMOD(1)\r
294                               | TPM_SC_PS(0x7)\r
295                               | TPM_SC_TOF_MASK;\r
296 \r
297         printf("test - %02lx %08lx\r\n", tpm->CONTROLS[1].CnSC, tpm->CONTROLS[1].CnV); wait(0.1);\r
298 }\r
299 \r
300 void test_tpm_run(void)\r
301 {\r
302         //static DigitalIn pin(PTC0);\r
303         //static DigitalIn pin(PTC2);\r
304         //static int pin = 0;\r
305 \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
312 }\r
313 \r
314 void test_pit_init(void)\r
315 {\r
316         //printf("test_pit_init\r\n");\r
317 \r
318         // Enable\r
319         SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;\r
320         PIT->MCR    = 0;\r
321 \r
322         // Channel 0\r
323         PIT->CHANNEL[0].LDVAL = 0xFFFFFFFF;\r
324         PIT->CHANNEL[0].TCTRL = 0;\r
325 \r
326         // Channel 1\r
327         PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;\r
328         PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK;\r
329 \r
330         // Start timers\r
331         PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;\r
332         PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;\r
333 \r
334 }\r
335 \r
336 void test_pit_run(void)\r
337 {\r
338         register volatile uint32_t *tmh asm("r4") = &PIT->LTMR64H;\r
339         register volatile uint32_t *tml asm("r5") = &PIT->LTMR64L;\r
340 \r
341         register uint32_t hi0 asm("r0"), lo0 asm("r1");\r
342         register uint32_t hi1 asm("r2"), lo1 asm("r3");\r
343 \r
344         asm("ldr %0, [%4]\n\t" // Two clocks per load\r
345             "ldr %1, [%5]\n\t"\r
346             "ldr %2, [%4]\n\t"\r
347             "ldr %3, [%5]\n\t"\r
348             : "=r"(hi0), "=r"(lo0), "=r"(hi1), "=r"(lo1)\r
349             :  "r"(tmh),  "r"(tml));\r
350 \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
354 \r
355         printf(" - pit");\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
360 }\r
361 \r
362 void test_sdma_init(void)\r
363 {\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
367 \r
368         sdma_pinmap(sdma1, PTE0, PTE1);\r
369         sdma_pinmap(sdma2, PTD3, PTD2);\r
370 }\r
371 \r
372 void test_sdma_run(void)\r
373 {\r
374         char xmt[32] = "hello, world";\r
375         char rcv[32] = {};\r
376 \r
377         uint64_t tm1, tm2;\r
378 \r
379         sdma_write(sdma1, xmt, strlen(xmt));\r
380         sdma_flush(sdma1, &tm1);\r
381 \r
382         sdma_read(sdma2, rcv, strlen(xmt));\r
383         sdma_wait(sdma2, &tm2);\r
384 \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
389 \r
390         (void)xmt; (void)rcv;\r
391         (void)tm1; (void)tm2;\r
392 }\r
393 \r
394 void test_tdma_init(void)\r
395 {\r
396         tdma_init();\r
397 \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
402 }\r
403 \r
404 void test_tdma_run(void)\r
405 {\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
410 \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
415 \r
416         tdma_reset(tdma0);\r
417         tdma_reset(tdma1);\r
418         tdma_reset(tdma2);\r
419         tdma_reset(tdma3);\r
420 \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
429 }\r
430 \r
431 void test_leds(void)\r
432 {\r
433         led1 = 1; led2 = 0; wait(0.1);\r
434         led1 = 0; led2 = 1; wait(0.1);\r
435 }\r
436 \r
437 int main(int argc, char **argv)\r
438 {\r
439         uart0.baud(115200);\r
440         uart1.baud(115200);\r
441         uart2.baud(115200);\r
442 \r
443         printf("init\r\n");\r
444         //test_tpm_init();\r
445         //test_pit_init();\r
446         //test_sdma_init();\r
447         test_tdma_init();\r
448 \r
449         printf("run\r\n");\r
450         for (int i = 0; true; i++) {\r
451                 printf("%8d", i);\r
452                 //test_leds();\r
453                 //test_tpm_run();\r
454                 //test_pit_run();\r
455                 //test_sdma_run();\r
456                 test_tdma_run();\r
457                 printf("\r\n");\r
458         }\r
459 }\r