Commit a788f220 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

rewrote pps_gen driver (to match the libswitchhw one), removed remaining…

rewrote pps_gen driver (to match the libswitchhw one), removed remaining references to UTC timescale
parent cd34a40e
...@@ -168,7 +168,8 @@ int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size, struct hw_ ...@@ -168,7 +168,8 @@ int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size, struct hw_
if(RX_DESC_HAS_OOB(desc_hdr) && hwts != NULL) if(RX_DESC_HAS_OOB(desc_hdr) && hwts != NULL)
{ {
uint32_t counter_r, counter_f, counter_ppsg, utc; uint32_t counter_r, counter_f, counter_ppsg;
uint64_t sec;
int cntr_diff; int cntr_diff;
uint16_t dhdr; uint16_t dhdr;
...@@ -178,12 +179,14 @@ int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size, struct hw_ ...@@ -178,12 +179,14 @@ int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size, struct hw_
memcpy(&dhdr, (uint8_t *)minic.rx_head + payload_size + 4, 2); memcpy(&dhdr, (uint8_t *)minic.rx_head + payload_size + 4, 2);
EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f); EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f);
pps_gen_get_time(&utc, &counter_ppsg); pps_gen_get_time(&sec, &counter_ppsg);
if(counter_r > 3*125000000/4 && counter_ppsg < 125000000/4) counter_ppsg /= (REF_CLOCK_PERIOD_PS / 1000);
utc--;
if(counter_r > 3*REF_CLOCK_FREQ_HZ/4 && counter_ppsg < REF_CLOCK_FREQ_HZ/4)
sec--;
hwts->utc = utc & 0x7fffffff ; hwts->sec = sec & 0x7fffffff ;
cntr_diff = (counter_r & F_COUNTER_MASK) - counter_f; cntr_diff = (counter_r & F_COUNTER_MASK) - counter_f;
...@@ -258,16 +261,14 @@ int minic_tx_frame(uint8_t *hdr, uint8_t *payload, uint32_t size, struct hw_time ...@@ -258,16 +261,14 @@ int minic_tx_frame(uint8_t *hdr, uint8_t *payload, uint32_t size, struct hw_time
while((minic_readl(MINIC_REG_MCR) & MINIC_MCR_TX_IDLE) == 0); while((minic_readl(MINIC_REG_MCR) & MINIC_MCR_TX_IDLE) == 0);
#if 1
if(hwts) /* wait for the timestamp */ if(hwts) /* wait for the timestamp */
{ {
uint32_t raw_ts; uint32_t raw_ts;
uint16_t fid; uint16_t fid;
uint32_t counter_r, counter_f; uint32_t counter_r, counter_f;
uint32_t utc; uint64_t sec;
uint32_t nsec; uint32_t nsec;
//while((minic_readl(MINIC_REG_TSR0) & MINIC_TSR0_VALID) == 0);
ts_valid = (uint8_t) (minic_readl(MINIC_REG_TSR0) & MINIC_TSR0_VALID); ts_valid = (uint8_t) (minic_readl(MINIC_REG_TSR0) & MINIC_TSR0_VALID);
raw_ts = minic_readl(MINIC_REG_TSR1); raw_ts = minic_readl(MINIC_REG_TSR1);
...@@ -278,21 +279,21 @@ int minic_tx_frame(uint8_t *hdr, uint8_t *payload, uint32_t size, struct hw_time ...@@ -278,21 +279,21 @@ int minic_tx_frame(uint8_t *hdr, uint8_t *payload, uint32_t size, struct hw_time
TRACE_DEV("minic_tx_frame: unmatched fid %d vs %d\n", fid, tx_oob_val); TRACE_DEV("minic_tx_frame: unmatched fid %d vs %d\n", fid, tx_oob_val);
} }
EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f); EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f);
pps_gen_get_time(&utc, &nsec); pps_gen_get_time(&sec, &nsec);
if(counter_r > 3*125000000/4 && nsec < 125000000/4) if(counter_r > 3*REF_CLOCK_FREQ_HZ/4 && nsec < REF_CLOCK_FREQ_HZ/4)
utc--; sec--;
hwts->valid = ts_valid; hwts->valid = ts_valid;
hwts->utc = utc; hwts->sec = sec;
hwts->ahead = 0; hwts->ahead = 0;
hwts->nsec = counter_r * 8; hwts->nsec = counter_r * 8;
// TRACE_DEV("minic_tx_frame [%d bytes] TS: %d.%d valid %d\n", size, hwts->utc, hwts->nsec, hwts->valid); // TRACE_DEV("minic_tx_frame [%d bytes] TS: %d.%d valid %d\n", size, hwts->utc, hwts->nsec, hwts->valid);
minic.tx_count++; minic.tx_count++;
} }
#endif
tx_oob_val++; tx_oob_val++;
return size; return size;
......
#include "board.h" #include "board.h"
#include "pps_gen.h"
#include <inttypes.h> #include "hw/pps_gen_regs.h"
/* PPS Generator driver */
#include <hw/pps_gen_regs.h> /* Warning: references to "UTC" in the registers DO NOT MEAN actual UTC time, it's just a plain second counter
It doesn't care about leap seconds. */
#define PPS_PULSE_WIDTH 100000 /* Default width (in 8ns units) of the pulses on the PPS output */
static volatile struct PPSG_WB *PPSG = (volatile struct PPS_GEN_WB *) BASE_PPS_GEN; #define PPS_WIDTH 100000
void pps_gen_init() #define ppsg_write(reg, val) \
{ *(volatile uint32_t *) (BASE_PPS_GEN + (offsetof(struct PPSG_WB, reg))) = (val)
pps_gen_set_time(0, 0);
}
void pps_gen_adjust_nsec(int32_t how_much) #define ppsg_read(reg) \
{ *(volatile uint32_t *) (BASE_PPS_GEN + (offsetof(struct PPSG_WB, reg)))
TRACE_DEV("ADJ: nsec %d nanoseconds\n", how_much);
PPSG->ADJ_UTCLO = 0;
PPSG->ADJ_UTCHI = 0;
PPSG->ADJ_NSEC = ( how_much / 8 );
PPSG->CR = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_PULSE_WIDTH) | PPSG_CR_CNT_ADJ;
}
void pps_gen_adjust_utc(int32_t how_much) int pps_gen_init()
{ {
TRACE_DEV("ADJ: utc %d seconds\n", how_much); uint32_t cr;
PPSG->ADJ_UTCLO = how_much;
PPSG->ADJ_UTCHI = 0; cr = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_WIDTH);
PPSG->ADJ_NSEC = 0;
PPSG->CR = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_PULSE_WIDTH) | PPSG_CR_CNT_ADJ; ppsg_write(CR, cr);
ppsg_write(ADJ_UTCLO, 0);
ppsg_write(ADJ_UTCHI, 0);
ppsg_write(ADJ_NSEC, 0);
ppsg_write(CR, cr | PPSG_CR_CNT_SET);
ppsg_write(CR, cr);
ppsg_write(ESCR, 0x6); /* enable PPS output */
} }
int pps_gen_busy() /* Adjusts the nanosecond (refclk cycle) counter by atomically adding (how_much) cycles. */
int pps_gen_adjust(int counter, int64_t how_much)
{ {
return PPSG->CR & PPSG_CR_CNT_ADJ ? 0 : 1; uint32_t cr;
TRACE_DEV("Adjust: counter = %s [%c%lld]",
counter == PPSG_ADJUST_SEC ? "seconds" : "nanoseconds", how_much<0?'-':'+', abs(how_much));
if(counter == PPSG_ADJUST_NSEC)
{
ppsg_write(ADJ_UTCLO, 0);
ppsg_write(ADJ_UTCHI, 0);
ppsg_write(ADJ_NSEC, (int32_t) ((int64_t) how_much * 1000LL / (int64_t)REF_CLOCK_PERIOD_PS));
} else {
ppsg_write(ADJ_UTCLO, (uint32_t ) (how_much & 0xffffffffLL));
ppsg_write(ADJ_UTCHI, (uint32_t ) (how_much >> 32) & 0xff);
ppsg_write(ADJ_NSEC, 0);
}
ppsg_write(CR, ppsg_read(CR) | PPSG_CR_CNT_ADJ);
return 0;
} }
void pps_gen_set_time(uint32_t utc, uint32_t nsec) /* Sets the current time */
int pps_gen_set_time(uint64_t seconds, uint32_t nanoseconds)
{ {
uint32_t cr = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_PULSE_WIDTH); uint32_t cr;
PPSG->CR = cr;
PPSG->ESCR = 0;
PPSG->ADJ_UTCLO = utc; ppsg_write(ADJ_UTCLO, (uint32_t ) (seconds & 0xffffffffLL));
PPSG->ADJ_UTCHI = 0; ppsg_write(ADJ_UTCHI, (uint32_t ) (seconds >> 32) & 0xff);
PPSG->ADJ_NSEC = nsec; ppsg_write(ADJ_NSEC, (int32_t) ((int64_t) nanoseconds * 1000LL / (int64_t)REF_CLOCK_PERIOD_PS));
PPSG->CR = cr | PPSG_CR_CNT_SET; ppsg_write(CR, ppsg_read(CR) | PPSG_CR_CNT_SET);
PPSG->CR = cr; return 0;
} }
void pps_gen_get_time(uint32_t *utc, uint32_t *cntr_nsec) void pps_gen_get_time(uint64_t *seconds, uint32_t *nanoseconds)
{ {
uint32_t cyc_before, cyc_after; uint32_t ns_cnt;
uint32_t utc_lo; uint64_t sec1, sec2;
do { do {
cyc_before = PPSG->CNTR_NSEC & 0xfffffff; sec1 = (uint64_t)ppsg_read(CNTR_UTCLO) | (uint64_t)ppsg_read(CNTR_UTCHI) << 32;
utc_lo = PPSG->CNTR_UTCLO ; ns_cnt = ppsg_read(CNTR_NSEC);
cyc_after = PPSG->CNTR_NSEC & 0xfffffff; sec2 = (uint64_t)ppsg_read(CNTR_UTCLO) | (uint64_t)ppsg_read(CNTR_UTCHI) << 32;
} while (cyc_after < cyc_before); } while(sec2 != sec1);
// delay(100000); if(seconds) *seconds = sec2;
if(nanoseconds) *nanoseconds = (uint32_t) ((int64_t)ns_cnt * (int64_t) REF_CLOCK_PERIOD_PS / 1000LL);
if(utc) *utc = utc_lo;
if(cntr_nsec) *cntr_nsec = cyc_after;
} }
void pps_gen_enable_output(int enable) /* Returns 1 when the adjustment operation is not yet finished */
int pps_gen_busy()
{ {
if(enable) uint32_t cr = ppsg_read(CR);
PPSG->ESCR = PPSG_ESCR_PPS_VALID | PPSG_ESCR_TM_VALID; return cr & PPSG_CR_CNT_ADJ ? 0 : 1;
else
PPSG->ESCR = 0;
} }
/* Enables/disables PPS output */
int pps_gen_enable_output(int enable)
{
uint32_t escr = ppsg_read(ESCR);
if(enable)
ppsg_write(ESCR, escr | PPSG_ESCR_PPS_VALID);
else
ppsg_write(ESCR, escr & ~PPSG_ESCR_PPS_VALID);
return 0;
}
...@@ -13,6 +13,9 @@ ...@@ -13,6 +13,9 @@
#define CPU_CLOCK 62500000ULL #define CPU_CLOCK 62500000ULL
#define REF_CLOCK_PERIOD_PS 8000
#define REF_CLOCK_FREQ_HZ 125000000
#define UART_BAUDRATE 115200ULL /* not a real UART */ #define UART_BAUDRATE 115200ULL /* not a real UART */
static inline void delay(int x) static inline void delay(int x)
......
#ifndef __PPS_GEN_H #ifndef __PPS_GEN_H
#define __PPS_GEN_H #define __PPS_GEN_H
#include <inttypes.h> #include <stdint.h>
void pps_gen_init(); #define PPSG_ADJUST_SEC 0x1
void pps_gen_adjust_nsec(int32_t how_much); #define PPSG_ADJUST_NSEC 0x2
void shw_pps_gen_adjust_utc(int32_t how_much);
int pps_gen_busy(); /* Initializes the PPS Generator. 0 on success, negative on failure. */
void pps_gen_get_time(uint32_t *utc, uint32_t *cntr_nsec); int shw_pps_gen_init();
void pps_gen_set_time(uint32_t utc, uint32_t nsec);
/* Adjusts the <counter> (PPSG_ADJUST_SEC/NSEC) by (how_much) seconds/nanoseconds */
int shw_pps_gen_adjust(int counter, int64_t how_much);
/* Returns 1 when the PPS is busy adjusting its time counters, 0 if PPS gen idle */
int shw_pps_gen_busy();
/* Enables/disables PPS Generator PPS output */
int shw_pps_gen_enable_output(int enable);
/* Reads the current time and stores at <seconds,nanoseconds>. */
void shw_pps_gen_get_time(uint64_t *seconds, uint32_t *nanoseconds);
/* Sets the time to <seconds,nanoseconds>. */
void shw_pps_gen_set_time(uint64_t seconds, uint32_t nanoseconds);
#endif #endif
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
struct hw_timestamp { struct hw_timestamp {
uint8_t valid; uint8_t valid;
int ahead; int ahead;
uint32_t utc; uint64_t sec;
uint32_t nsec; uint32_t nsec;
uint32_t phase; uint32_t phase;
}; };
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#define C_BLUE 4 #define C_BLUE 4
/* Return TAI date/time in human-readable form. Non-reentrant. */ /* Return TAI date/time in human-readable form. Non-reentrant. */
char *format_time(uint32_t utc); char *format_time(uint64_t sec);
/* Color printf() variant. */ /* Color printf() variant. */
void cprintf(int color, const char *fmt, ...); void cprintf(int color, const char *fmt, ...);
......
...@@ -34,15 +34,15 @@ static const int _ytab[2][12] = { ...@@ -34,15 +34,15 @@ static const int _ytab[2][12] = {
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
}; };
char *format_time(uint32_t utc) char *format_time(uint64_t sec)
{ {
struct tm t; struct tm t;
static char buf[64]; static char buf[64];
unsigned long dayclock, dayno; unsigned long dayclock, dayno;
int year = EPOCH_YR; int year = EPOCH_YR;
dayclock = (unsigned long)utc % SECS_DAY; dayclock = (unsigned long)sec % SECS_DAY;
dayno = (unsigned long)utc / SECS_DAY; dayno = (unsigned long)sec / SECS_DAY;
t.tm_sec = dayclock % 60; t.tm_sec = dayclock % 60;
t.tm_min = (dayclock % 3600) / 60; t.tm_min = (dayclock % 3600) / 60;
......
...@@ -16,12 +16,13 @@ extern int wrc_man_phase; ...@@ -16,12 +16,13 @@ extern int wrc_man_phase;
int wrc_mon_gui(void) int wrc_mon_gui(void)
{ {
static char* slave_states[] = {"Uninitialized", "SYNC_UTC", "SYNC_NSEC", "SYNC_PHASE", "TRACK_PHASE"}; static char* slave_states[] = {"Uninitialized", "SYNC_SEC", "SYNC_NSEC", "SYNC_PHASE", "TRACK_PHASE"};
static uint32_t last = 0; static uint32_t last = 0;
hexp_port_state_t ps; hexp_port_state_t ps;
int tx, rx; int tx, rx;
int aux_stat; int aux_stat;
int32_t utc,nsec; uint64_t sec;
uint32_t nsec;
if(timer_get_tics() - last < UI_REFRESH_PERIOD) if(timer_get_tics() - last < UI_REFRESH_PERIOD)
return 0; return 0;
...@@ -33,10 +34,10 @@ int wrc_mon_gui(void) ...@@ -33,10 +34,10 @@ int wrc_mon_gui(void)
pcprintf(1, 1, C_BLUE, "WR PTP Core Sync Monitor v 1.0"); pcprintf(1, 1, C_BLUE, "WR PTP Core Sync Monitor v 1.0");
pcprintf(2, 1, C_GREY, "Esc = exit"); pcprintf(2, 1, C_GREY, "Esc = exit");
pps_gen_get_time(&utc, &nsec); pps_gen_get_time(&sec, &nsec);
cprintf(C_BLUE, "\n\nUTC Time: "); cprintf(C_BLUE, "\n\nTAI Time: ");
cprintf(C_WHITE, "%s", format_time(utc)); cprintf(C_WHITE, "%s", format_time(sec));
/*show_ports*/ /*show_ports*/
halexp_get_port_state(&ps, NULL); halexp_get_port_state(&ps, NULL);
...@@ -114,14 +115,15 @@ int wrc_mon_gui(void) ...@@ -114,14 +115,15 @@ int wrc_mon_gui(void)
int wrc_log_stats(void) int wrc_log_stats(void)
{ {
static char* slave_states[] = {"Uninitialized", "SYNC_UTC", "SYNC_NSEC", "SYNC_PHASE", "TRACK_PHASE"}; static char* slave_states[] = {"Uninitialized", "SYNC_SEC", "SYNC_NSEC", "SYNC_PHASE", "TRACK_PHASE"};
static uint32_t last = 0; static uint32_t last = 0;
hexp_port_state_t ps; hexp_port_state_t ps;
int tx, rx; int tx, rx;
int aux_stat; int aux_stat;
uint32_t utc, nsec; uint64_t sec;
uint32_t nsec;
pps_gen_get_time(&utc, &nsec); pps_gen_get_time(&sec, &nsec);
halexp_get_port_state(&ps, NULL); halexp_get_port_state(&ps, NULL);
minic_get_stats(&tx, &rx); minic_get_stats(&tx, &rx);
mprintf("lnk:%d rx:%d tx:%d ", ps.up, rx, tx); mprintf("lnk:%d rx:%d tx:%d ", ps.up, rx, tx);
...@@ -130,7 +132,7 @@ int wrc_log_stats(void) ...@@ -130,7 +132,7 @@ int wrc_log_stats(void)
mprintf("ss:'%s' ", cur_servo_state.slave_servo_state); mprintf("ss:'%s' ", cur_servo_state.slave_servo_state);
aux_stat = spll_get_aux_status(0); aux_stat = spll_get_aux_status(0);
mprintf("aux:%x ", aux_stat); mprintf("aux:%x ", aux_stat);
mprintf("utc:%d nsec:%d ", utc,nsec*8); /* fixme: clock is not always 125 MHz */ mprintf("sec:%d nsec:%d ", (uint32_t) sec, nsec); /* fixme: clock is not always 125 MHz */
mprintf("mu:%d ", (int32_t)cur_servo_state.mu); mprintf("mu:%d ", (int32_t)cur_servo_state.mu);
mprintf("dms:%d ", (int32_t)cur_servo_state.delay_ms); mprintf("dms:%d ", (int32_t)cur_servo_state.delay_ms);
mprintf("dtxm:%d drxm:%d ", (int32_t)cur_servo_state.delta_tx_m, (int32_t)cur_servo_state.delta_rx_m); mprintf("dtxm:%d drxm:%d ", (int32_t)cur_servo_state.delta_tx_m, (int32_t)cur_servo_state.delta_rx_m);
......
...@@ -10,16 +10,17 @@ ...@@ -10,16 +10,17 @@
#include <string.h> #include <string.h>
#include "shell.h" #include "shell.h"
#include "util.h"
#include "wrc_ptp.h" #include "wrc_ptp.h"
#include "pps_gen.h" #include "pps_gen.h"
extern char *format_time(uint32_t utc);
int cmd_time(const char *args[]) int cmd_time(const char *args[])
{ {
uint32_t utc, nsec; uint64_t sec;
uint32_t nsec;
pps_gen_get_time(&utc, &nsec); pps_gen_get_time(&sec, &nsec);
if(args[2] && !strcasecmp(args[0], "set")) { if(args[2] && !strcasecmp(args[0], "set")) {
if(wrc_ptp_get_mode() != WRC_MODE_SLAVE) if(wrc_ptp_get_mode() != WRC_MODE_SLAVE)
...@@ -30,11 +31,11 @@ int cmd_time(const char *args[]) ...@@ -30,11 +31,11 @@ int cmd_time(const char *args[])
return -EBUSY; return -EBUSY;
} else if(args[0] && !strcasecmp(args[0], "raw")) } else if(args[0] && !strcasecmp(args[0], "raw"))
{ {
mprintf("%d %d\n", utc, nsec); mprintf("%d %d\n", sec, nsec);
return 0; return 0;
} }
mprintf("%s +%d nanoseconds.\n", format_time(utc), nsec*8); /* fixme: clock freq is not always 125 MHz */ mprintf("%s +%d nanoseconds.\n", format_time(sec), nsec); /* fixme: clock freq is not always 125 MHz */
return 0; return 0;
} }
\ No newline at end of file
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "minic.h" #include "minic.h"
#include "pps_gen.h" #include "pps_gen.h"
#include "softpll_ng.h" #include "softpll_ng.h"
#undef PACKED
#include "ptpd_netif.h" #include "ptpd_netif.h"
#include "ptpd.h" #include "ptpd.h"
...@@ -72,7 +74,7 @@ static int meas_phase_range(wr_socket_t *sock, int phase_min, int phase_max, int ...@@ -72,7 +74,7 @@ static int meas_phase_range(wr_socket_t *sock, int phase_min, int phase_max, int
results[i].phase_sync = ts_sync.phase; results[i].phase_sync = ts_sync.phase;
results[i].ahead = ts_sync.raw_ahead; results[i].ahead = ts_sync.raw_ahead;
results[i].delta_ns = fup.preciseOriginTimestamp.nanosecondsField - ts_sync.nsec; results[i].delta_ns = fup.preciseOriginTimestamp.nanosecondsField - ts_sync.nsec;
results[i].delta_ns += (fup.preciseOriginTimestamp.secondsField.lsb - ts_sync.utc) * 1000000000; results[i].delta_ns += (fup.preciseOriginTimestamp.secondsField.lsb - ts_sync.sec) * 1000000000;
setpoint += phase_step; setpoint += phase_step;
spll_set_phase_shift(0, setpoint); spll_set_phase_shift(0, setpoint);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment