]> Pileus Git - ~andy/csm213a-hw/blobdiff - hw2/timer_dma.c
Improve time sync accuracy
[~andy/csm213a-hw] / hw2 / timer_dma.c
index 2e197186cec8b507d902b75b660dfd141aaf4cf5..529fd7e2a59d2873563995cf5d5800f698df91ba 100644 (file)
@@ -6,6 +6,7 @@
 #include <string.h>\r
 \r
 #include "timer_dma.h"\r
+#include "serial_irq.h"\r
 \r
 /* Defines */\r
 enum {\r
@@ -36,6 +37,10 @@ struct tdma_t {
 \r
        /* Time stamping */\r
        uint32_t time[2];\r
+\r
+       /* Save state */\r
+       int      req;\r
+       int      irqc;\r
 };\r
 \r
 /* Port data */\r
@@ -77,7 +82,7 @@ tdma_t *tdma_open(tdma_chan_t chan, int alt, PinName pin, PinMode mode)
                   pin >= PTC0 ? TDMA_REQ_PTC :\r
                   pin >= PTA0 ? TDMA_REQ_PTA : 0;\r
 \r
-       int ircq = mode == PullUp ? 2 : 1;\r
+       int irqc = mode == PullUp ? 1 : 2;\r
 \r
        // Allocate port\r
        tdma_t *port    = &tdma_ports[chan];\r
@@ -104,24 +109,30 @@ tdma_t *tdma_open(tdma_chan_t chan, int alt, PinName pin, PinMode mode)
        // 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(ircq)       // DMA on falling edge\r
+                       | PORT_PCR_IRQC(irqc)       // DMA on falling edge\r
                        | mode;                     // Pin pull up/down\r
 \r
-       // Initial reset\r
-       tdma_reset(port);\r
+       // Save IRC for later\r
+       port->req       = req;\r
+       port->irqc      = irqc;\r
 \r
        return port;\r
 }\r
 \r
-void tdma_reset(tdma_t *port)\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
@@ -133,8 +144,41 @@ void tdma_reset(tdma_t *port)
        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)\r
+{\r
+       if (!port)\r
+               return;\r
+\r
+       //sirq_printf("isfr0: %08x\r\n", PORTD->ISFR);\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