From: Andy Spencer Date: Thu, 13 Mar 2014 06:31:11 +0000 (+0000) Subject: Save a working version of TPM X-Git-Url: http://pileus.org/git/?p=~andy%2Fcsm213a-hw;a=commitdiff_plain;h=dad3dcaa103d9f23921ad2bb91b16c464a7878ac Save a working version of TPM --- diff --git a/hw2/main.cpp b/hw2/main.cpp index 47b701b..d824863 100644 --- a/hw2/main.cpp +++ b/hw2/main.cpp @@ -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 diff --git a/hw2/timer_dma.c b/hw2/timer_dma.c index 9a803ac..f80572e 100644 --- a/hw2/timer_dma.c +++ b/hw2/timer_dma.c @@ -215,7 +215,7 @@ uint64_t tdma_time(void) | ((uint64_t)~tml) << 0; // Convert to nanoseconds - return clocks * 1000 / 24; + return clocks * 125 / 3; } void tdma_debug(tdma_t *port)