Commit be8e0372 authored by Adam Wujek's avatar Adam Wujek 💬

Merge branch 'jcb-HA-implementation'

Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parents 2dc1b909 97d91967
......@@ -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,52 +127,69 @@ menu "PTP Protocol Options"
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.
menu "Enabled profiles"
config EXT_WR
bool
default y if ARCH_WRS || ARCH_WRPC
config PROFILE_WR
bool "WhiteRabbit"
default y if ARCH_WRS
config EXT_NONE
bool
default !EXT_WR
config PROFILE_HA
bool "HighAccuracy"
default y if ARCH_WRS || ARCH_WRPC
config EXTENSION
string
default "whiterabbit" if EXT_WR
default "" if EXT_NONE
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 PROFILE_CUSTOM
bool "Custom"
default y if ARCH_WRS
config ARCH_CFLAGS
string
default "-m32" if ARCH_BARE_I386
default "-m64" if ARCH_BARE_X86_64
default ""
endmenu
config ARCH_LDFLAGS
string
default "-m elf_i386" if ARCH_BARE_I386
default "-m elf_x86_64" if ARCH_BARE_X86_64
default ""
config PROFILE_PTP
bool
default y
config WRPCSW_ROOT
string "Source location of wrpc-sw"
depends on ARCH_WRPC
default "../wrpc-sw"
config HAS_EXT_WR
int
range 0 1
default 1 if PROFILE_WR
default 0
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 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
......@@ -182,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
......@@ -191,18 +233,238 @@ 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"
config OPTIMIZATION
int
default 0 if DISABLE_OPTIMIZATION
default 2
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).
If the code is optimized with externalPortConfiguration.enable forced to true,
the NR_FOREIGN_RECORDS should be set to 1
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 WRPC_FAULTS
bool "Add the fault injection mechanism and shell command for wrpc"
depends on ARCH_WRPC
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
string
default "-Os" if OPTIMIZATION_SIZE_SPEED && ARCH_WRPC
default "-Os -ggdb" if OPTIMIZATION_SIZE_SPEED
default "-O2" if OPTIMIZATION_SPEED && ARCH_WRPC
default "-O2 -ggdb" if OPTIMIZATION_SPEED
default "-Og -ggdb" if OPTIMIZATION_DEBUGGING
default "-ggdb" if OPTIMIZATION_NONE_DEBUGGING
default ""
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
......@@ -7,7 +7,7 @@
# We still accept command-line choices like we used to do.
# Also, we must remove the quotes from these Kconfig values
PROTO_EXT ?= $(patsubst "%",%,$(CONFIG_EXTENSION))
PROTO_EXTS ?= $(patsubst "%",%,$(CONFIG_EXTENSIONS))
ARCH ?= $(patsubst "%",%,$(CONFIG_ARCH))
CROSS_COMPILE ?= $(patsubst "%",%,$(CONFIG_CROSS_COMPILE))
WRPCSW_ROOT ?= $(patsubst "%",%,$(CONFIG_WRPCSW_ROOT))
......@@ -47,8 +47,13 @@ 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 += -O$(CONFIG_OPTIMIZATION)
CFLAGS += -ggdb -Iinclude -fno-common
CFLAGS += -ffunction-sections -fdata-sections
export CFLAGS_OPTIMIZATION:= ${shell echo $(CONFIG_OPTIMIZATION)}
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
......@@ -65,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
......@@ -73,9 +78,13 @@ CFLAGS += -Iarch-$(ARCH)/include
# proto-standard is always included, as it provides default function
# so the extension can avoid duplication of code.
ifneq ($(PROTO_EXT),)
include proto-ext-$(PROTO_EXT)/Makefile
ifeq ($(CONFIG_HAS_EXT_WR),1)
include proto-ext-whiterabbit/Makefile
endif
ifeq ($(CONFIG_HAS_EXT_L1SYNC),1)
include proto-ext-l1sync/Makefile
endif
include proto-ext-common/Makefile
include proto-standard/Makefile
# ...and the TIME choice sets the default operations
......@@ -94,7 +103,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)
......
......@@ -88,10 +88,10 @@ struct sim_ppi_arch_data {
/* Runtime options */
struct pp_runtime_opts *rt_opts;
/* Data sets */
DSDefault *defaultDS;
DSCurrent *currentDS;
DSParent *parentDS;
DSTimeProperties *timePropertiesDS;
defaultDS_t *defaultDS;
currentDS_t *currentDS;
[parentDS_t *parentDS;
timePropertiesDS_t *timePropertiesDS;
/* other pp_instance, used in net ops */
struct pp_instance *other_ppi;
};
......
......@@ -20,14 +20,16 @@ static struct pp_runtime_opts sim_master_rt_opts = {
.ap = PP_DEFAULT_AP,
.ai = PP_DEFAULT_AI,
.s = PP_DEFAULT_DELAY_S,
.announce_intvl = PP_DEFAULT_ANNOUNCE_INTERVAL,
.sync_intvl = PP_DEFAULT_SYNC_INTERVAL,
.prio1 = PP_DEFAULT_PRIORITY1,
.prio2 = PP_DEFAULT_PRIORITY2,
.domain_number = PP_DEFAULT_DOMAIN_NUMBER,
.logAnnounceInterval = PP_DEFAULT_ANNOUNCE_INTERVAL,
.logSyncInterval = PP_DEFAULT_SYNC_INTERVAL,
.priority1 = PP_DEFAULT_PRIORITY1,
.priority2 = PP_DEFAULT_PRIORITY2,
.domainNumber = PP_DEFAULT_DOMAIN_NUMBER,
.ttl = PP_DEFAULT_TTL,
};
extern struct pp_ext_hooks pp_hooks;
/*
* In arch-sim we use two pp_instaces in the same pp_globals to represent
* two different machines. This means *completely differnt* machines, with
......@@ -58,6 +60,7 @@ static int sim_ppi_init(struct pp_instance *ppi, int which_ppi)
ppi->__rx_buffer = malloc(PP_MAX_FRAME_LENGTH);
ppi->arch_data = calloc(1, sizeof(struct sim_ppi_arch_data));
ppi->portDS = calloc(1, sizeof(*ppi->portDS));
ppi->ext_hooks=&pp_hooks;
if ((!ppi->arch_data) || (!ppi->portDS))
return -1;
data = SIM_PPI_ARCH(ppi);
......@@ -139,7 +142,7 @@ int main(int argc, char **argv)
sim_set_global_DS(ppi);
ppi->iface_name = ppi->cfg.iface_name;
ppi->port_name = ppi->cfg.port_name;
ppi->mech = ppi->cfg.mech;
ppi->delayMechanism = ppi->cfg.delayMechanism;
if (ppi->proto == PPSI_PROTO_RAW)
pp_printf("Warning: simulator doesn't support raw "
"ethernet. Using UDP\n");
......
......@@ -25,12 +25,14 @@
/* ppg and fields */
static struct pp_globals ppg_static;
static DSDefault defaultDS;
static DSCurrent currentDS;
static DSParent parentDS;
static DSTimeProperties timePropertiesDS;
static defaultDS_t defaultDS;
static currentDS_t currentDS;
static [parentDS_t parentDS;
static timePropertiesDS_t timePropertiesDS;
static struct pp_servo servo;
extern struct pp_ext_hooks pp_hooks;
int main(int argc, char **argv)
{
struct pp_globals *ppg;
......@@ -66,7 +68,7 @@ int main(int argc, char **argv)
ppi = INST(ppg, i);
ppi->proto = PP_DEFAULT_PROTO;
ppi->role = PP_DEFAULT_ROLE;
ppi->mech = PP_E2E_MECH;
ppi->delayMechanism = E2E;
}
/* Set offset here, so config parsing can override it */
......@@ -92,7 +94,8 @@ int main(int argc, char **argv)
ppi->vlans_array_len = CONFIG_VLAN_ARRAY_SIZE,
ppi->iface_name = ppi->cfg.iface_name;
ppi->port_name = ppi->cfg.port_name;
ppi->mech = ppi->cfg.mech;
ppi->delayMechanism = ppi->cfg.delayMechanism;
ppi->ext_hooks= &pp_hooks;
/* The following default names depend on TIME= at build time */
ppi->n_ops = &DEFAULT_NET_OPS;
......
......@@ -24,7 +24,9 @@ OBJ-y += \
$A/wrc_ptp_ppsi.o \
lib/dump-funcs.o \
lib/drop.o \
lib/div64.o
lib/div64.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__ */
......@@ -11,8 +11,6 @@
#include <ppsi/ppsi.h>
#include "wrpc.h"
#include <common-fun.h>
#include "../proto-ext-whiterabbit/wr-api.h"
#include "../proto-ext-whiterabbit/wr-constants.h"
/* All of these live in wrpc-sw/include */
#include "minic.h"
......@@ -28,7 +26,7 @@ extern int32_t cal_phase_transition;
int ptp_mode = WRC_MODE_UNKNOWN;
static int ptp_enabled = 0;
static struct wr_operations wrpc_wr_operations = {
struct wrh_operations wrh_oper = {
.locking_enable = wrpc_spll_locking_enable,
.locking_poll = wrpc_spll_locking_poll,
.locking_disable = wrpc_spll_locking_disable,
......@@ -50,20 +48,24 @@ static struct wr_operations wrpc_wr_operations = {
};
/*ppi fields*/
static DSDefault defaultDS;
static DSCurrent currentDS;
static DSParent parentDS;
static DSTimeProperties timePropertiesDS;
static defaultDS_t defaultDS;
static currentDS_t currentDS;
static [parentDS_t parentDS;
static timePropertiesDS_t timePropertiesDS;
static struct pp_servo servo;
static struct wr_servo_state servo_state;
static struct wr_dsport wr_dsport = {
.ops = &wrpc_wr_operations,
};
static DSPort portDS = {
.ext_dsport = &wr_dsport
};
#if CONFIG_EXT_WR == 1
/* WR extension declaration */
#include "../proto-ext-whiterabbit/wr-api.h"
#include "../proto-ext-whiterabbit/wr-constants.h"
static struct wr_data wr_ext_data; /* WR extension data */
static struct wr_dsport wr_dsport;
#endif
static portDS_t portDS ;
static int delay_ms = PP_DEFAULT_NEXT_DELAY_MS;
static int start_tics = 0;
......@@ -80,11 +82,11 @@ struct pp_instance ppi_static = {
.t_ops = &wrpc_time_ops,
.vlans_array_len = CONFIG_VLAN_ARRAY_SIZE,
.proto = PP_DEFAULT_PROTO,
.mech = PP_E2E_MECH, /* until changed by cfg */
.delayMechanism = E2E, /* until changed by cfg */
.iface_name = "wr1",
.port_name = "wr1",
.__tx_buffer = __tx_buffer,
.__rx_buffer = __rx_buffer,
.__tx_buffer = __tx_buffer,
.__rx_buffer = __rx_buffer,
};
/* We now have a structure with all globals, and multiple ppi inside */
......@@ -95,17 +97,29 @@ static struct pp_globals ppg_static = {
.currentDS = &currentDS,
.parentDS = &parentDS,
.timePropertiesDS = &timePropertiesDS,
.global_ext_data = &servo_state,
};
extern struct pp_ext_hooks pp_hooks;
int wrc_ptp_init()
{
struct pp_instance *ppi = &ppi_static;
sdb_find_devices();
uart_init_hw();
pp_printf("PPSi for WRPC. Commit %s, built on " __DATE__ "\n",
PPSI_VERSION);
ppi->ext_hooks =&pp_hooks; /* default value */
if ( CONFIG_EXT_WR == 1 ) {
ppi->ext_hooks = &wr_ext_hooks;
ppi->ext_data = &wr_ext_data;
wr_ext_data->servo_state.servo_head.extension=PPSI_EXT_WR;
portDS.ext_dsport = &wr_dsport;
}
return 0;
}
......@@ -210,18 +224,18 @@ int wrc_ptp_sync_mech(int e2e_p2p_qry)
int running;
if (!CONFIG_HAS_P2P)
return ppi->mech;
return ppi->delayMechanism;
switch(e2e_p2p_qry) {
case PP_E2E_MECH:
case PP_P2P_MECH:
case E2E:
case P2P:
running = wrc_ptp_run(-1);
wrc_ptp_run(0);
ppi->mech = e2e_p2p_qry;
ppi->delayMechanism = e2e_p2p_qry;
wrc_ptp_run(running);
return 0;
default:
return ppi->mech;
return ppi->delayMechanism;
}
}
......
......@@ -73,7 +73,7 @@ int wrpc_calibrating_poll(struct pp_instance *ppi, int txrx, uint32_t *delta)
/* FIXME: why delta was 64bit whereas ep_get_deltas accepts 32bit? */
wrpc_read_calibration_data(ppi, &delta_tx, &delta_rx, NULL, NULL);
if (txrx == WR_HW_CALIB_TX)
if (txrx == WRH_HW_CALIB_TX)
*delta = delta_tx;
else
*delta = delta_rx;
......
......@@ -11,6 +11,8 @@
#include <softpll_ng.h>
#include "../proto-ext-whiterabbit/wr-constants.h"
#include <rxts_calibrator.h>
#include "../include/hw-specific/wrh.h"
#include "wrpc.h"
extern uint32_t cal_phase_transition;
......@@ -20,7 +22,7 @@ int wrpc_spll_locking_enable(struct pp_instance *ppi)
spll_init(SPLL_MODE_SLAVE, 0, 1);
spll_enable_ptracker(0, 1);
rxts_calibration_start();
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
int wrpc_spll_locking_poll(struct pp_instance *ppi, int grandmaster)
......@@ -31,7 +33,7 @@ int wrpc_spll_locking_poll(struct pp_instance *ppi, int grandmaster)
locked = spll_check_lock(0); /* both slave and gm mode */
if (grandmaster)
return locked ? WR_SPLL_READY : WR_SPLL_ERROR;
return locked ? WRH_SPLL_READY : WRH_SPLL_ERROR;
/* Else, slave: ensure calibration is done */
if(!locked) {
......@@ -40,30 +42,30 @@ int wrpc_spll_locking_poll(struct pp_instance *ppi, int grandmaster)
else if(locked && !t24p_calibrated) {
/*run t24p calibration if needed*/
if (calib_t24p(WRC_MODE_SLAVE, &cal_phase_transition) < 0)
return WR_SPLL_CALIB_NOT_READY;
return WRH_SPLL_CALIB_NOT_READY;
t24p_calibrated = 1;
}
return locked ? WR_SPLL_READY : WR_SPLL_ERROR;
return locked ? WRH_SPLL_READY : WRH_SPLL_ERROR;
}
int wrpc_spll_locking_reset(struct pp_instance *ppi)
{
//TODO?
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
int wrpc_spll_locking_disable(struct pp_instance *ppi)
{
/* softpll_disable(); */
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
int wrpc_spll_enable_ptracker(struct pp_instance *ppi)
{
spll_enable_ptracker(0, 1);
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
int wrpc_enable_timing_output(struct pp_instance *ppi, int enable)
......@@ -73,7 +75,7 @@ int wrpc_enable_timing_output(struct pp_instance *ppi, int enable)
WR_DSPOR(ppi)->ppsOutputOn = enable;
shw_pps_gen_enable_output(enable);
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
int wrpc_adjust_in_progress(void)
......@@ -93,6 +95,6 @@ int wrpc_adjust_counters(int64_t adjust_sec, int32_t adjust_nsec)
int wrpc_adjust_phase(int32_t phase_ps)
{
spll_set_phase_shift(SPLL_ALL_CHANNELS, phase_ps);
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
......@@ -51,7 +51,7 @@ int wrpc_spll_enable_ptracker(struct pp_instance *ppi);
int wrpc_adjust_in_progress(void);
int wrpc_adjust_counters(int64_t adjust_sec, int32_t adjust_nsec);
int wrpc_adjust_phase(int32_t phase_ps);
int wrpc_enable_timing_output(struct pp_instance *ppi, int enable);
int wrpc_enable_timing_output(struct pp_instance *ppi, int *ppsOutputOn, int enable);
/* wrpc-calibration.c */
int wrpc_read_calibration_data(struct pp_instance *ppi,
......
# 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 \
......@@ -19,7 +23,11 @@ OBJ-y += $A/wrs-startup.o \
lib/dump-funcs.o \
lib/drop.o \
lib/assert.o \
lib/div64.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
......@@ -36,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)
......@@ -46,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
......@@ -2,9 +2,6 @@
#define __ARCH_H__
#include <ppsi/assert.h>
/* 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 */
#include <arpa/inet.h> /* ntohs etc */
......
......@@ -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,13 +80,15 @@ 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
/*
......@@ -100,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
......@@ -39,6 +39,9 @@ typedef struct hal_port_calibration {
uint32_t delta_tx_phy;
uint32_t delta_rx_phy;
/* bit slide expresse in picos */
uint32_t bitslide_ps;
/* Current board routing delays (between the DDMTD inputs to
the PHY clock inputs/outputs), in picoseconds */
uint32_t delta_tx_board;
......@@ -71,9 +74,6 @@ struct hal_port_state {
int fd;
int hw_addr_auto;
/* port timing mode (HEXP_PORT_MODE_xxxx) */
int mode;
/* port FSM state (HAL_PORT_STATE_xxxx) */
int state;
......
......@@ -10,8 +10,13 @@
*/
#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 */
extern struct minipc_ch *hal_ch;
extern struct minipc_ch *ppsi_ch;
......@@ -30,26 +35,6 @@ static inline struct hal_port_state *pp_wrs_lookup_port(char *name)
#define DEFAULT_TO 200000 /* ms */
/* FIXME return values, here copied from proto-ext-whiterabbit.
* I do not include proto-ext-whiterabbit/wr-constants.h in order not to
* have a dependency on ext when compiling wrs architecture. All the return
* values mechanism of wrs hw should be reviewed in this src and in the
* whole ppsi */
/* White Rabbit softpll status values */
#define WR_SPLL_OK 0
#define WR_SPLL_READY 1
#define WR_SPLL_CALIB_NOT_READY 2
#define WR_SPLL_ERROR -1
/* White Rabbit calibration defines */
#define WR_HW_CALIB_TX 1
#define WR_HW_CALIB_RX 2
#define WR_HW_CALIB_OK 0
#define WR_HW_CALIB_READY 1
#define WR_HW_CALIB_ERROR -1
#define WR_HW_CALIB_NOT_FOUND -3
#define POSIX_ARCH(ppg) ((struct unix_arch_data *)(ppg->arch_data))
struct unix_arch_data {
struct timeval tv;
......@@ -60,25 +45,21 @@ extern void wrs_main_loop(struct pp_globals *ppg);
extern void wrs_init_ipcserver(struct minipc_ch *ppsi_ch);
/* wrs-calibration.c */
int wrs_read_calibration_data(struct pp_instance *ppi,
uint32_t *delta_tx, uint32_t *delta_rx,
int32_t *fix_alpha, int32_t *clock_period);
int wrs_calibrating_disable(struct pp_instance *ppi, int txrx);
int wrs_calibrating_enable(struct pp_instance *ppi, int txrx);
int wrs_calibrating_poll(struct pp_instance *ppi, int txrx, uint32_t *delta);
int wrs_calibration_pattern_enable(struct pp_instance *ppi,
unsigned int calib_period,
unsigned int calib_pattern,
unsigned int calib_pattern_len);
int wrs_calibration_pattern_disable(struct pp_instance *ppi);
int wrs_read_calibration_data(struct pp_instance *ppi, int32_t *clock_period,
uint32_t *bit_slide_ps);
/* 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);
timing_mode_t wrs_get_timing_mode(struct pp_globals *ppg);
......@@ -13,16 +13,18 @@
#include <errno.h>
#include <sys/select.h>
#include <netinet/if_ether.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <ppsi/ppsi.h>
#include <ppsi-wrs.h>
#include <wr-api.h>
#include <hal_exports.h>
#include <common-fun.h>
/* Call pp_state_machine for each instance. To be called periodically,
* when no packets are incoming */
static int run_all_state_machines(struct pp_globals *ppg)
static unsigned int run_all_state_machines(struct pp_globals *ppg)
{
int j;
int delay_ms = 0, delay_ms_j;
......@@ -50,16 +52,25 @@ static int run_all_state_machines(struct pp_globals *ppg)
ppi->iface_name, ppi->link_up ? "up":"down");
if (ppi->link_up) {
uint32_t bit_slide_ps;
ppi->state = PPS_INITIALIZING;
if ( wrs_read_calibration_data(ppi,NULL,&bit_slide_ps)!= WRH_HW_CALIB_OK ) {
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",(unsigned int)bit_slide_ps);
ppi->timestampCorrectionPortDS.semistaticLatency= picos_to_interval(bit_slide_ps);
}
else {
ppi->next_state = PPS_DISABLED;
pp_leave_current_state(ppi);
ppi->n_ops->exit(ppi);
ppi->frgn_rec_num = 0;
ppi->frgn_rec_best = 0;
ppi->frgn_rec_best = -1;
if (ppg->ebest_idx == ppi->port_idx)
wr_servo_reset(ppi);
if( ppi->ext_hooks->servo_reset)
(*ppi->ext_hooks->servo_reset)(ppi);
}
}
......@@ -76,13 +87,88 @@ 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;
}
static int alarmDetected=1;
static void sched_handler(int sig, siginfo_t *si, void *uc)
{
alarmDetected=1;
}
static void init_alarm(timer_t *timerid) {
struct sigevent sev;
struct sigaction sa;
/* Set the signal handler */
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = sched_handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGALRM, &sa, NULL) == -1) {
fprintf(stderr, "ppsi: cannot set signal handler\n");
exit(1);
}
/* Create the timer */
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGALRM;
sev.sigev_value.sival_ptr = timerid;
if (timer_create(CLOCK_MONOTONIC, &sev, timerid) == -1) {
fprintf(stderr, "ppsi: Cannot create timer\n");
exit(1);
}
}
static void start_alarm(timer_t *timerid, unsigned int delay_ms) {
struct itimerspec its;
its.it_value.tv_sec = delay_ms/1000;
its.it_value.tv_nsec = (delay_ms%1000) * 1000000;
its.it_interval.tv_sec =
its.it_interval.tv_nsec = 0;
if (timer_settime(*timerid, 0, &its, NULL) == -1){
fprintf(stderr, "ppsi: Cannot start timer. DelayMs=%u. Errno=%d\n",delay_ms, errno);
}
}
static int stop_alarm(timer_t *timerid) {
struct itimerspec its;
struct itimerspec ito;
its.it_value.tv_sec =
its.it_value.tv_nsec =
its.it_interval.tv_sec =
its.it_interval.tv_nsec = 0;
if (timer_settime(*timerid, 0, &its, &ito) == -1){
fprintf(stderr, "ppsi: Cannot stop timer\n");
return 0;
}
return (int) (ito.it_value.tv_sec*1000+ito.it_value.tv_nsec/1000000);
}
void wrs_main_loop(struct pp_globals *ppg)
{
struct pp_instance *ppi;
int delay_ms;
int skipped_checks=0;
unsigned int delay_ms;
timer_t timerid;
int j;
/* Initialize each link's state machine */
......@@ -100,71 +186,78 @@ void wrs_main_loop(struct pp_globals *ppg)
delay_ms = run_all_state_machines(ppg);
while (1) {
int i;
/* Create the timer */
init_alarm(&timerid);
minipc_server_action(ppsi_ch, 10 /* ms */);
while (1) {
int packet_available;
/*
* If Ebest was changed in previous loop, run best
* master clock before checking for new packets, which
* would affect port state again
/* Checking of received frames or minirpc are not done if the delay
* is 0 or the scheduling alarm is raised. These checks must be forced sometime
* (see skipped_checks)
*/
if (ppg->ebest_updated) {
for (j = 0; j < ppg->nlinks; j++) {
int new_state;
struct pp_instance *ppi = INST(ppg, j);
new_state = bmc(ppi);
if (new_state != ppi->state) {
ppi->state = new_state;
ppi->is_new_state = 1;
}
}
ppg->ebest_updated = 0;
if ( !alarmDetected && (skipped_checks > 10 || delay_ms !=0) ) {
minipc_server_action(ppsi_ch, 1 /* ms */);
packet_available = wrs_net_ops.check_packet(ppg, delay_ms);
skipped_checks=0;
} else {
skipped_checks++;
packet_available=0;
}
i = wrs_net_ops.check_packet(ppg, delay_ms);
if (i < 0)
continue;
if (i == 0) {
delay_ms = run_all_state_machines(ppg);
if ((packet_available<=0) && (alarmDetected || (delay_ms==0))) {
/* Time to run the state machine */
stop_alarm(&timerid); /* Clear previous alarm */
delay_ms = run_all_state_machines(ppg);
alarmDetected=0;
if ( delay_ms != 0 ) {
/* Start the alarm */
start_alarm(&timerid,delay_ms);
}
continue;
}
/* If delay_ms is -1, the above ops.check_packet will continue
* consuming the previous timeout (see its implementation).
* This ensures that every state machine is called at least once
* every delay_ms */
delay_ms = -1;
if (packet_available > 0 ) {
/* If delay_ms is UINT_MAX, the above ops.check_packet will continue
* consuming the previous timeout (see its implementation).
* This ensures that every state machine is called at least once
* every delay_ms */
delay_ms = UINT_MAX;
for (j = 0; j < ppg->nlinks; j++) {
int tmp_d,i;
ppi = INST(ppg, j);
if ((ppi->ch[PP_NP_GEN].pkt_present) ||
(ppi->ch[PP_NP_EVT].pkt_present)) {
for (j = 0; j < ppg->nlinks; j++) {
int tmp_d;
ppi = INST(ppg, j);
i = __recv_and_count(ppi, ppi->rx_frame,
PP_MAX_FRAME_LENGTH - 4,
&ppi->last_rcv_time);
if ((ppi->ch[PP_NP_GEN].pkt_present) ||
(ppi->ch[PP_NP_EVT].pkt_present)) {
if (i == PP_RECV_DROP) {
continue; /* dropped or not for us */
}
if (i == -1) {
pp_diag(ppi, frames, 1, "Receive Error %i: %s\n",errno, strerror(errno));
continue;
}
i = __recv_and_count(ppi, ppi->rx_frame,
PP_MAX_FRAME_LENGTH - 4,
&ppi->last_rcv_time);
tmp_d = pp_state_machine(ppi, ppi->rx_ptp,
i - ppi->rx_offset);
if (i == PP_RECV_DROP) {
continue; /* dropped or not for us */
}
if (i == -1) {
pp_diag(ppi, frames, 1,
"Receive Error %i: %s\n",
errno, strerror(errno));
continue;
if ( tmp_d < delay_ms )
delay_ms = tmp_d;
}
}
if ((delay_ms!=UINT_MAX) && !alarmDetected ) {
int rem_delay_ms=stop_alarm(&timerid); /* Stop alarm and get remaining delay */
tmp_d = pp_state_machine(ppi, ppi->rx_ptp,
i - ppi->rx_offset);
if ((delay_ms == -1) || (tmp_d < delay_ms))
delay_ms = tmp_d;
if ( rem_delay_ms < delay_ms) {
/* Re-adjust delay_ms */
delay_ms=rem_delay_ms;
}
alarmDetected=0;
start_alarm(&timerid,delay_ms); /* Start alarm */
}
}
}
......
......@@ -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
......
......@@ -130,14 +130,17 @@ int minipc_call(struct minipc_ch *ch, int millisec_timeout,
pfd.fd = ch->fd;
pfd.events = POLLIN | POLLHUP;
pfd.revents = 0;
pollnr = poll(&pfd, 1, millisec_timeout);
if (pollnr < 0) {
/* errno already set */
return -1;
}
if (pollnr == 0) {
errno = ETIMEDOUT;
return -1;
while ( 1 ) {
if ( (pollnr = poll(&pfd, 1, millisec_timeout)) > 0 )
break;
if (pollnr < 0 && errno!=EINTR) {
/* errno already set */
return -1;
}
if (pollnr == 0) {
errno = ETIMEDOUT;
return -1;
}
}
if (shm) {
......
#!/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
......@@ -13,80 +13,20 @@
#include <hal_exports.h>
int wrs_read_calibration_data(struct pp_instance *ppi,
uint32_t *delta_tx, uint32_t *delta_rx, int32_t *fix_alpha,
int32_t *clock_period)
int wrs_read_calibration_data(struct pp_instance *ppi,int32_t *clock_period, uint32_t *bit_slide_ps)
{
struct hal_port_state *p;
/* The following fields come from struct hexp_port_state */
uint32_t port_delta_tx, port_delta_rx;
int32_t port_fix_alpha;
p = pp_wrs_lookup_port(ppi->iface_name);
if (!p)
return WR_HW_CALIB_NOT_FOUND;
return WRH_HW_CALIB_NOT_FOUND;
if(!p->calib.tx_calibrated || !p->calib.rx_calibrated)
return WR_HW_CALIB_NOT_FOUND;
return WRH_HW_CALIB_NOT_FOUND;
/*
* Like in wrs_net_init, we build fields that were in
* hexp_port_state from the "real" hal_port_state in the same
* way as the HAL itself was doing to fill the RPC structure.
* Formulas copied from libwr/hal_shmem.c (get_exported_state).
*/
port_delta_tx = p->calib.delta_tx_phy
+ p->calib.sfp.delta_tx_ps + p->calib.delta_tx_board;
port_delta_rx = p->calib.delta_rx_phy
+ p->calib.sfp.delta_rx_ps + p->calib.delta_rx_board;
port_fix_alpha = (double)pow(2.0, 40.0) *
((p->calib.sfp.alpha + 1.0) / (p->calib.sfp.alpha + 2.0)
- 0.5);
pp_diag(ppi, servo, 1, "deltas: tx=%d, rx=%d\n",
port_delta_tx, port_delta_rx);
if(delta_tx)
*delta_tx = port_delta_tx;
if(delta_rx)
*delta_rx = port_delta_rx;
if(fix_alpha)
*fix_alpha = port_fix_alpha;
if ( bit_slide_ps )
*bit_slide_ps=p->calib.bitslide_ps;
if(clock_period)
*clock_period = 16000; /* REF_CLOCK_PERIOD_PS */
return WR_HW_CALIB_OK;
}
int wrs_calibrating_disable(struct pp_instance *ppi, int txrx)
{
return 0;
}
int wrs_calibrating_enable(struct pp_instance *ppi, int txrx)
{
return 0;
}
int wrs_calibrating_poll(struct pp_instance *ppi, int txrx, uint32_t *delta)
{
uint32_t delta_tx, delta_rx;
wrs_read_calibration_data(ppi, &delta_tx, &delta_rx, NULL, NULL);
*delta = (txrx == WR_HW_CALIB_TX) ? delta_tx : delta_rx;
return WR_HW_CALIB_READY;
}
int wrs_calibration_pattern_enable(struct pp_instance *ppi,
unsigned int calib_period,
unsigned int calib_pattern,
unsigned int calib_pattern_len)
{
return WR_HW_CALIB_OK;
}
int wrs_calibration_pattern_disable(struct pp_instance *ppi)
{
return WR_HW_CALIB_OK;
return WRH_HW_CALIB_OK;
}
......@@ -8,11 +8,11 @@
#include <ppsi/ppsi.h>
#include <ppsi-wrs.h>
#include <hal_exports.h>
#include <wr-api.h>
/* minipc Encoding of the supported commands */
#define PTPDEXP_COMMAND_TRACKING 1
#define PTPDEXP_COMMAND_WR_TRACKING 1
#define PTPDEXP_COMMAND_L1SYNC_TRACKING 2
static struct minipc_pd __rpcdef_cmd = {
.name = "cmd",
......@@ -27,9 +27,17 @@ static struct minipc_pd __rpcdef_cmd = {
/* Execute command coming ipc */
static int wrsipc_cmd(int cmd, int value)
{
if(cmd == PTPDEXP_COMMAND_TRACKING) {
wr_servo_enable_tracking(value);
return 0;
if(cmd == PTPDEXP_COMMAND_WR_TRACKING) {
if ( CONFIG_HAS_EXT_WR ) {
wrh_servo_enable_tracking(value);
return 0;
}
}
if(cmd == PTPDEXP_COMMAND_L1SYNC_TRACKING) {
if ( CONFIG_HAS_EXT_L1SYNC ) {
wrh_servo_enable_tracking(value);
return 0;
}
}
return -1;
......
This diff is collapsed.
#
# Automatically generated make config: don't edit
# Automatically generated file; DO NOT EDIT.
# PPSi configuration
#
# CONFIG_ARCH_UNIX is not set
# CONFIG_ARCH_BARE_I386 is not set
......@@ -14,14 +15,58 @@ CONFIG_ARCH="wrs"
#
CONFIG_E2E=y
# CONFIG_P2P is not set
CONFIG_EXT_WR=y
# CONFIG_EXT_NONE is not set
CONFIG_EXTENSION="whiterabbit"
CONFIG_CROSS_COMPILE="/opt/arm-wrswitch/bin/arm-linux-"
CONFIG_ARCH_CFLAGS=""
CONFIG_ARCH_LDFLAGS=""
# CONFIG_E2E_ONLY is not set
CONFIG_HAS_P2P=1
#
# Enabled profiles
#
CONFIG_PROFILE_WR=y
# CONFIG_PROFILE_HA is not set
CONFIG_PROFILE_CUSTOM=y
CONFIG_PROFILE_PTP=y
CONFIG_HAS_EXT_WR=1
CONFIG_HAS_EXT_L1SYNC=0
CONFIG_HAS_EXT_NONE=0
CONFIG_HAS_PROFILE_PTP=1
CONFIG_HAS_PROFILE_HA=0
CONFIG_HAS_PROFILE_WR=1
CONFIG_HAS_PROFILE_CUSTOM=1
#
# VLAN
#
CONFIG_HAS_VLAN=y
CONFIG_HAS_MULTIPLE_VLAN=y
CONFIG_VLAN=y
CONFIG_MAX_VLANS_PER_PORT=32
CONFIG_VLAN_ARRAY_SIZE=32
# CONFIG_ASSERT is not set
CONFIG_NR_FOREIGN_RECORDS=5
# CONFIG_SINGLE_FMASTER is not set
CONFIG_NR_PORTS=18
CONFIG_NR_INSTANCES_PER_PORT=2
#
# Code optimization
#
# CONFIG_CODEOPT_ENABLED is not set
# CONFIG_SINGLE_INSTANCE_PER_PORT is not set
# CONFIG_SINGLE_INSTANCE is not set
# CONFIG_SINGLE_PORT is not set
CONFIG_OPTIMIZATION_SPEED=y
# CONFIG_OPTIMIZATION_SIZE_SPEED is not set
# CONFIG_OPTIMIZATION_DEBUGGING is not set
# CONFIG_OPTIMIZATION_NONE_DEBUGGING is not set
CONFIG_OPTIMIZATION="-O2 -ggdb"
# CONFIG_FAULT_INJECTION_MECHANISM is not set
CONFIG_HAS_FAULT_INJECTION_MECHANISM=0
CONFIG_HAS_WRPC_FAULTS=0
CONFIG_HAS_CODEOPT_SINGLE_FMASTER=0
CONFIG_HAS_CODEOPT_SINGLE_PORT=0
CONFIG_HAS_CODEOPT_SINGLE_INSTANCE_PER_PORT=0
CONFIG_HAS_CODEOPT_EPC_ENABLED=0
CONFIG_HAS_CODEOPT_SO_ENABLED=0
CONFIG_ARCH_IS_WRS=1
CONFIG_ARCH_IS_WRPC=0
CONFIG_HAS_ASSERT=0
......@@ -26,13 +26,25 @@ void __pp_diag(struct pp_instance *ppi, enum pp_diag_things th,
int level, char *fmt, ...)
{
va_list args;
char *name = ppi ? ppi->port_name : "ppsi";
char *name;
if (!__PP_DIAG_ALLOW(ppi, th, level))
return;
name = ppi ? ppi->port_name : "ppsi";
/* Use the normal output channel for diagnostics */
pp_printf("%s-%i-%s: ", thing_name[th], level, name);
if (PP_DIAG_EXTRA_PRINT_TIME) {
int hours, minutes, seconds;
if (ppi && ppi->t_ops && ppi->t_ops->get_utc_time )
ppi->t_ops->get_utc_time(ppi, &hours, &minutes, &seconds);
else
hours=minutes=seconds=0;
pp_printf("%02d:%02d:%02d %s-%i-%s: ", hours, minutes,seconds,thing_name[th], level, name);
} else {
pp_printf("%s-%i-%s: ", thing_name[th], level, name);
}
va_start(args, fmt);
pp_vprintf(fmt, args);
va_end(args);
......
......@@ -65,7 +65,7 @@ static void pp_diag_fsm(struct pp_instance *ppi, char *name, int sequence,
static struct pp_state_table_item *
get_current_state_table_item(struct pp_instance *ppi)
{
struct pp_state_table_item *ip = ppi->current_state_item;;
struct pp_state_table_item *ip = ppi->current_state_item;
/* Avoid searching if we already know where we are */
ppi->is_new_state = 0;
......@@ -82,14 +82,25 @@ get_current_state_table_item(struct pp_instance *ppi)
return NULL;
}
char *get_state_as_string(struct pp_instance *ppi, int state) {
static char *def="INVALID";
struct pp_state_table_item *ip = ppi->current_state_item;
for (ip = pp_state_table; ip->state != PPS_END_OF_TABLE; ip++)
if (ip->state == state) {
return ip->name;
}
return def;
}
/*
* Returns delay to next state, which is always zero.
*/
int pp_leave_current_state(struct pp_instance *ppi)
{
/* If something has to be done in an extension */
if (pp_hooks.state_change)
pp_hooks.state_change(ppi);
if ( ppi->ext_hooks->state_change)
ppi->ext_hooks->state_change(ppi);
/* if the next or old state is non standard PTP reset all timeouts */
if ((ppi->state > PPS_LAST_STATE) || (ppi->next_state > PPS_LAST_STATE))
......@@ -151,9 +162,9 @@ 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 */
* also the PASSIVE states in this case is overwritten */
if (hdr->messageType != PPM_ANNOUNCE) {
/* ignore messages, except announce coming from its own clock */
return -1;
......@@ -214,7 +225,7 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
"RECV %02d bytes at %9d.%09d.%03d (type %x, %s)\n",
len, (int)t->secs, (int)(t->scaled_nsecs >> 16),
((int)(t->scaled_nsecs & 0xffff) * 1000) >> 16,
msgtype, pp_msgtype_info[msgtype].name);
msgtype, pp_msgtype_name[msgtype]);
}
/*
......@@ -265,7 +276,22 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
if (ppi->state != ppi->next_state)
return pp_leave_current_state(ppi);
if (!len)
if (len) {
if ( ppi->ext_enabled && !ppi->ptp_msg_received ) {
/* First frame received since instance initialization */
int tmo;
ppi->ptp_msg_received=TRUE;
if (is_ext_hook_available(ppi,get_tmo_lstate_detection) )
tmo=(*ppi->ext_hooks->get_tmo_lstate_detection)(ppi);
else
tmo= is_externalPortConfigurationEnabled(DSDEF(ppi)) ?
6000 /* JCB: Default value. Is it correct ? */
: pp_timeout_get(ppi,PP_TO_ANN_RECEIPT);
pp_timeout_set(ppi,PP_TO_PROT_STATE, tmo);
lstate_set_link_pdetection(ppi);
}
} else
ppi->received_ptp_header.messageType = PPM_NO_MESSAGE;
err = ip->f1(ppi, buf, len);
......@@ -277,10 +303,29 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
if (ppi->state != ppi->next_state)
return pp_leave_current_state(ppi);
/* Check protocol state */
if ( ppi->protocol_extension == PPSI_EXT_NONE ) {
lstate_set_link_none(ppi);
} else {
if ( ppi->ext_enabled ) {
if ( ppi->link_state==PP_LSTATE_PROTOCOL_ERROR ||
( ppi->link_state!=PP_LSTATE_LINKED && ppi->ptp_msg_received && pp_timeout(ppi, PP_TO_PROT_STATE)) ) {
if ( ppi->ptp_support )
lstate_disable_extension(ppi);
else
lstate_set_link_failure(ppi);
}
} else {
lstate_set_link_failure(ppi);
}
}
/* 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)
......@@ -289,9 +334,24 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
pp_diag_fsm(ppi, ip->name, STATE_LOOP, 0);
/* 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);
/* Run the extension state machine. The extension can provide its own time-out */
if ( is_ext_hook_available(ppi,run_ext_state_machine) ) {
int delay = ppi->ext_hooks->run_ext_state_machine(ppi,buf,len);
if ( ppi->ext_enabled && ppi->link_state==PP_LSTATE_PROTOCOL_ERROR) {
if (ppi->ptp_support ) {
lstate_disable_extension(ppi);
}
else
lstate_set_link_failure(ppi);
}
/* if new state mark it, and enter it now (0 ms) */
if (ppi->state != ppi->next_state)
return pp_leave_current_state(ppi);
if (delay < ppi->next_delay)
ppi->next_delay=delay;
}
return ppi->next_delay;
}
/*
* Copyright (C) 2011 CERN (www.cern.ch)
* Author: Jean-Claude BAU
* Declarations common to WR switches and nodes.
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#ifndef __WRH_H__
#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 */
#define WRS_PPSI_SHMEM_VERSION 32 /* added HAL_PORT_STATE_RESET to hal */
/* White Rabbit softpll status values */
#define WRH_SPLL_OK 0
#define WRH_SPLL_READY 1
#define WRH_SPLL_CALIB_NOT_READY 2
#define WRH_SPLL_ERROR -1
/* White Rabbit calibration defines */
#define WRH_HW_CALIB_TX 1
#define WRH_HW_CALIB_RX 2
#define WRH_HW_CALIB_OK 0
#define WRH_HW_CALIB_READY 1
#define WRH_HW_CALIB_ERROR -1
#define WRH_HW_CALIB_NOT_FOUND -3
#define FIX_ALPHA_FRACBITS 40
#define FIX_ALPHA_FRACBITS_AS_FLOAT 40.0
#define WRH_SERVO_OFFSET_STABILITY_THRESHOLD 60 /* psec */
/* 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 (*locking_disable)(struct pp_instance *ppi);
int (*locking_reset)(struct pp_instance *ppi);
int (*enable_ptracker)(struct pp_instance *ppi);
int (*adjust_in_progress)(void);
int (*adjust_counters)(int64_t adjust_sec, int32_t adjust_nsec);
int (*adjust_phase)(int32_t phase_ps);
int (*read_calib_data)(struct pp_instance *ppi,int32_t *clock_period, uint32_t *bit_slide_ps);
int (*enable_timing_output)(struct pp_globals *,int enable);
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;
static inline struct wrh_operations *WRH_OPER(void)
{
return &wrh_oper;
}
/****************************************************************************************/
/* wrh_servo interface */
/* Servo state */
typedef enum {
WRH_UNINITIALIZED = 0,
WRH_SYNC_TAI,
WRH_SYNC_NSEC,
WRH_SYNC_PHASE,
WRH_TRACK_PHASE,
WRH_WAIT_OFFSET_STABLE,
}wrh_servo_state_t;
#define WRH_SERVO_RESET_DATA_SIZE (sizeof(wrh_servo_t)-offsetof(wrh_servo_t,reset_address))
#define WRH_SERVO_RESET_DATA(servo) memset(&servo->reset_address,0,WRH_SERVO_RESET_DATA_SIZE);
typedef struct wrh_servo_t {
/* Values used by snmp. Values are increased at servo update when
* erroneous condition occurs. */
uint32_t n_err_state;
uint32_t n_err_offset;
uint32_t n_err_delta_rtt;
int32_t cur_setpoint_ps;
/* ----- All data after this line will cleared during a servo reset */
int reset_address;
/* These fields are used by servo code, after setting at init time */
int32_t clock_period_ps;
/* Following fields are for monitoring/diagnostics (use w/ shmem) */
int64_t delayMM_ps;
int64_t delayMS_ps;
int tracking_enabled;
int64_t skew_ps;
int64_t offsetMS_ps;
/* These fields are used by servo code, across iterations */
int64_t prev_delayMS_ps;
int missed_iters;
Boolean readyForSync; /* Ready for synchronization */
} wrh_servo_t;
static inline wrh_servo_t *WRH_SRV(struct pp_instance *ppi)
{
return (wrh_servo_t *)ppi->ext_data;
}
/* Prototypes */
extern void wrh_servo_enable_tracking(int enable);
extern int wrh_servo_init(struct pp_instance *ppi);
extern void wrh_servo_reset(struct pp_instance *ppi);
extern void wrh_servo_enable_tracking(int enable);
extern int wrh_servo_got_sync(struct pp_instance *ppi);
extern int wrh_servo_got_resp(struct pp_instance *ppi);
extern int wrh_servo_got_presp(struct pp_instance *ppi);
extern int wrh_update_correction_values(struct pp_instance *ppi);
#endif /* __WRH_H__ */
......@@ -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);
......@@ -11,30 +11,66 @@
/* general purpose constants */
#define PP_NSEC_PER_SEC (1000*1000*1000)
#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
#define PP_DEFAULT_ROLE PPSI_ROLE_AUTO
#define PP_DEFAULT_PROTO PPSI_PROTO_UDP /* overridden by arch */
#define PP_DEFAULT_DOMAIN_NUMBER 0
#define PP_DEFAULT_AP 10
#define PP_DEFAULT_AI 1000
#define PP_DEFAULT_DELAY_S 6
#define PP_MIN_DOMAIN_NUMBER 0
#define PP_MAX_DOMAIN_NUMBER 255
#define PP_DEFAULT_DOMAIN_NUMBER 0
#define PP_DEFAULT_ANNOUNCE_INTERVAL 1 /* 0 in 802.1AS */
#define PP_DEFAULT_DELAYREQ_INTERVAL 0
#define PP_DEFAULT_SYNC_INTERVAL 0 /* -7 in 802.1AS */
#define PP_DEFAULT_SYNC_RECEIPT_TIMEOUT 3
#define PP_MIN_ANNOUNCE_INTERVAL 0
#define PP_MAX_ANNOUNCE_INTERVAL 4
#define PP_DEFAULT_ANNOUNCE_RECEIPT_TIMEOUT 3 /* 3 by default */
#define PP_MIN_ANNOUNCE_RECEIPT_TIMEOUT 2
#define PP_MAX_ANNOUNCE_RECEIPT_TIMEOUT 255
#define PP_DEFAULT_MIN_DELAY_REQ_INTERVAL 0
#define PP_MIN_MIN_DELAY_REQ_INTERVAL 0
#define PP_MAX_MIN_DELAY_REQ_INTERVAL 5
#define PP_DEFAULT_MIN_PDELAY_REQ_INTERVAL 0
#define PP_MIN_MIN_PDELAY_REQ_INTERVAL 0
#define PP_MAX_MIN_PDELAY_REQ_INTERVAL 5
#define PP_DEFAULT_SYNC_INTERVAL 0 /* -7 in 802.1AS */
#define PP_MIN_SYNC_INTERVAL -1
#define PP_MAX_SYNC_INTERVAL 1
#define PP_DEFAULT_UTC_OFFSET 37
#define PP_DEFAULT_PRIORITY1 128
#define PP_MIN_PRIORITY1 0
#define PP_MAX_PRIORITY1 255
#define PP_DEFAULT_PRIORITY1 64
#define PP_MIN_PRIORITY2 0
#define PP_MAX_PRIORITY2 255
#define PP_DEFAULT_PRIORITY2 128
#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_CLASS_SLAVE_ONLY 255
#define PP_CLASS_DEFAULT 248
#define PP_MIN_CLOCK_CLASS 0
#define PP_MAX_CLOCK_CLASS 255
#define PP_CLASS_SLAVE_ONLY 255
#define PP_CLASS_DEFAULT 248
#define PP_PTP_CLASS_GM_LOCKED 6
#define PP_PTP_CLASS_GM_HOLDOVER 7
#define PP_PTP_CLASS_GM_UNLOCKED 52
......@@ -42,7 +78,9 @@
#define PP_ARB_CLASS_GM_HOLDOVER 14
#define PP_ARB_CLASS_GM_UNLOCKED 58
#define PP_ACCURACY_DEFAULT 0xFE
#define PP_MIN_CLOCK_ACCURACY 0
#define PP_MAX_CLOCK_ACCURACY 255
#define PP_ACCURACY_DEFAULT 0xFE
#define PP_PTP_ACCURACY_GM_LOCKED 0x21
#define PP_PTP_ACCURACY_GM_HOLDOVER 0x21
#define PP_PTP_ACCURACY_GM_UNLOCKED 0xFE
......@@ -50,7 +88,9 @@
#define PP_ARB_ACCURACY_GM_HOLDOVER 0x21
#define PP_ARB_ACCURACY_GM_UNLOCKED 0xFE
#define PP_VARIANCE_DEFAULT 0xC71D
#define PP_MIN_CLOCK_VARIANCE 0
#define PP_MAX_CLOCK_VARIANCE 65535
#define PP_VARIANCE_DEFAULT 0xC71D
#define PP_PTP_VARIANCE_GM_LOCKED 0xB900
#define PP_PTP_VARIANCE_GM_HOLDOVER 0xC71D
#define PP_PTP_VARIANCE_GM_UNLOCKED 0xC71D
......@@ -58,38 +98,24 @@
#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,
/* 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
#define PP_VERSION_PTP 2
#define PP_MINOR_VERSION_PTP 1
#define PP_HEADER_LENGTH 34
#define PP_ANNOUNCE_LENGTH 64
......
......@@ -69,6 +69,9 @@ extern void __pp_diag(struct pp_instance *ppi, enum pp_diag_things th,
# define PP_HAS_DIAG 1
#endif
/* Constant used to enable extra diagnostic information - Inserted at compilation time */
#define PP_DIAG_EXTRA_PRINT_TIME (0 && PP_HAS_DIAG) /* Print time on each pp_diag calls */
/* So, this is the function that is to be used by real ppsi code */
#define pp_diag(ppi_, th_, level_, ...) \
({ \
......
/*
* 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);
}
}
This diff is collapsed.
......@@ -35,7 +35,7 @@
#define time_after_eq(a,b) \
(typecheck(unsigned long, a) && \
typecheck(unsigned long, b) && \
((long)(a) - (long)(b) >= 0))
((unsigned long)(a) >= (unsigned long)(b)))
#define time_before_eq(a,b) time_after_eq(b,a)
#endif /* ifndef */
#endif
......@@ -15,16 +15,21 @@
* Runtime options. Default values can be overridden by command line.
*/
struct pp_runtime_opts {
uint32_t updated_fields_mask;
ClockQuality clock_quality;
Integer32 ttl;
int flags; /* see below */
Integer16 ap, ai;
Integer16 s;
Integer8 announce_intvl;
int sync_intvl;
int prio1;
int prio2;
int domain_number;
int priority1;
int priority2;
int domainNumber;
int ptpPpsThresholdMs;
int gmDelayToGenPpsSec;
Boolean externalPortConfigurationEnabled;
Boolean slaveOnly;
Boolean forcePpsGen;
Boolean ptpFallbackPpsGen;
void *arch_opts;
};
......@@ -41,20 +46,22 @@ struct pp_runtime_opts {
/* We need a globally-accessible structure with preset defaults */
/* We need globally-accessible structures with preset defaults */
extern struct pp_runtime_opts __pp_default_rt_opts;
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;
};
......@@ -89,7 +96,7 @@ struct pp_frgn_master {
* machine are implemented.
*
* pp_avg_fltr: It is a variable cutoff/delay low-pass, infinite impulse
* response (IIR) filter. The meanPathDelay filter has the difference equation:
* response (IIR) filter. The meanDelay filter has the difference equation:
* s*y[n] - (s-1)*y[n-1] = x[n]/2 + x[n-1]/2,
* where increasing the stiffness (s) lowers the cutoff and increases the delay.
*/
......@@ -99,11 +106,43 @@ struct pp_avg_fltr {
int64_t s_exp;
};
/* Servo flags for communication diagnostic tool */
#define PP_SERVO_FLAG_VALID (1<<0)
#define PP_SERVO_FLAG_WAIT_HW (1<<1)
#define PP_SERVO_RESET_DATA_SIZE (sizeof(struct pp_servo)-offsetof(struct pp_servo,reset_address))
#define PP_SERVO_RESET_DATA(servo) memset(&servo->reset_address,0,PP_SERVO_RESET_DATA_SIZE);
struct pp_servo {
struct pp_time m_to_s_dly;
struct pp_time s_to_m_dly;
/* ptp servo specific data */
long long obs_drift;
struct pp_avg_fltr mpd_fltr;
/* Data shared with extension servo */
struct pp_time delayMM; /* Shared with extension servo */
struct pp_time delayMS; /* Shared with extension servo */
struct pp_time meanDelay; /* Shared with extension servo */
struct pp_time offsetFromMaster; /* Shared with extension servo */
unsigned long flags; /* PP_SERVO_FLAG_INVALID, PP_SERVO_FLAG_VALID, ...*/
/* Data used only by extensions */
int state;
char servo_state_name[32]; /* Updated by the servo itself */
/*
* ----- All data after this line will be cleared during by a servo initialization
*/
int reset_address;
/* Data shared with extension servo */
uint32_t update_count; /* incremented each time the servo is running */
struct pp_time update_time; /* Last updated time of the servo */
struct pp_time t1, t2, t3, t4, t5, t6;
/* ptp servo specific data */
int servo_locked; /* TRUE when servo is locked. This info can be used by HAL */
int got_sync; /* True when T1/T2 are available */
};
enum { /* The two sockets. They are called "net path" for historical reasons */
......@@ -114,15 +153,51 @@ enum { /* The two sockets. They are called "net path" for historical reasons */
/*
* Struct containg the result of ppsi.conf parsing: one for each link
* (see lib/conf.c). Actually, protocol and role are in the main ppi.
* (see lib/conf.c). Actually, protocol are in the main ppi.
*/
struct pp_instance_cfg {
char port_name[16];
char port_name[16];
char iface_name[16];
int ext; /* 0: none, 1: whiterabbit. 2: HA */
int mech; /* 0: E2E, 1: P2P */
int profile; /* PPSI_PROFILE_PTP, PPSI_PROFILE_WR, PPSI_PROFILE_HA */
int delayMechanism; /* Should be enum ENDelayMechanism but forced to int for configuration parsing */
int announce_interval; /* Announce messages interval */
int announce_receipt_timeout; /* Announce interval receipt timeout*/
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_HAS_EXT_L1SYNC
Boolean l1SyncEnabled; /* L1SYNC: protocol enabled */
Boolean l1SyncRxCoherencyIsRequired; /* L1SYNC: Rx coherency is required */
Boolean l1SyncTxCoherencyIsRequired; /* L1SYNC: Tx coherency is required */
Boolean l1SyncCongruencyIsRequired; /* L1SYNC: Congruency isrRequired */
Boolean l1SyncOptParamsEnabled; /* L1SYNC: Optional parameters enabled */
int l1syncInterval; /* L1SYNC: l1sync messages interval */
int l1syncReceiptTimeout; /* L1SYNC: l1sync messages receipt timeout */
Boolean l1SyncOptParamsTimestampsCorrectedTx; /* L1SYNC: correction of the transmitted egress timestamps */
#endif
int64_t egressLatency_ps; /* egressLatency in picos */
int64_t ingressLatency_ps; /* ingressLatency in picos */
int64_t constantAsymmetry_ps; /* constantAsymmetry in picos */
double delayCoefficient; /* fiber delay coefficient as a double */
int64_t scaledDelayCoefficient; /* fiber delay coefficient as RelativeDifference type */
int desiredState; /* externalPortConfigurationPortDS.desiredState */
Boolean masterOnly; /* masterOnly */
Boolean asymmetryCorrectionEnable; /* asymmetryCorrectionPortDS.enable */
};
/*
* 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.
*/
typedef enum {
PP_LSTATE_NONE, /* Link state not applied : No extension */
PP_LSTATE_PROTOCOL_DETECTION, /* Checking if the peer instance is using the same protocol */
PP_LSTATE_IN_PROGRESS, /* Right protocol detected. Try to establish the link with peer instance */
PP_LSTATE_LINKED, /* Link with peer well established */
PP_LSTATE_PROTOCOL_ERROR, /* The extension has detected a problem. */
PP_LSTATE_FAILURE, /* Impossible to connect correctly to a peer instance - extension disabled */
} pp_link_state;
/*
* Structure for the individual ppsi link
*/
......@@ -132,11 +207,12 @@ struct pp_instance {
struct pp_state_table_item *current_state_item;
void *arch_data; /* if arch needs it */
void *ext_data; /* if protocol ext needs it */
int protocol_extension; /* PPSI_EXT_NONE, PPSI_EXT_WR, PPSI_EXT_L1S */
struct pp_ext_hooks *ext_hooks; /* if protocol ext needs it */
unsigned long d_flags; /* diagnostics, ppi-specific flags */
unsigned char flags; /* protocol flags (see below) */
int role, /* same as in config file */
proto, /* same as in config file */
mech; /* same as in config file */
int proto; /* same as in config file */
int delayMechanism; /* same as in config file */
/* Pointer to global instance owning this pp_instance*/
struct pp_globals *glbs;
......@@ -162,6 +238,7 @@ struct pp_instance {
/* Times, for the various offset computations */
struct pp_time t1, t2, t3, t4, t5, t6; /* *the* stamps */
Integer32 t4_cf, t6_cf;
uint64_t syncCF; /* transp. clocks */
struct pp_time last_rcv_time, last_snt_time; /* two temporaries */
......@@ -172,9 +249,16 @@ struct pp_instance {
Integer16 frgn_rec_best;
struct pp_frgn_master frgn_master[PP_NR_FOREIGN_RECORDS];
DSPort *portDS; /* page 72 */
portDS_t *portDS; /* page 72 */
struct pp_servo *servo; /* Servo moved from globals because we may have more than one servo : redundancy */
unsigned long timeouts[__PP_TO_ARRAY_SIZE];
/** (IEEE1588-2019) */
asymmetryCorrectionPortDS_t asymmetryCorrectionPortDS; /*draft P1588_v_29: page 99*/
timestampCorrectionPortDS_t timestampCorrectionPortDS; /*draft P1588_v_29: page 99*/
externalPortConfigurationPortDS_t externalPortConfigurationPortDS; /*draft P1588: Clause 17.6.3*/
/************************* */
timeOutInstCnt_t tmo_cfg[PP_TO_COUNT];
UInteger16 recv_sync_sequence_id;
UInteger16 sent_seq[__PP_NR_MESSAGES_TYPES]; /* last sent this type */
......@@ -191,7 +275,15 @@ struct pp_instance {
unsigned long ptp_tx_count;
unsigned long ptp_rx_count;
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 */
Boolean ptp_msg_received; /* Use to detect reception of a ptp message after an ppsi instance initialization */
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 */
#define PPI_FLAG_WAITING_FOR_F_UP 0x02
#define PPI_FLAG_WAITING_FOR_RF_UP 0x04
......@@ -208,16 +300,14 @@ struct pp_globals_cfg {
struct pp_globals {
struct pp_instance *pp_instances;
struct pp_servo *servo;
/* Real time options */
struct pp_runtime_opts *rt_opts;
/* Data sets */
DSDefault *defaultDS; /* page 65 */
DSCurrent *currentDS; /* page 67 */
DSParent *parentDS; /* page 68 */
DSTimeProperties *timePropertiesDS; /* page 70 */
defaultDS_t *defaultDS; /* page 65 */
currentDS_t *currentDS; /* page 67 */
parentDS_t *parentDS; /* page 68 */
timePropertiesDS_t *timePropertiesDS; /* page 70 */
/* Index of the pp_instance receiving the "Ebest" clock */
int ebest_idx;
......@@ -231,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 */
};
......
#ifndef __PPSI_PP_TIME_H__
#define __PPSI_PP_TIME_H__
#define TIME_FRACBITS 16
#define TIME_FRACMASK 0xFFFF
#define TIME_FRACBITS_AS_FLOAT 16.0
#define TIME_ROUNDING_VALUE (1<<(TIME_FRACBITS-1))
/* Everything internally uses this time format, *signed* */
struct pp_time {
int64_t secs;
......
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_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_
......@@ -23,11 +23,11 @@ void ppsi_clear_bss(void)
}
/* ppg fields */
static DSDefault defaultDS;
static DSCurrent currentDS;
static DSParent parentDS;
static DSPort portDS;
static DSTimeProperties timePropertiesDS;
static defaultDS_t defaultDS;
static currentDS_t currentDS;
static [parentDS_t parentDS;
static portDS_t portDS;
static timePropertiesDS_t timePropertiesDS;
static struct pp_servo servo;
static struct pp_globals ppg_static; /* forward declaration */
......@@ -43,7 +43,7 @@ static struct pp_instance ppi_static = {
.port_name = "eth0",
.vlans_array_len = CONFIG_VLAN_ARRAY_SIZE,
.proto = PP_DEFAULT_PROTO,
.mech = CONFIG_HAS_P2P ? PP_P2P_MECH : PP_E2E_MECH,
.delayMechanism = CONFIG_HAS_P2P ? P2P : E2E,
.__tx_buffer = __tx_buffer,
.__rx_buffer = __rx_buffer,
};
......
......@@ -28,7 +28,7 @@ static struct cmd_line_opt cmd_line_list[] = {
{"-d STRING", "diagnostic level (see diag-macros.h)"},
CMD_LINE_SEPARATOR,
{"-t", "do not adjust the system clock"},
{"-w NUMBER", "specify meanPathDelay filter stiffness"},
{"-w NUMBER", "specify meanDelay filter stiffness"},
CMD_LINE_SEPARATOR,
//{"-u ADDRESS", "also send uni-cast to ADDRESS\n"}, -- FIXME: useful?
{"-g", "run as slave only"},
......@@ -53,7 +53,6 @@ static void cmd_line_print_help(void)
int pp_parse_cmdline(struct pp_globals *ppg, int argc, char **argv)
{
int i, err = 0;
int j;
char *a; /* cmd line argument */
for (i = 1; i < argc; i++) {
......@@ -90,13 +89,6 @@ int pp_parse_cmdline(struct pp_globals *ppg, int argc, char **argv)
a = argv[++i];
GOPTS(ppg)->s = atoi(a);
break;
case 'g':
GOPTS(ppg)->clock_quality.clockClass
= PP_CLASS_SLAVE_ONLY;
/* Apply -g option globally, to each configured link */
for (j = 0; j < ppg->nlinks; j++)
INST(ppg, j)->role = PPSI_ROLE_SLAVE;
break;
case 'h':
/* ignored: was "GOPTS(ppg)->e2e_mode = 1;" */
break;
......
This diff is collapsed.
/*
* 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
/*
* Copyright (C) 2011 CERN (www.cern.ch)
* Author: Jean-Claude BAU
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <ppsi/ppsi.h>
void normalize_pp_time(struct pp_time *t)
{
/* no 64b division please, we'll rather loop a few times */
#define SNS_PER_S ((1000LL * 1000 * 1000) << 16)
/* For whatever reason we perform a normalization on an incorrect
* timestamp, don't treat is as an negative value. */
int64_t sign = ((t->secs < 0 && !is_incorrect(t))
|| (t->secs == 0 && t->scaled_nsecs < 0))
? -1 : 1;
/* turn into positive, to make code shorter (don't replicate loops) */
t->secs *= sign;
t->scaled_nsecs *= sign;
while (t->scaled_nsecs < 0) {
t->secs--;
t->scaled_nsecs += SNS_PER_S;
}
while (t->scaled_nsecs > SNS_PER_S) {
t->secs++;
t->scaled_nsecs -= SNS_PER_S;
}
t->secs *= sign;
t->scaled_nsecs *= sign;
}
/* Add a TimeInterval to a pp_time */
void pp_time_add_interval(struct pp_time *t1, TimeInterval t2)
{
struct pp_time t = {
.secs=0,
.scaled_nsecs=t2
};
normalize_pp_time(&t);
pp_time_add(t1,&t);
}
/* Substract a TimeInterval to a pp_time */
void pp_time_sub_interval(struct pp_time *t1, TimeInterval t2)
{
struct pp_time t = {
.secs=0,
.scaled_nsecs=t2
};
normalize_pp_time(&t);
pp_time_sub(t1,&t);
}
#define IS_ADD_WILL_OVERFLOW(a,b) \
( (((a > 0) && (b > INT64_MAX - a))) ||\
(((a < 0) && (b < INT64_MIN - a))) \
)
void pp_time_add(struct pp_time *t1, struct pp_time *t2)
{
t1->secs += t2->secs;
t1->scaled_nsecs += t2->scaled_nsecs;
normalize_pp_time(t1);
}
#define IS_SUB_WILL_OVERFLOW(a,b) \
( ((b < 0) && (a > INT64_MAX + b)) ||\
((b > 0) && (a < INT64_MIN + b)) \
)
void pp_time_sub(struct pp_time *t1, struct pp_time *t2)
{
t1->secs -= t2->secs;
t1->scaled_nsecs -= t2->scaled_nsecs;
normalize_pp_time(t1);
}
void pp_time_div2(struct pp_time *t)
{
int sign = (t->secs < 0) ? -1 : 1;
t->scaled_nsecs >>= 1;
if (t->secs &1)
t->scaled_nsecs += sign * SNS_PER_S / 2;
t->secs >>= 1;
}
int64_t pp_time_to_picos(struct pp_time *ts)
{
return ts->secs * PP_PSEC_PER_SEC
+ ((ts->scaled_nsecs * 1000 + TIME_ROUNDING_VALUE) >> TIME_FRACBITS);
}
void fixedDelta_to_pp_time(struct FixedDelta fd, struct pp_time *t) {
/* FixedDelta is expressed in ps*2^16 */
uint64_t *v=(uint64_t*)&fd;
t->scaled_nsecs=*v/1000L; /* We can do it because scaled_nsecs is also multiply by 2^16 */
t->secs=0;
normalize_pp_time(t);
}
void picos_to_pp_time(int64_t picos, struct pp_time *ts)
{
uint64_t sec, nsec;
int sign = (picos < 0 ? -1 : 1);
picos *= sign;
sec=picos/PP_PSEC_PER_SEC;
picos-=sec*PP_PSEC_PER_SEC;
nsec = picos/1000;
picos%=1000;
ts->scaled_nsecs = nsec << TIME_FRACBITS;
ts->scaled_nsecs += ((picos << TIME_FRACBITS)+TIME_ROUNDING_VALUE) / 1000;
ts->scaled_nsecs *= sign;
ts->secs = sec * sign;
}
/* "Hardwarizes" the timestamp - e.g. makes the nanosecond field a multiple
* of 8/16ns cycles and puts the extra nanoseconds in the picos result */
void pp_time_hardwarize(struct pp_time *time, int clock_period_ps,
int32_t *ticks, int32_t *picos)
{
int64_t ps, adj_ps;
int32_t sign=(time->scaled_nsecs<0) ? -1 : 1;
int64_t scaled_nsecs=time->scaled_nsecs*sign;
if ( clock_period_ps <= 0 ) {
pp_error("%s : Invalid clock period %d\n",__func__, clock_period_ps);
return;
}
ps = (scaled_nsecs * 1000L+TIME_INTERVAL_ROUNDING_VALUE) >> TIME_INTERVAL_FRACBITS; /* now picoseconds 0..999 -- positive*/
adj_ps=ps - ps%clock_period_ps;
*picos=(int32_t)(ps-adj_ps)*sign;
*ticks = (int32_t)(adj_ps/1000)*sign;
}
TimeInterval pp_time_to_interval(struct pp_time *ts)
{
return ((ts->secs * PP_NSEC_PER_SEC)<<TIME_INTERVAL_FRACBITS) + ts->scaled_nsecs ;
}
TimeInterval picos_to_interval(int64_t picos)
{
if ( picos <= TIME_INTERVAL_MIN_PICOS_VALUE_AS_INT64) {
/* special case : Return the minimum value */
/* The evaluation is made at compilation time */
return (TimeInterval) 1<<(64-1); /* Maximum negative value */
}
if ( picos >= TIME_INTERVAL_MAX_PICOS_VALUE_AS_INT64 ) {
/* special case : Return the maximum */
/* The evaluation is made at compilation time */
return (TimeInterval) (((TIME_INTERVAL_MAX_PICOS_VALUE_AS_INT64/1000) << TIME_INTERVAL_FRACBITS)|
(((TIME_INTERVAL_MAX_PICOS_VALUE_AS_INT64%1000) << TIME_INTERVAL_FRACBITS)/1000));
} else {
int64_t scaled_ns;
int sign = (picos < 0 ? -1 : 1);
picos *= sign;
scaled_ns=(picos/1000) << TIME_INTERVAL_FRACBITS; /* Calculate nanos */
scaled_ns+=(((picos%1000) << TIME_INTERVAL_FRACBITS) + TIME_INTERVAL_ROUNDING_VALUE)/1000; /* Add picos */
return scaled_ns*sign;
}
}
int64_t interval_to_picos(TimeInterval interval)
{
return (interval * 1000) >> TIME_INTERVAL_FRACBITS;
}
/*
* Check the timestamps (t1 to t6).
* err_count is a counter to avoid printing the first time the error messages
* ts_mask is the mask of the timestamps to check.
* Returns 1 if a timestamp is incorrect otherwise 0.
*/
int is_timestamps_incorrect(struct pp_instance *ppsi, int *err_count, int ts_mask) {
static int ts_ppsi_offset[6]={
offsetof(struct pp_instance,t1),
offsetof(struct pp_instance,t2),
offsetof(struct pp_instance,t3),
offsetof(struct pp_instance,t4),
offsetof(struct pp_instance,t5),
offsetof(struct pp_instance,t6)
};
int mask=1,i,local_err_count;
if ( err_count==NULL ) {
/* Optimize the execution of the next code avoiding checking err_count at each step */
err_count=&local_err_count;
local_err_count=5; /* Force printing immediately if a timestamp is incorrect */
}
for ( i=0; i<6 && ts_mask; i++ ) { // Check up to 6 timestamps
if ( mask & ts_mask ) {
struct pp_time *ts=(void *) ppsi + ts_ppsi_offset[i] ;
if ( is_incorrect(ts) ) {
if ( (*err_count)++ > 5 ) {
pp_error("%s: t%d is incorrect\n",__func__,i+1);
}
return 1;
}
}
ts_mask &=~mask;
mask<<=1;
}
return *err_count=0;
}
static char time_as_string[32];
/* Convert pp_time to string */
char *time_to_string(struct pp_time *t)
{
struct pp_time time=*t;
int picos;
char *sign;
if (t->secs < 0 || (t->secs == 0 && t->scaled_nsecs < 0) ) {
sign="-";
time.scaled_nsecs=-t->scaled_nsecs;
time.secs=-t->secs;
} else {
sign="";
time=*t;
}
picos=((int)(time.scaled_nsecs&TIME_FRACMASK)*1000+TIME_ROUNDING_VALUE)>>TIME_FRACBITS;
pp_sprintf(time_as_string, "%s%d.%09d%03d",
sign,
(int)time.secs,
(int)(time.scaled_nsecs >> TIME_FRACBITS),
picos);
return time_as_string;
}
/* Convert TimeInterval to string */
char *interval_to_string(TimeInterval time)
{
int64_t sign,nanos,picos;
if ( time<0 && time !=INT64_MIN) {
sign=-1;
time=-time;
} else {
sign=1;
}
nanos = time >> TIME_INTERVAL_FRACBITS;
picos = (((time & TIME_INTERVAL_FRACMASK) * 1000) + TIME_INTERVAL_ROUNDING_VALUE ) >> TIME_INTERVAL_FRACBITS;
sprintf(time_as_string,"%" PRId64 ".%03" PRId64, sign*nanos,picos);
return time_as_string;
}
/* Convert RelativeInterval to string */
char *relative_interval_to_string(TimeInterval time) {
int32_t nsecs=time >> REL_DIFF_FRACBITS;
uint64_t sub_yocto=0;
int64_t fraction;
uint64_t bitWeight=500000000000000000;
uint64_t mask;
fraction=time & REL_DIFF_FRACMASK;
for (mask=(uint64_t) 1<< (REL_DIFF_FRACBITS-1);mask!=0; mask>>=1 ) {
if ( mask & fraction )
sub_yocto+=bitWeight;
bitWeight/=2;
}
sprintf(time_as_string,"%"PRId32".%018"PRIu64, nsecs, sub_yocto);
return time_as_string;
}
......@@ -6,33 +6,50 @@
* the numeric 0..5 is the "controlField" (magic ptpV1 numbers in byte 32).
* PP_LOG is the kind of logInterval to put in byte 33.
*/
struct pp_msgtype_info pp_msgtype_info[16] = {
[PPM_SYNC] = {
"sync", PP_SYNC_LENGTH,
struct pp_msgtype_info pp_msgtype_info[] = {
[PPM_SYNC_FMT] = {
PPM_SYNC, PP_SYNC_LENGTH,
PP_NP_EVT, PP_E2E_MECH, 0, PP_LOG_SYNC },
[PPM_DELAY_REQ] = {
"delay_req", PP_DELAY_REQ_LENGTH,
[PPM_DELAY_REQ_FMT] = {
PPM_DELAY_REQ, PP_DELAY_REQ_LENGTH,
PP_NP_EVT, PP_E2E_MECH, 1, 0x7f },
[PPM_PDELAY_REQ] = {
"pdelay_req", PP_PDELAY_REQ_LENGTH,
[PPM_PDELAY_REQ_FMT] = {
PPM_PDELAY_REQ,PP_PDELAY_REQ_LENGTH,
PP_NP_EVT, PP_P2P_MECH, 5, 0x7f },
[PPM_PDELAY_RESP] = {
"pdelay_resp", PP_PDELAY_RESP_LENGTH,
[PPM_PDELAY_RESP_FMT] = {
PPM_PDELAY_RESP, PP_PDELAY_RESP_LENGTH,
PP_NP_EVT, PP_P2P_MECH, 5, 0x7f },
[PPM_FOLLOW_UP] = {
"follow_up", PP_FOLLOW_UP_LENGTH,
[PPM_FOLLOW_UP_FMT] = {
PPM_FOLLOW_UP, PP_FOLLOW_UP_LENGTH,
PP_NP_GEN, PP_E2E_MECH, 2, PP_LOG_SYNC },
[PPM_DELAY_RESP] = {
"delay_resp", PP_DELAY_RESP_LENGTH,
[PPM_DELAY_RESP_FMT] = {
PPM_DELAY_RESP, PP_DELAY_RESP_LENGTH,
PP_NP_GEN, PP_E2E_MECH, 3, PP_LOG_REQUEST },
[PPM_PDELAY_R_FUP] = {
"pdelay_resp_follow_up", PP_PDELAY_RESP_FOLLOW_UP_LENGTH,
[PPM_PDELAY_R_FUP_FMT] = {
PPM_PDELAY_R_FUP, PP_PDELAY_RESP_FOLLOW_UP_LENGTH,
PP_NP_GEN, PP_P2P_MECH, 5, 0x7f },
[PPM_ANNOUNCE] = {
"announce", PP_ANNOUNCE_LENGTH,
[PPM_ANNOUNCE_FMT] = {
PPM_ANNOUNCE, PP_ANNOUNCE_LENGTH,
PP_NP_GEN, PP_E2E_MECH, 5, PP_LOG_ANNOUNCE},
/* We don't use signaling and management, or not in the table-driven code */
[PPM_SIGNALING] = { "signaling", -1, PP_NP_GEN, PP_E2E_MECH, 5, 0x7f},
[PPM_MANAGEMENT] = { "management", -1, PP_NP_GEN, PP_E2E_MECH, 4, 0x7f},
[PPM_SIGNALING_FMT] = {
PPM_SIGNALING, -1,
PP_NP_GEN, PP_E2E_MECH, 5, 0x7f},
[PPM_SIGNALING_NO_FWD_FMT] = {
PPM_SIGNALING, -1,
PP_NP_GEN, PP_P2P_MECH, 5, 0x7f},
/* We don't use management, or not in the table-driven code */
[PPM_MANAGEMENT_FMT] = { PPM_MANAGEMENT, -1, PP_NP_GEN, PP_E2E_MECH, 4, 0x7f},
};
char *pp_msgtype_name[] = {
[PPM_SYNC] = "sync",
[PPM_DELAY_REQ] = "delay_req",
[PPM_PDELAY_REQ] = "pdelay_req",
[PPM_PDELAY_RESP] ="pdelay_resp",
[PPM_FOLLOW_UP] = "follow_up",
[PPM_DELAY_RESP] ="delay_resp",
[PPM_PDELAY_R_FUP] ="pdelay_resp_follow_up",
[PPM_ANNOUNCE] ="announce",
[PPM_SIGNALING] ="signaling",
[PPM_MANAGEMENT] ="management"
};
......@@ -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
......
D := proto-ext-common
INC_WRH_SERVO=$(shell test ".$(CONFIG_HAS_EXT_WR)" = ".1" -o \
".$(CONFIG_HAS_EXT_L1SYNC)" = ".1" \
&& echo -n "true")
ifeq ($(INC_WRH_SERVO),true)
OBJ-y += $D/wrh-servo.o
endif
This diff is collapsed.
# All files are under directory D: I'm lazy
D := proto-ext-l1sync
OBJ-y += $D/l1e-hooks.o \
$D/l1e-msg.o\
$D/l1e-state-machine.o
This diff is collapsed.
/*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Jean-Claude BAU & Maciej Lipinski
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#ifndef __L1SYNC_EXT_CONSTANTS_H__
#define __L1SYNC_EXT_CONSTANTS_H__
#endif /* __L1SYNC_EXT_CONSTANTS_H__ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -13,7 +13,9 @@ OBJ-y += $D/fsm-table.o \
$D/state-wr-calibrated.o \
$D/state-wr-resp-calib-req.o \
$D/state-wr-link-on.o \
$D/state-wr-idle.o \
$D/wr-msg.o \
$D/wr-servo.o
$D/wr-servo.o \
$D/wr-state-machine.o
OBJ-$(CONFIG_ABSCAL) += $D/state-wr-abscal.o
......@@ -5,32 +5,20 @@
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
/* We are entering WR handshake, as either master or slave */
void wr_handshake_init(struct pp_instance *ppi, int mode_or_retry)
{
void wr_reset_process(struct pp_instance *ppi, wr_role_t role) {
struct wr_dsport *wrp = WR_DSPOR(ppi);
switch(mode_or_retry) {
case PPS_MASTER:
wrp->wrMode = WR_MASTER;
ppi->next_state = WRS_M_LOCK;
break;
case PPS_SLAVE:
wrp->wrMode = WR_SLAVE;
ppi->next_state = WRS_PRESENT;
break;
default: /* retry: only called from below in this file */
if (wrp->wrMode == WR_MASTER)
ppi->next_state = WRS_M_LOCK;
else
ppi->next_state = WRS_PRESENT;
break;
}
wrp->wrStateTimeout = WR_DEFAULT_STATE_TIMEOUT_MS;
wrp->calPeriod = WR_DEFAULT_CAL_PERIOD;
wrp->wrMode = role;
wrp->wrModeOn=FALSE;
wrp->calibrated = !WR_DEFAULT_PHY_CALIBRATION_REQUIRED;
/* Reset parent data */
wrp->parentWrConfig = NON_WR;
wrp->parentIsWRnode =
wrp->parentWrModeOn =
wrp->parentCalibrated = FALSE;
}
/* The handshake failed: go master or slave in normal PTP mode */
......@@ -40,11 +28,10 @@ void wr_handshake_fail(struct pp_instance *ppi)
pp_diag(ppi, ext, 1, "Handshake failure: now non-wr %s\n",
wrp->wrMode == WR_MASTER ? "master" : "slave");
if (wrp->wrMode == WR_MASTER)
ppi->next_state = PPS_MASTER;
else
ppi->next_state = PPS_SLAVE;
wrp->wrMode = NON_WR;
wrp->next_state=WRS_IDLE;
wr_reset_process(ppi,WR_ROLE_NONE);
wr_servo_reset(ppi);
lstate_set_link_perror(ppi);
}
......
......@@ -6,12 +6,12 @@
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
/*
* This is the WR state machine table.
*/
#if 0
struct pp_state_table_item pp_state_table[] = {
{ PPS_INITIALIZING, "initializing", pp_initializing,},
{ PPS_FAULTY, "faulty", pp_faulty,},
......@@ -35,3 +35,4 @@ struct pp_state_table_item pp_state_table[] = {
#endif
{ PPS_END_OF_TABLE,}
};
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -13,9 +13,10 @@ OBJ-y += $D/fsm-table.o \
$D/state-passive.o \
$D/state-slave.o \
$D/common-fun.o \
$D/common-fun-p2p.o \
$D/bmc.o \
$D/msg.o \
$D/arith.o \
$D/msg-p2p.o \
$D/servo.o \
$D/hooks.o \
$D/open-close.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#include <ppsi/ppsi.h>
/* proto-standard offers all-null hooks as a default extension */
struct pp_ext_hooks __attribute__((weak)) 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
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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