From: Andy Spencer Date: Wed, 12 Mar 2014 17:26:50 +0000 (+0000) Subject: Perform no-delay time synchronization X-Git-Url: http://pileus.org/git/?p=~andy%2Fcsm213a-hw;a=commitdiff_plain;h=16ad7d215971b9bbd79007f7c334c4f8d9659c49 Perform no-delay time synchronization --- diff --git a/hw2/main.cpp b/hw2/main.cpp index d32dd0c..3e82918 100644 --- a/hw2/main.cpp +++ b/hw2/main.cpp @@ -220,18 +220,12 @@ typedef struct { static uint32_t serial_device_id = 0; -const uint64_t serial_sync_delay = NSEC_PER_SEC / 100; // 1hz +const uint64_t serial_sync_delay = NSEC_PER_SEC / 100; static uint64_t serial_sync_due = 0; static tdma_t *serial_tdma_rcv = NULL; static tdma_t *serial_tdma_xmt = NULL; -static uint64_t serial_prev_local = 0; -static uint64_t serial_prev_seq = 0; - -static uint64_t serial_xmt_local = 0; -static uint64_t serial_xmt_seq = 0; - /** * Convert world to local time */ @@ -249,6 +243,20 @@ ntime_t serial_write_time(uint64_t time) return buf; } +int serial_time_stamp(tdma_t *port, uint64_t *local, uint64_t *world, + const char *msg) +{ + int valid = tdma_stamp(port, local); + *world = time_to_world(*local); + + if (!valid) + sirq_printf("%s -- missing\r\n", msg); + //else + // time_printf(msg, current); + + return valid; +} + /** * Output initialization message init message */ @@ -264,45 +272,41 @@ void serial_send_sync(sirq_t *port, uint64_t now) if (serial_sync_due == 0 || now < serial_sync_due) return; // not ready - //sirq_printf("sending sync\r\n"); - - // Calculate world time - uint64_t local = 0; - uint64_t world = time_to_world(serial_xmt_local); - // Message data header_t head; sync_msg_t body; - // Transmit sync message + // Write header head.header = MSG_HEADER; head.msgid = MSG_ID_SYNC; head.length = sizeof(body); head.cksum = 0; // todo - body.seq = serial_xmt_seq; - body.time.seconds = world / NSEC_PER_SEC; - body.time.nanosec = world % NSEC_PER_SEC; - - tdma_stop(serial_tdma_rcv); - + tdma_stop(serial_tdma_rcv, 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 - int valid = tdma_stamp(serial_tdma_xmt, &local); - if (!valid) - sirq_printf("sync transmit time -- missed\r\n"); - else - //time_printf("sync transmit time ", local); + sirq_write(port, &head, sizeof(head)); + tdma_stop(serial_tdma_xmt, 100); tdma_start(serial_tdma_rcv); - serial_xmt_seq += 1; + // Save transmit time + uint64_t local = 0, world = 0; + serial_time_stamp(serial_tdma_xmt, &local, &world, + "sync time transmit"); + + // Debug output + //sirq_printf("sync time transmit\r\n"); + //time_printf(" local", local); + //time_printf(" world", world); + + // Write body with updated time and send + body.time = serial_write_time(world); + + sirq_write(port, &body, sizeof(body)); + + // Queue next transmit time serial_sync_due = 0; - serial_xmt_local = local; } /** @@ -380,31 +384,26 @@ void serial_handle_init(init_msg_t *msg) */ void serial_handle_sync(sync_msg_t *msg) { - // Read receive timestamp for next time sync message - uint64_t current = 0; - int valid = tdma_stamp(serial_tdma_rcv, ¤t); - if (!valid) - sirq_printf("sync receive time -- missing\r\n"); - //else - // time_printf("sync receive time ", current); - tdma_stop(serial_tdma_rcv); + // Read receive timestamp + uint64_t local = 0, world = 0; + serial_time_stamp(serial_tdma_rcv, &local, &world, + "sync time receive "); + tdma_stop(serial_tdma_rcv, 0); - // Lookup times - uint64_t world = ((uint64_t)msg->time.seconds) * NSEC_PER_SEC - + ((uint64_t)msg->time.nanosec); + // Lookup reference time from message + uint64_t reference = serial_read_time(msg->time); - // Valid times timestamp - if (serial_prev_seq == (msg->seq-1)) { - uint64_t local = serial_prev_local; - time_ext_sync(local, world); - } + // Debug output + //sirq_printf("sync time receive\r\n"); + //time_printf(" local", local); + //time_printf(" world", world); + //time_printf(" ref ", reference); + + // Synchronize the clocks + time_ext_sync(local, reference); // Queue transmit to other board serial_sync_due = tdma_time() + serial_sync_delay; - - // Update states - serial_prev_local = current; - serial_prev_seq = msg->seq; } /** @@ -541,7 +540,7 @@ void task_events(uint64_t local, uint64_t world) if (tdma_stamp(tdma_evt, &event)) serial_send_event(sirq_bbb, 0, event); - tdma_stop(tdma_evt); + tdma_stop(tdma_evt, 0); tdma_start(tdma_evt); } diff --git a/hw2/messages.h b/hw2/messages.h index cefdecf..752476f 100644 --- a/hw2/messages.h +++ b/hw2/messages.h @@ -42,7 +42,6 @@ typedef struct { } init_msg_t; typedef struct { - uint32_t seq; // Current sequence counter ntime_t time; // Time of previous message } sync_msg_t; diff --git a/hw2/timer_dma.c b/hw2/timer_dma.c index 529fd7e..7d06bac 100644 --- a/hw2/timer_dma.c +++ b/hw2/timer_dma.c @@ -158,13 +158,17 @@ void tdma_start(tdma_t *port) //sirq_printf("isfr3: %08x\r\n", PORTD->ISFR); } -void tdma_stop(tdma_t *port) +void tdma_stop(tdma_t *port, int wait) { if (!port) return; //sirq_printf("isfr0: %08x\r\n", PORTD->ISFR); + for (int i = 0; port->dma->dsr & DMA_DSR_BCR_BCR_MASK; i++) + if (i > wait) + return 0; + // Disable DMA Mux port->mux->cfg &= DMAMUX_CHCFG_ENBL_MASK; diff --git a/hw2/timer_dma.h b/hw2/timer_dma.h index e35af73..41370fb 100644 --- a/hw2/timer_dma.h +++ b/hw2/timer_dma.h @@ -31,7 +31,7 @@ tdma_t *tdma_open(tdma_chan_t chan, int alt, PinName pin, PinMode mode); /* Flush/Wait */ void tdma_start(tdma_t *port); -void tdma_stop(tdma_t *port); +void tdma_stop(tdma_t *port, int wait); int tdma_stamp(tdma_t *port, uint64_t *time); /* Time */