Commit 5d9b4c65 authored by Adam Wujek's avatar Adam Wujek

arch-unix: fix architecture

Signed-off-by: 's avatarAdam Wujek <dev_public@wujek.eu>
parent c3672fd9
......@@ -4,6 +4,9 @@ A := arch-$(ARCH)
CFLAGS += -Itools
# needed for --gc-sections option of ld
PPSI_O_LDFLAGS = --entry=main
OBJ-y += $A/unix-startup.o \
$A/main-loop.o \
$A/unix-io.o \
......@@ -14,7 +17,8 @@ OBJ-y += $A/unix-startup.o \
lib/dump-funcs.o \
lib/drop.o \
lib/assert.o \
lib/div64.o
lib/div64.o \
lib/time-arith.o
# The user can set TIME=, but we pick unix time by default
TIME ?= unix
......
/*
* Copyright (C) 2011 CERN (www.cern.ch)
* Copyright (C) 2011-2022 CERN (www.cern.ch)
* Author: Alessandro Rubini
*
* Released to the public domain
......@@ -24,8 +24,26 @@ static int run_all_state_machines(struct pp_globals *ppg)
int j;
int delay_ms = 0, delay_ms_j;
/* TODO: check if in GM mode and initialized */
for (j = 0; j < ppg->nlinks; j++) {
struct pp_instance *ppi = INST(ppg, j);
int old_lu = ppi->link_up;
/* TODO: add the proper discovery of link_up */
ppi->link_up = 1;
if (old_lu != ppi->link_up) {
pp_diag(ppi, fsm, 1, "iface %s went %s\n",
ppi->iface_name, ppi->link_up ? "up" : "down");
if (ppi->link_up) {
ppi->state = PPS_INITIALIZING;
/* TODO: Get calibration values here */
}
}
delay_ms_j = pp_state_machine(ppi, NULL, 0);
/* delay_ms is the least delay_ms among all instances */
......@@ -35,6 +53,22 @@ 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)) {
/* Calculation of erbest, ebest, ... */
bmc_calculate_ebest(ppg);
pp_gtimeout_reset(ppg, PP_TO_BMC);
delay_ms = 0;
/* TODO: Check PLL state if needed/available */
} 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;
}
......@@ -48,8 +82,6 @@ void unix_main_loop(struct pp_globals *ppg)
for (j = 0; j < ppg->nlinks; j++) {
ppi = INST(ppg, j);
/* just tell that the links are up */
ppi->link_up = TRUE;
/*
* The main loop here is based on select. While we are not
......@@ -62,32 +94,14 @@ void unix_main_loop(struct pp_globals *ppg)
delay_ms = run_all_state_machines(ppg);
while (1) {
int i;
/*
* If Ebest was changed in previous loop, run best
* master clock before checking for new packets, which
* would affect port state again
*/
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;
}
int packet_available;
i = unix_net_ops.check_packet(ppg, delay_ms);
packet_available = unix_net_ops.check_packet(ppg, delay_ms);
if (i < 0)
if (packet_available < 0)
continue;
if (i == 0) {
if (packet_available == 0) {
delay_ms = run_all_state_machines(ppg);
continue;
}
......@@ -99,7 +113,7 @@ void unix_main_loop(struct pp_globals *ppg)
delay_ms = -1;
for (j = 0; j < ppg->nlinks; j++) {
int tmp_d;
int tmp_d, i;
ppi = INST(ppg, j);
if ((ppi->ch[PP_NP_GEN].pkt_present) ||
......
/*
* Copyright (C) 2011 CERN (www.cern.ch)
* Copyright (C) 2011-2022 CERN (www.cern.ch)
* Author: Alessandro Rubini
*
* Released to the public domain
......@@ -23,16 +23,36 @@
#include <ppsi/ppsi.h>
#include "ppsi-unix.h"
char *format_hex(char *s, const unsigned char *mac, int cnt);
char *format_hex8(char *s, const unsigned char *mac);
/* ppg and fields */
static struct pp_globals ppg_static;
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;
/**
* Enable/disable asymmetry correction
*/
static void enable_asymmetryCorrection(struct pp_instance *ppi, Boolean enable ) {
if ((ppi->asymmetryCorrectionPortDS.enable = enable) == TRUE ) {
/* Enabled: The delay asymmetry will be calculated */
ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient =
(ppi->cfg.scaledDelayCoefficient != 0) ?
ppi->cfg.scaledDelayCoefficient :
(RelativeDifference)(ppi->cfg.delayCoefficient * REL_DIFF_TWO_POW_FRACBITS);
ppi->portDS->delayAsymCoeff =
pp_servo_calculateDelayAsymCoefficient(ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient);
}
ppi->asymmetryCorrectionPortDS.constantAsymmetry =
picos_to_interval(ppi->cfg.constantAsymmetry_ps);
}
int main(int argc, char **argv)
{
struct pp_globals *ppg;
......@@ -45,12 +65,20 @@ int main(int argc, char **argv)
pp_printf("PPSi. Commit %s, built on " __DATE__ "\n", PPSI_VERSION);
/* So far allow more than one instance of PPSi running on the same
* machine.
TODO: to be considered to allow only one instance of PPSi to run
* at the same time.
* Potential problems my be in:
* shmem (not used in arch-unix)
* race of setting of time if more than one instance run as slave
*/
ppg = &ppg_static;
ppg->defaultDS = &defaultDS;
ppg->currentDS = &currentDS;
ppg->parentDS = &parentDS;
ppg->timePropertiesDS = &timePropertiesDS;
ppg->servo = &servo;
ppg->rt_opts = &__pp_default_rt_opts;
/* We are hosted, so we can allocate */
......@@ -63,17 +91,17 @@ int main(int argc, char **argv)
exit(1);
}
/* Before the configuration is parsed, set defaults */
/* Set default configuration value for all instances */
for (i = 0; i < ppg->max_links; i++) {
ppi = INST(ppg, i);
ppi->proto = PP_DEFAULT_PROTO;
ppi->role = PP_DEFAULT_ROLE;
ppi->delayMechanism = MECH_E2E;
memcpy(&INST(ppg, i)->cfg, &__pp_default_instance_cfg,
sizeof(__pp_default_instance_cfg));
}
/* Set offset here, so config parsing can override it */
if (adjtimex(&t) >= 0)
timePropertiesDS.currentUtcOffset = t.tai;
memset(&t, 0, sizeof(t));
if (adjtimex(&t) >= 0) {
ppg->timePropertiesDS->currentUtcOffset = (Integer16)t.tai;
}
if (pp_parse_cmdline(ppg, argc, argv) != 0)
return -1;
......@@ -81,6 +109,8 @@ int main(int argc, char **argv)
/* If no item has been parsed, provide a default file or string */
if (ppg->cfg.cfg_items == 0)
pp_config_file(ppg, 0, PP_DEFAULT_CONFIGFILE);
/* No config found, add default */
if (ppg->cfg.cfg_items == 0)
pp_config_string(ppg, strdup("link 0; iface eth0; proto udp"));
......@@ -95,21 +125,113 @@ int main(int argc, char **argv)
ppi->iface_name = ppi->cfg.iface_name;
ppi->port_name = ppi->cfg.port_name;
ppi->delayMechanism = ppi->cfg.delayMechanism;
ppi->ext_hooks= &pp_hooks;
ppi->portDS = calloc(1, sizeof(*ppi->portDS));
ppi->servo = calloc(1, sizeof(*ppi->servo));
ppi->ext_hooks = &pp_hooks;
ppi->ptp_support = TRUE;
if (ppi->portDS) {
switch (ppi->cfg.profile) {
case PPSI_PROFILE_WR:
#if CONFIG_HAS_PROFILE_WR
ppi->protocol_extension = PPSI_EXT_WR;
/* Add WR extension portDS */
if ( !(ppi->portDS->ext_dsport =
wrs_shm_alloc(ppsi_head,
sizeof(struct wr_dsport))
)
) {
goto exit_out_of_memory;
}
/* Allocate WR data extension */
if (! (ppi->ext_data =
wrs_shm_alloc(ppsi_head,
sizeof(struct wr_data))
)
) {
goto exit_out_of_memory;
}
/* Set WR extension hooks */
ppi->ext_hooks = &wr_ext_hooks;
enable_asymmetryCorrection(ppi, TRUE);
#else
fprintf(stderr, "ppsi: Profile WR not supported");
exit(1);
#endif
break;
case PPSI_PROFILE_HA:
#if CONFIG_HAS_PROFILE_HA
if (!enable_l1Sync(ppi, TRUE))
goto exit_out_of_memory;
/* Force mandatory attributes - Do not take care of the configuration */
L1E_DSPOR_BS(ppi)->rxCoherentIsRequired = TRUE;
L1E_DSPOR_BS(ppi)->txCoherentIsRequired = TRUE;
L1E_DSPOR_BS(ppi)->congruentIsRequired = TRUE;
L1E_DSPOR_BS(ppi)->L1SyncEnabled = TRUE;
L1E_DSPOR_BS(ppi)->optParamsEnabled = FALSE;
enable_asymmetryCorrection(ppi, TRUE);
#else
fprintf(stderr, "ppsi: Profile HA not supported");
exit(1);
#endif
break;
case PPSI_PROFILE_PTP :
/* Do not take care of L1SYNC */
enable_asymmetryCorrection(ppi,
ppi->cfg.asymmetryCorrectionEnable);
ppi->protocol_extension = PPSI_EXT_NONE;
break;
case PPSI_PROFILE_CUSTOM :
#if CONFIG_HAS_PROFILE_CUSTOM
ppi->protocol_extension = PPSI_EXT_NONE; /* can be changed ...*/
#if CONFIG_HAS_EXT_L1SYNC
if (ppi->cfg.l1SyncEnabled) {
if (!enable_l1Sync(ppi, TRUE))
goto exit_out_of_memory;
/* Read L1SYNC parameters */
L1E_DSPOR_BS(ppi)->rxCoherentIsRequired = ppi->cfg.l1SyncRxCoherencyIsRequired;
L1E_DSPOR_BS(ppi)->txCoherentIsRequired = ppi->cfg.l1SyncTxCoherencyIsRequired;
L1E_DSPOR_BS(ppi)->congruentIsRequired = ppi->cfg.l1SyncCongruencyIsRequired;
L1E_DSPOR_BS(ppi)->optParamsEnabled = ppi->cfg.l1SyncOptParamsEnabled;
if (L1E_DSPOR_BS(ppi)->optParamsEnabled) {
L1E_DSPOR_OP(ppi)->timestampsCorrectedTx = ppi->cfg.l1SyncOptParamsTimestampsCorrectedTx;
}
}
enable_asymmetryCorrection(ppi, ppi->cfg.asymmetryCorrectionEnable);
#endif
#else
fprintf(stderr, "ppsi: Profile CUSTOM not supported");
exit(1);
#endif
break;
}
/* Parameters profile independent */
ppi->timestampCorrectionPortDS.egressLatency = picos_to_interval(ppi->cfg.egressLatency_ps);
ppi->timestampCorrectionPortDS.ingressLatency = picos_to_interval(ppi->cfg.ingressLatency_ps);
ppi->timestampCorrectionPortDS.messageTimestampPointLatency = 0;
ppi->portDS->masterOnly = ppi->cfg.masterOnly; /* can be overridden in pp_init_globals() */
} else {
goto exit_out_of_memory;
}
/* The following default names depend on TIME= at build time */
ppi->n_ops = &DEFAULT_NET_OPS;
ppi->t_ops = &DEFAULT_TIME_OPS;
ppi->portDS = calloc(1, sizeof(*ppi->portDS));
ppi->__tx_buffer = malloc(PP_MAX_FRAME_LENGTH);
ppi->__rx_buffer = malloc(PP_MAX_FRAME_LENGTH);
if (!ppi->portDS || !ppi->__tx_buffer || !ppi->__rx_buffer) {
fprintf(stderr, "ppsi: out of memory\n");
exit(1);
goto exit_out_of_memory;
}
}
pp_init_globals(ppg, &__pp_default_rt_opts);
seed = time(NULL);
......@@ -119,4 +241,32 @@ int main(int argc, char **argv)
unix_main_loop(ppg);
return 0; /* never reached */
exit_out_of_memory:
fprintf(stderr, "ppsi: out of memory\n");
exit(1);
}
char *format_hex(char *s, const unsigned char *mac, int cnt)
{
int i;
*s = '\0';
for (i = 0; i < cnt; i++) {
pp_sprintf(s, "%s%02x:", s, mac[i]);
}
/* remove last colon */
s[cnt * 3 - 1] = '\0'; /* cnt * strlen("FF:") - 1 */
return s;
}
char *format_hex8(char *s, const unsigned char *mac)
{
return format_hex(s, mac, 8);
}
char *format_mac(char *s, const unsigned char *mac)
{
format_hex(s, mac, 6);
return s;
}
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