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_
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;
uint16_t dhdr;
......@@ -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);
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)
utc--;
counter_ppsg /= (REF_CLOCK_PERIOD_PS / 1000);
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;
......@@ -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);
#if 1
if(hwts) /* wait for the timestamp */
{
uint32_t raw_ts;
uint16_t fid;
uint32_t counter_r, counter_f;
uint32_t utc;
uint64_t sec;
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);
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
TRACE_DEV("minic_tx_frame: unmatched fid %d vs %d\n", fid, tx_oob_val);
}
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)
utc--;
if(counter_r > 3*REF_CLOCK_FREQ_HZ/4 && nsec < REF_CLOCK_FREQ_HZ/4)
sec--;
hwts->valid = ts_valid;
hwts->utc = utc;
hwts->sec = sec;
hwts->ahead = 0;
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);
minic.tx_count++;
minic.tx_count++;
}
#endif
tx_oob_val++;
return size;
......
#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()
{
pps_gen_set_time(0, 0);
}
#define ppsg_write(reg, val) \
*(volatile uint32_t *) (BASE_PPS_GEN + (offsetof(struct PPSG_WB, reg))) = (val)
void pps_gen_adjust_nsec(int32_t how_much)
{
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;
}
#define ppsg_read(reg) \
*(volatile uint32_t *) (BASE_PPS_GEN + (offsetof(struct PPSG_WB, reg)))
void pps_gen_adjust_utc(int32_t how_much)
int pps_gen_init()
{
TRACE_DEV("ADJ: utc %d seconds\n", how_much);
PPSG->ADJ_UTCLO = how_much;
PPSG->ADJ_UTCHI = 0;
PPSG->ADJ_NSEC = 0;
PPSG->CR = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_PULSE_WIDTH) | PPSG_CR_CNT_ADJ;
uint32_t cr;
cr = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_WIDTH);
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);
PPSG->CR = cr;
PPSG->ESCR = 0;
uint32_t cr;
PPSG->ADJ_UTCLO = utc;
PPSG->ADJ_UTCHI = 0;
PPSG->ADJ_NSEC = nsec;
ppsg_write(ADJ_UTCLO, (uint32_t ) (seconds & 0xffffffffLL));
ppsg_write(ADJ_UTCHI, (uint32_t ) (seconds >> 32) & 0xff);
ppsg_write(ADJ_NSEC, (int32_t) ((int64_t) nanoseconds * 1000LL / (int64_t)REF_CLOCK_PERIOD_PS));
PPSG->CR = cr | PPSG_CR_CNT_SET;
PPSG->CR = cr;
ppsg_write(CR, ppsg_read(CR) | PPSG_CR_CNT_SET);
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 utc_lo;
do {
cyc_before = PPSG->CNTR_NSEC & 0xfffffff;
utc_lo = PPSG->CNTR_UTCLO ;
cyc_after = PPSG->CNTR_NSEC & 0xfffffff;
} while (cyc_after < cyc_before);
// delay(100000);
if(utc) *utc = utc_lo;
if(cntr_nsec) *cntr_nsec = cyc_after;
uint32_t ns_cnt;
uint64_t sec1, sec2;
do {
sec1 = (uint64_t)ppsg_read(CNTR_UTCLO) | (uint64_t)ppsg_read(CNTR_UTCHI) << 32;
ns_cnt = ppsg_read(CNTR_NSEC);
sec2 = (uint64_t)ppsg_read(CNTR_UTCLO) | (uint64_t)ppsg_read(CNTR_UTCHI) << 32;
} while(sec2 != sec1);
if(seconds) *seconds = sec2;
if(nanoseconds) *nanoseconds = (uint32_t) ((int64_t)ns_cnt * (int64_t) REF_CLOCK_PERIOD_PS / 1000LL);
}
void pps_gen_enable_output(int enable)
/* Returns 1 when the adjustment operation is not yet finished */
int pps_gen_busy()
{
if(enable)
PPSG->ESCR = PPSG_ESCR_PPS_VALID | PPSG_ESCR_TM_VALID;
else
PPSG->ESCR = 0;
uint32_t cr = ppsg_read(CR);
return cr & PPSG_CR_CNT_ADJ ? 0 : 1;
}
/* 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 @@
#define CPU_CLOCK 62500000ULL
#define REF_CLOCK_PERIOD_PS 8000
#define REF_CLOCK_FREQ_HZ 125000000
#define UART_BAUDRATE 115200ULL /* not a real UART */
static inline void delay(int x)
......
#ifndef __PPS_GEN_H
#define __PPS_GEN_H
#include <inttypes.h>
void pps_gen_init();
void pps_gen_adjust_nsec(int32_t how_much);
void shw_pps_gen_adjust_utc(int32_t how_much);
int pps_gen_busy();
void pps_gen_get_time(uint32_t *utc, uint32_t *cntr_nsec);
void pps_gen_set_time(uint32_t utc, uint32_t nsec);
#include <stdint.h>
#define PPSG_ADJUST_SEC 0x1
#define PPSG_ADJUST_NSEC 0x2
/* Initializes the PPS Generator. 0 on success, negative on failure. */
int shw_pps_gen_init();
/* 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
......@@ -6,7 +6,7 @@
struct hw_timestamp {
uint8_t valid;
int ahead;
uint32_t utc;
uint64_t sec;
uint32_t nsec;
uint32_t phase;
};
......
......@@ -10,7 +10,7 @@
#define C_BLUE 4
/* 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. */
void cprintf(int color, const char *fmt, ...);
......
......@@ -34,15 +34,15 @@ static const int _ytab[2][12] = {
{ 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;
static char buf[64];
unsigned long dayclock, dayno;
int year = EPOCH_YR;
dayclock = (unsigned long)utc % SECS_DAY;
dayno = (unsigned long)utc / SECS_DAY;
dayclock = (unsigned long)sec % SECS_DAY;
dayno = (unsigned long)sec / SECS_DAY;
t.tm_sec = dayclock % 60;
t.tm_min = (dayclock % 3600) / 60;
......
......@@ -16,12 +16,13 @@ extern int wrc_man_phase;
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;
hexp_port_state_t ps;
int tx, rx;
int aux_stat;
int32_t utc,nsec;
uint64_t sec;
uint32_t nsec;
if(timer_get_tics() - last < UI_REFRESH_PERIOD)
return 0;
......@@ -33,10 +34,10 @@ int wrc_mon_gui(void)
pcprintf(1, 1, C_BLUE, "WR PTP Core Sync Monitor v 1.0");
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_WHITE, "%s", format_time(utc));
cprintf(C_BLUE, "\n\nTAI Time: ");
cprintf(C_WHITE, "%s", format_time(sec));
/*show_ports*/
halexp_get_port_state(&ps, NULL);
......@@ -114,14 +115,15 @@ int wrc_mon_gui(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;
hexp_port_state_t ps;
int tx, rx;
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);
minic_get_stats(&tx, &rx);
mprintf("lnk:%d rx:%d tx:%d ", ps.up, rx, tx);
......@@ -130,7 +132,7 @@ int wrc_log_stats(void)
mprintf("ss:'%s' ", cur_servo_state.slave_servo_state);
aux_stat = spll_get_aux_status(0);
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("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);
......
......@@ -10,16 +10,17 @@
#include <string.h>
#include "shell.h"
#include "util.h"
#include "wrc_ptp.h"
#include "pps_gen.h"
extern char *format_time(uint32_t utc);
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(wrc_ptp_get_mode() != WRC_MODE_SLAVE)
......@@ -30,11 +31,11 @@ int cmd_time(const char *args[])
return -EBUSY;
} else if(args[0] && !strcasecmp(args[0], "raw"))
{
mprintf("%d %d\n", utc, nsec);
mprintf("%d %d\n", sec, nsec);
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;
}
\ No newline at end of file
......@@ -11,6 +11,8 @@
#include "minic.h"
#include "pps_gen.h"
#include "softpll_ng.h"
#undef PACKED
#include "ptpd_netif.h"
#include "ptpd.h"
......@@ -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].ahead = ts_sync.raw_ahead;
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;
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