* 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;
(uint32_t)(error % (int64_t)NSEC_PER_SEC));
#endif
//#endif
-
- // .000000284
- // .000000253
- // .000000264
- // .000000451
- // .000000284
- // .000000267
- // .000000223
- // .000000326
-
}
void time_printf(const char *label, uint64_t local)
static uint32_t *emit_pcr = 0; // transmit pin name
-static uint64_t emit_start = 0; // transmit start time
+static uint64_t emit_start = 0; // transmit start time (world time)
static uint64_t emit_period = 0; // transmit period
-static uint64_t emit_due = 0; // next transmit time
+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("scheuled emit - ", emit_due);
+ time_printf("emit scheduled", emit_due);
}
void emit_schedule(uint64_t when)
{
- uint64_t now = tdma_time();
+ uint64_t now = time_to_world(tdma_time());
uint16_t delay = (uint16_t)(when-now);
// Clear pending flags
// Start the timer
TPM0->SC = TPM_SC_TOF_MASK
| TPM_SC_CMOD(1);
+
+ // Debug
+ 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 = 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 (world+emit_slack > emit_due)
+ if (emit_due && emit_period &&
+ world+emit_slack > emit_due) {
emit_schedule(emit_due);
+ 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 serial_handle_init(init_msg_t *msg)
{
+ sirq_printf("initialize: %s %s %s %s %s\r\n",
+ msg->valid & MSG_VALID_DEVICE ? "DEV" : "dev",
+ msg->valid & MSG_VALID_START ? "START" : "start",
+ msg->valid & MSG_VALID_PERIOD ? "PERIOD" : "period",
+ msg->valid & MSG_VALID_WORLD ? "WORLD" : "world",
+ msg->valid & MSG_VALID_SYNC ? "SYNC" : "sync");
+ sirq_printf(" dev -- %d\r\n", msg->device);
+ time_printf(" start ", serial_read_time(msg->start));
+ time_printf(" period", serial_read_time(msg->period));
+ time_printf(" world ", serial_read_time(msg->world));
+
if (msg->valid & MSG_VALID_DEVICE)
serial_device_id = msg->device;
- if ((msg->valid & MSG_VALID_START) ||
- (msg->valid & MSG_VALID_PERIOD)) {
+ if (msg->valid & MSG_VALID_START ||
+ msg->valid & MSG_VALID_PERIOD) {
uint64_t start = serial_read_time(msg->start);
uint64_t period = serial_read_time(msg->period);
emit_enable(start, period);
uint64_t local = tdma_time();
time_ext_init(local, world);
}
+
+ if (msg->valid & MSG_VALID_SYNC)
+ serial_sync_due = tdma_time() + serial_sync_delay;
}
/**
void task_emit(uint64_t local, uint64_t world)
{
- emit_transmit();
+ emit_transmit(local, world);
}
void task_debug(uint64_t local, uint64_t world)
int main(int argc, char **argv)
{
tdma_init();
+ emit_init(4, PTC1, PullDown);
// Open serial ports
sirq_dbg = sirq_open(SIRQ_UART0, USBTX, USBRX, 115200); // to pc
//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();