diff --git a/.gitmodules b/.gitmodules index d387b1b1378863f0a1bb0f4c3f63429c3057e780..eb7b43a7904380c988eea30091523c337a9e4ef9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "ptp-noposix"] path = ptp-noposix url = git://ohwr.org/white-rabbit/ppsi/ptp-noposix.git +[submodule "ppsi"] + path = ppsi + url = git://ohwr.org/white-rabbit/ppsi.git diff --git a/Kconfig b/Kconfig index a6b6a6bcade6f40f14d706ae3a7e4428dc773c80..3167d3725a1107d218d8184af3f4c4d3a202ca5a 100644 --- a/Kconfig +++ b/Kconfig @@ -10,8 +10,46 @@ config RAMSIZE more features you may want to adjust the FPGA size and choose your preferred value here. +choice + prompt "Choose your preferred ptp engine" + default PTP_NOPOSIX + +config PTP_NOPOSIX + boolean "ptp-noposix" + help + Select this option for the ptp-noposix engine + +config PPSI + boolean "ppsi" + help + Select this option for the ppsi engine. Warning: this option is + work in progress, may not work or not compile at all. + +endchoice + +config PPSI_VERBOSITY + depends on PPSI + int "Default verbosity for PPSI" + help + This option makes you select the verbosity of PPSI at startup: + 0 means silent + 1 means normal verbosity messages + 2 means more verbose messages + default 0 + range 0 2 + +config PPSI_RUNTIME_VERBOSITY + depends on PPSI + boolean "Enable runtime verbosity setting" + default n + help + If set, this option permits to change the verbosity of PPSI engine + runtime. This causes a bigger RAM occupation, so it is suggested + to set it only for debugging purpose. + config STACKSIZE int "Size of the stack area needed by this program" + default 3584 if PPSI default 2048 help The linker complains if the code doesn't fit into RAM, but @@ -20,6 +58,7 @@ config STACKSIZE config MPRINTF boolean "Use the old mprintf implementation for printf" + depends on !PPSI default y help wrpc-sw has traditionally used mprintf as its printf engine. @@ -97,7 +136,4 @@ config DETERMINISTIC_BINARY If in doubt, say No. -# The following will soon become a choice with ppsi -config PTP_NOPOSIX - boolean - default y \ No newline at end of file + diff --git a/Makefile b/Makefile index 2382db79b3b58b817c78df73cc0b460f503ce2de..8e5438fbc5c317eb7d569df90d5170e96f61169d 100644 --- a/Makefile +++ b/Makefile @@ -17,12 +17,13 @@ SIZE = $(CROSS_COMPILE)size AUTOCONF = $(CURDIR)/include/generated/autoconf.h PTP_NOPOSIX = ptp-noposix +PPSI = ppsi # we miss CONFIG_ARCH_LM32 as we have no other archs by now obj-y = arch/lm32/crt0.o arch/lm32/irq.o arch/lm32/debug.o LDS = arch/lm32/ram.ld -obj-y += wrc_main.o wrc_ptp.o monitor/monitor.o +obj-y += wrc_main.o obj-y += softpll/softpll_ng.o @@ -31,13 +32,11 @@ obj-y += softpll/softpll_ng.o $(CC) -include $(AUTOCONF) -E -P $*.ld.S -o $@ -cflags-y = -include $(AUTOCONF) -Iinclude -I. -Isoftpll - +cflags-y = -ffreestanding -include $(AUTOCONF) -Iinclude -I. -Isoftpll cflags-$(CONFIG_PP_PRINTF) += -I$(CURDIR)/pp_printf cflags-$(CONFIG_PTP_NOPOSIX) += \ - -ffreestanding \ -DPTPD_FREESTANDING \ -DWRPC_EXTRA_SLIM \ -DPTPD_MSBF \ @@ -48,11 +47,12 @@ cflags-$(CONFIG_PTP_NOPOSIX) += \ -include $(PTP_NOPOSIX)/compat.h \ -include $(PTP_NOPOSIX)/PTPWRd/dep/trace.h \ -include $(PTP_NOPOSIX)/libposix/ptpd-wrappers.h \ - -I$(PTP_NOPOSIX)/wrsw_hal \ -I$(PTP_NOPOSIX)/libptpnetif \ -I$(PTP_NOPOSIX)/PTPWRd -obj-$(CONFIG_PTP_NOPOSIX) += $(PTP_NOPOSIX)/PTPWRd/arith.o \ +obj-$(CONFIG_PTP_NOPOSIX) += wrc_ptp_noposix.o \ + monitor/monitor.o \ + $(PTP_NOPOSIX)/PTPWRd/arith.o \ $(PTP_NOPOSIX)/PTPWRd/bmc.o \ $(PTP_NOPOSIX)/PTPWRd/dep/msg.o \ $(PTP_NOPOSIX)/PTPWRd/dep/net.o \ @@ -65,6 +65,27 @@ obj-$(CONFIG_PTP_NOPOSIX) += $(PTP_NOPOSIX)/PTPWRd/arith.o \ $(PTP_NOPOSIX)/libposix/freestanding-startup.o \ $(PTP_NOPOSIX)/libposix/freestanding-wrapper.o +cflags-$(CONFIG_PPSI) += \ + -ffreestanding \ + -include include/ppsi-wrappers.h \ + -Iinclude \ + -I$(PPSI)/include \ + -I$(PPSI)/arch-spec \ + -I$(PPSI)/arch-spec/include \ + -I$(PPSI)/proto-ext-whiterabbit \ + -Iboards/spec + +# FIXM: The following it temporary, untile we clean up +cflags-$(CONFIG_PPSI) += \ + -I$(PTP_NOPOSIX)/PTPWRd \ + -include $(PTP_NOPOSIX)/PTPWRd/dep/trace.h \ + +obj-$(CONFIG_PPSI) += wrc_ptp_ppsi.o \ + monitor/monitor_ppsi.o \ + lib/ppsi-wrappers.o \ + $(PPSI)/ppsi.o \ + $(PPSI)/arch-spec/libarch.a + CFLAGS_PLATFORM = -mmultiply-enabled -mbarrel-shift-enabled LDFLAGS_PLATFORM = -mmultiply-enabled -mbarrel-shift-enabled \ -nostdlib -T $(LDS) @@ -93,7 +114,11 @@ REVISION=$(shell git describe --dirty --always) all: tools $(OUTPUT).ram $(OUTPUT).vhd $(OUTPUT).mif .PRECIOUS: %.elf %.bin -.PHONY: all tools clean gitmodules +.PHONY: all tools clean gitmodules $(PPSI)/ppsi.o + +$(PPSI)/ppsi.o: + $(MAKE) -C $(PPSI) ARCH=spec PROTO_EXT=whiterabbit HAS_FULL_DIAG=y \ + CROSS_COMPILE=$(CROSS_COMPILE) $(OUTPUT).elf: $(LDS) $(AUTOCONF) gitmodules $(OUTPUT).o $(CC) $(CFLAGS) -DGIT_REVISION=\"$(REVISION)\" -c revision.c @@ -126,6 +151,7 @@ include/board.h: clean: rm -f $(OBJS) $(OUTPUT).elf $(OUTPUT).bin $(OUTPUT).ram include/board.h + $(MAKE) -C $(PPSI) clean %.o: %.c ${CC} $(CFLAGS) $(PTPD_CFLAGS) $(INCLUDE_DIR) $(LIB_DIR) -c $*.c -o $@ diff --git a/configs/spec_ppsi_defconfig b/configs/spec_ppsi_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..49ed2b8c7343850d3fe2b0a4d606663ae96c816d --- /dev/null +++ b/configs/spec_ppsi_defconfig @@ -0,0 +1,17 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_RAMSIZE=90112 +# CONFIG_PTP_NOPOSIX is not set +CONFIG_PPSI=y +CONFIG_PPSI_VERBOSITY=0 +# CONFIG_PPSI_RUNTIME_VERBOSITY is not set +CONFIG_STACKSIZE=2048 +CONFIG_PP_PRINTF=y +# CONFIG_PRINTF_FULL is not set +CONFIG_PRINTF_XINT=y +# CONFIG_PRINTF_MINI is not set +# CONFIG_PRINTF_NONE is not set +CONFIG_PRINT_BUFSIZE=128 +# CONFIG_ETHERBONE is not set +# CONFIG_DETERMINISTIC_BINARY is not set diff --git a/include/hal_exports.h b/include/hal_exports.h new file mode 100644 index 0000000000000000000000000000000000000000..83a6773f105c6d3a8ab3d5fb015412418705457c --- /dev/null +++ b/include/hal_exports.h @@ -0,0 +1,242 @@ +#ifndef __HAL_EXPORTS_H +#define __HAL_EXPORTS_H + +#include <stdint.h> + +#define HAL_MAX_PORTS 32 + +#define WRSW_HAL_SERVER_ADDR "wrsw_hal" + +// checks if the calibration unit is idle +#define HEXP_CAL_CMD_CHECK_IDLE 1 + +// enables/disables transmission of calibration pattern +#define HEXP_CAL_CMD_TX_PATTERN 2 + +// requests a measurement of TX delta +#define HEXP_CAL_CMD_TX_MEASURE 4 + +// requests a measurement of RX delta +#define HEXP_CAL_CMD_RX_MEASURE 5 + +#define HEXP_CAL_RESP_BUSY 1 +#define HEXP_CAL_RESP_OK 0 +#define HEXP_CAL_RESP_ERROR -1 + +#define HEXP_LOCK_CMD_START 1 +#define HEXP_LOCK_CMD_CHECK 2 +#define HEXP_LOCK_CMD_ENABLE_TRACKING 3 + +#define HEXP_LOCK_STATUS_LOCKED 0 +#define HEXP_LOCK_STATUS_BUSY 1 +#define HEXP_LOCK_STATUS_NONE 2 + +#define HEXP_PPSG_CMD_GET 0 +#define HEXP_PPSG_CMD_ADJUST_PHASE 1 +#define HEXP_PPSG_CMD_ADJUST_SEC 2 +#define HEXP_PPSG_CMD_ADJUST_NSEC 3 +#define HEXP_PPSG_CMD_POLL 4 +#define HEXP_PPSG_CMD_SET_VALID 5 + +#define HEXP_ON 1 +#define HEXP_OFF 0 + +#define HEXP_FREQ 0 +#define HEXP_PHASE 1 + +/////////////////added by ML////////// +#define HEXP_EXTSRC_CMD_CHECK 0 + +#define HEXP_EXTSRC_STATUS_LOCKED 0 +#define HEXP_LOCK_STATUS_BUSY 1 +#define HEXP_EXTSRC_STATUS_NOSRC 2 +///////////////////////////////////// + +#define HAL_TIMING_MODE_GRAND_MASTER 0 +#define HAL_TIMING_MODE_FREE_MASTER 1 +#define HAL_TIMING_MODE_BC 2 + +typedef struct { + + char port_name[16]; + + int pps_valid; + + uint32_t current_phase_shift; + int32_t adjust_phase_shift; + + int64_t adjust_sec; + int32_t adjust_nsec; + + uint64_t current_sec; + uint32_t current_nsec; + +} hexp_pps_params_t; + +/* Port modes (hexp_port_state_t.mode) */ +#define HEXP_PORT_MODE_WR_M_AND_S 4 +#define HEXP_PORT_MODE_WR_MASTER 1 +#define HEXP_PORT_MODE_WR_SLAVE 2 +#define HEXP_PORT_MODE_NON_WR 3 + +#define FIX_ALPHA_FRACBITS 40 +/* +#define HEXP_PORT_TSC_RISING 1 +#define HEXP_PORT_TSC_FALLING 2 +*/ + +typedef struct { + /* When non-zero: port state is valid */ + int valid; + + /* WR-PTP role of the port (Master, Slave, etc.) */ + int mode; + + /* TX and RX delays (combined, big Deltas from the link model in the spec) */ + uint32_t delta_tx; + uint32_t delta_rx; + + /* DDMTD raw phase value in picoseconds */ + uint32_t phase_val; + + /* When non-zero: phase_val contains a valid phase readout */ + int phase_val_valid; + + /* When non-zero: link is up */ + int up; + + /* When non-zero: TX path is calibrated (delta_tx contains valid value) */ + int tx_calibrated; + + /* When non-zero: RX path is calibrated (delta_rx contains valid value) */ + int rx_calibrated; + int tx_tstamp_counter; + int rx_tstamp_counter; + int is_locked; + int lock_priority; + + // timestamp linearization paramaters + + uint32_t phase_setpoint; // DMPLL phase setpoint (picoseconds) + + uint32_t clock_period; // reference lock period in picoseconds + uint32_t t2_phase_transition; // approximate DMTD phase value (on slave port) at which RX timestamp (T2) counter transistion occurs (picoseconds) + + uint32_t t4_phase_transition; // approximate phase value (on master port) at which RX timestamp (T4) counter transistion occurs (picoseconds) + + uint8_t hw_addr[6]; + int hw_index; + int32_t fiber_fix_alpha; +} hexp_port_state_t; + +typedef struct { + int num_ports; /* Number of ports in the list */ + int num_physical_ports; /* Number of physical ports compiled into the FPGA bitstream */ + char port_names[HAL_MAX_PORTS][16]; +} hexp_port_list_t; + +typedef struct { + int timing_mode; /* Free-running Master/GM/BC */ + int locked_port; + +} hexp_timing_state_t; + +/* Prototypes of functions that call on rpc */ +extern int halexp_check_running(void); +extern int halexp_reset_port(const char *port_name); +extern int halexp_calibration_cmd(const char *port_name, int command, + int on_off); +extern int halexp_lock_cmd(const char *port_name, int command, int priority); +extern int halexp_query_ports(hexp_port_list_t * list); +extern int halexp_get_port_state(hexp_port_state_t * state, + const char *port_name); +extern int halexp_pps_cmd(int cmd, hexp_pps_params_t * params); +extern int halexp_get_timing_state(hexp_timing_state_t * state); + +/* Export structures, shared by server and client for argument matching */ +#ifdef HAL_EXPORT_STRUCTURES + +//int halexp_check_running(); +struct minipc_pd __rpcdef_check_running = { + .name = "check_running", + .retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), + .args = { + MINIPC_ARG_END, + }, +}; + +//int halexp_reset_port(const char *port_name); +struct minipc_pd __rpcdef_reset_port = { + .name = "reset_port", + .retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), + .args = { + MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRING, char *), + MINIPC_ARG_END, + }, +}; + +//int halexp_calibration_cmd(const char *port_name, int command, int on_off); +struct minipc_pd __rpcdef_calibration_cmd = { + .name = "calibration_cmd", + .retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), + .args = { + MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRING, char *), + MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), + MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), + MINIPC_ARG_END, + }, +}; + +//int halexp_lock_cmd(const char *port_name, int command, int priority); +struct minipc_pd __rpcdef_lock_cmd = { + .name = "lock_cmd", + .retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), + .args = { + MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRING, char *), + MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), + MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), + MINIPC_ARG_END, + }, +}; + +//int halexp_query_ports(hexp_port_list_t *list); +struct minipc_pd __rpcdef_query_ports = { + .name = "query_ports", + .retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRUCT, hexp_port_list_t), + .args = { + MINIPC_ARG_END, + }, +}; + +//int halexp_get_port_state(hexp_port_state_t *state, const char *port_name); +struct minipc_pd __rpcdef_get_port_state = { + .name = "get_port_state", + .retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRUCT, hexp_port_state_t), + .args = { + MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRING, char *), + MINIPC_ARG_END, + }, +}; + +//int halexp_pps_cmd(int cmd, hexp_pps_params_t *params); +struct minipc_pd __rpcdef_pps_cmd = { + .name = "pps_cmd", + .retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), + .args = { + MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), + MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRUCT, hexp_pps_params_t), + MINIPC_ARG_END, + }, +}; + +struct minipc_pd __rpcdef_get_timing_state = { + .name = "get_timing_state", + .retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRUCT, hexp_timing_state_t), + .args = { + MINIPC_ARG_END, + }, +}; + +#endif /* HAL_EXPORT_STRUCTURES */ + +#endif diff --git a/include/ppsi-wrappers.h b/include/ppsi-wrappers.h new file mode 100644 index 0000000000000000000000000000000000000000..e269b61382be426a744e30d82509af1d0b12c299 --- /dev/null +++ b/include/ppsi-wrappers.h @@ -0,0 +1,22 @@ +/* + * This includes stuff that is needed to link ppsi into wrpc-sw + * + * It is included by the command line (-include) like ptp-noposix's + * ptpd-wrappers.h is. It is a subset of that file, with only needed stuff + */ +#include <sys/types.h> +#include <stdlib.h> +#include <stdint.h> + +#ifndef __IEEE_BIG_ENDIAN +#error "Not big endian, or unknown endianness" +#endif + +static inline uint16_t ntohs(uint16_t x) {return x;} + +static inline int usleep(useconds_t useconds) +{ + while(useconds--) + asm volatile("nop"); + return 0; +} diff --git a/include/shell.h b/include/shell.h index 05203c0859fde1b9ff85d2b680e0c7937329e721..9ff111a8be0897d67c36378fe7a1b07c674f8cc2 100644 --- a/include/shell.h +++ b/include/shell.h @@ -21,6 +21,7 @@ int cmd_mode(const char *args[]); int cmd_calib(const char *args[]); int cmd_time(const char *args[]); int cmd_ip(const char *args[]); +int cmd_verbose(const char *args[]); int cmd_sdb(const char *args[]); int cmd_mac(const char *args[]); int cmd_init(const char *args[]); diff --git a/lib/net.c b/lib/net.c index 2cce149c08dd93633442176c37f2ce831c6eee61..69d5064eb82c8cce78671e3043000befeca16a5b 100644 --- a/lib/net.c +++ b/lib/net.c @@ -252,7 +252,7 @@ int ptpd_netif_recvfrom(wr_socket_t * sock, wr_sockaddr_t * from, void *data, from->mac[4],from->mac[5],from->mac[6],from->mac[7], from->mac_dest[0],from->mac_dest[1],from->mac_dest[2],from->mac_dest[3], from->mac_dest[4],from->mac_dest[5],from->mac_dest[6],from->mac_dest[7]);*/ - return min(size, data_length); + return min(size - sizeof(struct ethhdr), data_length); return 0; } diff --git a/lib/ppsi-wrappers.c b/lib/ppsi-wrappers.c new file mode 100644 index 0000000000000000000000000000000000000000..f59b8fa60c5fc538f2d489377a7f31fe603c7e17 --- /dev/null +++ b/lib/ppsi-wrappers.c @@ -0,0 +1,69 @@ +#include <stdint.h> +#include <hal_exports.h> +#include <wrc_ptp.h> +#include <syscon.h> +#include <endpoint.h> +#include <softpll_ng.h> +#include <ptpd_netif.h> + +/* Following code from ptp-noposix/libposix/freestanding-wrapper.c */ + +uint64_t ptpd_netif_get_msec_tics(void) +{ + return timer_get_tics(); +} + +static int read_phase_val(hexp_port_state_t *state) +{ + int32_t dmtd_phase; + + if(spll_read_ptracker(0, &dmtd_phase, NULL)) + { + state->phase_val = dmtd_phase; + state->phase_val_valid = 1; + } + else + { + state->phase_val = 0; + state->phase_val_valid = 0; + } + + return 0; +} + +extern int32_t cal_phase_transition; +extern int32_t sfp_alpha; + +int halexp_get_port_state(hexp_port_state_t *state, const char *port_name) +{ + state->valid = 1; + + if(wrc_ptp_get_mode()==WRC_MODE_SLAVE) + state->mode = HEXP_PORT_MODE_WR_SLAVE; + else + state->mode = HEXP_PORT_MODE_WR_MASTER; + + ep_get_deltas( &state->delta_tx, &state->delta_rx); + read_phase_val(state); + state->up = ep_link_up(NULL); + state->tx_calibrated = 1; + state->rx_calibrated = 1; + state->is_locked = spll_check_lock(0); + state->lock_priority = 0; + spll_get_phase_shift(0, NULL, (int32_t *)&state->phase_setpoint); + state->clock_period = 8000; + state->t2_phase_transition = cal_phase_transition; + state->t4_phase_transition = cal_phase_transition; + get_mac_addr(state->hw_addr); + state->hw_index = 0; + state->fiber_fix_alpha = sfp_alpha; + + return 0; +} + +int ptpd_netif_get_dmtd_phase(wr_socket_t *sock, int32_t *phase) +{ + if(phase) + return spll_read_ptracker(0, phase, NULL); + return 0; +} diff --git a/monitor/monitor_ppsi.c b/monitor/monitor_ppsi.c new file mode 100644 index 0000000000000000000000000000000000000000..743a93b9fb7db09b4eb5115163d0af7fcd6576f3 --- /dev/null +++ b/monitor/monitor_ppsi.c @@ -0,0 +1,216 @@ +/* + * This work is part of the White Rabbit project + * + * Copyright (C) 2011,2012 CERN (www.cern.ch) + * Author: Aurelio Colosimo <aurelio@aureliocolosimo.it> + * + * Released according to the GNU GPL, version 2 or any later version. + */ + +#include <inttypes.h> +#include <wrc.h> +#include <ppsi/ppsi.h> +#include <spec.h> +#include <wr-api.h> +#include <minic.h> +#include <softpll_ng.h> +#include <syscon.h> +#include <pps_gen.h> +#include <onewire.h> +#include <util.h> +#include "wrc_ptp.h" + +#define UI_REFRESH_PERIOD TICS_PER_SECOND /* 1 sec */ + +struct ptpdexp_sync_state_t; +extern ptpdexp_sync_state_t cur_servo_state; +extern int wrc_man_phase; + +void wrc_mon_gui(void) +{ + static uint32_t last = 0; + hexp_port_state_t ps; + int tx, rx; + int aux_stat; + uint64_t sec; + uint32_t nsec; + + if (timer_get_tics() - last < UI_REFRESH_PERIOD) + return; + + last = timer_get_tics(); + + term_clear(); + + pcprintf(1, 1, C_BLUE, "WR PTP Core Sync Monitor v 1.0"); + pcprintf(2, 1, C_GREY, "Esc = exit"); + + shw_pps_gen_get_time(&sec, &nsec); + + cprintf(C_BLUE, "\n\nTAI Time: "); + cprintf(C_WHITE, "%s", format_time(sec)); + + /*show_ports */ + halexp_get_port_state(&ps, NULL); + pcprintf(4, 1, C_BLUE, "\n\nLink status:"); + + pcprintf(6, 1, C_WHITE, "%s: ", "wru1"); + if (ps.up) + cprintf(C_GREEN, "Link up "); + else + cprintf(C_RED, "Link down "); + + if (ps.up) { + minic_get_stats(&tx, &rx); + cprintf(C_GREY, "(RX: %d, TX: %d), mode: ", rx, tx); + + switch (ptp_mode) { + case WRC_MODE_GM: + case WRC_MODE_MASTER: + cprintf(C_WHITE, "WR Master "); + break; + case WRC_MODE_SLAVE: + cprintf(C_WHITE, "WR Slave "); + break; + default: + cprintf(C_RED, "WR Unknown "); + } + + if (ps.is_locked) + cprintf(C_GREEN, "Locked "); + else + cprintf(C_RED, "NoLock "); + if (ps.rx_calibrated && ps.tx_calibrated) + cprintf(C_GREEN, "Calibrated "); + else + cprintf(C_RED, "Uncalibrated "); + + /* show_servo */ + cprintf(C_BLUE, "\n\nSynchronization status:\n\n"); + + if (!cur_servo_state.valid) { + cprintf(C_RED, + "Master mode or sync info not valid\n\n"); + return; + } + + cprintf(C_GREY, "Servo state: "); + cprintf(C_WHITE, "%s\n", cur_servo_state.slave_servo_state); + cprintf(C_GREY, "Phase tracking: "); + if (cur_servo_state.tracking_enabled) + cprintf(C_GREEN, "ON\n"); + else + cprintf(C_RED, "OFF\n"); + cprintf(C_GREY, "Synchronization source: "); + cprintf(C_WHITE, "%s\n", cur_servo_state.sync_source); + + cprintf(C_GREY, "Aux clock status: "); + + aux_stat = spll_get_aux_status(0); + + if (aux_stat & SPLL_AUX_ENABLED) + cprintf(C_GREEN, "enabled"); + + if (aux_stat & SPLL_AUX_LOCKED) + cprintf(C_GREEN, ", locked"); + mprintf("\n"); + + cprintf(C_BLUE, "\nTiming parameters:\n\n"); + + cprintf(C_GREY, "Round-trip time (mu): "); + cprintf(C_WHITE, "%9d ps\n", (int32_t) (cur_servo_state.mu)); + cprintf(C_GREY, "Master-slave delay: "); + cprintf(C_WHITE, "%9d ps\n", + (int32_t) (cur_servo_state.delay_ms)); + cprintf(C_GREY, "Master PHY delays: "); + cprintf(C_WHITE, "TX: %d ps, RX: %d ps\n", + (int32_t) cur_servo_state.delta_tx_m, + (int32_t) cur_servo_state.delta_rx_m); + cprintf(C_GREY, "Slave PHY delays: "); + cprintf(C_WHITE, "TX: %d ps, RX: %d ps\n", + (int32_t) cur_servo_state.delta_tx_s, + (int32_t) cur_servo_state.delta_rx_s); + cprintf(C_GREY, "Total link asymmetry: "); + cprintf(C_WHITE, "%9d ps\n", + (int32_t) (cur_servo_state.total_asymmetry)); + cprintf(C_GREY, "Cable rtt delay: "); + cprintf(C_WHITE, "%9d ps\n", + (int32_t) (cur_servo_state.mu) - + (int32_t) cur_servo_state.delta_tx_m - + (int32_t) cur_servo_state.delta_rx_m - + (int32_t) cur_servo_state.delta_tx_s - + (int32_t) cur_servo_state.delta_rx_s); + cprintf(C_GREY, "Clock offset: "); + cprintf(C_WHITE, "%9d ps\n", + (int32_t) (cur_servo_state.cur_offset)); + cprintf(C_GREY, "Phase setpoint: "); + cprintf(C_WHITE, "%9d ps\n", + (int32_t) (cur_servo_state.cur_setpoint)); + cprintf(C_GREY, "Skew: "); + cprintf(C_WHITE, "%9d ps\n", + (int32_t) (cur_servo_state.cur_skew)); + cprintf(C_GREY, "Manual phase adjustment: "); + cprintf(C_WHITE, "%9d ps\n", (int32_t) (wrc_man_phase)); + + cprintf(C_GREY, "Update counter: "); + cprintf(C_WHITE, "%9d \n", + (int32_t) (cur_servo_state.update_count)); + + } + + pp_printf("--"); + + return; +} + +int wrc_log_stats(uint8_t onetime) +{ + static uint32_t last = 0; + hexp_port_state_t ps; + int tx, rx; + int aux_stat; + uint64_t sec; + uint32_t nsec; + int16_t brd_temp = 0; + int16_t brd_temp_frac = 0; + + if (!onetime && timer_get_tics() - last < UI_REFRESH_PERIOD) + return 0; + + last = timer_get_tics(); + + shw_pps_gen_get_time(&sec, &nsec); + halexp_get_port_state(&ps, NULL); + minic_get_stats(&tx, &rx); + pp_printf("lnk:%d rx:%d tx:%d ", ps.up, rx, tx); + pp_printf("lock:%d ", ps.is_locked ? 1 : 0); + pp_printf("sv:%d ", cur_servo_state.valid ? 1 : 0); + pp_printf("ss:'%s' ", cur_servo_state.slave_servo_state); + aux_stat = spll_get_aux_status(0); + pp_printf("aux:%x ", aux_stat); + pp_printf("sec:%d nsec:%d ", (uint32_t) sec, nsec); /* fixme: clock is not always 125 MHz */ + pp_printf("mu:%d ", (int32_t) cur_servo_state.mu); + pp_printf("dms:%d ", (int32_t) cur_servo_state.delay_ms); + pp_printf("dtxm:%d drxm:%d ", (int32_t) cur_servo_state.delta_tx_m, + (int32_t) cur_servo_state.delta_rx_m); + pp_printf("dtxs:%d drxs:%d ", (int32_t) cur_servo_state.delta_tx_s, + (int32_t) cur_servo_state.delta_rx_s); + pp_printf("asym:%d ", (int32_t) (cur_servo_state.total_asymmetry)); + pp_printf("crtt:%d ", + (int32_t) (cur_servo_state.mu) - + (int32_t) cur_servo_state.delta_tx_m - + (int32_t) cur_servo_state.delta_rx_m - + (int32_t) cur_servo_state.delta_tx_s - + (int32_t) cur_servo_state.delta_rx_s); + pp_printf("cko:%d ", (int32_t) (cur_servo_state.cur_offset)); + pp_printf("setp:%d ", (int32_t) (cur_servo_state.cur_setpoint)); + pp_printf("hd:%d md:%d ad:%d ", spll_get_dac(-1), spll_get_dac(0), + spll_get_dac(1)); + pp_printf("ucnt:%d ", (int32_t) cur_servo_state.update_count); + + own_readtemp(ONEWIRE_PORT, &brd_temp, &brd_temp_frac); + pp_printf("temp:%d.%02d C", brd_temp, brd_temp_frac); + + pp_printf("\n"); + return 0; +} diff --git a/ppsi b/ppsi new file mode 160000 index 0000000000000000000000000000000000000000..d3b860f2d0ca04cd041f08858d0fd1c5ad0f4835 --- /dev/null +++ b/ppsi @@ -0,0 +1 @@ +Subproject commit d3b860f2d0ca04cd041f08858d0fd1c5ad0f4835 diff --git a/shell/cmd_verbose.c b/shell/cmd_verbose.c new file mode 100644 index 0000000000000000000000000000000000000000..8edd6065ac11b6ea40778326ffb6c1cb66d05979 --- /dev/null +++ b/shell/cmd_verbose.c @@ -0,0 +1,27 @@ +/* + * This work is part of the White Rabbit project + * + * Copyright (C) 2012 GSI (www.gsi.de) + * Author: Wesley W. Terpstra <w.terpstra@gsi.de> + * + * Released according to the GNU GPL, version 2 or any later version. + */ + +#include <wrc.h> + +extern int pp_diag_verbosity; + +int cmd_verbose(const char *args[]) +{ + int v; + v = args[0][0] - '0'; + + if (v < 0) + v = 0; + else if (v > 2) + v = 2; + + pp_printf("PPSI verbosity set to %d\n", v); + pp_diag_verbosity = v; + return 0; +} diff --git a/shell/shell.c b/shell/shell.c index 8f3e828bf40f65c9aaf6bd5b310bf1888cd81aa3..004f3f54a3934b53e2027f171a7f43b4f8dc56ee 100644 --- a/shell/shell.c +++ b/shell/shell.c @@ -60,6 +60,9 @@ static const struct shell_cmd cmds_list[] = { {"init", cmd_init}, #ifdef CONFIG_ETHERBONE {"ip", cmd_ip}, +#endif +#if (defined CONFIG_PPSI) && (defined CONFIG_PPSI_RUNTIME_VERBOSITY) + {"verbose", cmd_verbose}, #endif {"mac", cmd_mac}, {"sdb", cmd_sdb}, diff --git a/shell/shell.mk b/shell/shell.mk index 3cc6111d8f39a521b8dfd64b3c50e9a29efdcfc2..c1c5afa8e531111369d08a205edf1c3e52a7548d 100644 --- a/shell/shell.mk +++ b/shell/shell.mk @@ -15,3 +15,4 @@ obj-y += \ shell/cmd_init.o obj-$(CONFIG_ETHERBONE) += shell/cmd_ip.o +obj-$(CONFIG_PPSI_RUNTIME_VERBOSITY) += shell/cmd_verbose.o diff --git a/tests/measure_t24p.c b/tests/measure_t24p.c index 1ee21ab83a095aa9d0ecc7a9cfaa77eccad6b617..3f39fd55c782ea5cf2bc12d04cc6efb89f300501 100644 --- a/tests/measure_t24p.c +++ b/tests/measure_t24p.c @@ -24,7 +24,11 @@ #undef PACKED #include "ptpd_netif.h" +#ifdef CONFIG_PPSI +#include <ppsi/ppsi.h> +#else #include "ptpd.h" +#endif #if 0 /* not used, currently */ static int get_bitslide(int ep) @@ -50,6 +54,70 @@ static void purge_socket(wr_socket_t *sock, char *buf) update_rx_queues(); } +#ifdef CONFIG_PPSI + +extern struct pp_instance ppi_static; +static struct pp_instance *ppi = &ppi_static; + +static int meas_phase_range(wr_socket_t * sock, int phase_min, int phase_max, + int phase_step, struct meas_entry *results) +{ + char buf[128]; + TimeInternal ts_rx, ts_sync = {0,}; + MsgHeader *mhdr; + int setpoint = phase_min, i = 0, phase; + + mhdr = &ppi->msg_tmp_header; + + spll_set_phase_shift(SPLL_ALL_CHANNELS, phase_min); + + while (spll_shifter_busy(0)) ; + + purge_socket(sock, buf); + + i = 0; + while (setpoint <= phase_max) { + ptpd_netif_get_dmtd_phase(sock, &phase); + + update_rx_queues(); + int n = pp_recv_packet(ppi, buf, 128, &ts_rx); + + if (n > 0) { + msg_unpack_header(ppi, buf); + if (mhdr->messageType == 0) + assign_TimeInternal(&ts_sync, &ts_rx); + else if (mhdr->messageType == 8 && ts_sync.correct) { + MsgFollowUp fup; + msg_unpack_follow_up(buf, &fup); + + mprintf("Shift: %d/%dps [step %dps] \r", + setpoint, phase_max, phase_step); + results[i].phase = phase; + results[i].phase_sync = ts_sync.phase; + results[i].ahead = ts_sync.raw_ahead; + results[i].delta_ns = + fup.preciseOriginTimestamp. + nanosecondsField - ts_sync.nanoseconds; + results[i].delta_ns += + (fup.preciseOriginTimestamp.secondsField. + lsb - ts_sync.seconds) * 1000000000; + + setpoint += phase_step; + spll_set_phase_shift(0, setpoint); + while (spll_shifter_busy(0)) ; + purge_socket(sock, buf); + + ts_sync.correct = 0; + i++; + } + } + } + mprintf("\n"); + return i; +} + +#else + static int meas_phase_range(wr_socket_t * sock, int phase_min, int phase_max, int phase_step, struct meas_entry *results) { @@ -105,6 +173,8 @@ static int meas_phase_range(wr_socket_t * sock, int phase_min, int phase_max, return i; } +#endif /* CONFIG_PPSI else CONFIG_PTPNOPOSIX*/ + static int find_transition(struct meas_entry *results, int n, int positive) { int i; @@ -125,6 +195,13 @@ int measure_t24p(int *value) int i, nr; struct meas_entry results[128]; +#ifdef CONFIG_PPSI + if (!NP(ppi)->inited) { + if (pp_net_init(ppi) < 0) + return -1; + NP(ppi)->inited = 1; + } +#endif spll_enable_ptracker(0, 1); sock_addr.family = PTPD_SOCK_RAW_ETHERNET; // socket type @@ -181,6 +258,11 @@ int measure_t24p(int *value) mprintf("Verification... \n"); nr = meas_phase_range(sock, 0, 16000, 500, results); +#ifdef CONFIG_PPSI + pp_net_shutdown(ppi); + NP(ppi)->inited = 0; +#endif + for (i = 0; i < nr; i++) mprintf("phase_dmtd: %d delta_ns: %d, phase_sync: %d\n", results[i].phase, results[i].delta_ns, diff --git a/wrc_ptp.h b/wrc_ptp.h index b9045fb325812d21481bc2aa27a01771c4983491..27aa6bda53c866adba4288a477016eb8a438aefe 100644 --- a/wrc_ptp.h +++ b/wrc_ptp.h @@ -5,6 +5,7 @@ #define WRC_MODE_GM 1 #define WRC_MODE_MASTER 2 #define WRC_MODE_SLAVE 3 +extern int ptp_mode; int wrc_ptp_init(); int wrc_ptp_set_mode(int mode); diff --git a/wrc_ptp.c b/wrc_ptp_noposix.c similarity index 98% rename from wrc_ptp.c rename to wrc_ptp_noposix.c index be1a827847d0e0181e42dc1cf3fbed029fe90344..b0ac1292b81c99b107c6f96b7f1b494fc5aaeeac 100644 --- a/wrc_ptp.c +++ b/wrc_ptp_noposix.c @@ -58,7 +58,8 @@ static RunTimeOpts rtOpts = { static PtpPortDS *ptpPortDS; static PtpClockDS ptpClockDS; -static int ptp_enabled = 0, ptp_mode = WRC_MODE_UNKNOWN; +int ptp_mode = WRC_MODE_UNKNOWN; +static int ptp_enabled = 0; int wrc_ptp_init() { diff --git a/wrc_ptp_ppsi.c b/wrc_ptp_ppsi.c new file mode 100644 index 0000000000000000000000000000000000000000..672dbfec6be791da64899e4c8f4753116d402138 --- /dev/null +++ b/wrc_ptp_ppsi.c @@ -0,0 +1,223 @@ +/* + * This work is part of the White Rabbit project + * + * Copyright (C) 2012 CERN (www.cern.ch) + * Author: Aurelio Colosimo <aurelio@aureliocolosimo.it> + * + * Released according to the GNU GPL, version 2 or any later version. + */ +#include <stdio.h> +#include <inttypes.h> +#include <errno.h> +#include <wrc.h> +#include <minic.h> +#include <spec.h> + +#include <ppsi/ppsi.h> +#include <wr-constants.h> +#include "syscon.h" +#include "endpoint.h" +#include "softpll_ng.h" +#include "wrc_ptp.h" +#include "pps_gen.h" +#include "uart.h" + +int ptp_mode = WRC_MODE_UNKNOWN; +static int ptp_enabled = 0, ptp_forced_stop = 0; +struct pp_instance ppi_static; /* FIXME: no more static, because used in + tests/measure_t24p.c */ +CONST_VERBOSITY int pp_diag_verbosity = CONFIG_PPSI_VERBOSITY; + +/*ppi fields*/ +static UInteger16 sent_seq_id[16]; +static DSDefault defaultDS; +static DSCurrent currentDS; +static DSParent parentDS; +static DSPort portDS; +static DSTimeProperties timePropertiesDS; +static struct pp_net_path net_path; +static struct pp_servo servo; +static struct pp_frgn_master frgn_master; + +static int delay_ms = PP_DEFAULT_NEXT_DELAY_MS; +static int start_tics = 0; +static int last_link_up = 0; + +int wrc_ptp_init() +{ + struct pp_instance *ppi = &ppi_static; /* no malloc, one instance */ + sdb_find_devices(); + uart_init(); + + pp_printf("Spec: starting. Compiled on " __DATE__ "\n"); + + ppi->sent_seq_id = sent_seq_id; + ppi->defaultDS = &defaultDS; + ppi->currentDS = ¤tDS; + ppi->parentDS = &parentDS; + ppi->portDS = &portDS; + ppi->timePropertiesDS = &timePropertiesDS; + ppi->net_path = &net_path; + ppi->servo = &servo; + ppi->frgn_master = &frgn_master; + ppi->arch_data = NULL; + + return 0; +} + +#define LOCK_TIMEOUT_FM (4 * TICS_PER_SECOND) +#define LOCK_TIMEOUT_GM (60 * TICS_PER_SECOND) + +int wrc_ptp_set_mode(int mode) +{ + uint32_t start_tics, lock_timeout = 0; + struct pp_instance *ppi = &ppi_static; + + ptp_mode = 0; + + wrc_ptp_stop(); + + switch (mode) { + case WRC_MODE_GM: + /* FIXME multiport rtOpts.primarySource = TRUE; */ + DSPOR(ppi)->wrConfig = WR_M_ONLY; + OPTS(ppi)->master_only = TRUE; + OPTS(ppi)->slave_only = FALSE; + spll_init(SPLL_MODE_GRAND_MASTER, 0, 1); + lock_timeout = LOCK_TIMEOUT_GM; + break; + + case WRC_MODE_MASTER: + /* FIXME multiport rtOpts.primarySource = FALSE; */ + DSPOR(ppi)->wrConfig = WR_M_ONLY; + OPTS(ppi)->master_only = TRUE; + OPTS(ppi)->slave_only = FALSE; + spll_init(SPLL_MODE_FREE_RUNNING_MASTER, 0, 1); + lock_timeout = LOCK_TIMEOUT_FM; + break; + + case WRC_MODE_SLAVE: + /* FIXME multiport rtOpts.primarySource = FALSE; */ + DSPOR(ppi)->wrConfig = WR_S_ONLY; + OPTS(ppi)->master_only = FALSE; + OPTS(ppi)->slave_only = TRUE; + spll_init(SPLL_MODE_SLAVE, 0, 1); + break; + } + + start_tics = timer_get_tics(); + + pp_printf("Locking PLL"); + + shw_pps_gen_enable_output(0); + + while (!spll_check_lock(0) && lock_timeout) { + timer_delay(TICS_PER_SECOND); + pp_printf("."); + if (timer_get_tics() - start_tics > lock_timeout) { + pp_printf("\nLock timeout.\n"); + return -ETIMEDOUT; + } else if (uart_read_byte() == 27) { + pp_printf("\n"); + return -EINTR; + } + } + + if (mode == WRC_MODE_MASTER || mode == WRC_MODE_GM) + shw_pps_gen_enable_output(1); + + pp_printf("\n"); + ptp_mode = mode; + return 0; +} + +int wrc_ptp_get_mode() +{ + return ptp_mode; +} + +int wrc_ptp_start() +{ + struct pp_instance *ppi = &ppi_static; + + pp_open_instance(ppi, 0 /* no opts */); + OPTS(ppi)->e2e_mode = 1; + + /* Call the state machine. Being it in "Initializing" state, make + * ppsi initialize what is necessary */ + delay_ms = pp_state_machine(ppi, NULL, 0); + start_tics = timer_get_tics(); + + DSPOR(ppi)->linkUP = FALSE; + wr_servo_reset(); + + ptp_enabled = 1; + return 0; +} + +int wrc_ptp_stop() +{ + ptp_enabled = 0; + wr_servo_reset(); + pp_close_instance(&ppi_static); + return 0; +} + +int wrc_ptp_update() +{ + int i; + struct pp_instance *ppi = &ppi_static; + + int now_link_up; + + now_link_up = ep_link_up(NULL); + + if (last_link_up != now_link_up) { + last_link_up = now_link_up; + if (ptp_enabled && (!now_link_up)) { + wrc_ptp_stop(); + ptp_forced_stop = 1; + pp_printf("Link down: PTP stop\n"); + } + else { + if (ptp_forced_stop) { + pp_printf("Link up: PTP start\n"); + ptp_forced_stop = 0; + wrc_ptp_start(); + } + } + } + + if (ptp_enabled) { + static unsigned char packet[500]; + + /* + * We got a packet. If it's not ours, continue consuming + * the pending timeout + */ + i = spec_recv_packet(ppi, packet, sizeof(packet), + &ppi->last_rcv_time); + if ((!i) && (timer_get_tics() - start_tics < delay_ms)) + return 0; + if (!i) { + /* Nothing received, but timeout elapsed */ + start_tics = timer_get_tics(); + delay_ms = pp_state_machine(ppi, NULL, 0); + return 0; + } + if (pp_diag_verbosity > 1) { + int j; + pp_printf("recvd: %i\n", i); + for (j = 0; j < i; j++) { + pp_printf("%02x ", packet[j]); + if( (j+1)%16==0 ) + pp_printf("\n"); + } + pp_printf("\n"); + } + /* Warning: PP_ETHERTYPE is endian-agnostic by design */ + + delay_ms = pp_state_machine(ppi, packet, i); + } + return 0; +}