-#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");
+ }
+}
-#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);
+}
-#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);
+}
-#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);
+}