Commit 8044c8cc authored by Jean-Claude BAU's avatar Jean-Claude BAU Committed by Adam Wujek

High accuracy implementation - First version

- Upgrade HAL to transmit the bit-slide to HA
- Upgrade wr_mon tool to displat HA servo data
- Upgrade wrs_dump_shmem to display the right data
Conflicts:
	userspace/tools/wr_mon.c
	userspace/tools/wrs_dump_shmem.c
parent cbd4366e
...@@ -39,6 +39,9 @@ typedef struct hal_port_calibration { ...@@ -39,6 +39,9 @@ typedef struct hal_port_calibration {
uint32_t delta_tx_phy; uint32_t delta_tx_phy;
uint32_t delta_rx_phy; uint32_t delta_rx_phy;
/* bit slide expresse in picos */
uint32_t bitslide_ps;
/* Current board routing delays (between the DDMTD inputs to /* Current board routing delays (between the DDMTD inputs to
the PHY clock inputs/outputs), in picoseconds */ the PHY clock inputs/outputs), in picoseconds */
uint32_t delta_tx_board; uint32_t delta_tx_board;
......
This diff is collapsed.
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <inttypes.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <libwr/shmem.h> #include <libwr/shmem.h>
#include <libwr/hal_shmem.h> #include <libwr/hal_shmem.h>
...@@ -76,10 +77,13 @@ void dump_one_field(void *addr, struct dump_info *info) ...@@ -76,10 +77,13 @@ void dump_one_field(void *addr, struct dump_info *info)
{ {
void *p = addr + info->offset; void *p = addr + info->offset;
struct pp_time *t = p; struct pp_time *t = p;
RelativeDifference *rd=p;
Timestamp *ts=p;
TimeInterval *ti=p;
struct PortIdentity *pi = p; struct PortIdentity *pi = p;
struct ClockQuality *cq = p; struct ClockQuality *cq = p;
char format[16]; char format[16];
long nano, pico; uint64_t sec, nano, pico;
int i; int i;
printf(" %-30s ", info->name); /* name includes trailing ':' */ printf(" %-30s ", info->name); /* name includes trailing ':' */
...@@ -108,6 +112,7 @@ void dump_one_field(void *addr, struct dump_info *info) ...@@ -108,6 +112,7 @@ void dump_one_field(void *addr, struct dump_info *info)
case dump_type_uint64_t: case dump_type_uint64_t:
printf("%lld\n", *(unsigned long long *)p); printf("%lld\n", *(unsigned long long *)p);
break; break;
case dump_type_long_long:
case dump_type_Integer64: case dump_type_Integer64:
printf("%lld\n", *(long long *)p); printf("%lld\n", *(long long *)p);
break; break;
...@@ -146,14 +151,43 @@ void dump_one_field(void *addr, struct dump_info *info) ...@@ -146,14 +151,43 @@ void dump_one_field(void *addr, struct dump_info *info)
case dump_type_Integer16: case dump_type_Integer16:
printf("%i\n", *(short *)p); printf("%i\n", *(short *)p);
break; break;
#define TIME_FRACBITS 16
#define TIME_FRACMASK 0xFFFF
case dump_type_time: case dump_type_time:
nano = t->scaled_nsecs >> 16; nano = t->scaled_nsecs >> TIME_FRACBITS;
pico = t->scaled_nsecs & 0xffff; pico = t->scaled_nsecs & TIME_FRACMASK;
pico = (pico * 1000) >> 16; pico = (pico * 1000) >> TIME_FRACBITS;
printf("correct %i: %10lli.%09li.%03li\n", printf("correct %i: %10lli.%09"PRIu64".%03"PRIu64"\n",
!is_incorrect(t), t->secs, nano,pico); !is_incorrect(t), t->secs, nano,pico);
break; break;
case dump_type_Timestamp:
sec=(ts->secondsField.msb << sizeof(ts->secondsField.msb)) + ts->secondsField.lsb;
printf("%10"PRIu64".%09"PRIu32".000\n",
sec, (uint32_t)ts->nanosecondsField);
break;
#define TIME_INTERVAL_FRACBITS 16
#define TIME_INTERVAL_FRACMASK 0xFFFF
case dump_type_TimeInterval:
nano = *ti >> TIME_INTERVAL_FRACBITS;
pico = *ti & TIME_INTERVAL_FRACMASK;
pico = (pico * 1000) >> TIME_INTERVAL_FRACBITS;
printf("%09"PRIu64".%03"PRIu64"\n", nano,pico);
break;
#define REL_DIFF_FRACBITS 62
#define REL_DIFF_FRACMASK 0x3fffffffffffffff
case dump_type_RelativeDifference:
nano = *rd >> REL_DIFF_FRACBITS;
pico = *rd & REL_DIFF_FRACMASK;
pico = (pico * 1000L) >> REL_DIFF_FRACBITS;
printf("%01"PRIu64".%03"PRIu64"\n", nano,pico);
break;
case dump_type_ip_address: case dump_type_ip_address:
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
printf("%02x%c", ((unsigned char *)p)[i], printf("%02x%c", ((unsigned char *)p)[i],
...@@ -305,6 +339,7 @@ void dump_one_field(void *addr, struct dump_info *info) ...@@ -305,6 +339,7 @@ void dump_one_field(void *addr, struct dump_info *info)
break; break;
} }
} }
void dump_many_fields(void *addr, struct dump_info *info, int ninfo) void dump_many_fields(void *addr, struct dump_info *info, int ninfo)
{ {
int i; int i;
......
...@@ -28,7 +28,7 @@ int halexp_lock_cmd(const char *port_name, int command, int priority) ...@@ -28,7 +28,7 @@ int halexp_lock_cmd(const char *port_name, int command, int priority)
{ {
int rval; int rval;
pr_debug("halexp_lock_cmd: cmd=%d port=%s\n", command, port_name); /* pr_debug("halexp_lock_cmd: cmd=%d port=%s\n", command, port_name); */
switch (command) { switch (command) {
case HEXP_LOCK_CMD_ENABLE_TRACKING: case HEXP_LOCK_CMD_ENABLE_TRACKING:
...@@ -80,6 +80,7 @@ int halexp_pps_cmd(int cmd, hexp_pps_params_t * params) ...@@ -80,6 +80,7 @@ int halexp_pps_cmd(int cmd, hexp_pps_params_t * params)
{ {
int busy; int busy;
pr_debug("halexp_pps_cmd: cmd=%d\n", cmd);
switch (cmd) { switch (cmd) {
/* fixme: TODO: implement HEXP_PPSG_CMD_GET call */ /* fixme: TODO: implement HEXP_PPSG_CMD_GET call */
......
...@@ -37,6 +37,14 @@ ...@@ -37,6 +37,14 @@
#define UPDATE_LINK_LEDS_PERIOD 500 /* ms */ #define UPDATE_LINK_LEDS_PERIOD 500 /* ms */
#define UPDATE_SFP_DOM_PERIOD 1000 /* ms */ #define UPDATE_SFP_DOM_PERIOD 1000 /* ms */
typedef struct {
struct pp_instance * ppi; /* pointer to the ppi instance */
struct pp_servo servo_snapshot; /* image of a the ppsi servo */
} inst_servo_t ;
static inst_servo_t servo;
struct pp_servo *ppsi_servo;
extern struct hal_shmem_header *hal_shmem; extern struct hal_shmem_header *hal_shmem;
extern struct wrs_shm_head *hal_shmem_hdr; extern struct wrs_shm_head *hal_shmem_hdr;
...@@ -56,8 +64,7 @@ static timeout_t update_sync_leds_tmo, update_link_leds_tmo; ...@@ -56,8 +64,7 @@ static timeout_t update_sync_leds_tmo, update_link_leds_tmo;
static timeout_t update_sfp_dom_tmo; static timeout_t update_sfp_dom_tmo;
static int hal_port_nports; static int hal_port_nports;
static struct wr_servo_state *ppsi_servo; static struct pp_globals *ppg;
static struct wr_servo_state ppsi_servo_local;
static struct pp_instance *ppsi_instances; static struct pp_instance *ppsi_instances;
static struct pp_instance ppsi_instances_local[PP_MAX_LINKS]; static struct pp_instance ppsi_instances_local[PP_MAX_LINKS];
static struct wrs_shm_head *ppsi_head; static struct wrs_shm_head *ppsi_head;
...@@ -426,14 +433,17 @@ static void hal_port_fsm(struct hal_port_state * p) ...@@ -426,14 +433,17 @@ static void hal_port_fsm(struct hal_port_state * p)
case HAL_PORT_STATE_RESET: case HAL_PORT_STATE_RESET:
{ {
if (link_up) { if (link_up) {
uint32_t bit_slide_steps;
p->calib.tx_calibrated = 1; p->calib.tx_calibrated = 1;
p->calib.rx_calibrated = 1; p->calib.rx_calibrated = 1;
/* FIXME: use proper register names */ /* FIXME: use proper register names */
pr_info("Bitslide: %d\n", bit_slide_steps=(pcs_readl(p, 16) >> 4) & 0x1f;
((pcs_readl(p, 16) >> 4) & 0x1f)); p->calib.bitslide_ps=bit_slide_steps*800; /* 1 step = 800ps */
pr_info("Bitslide: %d\n",bit_slide_steps);
p->calib.delta_rx_phy = p->calib.delta_rx_phy =
p->calib.phy_rx_min + p->calib.phy_rx_min + p->calib.bitslide_ps;
((pcs_readl(p, 16) >> 4) & 0x1f) * 800;
p->calib.delta_tx_phy = p->calib.phy_tx_min; p->calib.delta_tx_phy = p->calib.phy_tx_min;
if (0) if (0)
...@@ -921,15 +931,19 @@ static void update_sync_leds(void) ...@@ -921,15 +931,19 @@ static void update_sync_leds(void)
int i; int i;
static uint32_t update_count = 0; static uint32_t update_count = 0;
static uint32_t since_last_servo_update = 0; static uint32_t since_last_servo_update = 0;
char *iface_name;
/* read servo */ /* read servo */
if (read_servo()) if (read_servo())
return; return;
if (!strnlen(ppsi_servo_local.if_name, 16)) iface_name=servo.ppi->cfg.iface_name;
if (!strnlen(iface_name, 16))
return; return;
for (i = 0; i < HAL_MAX_PORTS; i++) { for (i = 0; i < HAL_MAX_PORTS; i++) {
int ledValue;
/* Check: /* Check:
* --port in use * --port in use
* --link is up * --link is up
...@@ -939,53 +953,68 @@ static void update_sync_leds(void) ...@@ -939,53 +953,68 @@ static void update_sync_leds(void)
*/ */
if (ports[i].in_use if (ports[i].in_use
&& state_up(ports[i].state) && state_up(ports[i].state)
&& !strcmp(ppsi_servo_local.if_name, ports[i].name)) { && !strcmp(iface_name, ports[i].name)) {
if (update_count == ppsi_servo_local.update_count) { if (update_count == servo.servo_snapshot.update_count) {
if (since_last_servo_update < 7) if (since_last_servo_update < 7)
since_last_servo_update++; since_last_servo_update++;
} else { } else {
since_last_servo_update = 0; since_last_servo_update = 0;
update_count = ppsi_servo_local.update_count; update_count = servo.servo_snapshot.update_count;
} }
/* Check: /* Check:
* --port in slave mode * --port in slave mode
* --servo is in track phase * --servo is locked
* --not the standard PTP servo
* --servo is updating * --servo is updating
*/ */
if (ports[i].mode == HEXP_PORT_MODE_WR_SLAVE ledValue=(ports[i].mode == HEXP_PORT_MODE_WR_SLAVE
&& ppsi_servo_local.state == WR_TRACK_PHASE && servo.servo_snapshot.servo_locked
&& servo.ppi->protocol_extension != PPSI_EXT_NONE
&& since_last_servo_update < 7 && since_last_servo_update < 7
) { ) ? 1 : 0;
set_led_synced(i, 1); set_led_synced(i, ledValue);
} else {
set_led_synced(i, 0);
}
} }
} }
} }
static int read_servo(void){ static int read_servo(void){
unsigned ii;
unsigned retries = 0;
/* read data, with the sequential lock to have all data consistent */ unsigned int i;
while (1) {
ii = wrs_shm_seqbegin(ppsi_head);
memcpy(&ppsi_servo_local, ppsi_servo, sizeof(*ppsi_servo));
retries++;
if (retries > 100)
return -1;
if (!wrs_shm_seqretry(ppsi_head, ii))
break; /* consistent read */
}
return 0; if ( read_ppsi_instances() )
return -1;
bzero(&servo.servo_snapshot,sizeof(struct pp_servo));
for (i = 0; i < ppg->nlinks; i++) {
struct pp_instance *ppi = &ppsi_instances_local[i];
/* we are only interested on instances in SLAVE state */
if (ppi->state == PPS_SLAVE ) {
while (1) {
unsigned ii = wrs_shm_seqbegin(ppsi_head);
unsigned retries = 0;
memcpy(&servo.servo_snapshot, ppsi_servo, sizeof(struct pp_servo));
servo.ppi=ppi;
if (!wrs_shm_seqretry(ppsi_head, ii)) {
break; /* consistent read */
}
retries++;
if (retries > 100)
return -1;
}
return 0; /* We assume that we have only one servo */
}
}
return -1; /* No active servo found */
} }
static int try_open_ppsi_shmem(void) static int try_open_ppsi_shmem(void)
{ {
int ret; int ret;
struct pp_globals *ppg;
static int open_error; static int open_error;
if (ppsi_servo && ppsi_instances) { if (ppsi_servo && ppsi_instances) {
...@@ -1021,8 +1050,8 @@ static int try_open_ppsi_shmem(void) ...@@ -1021,8 +1050,8 @@ static int try_open_ppsi_shmem(void)
} }
ppg = (void *)ppsi_head + ppsi_head->data_off; ppg = (void *)ppsi_head + ppsi_head->data_off;
/* there is an assumption that there is only one servo in ppsi! */ /* ppsi-servo points to the common servo data */
ppsi_servo = wrs_shm_follow(ppsi_head, ppg->global_ext_data); ppsi_servo = wrs_shm_follow(ppsi_head, ppg->servo);
if (!ppsi_servo) { if (!ppsi_servo) {
pr_error("Cannot follow ppsi_servo in shmem.\n"); pr_error("Cannot follow ppsi_servo in shmem.\n");
return 0; return 0;
......
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