]> Pileus Git - ~andy/csm213a-hw/commitdiff
Save a working version of TPM
authorAndy Spencer <andy753421@gmail.com>
Thu, 13 Mar 2014 06:31:11 +0000 (06:31 +0000)
committerAndy Spencer <andy753421@gmail.com>
Thu, 13 Mar 2014 06:31:11 +0000 (06:31 +0000)
hw2/main.cpp
hw2/timer_dma.c

index 47b701b4f2d2c269711032a59e082f3222b4783b..d824863b2dbc87413f57488f2acf4ff8d11f1082 100644 (file)
@@ -40,6 +40,12 @@ uint64_t time_to_world(uint64_t local)
        return time_last_world + elapsed;
 }
 
+uint64_t time_to_local(uint64_t world)
+{
+       uint64_t elapsed = world - time_last_world;
+       return time_last_local + elapsed;
+}
+
 /**
  * Synchronize the timer internal state with updates
  * from an external time sync message.
@@ -79,7 +85,7 @@ void time_ext_sync(uint64_t local, uint64_t world)
        world = time_last_world;
 
 //#ifdef VERBOSE
-#if 1
+#if 0
        uint64_t error = world > guess ? world - guess :
                         guess > world ? guess - world : 0;
        int      ahead = guess > world;
@@ -111,11 +117,36 @@ void time_printf(const char *label, uint64_t local)
  * Signal generation *
  *********************/
 
+// for 50 Mhz clock  50/1000 = 1/20  (PLL/2)
+
+// for 48 Mhz clock  48/1000 = 6/125 (FLL)
 // for 24 Mhz clock, 24/1000 = 3/125
-// for 48 Mhz clock  48/1000 = 6/125
-// for 50 Mhz clock  50/1000 = 1/20  (FLL/2)
-#define EMIT_CLOCKS(nsec) ((uint16_t)((nsec)   / 20))
-#define EMIT_NSEC(clocks) ((uint16_t)((clocks) * 20))
+// for 12 Mhz clock, 12/1000 = 3/250
+// for  6 Mhz clock,  6/1000 = 3/500
+// for  3 Mhz clock,  3/1000 = 3/1000
+
+#define EMIT_PS 1
+
+//#if EMIT_PS == 0
+//#define EMIT_CLOCKS(nsec) ((uint16_t)((nsec)   / 20))
+//#define EMIT_NSEC(clocks) ((uint16_t)((clocks) * 20))
+
+#if EMIT_PS == 0
+#define EMIT_CLOCKS(nsec) ((uint32_t)((nsec)   * 6 / 125))
+#define EMIT_NSEC(clocks) ((uint32_t)((clocks) * 125 / 6))
+#elif EMIT_PS == 1
+#define EMIT_CLOCKS(nsec) ((uint32_t)((nsec)   * 3 / 125))
+#define EMIT_NSEC(clocks) ((uint32_t)((clocks) * 125 / 3))
+#elif EMIT_PS == 2
+#define EMIT_CLOCKS(nsec) ((uint32_t)((nsec)   * 3 / 250))
+#define EMIT_NSEC(clocks) ((uint32_t)((clocks) * 250 / 3))
+#elif EMIT_PS == 3
+#define EMIT_CLOCKS(nsec) ((uint32_t)((nsec)   * 3 / 500))
+#define EMIT_NSEC(clocks) ((uint32_t)((clocks) * 500 / 3))
+#elif EMIT_PS == 4
+#define EMIT_CLOCKS(nsec) ((uint32_t)((nsec)   * 3 / 1000))
+#define EMIT_NSEC(clocks) ((uint32_t)((clocks) * 1000 / 3))
+#endif
 
 static uint32_t *emit_pcr    = 0; // transmit pin name
 
@@ -135,8 +166,12 @@ void emit_init(int alt, PinName pin, PinMode mode)
        SIM->SCGC6            |= SIM_SCGC6_TPM1_MASK;
        SIM->SOPT2            |= SIM_SOPT2_TPMSRC(1);
 
+       // Reset PLL Source
+       //SIM->SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK;
+
        // Debug print on SOPT2
        // -- mbed may set PLLFLL when configuring UART0
