#include "mbed.h"\r
#include "serial_dma.h"\r
+#include "timer_dma.h"\r
\r
/**\r
* Mode of operation:\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
+ * A2 A1 --A19 A18-- - -\r
* A14 A15 - - - -\r
* B17 B16 - - - -\r
- * - - **C4 C3** - -\r
- * D7 D6 - - **D3 D2** <<<\r
- * - - - - **D5 D4**\r
- * E20 E21 E0 E1 E16 E17 \r
- * - - - - E22 E23 \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
+ * 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
sdma_t *sdma1;\r
sdma_t *sdma2;\r
\r
+// Timer DMA\r
+tdma_t *tdma0;\r
+tdma_t *tdma1;\r
+tdma_t *tdma2;\r
+tdma_t *tdma3;\r
+\r
/********\r
* Main *\r
********/\r
uint64_t tm1 = ~((uint64_t)hi1 << 32 | lo1);\r
double bus = 24E6; // 24 MHz bus clock\r
\r
- printf("tick %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\r\n", (double)tm0 / bus);\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_uart(void)\r
+void test_sdma_run(void)\r
{\r
char xmt[32] = "hello, world";\r
char rcv[32] = {};\r
sdma_write(sdma1, xmt, strlen(xmt));\r
sdma_flush(sdma1, &tm1);\r
\r
- //sdma_read(sdma2, rcv, strlen(xmt));\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
+ 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_leds(void)\r
+void test_tdma_init(void)\r
{\r
- led1 = 1; led2 = 0; wait(0.1);\r
- led1 = 0; led2 = 1; wait(0.1);\r
+ tdma_init();\r
+\r
+ tdma0 = tdma_open(TDMA_CHAN0, PTA1, PullNone);\r
+ tdma1 = tdma_open(TDMA_CHAN1, PTC1, PullNone);\r
+ tdma2 = tdma_open(TDMA_CHAN2, PTD3, PullUp);\r
+ tdma3 = tdma_open(TDMA_CHAN3, PTD2, PullUp);\r
}\r
\r
-void test_irq(void)\r
+void test_tdma_run(void)\r
{\r
- printf("\r\nirq");\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_reset(tdma0);\r
+ tdma_reset(tdma1);\r
+ tdma_reset(tdma2);\r
+ tdma_reset(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
int main(int argc, char **argv)\r
uart1.baud(115200);\r
uart2.baud(115200);\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
- //test_uart();\r
- //test_leds();\r
- test_pit_init();\r
+ printf("init\r\n");\r
//test_tpm_init();\r
+ //test_pit_init();\r
+ //test_sdma_init();\r
+ test_tdma_init();\r
\r
- while (1) {\r
- test_uart();\r
+ printf("run\r\n");\r
+ for (int i = 0; true; i++) {\r
+ printf("%8d", i);\r
//test_leds();\r
- //test_pit_run();\r
//test_tpm_run();\r
+ //test_pit_run();\r
+ //test_sdma_run();\r
+ test_tdma_run();\r
printf("\r\n");\r
}\r
}\r
--- /dev/null
+#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
+\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
+\r
+/* Port data */\r
+static tdma_t tdma_ports[TDMA_NUM_CHAN];\r
+\r
+/* Global timer initialization */\r
+void tdma_init(void)\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
+\r
+/* DMA Functions */\r
+tdma_t *tdma_open(tdma_chan_t chan, 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 ircq = mode == PullUp ? 2 : 1;\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_ERQ_MASK; // Enable port request\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(3) // Pin mapping\r
+ | PORT_PCR_IRQC(ircq) // DMA on falling edge\r
+ | mode; // Pin pull up/down\r
+\r
+ return port;\r
+}\r
+\r
+void tdma_reset(tdma_t *port)\r
+{\r
+ // Clear previous time\r
+ port->time[0] = 0;\r
+ port->time[1] = 0;\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
+\r
+int tdma_stamp(tdma_t *port, uint64_t *time)\r
+{\r
+ if (port->dma->dsr & DMA_DSR_BCR_BCR_MASK)\r
+ return 0;\r
+\r
+ // Read the timestamp\r
+ *time = ((uint64_t)~port->time[0]) << 32\r
+ | ((uint64_t)~port->time[1]) << 0;\r
+\r
+ // Debug output..\r
+ //printf(" - sar:%08lx dar:%08lx pcr:%08lx dsr:%08lx time:%08lx:%08lx",\r
+ // port->dma->sar, port->dma->dar,\r
+ // port->pin->pcr, port->dma->dsr,\r
+ // (uint32_t)(*time >> 32), (uint32_t)*time);\r
+\r
+ return 1;\r
+}\r