]> Pileus Git - ~andy/csm213a-hw/commitdiff
Add dma timestamper
authorAndy Spencer <andy753421@gmail.com>
Sun, 9 Mar 2014 06:41:37 +0000 (06:41 +0000)
committerAndy Spencer <andy753421@gmail.com>
Sun, 9 Mar 2014 06:41:37 +0000 (06:41 +0000)
hw2/main.cpp
hw2/makefile
hw2/timer_dma.c [new file with mode: 0644]
hw2/timer_dma.h [new file with mode: 0644]

index d6a074209846106991cb51d430cd112ca48b5666..006f85269dfcf1e55788f1a2027c7b8e461f4018 100644 (file)
@@ -1,5 +1,6 @@
 #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
@@ -188,6 +196,12 @@ sdma_t    *sdma0;
 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
@@ -338,13 +352,24 @@ void test_pit_run(void)
        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
@@ -354,27 +379,59 @@ void test_uart(void)
        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
@@ -383,23 +440,20 @@ int main(int argc, char **argv)
        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
index 118544885d22d14c64510eebc79b77a6c029653b..d27995c52cfbc902908b5ad019ee0f898421ae97 100644 (file)
@@ -1,5 +1,5 @@
 PROG = mbed
-OBJS = main.o serial_dma.o
+OBJS = main.o serial_dma.o timer_dma.o
 
 CPPFLAGS =
 LDFLAGS  = -lm
diff --git a/hw2/timer_dma.c b/hw2/timer_dma.c
new file mode 100644 (file)
index 0000000..23f11e2
--- /dev/null
@@ -0,0 +1,144 @@
+#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
diff --git a/hw2/timer_dma.h b/hw2/timer_dma.h
new file mode 100644 (file)
index 0000000..cf672d0
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef TIMER_DMA_H
+#define TIMER_DMA_H
+
+#include <stdarg.h>
+#include <MKL46Z4.h>
+#include <PinNames.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Sizes */
+#define TDMA_NUM_CHAN  4
+
+/* DMA Channels */
+typedef enum {
+       TDMA_CHAN0,
+       TDMA_CHAN1,
+       TDMA_CHAN2,
+       TDMA_CHAN3,
+} tdma_chan_t;
+
+/* Port */
+typedef struct tdma_t tdma_t;
+
+/* Open */
+void tdma_init(void);
+
+/* Open */
+tdma_t *tdma_open(tdma_chan_t chan, PinName pin, PinMode mode);
+
+/* Flush/Wait */
+void tdma_reset(tdma_t *port);
+int  tdma_stamp(tdma_t *port, uint64_t *time);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif