]> Pileus Git - ~andy/csm213a-hw/blobdiff - hw2/main.cpp
Fix bug in irq code
[~andy/csm213a-hw] / hw2 / main.cpp
index d4c0b046737222fb00127e02c68619fc32c76359..9292124da454b95e442519ba975843df35c051d1 100644 (file)
  *   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 *
  *******************/
@@ -112,7 +101,7 @@ void time_ext_sync(uint64_t local, uint64_t world)
        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;
@@ -127,16 +116,6 @@ void time_ext_sync(uint64_t local, uint64_t 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)
@@ -156,11 +135,11 @@ 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)
@@ -200,18 +179,20 @@ 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
@@ -227,22 +208,26 @@ void emit_schedule(uint64_t when)
        // 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;
+       }
 }
 
 /************************
@@ -323,25 +308,17 @@ void serial_send_sync(sirq_t *port, uint64_t now)
 
        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);
 
@@ -384,10 +361,6 @@ void serial_send_event(uint16_t event, uint64_t local)
 
        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));
@@ -400,11 +373,22 @@ void serial_send_event(uint16_t event, uint64_t local)
  */
 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);
@@ -415,6 +399,9 @@ void serial_handle_init(init_msg_t *msg)
                uint64_t local = tdma_time();
                time_ext_init(local, world);
        }
+
+       if (msg->valid & MSG_VALID_SYNC)
+               serial_sync_due = tdma_time() + serial_sync_delay;
 }
 
 /**
@@ -602,7 +589,7 @@ void task_leds(uint64_t local, uint64_t world)
 
 void task_emit(uint64_t local, uint64_t world)
 {
-       emit_transmit();
+       emit_transmit(local, world);
 }
 
 void task_debug(uint64_t local, uint64_t world)
@@ -661,6 +648,7 @@ void background(void)
 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
@@ -719,10 +707,36 @@ int main(int argc, char **argv)
        //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();