* Time synchronization is performed in both directions.
*/
-/****************
- * Testing vars *
- ****************/
-
-uint32_t test_xmt_enab = 0;
-uint64_t test_xmt_time0 = 0;
-uint64_t test_xmt_time1 = 0;
-
-uint32_t test_rcv_enab = 0;
-uint64_t test_rcv_time = 0;
-
/*******************
* Timer functions *
*******************/
world = time_last_world;
//#ifdef VERBOSE
-#if 0
+#if 1
uint64_t error = world > guess ? world - guess :
guess > world ? guess - world : 0;
int ahead = guess > world;
static uint64_t emit_period = 0; // transmit period
static uint64_t emit_due = 0; // next transmit (world time)
-static uint32_t emit_slack = 0; // how far ahead we need to schedule
+static uint32_t emit_slack = 0; // how far ahead we need to schedule, in us
static uint32_t emit_worst = 0; // worst-case latency in task table
void emit_init(int alt, PinName pin, PinMode mode)
void emit_enable(uint64_t start, uint64_t period)
{
+ const int slack_tick = 0xC000; // tune based on emit_worst
+
emit_start = start;
emit_period = period;
emit_due = start + period;
- emit_slack = 10000; // tune based on emit_worst
+ emit_slack = slack_tick * 1000 / 24;
time_printf("emit scheduled", emit_due);
}
| TPM_SC_CMOD(1);
// Debug
- //sirq_printf("emitting event\r\n");
+ sirq_printf("emitting event\r\n");
}
-void emit_transmit(void)
+void emit_transmit(uint64_t local, uint64_t world)
{
- static uint64_t prev;
-
- // Get a fresh timestamp
- uint64_t world = time_to_world(tdma_time());
+ static uint64_t prev = 0;
// Record how how much time we have to reschedule
- if (prev && world - prev > emit_worst)
- emit_worst = prev;
+ if (prev && (local-prev) > emit_worst)
+ emit_worst = (local-prev);
+ prev = local;
// Schedule task if needed
if (emit_due && emit_period &&
tdma_stop(serial_tdma_rcv);
- test_xmt_enab = 1;
- test_xmt_time0 = 0;
- test_xmt_time1 = 0;
-
tdma_start(serial_tdma_xmt);
sirq_write(port, &head, sizeof(head));
sirq_write(port, &body, sizeof(body));
tdma_stop(serial_tdma_xmt);
// save transmit time
- //local = test_xmt_time1;
int valid = tdma_stamp(serial_tdma_xmt, &local);
- if (!valid) {
+ if (!valid)
sirq_printf("sync transmit time -- missed\r\n");
- } else {
+ else
//time_printf("sync transmit time ", local);
- //time_printf("sync transmit test0", test_xmt_time0);
- //time_printf("sync transmit test1", test_xmt_time1);
- }
tdma_start(serial_tdma_rcv);
tdma_stop(serial_tdma_rcv);
- test_xmt_enab = 1;
- test_xmt_time0 = 0;
- test_xmt_time1 = 0;
-
tdma_start(serial_tdma_xmt);
sirq_write(port, &head, sizeof(head));
sirq_write(port, &body, sizeof(body));
void task_emit(uint64_t local, uint64_t world)
{
- emit_transmit();
+ emit_transmit(local, world);
}
void task_debug(uint64_t local, uint64_t world)
//sirq_printf("MGC - C10 %02hx\r\n", MCG->C10); // 00
// Run background loop
- printf("hello");
while (true)
background();
+ // Performance testing
+ //uint64_t prev = 0, due = 0;
+ //uint64_t worst[10] = {};
+ //int count = 0;
+ //while (true) {
+ // uint64_t local = tdma_time();
+ // if (prev && (local-prev) > worst[count])
+ // worst[count] = (local-prev);
+ // prev = local;
+ // if (local > due) {
+ // if (count == 5) {
+ // static char str[] = "background background background\r\n";
+ // sirq_write(sirq_dbg, str, sizeof(str));
+ // }
+ // if (count == 9) {
+ // sirq_printf("background\r\n");
+ // for (int i = 0; i < 10; i++) {
+ // sirq_printf(" worst[%d] = 0.%09u\r\n",
+ // i, worst[i]);
+ // worst[i] = 0;
+ // }
+ // }
+ // due += NSEC_PER_SEC;
+ // count = (count + 1) % 10;
+ // }
+ //}
+
// Run tests
//test_main();
serial_t uart;\r
queue_t xmt;\r
queue_t rcv;\r
+ int irq;\r
};\r
\r
-/* Test data */\r
-extern uint32_t test_xmt_enab;\r
-extern uint64_t test_xmt_time0;\r
-extern uint64_t test_xmt_time1;\r
-\r
-extern uint32_t test_rcv_enab;\r
-extern uint64_t test_rcv_time;\r
-\r
/* Port data */\r
static sirq_t sirq_ports[SIRQ_NUM_UART];\r
\r
// Handle transmit\r
if (event == TxIrq && port->xmt.rix != port->xmt.wix) {\r
int byte = port->xmt.buf[port->xmt.rix];\r
-\r
- uint64_t time0 = tdma_time();\r
serial_putc(&port->uart, byte);\r
- uint64_t time1 = tdma_time();\r
-\r
- if (test_xmt_enab) {\r
- test_xmt_time0 = time0;\r
- test_xmt_time1 = time1;\r
- test_xmt_enab = 0;\r
- }\r
-\r
port->xmt.rix = (port->xmt.rix+1) % SIRQ_LEN;\r
} else {\r
serial_irq_set(&port->uart, TxIrq, 0);\r
+ port->irq = 0;\r
}\r
\r
// Handle receive\r
{\r
port->xmt.buf[port->xmt.wix] = byte;\r
port->xmt.wix = (port->xmt.wix+1) % SIRQ_LEN;\r
- serial_irq_set(&port->uart, TxIrq, 1);\r
+ if (!port->irq) {\r
+ port->irq = 1;\r
+ serial_irq_set(&port->uart, TxIrq, 1);\r
+ }\r
}\r
\r
/* Read byte from the port */\r