Commit 515af578 authored by baujc's avatar baujc

Big update 2

. Better integrate of code optimization with PPSi Kconfig
. PPSi Kconfig changes to simplify the code in PPSi and avoid #ifdef ..
. Improve code optimization
. Move some declaration in ppsi.h in other files to ligthen ppsi.h
. Improvement of timers: global or instance dependent, dyn. allocation,
renaming for better diagnostics, disabling allowed, ...
. New behaviour for the PPS output generation (configurable,...)
. Move control of the timing mode from HAL to PPSi
. Optimization of code when a Protocol extension is not available
. BMCA: Calculate the ebest,... only one time and then trigger all
instances to execute the bmca state descision
. Fix bug in the calculation of the clockIdentity to bring it into
compliance with PTP spec 2008 document
. Fix a bug related to Announce message received in SLAVE/UNCALIB
. WR ext: use dynamic timer and adapt to new PPS generation
. HA ext: Fix bug in fault injection mechanism
parent 519c9c27
......@@ -70,6 +70,32 @@ config ARCH
default "wrs" if ARCH_WRS
default "sim" if ARCH_SIMULATOR
config CROSS_COMPILE
string "Cross compiler prefix"
default "/opt/gcc-lm32/bin/lm32-elf-" if ARCH_WRPC
default "/opt/arm-wrswitch/bin/arm-linux-" if ARCH_WRS
default ""
config ARCH_CFLAGS
string
default "-m32" if ARCH_BARE_I386
default "-m64" if ARCH_BARE_X86_64
default ""
config ARCH_LDFLAGS
string
default "-m elf_i386" if ARCH_BARE_I386
default "-m elf_x86_64" if ARCH_BARE_X86_64
default ""
config WRPCSW_ROOT
string "Source location of wrpc-sw"
depends on ARCH_WRPC
default "../wrpc-sw"
menu "Options"
menu "PTP Protocol Options"
choice
prompt "PTP Synchronization Mechanism"
......@@ -101,7 +127,7 @@ menu "PTP Protocol Options"
endmenu
menu "Profiles"
menu "Enabled profiles"
config PROFILE_WR
bool "WhiteRabbit"
......@@ -117,53 +143,53 @@ menu "Profiles"
endmenu
config ASSERT
bool "Build assertion checks in the code"
default n
help
Build assertions in the code, to catch unexpected situations.
When an assertion fails the code loops over repeating the
error message every second. OTOH, panic() is always built,
with no Kconfig -- and it does the same, unconditionally.
config PROFILE_PTP
bool
default y
config EXT_WR
bool
default y if PROFILE_WR
config HAS_EXT_WR
int
range 0 1
default 1 if PROFILE_WR
default 0
config EXT_L1SYNC
bool
default y if PROFILE_HA
config EXT_NONE
bool
default y if !(PROFILE_WR || PROFILE_HA || PROFILE_CUSTOM)
config HAS_EXT_L1SYNC
int
range 0 1
default 1 if PROFILE_HA
default 0
config HAS_EXT_NONE
int
range 0 1
default 1 if !(PROFILE_WR || PROFILE_HA || PROFILE_CUSTOM)
default 0
config CROSS_COMPILE
string "Cross compiler prefix"
default "/opt/gcc-lm32/bin/lm32-elf-" if ARCH_WRPC
default "/opt/arm-wrswitch/bin/arm-linux-" if ARCH_WRS
default ""
config ARCH_CFLAGS
string
default "-m32" if ARCH_BARE_I386
default "-m64" if ARCH_BARE_X86_64
default ""
config ARCH_LDFLAGS
string
default "-m elf_i386" if ARCH_BARE_I386
default "-m elf_x86_64" if ARCH_BARE_X86_64
default ""
config WRPCSW_ROOT
string "Source location of wrpc-sw"
depends on ARCH_WRPC
default "../wrpc-sw"
config HAS_PROFILE_PTP
int
range 0 1
default 1 if PROFILE_PTP
default 0
config HAS_PROFILE_HA
int
range 0 1
default 1 if PROFILE_HA
default 0
config HAS_PROFILE_WR
int
range 0 1
default 1 if PROFILE_WR
default 0
config HAS_PROFILE_CUSTOM
int
range 0 1
default 1 if PROFILE_CUSTOM
default 0
menu VLAN
# Vlan support: not all architectures have it, so this is set by them
config HAS_VLAN
......@@ -199,8 +225,7 @@ config MAX_VLANS_PER_PORT
the special case of 1 VLAN per port, useful for
microcontroller-class architectures. Hosted builds
feature a bigger default, because they have no size constraints.
# I want a number, to be used without ifdef
config VLAN_ARRAY_SIZE
int
......@@ -208,18 +233,234 @@ config VLAN_ARRAY_SIZE
default 1 if !HAS_MULTIPLE_VLAN
default MAX_VLANS_PER_PORT
config DISABLE_OPTIMIZATION
bool "Disable -O2, to ease running a debugger"
endmenu
config ASSERT
bool "Build assertion checks in the code"
default n
help
Build assertions in the code, to catch unexpected situations.
When an assertion fails the code loops over repeating the
error message every second. OTOH, panic() is always built,
with no Kconfig -- and it does the same, unconditionally.
config NR_FOREIGN_RECORDS
int "Size of foreignMasterDS data set"
range 1 20
default 1 if ARCH_WRPC
default 5
help
Size of foreignMasterDS data set (Clause 9.3.2.4.5)
config SINGLE_FMASTER
boolean
default y if NR_FOREIGN_RECORDS=1
default n
config NR_PORTS
int "Number of ports"
range 1 64
default 1 if ARCH_WRPC
default 18 if ARCH_WRS
default 64
help
number of physical ports
config NR_INSTANCES_PER_PORT
int "Max instances per port"
range 1 64
default 1 if ARCH_WRPC
default 2 if ARCH_WRS
default 1
help
Number of PPSi instances per physical port
menu "Code optimization"
config CODEOPT_ENABLED
boolean "Enable code optimization"
default y
help
Enable code optimization
config SINGLE_INSTANCE_PER_PORT
boolean
default y if NR_INSTANCES_PER_PORT=1
default n
config SINGLE_INSTANCE
boolean
default y if NR_INSTANCES_PER_PORT=1 && NR_PORTS=1
default n
config SINGLE_PORT
boolean
default y if NR_PORTS=1
default n
config CODEOPT_SINGLE_PORT
boolean "Single port"
depends on CODEOPT_ENABLED && SINGLE_PORT
default n
help
Code optimization when only one port is used (e.g:WRPC).
config CODEOPT_SINGLE_FMASTER
boolean "One foreign master"
depends on CODEOPT_ENABLED && SINGLE_FMASTER
default n
help
Only one foreign master per port instance.
config CODEOPT_SINGLE_INSTANCE_PER_PORT
boolean "One instance per port"
depends on CODEOPT_ENABLED && SINGLE_INSTANCE_PER_PORT
default n
help
Only one foreign master per port instance.
choice
prompt "Exclusive options"
config CODEOPT_EPC_SO_DISABLED
boolean "No optimization"
depends on CODEOPT_ENABLED
help
No optimization
config CODEOPT_EPC_ENABLED
boolean "Force externalPortConfiguration.enable to true"
depends on CODEOPT_ENABLED
help
externalPortConfiguration.enable is set to true and cannot be changed
config CODEOPT_SO_ENABLED
boolean "Force slaveOnly mode to true"
depends on CODEOPT_ENABLED && SINGLE_PORT
help
slaveOnly is set to true and cannot be changed.
It implies that the number of port instances must be set to 1.
endchoice
endmenu
endmenu
choice
prompt "Compilation optimization"
config OPTIMIZATION_SPEED
boolean "Execution time (-O2)"
help
GCC performs nearly all supported optimizations that do not involve a space-speed tradeoff.
config OPTIMIZATION_SIZE_SPEED
boolean "Size and execution time (-Os)"
help
Optimize for size. Enables all -O2 optimizations except those that often increase code size.
config OPTIMIZATION_DEBUGGING
boolean "Debugging (-Og -ggdb)"
help
Should be the optimization level of choice for the standard edit-compile-debug cycle
config OPTIMIZATION_NONE_DEBUGGING
boolean "Debugging without optimization(-ggdb)"
help
Compile without optimization and with debug informations
endchoice
config OPTIMIZATION
int
default 0 if DISABLE_OPTIMIZATION
default 2
string
default "-Os" if OPTIMIZATION_SIZE_SPEED
default "-O2" if OPTIMIZATION_SPEED
default "-Og -ggdb" if OPTIMIZATION_DEBUGGING
default "-ggdb" if OPTIMIZATION_NONE_DEBUGGING
default ""
config WRPC_FAULTS
bool "Add the fault injection mechanism and shell command for wrpc"
depends on ARCH_WRPC
config FAULT_INJECTION_MECHANISM
bool "Add fault injection mechanism"
help
This adds a "fault" shell command, with subcommands.
The implementation is architecture specific.
For wrpc it adds a "fault" shell command, with subcommands.
The same mechanisms are available in the wr switch, through
the configuration file.
config HAS_FAULT_INJECTION_MECHANISM
int
range 0 1
default 1 if FAULT_INJECTION_MECHANISM
default 0
# We want numbers (0/1) to avoid ifdef
config HAS_WRPC_FAULTS
int
range 0 1
default 1 if WRPC_FAULTS
default 0
config HAS_CODEOPT_SINGLE_FMASTER
int
range 0 1
default 1 if CODEOPT_SINGLE_FMASTER
default 0
config HAS_CODEOPT_SINGLE_PORT
int
range 0 1
default 1 if CODEOPT_SINGLE_PORT
default 0
config HAS_CODEOPT_SINGLE_INSTANCE_PER_PORT
int
range 0 1
default 1 if CODEOPT_SINGLE_INSTANCE_PER_PORT
default 0
config HAS_CODEOPT_EPC_ENABLED
int
range 0 1
default 1 if CODEOPT_EPC_ENABLED
default 0
config HAS_CODEOPT_SO_ENABLED
int
range 0 1
default 1 if CODEOPT_SO_ENABLED
default 0
config HAS_EXT_WR
int
range 0 1
default 1 if EXT_WR
default 0
config HAS_EXT_L1SYNC
int
range 0 1
default 1 if EXT_L1SYNC
default 0
config ARCH_IS_WRS
int
range 0 1
default 1 if ARCH_WRS
default 0
config ARCH_IS_WRPC
int
range 0 1
default 1 if ARCH_WRPC
default 0
config HAS_ASSERT
int
range 0 1
default 1 if ASSERT
default 0
\ No newline at end of file
......@@ -47,14 +47,17 @@ all: $(TARGET).o
# CFLAGS to use. Both this Makefile (later) and app-makefile may grow CFLAGS
CFLAGS = $(USER_CFLAGS)
CFLAGS += -Wall -Wstrict-prototypes -Wmissing-prototypes
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += -O$(CONFIG_OPTIMIZATION)
export CFLAGS_OPTIMIZATION:= ${shell echo $(CONFIG_OPTIMIZATION)}
CFLAGS += -ggdb -Iinclude -fno-common
CFLAGS += $(CFLAGS_OPTIMIZATION)
CFLAGS += -Iinclude -fno-common
CFLAGS += -DPPSI_VERSION=\"$(VERSION)\"
# to avoid ifdef as much as possible, I use the kernel trick for OBJ variables
OBJ-y := fsm.o diag.o timeout.o msgtype.o
OBJ-y := fsm.o diag.o timeout.o msgtype.o port_controller.o
# Include arch code. Each arch chooses its own time directory..
include arch-$(ARCH)/Makefile
......@@ -67,7 +70,7 @@ OBJ-y += pp_printf/pp-printf.o
pp_printf/pp-printf.o: $(wildcard pp_printf/*.[ch])
CFLAGS="$(ARCH_PP_PRINTF_CFLAGS)" \
$(MAKE) -C pp_printf pp-printf.o CC="$(CC)" LD="$(LD)" \
CONFIG_PRINTF_64BIT=y
CONFIG_PRINTF_64BIT=y CFLAGS_OPTIMIZATION="$(CFLAGS_OPTIMIZATION)"
endif
# We need this -I so <arch/arch.h> can be found
......@@ -75,10 +78,10 @@ CFLAGS += -Iarch-$(ARCH)/include
# proto-standard is always included, as it provides default function
# so the extension can avoid duplication of code.
ifeq ($(CONFIG_EXT_WR),y)
ifeq ($(CONFIG_HAS_EXT_WR),1)
include proto-ext-whiterabbit/Makefile
endif
ifeq ($(CONFIG_EXT_L1SYNC),y)
ifeq ($(CONFIG_HAS_EXT_L1SYNC),1)
include proto-ext-l1sync/Makefile
endif
include proto-standard/Makefile
......@@ -99,7 +102,7 @@ export CFLAGS
# libraries: see proto-standard/Makefile as an example.
$(TARGET).o: $(OBJ-y)
$(LD) -Map $(TARGET).map1 -r -o $@ $(PPSI_O_LDFLAGS) \
$(LD) --gc-sections --entry=main -Map $(TARGET).map1 -r -o $@ $(PPSI_O_LDFLAGS) \
--start-group $(OBJ-y) --end-group
$(OBJ-y): .config $(wildcard include/ppsi/*.h)
......
......@@ -25,7 +25,8 @@ OBJ-y += \
lib/dump-funcs.o \
lib/drop.o \
lib/div64.o \
lib/time-arith.o
lib/time-arith.o \
lib/iicomm.o
OBJ-$(CONFIG_WRPC_FAULTS) += $A/faults.o
......
......@@ -2,9 +2,6 @@
#define __ARCH_H__
#include <assert.h> /* wrpc-sw includes assert already */
/* This arch exports wr functions, so include this for consistency checking */
#include "../proto-ext-whiterabbit/wr-api.h"
/* Architecture-specific defines, included by top-level stuff */
#ifndef htons /* If we build as host process, we have them LE already */
......@@ -16,14 +13,5 @@
#endif
/* Code optimization for WRPC architecture */
#ifndef CODEOPT_BMCA
#define CODEOPT_BMCA 1 /* Code optimization for BMCA. Can be overwritten in the makefile*/
#endif
#define CODEOPT_ONE_PORT() (1 && CODEOPT_BMCA==1) /* Code optimization when only one port is used. */
#define CODEOPT_ROLE_MASTER_SLAVE_ONLY() (1 && CODEOPT_BMCA==1) /* Code optimization when only one port is used. */
#define abs(x) ((x >= 0) ? x : -x)
#endif /* __ARCH_H__ */
# All files are under A (short for ARCH): I'm lazy
A := arch-$(ARCH)
# classic cross-compilation tool-set
SIZE = $(CROSS_COMPILE)size
CFLAGS += -Itools
# Prevent a warning for a missing prototype in pp_printf, bug since ever
ARCH_PP_PRINTF_CFLAGS += -include ../$A/include/strnlen.h
OBJ-y += $A/wrs-startup.o \
$A/hal_minirpc.o \
$A/main-loop.o \
$A/wrs-io.o \
$A/wrs-conf.o \
......@@ -22,6 +26,9 @@ OBJ-y += $A/wrs-startup.o \
lib/div64.o \
lib/time-arith.o
export size_db_file:=size_wrs_db.txt
export size_info_file:=size_wrs_info.txt
# We only support "wrs" time operations
TIME = wrs
include time-$(TIME)/Makefile
......@@ -37,7 +44,7 @@ MINIPC_LIB := $(MINIPC_DIR)/libminipc.a
CFLAGS += -I$(MINIPC_DIR)
.PHONY: $(MINIPC_LIB)
$(MINIPC_LIB):
$(MAKE) -C $(MINIPC_DIR)
$(MAKE) -C $(MINIPC_DIR) CFLAGS_OPTIMIZATION="$(CFLAGS_OPTIMIZATION)"
OBJ-y += $(MINIPC_LIB)
......@@ -47,4 +54,8 @@ all: $(TARGET)
# were not selected yet (e.g., pp_init_globals() ).
$(TARGET): $(TARGET).o
$(CC) -Wl,-Map,$(TARGET).map2 -o $@ $(TARGET).o -lrt
$(SIZE) $@
./arch-wrs/save_size.sh $(SIZE) $@
cat $(size_info_file)
#ifndef __HAL_EXPORTS_C
#define __HAL_EXPORTS_C
#include <minipc.h>
#include <hal_exports.h>
/* Export structures, shared by server and client for argument matching */
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_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
......@@ -38,6 +38,9 @@
#define HEXP_PPSG_CMD_ADJUST_NSEC 3
#define HEXP_PPSG_CMD_POLL 4
#define HEXP_PPSG_CMD_SET_VALID 5
#define HEXP_PPSG_CMD_SET_TIMING_MODE 6
#define HEXP_PPSG_CMD_GET_TIMING_MODE 7
#define HEXP_PPSG_CMD_GET_TIMING_MODE_STATE 8
#define HEXP_ON 1
#define HEXP_OFF 0
......@@ -56,6 +59,11 @@
#define HAL_TIMING_MODE_GRAND_MASTER 0
#define HAL_TIMING_MODE_FREE_MASTER 1
#define HAL_TIMING_MODE_BC 2
#define HAL_TIMING_MODE_DISABLED 3
#define HAL_TIMING_MODE_TMDT_UNLOCKED 0
#define HAL_TIMING_MODE_TMDT_LOCKED 1
#define HAL_TIMING_MODE_TMDT_HOLDHOVER 2
typedef struct {
......@@ -72,14 +80,17 @@ typedef struct {
uint64_t current_sec;
uint32_t current_nsec;
uint32_t timing_mode;
} hexp_pps_params_t;
/* Port modes (hal_port_state.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 HEXP_PORT_MODE_WR_M_AND_S 4
#define HEXP_PORT_MODE_NONE 5
#define FIX_ALPHA_FRACBITS 40
/*
#define HEXP_PORT_TSC_RISING 1
#define HEXP_PORT_TSC_FALLING 2
......@@ -99,71 +110,4 @@ extern int halexp_lock_cmd(const char *port_name, int command, int priority);
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_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
......@@ -10,8 +10,10 @@
*/
#include <minipc.h>
#include <hw-specific/wrh.h>
#include <libwr/shmem.h>
#include <libwr/hal_shmem.h>
#include <ppsi/timeout_def.h>
#define WRS_NUMBER_PHYSICAL_PORTS 18 /* Number of physical ports on a WR switch */
......@@ -59,11 +61,16 @@ int wrs_read_correction_data(struct pp_instance *ppi, int64_t *fixAlpha,
/* wrs-time.c (some should moce to wrs-spll.c) */
int wrs_locking_enable(struct pp_instance *ppi);
int wrs_locking_poll(struct pp_instance *ppi, int grandmaster);
int wrs_locking_poll(struct pp_instance *ppi);
int wrs_locking_disable(struct pp_instance *ppi);
int wrs_locking_reset(struct pp_instance *ppi);
int wrs_enable_ptracker(struct pp_instance *ppi);
int wrs_adjust_in_progress(void);
int wrs_adjust_counters(int64_t adjust_sec, int32_t adjust_nsec);
int wrs_adjust_phase(int32_t phase_ps);
int wrs_enable_timing_output(struct pp_instance *ppi, int enable);
int wrs_enable_timing_output(struct pp_globals *,int enable);
timing_mode_t wrs_get_timing_mode(struct pp_globals *);
timing_mode_state_t wrs_get_timing_mode_state(struct pp_globals *);
int wrs_set_timing_mode(struct pp_globals *,timing_mode_t tm);
......@@ -59,7 +59,7 @@ static int run_all_state_machines(struct pp_globals *ppg)
pp_diag(ppi, fsm, 1, "Cannot read bit_slide value values\n");
bit_slide_ps=0;
}
pp_diag(ppi, fsm, 1, "semistaticLatency(bit-slide)=%u [ps]\n",bit_slide_ps);
pp_diag(ppi, fsm, 1, "semistaticLatency(bit-slide)=%u [ps]\n",(unsigned int)bit_slide_ps);
ppi->timestampCorrectionPortDS.semistaticLatency= picos_to_interval(bit_slide_ps);
}
else {
......@@ -87,6 +87,18 @@ static int run_all_state_machines(struct pp_globals *ppg)
delay_ms = delay_ms_j;
}
/* BMCA must run at least once per announce interval 9.2.6.8 */
if (pp_gtimeout(ppg, PP_TO_BMC)) {
bmc_calculate_ebest(ppg); /* Calculation of erbest, ebest ,... */
pp_gtimeout_set(ppg, PP_TO_BMC,TMO_DEFAULT_BMCA_MS);
delay_ms=0;
} else {
/* check if the BMC timeout is the next to run */
int delay_bmca;
if ( (delay_bmca=pp_gnext_delay_1(ppg,PP_TO_BMC))<delay_ms )
delay_ms=delay_bmca;
}
return delay_ms;
}
......@@ -147,7 +159,7 @@ static int stop_alarm(timer_t *timerid) {
fprintf(stderr, "ppsi: Cannot stop timer\n");
return 0;
}
return ito.it_value.tv_sec*1000+ito.it_value.tv_nsec/1000000;
return (int) (ito.it_value.tv_sec*1000+ito.it_value.tv_nsec/1000000);
}
......
......@@ -9,7 +9,7 @@ STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
CFLAGS = -Wall -ggdb -O2 -fno-strict-aliasing
CFLAGS = -Wall $(CFLAGS_OPTIMIZATION) -fno-strict-aliasing
LDFLAGS = -L. -lminipc -lm
# We need to support freestading environments: an embedded CPU that
......@@ -36,7 +36,7 @@ export IPC_FREESTANDING IPC_HOSTED
all: $(LIB)
$(MAKE) -C examples
$(MAKE) -C examples CFLAGS_OPTIMIZATION="$(CFLAGS_OPTIMIZATION)"
$(LIB): $(OBJ-y)
$(AR) r $@ $^
......
......@@ -11,7 +11,7 @@ STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
CFLAGS = -Wall -ggdb -I.. -O2
CFLAGS = -Wall $(CFLAGS_OPTIMIZATION) -I..
LDFLAGS = -L.. -lminipc -lm
# we may be hosted or freestanding. For freestanding there is one
......
#!/bin/bash
set -e
if ! [ -n "$size_info_file" ]; then
echo "save_size.sh: 'size_info_file' is empty"
exit 0
fi
# separate calling commands and filling DB
SIZES=`$1 $2 | grep $2`
#GIT_HASH=`git log --format=format:%H -1`
#echo -n "$GIT_HASH " >> "$size_info_file"
#echo -n "$DEFCONFIG_NAME ">> "$size_info_file"
#echo $SIZES >> "$size_info_file"
echo -n `date -u "+%m/%d/%y_%H:%M:%S"`>> "$size_info_file"
echo -n " $DEFCONFIG_NAME ">> "$size_info_file"
echo -n $SIZES >> "$size_info_file"
echo " Opt=\"$CFLAGS_OPTIMIZATION\"" >> "$size_info_file"
# update file, keeping only non redundant lines
tac "$size_info_file" | awk '!x[$1]++ { print $0 }' | tac >> tmp.txt
mv tmp.txt $size_info_file
rm -f tmp.txt
......@@ -35,13 +35,13 @@ int wrs_read_calibration_data(struct pp_instance *ppi,
* way as the HAL itself was doing to fill the RPC structure.
* Formulas copied from libwr/hal_shmem.c (get_exported_state).
*/
#if CONFIG_PROFILE_WR == 1
port_fix_alpha = FIX_ALPHA_TWO_POW_FRACBITS *
((p->calib.sfp.alpha + 1.0) / (p->calib.sfp.alpha + 2.0)
- 0.5);
#else
port_fix_alpha =0;
#endif
if ( CONFIG_HAS_PROFILE_WR ) {
port_fix_alpha = FIX_ALPHA_TWO_POW_FRACBITS *
((p->calib.sfp.alpha + 1.0) / (p->calib.sfp.alpha + 2.0)
- 0.5);
} else {
port_fix_alpha =0;
}
if ( delta_tx || delta_rx) {
port_delta_tx = p->calib.delta_tx_phy
......@@ -73,13 +73,13 @@ int wrs_read_correction_data(struct pp_instance *ppi, int64_t *fiber_fix_alpha,
wrs_read_calibration_data(ppi, NULL, NULL,NULL, &port_cP, bit_slide_ps);
if(fiber_fix_alpha) {
#if CONFIG_PROFILE_WR == 1
double alpha;
alpha = ((double) ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient)/REL_DIFF_TWO_POW_FRACBITS;
*fiber_fix_alpha = FIX_ALPHA_TWO_POW_FRACBITS * ((alpha + 1.0) / (alpha + 2.0) - 0.5);
#else
*fiber_fix_alpha=0;
#endif
if ( CONFIG_HAS_PROFILE_WR ) {
double alpha;
alpha = ((double) ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient)/REL_DIFF_TWO_POW_FRACBITS;
*fiber_fix_alpha = FIX_ALPHA_TWO_POW_FRACBITS * ((alpha + 1.0) / (alpha + 2.0) - 0.5);
} else {
*fiber_fix_alpha=0;
}
}
if(clock_period_ps)
......
......@@ -28,16 +28,16 @@ static struct minipc_pd __rpcdef_cmd = {
static int wrsipc_cmd(int cmd, int value)
{
if(cmd == PTPDEXP_COMMAND_WR_TRACKING) {
#if CONFIG_EXT_WR == 1
wr_servo_enable_tracking(value);
return 0;
#endif
if ( CONFIG_HAS_EXT_WR ) {
wr_servo_enable_tracking(value);
return 0;
}
}
if(cmd == PTPDEXP_COMMAND_L1SYNC_TRACKING) {
#if CONFIG_EXT_L1SYNC == 1
l1e_servo_enable_tracking(value);
return 0;
#endif
if ( CONFIG_HAS_EXT_L1SYNC ) {
l1e_servo_enable_tracking(value);
return 0;
}
}
return -1;
......
......@@ -51,6 +51,10 @@ struct wrh_operations wrh_oper = {
.calib_pattern_disable = wrs_calibration_pattern_disable,
.enable_timing_output = wrs_enable_timing_output,
.set_timing_mode= wrs_set_timing_mode,
.get_timing_mode= wrs_get_timing_mode,
.get_timing_mode_state= wrs_get_timing_mode_state,
};
struct minipc_ch *hal_ch;
......@@ -61,7 +65,7 @@ struct wrs_shm_head *ppsi_head;
extern struct pp_ext_hooks pp_hooks;
#if CONFIG_EXT_L1SYNC
#if CONFIG_HAS_EXT_L1SYNC
/**
* Enable the l1sync extension for a given ppsi instance
*/
......@@ -93,7 +97,7 @@ static int enable_l1Sync(struct pp_instance *ppi, Boolean enable) {
* delayCoeff/(delayCoeff/2)
*/
static __inline__ double calculateDelayAsymCoefficient(double delayCoefficient) {
return delayCoefficient/(delayCoefficient+2.0L);
return delayCoefficient/(delayCoefficient+2.0);
}
/**
......@@ -251,7 +255,7 @@ int main(int argc, char **argv)
* exactly after stbcnt. It's a bad hack, but it works
*/
p = (int *)(&t.stbcnt) + 1;
ppg->timePropertiesDS->currentUtcOffset = *p;
ppg->timePropertiesDS->currentUtcOffset = (Integer16)*p;
}
if (pp_parse_cmdline(ppg, argc, argv) != 0)
......@@ -263,18 +267,16 @@ int main(int argc, char **argv)
if (ppg->cfg.cfg_items == 0) {
/* Default configuration for switch is all ports - Priority given to HA */
char s[128];
int i;
for (i = 0; i < WRS_NUMBER_PHYSICAL_PORTS; i++) {
Boolean configured=FALSE;
#if CONFIG_PROFILE_HA == 1
sprintf(s, "port %i; iface wri%i; proto raw; profile ha", i + 1, i + 1);
#endif
#if CONFIG_PROFILE_WR == 1
configured=TRUE;
if ( ! configured )
sprintf(s, "port %i; iface wri%i; proto raw; profile wr", i + 1, i + 1);
#endif
if ( CONFIG_HAS_PROFILE_HA )
sprintf(s, "port %i; iface wri%i; proto raw; profile ha", i + 1, i + 1);
if ( CONFIG_HAS_PROFILE_WR ) {
configured=TRUE;
if ( ! configured )
sprintf(s, "port %i; iface wri%i; proto raw; profile wr", i + 1, i + 1);
}
pp_config_string(ppg, s);
}
}
......@@ -291,76 +293,81 @@ int main(int argc, char **argv)
ppi->portDS = wrs_shm_alloc(ppsi_head, sizeof(*ppi->portDS));
ppi->servo = wrs_shm_alloc(ppsi_head, sizeof(*ppi->servo));
ppi->ext_hooks=&pp_hooks; /* Default value. Can be overwritten by an extension */
ppi->ptp_support=FALSE;
ppi->ptp_support=TRUE;
if (ppi->portDS) {
switch (ppi->cfg.profile) {
#if CONFIG_PROFILE_WR == 1
case PPSI_PROFILE_WR :
ppi->protocol_extension=PPSI_EXT_WR;
/* Add WR extension portDS */
if ( !(ppi->portDS->ext_dsport =
wrs_shm_alloc(ppsi_head, sizeof(struct wr_dsport))) ) {
goto exit_out_of_memory;
}
if ( CONFIG_HAS_PROFILE_WR ) {
ppi->protocol_extension=PPSI_EXT_WR;
/* Add WR extension portDS */
if ( !(ppi->portDS->ext_dsport =
wrs_shm_alloc(ppsi_head, sizeof(struct wr_dsport))) ) {
goto exit_out_of_memory;
}
/* Allocate WR data extension */
if (! (ppi->ext_data = wrs_shm_alloc(ppsi_head,sizeof(struct wr_data))) ) {
goto exit_out_of_memory;
/* Allocate WR data extension */
if (! (ppi->ext_data = wrs_shm_alloc(ppsi_head,sizeof(struct wr_data))) ) {
goto exit_out_of_memory;
}
/* Set WR extension hooks */
ppi->ext_hooks=&wr_ext_hooks;
ppi->cfg.egressLatency_ps=ppi->cfg.ingressLatency_ps=0; /* Forced to 0: Already taken into account in WR calculation */
} else {
fprintf(stderr, "ppsi: Profile WR not supported");
exit(1);
}
/* Set WR extension hooks */
ppi->ext_hooks=&wr_ext_hooks;
ppi->cfg.egressLatency_ps=ppi->cfg.ingressLatency_ps=0; /* Forced to 0: Already taken into account in WR calculation */
break;
#endif
#if CONFIG_PROFILE_HA == 1
case PPSI_PROFILE_HA :
if ( !enable_l1Sync(ppi,TRUE) )
goto exit_out_of_memory;
/* Force mandatory attributes - Do not take care of the configuration */
L1E_DSPOR_BS(ppi)->rxCoherentIsRequired =
L1E_DSPOR_BS(ppi)->txCoherentIsRequired =
L1E_DSPOR_BS(ppi)->congruentIsRequired=
L1E_DSPOR_BS(ppi)->L1SyncEnabled=TRUE;
L1E_DSPOR_BS(ppi)->optParamsEnabled=FALSE;
enable_asymmetryCorrection(ppi,TRUE);
if ( CONFIG_HAS_PROFILE_HA ) {
if ( !enable_l1Sync(ppi,TRUE) )
goto exit_out_of_memory;
/* Force mandatory attributes - Do not take care of the configuration */
L1E_DSPOR_BS(ppi)->rxCoherentIsRequired =
L1E_DSPOR_BS(ppi)->txCoherentIsRequired =
L1E_DSPOR_BS(ppi)->congruentIsRequired=
L1E_DSPOR_BS(ppi)->L1SyncEnabled=TRUE;
L1E_DSPOR_BS(ppi)->optParamsEnabled=FALSE;
enable_asymmetryCorrection(ppi,TRUE);
}
else {
fprintf(stderr, "ppsi: Profile HA not supported");
exit(1);
}
break;
#endif
case PPSI_PROFILE_PTP :
/* Do not take care of L1SYNC */
enable_asymmetryCorrection(ppi,ppi->cfg.asymmetryCorrectionEnable);
ppi->protocol_extension=PPSI_EXT_NONE;
break;
#if CONFIG_PROFILE_CUSTOM == 1
case PPSI_PROFILE_CUSTOM :
if ( CONFIG_HAS_PROFILE_CUSTOM ) {
ppi->protocol_extension=PPSI_EXT_NONE; /* can be changed ...*/
#if CONFIG_EXT_L1SYNC
if (ppi->cfg.l1SyncEnabled ) {
if ( !enable_l1Sync(ppi,TRUE) )
goto exit_out_of_memory;
/* Read L1SYNC parameters */
L1E_DSPOR_BS(ppi)->rxCoherentIsRequired =ppi->cfg.l1SyncRxCoherencyIsRequired;
L1E_DSPOR_BS(ppi)->txCoherentIsRequired =ppi->cfg.l1SyncTxCoherencyIsRequired;
L1E_DSPOR_BS(ppi)->congruentIsRequired =ppi->cfg.l1SyncCongruencyIsRequired;
L1E_DSPOR_BS(ppi)->optParamsEnabled=ppi->cfg.l1SyncOptParamsEnabled;
if ( L1E_DSPOR_BS(ppi)->optParamsEnabled ) {
L1E_DSPOR_OP(ppi)->timestampsCorrectedTx=ppi->cfg.l1SyncOptParamsTimestampsCorrectedTx;
if ( CONFIG_HAS_EXT_L1SYNC ) {
if (ppi->cfg.l1SyncEnabled ) {
if ( !enable_l1Sync(ppi,TRUE) )
goto exit_out_of_memory;
/* Read L1SYNC parameters */
L1E_DSPOR_BS(ppi)->rxCoherentIsRequired =ppi->cfg.l1SyncRxCoherencyIsRequired;
L1E_DSPOR_BS(ppi)->txCoherentIsRequired =ppi->cfg.l1SyncTxCoherencyIsRequired;
L1E_DSPOR_BS(ppi)->congruentIsRequired =ppi->cfg.l1SyncCongruencyIsRequired;
L1E_DSPOR_BS(ppi)->optParamsEnabled=ppi->cfg.l1SyncOptParamsEnabled;
if ( L1E_DSPOR_BS(ppi)->optParamsEnabled ) {
L1E_DSPOR_OP(ppi)->timestampsCorrectedTx=ppi->cfg.l1SyncOptParamsTimestampsCorrectedTx;
}
}
}
#endif
enable_asymmetryCorrection(ppi,ppi->cfg.asymmetryCorrectionEnable);
} else {
fprintf(stderr, "ppsi: Profile CUSTOM not supported");
exit(1);
}
break;
#endif
}
/* Parameters profile independent */
ppi->timestampCorrectionPortDS.egressLatency=picos_to_interval(ppi->cfg.egressLatency_ps);
ppi->timestampCorrectionPortDS.ingressLatency=picos_to_interval(ppi->cfg.ingressLatency_ps);
ppi->timestampCorrectionPortDS.messageTimestampPointLatency=0;
ppi->portDS->masterOnly= ppi->cfg.masterOnly; /* can be overridden in pp_init_globals() */
ppi->portDS->logAnnounceInterval=ppi->cfg.announce_interval;
ppi->portDS->announceReceiptTimeout=ppi->cfg.announce_receipt_timeout;
ppi->portDS->logSyncInterval=ppi->cfg.sync_interval;
ppi->portDS->logMinDelayReqInterval=ppi->cfg.min_delay_req_interval;
ppi->portDS->logMinPdelayReqInterval=ppi->cfg.min_pdelay_req_interval;
} else {
goto exit_out_of_memory;
}
......@@ -379,9 +386,63 @@ int main(int argc, char **argv)
pp_init_globals(ppg, &__pp_default_rt_opts);
seed = time(NULL);
{
timing_mode_t prev_timing_mode=WRH_OPER()->get_timing_mode(ppg);
int nbRetry;
int enablePPS;
if ( ppg->defaultDS->clockQuality.clockClass == PP_PTP_CLASS_GM_LOCKED ) {
if (prev_timing_mode==-1) {
fprintf(stderr, "ppsi: Cannot get current timing mode\n");
exit(1);
}
/* If read timing mode was GM, then we do not reprogram the hardware because it
* may unlock the PLL.
*/
if ( prev_timing_mode != TM_GRAND_MASTER ){
/* Timing mode was not GM before */
WRH_OPER()->set_timing_mode(ppg,TM_GRAND_MASTER);
ppg->waitGmLocking=1; /* We might wait PPL locking ... see below */
}
} else {
/* Timing mode will be set to BC when a port will become slave */
WRH_OPER()->set_timing_mode(ppg,TM_FREE_MASTER);
}
/* Waiting for PLL locking. We do not need a precise time-out here */
/* We are waiting up to 3s for PLL locking.
* We do that to avoid to jump too quickly to a degraded clock class.
*/
nbRetry=2;
while(nbRetry>0) {
if ( WRH_OPER()->get_timing_mode_state(ppg)==PP_TIMING_MODE_STATE_LOCKED )
break;
sleep(1); // wait 1s
nbRetry--;
} // if nbRetry>0 it means that the PLL is locked
if ( (ppg->waitGmLocking=ppg->waitGmLocking && nbRetry==0)==1 ) {
/* we degrade the clockClass to be sure that all instances will stay in
* initializing state until the clock class goes to PP_PTP_CLASS_GM_LOCKED
*/
//GDSDEF(ppg)->clockQuality.clockClass = PP_PTP_CLASS_GM_UNLOCKED;
}
/* Enable the PPS generation only if
* - Grand master and PLL is locked
* OR
* - Free running master (no condition required)
* OOR
* - Timing output is forced (for testing only)
*/
enablePPS=(nbRetry>0 && ppg->defaultDS->clockQuality.clockClass == PP_PTP_CLASS_GM_LOCKED) ||
( ppg->defaultDS->clockQuality.clockClass == PP_PTP_CLASS_GM_UNLOCKED ||
GOPTS(ppg)->forcePpsGen);
WRH_OPER()->enable_timing_output(ppg,enablePPS);
}
seed = (unsigned long) time(NULL);
if (getenv("PPSI_DROP_SEED"))
seed = atoi(getenv("PPSI_DROP_SEED"));
seed = (unsigned long) atoi(getenv("PPSI_DROP_SEED"));
ppsi_drop_init(ppg, seed);
/* release lock from wrs_shm_get */
......
......@@ -162,7 +162,7 @@ static int pp_packet_prefilter(struct pp_instance *ppi)
if (!memcmp(&hdr->sourcePortIdentity.clockIdentity,
&DSPOR(ppi)->portIdentity.clockIdentity,
sizeof(ClockIdentity))) {
if (DSDEF(ppi)->numberPorts > 1) {
if ( get_numberPorts(DSDEF(ppi)) > 1) {
/* Announces are handled by the BMC, since otherwise the state
* also the PASSIVE states in this case is overwritten */
if (hdr->messageType != PPM_ANNOUNCE) {
......@@ -286,8 +286,8 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
if ( ppi->ext_hooks->get_tmo_lstate_detection!=NULL)
tmo=(*ppi->ext_hooks->get_tmo_lstate_detection)(ppi);
else
tmo= ppi->timeouts[PP_TO_ANN_RECEIPT].initValueMs;
__pp_timeout_set(ppi,PP_TO_PROT_STATE, tmo);
tmo= pp_timeout_get(ppi,PP_TO_ANN_RECEIPT);
pp_timeout_set(ppi,PP_TO_PROT_STATE, tmo);
}
}
if ( !ppi->ext_enabled && ppi->link_state==PP_LSTATE_PROTOCOL_DETECTION) {
......@@ -321,18 +321,16 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
/* run bmc independent of state, and since not message driven do this
* here 9.2.6.8 */
if (pp_timeout(ppi, PP_TO_BMC)) {
ppi->next_state = bmc(ppi);
if ( ppi->bmca_execute) {
ppi->bmca_execute=0; /* Clear the trigger */
ppi->next_state = bmc_apply_state_descision(ppi);
/* done: if new state mark it, and enter it now (0 ms) */
if (ppi->state != ppi->next_state)
return pp_leave_current_state(ppi);
}
/* check if the BMC timeout is the next to run */
if (pp_next_delay_1(ppi, PP_TO_BMC) < ppi->next_delay)
ppi->next_delay = pp_next_delay_1(ppi, PP_TO_BMC);
pp_diag_fsm(ppi, ip->name, STATE_LOOP, 0);
/* Run the extension state machine. The extension can provide its own time-out */
......
......@@ -10,6 +10,7 @@
#define __WRH_H__
#include <stdint.h>
#include <hal_exports.h>
#include <ppsi/lib.h>
/* Please increment WRS_PPSI_SHMEM_VERSION if you change any exported data structure */
......@@ -34,16 +35,19 @@
#define WRH_SERVO_OFFSET_STABILITY_THRESHOLD 60 /* psec */
#ifdef CONFIG_WRPC_FAULTS
#define PROTO_EXT_HAS_FAULTS 1
#else
#define PROTO_EXT_HAS_FAULTS 0
#endif
/* Parameter of wrs_set_timing_mode */
typedef enum {
TM_GRAND_MASTER=HAL_TIMING_MODE_GRAND_MASTER,
TM_FREE_MASTER= HAL_TIMING_MODE_FREE_MASTER,
TM_BOUNDARY_CLOCK=HAL_TIMING_MODE_BC,
TM_DISABLED=HAL_TIMING_MODE_DISABLED
}timing_mode_t;
/* White Rabbit hw-dependent functions (code in arch-wrpc and arch-wrs) */
struct wrh_operations {
int (*locking_enable)(struct pp_instance *ppi);
int (*locking_poll)(struct pp_instance *ppi, int grandmaster);
int (*locking_poll)(struct pp_instance *ppi);
int (*locking_disable)(struct pp_instance *ppi);
int (*locking_reset)(struct pp_instance *ppi);
int (*enable_ptracker)(struct pp_instance *ppi);
......@@ -63,10 +67,12 @@ struct wrh_operations {
unsigned int calibrationPattern,
unsigned int calibrationPatternLen);
int (*calib_pattern_disable)(struct pp_instance *ppi);
int (*enable_timing_output)(struct pp_instance *ppi, int enable);
int (*enable_timing_output)(struct pp_globals *,int enable);
int (*read_corr_data)(struct pp_instance *ppi, int64_t *fixAlpha,
int32_t *clock_period, uint32_t *bit_slide_ps);
timing_mode_t (*get_timing_mode)(struct pp_globals *);
timing_mode_state_t (*get_timing_mode_state)(struct pp_globals *);
int (*set_timing_mode)(struct pp_globals *, timing_mode_t tm);
};
extern struct wrh_operations wrh_oper;
......
......@@ -24,10 +24,4 @@ extern void __assert(const char *func, int line, int forever,
const char *fmt, ...)
__attribute__((format(printf, 4, 5)));
#ifdef CONFIG_ASSERT
# define CONFIG_HAS_ASSERT 1
#else
# define CONFIG_HAS_ASSERT 0
#endif
#endif /* __ASSERT_H__ */
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Jean-Claude BAU
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
/* platform independent timespec-like data structure */
struct pp_cfg_time {
long tv_sec;
long tv_nsec;
};
/* Data structure used to pass just a single argument to configuration
* functions. Any future new type for any new configuration function can be just
* added inside here, without redefining cfg_handler prototype */
union pp_cfg_arg {
int i;
int i2[2];
int64_t i64;
double d;
Boolean b;
char *s;
struct pp_cfg_time ts;
};
/*
* Configuration: we are structure-based, and a typedef simplifies things
*/
struct pp_argline;
typedef int (*cfg_handler)(struct pp_argline *l, int lineno,
struct pp_globals *ppg, union pp_cfg_arg *arg);
struct pp_argname {
char *name;
int value;
};
enum pp_argtype {
ARG_NONE,
ARG_INT,
ARG_INT2,
ARG_STR,
ARG_NAMES,
ARG_TIME,
ARG_DOUBLE,
ARG_INT64
};
/* This enumeration gives the list of run-time options that should be marked when they are set in the configuration */
enum {
OPT_RT_NO_UPDATE=0,
};
typedef struct {
union min {
int min_int;
Integer64 min_int64;
double min_double;
}min;
union max{
int max_int;
Integer64 max_int64;
double max_double;
}max;
}pp_argline_min_max_t;
struct pp_argline {
cfg_handler f;
char *keyword; /* Each line starts with a keyword */
enum pp_argtype t;
struct pp_argname *args;
size_t field_offset;
int needs_port;
pp_argline_min_max_t min_max;
};
/* Below are macros for setting up pp_argline arrays */
#define OFFS(s,f) offsetof(s, f)
#define OPTION_OPEN() {
#define OPTION_CLOSE() }
#define OPTION(s,func,k,typ,a,field,np) \
.f = func, \
.keyword = k, \
.t = typ, \
.args = a, \
.field_offset = OFFS(s,field), \
.needs_port = np,
#define LEGACY_OPTION(func,k,typ) \
{ \
.f = func, \
.keyword = k, \
.t = typ, \
}
#define INST_OPTION(func,k,t,a,field) \
OPTION_OPEN() \
OPTION(struct pp_instance,func,k,t,a,field,1) \
OPTION_CLOSE()
#define INST_OPTION_FCT(func,k,t) \
OPTION_OPEN() \
OPTION(struct pp_instance,func,k,t,NULL,cfg,1) \
OPTION_CLOSE()
#define INST_OPTION_STR(k,field) \
INST_OPTION(f_string,k,ARG_STR,NULL,field)
#define INST_OPTION_INT_RANGE(k,t,a,field,mn,mx) \
OPTION_OPEN() \
OPTION(struct pp_instance,f_simple_int,k,t,a,field,1) \
.min_max.min.min_int = mn,\
.min_max.max.max_int = mx,\
OPTION_CLOSE()
#define INST_OPTION_INT(k,t,a,field) \
INST_OPTION_INT_RANGE(k,t,a,field,INT_MIN,INT_MAX)
#define INST_OPTION_BOOL(k,field) \
INST_OPTION(f_simple_bool,k,ARG_NAMES,arg_bool,field)
#define INST_OPTION_INT64_RANGE(k,t,a,field,mn,mx) \
OPTION_OPEN() \
OPTION(struct pp_instance,f_simple_int64,k,t,a,field,1) \
.min_max.min.min_int64 = mn,\
.min_max.max.max_int64 = mx,\
OPTION_CLOSE()
#define INST_OPTION_INT64(k,t,a,field) \
INST_OPTION_INT64_RANGE(k,t,a,field,INT64_MIN,INT64_MAX)
#define INST_OPTION_DOUBLE_RANGE(k,t,a,field,mn,mx) \
OPTION_OPEN() \
OPTION(struct pp_instance,f_simple_double,k,t,a,field,1) \
.min_max.min.min_double = mn,\
.min_max.max.max_double = mx,\
OPTION_CLOSE()
#define INST_OPTION_DOUBLE(k,t,a,field) \
INST_OPTION_DOUBLE_RANGE(k,t,a,field,-DBL_MAX,DBL_MAX)
#define RT_OPTION(func,k,t,a,field) \
OPTION_OPEN() \
OPTION(struct pp_runtime_opts,func,k,t,a,field,0)\
OPTION_CLOSE()
#define RT_OPTION_INT_RANGE(k,t,a,field,mn,mx) \
OPTION_OPEN() \
OPTION(struct pp_runtime_opts,f_simple_int,k,t,a,field,0) \
.min_max.min.min_int = mn,\
.min_max.max.max_int = mx,\
OPTION_CLOSE()
#define RT_OPTION_INT(k,t,a,field) \
RT_OPTION_INT_RANGE(k,t,a,field,INT_MIN,INT_MAX)
#define RT_OPTION_BOOL(k,field) \
RT_OPTION(f_simple_bool,k,ARG_NAMES,arg_bool,field)
#define RT_OPTION_BOOL_TRUE(k,field) \
RT_OPTION(f_simple_bool,k,ARG_NAMES,arg_bool_true,field)
#define RT_OPTION_BOOL_FALSE(k,field) \
RT_OPTION(f_simple_bool,k,ARG_NAMES,arg_bool_false,field)
#define GLOB_OPTION(func,k,t,a,field) \
OPTION_OPEN() \
OPTION(struct pp_globals,func,k,t,a,field,0) \
OPTION_CLOSE()
#define GLOB_OPTION_INT_RANGE(k,t,a,field,mn,mx) \
OPTION_OPEN() \
OPTION(struct pp_globals,f_simple_int,k,t,a,field,0) \
.min_max.min.min_int = mn,\
.min_max.max.max_int = mx,\
OPTION_CLOSE()
#define GLOB_OPTION_INT(k,t,a,field) \
GLOB_OPTION_INT_RANGE(k,t,a,field,INT_MIN,INT_MAX)
/* Both the architecture and the extension can provide config arguments */
extern struct pp_argline pp_arch_arglines[];
extern struct pp_argline pp_ext_arglines[];
/* Note: config_string modifies the string it receives */
extern int pp_config_string(struct pp_globals *ppg, char *s);
extern int pp_config_file(struct pp_globals *ppg, int force, char *fname);
extern int f_simple_int(struct pp_argline *l, int lineno,
struct pp_globals *ppg, union pp_cfg_arg *arg);
......@@ -14,7 +14,7 @@
#define PP_PSEC_PER_SEC ((int64_t)1000*(int64_t)PP_NSEC_PER_SEC)
/* implementation specific constants */
#define PP_MAX_LINKS 64
#define PP_MAX_LINKS (CONFIG_NR_PORTS*CONFIG_NR_INSTANCES_PER_PORT)
#define PP_DEFAULT_CONFIGFILE "/etc/ppsi.conf"
#define PP_DEFAULT_FLAGS 0
......@@ -58,6 +58,14 @@
#define PP_DEFAULT_EXT_PORT_CONFIG_ENABLE 0
#define PP_MIN_PTP_PPSGEN_THRESHOLD_MS 1
#define PP_MAX_PTP_PPSGEN_THRESHOLD_MS 1000
#define PP_DEFAULT_PTP_PPSGEN_THRESHOLD_MS 500
#define PP_MIN_GM_DELAY_TO_GEN_PPS_SEC 0
#define PP_MAX_GM_DELAY_TO_GEN_PPS_SEC 1000
#define PP_DEFAULT_GM_DELAY_TO_GEN_PPS_SEC 0 // No PPS
/* Clock classes (pag 55, PTP-2008). See ppsi-manual for an explanation */
#define PP_MIN_CLOCK_CLASS 0
#define PP_MAX_CLOCK_CLASS 255
......@@ -90,35 +98,19 @@
#define PP_ARB_VARIANCE_GM_HOLDOVER 0xC71D
#define PP_ARB_VARIANCE_GM_UNLOCKED 0xC71D
#define PP_SERVO_UNKNOWN 0
#define PP_SERVO_LOCKED 1
#define PP_SERVO_HOLDOVER 2
#define PP_SERVO_UNLOCKED 3
#ifdef CONFIG_ARCH_WRPC
#define PP_NR_FOREIGN_RECORDS 1 /* Does not follow the standard : Clause 9.3.2.4.5 */
#else
#define PP_NR_FOREIGN_RECORDS 5 /* Clause 9.3.2.4.5 : Minimum size capacity is 5 */
#endif
#define PP_FOREIGN_MASTER_TIME_WINDOW 4
#define PP_NR_FOREIGN_RECORDS CONFIG_NR_FOREIGN_RECORDS /* Clause 9.3.2.4.5 */
#define PP_FOREIGN_MASTER_TIME_WINDOW 4
#define PP_FOREIGN_MASTER_THRESHOLD 2
#define PP_DEFAULT_TTL 1
/* We use an array of timeouts, with these indexes */
enum pp_timeouts {
PP_TO_REQUEST = 0,
PP_TO_SYNC_SEND,
PP_TO_BMC,
PP_TO_ANN_RECEIPT,
PP_TO_ANN_SEND,
PP_TO_FAULT,
PP_TO_QUALIFICATION,
PP_TO_PROT_STATE,
/* Two timeouts for the protocol extension */
PP_TO_EXT_0,
PP_TO_EXT_1,
__PP_TO_ARRAY_SIZE,
};
#define PP_DEFAULT_TTL 1
typedef enum {
PP_TIMING_MODE_STATE_ERROR=-1,
PP_TIMING_MODE_STATE_UNLOCKED=0,
PP_TIMING_MODE_STATE_LOCKED,
PP_TIMING_MODE_STATE_HOLDOVER,
PP_TIMING_MODE_STATE_UNKNOWN
}timing_mode_state_t;
#define PP_ALTERNATE_MASTER_FLAG 1
#define PP_TWO_STEP_FLAG 2
......
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Jean-Claude BAU
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
extern struct pp_time faulty_stamps[6]; /* if unused, dropped at link time */
extern int frame_rx_delay_us; /* set by faults.c */
static inline void apply_faulty_stamp(struct pp_instance *ppi, int index)
{
if ( CONFIG_HAS_FAULT_INJECTION_MECHANISM ) {
assert(index >= 1 && index <= 6, "Wrong T index %i\n", index);
pp_time_add(&SRV(ppi)->t1 + index - 1, faulty_stamps + index - 1);
}
}
......@@ -79,10 +79,10 @@ typedef struct Timestamp { /* page 13 (33) -- no typedef expected */
#define REL_DIFF_FRACMASK 0x3fffffffffffffff
/* Min/max values for RelativeDifference type */
#define RELATIVE_DIFFERENCE_MIN_VALUE INT64_MIN
#define RELATIVE_DIFFERENCE_MAX_VALUE INT64_MAX
#define RELATIVE_DIFFERENCE_MIN_VALUE_AS_DOUBLE -2.0
#define RELATIVE_DIFFERENCE_MAX_VALUE_AS_DOUBLE 1.9999999999999989
#define RELATIVE_DIFFERENCE_MIN_VALUE (((int64_t)-1)<<REL_DIFF_FRACBITS) /* INT64_MIN */
#define RELATIVE_DIFFERENCE_MAX_VALUE (((int64_t) 1)<<REL_DIFF_FRACBITS) /* INT64_MAX */
#define RELATIVE_DIFFERENCE_MIN_VALUE_AS_DOUBLE -1.0 /*-2.0*/
#define RELATIVE_DIFFERENCE_MAX_VALUE_AS_DOUBLE 1.0 /*1.9999999999999989 */
/*draft P1588_v_29: page 17*/
/* The scaledRelativeDifference member is the relative difference expressed
......
......@@ -24,8 +24,12 @@ struct pp_runtime_opts {
int priority1;
int priority2;
int domainNumber;
int ptpPpsThresholdMs;
int gmDelayToGenPpsSec;
Boolean externalPortConfigurationEnabled;
Boolean slaveOnly;
Boolean forcePpsGen;
Boolean ptpFallbackPpsGen;
void *arch_opts;
};
......@@ -49,13 +53,15 @@ extern struct pp_instance_cfg __pp_default_instance_cfg;
* Communication channel. Is the abstraction of a unix socket, so that
* this struct is platform independent
*/
#define PP_MAC_ADRESS_SIZE 6
struct pp_channel {
union {
int fd; /* Posix wants fid descriptor */
void *custom; /* Other archs want other stuff */
};
void *arch_data; /* Other arch-private info, if any */
unsigned char addr[6]; /* Our own MAC address */
unsigned char addr[PP_MAC_ADRESS_SIZE]; /* Our own MAC address */
int pkt_present;
};
......@@ -159,7 +165,7 @@ struct pp_instance_cfg {
int sync_interval; /* Sync messages interval */
int min_delay_req_interval; /* delay request messages interval */
int min_pdelay_req_interval;/* pdelay request messages interval */
#if CONFIG_EXT_L1SYNC
#if CONFIG_HAS_EXT_L1SYNC
Boolean l1SyncEnabled; /* L1SYNC: protocol enabled */
Boolean l1SyncRxCoherencyIsRequired; /* L1SYNC: Rx coherency is required */
Boolean l1SyncTxCoherencyIsRequired; /* L1SYNC: Tx coherency is required */
......@@ -179,21 +185,6 @@ struct pp_instance_cfg {
Boolean asymmetryCorrectionEnable; /* asymmetryCorrectionPortDS.enable */
};
/*
* Time-out structure and enumeration
*/
enum to_rand_type {
TO_RAND_NONE, /* Not randomized */
TO_RAND_70_130, /* Should be 70% to 130% of 1 << value */
TO_RAND_0_200, /* Should be 0% to 200% of 1 << value */
} ;
typedef struct {
enum to_rand_type which_rand;
unsigned int initValueMs;
unsigned long tmo;
} t_timeOutConfig;
/*
* This enumeration correspond to the protocol state of a pp_instance.
* It is used to decide which instance must be active on a given port.
......@@ -265,7 +256,7 @@ struct pp_instance {
externalPortConfigurationPortDS_t externalPortConfigurationPortDS; /*draft P1588: Clause 17.6.3*/
/************************* */
t_timeOutConfig timeouts[__PP_TO_ARRAY_SIZE];
timeOutInstCnt_t tmo_cfg[PP_TO_COUNT];
UInteger16 recv_sync_sequence_id;
UInteger16 sent_seq[__PP_NR_MESSAGES_TYPES]; /* last sent this type */
......@@ -282,7 +273,7 @@ struct pp_instance {
unsigned long ptp_tx_count;
unsigned long ptp_rx_count;
#if CONFIG_HAS_P2P == 1
#if CONFIG_HAS_P2P
Boolean received_dresp; /* Count the number of delay response messages received for a given delay request */
Boolean received_dresp_fup; /* Count the number of delay response follow up messages received for a given delay request */
#endif
......@@ -290,6 +281,7 @@ struct pp_instance {
Boolean ptp_support; /* True if allow pure PTP support */
Boolean ext_enabled; /* True if the extension is enabled */
pp_link_state link_state;
Boolean bmca_execute; /* True: Ask fsm to run bmca state decision */
};
/* The following things used to be bit fields. Other flags are now enums */
......@@ -329,6 +321,9 @@ struct pp_globals {
void *arch_data; /* if arch needs it */
void *global_ext_data; /* if protocol ext needs it */
Boolean waitGmLocking; /* If set, instances must stay in initializing state until the GM PLL is locked */
/* FIXME Here include all is common to many interfaces */
};
......
This diff is collapsed.
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Jean-Claude BAU
*
* A timeout, is a number that must be compared with the current counter.
* A counter can be PPSi dependant or dependant.
* A set of predefined counters are declared and a set is free. It can
* be use by protocol extensions and specific task.
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#ifndef _TIMEOUT_DEF_H_
#define _TIMEOUT_DEF_H_
/*
* Time-out structure and enumeration
*/
typedef enum {
TO_RAND_NONE, /* Not randomized */
TO_RAND_70_130, /* Should be 70% to 130% of 1 << value */
TO_RAND_0_200, /* Should be 0% to 200% of 1 << value */
}to_rand_t ;
typedef struct {
to_rand_t which_rand;
int initValueMs;
unsigned long tmo;
} timeOutInstCnt_t;
/* We use an array of timeouts, with these indexes */
enum pp_timeouts {
PP_TO_REQUEST = 0,
PP_TO_SYNC_SEND,
PP_TO_BMC,
PP_TO_ANN_RECEIPT,
PP_TO_ANN_SEND,
PP_TO_FAULT,
PP_TO_QUALIFICATION,
PP_TO_PROT_STATE,
PP_TO_IN_STATE,
PP_TO_GM_BY_BMCA,
PP_TO_PREDEF_COUNTERS /* Number of predefined counters */
};
#define PP_TO_MAX_FREE_COUNTERS 6
#define PP_TO_COUNT (PP_TO_PREDEF_COUNTERS+PP_TO_MAX_FREE_COUNTERS)
/* Control flags */
#define TMO_CF_INSTANCE_DEPENDENT 1 /* PPSi instance dependent: each instance has its own counters */
#define TMO_CF_ALLOW_COMMON_SET 2 /* Counter reseted when pp_timeout_setall() is called */
#define TMO_DEFAULT_BMCA_MS 2000 /* Can be readjusted dynamically to be executed at lest once per announce send msg */
#endif /* ifndef _TIMEOUT_DEF_H_*/
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Jean-Claude BAU
*
* Timer prototypes.
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#ifndef _TIMEOUT_PROT_H_
#define _TIMEOUT_PROT_H_
#define TIMEOUT_DISABLE_VALUE -1
extern void pp_timeout_init(struct pp_instance *ppi);
extern void __pp_timeout_reset(struct pp_instance *ppi, int index,unsigned int multiplier);
extern int pp_timeout_get(struct pp_instance *ppi, int index);
extern void pp_timeout_setall(struct pp_instance *ppi);
extern int pp_timeout(struct pp_instance *ppi, int index)
__attribute__((warn_unused_result));
extern int pp_next_delay_1(struct pp_instance *ppi, int i1);
extern int pp_next_delay_2(struct pp_instance *ppi, int i1, int i2);
extern int pp_next_delay_3(struct pp_instance *ppi, int i1, int i2, int i3);
extern int pp_timeout_get_timer(struct pp_instance *ppi, char *name,
to_rand_t rand, int ctl_flags);
extern void pp_timeout_free_timer(struct pp_instance *ppi, int index);
extern void pp_timeout_set_rename(struct pp_instance *ppi,int index , int millisec, char *name);
extern void pp_timeout_disable_all(struct pp_instance *ppi);
/*
* Access to global timers : Do not depend on a PPSi instances
* Counters are stored on instance 0.
*/
static inline int pp_gtimeout_get(struct pp_globals *ppg, int index) {
return pp_timeout_get(INST(ppg,0),index);
}
static inline void pp_timeout_set(struct pp_instance *ppi,int index , int millisec)
{
pp_timeout_set_rename(ppi,index,millisec,NULL);
}
static inline void pp_gtimeout_set(struct pp_globals *ppg,int index , int millisec) {
pp_timeout_set(INST(ppg,0),index,millisec);
}
static inline int pp_timeout_is_disabled(struct pp_instance *ppi, int index)
{
return pp_timeout_get(ppi, index)==TIMEOUT_DISABLE_VALUE;
}
static inline int pp_gtimeout_is_disabled(struct pp_globals *ppg, int index)
{
return pp_gtimeout_get(ppg, index)==TIMEOUT_DISABLE_VALUE;
}
static inline void pp_timeout_disable(struct pp_instance *ppi, int index)
{
pp_timeout_set(ppi, index, TIMEOUT_DISABLE_VALUE);
}
static inline void pp_gtimeout_disable(struct pp_globals *ppg, int index)
{
pp_gtimeout_set(ppg, index, TIMEOUT_DISABLE_VALUE);
}
static inline void pp_gtimeout_reset(struct pp_globals *ppg, int index) {
__pp_timeout_reset(INST(ppg,0),index,1);
}
static inline int pp_gtimeout(struct pp_globals *ppg, int index) {
return pp_timeout(INST(ppg,0),index);
}
static inline int pp_gnext_delay_1(struct pp_globals *ppg, int index) {
return pp_next_delay_1(INST(ppg,0),index);
}
static inline int pp_gtimeout_get_timer(struct pp_globals *ppg, char *name, to_rand_t rand, int ctl_flags){
return pp_timeout_get_timer(INST(ppg,0),name,rand,ctl_flags);
}
static inline void pp_gtimeout_free_timer(struct pp_globals *ppg, int index){
pp_timeout_free_timer(INST(ppg,0),index);
}
static inline void pp_timeout_reset(struct pp_instance *ppi, int index)
{
__pp_timeout_reset(ppi,index,1);
}
static inline void pp_timeout_reset_N(struct pp_instance *ppi, int index, unsigned int multiplier)
{
__pp_timeout_reset(ppi,index,multiplier);
}
#endif // ifndef _TIMEOUT_PROT_H_
......@@ -15,6 +15,7 @@
#include <sys/types.h>
#include <sys/stat.h>
static inline struct pp_instance *CUR_PPI(struct pp_globals *ppg)
{
if (ppg->cfg.cur_ppi_n < 0)
......@@ -262,9 +263,23 @@ static struct pp_argname arg_proto[] = {
/* PROTO_VLAN is an internal modification of PROTO_RAW */
{},
};
#define STR_BOOL_TRUE "t true 1 on y yes"
#define STR_BOOL_FALSE "f false 0 off n no"
static struct pp_argname arg_bool[] = {
{"t true 1 on y yes", 1},
{"f false 0 off n no", 0},
{STR_BOOL_TRUE, 1},
{STR_BOOL_FALSE, 0},
{},
};
static struct pp_argname CAN_BE_UNUSED arg_bool_true[] = {
{STR_BOOL_TRUE, 1},
{},
};
static struct pp_argname CAN_BE_UNUSED arg_bool_false[] = {
{STR_BOOL_FALSE, 0},
{},
};
......@@ -283,18 +298,20 @@ static struct pp_argname arg_states[] = {
static struct pp_argname arg_profile[] = {
{"none ptp", PPSI_PROFILE_PTP}, /* none is equal to ptp for backward compatibility */
#if CONFIG_PROFILE_WR == 1
#if CONFIG_HAS_PROFILE_WR
{"whiterabbit wr", PPSI_PROFILE_WR},
#endif
#if CONFIG_PROFILE_HA == 1
#if CONFIG_HAS_PROFILE_HA
{"highaccuracy ha", PPSI_PROFILE_HA},
#endif
#if CONFIG_HAS_PROFILE_CUSTOM
{"custom", PPSI_PROFILE_CUSTOM},
#endif
{},
};
static struct pp_argname arg_delayMechanism[] = {
{"request-response delay e2e", E2E},
#if CONFIG_HAS_P2P == 1
#if CONFIG_HAS_P2P
{"peer-delay pdelay p2p", P2P},
#endif
{},
......@@ -321,7 +338,7 @@ static struct pp_argline pp_global_arglines[] = {
INST_OPTION_INT_RANGE("min-pdelay-req-interval logMinPDelayReqInterval", ARG_INT, NULL, cfg.min_pdelay_req_interval,
PP_MIN_MIN_PDELAY_REQ_INTERVAL,PP_MAX_MIN_PDELAY_REQ_INTERVAL),
#if CONFIG_EXT_L1SYNC==1
#if CONFIG_HAS_EXT_L1SYNC
INST_OPTION_INT_RANGE("l1sync-interval logL1SyncInterval", ARG_INT, NULL, cfg.l1syncInterval,
L1E_MIN_L1SYNC_INTERVAL,L1E_MAX_L1SYNC_INTERVAL),
INST_OPTION_INT_RANGE("l1sync-receipt-timeout l1SyncReceiptTimeout", ARG_INT, NULL, cfg.l1syncReceiptTimeout,
......@@ -359,8 +376,25 @@ static struct pp_argline pp_global_arglines[] = {
PP_MIN_PRIORITY1, PP_MAX_PRIORITY1),
RT_OPTION_INT_RANGE("priority2", ARG_INT, NULL, priority2,
PP_MIN_PRIORITY2, PP_MAX_PRIORITY2),
RT_OPTION_INT_RANGE("ptpPpsThresholdMs", ARG_INT, NULL, ptpPpsThresholdMs,
PP_MIN_PTP_PPSGEN_THRESHOLD_MS, PP_MAX_PTP_PPSGEN_THRESHOLD_MS),
RT_OPTION_INT_RANGE("gmDelayToGenPpsSec", ARG_INT, NULL, gmDelayToGenPpsSec,
PP_MIN_GM_DELAY_TO_GEN_PPS_SEC, PP_MAX_GM_DELAY_TO_GEN_PPS_SEC),
#if !CONFIG_HAS_CODEOPT_EPC_ENABLED && !CONFIG_HAS_CODEOPT_SO_ENABLED
RT_OPTION_BOOL("externalPortConfigurationEnabled",externalPortConfigurationEnabled),
RT_OPTION_BOOL("slaveOnly",slaveOnly),
#else
#if CONFIG_HAS_CODEOPT_EPC_ENABLED
RT_OPTION_BOOL_TRUE("externalPortConfigurationEnabled",externalPortConfigurationEnabled),
RT_OPTION_BOOL_FALSE("slaveOnly",slaveOnly),
#endif
#if CONFIG_HAS_CODEOPT_SO_ENABLED
RT_OPTION_BOOL_FALSE("externalPortConfigurationEnabled",externalPortConfigurationEnabled),
RT_OPTION_BOOL_TRUE("slaveOnly",slaveOnly),
#endif
#endif
RT_OPTION_BOOL("forcePpsGen",forcePpsGen),
RT_OPTION_BOOL("ptpFallbackPpsGen",ptpFallbackPpsGen),
{}
};
......
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Jean-Claude BAU
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#if CONFIG_HAS_FAULT_INJECTION_MECHANISM
struct pp_time faulty_stamps[6]; /* if unused, dropped at link time */
#if CONFIG_ARCH_IS_WRPC
int frame_rx_delay_us; /* set by faults.c */
#endif
#endif
......@@ -10,7 +10,7 @@ STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
CFLAGS += -I. -Os -ggdb -Wall
CFLAGS += -I. $(CFLAGS_OPTIMIZATION) -Wall
obj-$(CONFIG_PRINTF_FULL) += vsprintf-full.o
obj-$(CONFIG_PRINTF_MINI) += vsprintf-mini.o
......
......@@ -8,13 +8,7 @@
#ifndef __L1SYNC_EXT_API_H__
#define __L1SYNC_EXT_API_H__
#if CONFIG_EXT_L1SYNC == 1
#define PROTO_EXT_L1SYNC (1)
#else
#define PROTO_EXT_L1SYNC (0)
#endif
#if CONFIG_EXT_L1SYNC == 1
#if CONFIG_HAS_EXT_L1SYNC
#include <ppsi/lib.h>
#include "../include/hw-specific/wrh.h"
......@@ -22,10 +16,13 @@
#include <math.h>
#define PROTO_EXT_L1SYNC (1)
/* Rename the timeouts, for readability */
#define L1E_TIMEOUT_TX_SYNC PP_TO_EXT_0
#define L1E_TIMEOUT_RX_SYNC PP_TO_EXT_1
#define L1E_TIMEOUT_TX_SYNC l1eTmoTxSync
#define L1E_TIMEOUT_RX_SYNC l1eTmoRxSync
/* Time-out */
#define L1E_DEFAULT_L1SYNC_INTERVAL 0
#define L1E_MIN_L1SYNC_INTERVAL -4
#define L1E_MAX_L1SYNC_INTERVAL 4
......@@ -103,6 +100,9 @@ typedef struct { /*draft P1588_v_29: page 101 and 340-341 */
typedef struct {
L1SyncBasicPortDS_t basic;
L1SyncOptParamsPortDS_t opt_params;
/* Non standard variables */
int execute_state_machine;
}l1e_ext_portDS_t;
static inline l1e_ext_portDS_t *L1E_DSPOR(struct pp_instance *ppi)
......@@ -185,5 +185,12 @@ static inline int l1e_get_rx_tmo_ms(L1SyncBasicPortDS_t * bds) {
extern struct pp_ext_hooks l1e_ext_hooks;
/* Timer indexes */
extern int l1eTmoTxSync;
extern int l1eTmoRxSync;
#else
#define PROTO_EXT_L1SYNC (0)
#endif /* CONFIG_EXT_L1SYNC == 1 */
#endif /* __L1SYNC_EXT_API_H__ */
......@@ -19,6 +19,9 @@ char *l1e_state_name[] = {
[L1SYNC_UP] = "L1SYNC_UP",
};
int l1eTmoTxSync=0;
int l1eTmoRxSync=0;
void l1e_print_L1Sync_basic_bitmaps(struct pp_instance *ppi, uint8_t configed,
uint8_t active, char* text)
{
......@@ -77,6 +80,17 @@ static int l1e_init(struct pp_instance *ppi, void *buf, int len)
pp_diag(ppi, ext, 2, "hook: %s -- ext %i\n", __func__,
ppi->protocol_extension);
if ( l1eTmoTxSync==0) {
l1eTmoTxSync=pp_timeout_get_timer(ppi,"L1E_TX_SYNC",TO_RAND_NONE, TMO_CF_INSTANCE_DEPENDENT);
}
if ( l1eTmoRxSync==0)
l1eTmoRxSync=pp_timeout_get_timer(ppi,"L1E_RX_SYNC",TO_RAND_NONE, TMO_CF_INSTANCE_DEPENDENT);
pp_timeout_set(ppi, L1E_TIMEOUT_TX_SYNC, 100); /* Will be set later to the appropriate value */
pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, 100); /* Will be set later to the appropriate value */
// init dynamic data set members with zeros/defaults
bds->L1SyncLinkAlive = FALSE;
bds->isTxCoherent = FALSE;
......@@ -114,7 +128,7 @@ static int l1e_handle_signaling(struct pp_instance * ppi, void *buf, int len)
/* Valid Sync message */
/* Reset reception timeout */
__pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, l1e_get_rx_tmo_ms(bds));
pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, l1e_get_rx_tmo_ms(bds));
bds->L1SyncLinkAlive = TRUE;
if ( ppi->link_state==PP_LSTATE_PROTOCOL_DETECTION ||
......@@ -135,7 +149,6 @@ uint8_t l1e_creat_L1Sync_bitmask(int tx_coh, int rx_coh, int congru)
return outputMask;
}
static int l1e_handle_resp(struct pp_instance *ppi)
{
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
......@@ -145,11 +158,7 @@ static int l1e_handle_resp(struct pp_instance *ppi)
l1e_servo_got_resp(ppi);
}
else {
pp_servo_got_resp(ppi);
WRH_OPER()->enable_timing_output(ppi,
ppi->state==PPS_SLAVE &&
SRV(ppi)->offsetFromMaster.secs==0 &&
SRV(ppi)->offsetFromMaster.scaled_nsecs!=0);
pp_servo_got_resp(ppi,OPTS(ppi)->ptpFallbackPpsGen);
}
return 0;
}
......@@ -159,18 +168,8 @@ static int l1e_sync_followup(struct pp_instance *ppi) {
l1e_servo_got_sync(ppi);
}
else {
pp_servo_got_sync(ppi);
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P ) {
/* pps always on if offset less than 1 second,
* until ve have a configurable threshold
*/
WRH_OPER()->enable_timing_output(ppi,
ppi->state==PPS_SLAVE &&
SRV(ppi)->offsetFromMaster.secs==0 &&
SRV(ppi)->offsetFromMaster.scaled_nsecs!=0);
}
pp_servo_got_sync(ppi,OPTS(ppi)->ptpFallbackPpsGen);
}
return 1; /* the caller returns too */
}
......@@ -189,7 +188,7 @@ static int l1e_handle_sync(struct pp_instance *ppi)
return l1e_sync_followup(ppi);
}
static __attribute__((used)) int l1e_handle_presp(struct pp_instance *ppi)
static int l1e_handle_presp(struct pp_instance *ppi)
{
/* FIXME: verify that last-received cField is already accounted for */
if ( ppi->ext_enabled )
......@@ -223,6 +222,11 @@ static void l1e_state_change(struct pp_instance *ppi) {
L1E_DSPOR(ppi)->basic.L1SyncState=L1E_DSPOR(ppi)->basic.next_state=L1SYNC_DISABLED;
break;
}
if ( ppi->state==PPS_SLAVE && ppi->next_state!=PPS_UNCALIBRATED ) {
/* Leave SLAVE state : We must stop the PPS generation */
WRH_OPER()->enable_timing_output(GLBS(ppi),0);
WRH_OPER()->locking_reset(ppi);
}
}
static int l1e_new_slave (struct pp_instance *ppi, void *buf, int len) {
......
......@@ -7,24 +7,24 @@
#include <ppsi/ppsi.h>
#define MSG_OFFSET_HEADER 0
#define MSG_OFFSET_HEADER_MESSAGE_LENGTH (MSG_OFFSET_HEADER+2)
#define MSG_OFFSET_HEADER_CONTROL_FIELD (MSG_OFFSET_HEADER+32)
#define MSG_OFFSET_TARGET_PORT_IDENTITY 34
#define MSG_OFFSET_TARGET_PORT_IDENTITY_CLOCK_IDENTITY (MSG_OFFSET_TARGET_PORT_IDENTITY+0)
#define MSG_OFFSET_TARGET_PORT_IDENTITY_PORT_NUMBER (MSG_OFFSET_TARGET_PORT_IDENTITY+8)
#define MSG_OFFSET_TLV 44
#define MSG_OFFSET_HEADER 0u
#define MSG_OFFSET_HEADER_MESSAGE_LENGTH (MSG_OFFSET_HEADER+2u)
#define MSG_OFFSET_HEADER_CONTROL_FIELD (MSG_OFFSET_HEADER+32u)
#define MSG_OFFSET_TARGET_PORT_IDENTITY 34u
#define MSG_OFFSET_TARGET_PORT_IDENTITY_CLOCK_IDENTITY (MSG_OFFSET_TARGET_PORT_IDENTITY+0u)
#define MSG_OFFSET_TARGET_PORT_IDENTITY_PORT_NUMBER (MSG_OFFSET_TARGET_PORT_IDENTITY+8u)
#define MSG_OFFSET_TLV 44u
#define MSG_OFFSET_TLV_TYPE (MSG_OFFSET_TLV )
#define MSG_OFFSET_TLV_LENGTH_FIELD (MSG_OFFSET_TLV+2)
#define MSG_OFFSET_TLV_L1SYNC_PEER_CONF (MSG_OFFSET_TLV+4)
#define MSG_OFFSET_TLV_L1SYNC_PEER_ACTIVE (MSG_OFFSET_TLV+5)
#define MSG_OFFSET_TLV_L1SYNC_OPT_CONFIG (MSG_OFFSET_TLV+6)
#define MSG_OFFSET_TLV_L1SYNC_OPT_PHASE_OFFSET_TX (MSG_OFFSET_TLV+7)
#define MSG_OFFSET_TLV_L1SYNC_OPT_PHASE_OFFSET_TX_TIMESTAMP (MSG_OFFSET_TLV+15)
#define MSG_OFFSET_TLV_L1SYNC_OPT_FREQ_OFFSET_TX (MSG_OFFSET_TLV+25)
#define MSG_OFFSET_TLV_L1SYNC_OPT_FREQ_OFFSET_TX_TIMESTAMP (MSG_OFFSET_TLV+33)
#define MSG_OFFSET_TLV_L1SYNC_OPT_RESERVED (MSG_OFFSET_TLV+43)
#define MSG_OFFSET_TLV_LENGTH_FIELD (MSG_OFFSET_TLV+2u)
#define MSG_OFFSET_TLV_L1SYNC_PEER_CONF (MSG_OFFSET_TLV+4u)
#define MSG_OFFSET_TLV_L1SYNC_PEER_ACTIVE (MSG_OFFSET_TLV+5u)
#define MSG_OFFSET_TLV_L1SYNC_OPT_CONFIG (MSG_OFFSET_TLV+6u)
#define MSG_OFFSET_TLV_L1SYNC_OPT_PHASE_OFFSET_TX (MSG_OFFSET_TLV+7u)
#define MSG_OFFSET_TLV_L1SYNC_OPT_PHASE_OFFSET_TX_TIMESTAMP (MSG_OFFSET_TLV+15u)
#define MSG_OFFSET_TLV_L1SYNC_OPT_FREQ_OFFSET_TX (MSG_OFFSET_TLV+25u)
#define MSG_OFFSET_TLV_L1SYNC_OPT_FREQ_OFFSET_TX_TIMESTAMP (MSG_OFFSET_TLV+33u)
#define MSG_OFFSET_TLV_L1SYNC_OPT_RESERVED (MSG_OFFSET_TLV+43u)
#define MSG_OFFSET_HEADER_TYPE (MSG_OFFSET_HEADER+0)
......@@ -32,28 +32,27 @@
#define MSG_TYPE_SIGNALING 0xC
#define MSG_GET_16(buf,off) (*(UInteger16 *)(buf+off))
#define MSG_GET_8(buf,off ) *(UInteger8 *)(buf+off)
#define MSG_GET_16(buf,off) (*(UInteger16 *)((buf)+(off)))
#define MSG_GET_8(buf,off ) *(UInteger8 *)((buf)+(off))
#define MSG_GET_HEADER_TYPE(buf) (MSG_GET_8(buf,MSG_OFFSET_HEADER_TYPE) & 0x0f)
#define MSG_GET_TLV_TYPE(buf) ntohs(MSG_GET_16(buf,MSG_OFFSET_TLV_TYPE))
#define MSG_GET_TLV_LENGTH_FIELD(buf) ntohs(MSG_GET_16(buf,MSG_OFFSET_TLV_LENGTH_FIELD))
#define MSG_GET_TLV_TYPE(buf) ntohs((uint16_t)(MSG_GET_16(buf,MSG_OFFSET_TLV_TYPE)))
#define MSG_GET_TLV_LENGTH_FIELD(buf) ntohs((uint16_t)(MSG_GET_16(buf,MSG_OFFSET_TLV_LENGTH_FIELD)))
#define MSG_GET_TLV_L1SYNC_PEER_CONF(buf) MSG_GET_8(buf,MSG_OFFSET_TLV_L1SYNC_PEER_CONF)
#define MSG_GET_TLV_L1SYNC_PEER_ACTIVE(buf) MSG_GET_8(buf,MSG_OFFSET_TLV_L1SYNC_PEER_ACTIVE)
#define MSG_SET_HEADER_MESSAGE_LENGTH(buf,val) MSG_GET_16(buf,MSG_OFFSET_HEADER_MESSAGE_LENGTH) = htons(val)
#define MSG_SET_TLV_LENGTH_FIELD(buf,val) MSG_GET_16(buf,MSG_OFFSET_TLV_LENGTH_FIELD)=htons(val)
#define MSG_SET_TLV_L1SYNC_PEER_CONF(buf,val) MSG_GET_8(buf,MSG_OFFSET_TLV_L1SYNC_PEER_CONF)= val
#define MSG_SET_TLV_L1SYNC_PEER_ACTIVE(buf,val) MSG_GET_8(buf,MSG_OFFSET_TLV_L1SYNC_PEER_ACTIVE)=val
#define MSG_SET_HEADER_MESSAGE_LENGTH(buf,val) MSG_GET_16(buf,MSG_OFFSET_HEADER_MESSAGE_LENGTH) = (UInteger16)htons((uint16_t)(val))
#define MSG_SET_TLV_LENGTH_FIELD(buf,val) MSG_GET_16(buf,MSG_OFFSET_TLV_LENGTH_FIELD)=(UInteger16)htons((uint16_t)(val))
#define MSG_SET_TLV_L1SYNC_PEER_CONF(buf,val) MSG_GET_8(buf,MSG_OFFSET_TLV_L1SYNC_PEER_CONF)= (UInteger8)(val)
#define MSG_SET_TLV_L1SYNC_PEER_ACTIVE(buf,val) MSG_GET_8(buf,MSG_OFFSET_TLV_L1SYNC_PEER_ACTIVE)=(UInteger8)(val)
#define MSG_SET_TLV_L1SYNC_OPT_CONFIG(buf,val) MSG_GET_8(buf,MSG_OFFSET_TLV_L1SYNC_OPT_CONFIG)=val
#define MSG_SET_TLV_L1SYNC_OPT_CONFIG(buf,val) MSG_GET_8(buf,MSG_OFFSET_TLV_L1SYNC_OPT_CONFIG)=(UInteger8)(val)
#define TLV_TYPE_L1_SYNC 0x8001
#define TLV_TYPE_L1_SYNC 0x8001u
#define MSG_L1SYNC_LEN 50
#define MSG_L1SYNC_TLV_LENGTH 2
#define MSG_L1SYNC_TLV_EXTENDED_LENGTH 40
#define MSG_L1SYNC_LEN 50u
#define MSG_L1SYNC_TLV_LENGTH 2u
#define MSG_L1SYNC_TLV_EXTENDED_LENGTH 40u
int l1e_pack_signal(struct pp_instance *ppi)
{
......@@ -86,9 +85,9 @@ int l1e_pack_signal(struct pp_instance *ppi)
/* Extended format of L1_SYNC TLV */
L1SyncOptParamsPortDS_t * ods=L1E_DSPOR_OP(ppi);
local_config= (ods->timestampsCorrectedTx? 1 : 0) |
(ods->phaseOffsetTxValid ? 2 : 0 ) |
(ods->frequencyOffsetTxValid ? 4 : 0 );
local_config= (ods->timestampsCorrectedTx? (uint8_t)1 : (uint8_t)0) |
(ods->phaseOffsetTxValid ? (uint8_t)2 : (uint8_t)0 ) |
(ods->frequencyOffsetTxValid ? (uint8_t)4 : (uint8_t)0 );
MSG_SET_TLV_L1SYNC_OPT_CONFIG(buf,local_config);
msgLen+=38;
MSG_SET_TLV_LENGTH_FIELD(buf,MSG_L1SYNC_TLV_EXTENDED_LENGTH);
......
......@@ -22,8 +22,7 @@ static const char *l1e_servo_state_name[] = {
/* Enable tracking by default. Disabling the tracking is used for demos. */
static int l1e_tracking_enabled = 1;
static struct pp_time l1e_faulty_stamps[6]; /* if unused, dropped at link time */
extern struct pp_time faulty_stamps[6]; /* if unused, dropped at link time */
/* prototypes */
static int __l1e_servo_update(struct pp_instance *ppi);
......@@ -50,8 +49,6 @@ int l1e_servo_init(struct pp_instance *ppi)
if (l1e_update_correction_values(ppi) < 0)
return -1;
WRH_OPER()->enable_timing_output(ppi, 0);
/*
* Do not reset cur_setpoint, but trim it to be less than one tick.
* The softpll code uses the module anyways, but if we unplug-replug
......@@ -105,8 +102,8 @@ int l1e_servo_got_sync(struct pp_instance *ppi)
/* shmem lock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
gs->t1=ppi->t1;pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,1);
gs->t2=ppi->t2;pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps, 2);
gs->t1=ppi->t1;apply_faulty_stamp(ppi,1);
gs->t2=ppi->t2;apply_faulty_stamp(ppi,2);
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P && gs->got_sync) {
......@@ -141,8 +138,8 @@ int l1e_servo_got_resp(struct pp_instance *ppi)
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
gs->t3 = ppi->t3; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,3);
gs->t4 = ppi->t4; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,4);
gs->t3 = ppi->t3; apply_faulty_stamp(ppi,3);
gs->t4 = ppi->t4; apply_faulty_stamp(ppi,4);
ret=__l1e_servo_update(ppi);
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
......@@ -162,10 +159,10 @@ int l1e_servo_got_presp(struct pp_instance *ppi)
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
gs->t3 = ppi->t3; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,3);
gs->t4 = ppi->t4; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,4);
gs->t5 = ppi->t5; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,5);
gs->t6 = ppi->t6; pp_servo_apply_faulty_stamp(gs, l1e_faulty_stamps,6);
gs->t3 = ppi->t3; apply_faulty_stamp(ppi,3);
gs->t4 = ppi->t4; apply_faulty_stamp(ppi,4);
gs->t5 = ppi->t5; apply_faulty_stamp(ppi,5);
gs->t6 = ppi->t6; apply_faulty_stamp(ppi,6);
gs->got_sync=1;
......@@ -204,23 +201,13 @@ static int __l1e_servo_update(struct pp_instance *ppi)
gs->update_count++;
ppi->t_ops->get(ppi, &gs->update_time);
// if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P) {
// if (!l1e_p2p_offset(ppi, s, &offsetMS))
// goto out;
// } else {
// if (!l1e_e2e_offset(ppi, s, &offsetMS))
// goto out;
// }
if (pds->basic.L1SyncState != L1SYNC_UP)
return 1; /* State is not UP. We have to wait before to start the synchronisation */
locking_poll_ret = WRH_OPER()->locking_poll(ppi, 0);
locking_poll_ret = WRH_OPER()->locking_poll(ppi);
if (locking_poll_ret != WRH_SPLL_READY
&& locking_poll_ret != WRH_SPLL_CALIB_NOT_READY) {
pp_diag(ppi, servo, 1, "PLL OutOfLock, should restart sync\n");
WRH_OPER()->enable_timing_output(ppi, 0);
pp_diag(ppi, servo, 1, "PLL out of lock\n");
/* TODO check
* DSPOR(ppi)->doRestart = TRUE; */
}
......@@ -286,7 +273,7 @@ static int __l1e_servo_update(struct pp_instance *ppi)
gs->flags |= PP_SERVO_FLAG_WAIT_HW;
gs->state = L1E_WAIT_OFFSET_STABLE;
if (ARCH_IS_WRS) {
if (CONFIG_ARCH_IS_WRS) {
/*
* Now, let's fix system time. We pass here
* once only, so that's the best place to do
......@@ -305,7 +292,7 @@ static int __l1e_servo_update(struct pp_instance *ppi)
/* ts_to_picos() below returns phase alone */
remaining_offset = abs(pp_time_to_picos(&offsetMS));
if(remaining_offset < WRH_SERVO_OFFSET_STABILITY_THRESHOLD) {
WRH_OPER()->enable_timing_output(ppi, 1);
WRH_OPER()->enable_timing_output(GLBS(ppi),1);
s->prev_delayMS_ps = s->delayMS_ps;
gs->state = L1E_TRACK_PHASE;
} else {
......
......@@ -54,18 +54,17 @@ static l1e_state_machine_t le1_state_actions[] ={
*/
int l1e_run_state_machine(struct pp_instance *ppi) {
L1SyncBasicPortDS_t * basicDS=L1E_DSPOR_BS(ppi);
static Boolean execute_state_machine=TRUE;
Enumeration8 nextState=basicDS->next_state;
Boolean newState=nextState!=basicDS->L1SyncState;
int *execute_state_machine=&L1E_DSPOR(ppi)->execute_state_machine;
int delay;
if ( !ppi->ext_enabled )
if ( !ppi->ext_enabled || ppi->state==PPS_INITIALIZING)
return INT_MAX; /* Return a big delay. fsm will then not use it */
if ( nextState>=MAX_STATE_ACTIONS)
return pp_next_delay_2(ppi,L1E_TIMEOUT_TX_SYNC, L1E_TIMEOUT_RX_SYNC);
/*
* Update the L1SYNC dynamic data independent of the state machine
*/
......@@ -76,14 +75,14 @@ int l1e_run_state_machine(struct pp_instance *ppi) {
/* Check L1SYNC reception Time-out */
if ( pp_timeout(ppi, L1E_TIMEOUT_RX_SYNC) ) {
/* Time-out detected */
__pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, l1e_get_rx_tmo_ms(basicDS));
pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, l1e_get_rx_tmo_ms(basicDS));
basicDS->L1SyncLinkAlive = FALSE;
execute_state_machine=TRUE;
*execute_state_machine=TRUE;
}
/* Check L1SYNC transmission Time-out */
if ( pp_timeout(ppi, L1E_TIMEOUT_TX_SYNC) ) {
execute_state_machine=TRUE;
*execute_state_machine=TRUE;
}
/*
......@@ -92,10 +91,10 @@ int l1e_run_state_machine(struct pp_instance *ppi) {
if ( newState ) {
basicDS->L1SyncState=nextState;
pp_diag(ppi, ext, 2, "L1SYNC state: Enter %s\n", l1e_state_name[nextState]);
execute_state_machine=TRUE;
*execute_state_machine=TRUE;
}
if ( execute_state_machine ) {
if ( *execute_state_machine ) {
/* The state machine is executed only when really needed because
* fsm can call this function too often.
*/
......@@ -104,7 +103,7 @@ int l1e_run_state_machine(struct pp_instance *ppi) {
delay=pp_next_delay_2(ppi,L1E_TIMEOUT_TX_SYNC, L1E_TIMEOUT_RX_SYNC); /* Return the shorter timeout */
/* If return delay is 0, it means that the state machine should be executed at last call */
execute_state_machine= (delay==0);
*execute_state_machine= (delay==0);
if ( basicDS->L1SyncState != basicDS->next_state )
pp_diag(ppi, ext, 2, "L1SYNC state: Exit %s\n", l1e_state_name[basicDS->L1SyncState]);
......@@ -117,7 +116,7 @@ static int l1e_empty_action(struct pp_instance *ppi, Boolean new_state){
/* L1_SYNC_RESET event */
static inline Boolean le1_evt_L1_SYNC_RESET(struct pp_instance *ppi) {
return ppi->link_up == 0;
return ppi->link_up == 0 || ppi->state==PPS_INITIALIZING;
}
/* L1_SYNC_ENABLED event */
......@@ -144,7 +143,7 @@ static Boolean le1_evt_STATE_OK(struct pp_instance *ppi) {
switch (ppi->state) {
case PPS_SLAVE :
case PPS_UNCALIBRATED :
pll_state= WRH_OPER()->locking_poll(ppi, 0); /* Get the PPL state */
pll_state= WRH_OPER()->locking_poll(ppi); /* Get the PPL state */
basicDS->isCongruent =
basicDS->isRxCoherent= pll_state == WRH_SPLL_READY ? 1 : 0;
break;
......@@ -206,7 +205,7 @@ static __inline__ int measure_last_time(struct pp_instance *ppi, int fmeas) {
static void l1e_send_sync_msg(struct pp_instance *ppi, Boolean immediatSend) {
if (pp_timeout(ppi, L1E_TIMEOUT_TX_SYNC) || immediatSend) {
if (immediatSend || pp_timeout(ppi, L1E_TIMEOUT_TX_SYNC) ) {
int len;
int fmeas, lmeas;
int diff;
......@@ -226,7 +225,7 @@ static void l1e_send_sync_msg(struct pp_instance *ppi, Boolean immediatSend) {
tmo_ms=pp_timeout_log_to_ms(L1E_DSPOR_BS(ppi)->logL1SyncInterval);
if ( tmo_ms >= diff ) /* to be sure to have a positive value */
tmo_ms-=diff;
__pp_timeout_set(ppi, L1E_TIMEOUT_TX_SYNC,tmo_ms); /* loop ever since */
pp_timeout_set(ppi, L1E_TIMEOUT_TX_SYNC,tmo_ms); /* loop ever since */
}
}
......@@ -301,7 +300,7 @@ static int l1e_handle_state_link_alive(struct pp_instance *ppi, Boolean new_stat
/* State initialization */
if ( new_state ) {
/* Initialize time-out peer L1SYNC reception */
__pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, l1e_get_rx_tmo_ms(basic));
pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, l1e_get_rx_tmo_ms(basic));
}
/* Check if state transition needed */
......@@ -329,13 +328,14 @@ static int l1e_handle_state_config_match(struct pp_instance *ppi, Boolean new_st
switch ( ppi->state ) {
case PPS_SLAVE :
case PPS_UNCALIBRATED :
if ( basic->congruentIsRequired==1 && basic->isRxCoherent==0) {
if ( basic->congruentIsRequired ) {
basic->isRxCoherent=0;
pp_diag(ppi, ext, 1, "Locking PLL\n");
WRH_OPER()->locking_enable(ppi);
}
break;
case PPS_MASTER :
if ( basic->congruentIsRequired == 1) {
if ( basic->congruentIsRequired ) {
WRH_OPER()->locking_disable(ppi);
}
break;
......@@ -371,9 +371,6 @@ static int l1e_handle_state_up(struct pp_instance *ppi, Boolean new_state){
/* State initialization */
if ( new_state ) {
// JCB - test one servo
// l1e_servo_init(ppi); /* The servo can be initialized because the PPL is locked */
WRH_OPER()->enable_ptracker(ppi);
}
......
......@@ -2,12 +2,17 @@
/* ext-whiterabbit must offer its own hooks */
int wrTmoIdx=0; /* TimeOut Index */
static int wr_init(struct pp_instance *ppi, void *buf, int len)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
if ( wrTmoIdx==0)
wrTmoIdx=pp_timeout_get_timer(ppi,"WR_EXT_0",TO_RAND_NONE, TMO_CF_INSTANCE_DEPENDENT);
wrp->wrStateTimeout = WR_DEFAULT_STATE_TIMEOUT_MS;
wrp->calPeriod = WR_DEFAULT_CAL_PERIOD;
wrp->wrModeOn =
......@@ -22,14 +27,6 @@ static int wr_init(struct pp_instance *ppi, void *buf, int len)
ppi->next_state = WRS_WR_LINK_ON;
#endif
if ((wrp->wrConfig & WR_M_AND_S) == WR_M_ONLY
#ifdef CONFIG_ABSCAL
&& ptp_mode != 4 /* WRC_MODE_ABSCAL -- not defined in wrs build */
#endif
)
WRH_OPER()->enable_timing_output(ppi, 1);
else
WRH_OPER()->enable_timing_output(ppi, 0);
return 0;
}
......@@ -39,7 +36,7 @@ static int wr_open(struct pp_instance *ppi, struct pp_runtime_opts *rt_opts)
pp_diag(NULL, ext, 2, "hook: %s\n", __func__);
if (ppi->protocol_extension == PPSI_EXT_WR) {
if ( DSDEF(ppi)->slaveOnly ) {
if ( is_slaveOnly(DSDEF(ppi)) ) {
WR_DSPOR(ppi)->wrConfig = WR_S_ONLY;
} else {
if ( ppi->portDS->masterOnly ) {
......@@ -99,33 +96,16 @@ static int wr_new_slave(struct pp_instance *ppi, void *buf, int len)
static int wr_handle_resp(struct pp_instance *ppi)
{
struct pp_time *ofm = &SRV(ppi)->offsetFromMaster;
struct wr_dsport *wrp = WR_DSPOR(ppi);
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
/* This correction_field we received is already part of t4 */
/*
* If no WR mode is on, run normal code, if T2/T3 are valid.
* After we adjusted the pps counter, stamps are invalid, so
* we'll have the Unix time instead, marked by "correct"
*/
if (!wrp->wrModeOn) {
if ( is_timestamps_incorrect(ppi, NULL, 0x6 /* mask=t2&t3 */) ) {
pp_diag(ppi, servo, 1,
"T2 or T3 incorrect, discarding tuple\n");
return 0;
}
pp_servo_got_resp(ppi);
/*
* pps always on if offset less than 1 second,
* until ve have a configurable threshold */
WRH_OPER()->enable_timing_output(ppi, ofm->secs==0);
if ( ppi->ext_enabled ) {
wr_servo_got_delay(ppi);
wr_servo_update(ppi);
} else {
pp_servo_got_resp(ppi,OPTS(ppi)->ptpFallbackPpsGen);
}
wr_servo_got_delay(ppi);
wr_servo_update(ppi);
return 0;
}
......@@ -180,7 +160,7 @@ static int wr_handle_announce(struct pp_instance *ppi)
case WRS_RESP_CALIB_REQ :
case WRS_WR_LINK_ON :
/* reset announce timeout when in the WR slave states */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
pp_timeout_reset(ppi, PP_TO_ANN_RECEIPT);
}
/* handshake is started in slave mode */
......@@ -189,13 +169,14 @@ static int wr_handle_announce(struct pp_instance *ppi)
static int wr_sync_followup(struct pp_instance *ppi) {
if (!WR_DSPOR(ppi)->wrModeOn)
return 0;
wr_servo_got_sync(ppi);
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P)
wr_servo_update(ppi);
if ( ppi->ext_enabled ) {
wr_servo_got_sync(ppi);
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P)
wr_servo_update(ppi);
}
else {
pp_servo_got_sync(ppi,OPTS(ppi)->ptpFallbackPpsGen);
}
return 1; /* the caller returns too */
}
......@@ -214,34 +195,14 @@ static int wr_handle_followup(struct pp_instance *ppi)
return wr_sync_followup(ppi);
}
static __attribute__((used)) int wr_handle_presp(struct pp_instance *ppi)
static int wr_handle_presp(struct pp_instance *ppi)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
struct pp_time *ofm = &SRV(ppi)->offsetFromMaster;
/*
* If no WR mode is on, run normal code, if T2/T3 are valid.
* After we adjusted the pps counter, stamps are invalid, so
* we'll have the Unix time instead, marked by "correct"
*/
if (!wrp->wrModeOn) {
if ( is_timestamps_incorrect(ppi, NULL, 0x24 /* mask=t3&t6 */) ) {
pp_diag(ppi, servo, 1,
"T3 or T6 incorrect, discarding tuple\n");
return 0;
}
/* FIXME: verify that last-received cField is already accounted for */
if ( ppi->ext_enabled )
wr_servo_got_delay(ppi);
else
pp_servo_got_presp(ppi);
/*
* pps always on if offset less than 1 second,
* until ve have a configurable threshold */
WRH_OPER()->enable_timing_output(ppi, ofm->secs==0);
return 0;
}
/* FIXME: verify that last-received cField is already accounted for */
wr_servo_got_delay(ppi);
return 0;
}
......@@ -326,6 +287,11 @@ static void wr_state_change(struct pp_instance *ppi)
if (ppi->state == PPS_SLAVE)
WRH_OPER()->locking_reset(ppi);
}
if ( ppi->state==PPS_SLAVE && ppi->next_state!=PPS_UNCALIBRATED ) {
/* Leave SLAVE state : We must stop the PPS generation */
WRH_OPER()->enable_timing_output(GLBS(ppi),0);
}
}
static int wr_require_precise_timestamp(struct pp_instance *ppi) {
......
......@@ -30,15 +30,15 @@ int wr_abscal(struct pp_instance *ppi, void *buf, int plen)
if (ppi->is_new_state) {
/* add 1s to be enough in the future, the first time */
__pp_timeout_set(ppi, PP_TO_EXT_0, 990 + next_pps_ms(ppi, &t));
pp_timeout_set_rename(ppi, wrTmoIdx, 990 + next_pps_ms(ppi, &t),"WR_ABSCAL");
return 0;
}
i = next_pps_ms(ppi, &t) - 10;
if (pp_timeout(ppi, PP_TO_EXT_0)) {
if (pp_timeout(ppi, wrTmoIdx)) {
uint64_t secs = t.secs;
wrp->ops->enable_timing_output(ppi, 1);
WRH_OPER()->enable_timing_output(GLBS(ppi), 1);
/* Wait for the second to tick */
while( ppi->t_ops->get(ppi, &t), t.secs == secs)
......@@ -50,7 +50,7 @@ int wr_abscal(struct pp_instance *ppi, void *buf, int plen)
__send_and_log(ppi, len, PP_NP_EVT);
/* And again next second */
__pp_timeout_set(ppi, PP_TO_EXT_0, next_pps_ms(ppi, &t) - 10);
pp_timeout_set(ppi, wrTmoIdx, next_pps_ms(ppi, &t) - 10);
ppi->next_delay = next_pps_ms(ppi, &t) - 10;
return 0;
}
......
......@@ -20,10 +20,10 @@ int wr_calibrated(struct pp_instance *ppi, void *buf, int len)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
__pp_timeout_set(ppi, PP_TO_EXT_0, WR_CALIBRATED_TIMEOUT_MS*(WR_STATE_RETRY+1));
pp_timeout_set_rename(ppi, wrTmoIdx, WR_CALIBRATED_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_CLAIBRATED");
enable = 1;
} else {
int rms=pp_next_delay_1(ppi, PP_TO_EXT_0);
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_CALIBRATED_TIMEOUT_MS)) {
/*
* FIXME: We should implement a retry by re-sending
......@@ -53,6 +53,6 @@ int wr_calibrated(struct pp_instance *ppi, void *buf, int len)
ppi->next_state = WRS_WR_LINK_ON;
}
ppi->next_delay = pp_next_delay_1(ppi,PP_TO_EXT_0)-wrp->wrStateRetry*WR_CALIBRATED_TIMEOUT_MS;
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_CALIBRATED_TIMEOUT_MS;
return 0;
}
......@@ -20,10 +20,10 @@ int wr_calibration(struct pp_instance *ppi, void *buf, int len)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
__pp_timeout_set(ppi, PP_TO_EXT_0, wrp->calPeriod*(WR_STATE_RETRY+1));
pp_timeout_set_rename(ppi, wrTmoIdx, wrp->calPeriod*(WR_STATE_RETRY+1),"WR_CALIBRATED");
sendmsg = 1;
} else {
int rms=pp_next_delay_1(ppi, PP_TO_EXT_0);
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*wrp->calPeriod)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
......@@ -137,7 +137,7 @@ int wr_calibration(struct pp_instance *ppi, void *buf, int len)
break;
}
ppi->next_delay = pp_next_delay_1(ppi,PP_TO_EXT_0)-wrp->wrStateRetry*wrp->calPeriod;
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*wrp->calPeriod;
return 0; /* ignore error */
}
......@@ -20,10 +20,10 @@ int wr_locked(struct pp_instance *ppi, void *buf, int len)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
__pp_timeout_set(ppi, PP_TO_EXT_0, WR_LOCKED_TIMEOUT_MS*(WR_STATE_RETRY+1));
pp_timeout_set_rename(ppi, wrTmoIdx, WR_LOCKED_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_LOCKED");
sendmsg = 1;
} else {
int rms=pp_next_delay_1(ppi, PP_TO_EXT_0);
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_LOCKED_TIMEOUT_MS)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
......@@ -45,7 +45,7 @@ int wr_locked(struct pp_instance *ppi, void *buf, int len)
ppi->next_state = WRS_RESP_CALIB_REQ;
}
ppi->next_delay = pp_next_delay_1(ppi,PP_TO_EXT_0)-wrp->wrStateRetry*WR_LOCKED_TIMEOUT_MS;
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_LOCKED_TIMEOUT_MS;
return e;
}
......@@ -20,10 +20,10 @@ int wr_m_lock(struct pp_instance *ppi, void *buf, int len)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
__pp_timeout_set(ppi, PP_TO_EXT_0, WR_M_LOCK_TIMEOUT_MS*(WR_STATE_RETRY+1));
pp_timeout_set_rename(ppi, wrTmoIdx, WR_M_LOCK_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_MLOCK");
sendmsg = 1;
} else {
int rms=pp_next_delay_1(ppi, PP_TO_EXT_0);
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_M_LOCK_TIMEOUT_MS)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
......@@ -45,7 +45,7 @@ int wr_m_lock(struct pp_instance *ppi, void *buf, int len)
}
ppi->next_delay = pp_next_delay_1(ppi,PP_TO_EXT_0)-wrp->wrStateRetry*WR_M_LOCK_TIMEOUT_MS;
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_M_LOCK_TIMEOUT_MS;
return e;
}
......@@ -23,10 +23,10 @@ int wr_present(struct pp_instance *ppi, void *buf, int len)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
__pp_timeout_set(ppi, PP_TO_EXT_0, WR_PRESENT_TIMEOUT_MS*(WR_STATE_RETRY+1));
pp_timeout_set_rename(ppi, wrTmoIdx, WR_PRESENT_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_PRESENT");
sendmsg = 1;
} else {
int rms=pp_next_delay_1(ppi, PP_TO_EXT_0);
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_PRESENT_TIMEOUT_MS)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
......@@ -53,7 +53,7 @@ int wr_present(struct pp_instance *ppi, void *buf, int len)
/* nothing, just stay here again */
}
ppi->next_delay = pp_next_delay_1(ppi,PP_TO_EXT_0)-wrp->wrStateRetry*WR_PRESENT_TIMEOUT_MS;
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_PRESENT_TIMEOUT_MS;
return e;
}
......@@ -17,10 +17,10 @@ int wr_resp_calib_req(struct pp_instance *ppi, void *buf, int len)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
__pp_timeout_set(ppi, PP_TO_EXT_0,WR_RESP_CALIB_REQ_TIMEOUT_MS*(WR_STATE_RETRY+1));
pp_timeout_set_rename(ppi, wrTmoIdx,WR_RESP_CALIB_REQ_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_CALIBREQ");
enable = 1;
} else {
int rms=pp_next_delay_1(ppi, PP_TO_EXT_0);
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_RESP_CALIB_REQ_TIMEOUT_MS)) {
if (send_pattern)
WRH_OPER()->calib_pattern_disable(ppi);
......@@ -51,6 +51,6 @@ int wr_resp_calib_req(struct pp_instance *ppi, void *buf, int len)
}
}
ppi->next_delay = pp_next_delay_1(ppi,PP_TO_EXT_0)-wrp->wrStateRetry*WR_RESP_CALIB_REQ_TIMEOUT_MS;
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_RESP_CALIB_REQ_TIMEOUT_MS;
return e;
}
......@@ -16,10 +16,10 @@ int wr_s_lock(struct pp_instance *ppi, void *buf, int len)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
__pp_timeout_set(ppi, PP_TO_EXT_0, WR_S_LOCK_TIMEOUT_MS*(WR_STATE_RETRY+1));
pp_timeout_set_rename(ppi, wrTmoIdx, WR_S_LOCK_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_SLOCK");
enable = 1;
} else {
int rms=pp_next_delay_1(ppi, PP_TO_EXT_0);
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_S_LOCK_TIMEOUT_MS)) {
WRH_OPER()->locking_disable(ppi);
if (wr_handshake_retry(ppi))
......@@ -33,9 +33,9 @@ int wr_s_lock(struct pp_instance *ppi, void *buf, int len)
WRH_OPER()->locking_enable(ppi);
}
ppi->next_delay = pp_next_delay_1(ppi,PP_TO_EXT_0)-wrp->wrStateRetry*WR_S_LOCK_TIMEOUT_MS;
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_S_LOCK_TIMEOUT_MS;
poll_ret = WRH_OPER()->locking_poll(ppi, 0);
poll_ret = WRH_OPER()->locking_poll(ppi);
if (poll_ret == WRH_SPLL_READY) {
ppi->next_state = WRS_LOCKED;
WRH_OPER()->locking_disable(ppi);
......@@ -46,7 +46,7 @@ int wr_s_lock(struct pp_instance *ppi, void *buf, int len)
}
/* Calibration can take time so we restart the BMC timer to avoid aged foreign master removed. */
pp_timeout_set(ppi, PP_TO_BMC);
pp_gtimeout_reset(GLBS(ppi), PP_TO_BMC);
return 0;
}
......@@ -9,14 +9,7 @@
#ifndef __WREXT_WR_API_H__
#define __WREXT_WR_API_H__
#if CONFIG_EXT_WR == 1
#define PROTO_EXT_WR (1)
#else
#define PROTO_EXT_WR (0)
#endif
#if CONFIG_EXT_WR == 1
#if CONFIG_HAS_EXT_WR
/* Don't include the Following when this file is included in assembler. */
#ifndef __ASSEMBLY__
......@@ -151,7 +144,9 @@ struct wr_data {
};
extern struct pp_ext_hooks wr_ext_hooks;
extern int wrTmoIdx;
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_EXT_WR == 1*/
#endif /* __WREXT_WR_API_H__ */
......@@ -10,17 +10,6 @@ static int wr_e2e_offset(struct pp_instance *ppi,
static int wr_p2p_offset(struct pp_instance *ppi,
struct wr_servo_state *s, struct pp_time *offset_hw);
struct pp_time faulty_stamps[6]; /* if unused, dropped at link time */
static void apply_faulty_stamp(struct wr_servo_state *s, int index)
{
if (PROTO_EXT_HAS_FAULTS) {
assert(index >= 1 && index <= 6, "Wrong T index %i\n", index);
pp_time_add(&s->t1 + index - 1, faulty_stamps + index - 1);
}
}
/* Define threshold values for SNMP */
#define SNMP_MAX_OFFSET_PS 500
#define SNMP_MAX_DELTA_RTT_PS 1000
......@@ -117,9 +106,6 @@ int wr_servo_init(struct pp_instance *ppi)
/* Update scaledDelayCoefficient. Need conversion because they use two different fraction bits */
ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient= (int64_t)s->fiber_fix_alpha << (REL_DIFF_FRACBITS-FIX_ALPHA_FRACBITS);
WRH_OPER()->enable_timing_output(ppi, 0);
/*
* Do not reset cur_setpoint, but trim it to be less than one tick.
* The softpll code uses the module anyways, but if we unplug-replug
......@@ -155,8 +141,8 @@ int wr_servo_got_sync(struct pp_instance *ppi)
struct wr_servo_state *s =
&((struct wr_data *)ppi->ext_data)->servo_state;
s->t1 = ppi->t1; apply_faulty_stamp(s, 1);
s->t2 = ppi->t2; apply_faulty_stamp(s, 2);
s->t1 = ppi->t1; apply_faulty_stamp(ppi, 1);
s->t2 = ppi->t2; apply_faulty_stamp(ppi, 2);
got_sync = 1;
return 0;
}
......@@ -168,12 +154,12 @@ int wr_servo_got_delay(struct pp_instance *ppi)
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
s->t3 = ppi->t3; apply_faulty_stamp(s, 3);
s->t4 = ppi->t4; apply_faulty_stamp(s, 4);
s->t3 = ppi->t3; apply_faulty_stamp(ppi, 3);
s->t4 = ppi->t4; apply_faulty_stamp(ppi, 4);
if (CONFIG_HAS_P2P && ppi->delayMechanism == P2P) {
s->t5 = ppi->t5; apply_faulty_stamp(s, 5);
s->t6 = ppi->t6; apply_faulty_stamp(s, 6);
s->t5 = ppi->t5; apply_faulty_stamp(ppi, 5);
s->t6 = ppi->t6; apply_faulty_stamp(ppi, 6);
wr_p2p_delay(ppi, s);
}
......@@ -377,11 +363,10 @@ int wr_servo_update(struct pp_instance *ppi)
(long)offset.secs, (long)offset_ticks,
(long)offset_ps,s->clock_period_ps);
locking_poll_ret = WRH_OPER()->locking_poll(ppi, 0);
locking_poll_ret = WRH_OPER()->locking_poll(ppi);
if (locking_poll_ret != WRH_SPLL_READY
&& locking_poll_ret != WRH_SPLL_CALIB_NOT_READY) {
pp_diag(ppi, servo, 1, "PLL OutOfLock, should restart sync\n");
WRH_OPER()->enable_timing_output(ppi, 0);
/* TODO check
* DSPOR(ppi)->doRestart = TRUE; */
}
......@@ -441,7 +426,7 @@ int wr_servo_update(struct pp_instance *ppi)
SRV(ppi)->flags |= PP_SERVO_FLAG_WAIT_HW;
SRV(ppi)->state = WR_WAIT_OFFSET_STABLE;
if (ARCH_IS_WRS) {
if (CONFIG_ARCH_IS_WRS) {
/*
* Now, let's fix system time. We pass here
* once only, so that's the best place to do
......@@ -459,7 +444,7 @@ int wr_servo_update(struct pp_instance *ppi)
remaining_offset_ps = abs(offset_ps);
if(remaining_offset_ps < WRH_SERVO_OFFSET_STABILITY_THRESHOLD) {
WRH_OPER()->enable_timing_output(ppi, 1);
WRH_OPER()->enable_timing_output(GLBS(ppi),1);
s->prev_delayMS_ps = s->delayMS_ps;
SRV(ppi)->state = WR_TRACK_PHASE;
} else {
......
This diff is collapsed.
......@@ -20,7 +20,7 @@ static int presp_call_servo(struct pp_instance *ppi)
if (is_incorrect(&ppi->t4))
return 0; /* not an error, just no data */
pp_timeout_set(ppi, PP_TO_FAULT);
pp_timeout_reset(ppi, PP_TO_FAULT);
if (is_ext_hook_available(ppi,handle_presp))
ret = ppi->ext_hooks->handle_presp(ppi);
else {
......@@ -64,7 +64,7 @@ int st_com_peer_handle_pres(struct pp_instance *ppi, void *buf,
/* Clause 11.4.3.C.1 When multiple Pdelay_Resp messages are received, PTP Instance-A shall ..
* enter the FAULTY state ...
*/
if ( !DSDEF(ppi)->externalPortConfigurationEnabled ) {
if ( !is_externalPortConfigurationEnabled(DSDEF(ppi)) ) {
ppi->next_state = PPS_FAULTY;
return 0;
} else {
......@@ -124,7 +124,7 @@ int st_com_peer_handle_pres_followup(struct pp_instance *ppi,
/* Clause 11.4.3.C.1 When multiple Pdelay_Resp messages are received, PTP Instance-A shall ..
* enter the FAULTY state ...
*/
if ( !DSDEF(ppi)->externalPortConfigurationEnabled ) {
if ( !is_externalPortConfigurationEnabled(DSDEF(ppi)) ) {
ppi->next_state = PPS_FAULTY;
return 0;
} else {
......
......@@ -35,10 +35,10 @@ void pp_prepare_pointers(struct pp_instance *ppi)
case PPSI_PROTO_RAW:
ppi->tx_offset = ETH_HLEN; /* 14, I know! */
ppi->rx_offset = ETH_HLEN;
#ifdef CONFIG_ARCH_WRPC
ppi->tx_offset = 0; /* Currently, wrpc has a separate header */
ppi->rx_offset = 0;
#endif
if ( CONFIG_ARCH_IS_WRPC ) {
ppi->tx_offset = 0; /* Currently, wrpc has a separate header */
ppi->rx_offset = 0;
}
break;
case PPSI_PROTO_VLAN:
ppi->tx_offset = sizeof(struct pp_vlanhdr);
......@@ -67,13 +67,9 @@ void pp_prepare_pointers(struct pp_instance *ppi)
static int is_grand_master(struct pp_instance *ppi) {
int has_slave= 0;
int has_master=0;
int i=0;
int i;
#if CODEOPT_ONE_PORT()
{
#else
for (; i < DSDEF(ppi)->numberPorts; i++) {
#endif
for (i=0; i < get_numberPorts(DSDEF(ppi)); i++) {
switch (INST(GLBS(ppi), i)->state) {
case PPS_UNCALIBRATED:
case PPS_SLAVE:
......@@ -92,15 +88,15 @@ int st_com_check_announce_receive_timeout(struct pp_instance *ppi)
{
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)) {
/* 9.2.6.11 b) reset timeout when an announce timeout happened */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
pp_timeout_reset(ppi, PP_TO_ANN_RECEIPT);
if ( !DSDEF(ppi)->slaveOnly ) {
if ( !is_slaveOnly(DSDEF(ppi)) ) {
if ( is_grand_master(ppi) ) {
bmc_m1(ppi);
} else {
bmc_m3(ppi);
}
if ( DSDEF(ppi)->externalPortConfigurationEnabled ) {
if ( is_externalPortConfigurationEnabled(DSDEF(ppi)) ) {
/* Clause 17.6.5.3 : The announce receipt timeout mechanism shall not be active */
return 0;
}
......@@ -115,13 +111,6 @@ int st_com_check_announce_receive_timeout(struct pp_instance *ppi)
int st_com_handle_announce(struct pp_instance *ppi, void *buf, int len)
{
/* Clause 9.2.2.2 MasterOnly PTP ports :
* Announce messages received on a masterOnly PTP Port shall not be considered
* in the operation of the best master clock algorithm or in the update of data sets.
*/
if ( ! DSPOR(ppi)->masterOnly ) {
bmc_add_frgn_master(ppi, buf, len);
}
if (is_ext_hook_available(ppi,handle_announce))
return ppi->ext_hooks->handle_announce(ppi);
return 0;
......
......@@ -70,7 +70,7 @@ int pp_lib_may_issue_sync(struct pp_instance *ppi)
if (!pp_timeout(ppi, PP_TO_SYNC_SEND))
return 0;
pp_timeout_set(ppi, PP_TO_SYNC_SEND);
pp_timeout_reset(ppi, PP_TO_SYNC_SEND);
e = pp_vlan_issue_sync_followup(ppi);
if (e)
pp_diag(ppi, frames, 1, "could not send sync\n");
......@@ -87,7 +87,7 @@ int pp_lib_may_issue_announce(struct pp_instance *ppi)
if (!pp_timeout(ppi, PP_TO_ANN_SEND))
return 0;
pp_timeout_set(ppi, PP_TO_ANN_SEND);
pp_timeout_reset(ppi, PP_TO_ANN_SEND);
/* this check has to be done here since the
* update of the properties might have not
......@@ -130,7 +130,7 @@ int pp_lib_may_issue_request(struct pp_instance *ppi)
if (!pp_timeout(ppi, PP_TO_REQUEST))
return 0;
pp_timeout_set(ppi, PP_TO_REQUEST);
pp_timeout_reset(ppi, PP_TO_REQUEST);
e = msg_issue_request(ppi); /* FIXME: what about multiple vlans? */
ppi->t3 = ppi->last_snt_time;
if (e == PP_SEND_ERROR) {
......
#include <ppsi/ppsi.h>
/* proto-standard offers all-null hooks as a default extension */
struct pp_ext_hooks pp_hooks;
/* proto-standard hooks */
static void state_change(struct pp_instance *ppi) {
if ( ppi->state==PPS_SLAVE && ppi->next_state!=PPS_UNCALIBRATED ) {
/* Leave SLAVE state : We must stop the timing output generation */
WRH_OPER()->enable_timing_output(GLBS(ppi),0);
}
}
struct pp_ext_hooks pp_hooks={
.state_change = state_change
};
......@@ -26,6 +26,11 @@ struct pp_runtime_opts __pp_default_rt_opts = {
.domainNumber = PP_DEFAULT_DOMAIN_NUMBER,
.ttl = PP_DEFAULT_TTL,
.externalPortConfigurationEnabled = PP_DEFAULT_EXT_PORT_CONFIG_ENABLE,
.ptpPpsThresholdMs=PP_DEFAULT_PTP_PPSGEN_THRESHOLD_MS,
.gmDelayToGenPpsSec=PP_DEFAULT_GM_DELAY_TO_GEN_PPS_SEC,
.forcePpsGen= FALSE,
.ptpFallbackPpsGen=FALSE,
};
/* Default values used to fill configurable parameters associated to each instance */
......@@ -38,7 +43,7 @@ struct pp_instance_cfg __pp_default_instance_cfg = {
.sync_interval=PP_DEFAULT_SYNC_INTERVAL,
.min_delay_req_interval=PP_DEFAULT_MIN_DELAY_REQ_INTERVAL,
.min_pdelay_req_interval=PP_DEFAULT_MIN_PDELAY_REQ_INTERVAL,
#if CONFIG_EXT_L1SYNC == 1
#if CONFIG_HAS_EXT_L1SYNC
.l1SyncEnabled=FALSE,
.l1SyncRxCoherencyIsRequired=FALSE,
.l1SyncTxCoherencyIsRequired=FALSE,
......@@ -71,12 +76,13 @@ int pp_init_globals(struct pp_globals *ppg, struct pp_runtime_opts *pp_rt_opts)
*/
int i,ret=0;
defaultDS_t *def = ppg->defaultDS;
struct pp_runtime_opts *rt_opts;
def->twoStepFlag = TRUE;
/* if ppg->nlinks == 0, let's assume that the 'pp_links style'
* configuration was not used, so we have 1 port */
def->numberPorts = ppg->nlinks > 0 ? ppg->nlinks : 1;
struct pp_runtime_opts *rt_opts;
if (!ppg->rt_opts)
ppg->rt_opts = pp_rt_opts;
......@@ -91,21 +97,21 @@ int pp_init_globals(struct pp_globals *ppg, struct pp_runtime_opts *pp_rt_opts)
*/
def->externalPortConfigurationEnabled=pp_rt_opts->externalPortConfigurationEnabled;
def->slaveOnly=rt_opts->slaveOnly;
if ( def->slaveOnly && def->externalPortConfigurationEnabled ) {
if ( is_slaveOnly(def) && is_externalPortConfigurationEnabled(def) ) {
pp_printf("ppsi: Incompatible configuration: SlaveOnly and externalPortConfigurationEnabled\n");
def->slaveOnly=FALSE;
}
if ( def->slaveOnly ) {
if ( def->numberPorts > 1 ) {
if ( is_slaveOnly(def) ) {
if ( get_numberPorts(def) > 1 ) {
/* Check if slaveOnly is allowed
* Only one ppsi instance must exist however n instances on the same physical port
* and using the same protocol must be considered as one. We do this because these
* instances are exclusive and will be never enabled at the same time
*/
struct pp_instance *ppi = INST(ppg, 0);
for (i = 1; i < def->numberPorts; i++) {
for (i = 1; i < get_numberPorts(def); i++) {
struct pp_instance *ppi_cmp = INST(ppg, i);
if ( ppi->proto != ppi_cmp->proto /* different protocol used */
|| strcmp(ppi->cfg.iface_name,ppi_cmp->cfg.iface_name)!=0 /* Not the same interface */
......@@ -117,32 +123,35 @@ int pp_init_globals(struct pp_globals *ppg, struct pp_runtime_opts *pp_rt_opts)
}
}
}
if ( def->slaveOnly ) {
def->clockQuality.clockClass = PP_CLASS_SLAVE_ONLY;
if ( is_slaveOnly(def) ) {
/* Configured clockClass must be also changed to avoid to be set by BMCA bmc_update_clock_quality() */
rt_opts->clock_quality.clockClass =
def->clockQuality.clockClass = PP_CLASS_SLAVE_ONLY;
pp_printf("Slave Only, clock class set to %d\n", def->clockQuality.clockClass);
}
}
if ( def->numberPorts > 1) {
/* slaveOnly can be applied only on a ordinary clock */
}
def->priority1 = rt_opts->priority1;
def->priority2 = rt_opts->priority2;
def->domainNumber = rt_opts->domainNumber;
for (i = 0; i < def->numberPorts; i++) {
for (i = 0; i < get_numberPorts(def); i++) {
struct pp_instance *ppi = INST(ppg, i);
ppi->state = PPS_INITIALIZING;
ppi->current_state_item = NULL;
ppi->port_idx = i;
ppi->frgn_rec_best = -1;
pp_timeout_disable_all(ppi); /* By default, disable all timers */
}
if ( ppg->defaultDS->externalPortConfigurationEnabled ) {
for (i = 0; i < def->numberPorts; i++) {
if ( is_externalPortConfigurationEnabled(GDSDEF(ppg)) ) {
Boolean isSlavePresent=FALSE;
for (i = 0; i < get_numberPorts(def); i++) {
struct pp_instance *ppi = INST(ppg, i);
Enumeration8 desiradedState=ppi->cfg.desiredState;
/* Clause 17.6.5.3 : - Clause 9.2.2 shall not be in effect */
if ( ppi->portDS->masterOnly ) {
......@@ -150,11 +159,19 @@ int pp_init_globals(struct pp_globals *ppg, struct pp_runtime_opts *pp_rt_opts)
ppi->portDS->masterOnly=FALSE;
pp_printf("ppsi: Wrong configuration: externalPortConfigurationEnabled=materOnly=TRUE. materOnly set to FALSE\n");
}
ppi->externalPortConfigurationPortDS.desiredState =ppi->cfg.desiredState ;
ppi->externalPortConfigurationPortDS.desiredState =desiradedState ;
isSlavePresent|=desiradedState==PPS_SLAVE || desiradedState==PPS_UNCALIBRATED;
}
if ( def->clockQuality.clockClass < 128 && isSlavePresent) {
/* clockClass cannot be < 128 if a port is configured as slave */
/* Configured clockClass must be also changed to avoid to be set by BMCA bmc_update_clock_quality() */
rt_opts->clock_quality.clockClass =
def->clockQuality.clockClass=PP_CLASS_DEFAULT;
pp_printf("PPSi: GM clock set but slave present. Clock class set to %d\n", def->clockQuality.clockClass);
}
}
for (i = 0; i < def->numberPorts; i++) {
for (i = 0; i < get_numberPorts(def); i++) {
struct pp_instance *ppi = INST(ppg, i);
int r;
......@@ -170,7 +187,7 @@ int pp_close_globals(struct pp_globals *ppg)
int i,ret=0;;
defaultDS_t *def = ppg->defaultDS;
for (i = 0; i < def->numberPorts; i++) {
for (i = 0; i < get_numberPorts(def); i++) {
struct pp_instance *ppi = INST(ppg, i);
int r;
......
......@@ -10,7 +10,6 @@
#include "../proto-standard/common-fun.h"
#ifdef CONFIG_ARCH_WRS
#include <libwr/shmem.h>
#define shmem_lock() wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
#define shmem_unlock() wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
......@@ -27,14 +26,6 @@ static int64_t pp_servo_pi_controller(struct pp_instance *, struct pp_time *);
static void _pp_servo_init(struct pp_instance *ppi);
static void __pp_servo_update(struct pp_instance *ppi);
void pp_servo_apply_faulty_stamp(struct pp_servo *s, struct pp_time *faulty_stamps, int index)
{
if (PROTO_EXT_HAS_FAULTS) {
assert(index >= 1 && index <= 6, "Wrong T index %i\n", index);
pp_time_add(&s->t1 + index - 1, faulty_stamps + index - 1);
}
}
void pp_servo_init(struct pp_instance *ppi)
{
shmem_lock(); /* Share memory locked */
......@@ -66,7 +57,7 @@ static void _pp_servo_init(struct pp_instance *ppi)
servo->flags |= PP_SERVO_FLAG_VALID;
pp_timeout_set(ppi, PP_TO_FAULT);
pp_timeout_reset(ppi, PP_TO_FAULT);
pp_diag(ppi, servo, 1, "Initialized: obs_drift %lli\n",
servo->obs_drift);
}
......@@ -228,9 +219,30 @@ int pp_servo_calculate_delays(struct pp_instance *ppi) {
return 1;
}
static void control_timing_output(struct pp_instance *ppi) {
int offsetFromMasterUs=(int)(pp_time_to_picos(&SRV(ppi)->offsetFromMaster)/(int64_t)1000000);
int ptpPpsThresholdUs=OPTS(ppi)->ptpPpsThresholdMs*1000;
/* activate timing output if abs(offsetFromMasterMs)<ptpPpsThreshold */
if ( offsetFromMasterUs<0)
offsetFromMasterUs=-offsetFromMasterUs;
if ( offsetFromMasterUs<=ptpPpsThresholdUs ) {
WRH_OPER()->enable_timing_output(GLBS(ppi),1);
} else {
if ( !OPTS(ppi)->forcePpsGen ) { /* if timing output forced, never stop it */
/* disable only if abs(offsetFromMasterMs)>ptpPpsThresholdMs+20% */
ptpPpsThresholdUs+=ptpPpsThresholdUs/5;
if ( offsetFromMasterUs>ptpPpsThresholdUs ) {
WRH_OPER()->enable_timing_output(GLBS(ppi),0);
}
}
}
}
/* Called by slave and uncalib when we have t1 and t2 */
/* t1 & t2 are already checked and they are correct */
void pp_servo_got_sync(struct pp_instance *ppi)
void pp_servo_got_sync(struct pp_instance *ppi, int allowTimingOutput)
{
struct pp_servo *servo=SRV(ppi);
......@@ -242,6 +254,9 @@ void pp_servo_got_sync(struct pp_instance *ppi)
/* P2P mechanism */
servo->got_sync=0;
__pp_servo_update(ppi);
if (allowTimingOutput ) {
control_timing_output(ppi);
}
} else
servo->got_sync=1;
......@@ -249,7 +264,7 @@ void pp_servo_got_sync(struct pp_instance *ppi)
}
/* called by slave states when delay_resp is received (all t1..t4 are valid) */
int pp_servo_got_resp(struct pp_instance *ppi)
int pp_servo_got_resp(struct pp_instance *ppi, int allowTimingOutput)
{
struct pp_servo *servo=SRV(ppi);
static int errcount=0;
......@@ -272,6 +287,10 @@ int pp_servo_got_resp(struct pp_instance *ppi)
__pp_servo_update(ppi);
shmem_unlock(); /* Share memory locked */
if (allowTimingOutput)
control_timing_output(ppi);
return 1;
}
......@@ -419,11 +438,6 @@ static int pp_servo_offset_master(struct pp_instance *ppi, struct pp_time *ofm)
_pp_servo_init(ppi);
if (ARCH_IS_WRS) {
/* Enable PPS output */
WRH_OPER()->enable_timing_output(ppi, 1);
}
return 1; /* done */
}
......
......@@ -8,6 +8,8 @@
#include <ppsi/ppsi.h>
#define TIMEOUT_FAULTY_STATE_MS (60*1000) /* define the time to stay on faulty state before to go to initializing state */
/*
* Fault troubleshooting. Now only comes back to
* PTP_INITIALIZING state after a grace period.
......@@ -15,10 +17,36 @@
int pp_faulty(struct pp_instance *ppi, void *buf, int len)
{
if (pp_timeout(ppi, PP_TO_FAULT)) {
ppi->next_state = PPS_INITIALIZING;
return 0;
/* If the clockClass is < 128 and externalPortConfigurationEnabled is active,
* states SALVE and UNCALIBRATED are not allowed. We must stay in FAULTY state.
*/
if (is_externalPortConfigurationEnabled(DSDEF(ppi))) {
Enumeration8 desiredState=ppi->externalPortConfigurationPortDS.desiredState;
if ( DSDEF(ppi)->clockQuality.clockClass<128 &&
(desiredState == PPS_SLAVE || desiredState == PPS_UNCALIBRATED)
) {
/*
* We set the next delay to an arbitrary value (1s) as we should stay forever
* in this state.
*/
ppi->next_delay = 1000; /* 1s */
return 0;
}
}
ppi->next_delay = pp_next_delay_1(ppi, PP_TO_FAULT);
if ( ppi->is_new_state) {
pp_timeout_set(ppi,PP_TO_IN_STATE, TIMEOUT_FAULTY_STATE_MS);
} else {
/* Check if we can exit from FAULTY state */
if (pp_timeout(ppi, PP_TO_IN_STATE)) {
pp_timeout_disable(ppi,PP_TO_IN_STATE);
ppi->next_state = PPS_INITIALIZING;
return 0;
}
}
/* We stay on FAULTY state */
ppi->next_delay = pp_next_delay_1(ppi, PP_TO_IN_STATE);
return 0;
}
......@@ -13,6 +13,7 @@
*/
static void init_parent_ds(struct pp_instance *ppi)
{
/* 8.2.3.2 */
DSPAR(ppi)->parentPortIdentity.clockIdentity =
DSDEF(ppi)->clockIdentity;
......@@ -38,22 +39,39 @@ static void init_parent_ds(struct pp_instance *ppi)
int pp_initializing(struct pp_instance *ppi, void *buf, int len)
{
unsigned char *mac;
unsigned char mac_port1[6];
portDS_t *port = DSPOR(ppi);
struct pp_globals *ppg = GLBS(ppi);
int ret = 0;
int i;
unsigned int portidx;
unsigned int remainder;
int initds = 1;
if ( ppg->waitGmLocking ) {
/* Waithing for GM locking */
if ( ppi->is_new_state ) {
/* Init time-out for next calls : Wait 2 x the BMCA tmo */
pp_timeout_set(ppi,PP_TO_IN_STATE,TMO_DEFAULT_BMCA_MS<<1);
}else {
if ( pp_timeout(ppi,PP_TO_IN_STATE)) {
/* At this point, the BMCA already run. We can check the clockClass */
if ( DSDEF(ppi)->clockQuality.clockClass == PP_PTP_CLASS_GM_LOCKED) {
ppg->waitGmLocking=0; /* The clock is locked now */
pp_timeout_disable(ppi,PP_TO_IN_STATE);
}
else {
pp_timeout_reset(ppi,PP_TO_IN_STATE);
goto failure;
}
} else
goto failure;
}
}
if (ppi->n_ops->init(ppi) < 0) /* it must handle being called twice */
goto failure;
/* only fill in the data set when initializing */
if (!CODEOPT_ONE_PORT() && DSDEF(ppi)->numberPorts > 1) {
for (i = 0; i < ppg->defaultDS->numberPorts; i++) {
if ( get_numberPorts(GDSDEF(ppg)) > 1) {
for (i = 0; i < get_numberPorts(GDSDEF(ppg)); i++) {
if ((INST(ppg, i)->state != PPS_INITIALIZING) && (INST(ppg, i)->link_up == TRUE))
initds = 0;
}
......@@ -64,28 +82,35 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
*/
if (initds)
{
if (!CODEOPT_ONE_PORT() && DSDEF(ppi)->numberPorts > 1) {
unsigned char mac_port1[PP_MAC_ADRESS_SIZE];
unsigned char *mac;
unsigned char *pci;
if (get_numberPorts(GDSDEF(ppg)) > 1) {
/* Clock identity comes from mac address with 0xff:0xfe intermixed */
mac = ppi->ch[PP_NP_GEN].addr;
/* calculate MAC of Port 0 */
portidx = ppi - ppi->glbs->pp_instances;
remainder = portidx;
for (i = 5; i >= 0; i--) {
mac_port1[i] = mac[i] - remainder;
if (mac[i] >= remainder)
remainder = 0;
else
remainder = 1;
unsigned char portIdx;
if ( (portIdx = ppi - ppi->glbs->pp_instances) > 0 ) {
unsigned char *mac = ppi->ch[PP_NP_GEN].addr;
unsigned char remainder = portIdx;
for (i = sizeof(mac_port1)-1; i >= 0; i--) {
mac_port1[i] = mac[i] - remainder;
if (mac[i] >= remainder)
remainder = 0;
else
remainder = 1;
}
}
} else {
/* Clock identity comes from mac address with 0xff:0xfe intermixed */
for (i = 5; i >= 0; i--)
mac_port1[i] = ((unsigned char*)ppi->ch[PP_NP_GEN].addr)[i];
memcpy (mac_port1,ppi->ch[PP_NP_GEN].addr,sizeof(mac_port1));
}
memcpy( DSDEF(ppi)->clockIdentity.id, mac_port1, PP_CLOCK_IDENTITY_LENGTH);
DSDEF(ppi)->clockIdentity.id[3] = 0xff;
DSDEF(ppi)->clockIdentity.id[4] = 0xfe;
pci=DSDEF(ppi)->clockIdentity.id;
mac=mac_port1;
*(pci++)=*(mac++);*(pci++)=*(mac++); *(pci++)=*(mac++);
*(pci++)= 0xff;
*(pci++)= 0xfe;
*(pci++)=*(mac++); *(pci++)=*(mac++); *pci=*mac;
init_parent_ds(ppi);
}
......@@ -99,9 +124,15 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
port->portIdentity.portNumber = 1 + ppi - ppi->glbs->pp_instances;
port->versionNumber = PP_VERSION_PTP;
port->minorVersionNumber = PP_MINOR_VERSION_PTP;
/* Init timers */
ppi->portDS->logAnnounceInterval=(Integer8)ppi->cfg.announce_interval;
ppi->portDS->announceReceiptTimeout=(UInteger8)ppi->cfg.announce_receipt_timeout;
ppi->portDS->logSyncInterval=(Integer8)ppi->cfg.sync_interval;
ppi->portDS->logMinDelayReqInterval=(Integer8)ppi->cfg.min_delay_req_interval;
ppi->portDS->logMinPdelayReqInterval=(Integer8)ppi->cfg.min_pdelay_req_interval;
pp_timeout_init(ppi);
pp_timeout_setall(ppi);/* PP_TO_BMC is not set by default */
pp_timeout_set(ppi, PP_TO_BMC);
pp_timeout_setall(ppi);
ppi->link_state=PP_LSTATE_PROTOCOL_DETECTION;
ppi->ptp_msg_received=FALSE;
......@@ -121,14 +152,29 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
msg_init_header(ppi, ppi->tx_ptp); /* This is used for all tx */
if (DSDEF(ppi)->externalPortConfigurationEnabled) {
if ( ppg->waitGmLocking ) {
/* must leave the BMC running before to check next time the clockClass */
ppi->next_delay = pp_gtimeout_get(ppg,PP_TO_BMC) << 1; /* wait 2 x BMCA tmo */
return 0;
}
if (is_externalPortConfigurationEnabled(DSDEF(ppi))) {
/* Clause 17.6.5.2 : the member portDS.portState shall be set to
* the value of the member externalPortConfigurationPortDS.desiredState
*/
if ( ppi->externalPortConfigurationPortDS.desiredState==PPS_SLAVE)
ppi->next_state=PPS_UNCALIBRATED;
else
ppi->next_state = ppi->externalPortConfigurationPortDS.desiredState;
Enumeration8 desiredState=ppi->externalPortConfigurationPortDS.desiredState;
if ( DSDEF(ppi)->clockQuality.clockClass<128 &&
(desiredState == PPS_SLAVE || desiredState == PPS_UNCALIBRATED)
) {
ppi->next_state=PPS_FAULTY;
} else {
if ( ppi->externalPortConfigurationPortDS.desiredState==PPS_SLAVE) {
ppi->next_state=PPS_UNCALIBRATED;
}
else
ppi->next_state = ppi->externalPortConfigurationPortDS.desiredState;
}
}
else
ppi->next_state = PPS_LISTENING;
......
......@@ -9,6 +9,9 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
static int listening_handle_announce(struct pp_instance *ppi, void *buf, int len);
static pp_action *actions[] = {
[PPM_SYNC] = 0,
[PPM_DELAY_REQ] = 0,
......@@ -19,16 +22,36 @@ static pp_action *actions[] = {
#endif
[PPM_FOLLOW_UP] = 0,
[PPM_DELAY_RESP] = 0,
[PPM_ANNOUNCE] = st_com_handle_announce,
[PPM_ANNOUNCE] = listening_handle_announce,
[PPM_SIGNALING] = st_com_handle_signaling,
};
static int listening_handle_announce(struct pp_instance *ppi, void *buf, int len) {
int ret;
if ((ret = st_com_handle_announce(ppi, buf, len))!=0)
return ret;
/* Clause 9.2.2.2 MasterOnly PTP ports :
* Announce messages received on a masterOnly PTP Port shall not be considered
* in the operation of the best master clock algorithm or in the update of data sets.
*/
if ( ! DSPOR(ppi)->masterOnly) {
struct pp_frgn_master frgn_master;
bmc_store_frgn_master(ppi, &frgn_master, buf, len);
bmc_add_frgn_master(ppi, &frgn_master);
}
return 0;
}
int pp_listening(struct pp_instance *ppi, void *buf, int len)
{
int e = 0; /* error var, to check errors in msg handling */
MsgHeader *hdr = &ppi->received_ptp_header;
pp_timeout_set(ppi, PP_TO_FAULT); /* no fault as long as we listen */
pp_timeout_reset(ppi, PP_TO_FAULT); /* no fault as long as we listen */
if (is_ext_hook_available(ppi,listening))
e = ppi->ext_hooks->listening(ppi, buf, len);
if (e)
......
......@@ -11,6 +11,7 @@
static int master_handle_delay_request(struct pp_instance *ppi,
void *buf, int len);
static int master_handle_announce(struct pp_instance *ppi, void *buf, int len);
static pp_action *actions[] = {
[PPM_SYNC] = 0,
......@@ -22,11 +23,32 @@ static pp_action *actions[] = {
#endif
[PPM_FOLLOW_UP] = 0,
[PPM_DELAY_RESP] = 0,
[PPM_ANNOUNCE] = st_com_handle_announce,
[PPM_ANNOUNCE] = master_handle_announce,
[PPM_SIGNALING] = st_com_handle_signaling,
/* skip management, for binary size */
};
static int master_handle_announce(struct pp_instance *ppi, void *buf, int len)
{
int ret = 0;
ret = st_com_handle_announce(ppi, buf, len);
if (ret)
return ret;
/* Clause 9.2.2.2 MasterOnly PTP ports :
* Announce messages received on a masterOnly PTP Port shall not be considered
* in the operation of the best master clock algorithm or in the update of data sets.
*/
if ( ! DSPOR(ppi)->masterOnly) {
struct pp_frgn_master frgn_master;
bmc_store_frgn_master(ppi, &frgn_master, buf, len);
bmc_add_frgn_master(ppi, &frgn_master);
}
return 0;
}
static int master_handle_delay_request(struct pp_instance *ppi,
void *buf, int len)
{
......@@ -47,17 +69,17 @@ int pp_master(struct pp_instance *ppi, void *buf, int len)
int pre = (ppi->state == PPS_PRE_MASTER);
int e = 0; /* error var, to check errors in msg handling */
pp_timeout_set(ppi, PP_TO_FAULT); /* no fault as long as we are
* master */
/* no fault as long as we are master */
pp_timeout_reset(ppi, PP_TO_FAULT);
/* upgrade from pre-master to master */
if (pre &&
pp_timeout(ppi, PP_TO_QUALIFICATION) &&
!DSDEF(ppi)->externalPortConfigurationEnabled) {
!is_externalPortConfigurationEnabled(DSDEF(ppi))) {
ppi->next_state = PPS_MASTER;
/* start sending immediately and reenter */
pp_timeout_clear(ppi, PP_TO_SYNC_SEND);
pp_timeout_clear(ppi, PP_TO_ANN_SEND);
pp_timeout_reset_N(ppi, PP_TO_SYNC_SEND,0);
pp_timeout_reset_N(ppi, PP_TO_ANN_SEND,0);
ppi->next_delay = 0;
return 0;
}
......@@ -109,7 +131,7 @@ out:
switch(e) {
case PP_SEND_OK: /* 0 */
/* Why should we switch to slave? Remove this code? */
if (DSDEF(ppi)->slaveOnly)
if (is_slaveOnly(DSDEF(ppi)))
ppi->next_state = PPS_LISTENING;
break;
case PP_SEND_ERROR:
......
......@@ -35,13 +35,24 @@ static int passive_handle_announce(struct pp_instance *ppi, void *buf, int len)
if (ret)
return ret;
/* Clause 9.2.2.2 MasterOnly PTP ports :
* Announce messages received on a masterOnly PTP Port shall not be considered
* in the operation of the best master clock algorithm or in the update of data sets.
*/
if ( ! DSPOR(ppi)->masterOnly) {
struct pp_frgn_master frgn_master;
bmc_store_frgn_master(ppi, &frgn_master, buf, len);
bmc_add_frgn_master(ppi, &frgn_master);
}
if (erbest!=NULL && !bmc_pidcmp(&hdr->sourcePortIdentity,
&erbest->sourcePortIdentity)) {
/*
* 9.2.6.11 d) reset timeout when an announce
* is received from the clock putting it into passive (erbest)
*/
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
pp_timeout_reset(ppi, PP_TO_ANN_RECEIPT);
}
return 0;
......@@ -52,7 +63,7 @@ int pp_passive(struct pp_instance *ppi, void *buf, int len)
int e = 0; /* error var, to check errors in msg handling */
MsgHeader *hdr = &ppi->received_ptp_header;
pp_timeout_set(ppi, PP_TO_FAULT); /* no fault as long as we are
pp_timeout_reset(ppi, PP_TO_FAULT); /* no fault as long as we are
* passive */
/* when the clock is using peer-delay, passive must send it too */
......
......@@ -40,15 +40,18 @@ static int slave_handle_sync(struct pp_instance *ppi, void *buf,
MsgHeader *hdr = &ppi->received_ptp_header;
MsgSync sync;
if (!msg_from_current_master(ppi))
if (!msg_from_current_master(ppi)) {
pp_error("%s: Sync message is not from current parent\n",
__func__);
return 0;
}
if ( ppi->delayMechanism==E2E && ppi->t1.scaled_nsecs==0 && ppi->t1.secs==0 ) {
/* First time we receive the SYNC message in uncalib/slave state
* We set the REQUEST time-out to the minDelayReqInterval/2 value (500ms)
* in order to provide quickly a DelayReq message
*/
__pp_timeout_set(ppi, PP_TO_REQUEST, (1000*(1<<PP_MIN_MIN_DELAY_REQ_INTERVAL))/2);
pp_timeout_set(ppi, PP_TO_REQUEST, (1000*(1<<PP_MIN_MIN_DELAY_REQ_INTERVAL))/2);
}
/* t2 may be overriden by follow-up, save it immediately */
ppi->t2 = ppi->last_rcv_time;
......@@ -77,7 +80,7 @@ static int slave_handle_sync(struct pp_instance *ppi, void *buf,
if (ret < 0)
return ret;
}
pp_servo_got_sync(ppi);
pp_servo_got_sync(ppi,1);
}
return 0;
}
......@@ -127,7 +130,7 @@ static int slave_handle_followup(struct pp_instance *ppi, void *buf,
return ret;
}
/* default servo action */
pp_servo_got_sync(ppi);
pp_servo_got_sync(ppi,0);
return 0;
}
......@@ -156,12 +159,12 @@ static int slave_handle_response(struct pp_instance *ppi, void *buf,
pp_time_add(&ppi->t4, &hdr->cField);
/* WARNING: should be "sub" (see README-cfield::BUG) */
pp_timeout_set(ppi, PP_TO_FAULT);
pp_timeout_reset(ppi, PP_TO_FAULT);
if (is_ext_hook_available(ppi,handle_resp)) {
ret=ppi->ext_hooks->handle_resp(ppi);
}
else {
if ( (ret=pp_servo_got_resp(ppi)) && !ppi->ext_enabled ) {
if ( (ret=pp_servo_got_resp(ppi,1)) && !ppi->ext_enabled ) {
ppi->link_state=PP_LSTATE_LINKED;
}
}
......@@ -178,23 +181,40 @@ static int slave_handle_response(struct pp_instance *ppi, void *buf,
static int slave_handle_announce(struct pp_instance *ppi, void *buf, int len)
{
int ret = 0;
int ret;
struct pp_frgn_master frgn_master;
ret = st_com_handle_announce(ppi, buf, len);
if (ret)
if ((ret = st_com_handle_announce(ppi, buf, len))!=0)
return ret;
/* If externalPortConfiguration option is set, we consider that all
* announce messages come from the current master.
*/
if (!DSDEF(ppi)->externalPortConfigurationEnabled && !msg_from_current_master(ppi))
return 0;
bmc_store_frgn_master(ppi, &frgn_master, buf, len);
if (!is_externalPortConfigurationEnabled(DSDEF(ppi)) ) {
if ( !msg_from_current_master(ppi) ) {
pp_error("%s: Announce message is not from current parent\n",
__func__);
/* Clause 9.2.2.2 MasterOnly PTP ports :
* Announce messages received on a masterOnly PTP Port shall not be considered
* in the operation of the best master clock algorithm or in the update of data sets.
*/
if ( ! DSPOR(ppi)->masterOnly) {
bmc_add_frgn_master(ppi, &frgn_master);
}
return 0;
}
}
/* Add foreign master: Figure 36 & 54 */
bmc_add_frgn_master(ppi, &frgn_master);
/* 9.2.6.11 a) reset timeout */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
pp_timeout_reset(ppi, PP_TO_ANN_RECEIPT);
/* 9.5.3 Figure 29 update data set if announce from current master */
bmc_store_frgn_master(ppi, &frgn_master, buf, len);
bmc_s1(ppi, &frgn_master);
return 0;
......@@ -239,7 +259,7 @@ int pp_slave(struct pp_instance *ppi, void *buf, int len)
ppi->next_state = PPS_UNCALIBRATED;
}
/* Force to stay on desired state if externalPortConfiguration option is enabled */
if (DSDEF(ppi)->externalPortConfigurationEnabled )
if (is_externalPortConfigurationEnabled(DSDEF(ppi)) )
ppi->next_state = ppi->externalPortConfigurationPortDS.desiredState;
/* when entering uncalibrated init servo */
......
......@@ -168,12 +168,6 @@ static int unix_time_set_utc_offset(struct pp_instance *ppi, int offset, int lea
return 0;
}
static int unix_time_get_servo_state(struct pp_instance *ppi, int *state)
{
*state = PP_SERVO_UNKNOWN;
return 0;
}
static int unix_time_get(struct pp_instance *ppi, struct pp_time *t)
{
struct timespec tp;
......@@ -290,7 +284,6 @@ struct pp_time_operations unix_time_ops = {
.get_utc_time = unix_time_get_utc_time,
.get_utc_offset = unix_time_get_utc_offset,
.set_utc_offset = unix_time_set_utc_offset,
.get_servo_state = unix_time_get_servo_state,
.get = unix_time_get,
.set = unix_time_set,
.adjust = unix_time_adjust,
......
......@@ -97,38 +97,117 @@ int wrs_enable_ptracker(struct pp_instance *ppi)
return WRH_SPLL_OK;
}
int wrs_enable_timing_output(struct pp_instance *ppi, int enable)
int wrs_enable_timing_output(struct pp_globals *ppg,int enable)
{
int ret, rval;
hexp_pps_params_t p;
static int ppsOutputOn=-1; /* -1 means we don't know the state */
if (enable == ppsOutputOn)
return WRH_SPLL_OK;
p.pps_valid = enable;
ret = minipc_call(hal_ch, DEFAULT_TO, &__rpcdef_pps_cmd,
&rval, HEXP_PPSG_CMD_SET_VALID, &p);
if ((ret < 0) || (rval < 0))
return WRH_SPLL_ERROR;
ppsOutputOn = enable;
return WRH_SPLL_OK;
}
int wrs_set_timing_mode(struct pp_globals * ppg,timing_mode_t tm)
{
int ret, rval;
hexp_pps_params_t p;
p.timing_mode = tm;
pp_diag(NULL, time, 1, "Set timing mode to %d\n",tm);
ret = minipc_call(hal_ch, DEFAULT_TO, &__rpcdef_pps_cmd,
&rval, HEXP_PPSG_CMD_SET_TIMING_MODE, &p);
if ((ret < 0) || (rval < 0))
return -1;
return 0;
}
#define TIMEOUT_REFRESH_GRAND_MASTER_MS 60000 /* 60s */
timing_mode_state_t wrs_get_timing_mode_state(struct pp_globals *ppg)
{
static int tmoIndex=0;
int ret, rval;
hexp_pps_params_t p;
ret = minipc_call(hal_ch, DEFAULT_TO, &__rpcdef_pps_cmd,
&rval, HEXP_PPSG_CMD_GET_TIMING_MODE_STATE, &p);
if ((ret < 0) || (rval < 0))
return -1;
if ( rval==PP_TIMING_MODE_STATE_UNLOCKED ) {
/*
* if the timing mode = GM then we need to reset the timing mode every 60s.
* This is an hack because the hardware need to be reinitialized after some time
* to be sure to be ready when the external clocks will be present.
*/
timing_mode_t timing_mode=wrs_get_timing_mode(ppg);
if ( timing_mode == TM_GRAND_MASTER){
if ( tmoIndex==0 ) {
/* First time. Timer must be initialized */
if ( (tmoIndex=pp_gtimeout_get_timer(ppg,"GM_REFRESH", TO_RAND_NONE,0))>0 )
pp_gtimeout_set(ppg,tmoIndex,TIMEOUT_REFRESH_GRAND_MASTER_MS);
}
if ( tmoIndex > 0 ) {
if ( pp_gtimeout(ppg,tmoIndex) ) {
wrs_set_timing_mode(ppg,TM_GRAND_MASTER);
pp_gtimeout_reset(ppg,tmoIndex);
pp_diag(NULL,time,3,"Refresh (hw) timing mode GM\n");
}
}
}
} else {
if (tmoIndex > 0 ) {
/* Free the timer: Next unlock state, we will wait then 60s again
* before to set again the Timing mode.
*/
pp_gtimeout_free_timer(ppg,tmoIndex);
tmoIndex=0;
}
}
return rval;
}
timing_mode_t wrs_get_timing_mode(struct pp_globals *ppg)
{
int ret, rval;
hexp_pps_params_t p;
ret = minipc_call(hal_ch, DEFAULT_TO, &__rpcdef_pps_cmd,
&rval, HEXP_PPSG_CMD_GET_TIMING_MODE, &p);
if (ret < 0)
return -1;
return rval;
}
int wrs_locking_disable(struct pp_instance *ppi)
{
return WRH_SPLL_OK;
pp_diag(ppi, time, 1, "Disable locking\n");
timing_mode_t tm=wrs_get_timing_mode(GLBS(ppi));
if ( tm==TM_BOUNDARY_CLOCK ) {
return wrs_set_timing_mode(GLBS(ppi),TM_FREE_MASTER);
}
return 0;
}
int wrs_locking_enable(struct pp_instance *ppi)
{
int ret, rval;
pp_diag(ppi, time, 1, "Start locking\n");
wrs_set_timing_mode(GLBS(ppi),TM_BOUNDARY_CLOCK);
pp_diag(ppi, time, 1, "Start locking\n");
ret = minipc_call(hal_ch, DEFAULT_TO, &__rpcdef_lock_cmd,
&rval, ppi->iface_name, HEXP_LOCK_CMD_START, 0);
......@@ -140,10 +219,14 @@ int wrs_locking_enable(struct pp_instance *ppi)
int wrs_locking_reset(struct pp_instance *ppi)
{
int ret, rval;
int ret=0, rval;
pp_diag(ppi, time, 1, "Reset locking\n");
if ( ppi->glbs->defaultDS->clockQuality.clockClass != PP_PTP_CLASS_GM_LOCKED )
if ( wrs_set_timing_mode(GLBS(ppi),TM_FREE_MASTER)<0 ) {
return -1;
}
ret = minipc_call(hal_ch, DEFAULT_TO, &__rpcdef_lock_cmd,
&rval, ppi->iface_name, HEXP_LOCK_CMD_RESET, 0);
......@@ -153,13 +236,10 @@ int wrs_locking_reset(struct pp_instance *ppi)
return WRH_SPLL_OK;
}
int wrs_locking_poll(struct pp_instance *ppi, int grandmaster)
int wrs_locking_poll(struct pp_instance *ppi)
{
int ret, rval;
if (grandmaster) /* FIXME: check wrs grandmaster PLL */
return WRH_SPLL_READY;
ret = minipc_call(hal_ch, DEFAULT_TO, &__rpcdef_lock_cmd,
&rval, ppi->iface_name, HEXP_LOCK_CMD_CHECK, 0);
if ( ret<0 ) {
......@@ -223,18 +303,6 @@ static int wrs_time_set_utc_offset(struct pp_instance *ppi, int offset, int leap
return unix_time_ops.set_utc_offset(ppi, offset, leap59, leap61);
}
static int wrs_time_get_servo_state(struct pp_instance *ppi, int *state)
{
int locked;
locked = WRH_OPER()->locking_poll(ppi, 1);
if (locked == WRH_SPLL_READY)
*state = PP_SERVO_LOCKED;
else
*state = PP_SERVO_UNLOCKED;
return 0;
}
/* This is only used when the wrs is slave to a non-WR master */
static int wrs_time_get(struct pp_instance *ppi, struct pp_time *t)
{
......@@ -408,11 +476,10 @@ struct pp_time_operations wrs_time_ops = {
.get_utc_time = wrs_time_get_utc_time,
.get_utc_offset = wrs_time_get_utc_offset,
.set_utc_offset = wrs_time_set_utc_offset,
.get_servo_state = wrs_time_get_servo_state,
.get = wrs_time_get,
.set = wrs_time_set,
.adjust = wrs_time_adjust,
.adjust_offset = wrs_time_adjust_offset,
.adjust_freq = wrs_time_adjust_freq,
.calc_timeout = wrs_calc_timeout,
.calc_timeout = wrs_calc_timeout
};
This diff is collapsed.
......@@ -12,7 +12,7 @@ OBJDUMP = $(CROSS_COMPILE)objdump
include ../.config
CFLAGS = -Wall -ggdb -I../include -I../arch-$(CONFIG_ARCH)/include
PROGS = ptpdump adjtime jmptime chktime adjrate
PROGS = ptpdump adjtime jmptime chktime adjrate monotonicClock
LDFLAGS += -lrt
all: $(PROGS)
......
This diff is collapsed.
This diff is collapsed.
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