]> Pileus Git - ~andy/csm213a-hw/commitdiff
Fix newlines
authorAndy Spencer <andy753421@gmail.com>
Sat, 15 Mar 2014 22:21:15 +0000 (22:21 +0000)
committerAndy Spencer <andy753421@gmail.com>
Sat, 15 Mar 2014 22:21:15 +0000 (22:21 +0000)
hw2/examples.cpp
hw2/serial_dma.c
hw2/serial_irq.c
hw2/timer_dma.c

index 5f95a858603eca0d96025bf870042809f6d2e578..f419e6dc8326798a030d3fea8ca9c61bbe203f4e 100644 (file)
-#include "mbed.h"\r
-#include "serial_dma.h"\r
-#include "timer_dma.h"\r
-\r
-/**\r
- *\r
- * Only port A, C, and D can do aysnc DMA (p. 67)\r
- *\r
- * DMA Channel Allocation:\r
- *     Ch  Trigger    Description\r
- *     0   gpio       timestamp (async event)\r
- *     1   uart1      transmit\r
- *     2   uart2 tx   timestamp (time sync xmt)\r
- *     3   uart2 rx   timestamp (time sync rcv)\r
- *\r
- * Uart Sources:\r
- *      UART 0     UART 1     UART 2\r
- *     xmt  rcv   xmt  rcv   xmt  rcv\r
- *     ---  ---   ---  ---   ---  ---\r
- *     A2   A1  --A19  A18-- -    -\r
- *     A14  A15   -    -     -    -\r
- *     B17  B16   -    -     -    -\r
- *     -    -   **C4   C3--  -    -\r
- *     D7   D6    -    -   **D3/3 D2/3** <<<\r
- *     -    -     -    -   **D5/3 D4/3**\r
- *     E20  E21   E0   E1    E16  E17\r
- *     -    -     -    -     E22  E23\r
- *\r
- * Pinout\r
- *     A1    B18        E30  C1\r
- *     A2    B19        B20  C2\r
- *     D3    C0         E23  B3\r
- *     A12   C4         E22  B2\r
- *     A4    C6         E21  B1\r
- *     A5    C7         E20  B0\r
- *     C8    C10\r
- *     C9    C11        E2   P5-9V\r
- *                      E3   GND\r
- *     A13   C13        E6   GND\r
- *     D2    C16        E16  P5V-USB\r
- *     D4    A7         E17  P3V3\r
- *     D6    A6         E18  RST\r
- *     D7    A14        E19  P3V3\r
- *     D5    A15        E31  SDA/D5\r
- *     GND   A15\r
- *     VREFH A17\r
- *     E0    B9\r
- *     E1    --\r
- */\r
-\r
-/* Trigger select options */\r
-\r
-#define TMP_CONF_TRGSEL_EXTRG 0x0 // 0b0000 External trigger pin input (EXTRG_IN)\r
-#define TMP_CONF_TRGSEL_CMP0  0x1 // 0b0001 CMP0 output\r
-#define TMP_CONF_TRGSEL_PIT0  0x4 // 0b0100 PIT trigger 0\r
-#define TMP_CONF_TRGSEL_PIT1  0x5 // 0b0101 PIT trigger 1\r
-#define TMP_CONF_TRGSEL_TPM0  0x8 // 0b1000 TPM0 overflow\r
-#define TMP_CONF_TRGSEL_TPM1  0x9 // 0b1001 TPM1 overflow\r
-#define TMP_CONF_TRGSEL_TPM2  0xA // 0b1010 TPM2 overflow\r
-#define TMP_CONF_TRGSEL_RTCA  0xC // 0b1100 RTC alarm\r
-#define TMP_CONF_TRGSEL_RTCS  0xD // 0b1101 RTC seconds\r
-#define TMP_CONF_TRGSEL_LPTMR 0xE // 0b1110 LPTMR trigger\r
-\r
-/********************\r
- * Data definitions *\r
- ********************/\r
-\r
-// LEDs\r
-extern DigitalOut led1;\r
-extern DigitalOut led2;\r
-\r
-// UARTs\r
-extern Serial     uart0;\r
-extern Serial     uart1;\r
-extern Serial     uart2;\r
-\r
-// Serial DMA\r
-extern sdma_t    *sdma0;\r
-extern sdma_t    *sdma1;\r
-extern sdma_t    *sdma2;\r
-\r
-// Timer DMA\r
-extern tdma_t    *tdma0;\r
-extern tdma_t    *tdma1;\r
-extern tdma_t    *tdma2;\r
-extern tdma_t    *tdma3;\r
-\r
-/********\r
- * Main *\r
- ********/\r
-\r
-void test_tpm_init(void)\r
-{\r
-       // EXTRG_IN - PTB8 - alt 3\r
-       //            PTC0 - alt 3\r
-       //            PTC6 - alt 3\r
-\r
-       // Setup System Integration Module\r
-       SIM_Type *sim = SIM;\r
-\r
-       sim->SCGC5 |= SIM_SCGC5_PORTA_MASK\r
-                  |  SIM_SCGC5_PORTB_MASK\r
-                  |  SIM_SCGC5_PORTC_MASK\r
-                  |  SIM_SCGC5_PORTD_MASK\r
-                  |  SIM_SCGC5_PORTE_MASK\r
-                  |  SIM_SCGC5_LPTMR_MASK;\r
-\r
-       sim->SCGC6 |= SIM_SCGC6_TPM0_MASK\r
-                  |  SIM_SCGC6_TPM1_MASK\r
-                  |  SIM_SCGC6_TPM2_MASK\r
-                  |  SIM_SCGC6_DAC0_MASK\r
-                  |  SIM_SCGC6_ADC0_MASK\r
-                  |  SIM_SCGC6_PIT_MASK\r
-                  |  SIM_SCGC6_DMAMUX_MASK\r
-                  |  SIM_SCGC6_RTC_MASK;\r
-\r
-       sim->SOPT2 |= SIM_SOPT2_TPMSRC(1);\r
-\r
-       sim->SOPT4  = SIM_SOPT4_TPM1CLKSEL_MASK\r
-                  |  SIM_SOPT4_TPM1CH0SRC(3);\r
-\r
-       printf("SOPT2:%08lx SCGC5:%08lx SCGC6:%08lx\r\n",\r
-                       sim->SOPT2, sim->SCGC5, sim->SCGC6);\r
-       //SOPT2:05010000 SCGC5:00003f83 SCGC6:07800001\r
-\r
-       //sim->SOPT7 |= SIM_SOPT7_ADC0TRGSEL(TMP_CONF_TRGSEL_EXTRG);\r
-\r
-       // Setup Port Control\r
-       PORT_Type *port = PORTC;\r
-\r
-       PORTE->PCR[25] = PORT_PCR_ISF_MASK\r
-                      | PORT_PCR_IRQC(0x1)\r
-                      | PORT_PCR_MUX(3) ;\r
-\r
-       port->PCR[0]   = PORT_PCR_ISF_MASK\r
-                      | PORT_PCR_IRQC(0x1)\r
-                      | PORT_PCR_MUX(3)\r
-                      | PORT_PCR_PE_MASK;\r
-\r
-       // Setup Timer/PWM Module\r
-       volatile TPM_Type *tpm = TPM1;\r
-\r
-       tpm->SC               = TPM_SC_PS(0x7)\r
-                             | TPM_SC_TOF_MASK;\r
-\r
-       tpm->CNT              = TPM_CNT_COUNT(0);\r
-\r
-       tpm->MOD              = TPM_CNT_COUNT(0xFFFF);\r
-\r
-       tpm->CONTROLS[1].CnV  = 0x1234;\r
-       tpm->CONTROLS[1].CnSC = TPM_CnSC_CHF_MASK\r
-                             | TPM_CnSC_CHIE_MASK\r
-                             | TPM_CnSC_ELSA_MASK;\r
-\r
-       //tpm->CONTROLS[0].CnSC = TPM_CnSC_CHF_MASK\r
-       //                    | TPM_CnSC_CHIE_MASK\r
-       //                    | TPM_CnSC_MSB_MASK\r
-       //                    | TPM_CnSC_MSA_MASK\r
-       //                    | TPM_CnSC_ELSB_MASK\r
-       //                    | TPM_CnSC_ELSA_MASK;\r
-\r
-       tpm->STATUS           = TPM_STATUS_CH0F_MASK\r
-                              | TPM_STATUS_CH1F_MASK\r
-                              | TPM_STATUS_CH2F_MASK\r
-                              | TPM_STATUS_CH3F_MASK\r
-                              | TPM_STATUS_CH4F_MASK\r
-                              | TPM_STATUS_CH5F_MASK\r
-                              | TPM_STATUS_TOF_MASK;\r
-\r
-       tpm->CONF             = TPM_CONF_TRGSEL(TMP_CONF_TRGSEL_EXTRG)\r
-                             | TPM_CONF_CSOO_MASK\r
-                             | TPM_CONF_CSOT_MASK\r
-                             | TPM_CONF_GTBEEN_MASK\r
-                             | TPM_CONF_DBGMODE_MASK;\r
-\r
-       tpm->SC               = TPM_SC_CMOD(1)\r
-                             | TPM_SC_PS(0x7)\r
-                             | TPM_SC_TOF_MASK;\r
-\r
-       printf("test - %02lx %08lx\r\n", tpm->CONTROLS[1].CnSC, tpm->CONTROLS[1].CnV); wait(0.1);\r
-}\r
-\r
-void test_tpm_run(void)\r
-{\r
-       //static DigitalIn pin(PTC0);\r
-       //static DigitalIn pin(PTC2);\r
-       //static int pin = 0;\r
-\r
-       printf("PTC0:%08lx GPCR:%08lx:%08lx - SC:%04lx CNT:%04lx MOD:%04lx STATUS:%04lx CONF:%08lx - CnSC:%02lx CnV:%04lx\r\n",\r
-                       PORTC->PCR[0], PORTC->GPCHR, PORTC->GPCLR,\r
-                       TPM1->SC, TPM1->CNT, TPM1->MOD, TPM1->STATUS, TPM1->CONF,\r
-                       TPM1->CONTROLS[1].CnSC, TPM1->CONTROLS[1].CnV);\r
-       TPM1->SC     |= TPM_STATUS_TOF_MASK;\r
-       TPM1->STATUS |= TPM_STATUS_TOF_MASK;\r
-}\r
-\r
-void test_pit_init(void)\r
-{\r
-       //printf("test_pit_init\r\n");\r
-\r
-       // Enable\r
-       SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;\r
-       PIT->MCR    = 0;\r
-\r
-       // Channel 0\r
-       PIT->CHANNEL[0].LDVAL = 0xFFFFFFFF;\r
-       PIT->CHANNEL[0].TCTRL = 0;\r
-\r
-       // Channel 1\r
-       PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;\r
-       PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK;\r
-\r
-       // Start timers\r
-       PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;\r
-       PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;\r
-\r
-}\r
-\r
-void test_pit_run(void)\r
-{\r
-       register volatile uint32_t *tmh asm("r4") = &PIT->LTMR64H;\r
-       register volatile uint32_t *tml asm("r5") = &PIT->LTMR64L;\r
-\r
-       register uint32_t hi0 asm("r0"), lo0 asm("r1");\r
-       register uint32_t hi1 asm("r2"), lo1 asm("r3");\r
-\r
-       asm("ldr %0, [%4]\n\t" // Two clocks per load\r
-           "ldr %1, [%5]\n\t"\r
-           "ldr %2, [%4]\n\t"\r
-           "ldr %3, [%5]\n\t"\r
-           : "=r"(hi0), "=r"(lo0), "=r"(hi1), "=r"(lo1)\r
-           :  "r"(tmh),  "r"(tml));\r
-\r
-       uint64_t tm0 = ~((uint64_t)hi0 << 32 | lo0);\r
-       uint64_t tm1 = ~((uint64_t)hi1 << 32 | lo1);\r
-       double   bus = 24E6;   // 24 MHz bus clock\r
-\r
-       printf(" - pit");\r
-       printf("  %08lx:%08lx", (uint32_t)(tm0>>32), (uint32_t)tm0);\r
-       printf("  %08lx:%08lx", (uint32_t)(tm1>>32), (uint32_t)tm1);\r
-       printf("  %08lx",       (uint32_t)(tm1-tm0));\r
-       printf("  %f",          (double)tm0 / bus);\r
-}\r
-\r
-void test_sdma_init(void)\r
-{\r
-       sdma0 = sdma_open(SDMA_UART0, SDMA_CHANNEL0, SDMA_CHANNEL1);\r
-       sdma1 = sdma_open(SDMA_UART1, SDMA_CHANNEL0, SDMA_CHANNEL1);\r
-       sdma2 = sdma_open(SDMA_UART2, SDMA_CHANNEL2, SDMA_CHANNEL3);\r
-\r
-       sdma_pinmap(sdma1, PTE0, PTE1);\r
-       sdma_pinmap(sdma2, PTD3, PTD2);\r
-}\r
-\r
-void test_sdma_run(void)\r
-{\r
-       char xmt[32] = "hello, world";\r
-       char rcv[32] = {};\r
-\r
-       uint64_t tm1, tm2;\r
-\r
-       sdma_write(sdma1, xmt, strlen(xmt));\r
-       sdma_flush(sdma1, &tm1);\r
-\r
-       sdma_read(sdma2, rcv, strlen(xmt));\r
-       sdma_wait(sdma2, &tm2);\r
-\r
-       printf("send: [%s] -> [%s] ", xmt, rcv);\r
-       printf("time: %08lx / %08lx ", (uint32_t)tm1, (uint32_t)tm2);\r
-       printf("tag: dir:%08lx in:%08lx\r\n",\r
-                       FPTD->PDDR, FPTD->PDIR);\r
-\r
-       (void)xmt; (void)rcv;\r
-       (void)tm1; (void)tm2;\r
-}\r
-\r
-void test_tdma_init(void)\r
-{\r
-       tdma_init();\r
-\r
-       tdma0 = tdma_open(TDMA_CHAN0, 3, PTA1, PullNone);\r
-       tdma1 = tdma_open(TDMA_CHAN1, 3, PTC1, PullNone);\r
-       tdma2 = tdma_open(TDMA_CHAN2, 3, PTD3, PullUp);\r
-       tdma3 = tdma_open(TDMA_CHAN3, 3, PTD2, PullUp);\r
-}\r
-\r
-void test_tdma_run(void)\r
-{\r
-       static uint32_t time0[2];\r
-       static uint32_t time1[2];\r
-       static uint32_t time2[2];\r
-       static uint32_t time3[2];\r
-\r
-       tdma_stamp(tdma0, (uint64_t*)&time0);\r
-       tdma_stamp(tdma1, (uint64_t*)&time1);\r
-       tdma_stamp(tdma2, (uint64_t*)&time2);\r
-       tdma_stamp(tdma3, (uint64_t*)&time3);\r
-\r
-       tdma_start(tdma0);\r
-       tdma_start(tdma1);\r
-       tdma_start(tdma2);\r
-       tdma_start(tdma3);\r
-\r
-       printf(" - timer:");\r
-       printf(" %08lx:%08lx", time0[1], time0[0]);\r
-       printf(" %08lx:%08lx", time1[1], time1[0]);\r
-       printf(" %08lx:%08lx", time2[1], time2[0]);\r
-       printf(" %08lx:%08lx", time3[1], time3[0]);\r
-       //printf(" do:%08lx", FPTD->PDOR);\r
-       //printf(" di:%08lx", FPTD->PDIR);\r
-       //printf(" dd:%08lx", FPTD->PDDR);\r
-}\r
-\r
-void test_leds(void)\r
-{\r
-       led1 = 1; led2 = 0; wait(0.1);\r
-       led1 = 0; led2 = 1; wait(0.1);\r
-}\r
-\r
-void test_main(void)\r
-{\r
-       printf("init\r\n");\r
-       //test_tpm_init();\r
-       //test_pit_init();\r
-       //test_sdma_init();\r
-       //test_tdma_init();\r
-\r
-       printf("run\r\n");\r
-       for (int i = 0; true; i++) {\r
-               printf("%8d", i);\r
-               test_leds();\r
-               //test_tpm_run();\r
-               //test_pit_run();\r
-               //test_sdma_run();\r
-               //test_tdma_run();\r
-               printf("\r\n");\r
-       }\r
-}\r
+#include "mbed.h"
+#include "serial_dma.h"
+#include "timer_dma.h"
+
+/**
+ *
+ * Only port A, C, and D can do aysnc DMA (p. 67)
+ *
+ * DMA Channel Allocation:
+ *     Ch  Trigger    Description
+ *     0   gpio       timestamp (async event)
+ *     1   uart1      transmit
+ *     2   uart2 tx   timestamp (time sync xmt)
+ *     3   uart2 rx   timestamp (time sync rcv)
+ *
+ * Uart Sources:
+ *      UART 0     UART 1     UART 2
+ *     xmt  rcv   xmt  rcv   xmt  rcv
+ *     ---  ---   ---  ---   ---  ---
+ *     A2   A1  --A19  A18-- -    -
+ *     A14  A15   -    -     -    -
+ *     B17  B16   -    -     -    -
+ *     -    -   **C4   C3--  -    -
+ *     D7   D6    -    -   **D3/3 D2/3** <<<
+ *     -    -     -    -   **D5/3 D4/3**
+ *     E20  E21   E0   E1    E16  E17
+ *     -    -     -    -     E22  E23
+ *
+ * Pinout
+ *     A1    B18        E30  C1
+ *     A2    B19        B20  C2
+ *     D3    C0         E23  B3
+ *     A12   C4         E22  B2
+ *     A4    C6         E21  B1
+ *     A5    C7         E20  B0
+ *     C8    C10
+ *     C9    C11        E2   P5-9V
+ *                      E3   GND
+ *     A13   C13        E6   GND
+ *     D2    C16        E16  P5V-USB
+ *     D4    A7         E17  P3V3
+ *     D6    A6         E18  RST
+ *     D7    A14        E19  P3V3
+ *     D5    A15        E31  SDA/D5
+ *     GND   A15
+ *     VREFH A17
+ *     E0    B9
+ *     E1    --
+ */
+
+/* Trigger select options */
+
+#define TMP_CONF_TRGSEL_EXTRG 0x0 // 0b0000 External trigger pin input (EXTRG_IN)
+#define TMP_CONF_TRGSEL_CMP0  0x1 // 0b0001 CMP0 output
+#define TMP_CONF_TRGSEL_PIT0  0x4 // 0b0100 PIT trigger 0
+#define TMP_CONF_TRGSEL_PIT1  0x5 // 0b0101 PIT trigger 1
+#define TMP_CONF_TRGSEL_TPM0  0x8 // 0b1000 TPM0 overflow
+#define TMP_CONF_TRGSEL_TPM1  0x9 // 0b1001 TPM1 overflow
+#define TMP_CONF_TRGSEL_TPM2  0xA // 0b1010 TPM2 overflow
+#define TMP_CONF_TRGSEL_RTCA  0xC // 0b1100 RTC alarm
+#define TMP_CONF_TRGSEL_RTCS  0xD // 0b1101 RTC seconds
+#define TMP_CONF_TRGSEL_LPTMR 0xE // 0b1110 LPTMR trigger
+
+/********************
+ * Data definitions *
+ ********************/
+
+// LEDs
+extern DigitalOut led1;
+extern DigitalOut led2;
+
+// UARTs
+extern Serial     uart0;
+extern Serial     uart1;
+extern Serial     uart2;
+
+// Serial DMA
+extern sdma_t    *sdma0;
+extern sdma_t    *sdma1;
+extern sdma_t    *sdma2;
+
+// Timer DMA
+extern tdma_t    *tdma0;
+extern tdma_t    *tdma1;
+extern tdma_t    *tdma2;
+extern tdma_t    *tdma3;
+
+/********
+ * Main *
+ ********/
+
+void test_tpm_init(void)
+{
+       // EXTRG_IN - PTB8 - alt 3
+       //            PTC0 - alt 3
+       //            PTC6 - alt 3
+
+       // Setup System Integration Module
+       SIM_Type *sim = SIM;
+
+       sim->SCGC5 |= SIM_SCGC5_PORTA_MASK
+                  |  SIM_SCGC5_PORTB_MASK
+                  |  SIM_SCGC5_PORTC_MASK
+                  |  SIM_SCGC5_PORTD_MASK
+                  |  SIM_SCGC5_PORTE_MASK
+                  |  SIM_SCGC5_LPTMR_MASK;
+
+       sim->SCGC6 |= SIM_SCGC6_TPM0_MASK
+                  |  SIM_SCGC6_TPM1_MASK
+                  |  SIM_SCGC6_TPM2_MASK
+                  |  SIM_SCGC6_DAC0_MASK
+                  |  SIM_SCGC6_ADC0_MASK
+                  |  SIM_SCGC6_PIT_MASK
+                  |  SIM_SCGC6_DMAMUX_MASK
+                  |  SIM_SCGC6_RTC_MASK;
+
+       sim->SOPT2 |= SIM_SOPT2_TPMSRC(1);
+
+       sim->SOPT4  = SIM_SOPT4_TPM1CLKSEL_MASK
+                  |  SIM_SOPT4_TPM1CH0SRC(3);
+
+       printf("SOPT2:%08lx SCGC5:%08lx SCGC6:%08lx\r\n",
+                       sim->SOPT2, sim->SCGC5, sim->SCGC6);
+       //SOPT2:05010000 SCGC5:00003f83 SCGC6:07800001
+
+       //sim->SOPT7 |= SIM_SOPT7_ADC0TRGSEL(TMP_CONF_TRGSEL_EXTRG);
+
+       // Setup Port Control
+       PORT_Type *port = PORTC;
+
+       PORTE->PCR[25] = PORT_PCR_ISF_MASK
+                      | PORT_PCR_IRQC(0x1)
+                      | PORT_PCR_MUX(3) ;
+
+       port->PCR[0]   = PORT_PCR_ISF_MASK
+                      | PORT_PCR_IRQC(0x1)
+                      | PORT_PCR_MUX(3)
+                      | PORT_PCR_PE_MASK;
+
+       // Setup Timer/PWM Module
+       volatile TPM_Type *tpm = TPM1;
+
+       tpm->SC               = TPM_SC_PS(0x7)
+                             | TPM_SC_TOF_MASK;
+
+       tpm->CNT              = TPM_CNT_COUNT(0);
+
+       tpm->MOD              = TPM_CNT_COUNT(0xFFFF);
+
+       tpm->CONTROLS[1].CnV  = 0x1234;
+       tpm->CONTROLS[1].CnSC = TPM_CnSC_CHF_MASK
+                             | TPM_CnSC_CHIE_MASK
+                             | TPM_CnSC_ELSA_MASK;
+
+       //tpm->CONTROLS[0].CnSC = TPM_CnSC_CHF_MASK
+       //                    | TPM_CnSC_CHIE_MASK
+       //                    | TPM_CnSC_MSB_MASK
+       //                    | TPM_CnSC_MSA_MASK
+       //                    | TPM_CnSC_ELSB_MASK
+       //                    | TPM_CnSC_ELSA_MASK;
+
+       tpm->STATUS           = TPM_STATUS_CH0F_MASK
+                              | TPM_STATUS_CH1F_MASK
+                              | TPM_STATUS_CH2F_MASK
+                              | TPM_STATUS_CH3F_MASK
+                              | TPM_STATUS_CH4F_MASK
+                              | TPM_STATUS_CH5F_MASK
+                              | TPM_STATUS_TOF_MASK;
+
+       tpm->CONF             = TPM_CONF_TRGSEL(TMP_CONF_TRGSEL_EXTRG)
+                             | TPM_CONF_CSOO_MASK
+                             | TPM_CONF_CSOT_MASK
+                             | TPM_CONF_GTBEEN_MASK
+                             | TPM_CONF_DBGMODE_MASK;
+
+       tpm->SC               = TPM_SC_CMOD(1)
+                             | TPM_SC_PS(0x7)
+                             | TPM_SC_TOF_MASK;
+
+       printf("test - %02lx %08lx\r\n", tpm->CONTROLS[1].CnSC, tpm->CONTROLS[1].CnV); wait(0.1);
+}
+
+void test_tpm_run(void)
+{
+       //static DigitalIn pin(PTC0);
+       //static DigitalIn pin(PTC2);
+       //static int pin = 0;
+
+       printf("PTC0:%08lx GPCR:%08lx:%08lx - SC:%04lx CNT:%04lx MOD:%04lx STATUS:%04lx CONF:%08lx - CnSC:%02lx CnV:%04lx\r\n",
+                       PORTC->PCR[0], PORTC->GPCHR, PORTC->GPCLR,
+                       TPM1->SC, TPM1->CNT, TPM1->MOD, TPM1->STATUS, TPM1->CONF,
+                       TPM1->CONTROLS[1].CnSC, TPM1->CONTROLS[1].CnV);
+       TPM1->SC     |= TPM_STATUS_TOF_MASK;
+       TPM1->STATUS |= TPM_STATUS_TOF_MASK;
+}
+
+void test_pit_init(void)
+{
+       //printf("test_pit_init\r\n");
+
+       // Enable
+       SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;
+       PIT->MCR    = 0;
+
+       // Channel 0
+       PIT->CHANNEL[0].LDVAL = 0xFFFFFFFF;
+       PIT->CHANNEL[0].TCTRL = 0;
+
+       // Channel 1
+       PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;
+       PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK;
+
+       // Start timers
+       PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;
+       PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;
+
+}
+
+void test_pit_run(void)
+{
+       register volatile uint32_t *tmh asm("r4") = &PIT->LTMR64H;
+       register volatile uint32_t *tml asm("r5") = &PIT->LTMR64L;
+
+       register uint32_t hi0 asm("r0"), lo0 asm("r1");
+       register uint32_t hi1 asm("r2"), lo1 asm("r3");
+
+       asm("ldr %0, [%4]\n\t" // Two clocks per load
+           "ldr %1, [%5]\n\t"
+           "ldr %2, [%4]\n\t"
+           "ldr %3, [%5]\n\t"
+           : "=r"(hi0), "=r"(lo0), "=r"(hi1), "=r"(lo1)
+           :  "r"(tmh),  "r"(tml));
+
+       uint64_t tm0 = ~((uint64_t)hi0 << 32 | lo0);
+       uint64_t tm1 = ~((uint64_t)hi1 << 32 | lo1);
+       double   bus = 24E6;   // 24 MHz bus clock
+
+       printf(" - pit");
+       printf("  %08lx:%08lx", (uint32_t)(tm0>>32), (uint32_t)tm0);
+       printf("  %08lx:%08lx", (uint32_t)(tm1>>32), (uint32_t)tm1);
+       printf("  %08lx",       (uint32_t)(tm1-tm0));
+       printf("  %f",          (double)tm0 / bus);
+}
+
+void test_sdma_init(void)
+{
+       sdma0 = sdma_open(SDMA_UART0, SDMA_CHANNEL0, SDMA_CHANNEL1);
+       sdma1 = sdma_open(SDMA_UART1, SDMA_CHANNEL0, SDMA_CHANNEL1);
+       sdma2 = sdma_open(SDMA_UART2, SDMA_CHANNEL2, SDMA_CHANNEL3);
+
+       sdma_pinmap(sdma1, PTE0, PTE1);
+       sdma_pinmap(sdma2, PTD3, PTD2);
+}
+
+void test_sdma_run(void)
+{
+       char xmt[32] = "hello, world";
+       char rcv[32] = {};
+
+       uint64_t tm1, tm2;
+
+       sdma_write(sdma1, xmt, strlen(xmt));
+       sdma_flush(sdma1, &tm1);
+
+       sdma_read(sdma2, rcv, strlen(xmt));
+       sdma_wait(sdma2, &tm2);
+
+       printf("send: [%s] -> [%s] ", xmt, rcv);
+       printf("time: %08lx / %08lx ", (uint32_t)tm1, (uint32_t)tm2);
+       printf("tag: dir:%08lx in:%08lx\r\n",
+                       FPTD->PDDR, FPTD->PDIR);
+
+       (void)xmt; (void)rcv;
+       (void)tm1; (void)tm2;
+}
+
+void test_tdma_init(void)
+{
+       tdma_init();
+
+       tdma0 = tdma_open(TDMA_CHAN0, 3, PTA1, PullNone);
+       tdma1 = tdma_open(TDMA_CHAN1, 3, PTC1, PullNone);
+       tdma2 = tdma_open(TDMA_CHAN2, 3, PTD3, PullUp);
+       tdma3 = tdma_open(TDMA_CHAN3, 3, PTD2, PullUp);
+}
+
+void test_tdma_run(void)
+{
+       static uint32_t time0[2];
+       static uint32_t time1[2];
+       static uint32_t time2[2];
+       static uint32_t time3[2];
+
+       tdma_stamp(tdma0, (uint64_t*)&time0);
+       tdma_stamp(tdma1, (uint64_t*)&time1);
+       tdma_stamp(tdma2, (uint64_t*)&time2);
+       tdma_stamp(tdma3, (uint64_t*)&time3);
+
+       tdma_start(tdma0);
+       tdma_start(tdma1);
+       tdma_start(tdma2);
+       tdma_start(tdma3);
+
+       printf(" - timer:");
+       printf(" %08lx:%08lx", time0[1], time0[0]);
+       printf(" %08lx:%08lx", time1[1], time1[0]);
+       printf(" %08lx:%08lx", time2[1], time2[0]);
+       printf(" %08lx:%08lx", time3[1], time3[0]);
+       //printf(" do:%08lx", FPTD->PDOR);
+       //printf(" di:%08lx", FPTD->PDIR);
+       //printf(" dd:%08lx", FPTD->PDDR);
+}
+
+void test_leds(void)
+{
+       led1 = 1; led2 = 0; wait(0.1);
+       led1 = 0; led2 = 1; wait(0.1);
+}
+
+void test_main(void)
+{
+       printf("init\r\n");
+       //test_tpm_init();
+       //test_pit_init();
+       //test_sdma_init();
+       //test_tdma_init();
+
+       printf("run\r\n");
+       for (int i = 0; true; i++) {
+               printf("%8d", i);
+               test_leds();
+               //test_tpm_run();
+               //test_pit_run();
+               //test_sdma_run();
+               //test_tdma_run();
+               printf("\r\n");
+       }
+}
index 26987769119b68a7419a097e839112b6426f41c8..bbb1d6bf5e39e144522b92a0d1284c6ce584c64f 100644 (file)
-#include <MKL46Z4.h>\r
-\r
-#include <stdint.h>\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-\r
-#include "serial_dma.h"\r
-\r
-/* Defines */\r
-#define SDMA_NUM  2\r
-#define SDMA_LEN  1024\r
-\r
-enum {\r
-       SDMA_REQ_U0RX = 2,\r
-       SDMA_REQ_U0TX = 3,\r
-       SDMA_REQ_U1RX = 4,\r
-       SDMA_REQ_U1TX = 5,\r
-       SDMA_REQ_U2RX = 6,\r
-       SDMA_REQ_U2TX = 7,\r
-       SDMA_REQ_PTA  = 49,\r
-       SDMA_REQ_PTC  = 51,\r
-       SDMA_REQ_PTD  = 52,\r
-       SDMA_REQ_ON0  = 60,\r
-       SDMA_REQ_ON1  = 61,\r
-       SDMA_REQ_ON2  = 62,\r
-       SDMA_REQ_ON3  = 63,\r
-};\r
-\r
-/* Port structure */\r
-struct sdma_t {\r
-       /* DMA channel */\r
-       struct {\r
-               uint32_t sar; // offset 0x00, Source Address Register\r
-               uint32_t dar; // offset 0x04, Destination Address Register\r
-               uint32_t dsr; // offset 0x08, DMA Status Register / Byte Count Register\r
-               uint32_t dcr; // offset 0x0C, DMA Control Register\r
-       } *dma_xmt, *dma_rcv;\r
-\r
-       /* DMA mux */\r
-       struct {\r
-               uint8_t  cfg; // offset 0x00, Channel Configuration register\r
-       } *mux_xmt, *mux_rcv;\r
-\r
-       /* Pin names */\r
-       struct {\r
-               uint32_t pcr; // offset 0x00, Pin Control register\r
-       } *pin_xmt, *pin_rcv;\r
-\r
-       /* UART */\r
-       struct {\r
-               uint8_t  bdh;    // offset 0x00, Baud Rate Register High\r
-               uint8_t  bdl;    // offset 0x01, Baud Rate Register Low\r
-               uint8_t  c1;     // offset 0x02, Control Register 1\r
-               uint8_t  c2;     // offset 0x03, Control Register 2\r
-               uint8_t  s1;     // offset 0x04, Status Register 1\r
-               uint8_t  s2;     // offset 0x05, Status Register 2\r
-               uint8_t  c3;     // offset 0x06, Control Register 3\r
-               uint8_t  d;      // offset 0x07, Data Register\r
-       } *uart;\r
-\r
-       /* Data buffering */\r
-       int      index;\r
-       int      length[SDMA_NUM];\r
-       uint8_t  queue[SDMA_NUM][SDMA_LEN];\r
-\r
-       /* Timestamping */\r
-       uint32_t time_xmt[2];\r
-       uint32_t time_rcv[2];\r
-\r
-       /* Error logging */\r
-       int      stuck;\r
-       int      full;\r
-};\r
-\r
-/* DMA Request Sources */\r
-static int sdma_req_rx[] = {\r
-       [SDMA_UART0] SDMA_REQ_U0RX,\r
-       [SDMA_UART1] SDMA_REQ_U1RX,\r
-       [SDMA_UART2] SDMA_REQ_U2RX,\r
-};\r
-static int sdma_req_tx[] = {\r
-       [SDMA_UART0] SDMA_REQ_U0TX,\r
-       [SDMA_UART1] SDMA_REQ_U1TX,\r
-       [SDMA_UART2] SDMA_REQ_U2TX,\r
-};\r
-static int sdma_uart[] = {\r
-       [SDMA_UART0] UART0_BASE,\r
-       [SDMA_UART1] UART1_BASE,\r
-       [SDMA_UART2] UART2_BASE,\r
-};\r
-\r
-/* Port data */\r
-static sdma_t sdma_ports[SDMA_NUM_UART];\r
-\r
-/* DMA Functions */\r
-sdma_t *sdma_open(sdma_uart_t uart, sdma_dma_t tx_chan, sdma_dma_t rx_chan)\r
-{\r
-       int rxreq = sdma_req_rx[uart]; (void)rxreq;\r
-       int txreq = sdma_req_tx[uart]; (void)txreq;\r
-\r
-       // Setup port\r
-       sdma_t *port = &sdma_ports[uart];\r
-\r
-       port->uart      = (void*)sdma_uart[uart];\r
-       port->dma_xmt   = (void*)&DMA0->DMA[tx_chan];\r
-       port->dma_rcv   = (void*)&DMA0->DMA[rx_chan];\r
-       port->mux_xmt   = (void*)&DMAMUX0->CHCFG[tx_chan];\r
-       port->mux_rcv   = (void*)&DMAMUX0->CHCFG[rx_chan];\r
-\r
-       // Enable DMA Cock\r
-       SIM->SCGC5     |= SIM_SCGC5_PORTA_MASK;\r
-       SIM->SCGC5     |= SIM_SCGC5_PORTC_MASK;\r
-       SIM->SCGC5     |= SIM_SCGC5_PORTD_MASK;\r
-       SIM->SCGC6     |= SIM_SCGC6_DMAMUX_MASK;\r
-       SIM->SCGC7     |= SIM_SCGC7_DMA_MASK;\r
-\r
-       // Reset channel\r
-       port->dma_xmt->dsr  = DMA_DSR_BCR_DONE_MASK;\r
-\r
-       // Configure DMA transfer\r
-       port->dma_xmt->dar  = (uint32_t)&port->uart->d;\r
-       port->dma_xmt->dcr  = DMA_DCR_CS_MASK\r
-                           | DMA_DCR_SINC_MASK\r
-                           | DMA_DCR_SSIZE(1)\r
-                           | DMA_DCR_DSIZE(1)\r
-                           | DMA_DCR_D_REQ_MASK;\r
-\r
-       // Configure DMA Mux\r
-       port->mux_xmt->cfg  = DMAMUX_CHCFG_SOURCE(txreq)\r
-                           | DMAMUX_CHCFG_ENBL_MASK;\r
-\r
-       // Configure UART for DMA Channel 0\r
-       switch (uart) {\r
-               case SDMA_UART0:\r
-                       UART0->C5 |= UART0_C5_TDMAE_MASK;\r
-                       break;\r
-\r
-               case SDMA_UART1:\r
-                       UART1->C2 = UART_C2_TIE_MASK\r
-                                 | UART_C2_TE_MASK\r
-                                 | UART_C2_RE_MASK;\r
-                       UART1->C4 = UART_C4_TDMAS_MASK;\r
-                       break;\r
-\r
-               case SDMA_UART2:\r
-                       UART2->C2 = UART_C2_TIE_MASK\r
-                                 | UART_C2_TE_MASK\r
-                                 | UART_C2_RE_MASK;\r
-                       UART2->C4 = UART_C4_TDMAS_MASK;\r
-                       break;\r
-       }\r
-       return port;\r
-}\r
-\r
-/* Map port to pins - for now, just save for timing */\r
-void sdma_pinmap(sdma_t *port, PinName tx, PinName rx)\r
-{\r
-       port->pin_xmt = (void*)(PORTA_BASE+tx);\r
-       port->pin_rcv = (void*)(PORTA_BASE+rx);\r
-}\r
-\r
-/* Write binary data out the DMA output queue */\r
-void sdma_write(sdma_t *port, void *data, int len)\r
-{\r
-       if (port->length[port->index] + len > SDMA_LEN) {\r
-               port->full++;\r
-       } else {\r
-               int   pos = port->length[port->index];\r
-               void *dst = &port->queue[port->index][pos];\r
-               memcpy(dst, data, len);\r
-               port->length[port->index] += len;\r
-       }\r
-}\r
-\r
-/* Read binary data from the channel */\r
-void sdma_read(sdma_t *port, void *data, int len)\r
-{\r
-       for (int i = 0; i < len; i++) {\r
-               // wait for byte\r
-               while (!(port->uart->s1 & UART_S1_RDRF_MASK))\r
-                       if (port->uart->s1 & UART_S1_OR_MASK)\r
-                               port->uart->s1 |= UART_S1_OR_MASK;\r
-\r
-               // read the byte\r
-               ((uint8_t*)data)[i] = port->uart->d;\r
-       }\r
-}\r
-\r
-/* Trigger DMA transmit of the current output queue\r
- * and swap buffers so we can write into unused space */\r
-void sdma_flush(sdma_t *port, uint64_t *time)\r
-{\r
-       if (port->length[port->index] == 0)\r
-               return;\r
-\r
-       // Wait for transmit complete\r
-       while (port->dma_xmt->dsr & DMA_DSR_BCR_BCR_MASK)\r
-               port->stuck++;\r
-\r
-       // Reset channel\r
-       port->dma_xmt->dsr  = DMA_DSR_BCR_DONE_MASK;\r
-\r
-       // Set source address and length\r
-       port->dma_xmt->sar  = (uint32_t)&port->queue[port->index];\r
-       port->dma_xmt->dsr  = DMA_DSR_BCR_BCR(port->length[port->index]);\r
-\r
-       // Enable DMA transmit\r
-       port->dma_xmt->dcr |= DMA_DCR_ERQ_MASK;\r
-\r
-       // Swap buffers\r
-       port->length[port->index] = 0;\r
-       port->index = (port->index + 1) % SDMA_NUM;\r
-}\r
-\r
-/* Wait for DMA receive complete */\r
-void sdma_wait(sdma_t *port, uint64_t *time)\r
-{\r
-       int req = (void*)port->pin_rcv > (void*)PORTD ? SDMA_REQ_PTD :\r
-                 (void*)port->pin_rcv > (void*)PORTC ? SDMA_REQ_PTC :\r
-                 (void*)port->pin_rcv > (void*)PORTA ? SDMA_REQ_PTA : 0;\r
-\r
-       // Reset channel\r
-       port->dma_rcv->dsr = DMA_DSR_BCR_DONE_MASK;\r
-\r
-       // Configure channel\r
-       port->dma_rcv->dcr  = DMA_DCR_SINC_MASK\r
-                           | DMA_DCR_DINC_MASK\r
-                           | DMA_DCR_SSIZE(0)\r
-                           | DMA_DCR_DSIZE(0)\r
-                           | DMA_DCR_D_REQ_MASK;\r
-\r
-       // Setup muxing\r
-       port->mux_rcv->cfg  = DMAMUX_CHCFG_SOURCE(req)\r
-                           | DMAMUX_CHCFG_ENBL_MASK;\r
-\r
-       // Set address and size\r
-       port->dma_rcv->sar  = (uint32_t)&PIT->LTMR64H;\r
-       port->dma_rcv->dar  = (uint32_t)&port->time_rcv;\r
-       port->dma_rcv->dsr  = DMA_DSR_BCR_BCR(sizeof(uint64_t));\r
-\r
-       // Enable DMA transmit\r
-       port->dma_rcv->dcr |= DMA_DCR_ERQ_MASK;\r
-\r
-       // set pin to generate DMA req\r
-       port->pin_rcv->pcr  = PORT_PCR_ISF_MASK\r
-                           | PORT_PCR_IRQC(1)\r
-                           | PORT_PCR_MUX(3)\r
-                           | PORT_PCR_PE_MASK;\r
-\r
-       // Wait for transmit complete\r
-       while ((port->dma_rcv->dsr & DMA_DSR_BCR_BCR_MASK))\r
-               port->stuck++;\r
-\r
-       // Save recv time\r
-       *time = ((uint64_t)~port->time_rcv[0]) << 32\r
-             | ((uint64_t)~port->time_rcv[1]) << 0;\r
-\r
-       // pcr:00030302 dsr:41000008\r
-       printf(" - pcr:%08lx dsr:%08lx time:%08lx:%08lx",\r
-               port->pin_rcv->pcr, port->dma_rcv->dsr,\r
-               (uint32_t)(*time >> 32), (uint32_t)*time);\r
-}\r
-\r
-/* Write ASCII data to the output queue */\r
-void sdma_vprintf(sdma_t *port, const char *fmt, va_list ap)\r
-{\r
-       int   pos = port->length[port->index];\r
-       void *dst = &port->queue[port->index][pos];\r
-       port->length[port->index] +=\r
-               vsnprintf((char*)dst, SDMA_LEN-pos, fmt, ap);\r
-}\r
-\r
-void sdma_printf(sdma_t *port, const char *fmt, ...)\r
-{\r
-       va_list ap;\r
-       va_start(ap, fmt);\r
-       sdma_vprintf(port, fmt, ap);\r
-       va_end(ap);\r
-}\r
+#include <MKL46Z4.h>
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "serial_dma.h"
+
+/* Defines */
+#define SDMA_NUM  2
+#define SDMA_LEN  1024
+
+enum {
+       SDMA_REQ_U0RX = 2,
+       SDMA_REQ_U0TX = 3,
+       SDMA_REQ_U1RX = 4,
+       SDMA_REQ_U1TX = 5,
+       SDMA_REQ_U2RX = 6,
+       SDMA_REQ_U2TX = 7,
+       SDMA_REQ_PTA  = 49,
+       SDMA_REQ_PTC  = 51,
+       SDMA_REQ_PTD  = 52,
+       SDMA_REQ_ON0  = 60,
+       SDMA_REQ_ON1  = 61,
+       SDMA_REQ_ON2  = 62,
+       SDMA_REQ_ON3  = 63,
+};
+
+/* Port structure */
+struct sdma_t {
+       /* DMA channel */
+       struct {
+               uint32_t sar; // offset 0x00, Source Address Register
+               uint32_t dar; // offset 0x04, Destination Address Register
+               uint32_t dsr; // offset 0x08, DMA Status Register / Byte Count Register
+               uint32_t dcr; // offset 0x0C, DMA Control Register
+       } *dma_xmt, *dma_rcv;
+
+       /* DMA mux */
+       struct {
+               uint8_t  cfg; // offset 0x00, Channel Configuration register
+       } *mux_xmt, *mux_rcv;
+
+       /* Pin names */
+       struct {
+               uint32_t pcr; // offset 0x00, Pin Control register
+       } *pin_xmt, *pin_rcv;
+
+       /* UART */
+       struct {
+               uint8_t  bdh;    // offset 0x00, Baud Rate Register High
+               uint8_t  bdl;    // offset 0x01, Baud Rate Register Low
+               uint8_t  c1;     // offset 0x02, Control Register 1
+               uint8_t  c2;     // offset 0x03, Control Register 2
+               uint8_t  s1;     // offset 0x04, Status Register 1
+               uint8_t  s2;     // offset 0x05, Status Register 2
+               uint8_t  c3;     // offset 0x06, Control Register 3
+               uint8_t  d;      // offset 0x07, Data Register
+       } *uart;
+
+       /* Data buffering */
+       int      index;
+       int      length[SDMA_NUM];
+       uint8_t  queue[SDMA_NUM][SDMA_LEN];
+
+       /* Timestamping */
+       uint32_t time_xmt[2];
+       uint32_t time_rcv[2];
+
+       /* Error logging */
+       int      stuck;
+       int      full;
+};
+
+/* DMA Request Sources */
+static int sdma_req_rx[] = {
+       [SDMA_UART0] SDMA_REQ_U0RX,
+       [SDMA_UART1] SDMA_REQ_U1RX,
+       [SDMA_UART2] SDMA_REQ_U2RX,
+};
+static int sdma_req_tx[] = {
+       [SDMA_UART0] SDMA_REQ_U0TX,
+       [SDMA_UART1] SDMA_REQ_U1TX,
+       [SDMA_UART2] SDMA_REQ_U2TX,
+};
+static int sdma_uart[] = {
+       [SDMA_UART0] UART0_BASE,
+       [SDMA_UART1] UART1_BASE,
+       [SDMA_UART2] UART2_BASE,
+};
+
+/* Port data */
+static sdma_t sdma_ports[SDMA_NUM_UART];
+
+/* DMA Functions */
+sdma_t *sdma_open(sdma_uart_t uart, sdma_dma_t tx_chan, sdma_dma_t rx_chan)
+{
+       int rxreq = sdma_req_rx[uart]; (void)rxreq;
+       int txreq = sdma_req_tx[uart]; (void)txreq;
+
+       // Setup port
+       sdma_t *port = &sdma_ports[uart];
+
+       port->uart      = (void*)sdma_uart[uart];
+       port->dma_xmt   = (void*)&DMA0->DMA[tx_chan];
+       port->dma_rcv   = (void*)&DMA0->DMA[rx_chan];
+       port->mux_xmt   = (void*)&DMAMUX0->CHCFG[tx_chan];
+       port->mux_rcv   = (void*)&DMAMUX0->CHCFG[rx_chan];
+
+       // Enable DMA Cock
+       SIM->SCGC5     |= SIM_SCGC5_PORTA_MASK;
+       SIM->SCGC5     |= SIM_SCGC5_PORTC_MASK;
+       SIM->SCGC5     |= SIM_SCGC5_PORTD_MASK;
+       SIM->SCGC6     |= SIM_SCGC6_DMAMUX_MASK;
+       SIM->SCGC7     |= SIM_SCGC7_DMA_MASK;
+
+       // Reset channel
+       port->dma_xmt->dsr  = DMA_DSR_BCR_DONE_MASK;
+
+       // Configure DMA transfer
+       port->dma_xmt->dar  = (uint32_t)&port->uart->d;
+       port->dma_xmt->dcr  = DMA_DCR_CS_MASK
+                           | DMA_DCR_SINC_MASK
+                           | DMA_DCR_SSIZE(1)
+                           | DMA_DCR_DSIZE(1)
+                           | DMA_DCR_D_REQ_MASK;
+
+       // Configure DMA Mux
+       port->mux_xmt->cfg  = DMAMUX_CHCFG_SOURCE(txreq)
+                           | DMAMUX_CHCFG_ENBL_MASK;
+
+       // Configure UART for DMA Channel 0
+       switch (uart) {
+               case SDMA_UART0:
+                       UART0->C5 |= UART0_C5_TDMAE_MASK;
+                       break;
+
+               case SDMA_UART1:
+                       UART1->C2 = UART_C2_TIE_MASK
+                                 | UART_C2_TE_MASK
+                                 | UART_C2_RE_MASK;
+                       UART1->C4 = UART_C4_TDMAS_MASK;
+                       break;
+
+               case SDMA_UART2:
+                       UART2->C2 = UART_C2_TIE_MASK
+                                 | UART_C2_TE_MASK
+                                 | UART_C2_RE_MASK;
+                       UART2->C4 = UART_C4_TDMAS_MASK;
+                       break;
+       }
+       return port;
+}
+
+/* Map port to pins - for now, just save for timing */
+void sdma_pinmap(sdma_t *port, PinName tx, PinName rx)
+{
+       port->pin_xmt = (void*)(PORTA_BASE+tx);
+       port->pin_rcv = (void*)(PORTA_BASE+rx);
+}
+
+/* Write binary data out the DMA output queue */
+void sdma_write(sdma_t *port, void *data, int len)
+{
+       if (port->length[port->index] + len > SDMA_LEN) {
+               port->full++;
+       } else {
+               int   pos = port->length[port->index];
+               void *dst = &port->queue[port->index][pos];
+               memcpy(dst, data, len);
+               port->length[port->index] += len;
+       }
+}
+
+/* Read binary data from the channel */
+void sdma_read(sdma_t *port, void *data, int len)
+{
+       for (int i = 0; i < len; i++) {
+               // wait for byte
+               while (!(port->uart->s1 & UART_S1_RDRF_MASK))
+                       if (port->uart->s1 & UART_S1_OR_MASK)
+                               port->uart->s1 |= UART_S1_OR_MASK;
+
+               // read the byte
+               ((uint8_t*)data)[i] = port->uart->d;
+       }
+}
+
+/* Trigger DMA transmit of the current output queue
+ * and swap buffers so we can write into unused space */
+void sdma_flush(sdma_t *port, uint64_t *time)
+{
+       if (port->length[port->index] == 0)
+               return;
+
+       // Wait for transmit complete
+       while (port->dma_xmt->dsr & DMA_DSR_BCR_BCR_MASK)
+               port->stuck++;
+
+       // Reset channel
+       port->dma_xmt->dsr  = DMA_DSR_BCR_DONE_MASK;
+
+       // Set source address and length
+       port->dma_xmt->sar  = (uint32_t)&port->queue[port->index];
+       port->dma_xmt->dsr  = DMA_DSR_BCR_BCR(port->length[port->index]);
+
+       // Enable DMA transmit
+       port->dma_xmt->dcr |= DMA_DCR_ERQ_MASK;
+
+       // Swap buffers
+       port->length[port->index] = 0;
+       port->index = (port->index + 1) % SDMA_NUM;
+}
+
+/* Wait for DMA receive complete */
+void sdma_wait(sdma_t *port, uint64_t *time)
+{
+       int req = (void*)port->pin_rcv > (void*)PORTD ? SDMA_REQ_PTD :
+                 (void*)port->pin_rcv > (void*)PORTC ? SDMA_REQ_PTC :
+                 (void*)port->pin_rcv > (void*)PORTA ? SDMA_REQ_PTA : 0;
+
+       // Reset channel
+       port->dma_rcv->dsr = DMA_DSR_BCR_DONE_MASK;
+
+       // Configure channel
+       port->dma_rcv->dcr  = DMA_DCR_SINC_MASK
+                           | DMA_DCR_DINC_MASK
+                           | DMA_DCR_SSIZE(0)
+                           | DMA_DCR_DSIZE(0)
+                           | DMA_DCR_D_REQ_MASK;
+
+       // Setup muxing
+       port->mux_rcv->cfg  = DMAMUX_CHCFG_SOURCE(req)
+                           | DMAMUX_CHCFG_ENBL_MASK;
+
+       // Set address and size
+       port->dma_rcv->sar  = (uint32_t)&PIT->LTMR64H;
+       port->dma_rcv->dar  = (uint32_t)&port->time_rcv;
+       port->dma_rcv->dsr  = DMA_DSR_BCR_BCR(sizeof(uint64_t));
+
+       // Enable DMA transmit
+       port->dma_rcv->dcr |= DMA_DCR_ERQ_MASK;
+
+       // set pin to generate DMA req
+       port->pin_rcv->pcr  = PORT_PCR_ISF_MASK
+                           | PORT_PCR_IRQC(1)
+                           | PORT_PCR_MUX(3)
+                           | PORT_PCR_PE_MASK;
+
+       // Wait for transmit complete
+       while ((port->dma_rcv->dsr & DMA_DSR_BCR_BCR_MASK))
+               port->stuck++;
+
+       // Save recv time
+       *time = ((uint64_t)~port->time_rcv[0]) << 32
+             | ((uint64_t)~port->time_rcv[1]) << 0;
+
+       // pcr:00030302 dsr:41000008
+       printf(" - pcr:%08lx dsr:%08lx time:%08lx:%08lx",
+               port->pin_rcv->pcr, port->dma_rcv->dsr,
+               (uint32_t)(*time >> 32), (uint32_t)*time);
+}
+
+/* Write ASCII data to the output queue */
+void sdma_vprintf(sdma_t *port, const char *fmt, va_list ap)
+{
+       int   pos = port->length[port->index];
+       void *dst = &port->queue[port->index][pos];
+       port->length[port->index] +=
+               vsnprintf((char*)dst, SDMA_LEN-pos, fmt, ap);
+}
+
+void sdma_printf(sdma_t *port, const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       sdma_vprintf(port, fmt, ap);
+       va_end(ap);
+}
index 2d4b70d24877d5b1d4445ebe01f85a304bf1bfed..91eb309ccde1fe1994089141eeb04f36984bfec1 100644 (file)
-#include <MKL46Z4.h>\r
-\r
-#include <stdint.h>\r
-#include <stdio.h>\r
-#include "serial_api.h"\r
-#include "serial_irq.h"\r
-#include "timer_dma.h"\r
-\r
-/* Defines */\r
-#define SIRQ_LEN  1024\r
-\r
-/* Port structure */\r
-typedef struct {\r
-       int     rix;\r
-       int     wix;\r
-       uint8_t buf[SIRQ_LEN];\r
-} queue_t;\r
-\r
-struct sirq_t {\r
-       serial_t uart;\r
-       queue_t  xmt;\r
-       queue_t  rcv;\r
-       int      irq;\r
-       int      buffered;\r
-};\r
-\r
-/* Port data */\r
-static sirq_t sirq_ports[SIRQ_NUM_UART];\r
-\r
-/* Receive handler */\r
-void sirq_handler(uint32_t _port, SerialIrq event)\r
-{\r
-       sirq_t *port = (sirq_t *)_port;\r
-\r
-       // Handle transmit\r
-       //   note: mbed seems to call TxIrq even it is not enabled,\r
-       //   so we need to manually prevent transmitting when the\r
-       //   port is set to buffered mode.\r
-       if (event == TxIrq && (port->irq || !port->buffered)) {\r
-               if (port->xmt.rix != port->xmt.wix) {\r
-                       int byte = port->xmt.buf[port->xmt.rix];\r
-                       serial_putc(&port->uart, byte);\r
-                       port->xmt.rix = (port->xmt.rix+1) % SIRQ_LEN;\r
-               } else {\r
-                       serial_irq_set(&port->uart, TxIrq, 0);\r
-                       port->irq = 0;\r
-               }\r
-       }\r
-\r
-       // Handle receive\r
-       if (event == RxIrq) {\r
-               int byte = serial_getc(&port->uart);\r
-               port->rcv.buf[port->rcv.wix] = byte;\r
-               port->rcv.wix = (port->rcv.wix+1) % SIRQ_LEN;\r
-       }\r
-}\r
-\r
-/* Open port */\r
-sirq_t *sirq_open(sirq_uart_t uart, PinName tx, PinName rx, int baud, int buffered)\r
-{\r
-       // Allocate port\r
-       sirq_t *port = &sirq_ports[uart];\r
-\r
-       // Buffered ports only transmit on demand\r
-       port->buffered = buffered;\r
-\r
-       // Configure port\r
-       serial_init(&port->uart, tx, rx);\r
-       serial_baud(&port->uart, baud);\r
-\r
-       // Set IRQ handlers\r
-       serial_irq_handler(&port->uart, sirq_handler, (uint32_t)port);\r
-       serial_irq_set(&port->uart, RxIrq, 1);\r
-\r
-       return port;\r
-}\r
-\r
-/* Write byte to the port */\r
-void sirq_putc(sirq_t *port, int byte)\r
-{\r
-       port->xmt.buf[port->xmt.wix] = byte;\r
-       port->xmt.wix = (port->xmt.wix+1) % SIRQ_LEN;\r
-       if (!port->buffered)\r
-               sirq_transmit(port);\r
-}\r
-\r
-/* Read byte from the port */\r
-int sirq_getc(sirq_t *port)\r
-{\r
-       int byte = 0;\r
-       if (port->rcv.rix != port->rcv.wix) {\r
-               byte = port->rcv.buf[port->rcv.rix];\r
-               port->rcv.rix = (port->rcv.rix+1) % SIRQ_LEN;\r
-       }\r
-       return byte;\r
-}\r
-\r
-/* Enable transmitter */\r
-void sirq_transmit(sirq_t *port)\r
-{\r
-       if (port->xmt.rix != port->xmt.wix && !port->irq) {\r
-               port->irq = 1;\r
-               serial_irq_set(&port->uart, TxIrq, 1);\r
-       }\r
-}\r
-\r
-/* Buffered write */\r
-void sirq_write(sirq_t *port, void *data, int len)\r
-{\r
-       uint8_t *bytes = (uint8_t*)data;\r
-       for (int i = 0; i < len; i++)\r
-               sirq_putc(port, bytes[i]);\r
-}\r
-\r
-/* Check if port is writable */\r
-int sirq_ready(sirq_t *port)\r
-{\r
-       return port->rcv.rix != port->rcv.wix;\r
-}\r
-\r
-/* Debug print */\r
-void sirq_debug(sirq_t *port)\r
-{\r
-       sirq_printf("xmt  - wix:%03x rix:%03x\r\n", port->xmt.wix, port->xmt.rix);\r
-       sirq_printf("rcv  - wix:%03x rix:%03x\r\n", port->rcv.wix, port->rcv.rix);\r
-       sirq_printf("irq  - ??\r\n");\r
-       sirq_printf("uart - ??\r\n");\r
-}\r
-\r
-/* Write ASCII data to the output queue */\r
-void sirq_vprintf(const char *fmt, va_list ap)\r
-{\r
-       static char buf[512];\r
-       int len = vsnprintf(buf, sizeof(buf), fmt, ap);\r
-       for (int i = 0; i < len; i++)\r
-               sirq_putc(&sirq_ports[0], buf[i]);\r
-}\r
-\r
-void sirq_printf(const char *fmt, ...)\r
-{\r
-       va_list ap;\r
-       va_start(ap, fmt);\r
-       sirq_vprintf(fmt, ap);\r
-       va_end(ap);\r
-}\r
+#include <MKL46Z4.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include "serial_api.h"
+#include "serial_irq.h"
+#include "timer_dma.h"
+
+/* Defines */
+#define SIRQ_LEN  1024
+
+/* Port structure */
+typedef struct {
+       int     rix;
+       int     wix;
+       uint8_t buf[SIRQ_LEN];
+} queue_t;
+
+struct sirq_t {
+       serial_t uart;
+       queue_t  xmt;
+       queue_t  rcv;
+       int      irq;
+       int      buffered;
+};
+
+/* Port data */
+static sirq_t sirq_ports[SIRQ_NUM_UART];
+
+/* Receive handler */
+void sirq_handler(uint32_t _port, SerialIrq event)
+{
+       sirq_t *port = (sirq_t *)_port;
+
+       // Handle transmit
+       //   note: mbed seems to call TxIrq even it is not enabled,
+       //   so we need to manually prevent transmitting when the
+       //   port is set to buffered mode.
+       if (event == TxIrq && (port->irq || !port->buffered)) {
+               if (port->xmt.rix != port->xmt.wix) {
+                       int byte = port->xmt.buf[port->xmt.rix];
+                       serial_putc(&port->uart, byte);
+                       port->xmt.rix = (port->xmt.rix+1) % SIRQ_LEN;
+               } else {
+                       serial_irq_set(&port->uart, TxIrq, 0);
+                       port->irq = 0;
+               }
+       }
+
+       // Handle receive
+       if (event == RxIrq) {
+               int byte = serial_getc(&port->uart);
+               port->rcv.buf[port->rcv.wix] = byte;
+               port->rcv.wix = (port->rcv.wix+1) % SIRQ_LEN;
+       }
+}
+
+/* Open port */
+sirq_t *sirq_open(sirq_uart_t uart, PinName tx, PinName rx, int baud, int buffered)
+{
+       // Allocate port
+       sirq_t *port = &sirq_ports[uart];
+
+       // Buffered ports only transmit on demand
+       port->buffered = buffered;
+
+       // Configure port
+       serial_init(&port->uart, tx, rx);
+       serial_baud(&port->uart, baud);
+
+       // Set IRQ handlers
+       serial_irq_handler(&port->uart, sirq_handler, (uint32_t)port);
+       serial_irq_set(&port->uart, RxIrq, 1);
+
+       return port;
+}
+
+/* Write byte to the port */
+void sirq_putc(sirq_t *port, int byte)
+{
+       port->xmt.buf[port->xmt.wix] = byte;
+       port->xmt.wix = (port->xmt.wix+1) % SIRQ_LEN;
+       if (!port->buffered)
+               sirq_transmit(port);
+}
+
+/* Read byte from the port */
+int sirq_getc(sirq_t *port)
+{
+       int byte = 0;
+       if (port->rcv.rix != port->rcv.wix) {
+               byte = port->rcv.buf[port->rcv.rix];
+               port->rcv.rix = (port->rcv.rix+1) % SIRQ_LEN;
+       }
+       return byte;
+}
+
+/* Enable transmitter */
+void sirq_transmit(sirq_t *port)
+{
+       if (port->xmt.rix != port->xmt.wix && !port->irq) {
+               port->irq = 1;
+               serial_irq_set(&port->uart, TxIrq, 1);
+       }
+}
+
+/* Buffered write */
+void sirq_write(sirq_t *port, void *data, int len)
+{
+       uint8_t *bytes = (uint8_t*)data;
+       for (int i = 0; i < len; i++)
+               sirq_putc(port, bytes[i]);
+}
+
+/* Check if port is writable */
+int sirq_ready(sirq_t *port)
+{
+       return port->rcv.rix != port->rcv.wix;
+}
+
+/* Debug print */
+void sirq_debug(sirq_t *port)
+{
+       sirq_printf("xmt  - wix:%03x rix:%03x\r\n", port->xmt.wix, port->xmt.rix);
+       sirq_printf("rcv  - wix:%03x rix:%03x\r\n", port->rcv.wix, port->rcv.rix);
+       sirq_printf("irq  - ??\r\n");
+       sirq_printf("uart - ??\r\n");
+}
+
+/* Write ASCII data to the output queue */
+void sirq_vprintf(const char *fmt, va_list ap)
+{
+       static char buf[512];
+       int len = vsnprintf(buf, sizeof(buf), fmt, ap);
+       for (int i = 0; i < len; i++)
+               sirq_putc(&sirq_ports[0], buf[i]);
+}
+
+void sirq_printf(const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       sirq_vprintf(fmt, ap);
+       va_end(ap);
+}
index 36fdc979e567527600268f1c27360c187460041b..77dc6899da804216930652ae27aa15f2273c90b7 100644 (file)
-#include <MKL46Z4.h>\r
-\r
-#include <stdint.h>\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-\r
-#include "timer_dma.h"\r
-#include "serial_irq.h"\r
-\r
-/* Defines */\r
-enum {\r
-       TDMA_REQ_PTA  = 49,\r
-       TDMA_REQ_PTC  = 51,\r
-       TDMA_REQ_PTD  = 52,\r
-};\r
-\r
-/* Port structure */\r
-struct tdma_t {\r
-       /* DMA channel */\r
-       struct {\r
-               uint32_t sar; // offset 0x00, Source Address Register\r
-               uint32_t dar; // offset 0x04, Destination Address Register\r
-               uint32_t dsr; // offset 0x08, DMA Status Register / Byte Count Register\r
-               uint32_t dcr; // offset 0x0C, DMA Control Register\r
-       } *dma;\r
-\r
-       /* DMA mux */\r
-       struct {\r
-               uint8_t  cfg; // offset 0x00, Channel Configuration register\r
-       } *mux;\r
-\r
-       /* Pin names */\r
-       struct {\r
-               uint32_t pcr; // offset 0x00, Pin Control register\r
-       } *pin;\r
-\r
-       /* Time stamping */\r
-       uint32_t time[2];\r
-\r
-       /* Save state */\r
-       int      req;\r
-       int      irqc;\r
-};\r
-\r
-/* Port data */\r
-static tdma_t tdma_ports[TDMA_NUM_CHAN];\r
-\r
-/* Global timer initialization */\r
-void tdma_init(void)\r
-{\r
-       static int tdma_init_done = 0;\r
-       if (tdma_init_done)\r
-               return;\r
-\r
-       // Enable DMA Cock\r
-       SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;\r
-       SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;\r
-       SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;\r
-       SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK;\r
-       SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;\r
-\r
-       // Enable timer Clock\r
-       SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;\r
-\r
-       // Enable PIT\r
-       PIT->MCR               = 0;\r
-\r
-       // Channel 0\r
-       PIT->CHANNEL[0].LDVAL  = 0xFFFFFFFF;\r
-       PIT->CHANNEL[0].TCTRL  = 0;\r
-\r
-       // Channel 1\r
-       PIT->CHANNEL[1].LDVAL  = 0xFFFFFFFF;\r
-       PIT->CHANNEL[1].TCTRL  = PIT_TCTRL_CHN_MASK;\r
-\r
-       // Start timers\r
-       PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;\r
-       PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;\r
-\r
-       // Done\r
-       tdma_init_done = 1;\r
-}\r
-\r
-/* DMA Functions */\r
-tdma_t *tdma_open(tdma_chan_t chan, int alt, PinName pin, PinMode mode)\r
-{\r
-       int req  = pin >= PTD0 ? TDMA_REQ_PTD :\r
-                  pin >= PTC0 ? TDMA_REQ_PTC :\r
-                  pin >= PTA0 ? TDMA_REQ_PTA : 0;\r
-\r
-       int irqc = mode == PullDown ? 1 : 2;\r
-\r
-       // Initialize global registers\r
-       tdma_init();\r
-\r
-       // Allocate port\r
-       tdma_t *port    = &tdma_ports[chan];\r
-\r
-       // Setup port pointers\r
-       port->dma       = (void*)&DMA0->DMA[chan];\r
-       port->mux       = (void*)&DMAMUX0->CHCFG[chan];\r
-       port->pin       = (void*)(PORTA_BASE + pin);\r
-\r
-       // Reset DMA channel\r
-       port->dma->dsr  = DMA_DSR_BCR_DONE_MASK;\r
-\r
-       // Configure DMA channel\r
-       port->dma->dcr  = DMA_DCR_SINC_MASK         // Source increment\r
-                       | DMA_DCR_DINC_MASK         // Dest increment\r
-                       | DMA_DCR_SSIZE(0)          // 32-bit access\r
-                       | DMA_DCR_DSIZE(0)          // 32-bit access\r
-                       | DMA_DCR_D_REQ_MASK;       // Only run once\r
-\r
-       // Setup and enable DMA MUX\r
-       port->mux->cfg  = DMAMUX_CHCFG_SOURCE(req)  // Request source\r
-                       | DMAMUX_CHCFG_ENBL_MASK;   // Enable DMA mux\r
-\r
-       // Set pin to generate DMA req\r
-       port->pin->pcr  = PORT_PCR_ISF_MASK         // Clear ISR flag\r
-                       | PORT_PCR_MUX(alt)         // Pin mapping\r
-                       | PORT_PCR_IRQC(irqc)       // DMA on falling edge\r
-                       | mode;                     // Pin pull up/down\r
-\r
-       // Save IRC for later\r
-       port->req       = req;\r
-       port->irqc      = irqc;\r
-\r
-       return port;\r
-}\r
-\r
-void tdma_start(tdma_t *port)\r
-{\r
-       if (!port)\r
-               return;\r
-\r
-       //sirq_printf("isfr2: %08x\r\n", PORTD->ISFR);\r
-\r
-       // Clear previous time\r
-       port->time[0] = 0;\r
-       port->time[1] = 0;\r
-\r
-       // Reset DMA Mux\r
-       port->mux->cfg &= DMAMUX_CHCFG_ENBL_MASK;\r
-\r
-       // Freeze DMA channel\r
-       port->dma->dcr &= ~DMA_DCR_ERQ_MASK;\r
-\r
-       // Reset DMA channel\r
-       port->dma->dsr  =  DMA_DSR_BCR_DONE_MASK;\r
-\r
-       // Set addresses and size\r
-       port->dma->sar  =  (uint32_t)&PIT->LTMR64H;  // Global timer\r
-       port->dma->dar  =  (uint32_t)&port->time;    // Temp timer buffer\r
-       port->dma->dsr  =  DMA_DSR_BCR_BCR(8);       // 64-bit timer\r
-\r
-       // Set pin to generate DMA req\r
-       port->pin->pcr |=  PORT_PCR_ISF_MASK;\r
-       port->pin->pcr |=  PORT_PCR_IRQC(port->irqc);\r
-\r
-       // Enable port request\r
-       port->dma->dcr |=  DMA_DCR_ERQ_MASK;\r
-\r
-       // Enable DMA Mux\r
-       port->mux->cfg  = DMAMUX_CHCFG_SOURCE(port->req)\r
-                       | DMAMUX_CHCFG_ENBL_MASK;\r
-\r
-       //sirq_printf("isfr3: %08x\r\n", PORTD->ISFR);\r
-}\r
-\r
-void tdma_stop(tdma_t *port, int wait)\r
-{\r
-       if (!port)\r
-               return;\r
-\r
-       //sirq_printf("isfr0: %08x\r\n", PORTD->ISFR);\r
-\r
-       for (int i = 0; port->dma->dsr & DMA_DSR_BCR_BCR_MASK; i++)\r
-               if (i > wait)\r
-                       return;\r
-\r
-       // Disable DMA Mux\r
-       port->mux->cfg &= DMAMUX_CHCFG_ENBL_MASK;\r
-\r
-       // Freeze DMA channel\r
-       port->dma->dcr &= ~DMA_DCR_ERQ_MASK;\r
-\r
-       // Reset DMA channel\r
-       port->dma->dsr  =  DMA_DSR_BCR_DONE_MASK;\r
-\r
-       // Disable pin DMA request\r
-       port->pin->pcr &= ~PORT_PCR_IRQC_MASK;\r
-       port->pin->pcr |=  PORT_PCR_ISF_MASK;\r
-\r
-       //sirq_printf("isfr1: %08x\r\n", PORTD->ISFR);\r
-}\r
-\r
-int tdma_stamp(tdma_t *port, uint64_t *time)\r
-{\r
-       uint64_t clocks;\r
-\r
-       if (!port)\r
-               return 0;\r
-\r
-       if (port->dma->dsr & DMA_DSR_BCR_BCR_MASK)\r
-               return 0;\r
-\r
-       // Read the timestamp\r
-       clocks = ((uint64_t)~port->time[0]) << 32\r
-              | ((uint64_t)~port->time[1]) << 0;\r
-\r
-       // Convert to nanoseconds\r
-       *time  = clocks * 1000 / 24;\r
-\r
-       return 1;\r
-}\r
-\r
-uint64_t tdma_time(void)\r
-{\r
-       uint32_t tmh = PIT->LTMR64H;\r
-       uint32_t tml = PIT->LTMR64L;\r
-\r
-       // Read the timestamp\r
-       uint64_t clocks = ((uint64_t)~tmh) << 32\r
-                       | ((uint64_t)~tml) << 0;\r
-\r
-       // Convert to nanoseconds\r
-       return clocks * 125 / 3;\r
-}\r
-\r
-void tdma_debug(tdma_t *port)\r
-{\r
-       int dsr = port->dma->dsr;\r
-       int dcr = port->dma->dcr;\r
-\r
-       printf("dsr: %s %s %s %s %s %s %d\r\n",\r
-                        dsr & DMA_DSR_BCR_CE_MASK   ? "CE"      : "ce",\r
-                        dsr & DMA_DSR_BCR_BES_MASK  ? "BSE"     : "bse",\r
-                        dsr & DMA_DSR_BCR_BED_MASK  ? "BED"     : "bed",\r
-                        dsr & DMA_DSR_BCR_REQ_MASK  ? "REQ"     : "req",\r
-                        dsr & DMA_DSR_BCR_BSY_MASK  ? "BSY"     : "bsy",\r
-                        dsr & DMA_DSR_BCR_DONE_MASK ? "DONE"    : "done",\r
-                        dsr & DMA_DSR_BCR_BCR_MASK);\r
-\r
-       printf("dcr: %s %s %s %s %s %s %s %s ssize=%d:%d mod=%d:%d link=%d:%d:%d\r\n",\r
-                        dcr & DMA_DCR_EINT_MASK     ? "EINT"    : "eint",\r
-                        dcr & DMA_DCR_ERQ_MASK      ? "ERQ"     : "erq",\r
-                        dcr & DMA_DCR_CS_MASK       ? "CS"      : "cs",\r
-                        dcr & DMA_DCR_AA_MASK       ? "AA"      : "aa",\r
-                        dcr & DMA_DCR_EADREQ_MASK   ? "EADRREQ" : "eadrreq",\r
-                        dcr & DMA_DCR_SINC_MASK     ? "SINC"    : "sinc",\r
-                        dcr & DMA_DCR_DINC_MASK     ? "DINC"    : "dinc",\r
-                        dcr & DMA_DCR_D_REQ_MASK    ? "DREQ"    : "dreq",\r
-                       (dcr & DMA_DCR_SSIZE_MASK ) >> DMA_DCR_SSIZE_SHIFT,\r
-                       (dcr & DMA_DCR_DSIZE_MASK ) >> DMA_DCR_DSIZE_SHIFT,\r
-                       (dcr & DMA_DCR_SMOD_MASK  ) >> DMA_DCR_SMOD_SHIFT,\r
-                       (dcr & DMA_DCR_DMOD_MASK  ) >> DMA_DCR_DMOD_SHIFT,\r
-                       (dcr & DMA_DCR_LINKCC_MASK) >> DMA_DCR_LINKCC_SHIFT,\r
-                       (dcr & DMA_DCR_LCH1_MASK  ) >> DMA_DCR_LCH1_SHIFT,\r
-                       (dcr & DMA_DCR_LCH2_MASK  ) >> DMA_DCR_LCH2_SHIFT);\r
-}\r
+#include <MKL46Z4.h>
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "timer_dma.h"
+#include "serial_irq.h"
+
+/* Defines */
+enum {
+       TDMA_REQ_PTA  = 49,
+       TDMA_REQ_PTC  = 51,
+       TDMA_REQ_PTD  = 52,
+};
+
+/* Port structure */
+struct tdma_t {
+       /* DMA channel */
+       struct {
+               uint32_t sar; // offset 0x00, Source Address Register
+               uint32_t dar; // offset 0x04, Destination Address Register
+               uint32_t dsr; // offset 0x08, DMA Status Register / Byte Count Register
+               uint32_t dcr; // offset 0x0C, DMA Control Register
+       } *dma;
+
+       /* DMA mux */
+       struct {
+               uint8_t  cfg; // offset 0x00, Channel Configuration register
+       } *mux;
+
+       /* Pin names */
+       struct {
+               uint32_t pcr; // offset 0x00, Pin Control register
+       } *pin;
+
+       /* Time stamping */
+       uint32_t time[2];
+
+       /* Save state */
+       int      req;
+       int      irqc;
+};
+
+/* Port data */
+static tdma_t tdma_ports[TDMA_NUM_CHAN];
+
+/* Global timer initialization */
+void tdma_init(void)
+{
+       static int tdma_init_done = 0;
+       if (tdma_init_done)
+               return;
+
+       // Enable DMA Cock
+       SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
+       SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
+       SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
+       SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
+       SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;
+
+       // Enable timer Clock
+       SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;
+
+       // Enable PIT
+       PIT->MCR               = 0;
+
+       // Channel 0
+       PIT->CHANNEL[0].LDVAL  = 0xFFFFFFFF;
+       PIT->CHANNEL[0].TCTRL  = 0;
+
+       // Channel 1
+       PIT->CHANNEL[1].LDVAL  = 0xFFFFFFFF;
+       PIT->CHANNEL[1].TCTRL  = PIT_TCTRL_CHN_MASK;
+
+       // Start timers
+       PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;
+       PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;
+
+       // Done
+       tdma_init_done = 1;
+}
+
+/* DMA Functions */
+tdma_t *tdma_open(tdma_chan_t chan, int alt, PinName pin, PinMode mode)
+{
+       int req  = pin >= PTD0 ? TDMA_REQ_PTD :
+                  pin >= PTC0 ? TDMA_REQ_PTC :
+                  pin >= PTA0 ? TDMA_REQ_PTA : 0;
+
+       int irqc = mode == PullDown ? 1 : 2;
+
+       // Initialize global registers
+       tdma_init();
+
+       // Allocate port
+       tdma_t *port    = &tdma_ports[chan];
+
+       // Setup port pointers
+       port->dma       = (void*)&DMA0->DMA[chan];
+       port->mux       = (void*)&DMAMUX0->CHCFG[chan];
+       port->pin       = (void*)(PORTA_BASE + pin);
+
+       // Reset DMA channel
+       port->dma->dsr  = DMA_DSR_BCR_DONE_MASK;
+
+       // Configure DMA channel
+       port->dma->dcr  = DMA_DCR_SINC_MASK         // Source increment
+                       | DMA_DCR_DINC_MASK         // Dest increment
+                       | DMA_DCR_SSIZE(0)          // 32-bit access
+                       | DMA_DCR_DSIZE(0)          // 32-bit access
+                       | DMA_DCR_D_REQ_MASK;       // Only run once
+
+       // Setup and enable DMA MUX
+       port->mux->cfg  = DMAMUX_CHCFG_SOURCE(req)  // Request source
+                       | DMAMUX_CHCFG_ENBL_MASK;   // Enable DMA mux
+
+       // Set pin to generate DMA req
+       port->pin->pcr  = PORT_PCR_ISF_MASK         // Clear ISR flag
+                       | PORT_PCR_MUX(alt)         // Pin mapping
+                       | PORT_PCR_IRQC(irqc)       // DMA on falling edge
+                       | mode;                     // Pin pull up/down
+
+       // Save IRC for later
+       port->req       = req;
+       port->irqc      = irqc;
+
+       return port;
+}
+
+void tdma_start(tdma_t *port)
+{
+       if (!port)
+               return;
+
+       //sirq_printf("isfr2: %08x\r\n", PORTD->ISFR);
+
+       // Clear previous time
+       port->time[0] = 0;
+       port->time[1] = 0;
+
+       // Reset DMA Mux
+       port->mux->cfg &= DMAMUX_CHCFG_ENBL_MASK;
+
+       // Freeze DMA channel
+       port->dma->dcr &= ~DMA_DCR_ERQ_MASK;
+
+       // Reset DMA channel
+       port->dma->dsr  =  DMA_DSR_BCR_DONE_MASK;
+
+       // Set addresses and size
+       port->dma->sar  =  (uint32_t)&PIT->LTMR64H;  // Global timer
+       port->dma->dar  =  (uint32_t)&port->time;    // Temp timer buffer
+       port->dma->dsr  =  DMA_DSR_BCR_BCR(8);       // 64-bit timer
+
+       // Set pin to generate DMA req
+       port->pin->pcr |=  PORT_PCR_ISF_MASK;
+       port->pin->pcr |=  PORT_PCR_IRQC(port->irqc);
+
+       // Enable port request
+       port->dma->dcr |=  DMA_DCR_ERQ_MASK;
+
+       // Enable DMA Mux
+       port->mux->cfg  = DMAMUX_CHCFG_SOURCE(port->req)
+                       | DMAMUX_CHCFG_ENBL_MASK;
+
+       //sirq_printf("isfr3: %08x\r\n", PORTD->ISFR);
+}
+
+void tdma_stop(tdma_t *port, int wait)
+{
+       if (!port)
+               return;
+
+       //sirq_printf("isfr0: %08x\r\n", PORTD->ISFR);
+
+       for (int i = 0; port->dma->dsr & DMA_DSR_BCR_BCR_MASK; i++)
+               if (i > wait)
+                       return;
+
+       // Disable DMA Mux
+       port->mux->cfg &= DMAMUX_CHCFG_ENBL_MASK;
+
+       // Freeze DMA channel
+       port->dma->dcr &= ~DMA_DCR_ERQ_MASK;
+
+       // Reset DMA channel
+       port->dma->dsr  =  DMA_DSR_BCR_DONE_MASK;
+
+       // Disable pin DMA request
+       port->pin->pcr &= ~PORT_PCR_IRQC_MASK;
+       port->pin->pcr |=  PORT_PCR_ISF_MASK;
+
+       //sirq_printf("isfr1: %08x\r\n", PORTD->ISFR);
+}
+
+int tdma_stamp(tdma_t *port, uint64_t *time)
+{
+       uint64_t clocks;
+
+       if (!port)
+               return 0;
+
+       if (port->dma->dsr & DMA_DSR_BCR_BCR_MASK)
+               return 0;
+
+       // Read the timestamp
+       clocks = ((uint64_t)~port->time[0]) << 32
+              | ((uint64_t)~port->time[1]) << 0;
+
+       // Convert to nanoseconds
+       *time  = clocks * 1000 / 24;
+
+       return 1;
+}
+
+uint64_t tdma_time(void)
+{
+       uint32_t tmh = PIT->LTMR64H;
+       uint32_t tml = PIT->LTMR64L;
+
+       // Read the timestamp
+       uint64_t clocks = ((uint64_t)~tmh) << 32
+                       | ((uint64_t)~tml) << 0;
+
+       // Convert to nanoseconds
+       return clocks * 125 / 3;
+}
+
+void tdma_debug(tdma_t *port)
+{
+       int dsr = port->dma->dsr;
+       int dcr = port->dma->dcr;
+
+       printf("dsr: %s %s %s %s %s %s %d\r\n",
+                        dsr & DMA_DSR_BCR_CE_MASK   ? "CE"      : "ce",
+                        dsr & DMA_DSR_BCR_BES_MASK  ? "BSE"     : "bse",
+                        dsr & DMA_DSR_BCR_BED_MASK  ? "BED"     : "bed",
+                        dsr & DMA_DSR_BCR_REQ_MASK  ? "REQ"     : "req",
+                        dsr & DMA_DSR_BCR_BSY_MASK  ? "BSY"     : "bsy",
+                        dsr & DMA_DSR_BCR_DONE_MASK ? "DONE"    : "done",
+                        dsr & DMA_DSR_BCR_BCR_MASK);
+
+       printf("dcr: %s %s %s %s %s %s %s %s ssize=%d:%d mod=%d:%d link=%d:%d:%d\r\n",
+                        dcr & DMA_DCR_EINT_MASK     ? "EINT"    : "eint",
+                        dcr & DMA_DCR_ERQ_MASK      ? "ERQ"     : "erq",
+                        dcr & DMA_DCR_CS_MASK       ? "CS"      : "cs",
+                        dcr & DMA_DCR_AA_MASK       ? "AA"      : "aa",
+                        dcr & DMA_DCR_EADREQ_MASK   ? "EADRREQ" : "eadrreq",
+                        dcr & DMA_DCR_SINC_MASK     ? "SINC"    : "sinc",
+                        dcr & DMA_DCR_DINC_MASK     ? "DINC"    : "dinc",
+                        dcr & DMA_DCR_D_REQ_MASK    ? "DREQ"    : "dreq",
+                       (dcr & DMA_DCR_SSIZE_MASK ) >> DMA_DCR_SSIZE_SHIFT,
+                       (dcr & DMA_DCR_DSIZE_MASK ) >> DMA_DCR_DSIZE_SHIFT,
+                       (dcr & DMA_DCR_SMOD_MASK  ) >> DMA_DCR_SMOD_SHIFT,
+                       (dcr & DMA_DCR_DMOD_MASK  ) >> DMA_DCR_DMOD_SHIFT,
+                       (dcr & DMA_DCR_LINKCC_MASK) >> DMA_DCR_LINKCC_SHIFT,
+                       (dcr & DMA_DCR_LCH1_MASK  ) >> DMA_DCR_LCH1_SHIFT,
+                       (dcr & DMA_DCR_LCH2_MASK  ) >> DMA_DCR_LCH2_SHIFT);
+}