+       // SOPT2: u0src=1 tpmsrc=1 USBSRC PLL/2 clkos=0 rtcos
        sirq_printf("SOPT2: u0src=%d tpmsrc=%d %s %s clkos=%d %s\r\n",
                (SIM->SOPT2 & SIM_SOPT2_UART0SRC_MASK)     >> SIM_SOPT2_UART0SRC_SHIFT,
                (SIM->SOPT2 & SIM_SOPT2_TPMSRC_MASK)       >> SIM_SOPT2_TPMSRC_SHIFT,
@@ -168,15 +203,12 @@ void emit_init(int alt, PinName pin, PinMode mode)
 
 void emit_enable(uint64_t start, uint64_t period)
 {
-       const int slack_clocks = 0x8000; // tune based on emit_worst
+       const int slack_clocks = 0x4000; // tune based on emit_worst
 
        emit_start  = start;
        emit_period = period;
        emit_due    = start + period;
 
-       // TODO - tune slack time
-       // TODO - check clock power
-       // TODO - TPM clock source
        emit_slack  = EMIT_NSEC(slack_clocks);
 
        time_printf("emit scheduled", emit_due);
@@ -184,37 +216,57 @@ void emit_enable(uint64_t start, uint64_t period)
 
 void emit_schedule(uint64_t when)
 {
-       uint64_t now    = time_to_world(tdma_time());
-       uint64_t start  = when - now;     // transmit time
-       uint64_t stop   = start + 100000; // 100 us pulse
+       uint64_t local  = time_to_local(when) * 3 / 125;
+       uint32_t width  = EMIT_CLOCKS(10000);
 
        // Disable timer
        TPM1->SC               = TPM_SC_TOF_MASK;
 
+       __disable_irq();
+
+       uint64_t now    = ((uint64_t)~PIT->LTMR64H << 32)
+                       | ((uint64_t)~PIT->LTMR64L);
+       uint32_t delta  = local - now;
+       uint32_t start  = delta >> (EMIT_PS-1); // convert to clocks
+       uint32_t stop   = start + width;        // end time
+
        // Set transmit time
-       TPM1->CONTROLS[0].CnV  = EMIT_CLOCKS(start);
-       TPM1->MOD              = TPM_MOD_MOD(EMIT_CLOCKS(stop));
+       TPM1->CONTROLS[0].CnV  = start;
+       TPM1->MOD              = TPM_MOD_MOD(stop);
 
        // Start the timer
        TPM1->SC               = TPM_SC_TOF_MASK
-                              | TPM_SC_PS(0)
+                              | TPM_SC_PS(EMIT_PS)
                               | TPM_SC_CMOD(1);
 
+       __enable_irq();
+
+       // Test
+       //int64_t  cnv = TPM1->CONTROLS[0].CnV;
+       //int64_t  mod = TPM1->MOD;
+       //int64_t  due = local - tdma_time();
+       //sirq_printf("%6d -- cnv=%04x mod=%04x due=%04x start=%04x\r\n",
+       //              (int)(cnv - EMIT_CLOCKS(due)),
+       //              (int)cnv, (int)mod,
+       //              (int)EMIT_CLOCKS(due), EMIT_CLOCKS(start));
+
        // Clock testing
-       uint32_t test_tpm0 = TPM1->SC;
-       uint32_t test_pit0 = PIT->CHANNEL[1].CVAL;
-       for (int i = 0; i < 1000; i++)
-               asm("nop");
-       uint32_t test_tpm1 = TPM1->SC;
-       uint32_t test_pit1 = PIT->CHANNEL[1].CVAL;
-       uint32_t test_tpm  = test_tpm0 - test_tpm0;
-       uint32_t test_pit  = test_pit1 - test_pit0;
-       sirq_printf("pit/tpm: tpm=%04hx/%04hx=%d pit=%08x/%08x=%d\r\n",
-                       test_tpm0, test_tpm1, test_tpm,
-                       test_pit0, test_pit1, test_pit);
+       //uint32_t test_tpm0 =  TPM1->CNT;
+       //uint32_t test_pit0 = ~PIT->CHANNEL[0].CVAL;
+       //for (int i = 0; i < 100; i++)
+       //      asm("nop");
+       //uint32_t test_tpm1 =  TPM1->CNT;
+       //uint32_t test_pit1 = ~PIT->CHANNEL[0].CVAL;
+
+       //uint32_t test_tpm  = test_tpm1 - test_tpm0;
+       //uint32_t test_pit  = test_pit1 - test_pit0;
+       //sirq_printf("pit/tpm: %d - tpm=%08x/%08x=%d pit=%08x/%08x=%d\r\n",
+       //              test_tpm - test_pit,
+       //              test_tpm0, test_tpm1, test_tpm,
+       //              test_pit0, test_pit1, test_pit);
 
        // Debug output
-       //sirq_printf("emitting event\r\n");
+       //time_printf("emitting event", when);
 }
 
 void emit_transmit(uint64_t local, uint64_t world)
@@ -342,7 +394,7 @@ void serial_send_sync(sirq_t *port, uint64_t now)
  */
 void serial_send_event(sirq_t *port, uint16_t event, uint64_t local)
 {
-       time_printf("event received", local);
+       //time_printf("event received", local);
 
        // Convert timestamp
        uint64_t world = time_to_world(local);
@@ -646,7 +698,6 @@ void background(void)
 int main(int argc, char **argv)
 {
        tdma_init();
-       emit_init(3, PTE20, PullDown);
 
        //pin = 1;
 
@@ -675,8 +726,11 @@ int main(int argc, char **argv)
        serial_tdma_rcv = tdma_rcv;
        serial_tdma_xmt = tdma_xmt;
 
+       // Setup event generation
+       emit_init(3, PTE20, PullDown);
+
        // configure crystal oscilator for high gain operation
-       MCG->C2 |= MCG_C2_HGO0_MASK;
+       //MCG->C2 |= MCG_C2_HGO0_MASK;
 
        // Test clocks
        //MCG->C1    = 0x05; // was 0x1A
index 9a803acc7ef4f41821ff0e0a5f940c478ad5aebf..f80572e51fad8956f02879e5728f58d031bd7aab 100644 (file)
@@ -215,7 +215,7 @@ uint64_t tdma_time(void)
                        | ((uint64_t)~tml) << 0;\r
 \r
        // Convert to nanoseconds\r
-       return clocks * 1000 / 24;\r
+       return clocks * 125 / 3;\r
 }\r
 \r
 void tdma_debug(tdma_t *port)\r