]> Pileus Git - ~andy/csm213a-hw/blob - hw2/main.cpp
Add dma and more tests
[~andy/csm213a-hw] / hw2 / main.cpp
1 #include "mbed.h"\r
2 #include "serial_dma.h"\r
3 \r
4 /**\r
5  * Mode of operation:\r
6  *   Devices 1 and 2 synchronize clocks using serial messages.\r
7  *\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
11  *      message.\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
15  *\r
16  *   Time synchronization is performed in both directions.\r
17  *\r
18  *\r
19  * Only port A, C, and D can do aysnc DMA (p. 67)\r
20  *\r
21  * Uart Sources:\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
26  *     A14  A15   -    -     -    -\r
27  *     B17  B16   -    -     -    -\r
28  *     -    -   **C4   C3**  -    -\r
29  *     D7   D6    -    -   **D3   D2** <<<\r
30  *     -    -     -    -   **D5   D4**\r
31  *     E20  E21   E0   E1    E16  E17 \r
32  *     -    -     -    -     E22  E23 \r
33  *\r
34  * Pinout\r
35  *     A1    B18        E30  C1        \r
36  *     A2    B19        B20  C2        \r
37  *     D3    C0         E23  B3        \r
38  *     A12   C4         E22  B2        \r
39  *     A4    C6         E21  B1        \r
40  *     A5    C7         E20  B0        \r
41  *     C8    C10                       \r
42  *     C9    C11        E2   P5-9V     \r
43  *                      E3   GND       \r
44  *     A13   C13        E6   GND       \r
45  *     D2    C16        E16  P5V-USB   \r
46  *     D4    A7         E17  P3V3      \r
47  *     D6    A6         E18  RST       \r
48  *     D7    A14        E19  P3V3      \r
49  *     D5    A15        E31  SDA/D5  \r
50  *     GND   A15 \r
51  *     VREFH A17 \r
52  *     E0    B9  \r
53  *     E1    --\r
54  */\r
55 \r
56 /* Trigger select options */\r
57 \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
68 \r
69 /***********************\r
70  * Message Definitions *\r
71  ***********************/\r
72 \r
73 #define MSG_HEADER 0x1234\r
74 \r
75 typedef enum {\r
76         MSG_ID_SYNC,       // Time synchronization\r
77         MSG_ID_EVENT,      // Event occurred\r
78 } msgid_t;\r
79 \r
80 typedef struct {\r
81         uint32_t seconds;  // Seconds since 1970 (without leap seconds)\r
82         uint32_t nanosec;  // Nanoseconds since 'seconds'\r
83 } ntime_t;\r
84 \r
85 typedef struct {\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
90 } header_t;\r
91 \r
92 typedef struct {\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
96 } sync_msg_t;\r
97 \r
98 typedef struct {\r
99         uint16_t device;   // Device ID\r
100         uint16_t event;    // Event ID\r
101         ntime_t  time;     // Timestamp\r
102 } event_msg_t;\r
103 \r
104 /*******************\r
105  * Timer functions *\r
106  *******************/\r
107 \r
108 /**\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
112  */\r
113 void time_stamp(ntime_t *time, uint32_t stamp)\r
114 {\r
115         // todo\r
116 }\r
117 \r
118 /**\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
122  */\r
123 void time_rtc_comp(void)\r
124 {\r
125         // todo\r
126 }\r
127 \r
128 /**\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
133  */\r
134 void time_ext_sync(ntime_t *ours, ntime_t *ref)\r
135 {\r
136         // todo\r
137 }\r
138 \r
139 /************************\r
140  * Serial I/O functions *\r
141  ************************/\r
142 \r
143 /**\r
144  * Output time sync message\r
145  */\r
146 void serial_send_sync(void)\r
147 {\r
148 }\r
149 \r
150 /**\r
151  * Output external event received message\r
152  *   event: id of the received event\r
153  *   time:  compensated timestamp of the event\r
154  */\r
155 void serial_send_event(uint16_t event, ntime_t *time)\r
156 {\r
157 }\r
158 \r
159 /**\r
160  * Process serial receive messages\r
161  */\r
162 void serial_receive(void)\r
163 {\r
164 }\r
165 \r
166 /***********************\r
167  * Timestamp functions *\r
168  ***********************/\r
169 \r
170 //void stamp() {\r
171 //}\r
172 \r
173 /********************\r
174  * Data definitions *\r
175  ********************/\r
176 \r
177 // LEDs\r
178 DigitalOut led1(LED1);\r
179 DigitalOut led2(LED2);\r
180 \r
181 // UARTs         tx      rx\r
182 Serial     uart0(USBTX,  USBRX);\r
183 Serial     uart1(PTE0,   PTE1);\r
184 Serial     uart2(PTD3,   PTD2);\r
185 \r
186 // Serial DMA\r
187 sdma_t    *sdma0;\r
188 sdma_t    *sdma1;\r
189 sdma_t    *sdma2;\r
190 \r
191 /********\r
192  * Main *\r
193  ********/\r
194 \r
195 void test_tpm_init(void)\r
196 {\r
197         // EXTRG_IN - PTB8 - alt 3\r
198         //            PTC0 - alt 3\r
199         //            PTC6 - alt 3\r
200 \r
201         // Setup System Integration Module\r
202         SIM_Type *sim = SIM;\r
203 \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
210 \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
219 \r
220         sim->SOPT2 |= SIM_SOPT2_TPMSRC(1);\r
221 \r
222         sim->SOPT4  = SIM_SOPT4_TPM1CLKSEL_MASK\r
223                    |  SIM_SOPT4_TPM1CH0SRC(3);\r
224 \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
228 \r
229         //sim->SOPT7 |= SIM_SOPT7_ADC0TRGSEL(TMP_CONF_TRGSEL_EXTRG);\r
230 \r
231         // Setup Port Control\r
232         PORT_Type *port = PORTC;\r
233 \r
234         PORTE->PCR[25] = PORT_PCR_ISF_MASK\r
235                        | PORT_PCR_IRQC(0x1)\r
236                        | PORT_PCR_MUX(3) ;\r
237 \r
238         port->PCR[0]   = PORT_PCR_ISF_MASK\r
239                        | PORT_PCR_IRQC(0x1)\r
240                        | PORT_PCR_MUX(3)\r
241                        | PORT_PCR_PE_MASK;\r
242 \r
243         // Setup Timer/PWM Module\r
244         volatile TPM_Type *tpm = TPM1;\r
245 \r
246         tpm->SC               = TPM_SC_PS(0x7)\r
247                               | TPM_SC_TOF_MASK;\r
248 \r
249         tpm->CNT              = TPM_CNT_COUNT(0);\r
250 \r
251         tpm->MOD              = TPM_CNT_COUNT(0xFFFF);\r
252 \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
257 \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
264 \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
272 \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
278 \r
279         tpm->SC               = TPM_SC_CMOD(1)\r
280                               | TPM_SC_PS(0x7)\r
281                               | TPM_SC_TOF_MASK;\r
282 \r
283         printf("test - %02lx %08lx\r\n", tpm->CONTROLS[1].CnSC, tpm->CONTROLS[1].CnV); wait(0.1);\r
284 }\r
285 \r
286 void test_tpm_run(void)\r
287 {\r
288         //static DigitalIn pin(PTC0);\r
289         //static DigitalIn pin(PTC2);\r
290         static int pin = 0;\r
291 \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
298 }\r
299 \r
300 void test_pit_init(void)\r
301 {\r
302         //printf("test_pit_init\r\n");\r
303 \r
304         // Enable\r
305         SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;\r
306         PIT->MCR    = 0;\r
307 \r
308         // Channel 0\r
309         PIT->CHANNEL[0].LDVAL = 0xFFFFFFFF;\r
310         PIT->CHANNEL[0].TCTRL = 0;\r
311 \r
312         // Channel 1\r
313         PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;\r
314         PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK;\r
315 \r
316         // Start timers\r
317         PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;\r
318         PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;\r
319 \r
320 }\r
321 \r
322 void test_pit_run(void)\r
323 {\r
324         register volatile uint32_t *tmh asm("r4") = &PIT->LTMR64H;\r
325         register volatile uint32_t *tml asm("r5") = &PIT->LTMR64L;\r
326 \r
327         register uint32_t hi0 asm("r0"), lo0 asm("r1");\r
328         register uint32_t hi1 asm("r2"), lo1 asm("r3");\r
329 \r
330         asm("ldr %0, [%4]\n\t" // Two clocks per load\r
331             "ldr %1, [%5]\n\t"\r
332             "ldr %2, [%4]\n\t"\r
333             "ldr %3, [%5]\n\t"\r
334             : "=r"(hi0), "=r"(lo0), "=r"(hi1), "=r"(lo1)\r
335             :  "r"(tmh),  "r"(tml));\r
336 \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
340 \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
345 }\r
346 \r
347 void test_uart(void)\r
348 {\r
349         char xmt[32] = "hello, world";\r
350         char rcv[32] = {};\r
351 \r
352         sdma_write(sdma1, xmt, strlen(xmt));\r
353         sdma_flush(sdma1);\r
354 \r
355         for (int i = 0; xmt[i]; i++)\r
356                 rcv[i] = uart2.getc();\r
357 \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
362 }\r
363 \r
364 void test_leds(void)\r
365 {\r
366         led1 = 1; led2 = 0; wait(0.1);\r
367         led1 = 0; led2 = 1; wait(0.1);\r
368 }\r
369 \r
370 int main(int argc, char **argv)\r
371 {\r
372         uart0.baud(115200);\r
373         uart1.baud(115200);\r
374         uart2.baud(115200);\r
375 \r
376         sdma1 = sdma_open(SDMA_UART1, SDMA_CHANNEL1);\r
377         sdma2 = sdma_open(SDMA_UART2, SDMA_CHANNEL2);\r
378 \r
379         test_uart();\r
380         //test_leds();\r
381         test_pit_init();\r
382         //test_tpm_init();\r
383 \r
384         while (1) {\r
385                 test_uart();\r
386                 //test_leds();\r
387                 //test_pit_run();\r
388                 //test_tpm_run();\r
389         }\r
390 }\r