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