]> Pileus Git - ~andy/csm213a-hw/commitdiff
Get DMA timestamp working
authorAndy Spencer <andy753421@gmail.com>
Sun, 9 Mar 2014 03:47:39 +0000 (03:47 +0000)
committerAndy Spencer <andy753421@gmail.com>
Sun, 9 Mar 2014 06:41:17 +0000 (06:41 +0000)
hw2/main.cpp
hw2/serial_dma.c
hw2/serial_dma.h

index 454bed5c5e3290e1c2f5283c6ad0c2980677cfb5..d6a074209846106991cb51d430cd112ca48b5666 100644 (file)
@@ -287,10 +287,10 @@ void test_tpm_run(void)
 {\r
        //static DigitalIn pin(PTC0);\r
        //static DigitalIn pin(PTC2);\r
-       static int pin = 0;\r
+       //static int pin = 0;\r
 \r
-       printf("%lx - PTC0:%08lx GPCR:%08lx:%08lx - SC:%04lx CNT:%04lx MOD:%04lx STATUS:%04lx CONF:%08lx - CnSC:%02lx CnV:%04lx\r\n",\r
-                       (long)pin, PORTC->PCR[0], PORTC->GPCHR, PORTC->GPCLR,\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
@@ -349,16 +349,21 @@ void test_uart(void)
        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);\r
+       sdma_flush(sdma1, &tm1);\r
+\r
+       //sdma_read(sdma2, rcv, strlen(xmt));\r
+       sdma_wait(sdma2, &tm2);\r
 \r
-       for (int i = 0; xmt[i]; i++)\r
-               rcv[i] = uart2.getc();\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
-       printf("xmt: %s    ", xmt);\r
-       printf("rcv: %s    ", rcv);\r
-       printf("tag: dir:%08lx in:%08lx\r\n",\r
-                       FPTD->PDDR, FPTD->PDIR);\r
+       (void)xmt; (void)rcv;\r
+       (void)tm1; (void)tm2;\r
 }\r
 \r
 void test_leds(void)\r
@@ -367,16 +372,25 @@ void test_leds(void)
        led1 = 0; led2 = 1; wait(0.1);\r
 }\r
 \r
+void test_irq(void)\r
+{\r
+       printf("\r\nirq");\r
+}\r
+\r
 int main(int argc, char **argv)\r
 {\r
        uart0.baud(115200);\r
        uart1.baud(115200);\r
        uart2.baud(115200);\r
 \r
-       sdma1 = sdma_open(SDMA_UART1, SDMA_CHANNEL1);\r
-       sdma2 = sdma_open(SDMA_UART2, SDMA_CHANNEL2);\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_uart();\r
        //test_leds();\r
        test_pit_init();\r
        //test_tpm_init();\r
@@ -386,5 +400,6 @@ int main(int argc, char **argv)
                //test_leds();\r
                //test_pit_run();\r
                //test_tpm_run();\r
+               printf("\r\n");\r
        }\r
 }\r
index c9ad6437958b801b4456d6975faef1fafa73a1f1..26987769119b68a7419a097e839112b6426f41c8 100644 (file)
 #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
@@ -19,40 +35,66 @@ struct sdma_t {
                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
+       } *dma_xmt, *dma_rcv;\r
 \r
        /* DMA mux */\r
        struct {\r
                uint8_t  cfg; // offset 0x00, Channel Configuration register\r
-       } *mux;\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
+       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
+       int      stuck;\r
+       int      full;\r
 };\r
 \r
 /* DMA Request Sources */\r
 static int sdma_req_rx[] = {\r
-       [SDMA_UART0] 2,\r
-       [SDMA_UART1] 4,\r
-       [SDMA_UART2] 6,\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] 3,\r
-       [SDMA_UART1] 5,\r
-       [SDMA_UART2] 7,\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 dma)\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
@@ -60,27 +102,33 @@ sdma_t *sdma_open(sdma_uart_t uart, sdma_dma_t dma)
        // Setup port\r
        sdma_t *port = &sdma_ports[uart];\r
 \r
-       port->dma = (void*)&DMA0->DMA[dma];\r
-       port->mux = (void*)&DMAMUX0->CHCFG[dma];\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->SCGC6         |= SIM_SCGC6_DMAMUX_MASK;\r
-       SIM->SCGC7         |= SIM_SCGC7_DMA_MASK;\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->dsr      = DMA_DSR_BCR_DONE_MASK;\r
+       port->dma_xmt->dsr  = DMA_DSR_BCR_DONE_MASK;\r
 \r
        // Configure DMA transfer\r
-       port->dma->dar      = (uint32_t)&UART1->D;\r
-       port->dma->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
+       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->cfg      = DMAMUX_CHCFG_SOURCE(txreq) |\r
-                             DMAMUX_CHCFG_ENBL_MASK;\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
@@ -105,6 +153,13 @@ sdma_t *sdma_open(sdma_uart_t uart, sdma_dma_t dma)
        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
@@ -118,45 +173,108 @@ void sdma_write(sdma_t *port, void *data, int len)
        }\r
 }\r
 \r
-/* Write ASCII data to the output queue */\r
-void sdma_vprintf(sdma_t *port, const char *fmt, va_list ap)\r
+/* Read binary data from the channel */\r
+void sdma_read(sdma_t *port, void *data, int len)\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
+       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
-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
+               // 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)\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->dsr & DMA_DSR_BCR_BCR_MASK)\r
+       while (port->dma_xmt->dsr & DMA_DSR_BCR_BCR_MASK)\r
                port->stuck++;\r
 \r
        // Reset channel\r
-       port->dma->dsr  = DMA_DSR_BCR_DONE_MASK;\r
+       port->dma_xmt->dsr  = DMA_DSR_BCR_DONE_MASK;\r
 \r
        // Set source address and length\r
-       port->dma->sar  = (uint32_t)&port->queue[port->index];\r
-       port->dma->dsr  = DMA_DSR_BCR_BCR(port->length[port->index]);\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->dcr |= DMA_DCR_ERQ_MASK;\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
index db2314666861dfd4381374b46e8ef4f4469215ed..4ca9bb680af0c4f970f7ab421ba9190f38aca478 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <stdarg.h>
 #include <MKL46Z4.h>
+#include <PinNames.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -30,19 +31,24 @@ typedef enum {
 /* Port */
 typedef struct sdma_t sdma_t;
 
+/* Open */
+sdma_t *sdma_open(sdma_uart_t uart, sdma_dma_t tx_chan, sdma_dma_t rx_chan);
+
 /* Setup */
-sdma_t *sdma_open(sdma_uart_t uart, sdma_dma_t dma);
+void sdma_pinmap(sdma_t *port, PinName tx, PinName rx);
 
 /* Write */
 void sdma_write(sdma_t *port, void *data, int len);
+void sdma_read(sdma_t *port, void *data, int len);
+
+/* Flush/Wait */
+void sdma_flush(sdma_t *port, uint64_t *time);
+void sdma_wait(sdma_t *port, uint64_t *time);
 
 /* Print */
 void sdma_vprintf(sdma_t *port, const char *fmt, va_list ap);
 void sdma_printf(sdma_t *port, const char *fmt, ...);
 
-/* Write */
-void sdma_flush(sdma_t *port);
-
 #ifdef __cplusplus
 }
 #endif