Commit 1f7f829b authored by Jean-Claude BAU's avatar Jean-Claude BAU

Export HAL generic fsm to libwr + bug fixes

- Export HAL generic fsm to libwr (based on Tom work)
- HAL bug fixes and state machines changes

This version of HAL works but need some improvements
parent b4ce2950
......@@ -10,7 +10,7 @@ OBJS = init.o fpga_io.o util.o pps_gen.o i2c.o shw_io.o i2c_bitbang.o \
dot-config.o config-lpcalib.o wrs-msg.o \
mac.o \
timeout.o \
config-lpcalib.o
config-lpcalib.o generic_fsm.o
LIB = libwr.a
......
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Jean-Claude BAU - CERN
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*
*/
#include <stdlib.h>
#include <string.h>
#include <libwr/wrs-msg.h>
#include <libwr/generic_fsm.h>
static char * fsm_generic_build_events( fsm_t *pfg, int *eventMask );
/* Generic engine used by all ports states machine */
int fsm_generic_run( fsm_t *pfg) {
int ret=0;
int eventMask,isNewState;
fsm_generic_build_events(pfg, &eventMask);
pfg->lastEventMask = eventMask;
isNewState=fsm_has_pending_state(pfg);
/* Check if state has changed */
if ( isNewState ) {
fsm_consume_state(pfg); // update the current state with the scheduled one
}
/* Call state entry */
if (eventMask || isNewState) {
fsm_state_table_entry_t *pt;;
for( pt = pfg->state_table; pt->state >= 0; pt++)
{
if (pt->state == fsm_get_state(pfg) ) {
/* if ( FSM_GEN_DEBUG && pt->fctName!=NULL)
printf("%s: Calling %s (newState=%d, evts=%s),\n",
pfg->fsm_name,
pt->fctName, isNewState,evtStr);*/
ret= (*pt->handler)(pfg,eventMask,isNewState);
if ( fsm_has_pending_state(pfg) ) {
/* Consume state immediately */
return fsm_generic_run(pfg);
}
break;
}
}
}
return ret;
}
static char * fsm_generic_build_events( fsm_t *pfg, int *eventMask)
{
*eventMask=0;
if ( pfg->build_events_handler )
*eventMask=(*pfg->build_events_handler)(pfg);
if ( FSM_GEN_DEBUG ) {
static char str[128];
int copy=*eventMask;
fsm_event_table_entry_t *pe;
str[0]=0;
for( pe = pfg->event_table; pe->evtMask > 0; pe++)
{
if (copy==0) break;
if ( (pe->evtMask & copy) !=0 ) {
if ( str[0]!=0)
strcat(str,"+");
strcat(str,pe->evtName);
copy &=~pe->evtMask;
}
}
return str;
} else {
static char str[1]="";
return str;
}
}
/*
* Fill the FSM structure
* returns 0 on success or -1 on error
*/
int fsm_generic_create(fsm_t *fsm,
const char *name,
fsm_build_event_handler_t build_events_handler,
fsm_state_table_entry_t *state_table,
fsm_event_table_entry_t *event_table,
void *priv)
{
if (fsm->fsm_name!=NULL )
free(fsm->fsm_name); // In case the structure is filled more than one time
fsm->fsm_name = strdup(name);
if ( fsm->fsm_name==NULL )
return -1;
fsm->event_table = event_table;
fsm->state_table = state_table;
fsm->build_events_handler = build_events_handler;
fsm->enabled = 1;
fsm->priv = priv;
fsm_init_state(fsm);
return 0;
}
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Jean-Claude BAU - CERN
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*
*
*/
#ifndef GENERIC_FSM_H
#define GENERIC_FSM_H
#include <stdio.h>
#include <string.h>
#define FSM_GEN_DEBUG 0
#define FSM_SET_FCT_NAME(name) .handler=name, .fctName=#name
/*
* Used to define the callback to call for a givent state
*/
struct fsm_s;
/* States used by the generic FSM */
typedef struct {
int state;
int nextState;
} fsm_state_t;
typedef int (*fsm_state_handler_t)( struct fsm_s* fsm, int eventMsk, int newState);
typedef int (*fsm_build_event_handler_t)( struct fsm_s *fsm );
typedef struct {
int state;
char * stateName;
fsm_state_handler_t handler;
char *fctName;
} fsm_state_table_entry_t;
typedef struct {
int evtMask;
char * evtName;
} fsm_event_table_entry_t;
/*
* Structure containing all information needed by the state machine
*/
typedef struct fsm_s {
char * fsm_name;
fsm_build_event_handler_t build_events_handler;
fsm_state_table_entry_t *state_table;
fsm_event_table_entry_t *event_table;
fsm_state_t st;
int enabled;
int lastEventMask;
void *priv;
} fsm_t;
/* returns current state of the FSM */
static inline int fsm_get_state(fsm_t *fsm)
{
return fsm->st.state;
}
/* sets the current (immediate) state of the FSM */
static inline int fsm_set_state(fsm_t *fsm, int newState)
{
fsm->st.state = newState;
return fsm->st.state;
}
/* Set state and next state to -1 */
static inline int fsm_init_state(fsm_t *fsm)
{
fsm->st.state = fsm->st.nextState=-1;
return fsm->st.state;
}
/* gets the next (scheduled) state of the FSM */
static inline int fsm_get_next_state(fsm_t *fsm)
{
return fsm->st.nextState;
}
/* returns a human-readable state name for a given state */
static inline const char * fsm_get_state_name(fsm_t *fsm)
{
static const char *unknown_msg = "<Unknown>";
static const char *not_init_msg = "<NotInit>";
int st = fsm_get_state(fsm);
if (st == -1 )
return not_init_msg;
if (st < -1 )
return unknown_msg;
fsm_state_table_entry_t *pt = &fsm->state_table[ fsm_get_state(fsm) ];
return pt->stateName;
}
static inline const char *fsm_get_event_mask_as_string(fsm_t *fsm)
{
static char str[1024];
fsm_event_table_entry_t *evt;
strcpy(str, "");
for( evt = fsm->event_table; evt->evtMask > 0; evt++ )
{
if (fsm->lastEventMask & evt->evtMask)
{
strcat(str, evt->evtName);
strcat(str, " ");
}
}
return str;
}
/* updates the current state of the FSM with the next (scheduled) state */
static inline void fsm_consume_state(fsm_t *fsm)
{
fsm->st.state = fsm_get_next_state(fsm);
if (FSM_GEN_DEBUG)
printf("%s: Enter state %s\n", fsm->fsm_name, fsm_get_state_name(fsm));
}
/* schedules next state of the FSM to newState */
static inline void fsm_fire_state(fsm_t *fsm, int newState)
{
fsm->st.nextState=newState;
}
/* returns nonzero if there's a next (scheduled) state present */
static inline int fsm_has_pending_state(fsm_t *fsm)
{
return fsm_get_state(fsm) != fsm_get_next_state(fsm);
}
/* prototypes */
/* Does a single turn of the FSM */
int fsm_generic_create(fsm_t *fsm, const char *name,
fsm_build_event_handler_t build_events_handler,
fsm_state_table_entry_t *state_table,
fsm_event_table_entry_t *event_table, void *priv);
int fsm_generic_run ( fsm_t *fsm );
#endif
#ifndef __LIBWR_HAL_SHMEM_H__
#define __LIBWR_HAL_SHMEM_H__
#include <string.h>
#include <hal_exports.h>
#include <libwr/sfp_lib.h>
#include <string.h>
#include <libwr/generic_fsm.h>
#include "timeout.h"
#include <libwr/timeout.h>
/* Port state machine states */
typedef enum {
......@@ -63,12 +65,6 @@ typedef struct hal_port_calibration {
struct shw_sfp_dom sfp_dom_raw;
} hal_port_calibration_t;
/* States used by the generic FSM */
typedef struct {
int state;
int nextState;
} halPortFsmState_t;
/* Low Phase Drift Calibration for tx */
typedef struct {
int attempts;
......@@ -87,12 +83,14 @@ typedef struct {
timeout_t link_timeout;
timeout_t align_timeout;
timeout_t earlyup_timeout;
timeout_t align_to_link_timeout;
int attempts;
}halPortLpdcRx_t;
typedef struct {
int numberOfLpdcPorts;
int numberOfTxSetupDonePorts;
uint32_t maskLpdcPorts;
uint32_t maskTxSetupDonePorts;
int firstLpdcPort;
int lastLpdcPort;
int calFileSynced;
......@@ -100,8 +98,8 @@ typedef struct {
typedef struct {
int isSupported; /* Set if Low Phase Drift Calibration is supported */
halPortFsmState_t txSetupStates;
halPortFsmState_t rxSetupStates;
fsm_t txSetupFSM;
fsm_t rxSetupFSM;
halPortLpdcTx_t *txSetup;
halPortLpdcRx_t *rxSetup;
halGlobalLPDC_t *globalLpdc;
......@@ -118,7 +116,8 @@ struct hal_port_state {
int hw_addr_auto;
/* port FSM state (HAL_PORT_STATE_xxxx) */
halPortFsmState_t portStates;
fsm_t fsm;
fsm_t pllFsm;
int fiber_index;/* fiber type, used to get alpha for SFP frequency */
int locked; /* 1: PLL is locked to this port */
......@@ -162,12 +161,10 @@ struct hal_port_state {
int evt_reset; /* Set if a reset is requested */
int evt_lock; /* Set if the ptracker must be activated*/
int evt_linkUp; /* Set if link is up ( driver call )*/
int evt_powerDown; /* Set if port is in power down state (MII MCR.PDOWN ==1 ) */
/* Low phase drift calibration data */
halPortLPDC_t *lpdc; /* Use a pointer to avoid to export this structure to PPSi */
/* Pll FSM */
halPortFsmState_t pllStates;
halPortLPDC_t lpdc;
};
struct hal_temp_sensors {
......@@ -197,7 +194,7 @@ struct hal_shmem_header {
static inline int get_port_state(struct hal_port_state *ps)
{
return ps->portStates.state;
return fsm_get_state( &ps->fsm );
}
static inline int state_up(struct hal_port_state *ps)
......
......@@ -238,7 +238,7 @@ struct wr_socket *ptpd_netif_create_socket(int sock_type, int flags,
hwconfig.tx_type = HWTSTAMP_TX_ON;
hwconfig.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
ifr.ifr_data = &hwconfig;
ifr.ifr_data = (char *)&hwconfig;
if (ioctl(fd, SIOCSHWTSTAMP, &ifr) < 0) {
perror("SIOCSHWTSTAMP");
......
......@@ -402,8 +402,8 @@ struct dump_info hal_port_info [] = {
DUMP_FIELD(int, hw_index),
DUMP_FIELD(int, fd),
DUMP_FIELD(int, hw_addr_auto),
DUMP_FIELD(int, portStates.state),
DUMP_FIELD(int, pllStates.state),
DUMP_FIELD(int, fsm.st.state),
DUMP_FIELD(int, pllFsm.st.state),
DUMP_FIELD(int, fiber_index),
DUMP_FIELD(int, locked),
/* these fields are defined as uint32_t but we prefer %i to %x */
......@@ -458,7 +458,6 @@ struct dump_info hal_port_info [] = {
DUMP_FIELD(int, evt_lock),
DUMP_FIELD(int, evt_linkUp),
DUMP_FIELD(int, pllStates.state),
};
/* map for fields of hal_port_state.lpdc (hal_shmem.h) */
......@@ -466,8 +465,8 @@ struct dump_info hal_port_info [] = {
#define DUMP_STRUCT halPortLPDC_t
struct dump_info hal_port_info_lpdc [] = {
DUMP_FIELD(int, isSupported),
DUMP_FIELD(int, txSetupStates.state),
DUMP_FIELD(int, rxSetupStates.state),
DUMP_FIELD(int, txSetupFSM.st.state),
DUMP_FIELD(int, rxSetupFSM.st.state),
};
/* map for fields of hal_port_state.lpdc.txsetup (hal_shmem.h) */
......@@ -522,31 +521,24 @@ int dump_hal_mem(struct wrs_shm_head *head)
sprintf(prefix,"HAL.port.%d",i+1);
dump_many_fields(p, hal_port_info, ARRAY_SIZE(hal_port_info),prefix);
if ( p->lpdc ) {
halPortLPDC_t *lpdc;
if ( (lpdc=wrs_shm_follow(head, p->lpdc))!=NULL ) {
strcat(prefix,".lpdc");
dump_many_fields(lpdc, hal_port_info_lpdc, ARRAY_SIZE(hal_port_info_lpdc),prefix);
if ( lpdc->txSetup) {
halPortLpdcTx_t *txsetup;
if ( (txsetup=wrs_shm_follow(head, lpdc->txSetup))!=NULL ) {
strcpy(prefix2,prefix);
strcat(prefix2,".txsetup");
dump_many_fields(txsetup, hal_port_info_lpdc_txsetup, ARRAY_SIZE(hal_port_info_lpdc_txsetup),prefix2);
}
}
if ( lpdc->rxSetup) {
halPortLpdcTx_t *rxsetup;
if ( (rxsetup=wrs_shm_follow(head, lpdc->rxSetup))!=NULL ) {
strcpy(prefix2,prefix);
strcat(prefix2,".rxsetup");
dump_many_fields(rxsetup, hal_port_info_lpdc_rxsetup, ARRAY_SIZE(hal_port_info_lpdc_rxsetup),prefix2);
}
}
strcat(prefix,".lpdc");
dump_many_fields(&p->lpdc, hal_port_info_lpdc, ARRAY_SIZE(hal_port_info_lpdc),prefix);
if ( p->lpdc.txSetup) {
halPortLpdcTx_t *txsetup;
if ( (txsetup=wrs_shm_follow(head, p->lpdc.txSetup))!=NULL ) {
strcpy(prefix2,prefix);
strcat(prefix2,".txsetup");
dump_many_fields(txsetup, hal_port_info_lpdc_txsetup, ARRAY_SIZE(hal_port_info_lpdc_txsetup),prefix2);
}
}
if ( p->lpdc.rxSetup) {
halPortLpdcTx_t *rxsetup;
if ( (rxsetup=wrs_shm_follow(head, p->lpdc.rxSetup))!=NULL ) {
strcpy(prefix2,prefix);
strcat(prefix2,".rxsetup");
dump_many_fields(rxsetup, hal_port_info_lpdc_rxsetup, ARRAY_SIZE(hal_port_info_lpdc_rxsetup),prefix2);
}
}
}
......
......@@ -4,7 +4,7 @@
-include ../../.config
OBJS = hal_exports.o hal_main.o hal_ports.o hal_timing.o \
hal_port_gen_fsm.o hal_port_fsm.o hal_port_fsm_tx.o hal_port_fsm_rx.o hal_port_fsm_pll.o\
hal_port_fsm.o hal_port_fsm_tx.o hal_port_fsm_rx.o hal_port_fsm_pll.o\
hal_port_leds.o hal_timer.o
BINARY = wrsw_hal
......
This diff is collapsed.
......@@ -13,9 +13,7 @@
#define HAL_CAL_DMTD_SAMPLES 16
#define HAL_DEFAULT_DMTD_SAMPLES 512
/* Prototypes */
void fsm_state_machine( struct hal_port_state * ps );
void hal_port_state_fsm( struct hal_port_state * ps );
void hal_port_state_fsm_init( struct hal_port_state * ps,halGlobalLPDC_t *globalLpdc);
void hal_port_state_fsm_init_all( struct hal_port_state * ports, halGlobalLPDC_t *globalLpdc);
void hal_port_state_fsm_run_all( struct hal_port_state * ports);
#endif
......@@ -14,36 +14,52 @@
typedef enum
{
HAL_PORT_EVENT_TIMER=(1<<0),
HAL_PORT_EVENT_SFP_INSERTED=(1<<1),
HAL_PORT_EVENT_SFP_REMOVED=(1<<3),
HAL_PORT_EVENT_LINK_UP=(1<<4),
HAL_PORT_EVENT_LINK_DOWN=(1<<5),
HAL_PORT_EVENT_RESET=(1<<6)
}halPortEventMask_t ;
static __inline__ int _isHalEventInitialized(halPortEventMask_t eventMsk) {
HAL_PORT_EVENT_TIMER = (1 << 0),
HAL_PORT_EVENT_SFP_INSERTED = (1 << 1),
HAL_PORT_EVENT_SFP_REMOVED = (1 << 2),
HAL_PORT_EVENT_LINK_UP = (1 << 3),
HAL_PORT_EVENT_LINK_DOWN = (1 << 4),
HAL_PORT_EVENT_RESET = (1 << 5),
HAL_PORT_EVENT_POWER_DOWN = (1 << 6),
HAL_PORT_EVENT_EARLY_LINK_UP = (1 << 7),
HAL_PORT_EVENT_RX_ALIGNED = (1 << 8)
} halPortEventMask_t;
static inline int _isHalEventInitialized(halPortEventMask_t eventMsk) {
return eventMsk & HAL_PORT_EVENT_TIMER;
}
static __inline__ int _isHalEventSfpInserted(halPortEventMask_t eventMsk) {
static inline int _isHalEventSfpInserted(halPortEventMask_t eventMsk) {
return eventMsk & HAL_PORT_EVENT_SFP_INSERTED;
}
static __inline__ int _isHalEventSfpRemoved(halPortEventMask_t eventMsk) {
static inline int _isHalEventSfpRemoved(halPortEventMask_t eventMsk) {
return eventMsk & HAL_PORT_EVENT_SFP_REMOVED;
}
static __inline__ int _isHalEventLinkUp(halPortEventMask_t eventMsk) {
static inline int _isHalEventLinkUp(halPortEventMask_t eventMsk) {
return eventMsk & HAL_PORT_EVENT_LINK_UP;
}
static __inline__ int _isHalEventLinkDown(halPortEventMask_t eventMsk) {
static inline int _isHalEventLinkDown(halPortEventMask_t eventMsk) {
return eventMsk & HAL_PORT_EVENT_LINK_DOWN;
}
static __inline__ int _isHalEventReset(halPortEventMask_t eventMsk) {
static inline int _isHalEventReset(halPortEventMask_t eventMsk) {
return eventMsk & HAL_PORT_EVENT_RESET;
}
static inline int _isHalEventPortPowerDown(halPortEventMask_t eventMsk) {
return eventMsk & HAL_PORT_EVENT_POWER_DOWN;
}
static inline int _isHalEventPortEarlyLinkUp(halPortEventMask_t eventMsk) {
return eventMsk & HAL_PORT_EVENT_EARLY_LINK_UP;
}
static inline int _isHalEventPortRxAligned(halPortEventMask_t eventMsk) {
return eventMsk & HAL_PORT_EVENT_RX_ALIGNED;
}
#endif
#include <stdlib.h>
#include <hal_exports.h>
#include <libwr/hal_shmem.h>
......@@ -23,13 +24,13 @@
*/
/* external prototypes */
static int _buildEvents(void * vpfg);
static int _hal_port_pll_state_unlocked(void *vpfg, int eventMsk, int isNewState);
static int _hal_port_pll_state_locked(void *vpfg, int eventMsk, int isNewState);
static int _hal_port_pll_state_locking(void *vpfg, int eventMsk, int isNewState);
static int port_pll_fsm_build_events(fsm_t *pfg);
static int _hal_port_pll_state_unlocked(fsm_t *pfg, int eventMsk, int isNewState);
static int _hal_port_pll_state_locked(fsm_t *pfg, int eventMsk, int isNewState);
static int _hal_port_pll_state_locking(fsm_t *pfg, int eventMsk, int isNewState);
static halPortStateTable_t _fsmStateTable[] =
static fsm_state_table_entry_t port_pll_fsm_states[] =
{
{
.state=HAL_PORT_PLL_STATE_UNLOCKED,
......@@ -49,7 +50,7 @@ static halPortStateTable_t _fsmStateTable[] =
{ .state=-1 }
};
static halPortEventTable_t _fsmEvtTable[] = {
static fsm_event_table_entry_t port_pll_fsm_events[] = {
{
.evtMask = HAL_PORT_PLL_EVENT_TIMER,
.evtName="TIMER"
......@@ -72,13 +73,6 @@ static halPortEventTable_t _fsmEvtTable[] = {
},
{ .evtMask = -1 } };
static halPortFsmGen_t _portFsm = {
.fsm_name="PortFsmPll",
.fctBuilEvents=_buildEvents,
.pt=_fsmStateTable,
.pe=_fsmEvtTable
};
/* UNLOCKED state
*
* if locked event then
......@@ -91,16 +85,16 @@ static halPortFsmGen_t _portFsm = {
* fi
*
*/
static int _hal_port_pll_state_unlocked(void *vpfg, int eventMsk, int isNewState) {
struct hal_port_state * ps=((halPortFsmGen_t *)vpfg)->ps;
static int _hal_port_pll_state_unlocked(fsm_t *fsm, int eventMsk, int isNewState) {
struct hal_port_state * ps = (struct hal_port_state*) fsm->priv;
if ( _isHalPllEventLocked(eventMsk) ) {
_fireState(vpfg,HAL_PORT_PLL_STATE_LOCKED);
fsm_fire_state(fsm, HAL_PORT_PLL_STATE_LOCKED);
return 0;
}
if ( _isHalPllEventLock(eventMsk) ) {
if ( rts_lock_channel(ps->hw_index, 0)>=0 ) {
_fireState(vpfg,HAL_PORT_PLL_STATE_LOCKING);
fsm_fire_state(fsm, HAL_PORT_PLL_STATE_LOCKING);
return 0;
}
}
......@@ -113,14 +107,14 @@ static int _hal_port_pll_state_unlocked(void *vpfg, int eventMsk, int isNewState
* if locked event then state=LOCKED
* else if unlock event then state=UNLOCKED
*/
static int _hal_port_pll_state_locking(void *vpfg, int eventMsk, int isNewState) {
static int _hal_port_pll_state_locking(fsm_t *fsm, int eventMsk, int isNewState) {
if ( _isHalPllEventLocked(eventMsk) ) {
_fireState(vpfg,HAL_PORT_PLL_STATE_LOCKED);
fsm_fire_state(fsm, HAL_PORT_PLL_STATE_LOCKED);
return 0;
}
if ( _isHalPllEventDisable(eventMsk) ) {
_fireState(vpfg,HAL_PORT_PLL_STATE_UNLOCKED);
fsm_fire_state(fsm, HAL_PORT_PLL_STATE_UNLOCKED);
return 0;
}
return 0;
......@@ -135,13 +129,13 @@ static int _hal_port_pll_state_locking(void *vpfg, int eventMsk, int isNewState)
* else return final state machine reached
* fi
*/
static int _hal_port_pll_state_locked(void *vpfg, int eventMsk, int isNewState) {
static int _hal_port_pll_state_locked(fsm_t *fsm, int eventMsk, int isNewState) {
if ( _isHalPllEventUnlock(eventMsk) ) {
_fireState(vpfg,HAL_PORT_PLL_STATE_LOCKING);
fsm_fire_state(fsm, HAL_PORT_PLL_STATE_LOCKING);
return 0;
}
if ( _isHalPllEventDisable(eventMsk) ) {
_fireState(vpfg,HAL_PORT_PLL_STATE_UNLOCKED);
fsm_fire_state(fsm, HAL_PORT_PLL_STATE_UNLOCKED);
return 0;
}
return 1; /* final state */
......@@ -152,8 +146,8 @@ static int _hal_port_pll_state_locked(void *vpfg, int eventMsk, int isNewState)
*
* Lock & Locked events are generated only if the timing mode is BC
*/
static int _buildEvents(void * vpfg) {
struct hal_port_state * ps=((halPortFsmGen_t *)vpfg)->ps;
static int port_pll_fsm_build_events(fsm_t *fsm) {
struct hal_port_state * ps = (struct hal_port_state*) fsm->priv;
int portEventMask=HAL_PORT_PLL_EVENT_TIMER;
int tm;
......@@ -177,13 +171,36 @@ static int _buildEvents(void * vpfg) {
return portEventMask;
}
/* Initialize rx_setup - this is a global init, executed once for all ports/FSMs.
*/
void hal_port_pll_setup_init_all(struct hal_port_state * ports) {
char name[64];
int index;
for (index = 0; index < HAL_MAX_PORTS; index++){
struct hal_port_state *ps = &ports[index];
snprintf(name, sizeof(name), "PortPllFSM.%d", ps->hw_index);
if (fsm_generic_create(&ps->pllFsm, name, port_pll_fsm_build_events,
port_pll_fsm_states, port_pll_fsm_events, ps)) {
pr_error("Cannot create PLL fsm !\n");
exit(EXIT_FAILURE);
}
}
}
/* Init PLL FSM */
void hal_port_pll_init_fsm(struct hal_port_state * ps ) {
void hal_port_pll_fsm_init(struct hal_port_state * ps )
{
fsm_init_state(&ps->pllFsm);
fsm_fire_state(&ps->pllFsm, HAL_PORT_PLL_STATE_UNLOCKED);
}
_portFsm.ps=ps;
_portFsm.st=&ps->pllStates;
ps->pllStates.state=-1;
_fireState(&_portFsm,HAL_PORT_PLL_STATE_UNLOCKED);
void hal_port_pll_fsm_reset(struct hal_port_state * ps )
{
fsm_init_state(&ps->pllFsm);
fsm_fire_state(&ps->pllFsm, HAL_PORT_PLL_STATE_UNLOCKED);
}
/* FSM state machine for PLL on a given port
......@@ -193,9 +210,9 @@ void hal_port_pll_init_fsm(struct hal_port_state * ps ) {
* -1: error detected
*/
int hal_port_pll_state_fsm( struct hal_port_state * ps ) {
_portFsm.ps=ps;
_portFsm.st=&ps->pllStates;
return hal_port_generic_fsm(&_portFsm);
int hal_port_pll_fsm_run( struct hal_port_state * ps ) {
if ( !ps->in_use )
return 1;
return fsm_generic_run( &ps->pllFsm );
}
......@@ -10,8 +10,8 @@
#ifndef HAL_PORT_FSM_PLL_H
#define HAL_PORT_FSM_PLL_H
/* prototypes */
void hal_port_pll_init_fsm(struct hal_port_state * ps );
int hal_port_pll_state_fsm( struct hal_port_state * ps );
void hal_port_pll_fsm_init(struct hal_port_state * ps );
int hal_port_pll_fsm_run( struct hal_port_state * ps );
void hal_port_pll_setup_init_all(struct hal_port_state * ports);
#endif
......@@ -11,7 +11,8 @@
#define HAL_PORT_FSM_PLLP_H
#include <libwr/wrs-msg.h>
#include "hal_port_gen_fsm.h"
#include <libwr/generic_fsm.h>
#include "hal_port_fsm_pll.h"
typedef enum {
......@@ -30,19 +31,19 @@ typedef enum
}halPortPllEventMask_t ;
static __inline__ int _isHalPllEventLock(halPortPllEventMask_t eventMsk) {
static inline int _isHalPllEventLock(halPortPllEventMask_t eventMsk) {
return eventMsk & HAL_PORT_PLL_EVENT_LOCK;
}
static __inline__ int _isHalPllEventLocked(halPortPllEventMask_t eventMsk) {
static inline int _isHalPllEventLocked(halPortPllEventMask_t eventMsk) {
return eventMsk & HAL_PORT_PLL_EVENT_LOCKED;
}
static __inline__ int _isHalPllEventUnlock(halPortPllEventMask_t eventMsk) {
static inline int _isHalPllEventUnlock(halPortPllEventMask_t eventMsk) {
return eventMsk & HAL_PORT_PLL_EVENT_UNLOCKED;
}
static __inline__ int _isHalPllEventDisable(halPortPllEventMask_t eventMsk) {
static inline int _isHalPllEventDisable(halPortPllEventMask_t eventMsk) {
return eventMsk & HAL_PORT_PLL_EVENT_DISABLE;
}
......
This diff is collapsed.
......@@ -11,8 +11,10 @@
#define HAL_PORT_FSM_RX_H
/* prototypes */
void hal_port_rx_setup_init_fsm(struct hal_port_state * ps );
int hal_port_rx_setup_state_fsm( struct hal_port_state * ps );
void hal_port_rx_setup_fsm_init(struct hal_port_state * ps );
int hal_port_rx_setup_fsm_run( struct hal_port_state * ps );
void hal_port_rx_setup_fsm_reset(struct hal_port_state * ps );
void hal_port_rx_setup_init_all(struct hal_port_state * ports);
#endif
......@@ -11,7 +11,7 @@
#define HAL_PORT_FSM_RXP_H
#include <libwr/wrs-msg.h>
#include "hal_port_gen_fsm.h"
#include <libwr/generic_fsm.h>
typedef enum {
HAL_PORT_RX_SETUP_STATE_START=0,
......@@ -30,23 +30,23 @@ HAL_PORT_RX_SETUP_EVENT_EARLY_LINK_UP=(1<<3),
HAL_PORT_RX_SETUP_EVENT_RX_ALIGNED=(1<<4)
}halPortRxSetupEventMask_t ;
static __inline__ int _isHalRxSetupEventTimer(halPortRxSetupEventMask_t eventMsk) {
static inline int _isHalRxSetupEventTimer(halPortRxSetupEventMask_t eventMsk) {
return eventMsk & HAL_PORT_RX_SETUP_EVENT_TIMER;
}
static __inline__ int _isHalRxSetupEventLinkDown(halPortRxSetupEventMask_t eventMsk) {
static inline int _isHalRxSetupEventLinkDown(halPortRxSetupEventMask_t eventMsk) {
return eventMsk & HAL_PORT_RX_SETUP_EVENT_LINK_DOWN;
}
static __inline__ int _isHalRxSetupEventLinkUp(halPortRxSetupEventMask_t eventMsk) {
static inline int _isHalRxSetupEventLinkUp(halPortRxSetupEventMask_t eventMsk) {
return eventMsk & HAL_PORT_RX_SETUP_EVENT_LINK_UP;
}
static __inline__ int _isHalRxSetupEventEarlyLinkUp(halPortRxSetupEventMask_t eventMsk) {
static inline int _isHalRxSetupEventEarlyLinkUp(halPortRxSetupEventMask_t eventMsk) {
return eventMsk & HAL_PORT_RX_SETUP_EVENT_EARLY_LINK_UP;
}
static __inline__ int _isHalRxSetupEventRxAligned(halPortRxSetupEventMask_t eventMsk) {
static inline int _isHalRxSetupEventRxAligned(halPortRxSetupEventMask_t eventMsk) {
return eventMsk & HAL_PORT_RX_SETUP_EVENT_RX_ALIGNED;
}
......
This diff is collapsed.
......@@ -10,9 +10,9 @@
#ifndef HAL_PORT_FSM_TX_H
#define HAL_PORT_FSM_TX_H
/* prototypes */
void hal_port_tx_setup_init_fsm(struct hal_port_state * ps );
void hal_port_tx_setup_init(struct hal_port_state * ps, halGlobalLPDC_t *globalLpdc );
int hal_port_tx_setup_state_fsm( struct hal_port_state * ps);
void hal_port_tx_setup_init_all(struct hal_port_state * ports, halGlobalLPDC_t *globalLpdc);
void hal_port_tx_setup_fsm_init(struct hal_port_state * ps );
int hal_port_tx_setup_fsm_run( struct hal_port_state * ps );
void hal_port_tx_setup_fsm_reset(struct hal_port_state * ps );
#endif
......@@ -11,13 +11,12 @@
#define HAL_PORT_FSM_TXP_H
#include <libwr/wrs-msg.h>
#include "hal_port_gen_fsm.h"
#include <libwr/generic_fsm.h>
#define TX_CAL_PHASE_MEAS_TIMEOUT 1000 /* ms */
#define TX_CAL_TOLLERANCE 300 /* ps */
#define TX_CAL_FIRST_CAL_TOLLERANCE 750 /* ps */
#define TX_CAL_TOLERANCE 300 /* ps */
#define TX_CAL_FIRST_CAL_TOLERANCE 750 /* ps */
#define TX_CAL_FIRST_CAL_EXPECTED_PHASE 750 /* ps */
typedef enum {
......@@ -28,14 +27,14 @@ HAL_PORT_TX_SETUP_STATE_MEASURE_PHASE,
HAL_PORT_TX_SETUP_STATE_VALIDATE,
HAL_PORT_TX_SETUP_STATE_WAIT_OTHER_PORTS,
HAL_PORT_TX_SETUP_STATE_DONE
} hapPortTxSetupState_t;
} halPortTxSetupState_t;
typedef enum
{
HAL_PORT_TX_SETUP_EVENT_TIMER=(1<<0),
}halPortTxSetupEventMask_t ;
static __inline__ int _isHalTxSetupEventTimer(halPortTxSetupEventMask_t eventMsk) {
static inline int _isHalTxSetupEventTimer(halPortTxSetupEventMask_t eventMsk) {
return eventMsk & HAL_PORT_TX_SETUP_EVENT_TIMER;
}
......
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Jean-Claude BAU - CERN
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*
*/
#include "hal_port_gen_fsm.h"
static char * _generic_build_events( halPortFsmGen_t *pfg, int *portEventMask);
/* Generic engine used by all ports states machine */
int hal_port_generic_fsm( halPortFsmGen_t *pfg) {
int ret=0;
if ( pfg->ps->in_use ) {
int portEventMask,isNewState;
char *evtStr=_generic_build_events(pfg, &portEventMask);
/* Check if state has changed */
if ( (isNewState=_isPendingState(pfg))==1 ) {
_consumeState(pfg);
}
/* Call state entry */
if (portEventMask || isNewState) {
halPortStateTable_t *pt=pfg->pt;
while (pt->state!=-1 ) {
if (pt->state==_getState(pfg) ) {
if ( FSM_GEN_DEBUG && pt->fctName!=NULL)
pr_debug("%s.%s: Calling %s (newState=%d, evts=%s),\n",
pfg->ps->name,pfg->fsm_name,
pt->fctName, isNewState,evtStr);
ret=(*pt->fct)(pfg,portEventMask,isNewState);
if ( _isPendingState(pfg) ) {
/* Consume state immediately */
return hal_port_generic_fsm(pfg);
}
break;
}
pt++;
}
}
}
return ret;
}
static char * _generic_build_events( halPortFsmGen_t *pfg, int *portEventMask) {
*portEventMask=0;
if ( pfg->fctBuilEvents )
*portEventMask=(*pfg->fctBuilEvents)(pfg);
if ( FSM_GEN_DEBUG ) {
static char str[128];
int copy=*portEventMask;
halPortEventTable_t *pe=pfg->pe;
str[0]=0;
while (pe->evtMask!=-1 ) {
if (copy==0) break;
if ( (pe->evtMask & copy) !=0 ) {
if ( str[0]!=0)
strcat(str,"+");
strcat(str,pe->evtName);
copy &=~pe->evtMask;
}
pe++;
}
return str;
} else {
static char str[1]="";
return str;
}
}
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Jean-Claude BAU - CERN
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*
*
*/
#ifndef HAL_PORT_GEN_FSM_H
#define HAL_PORT_GEN_FSM_H
#include <libwr/wrs-msg.h>
#include <libwr/hal_shmem.h>
#define FSM_GEN_DEBUG 0
#define FSM_SET_FCT_NAME(name) .fct=name, .fctName=#name
/*
* Used to define the callback to call for a givent state
*/
typedef struct {
int state;
char * stateName;
int (*fct)(void * vpfg/* struct halPortFsmGen_t *pfg*/, int eventMsk, int newState);
char *fctName;
}halPortStateTable_t;
typedef struct {
int evtMask;
char * evtName;
}halPortEventTable_t;
/*
* Structure containing all information needed by the state machine
*/
typedef struct {
char * fsm_name;
int (*fctBuilEvents)(void * vpfg/* struct halPortFsmGen_t *pfg*/);
halPortStateTable_t *pt;
halPortEventTable_t *pe;
struct hal_port_state *ps;
halPortFsmState_t *st;
}halPortFsmGen_t;
extern halPortFsmGen_t *pfg;
static __inline__ int _getState(halPortFsmGen_t *pfg) {
return pfg->st->state;
}
static __inline__ int _setState(halPortFsmGen_t *pfg, int newState) {
return pfg->st->state=newState;
}
static __inline__ int _getNextState(halPortFsmGen_t *pfg) {
return pfg->st->nextState;
}
static __inline__ char * _getStateName(halPortFsmGen_t *pfg) {
halPortStateTable_t *pt=pfg->pt+_getState(pfg);
return pt->stateName;
}
static __inline__ void _consumeState(halPortFsmGen_t *pfg) {
pfg->st->state=_getNextState(pfg);
if (FSM_GEN_DEBUG)
printf("%s.%s: Enter state %s\n",pfg->ps->name,pfg->fsm_name,_getStateName(pfg));
}
static __inline__ void _fireState(halPortFsmGen_t *pfg, int newState) {
pfg->st->nextState=newState;
}
static __inline__ int _isPendingState(halPortFsmGen_t *pfg) {
return _getState(pfg) != _getNextState(pfg);
}
/* prototypes */
int hal_port_generic_fsm( halPortFsmGen_t *pfg);
#endif
......@@ -39,6 +39,12 @@
extern struct hal_shmem_header *hal_shmem;
extern struct wrs_shm_head *hal_shmem_hdr;
#define FSM_DEBUG 1
#if FSM_DEBUG
static timeout_t debug_tmo;
#endif
hal_ports_t halPorts;
/**
......@@ -134,20 +140,15 @@ static int hal_port_init(struct hal_port_state *ps, int index)
if (!hal_port_check_presence(ps->name, ps->hw_addr))
return -1;
/* Allocate LPDC structure */
if ( (ps->lpdc = wrs_shm_alloc(hal_shmem_hdr, sizeof(halPortLPDC_t)))==NULL ) {
pr_error("Can't allocate LPDC structure in shmem\n");
return -1;
}
ps->in_use = 1;
ps->lpdc->isSupported = hal_port_check_lpdc_support(ps);
ps->lpdc.isSupported = hal_port_check_lpdc_support(ps);
if ( ps->lpdc->isSupported ) {
if ( ps->lpdc.isSupported ) {
// Allocate memory for tx/rx setup
ps->lpdc->txSetup = wrs_shm_alloc(hal_shmem_hdr,sizeof(halPortLpdcTx_t));
ps->lpdc->rxSetup = wrs_shm_alloc(hal_shmem_hdr,sizeof(halPortLpdcRx_t));
if ( ps->lpdc->rxSetup==NULL || ps->lpdc->txSetup==NULL) {
ps->lpdc.txSetup = wrs_shm_alloc(hal_shmem_hdr,sizeof(halPortLpdcTx_t));
ps->lpdc.rxSetup = wrs_shm_alloc(hal_shmem_hdr,sizeof(halPortLpdcRx_t));
if ( ps->lpdc.rxSetup==NULL || ps->lpdc.txSetup==NULL) {
pr_error("Can't allocate LPDC (rx/tx) structures in shmem\n");
return -1;
}
......@@ -260,7 +261,11 @@ int hal_port_shmem_init(char *logfilename)
if (hal_port_init(&halPorts.ports[index],index) < 0)
break;
hal_port_state_fsm_init(halPorts.ports,&halPorts.globalLpdc); // Init fsm
hal_port_state_fsm_init_all(halPorts.ports, &halPorts.globalLpdc); // Init main port FSM for all ports
if ( FSM_DEBUG )
libwr_tmo_init( &debug_tmo, 1000, 1 );
led_init_all_ports(halPorts.ports); // Reset all leds
halPorts.numberOfPorts = index;
......@@ -639,10 +644,40 @@ void hal_port_update_all()
/* lock shmem */
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_BEGIN);
hal_port_state_fsm(halPorts.ports);
hal_port_state_fsm_run_all(halPorts.ports);
/* unlock shmem */
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_END);
if( FSM_DEBUG && libwr_tmo_expired( &debug_tmo ))
{
int i;
printf("PortDBG: \n");
for(i = 0; i < HAL_MAX_PORTS; i++)
{
struct hal_port_state *ps = &halPorts.ports[i];
char txEventsStr[128];
char rxEventsStr[128];
if ( !ps->in_use || !ps->lpdc.isSupported )
continue;
strncpy( txEventsStr, fsm_get_event_mask_as_string( &ps->lpdc.txSetupFSM ), sizeof(txEventsStr) );
strncpy( rxEventsStr, fsm_get_event_mask_as_string( &ps->lpdc.rxSetupFSM ), sizeof(rxEventsStr) );
printf(" - wri%02d: PORT:%-20s TX:%-21s (%-40s) RX:%-21s (%-40s) bslide=%d\n",
ps->hw_index + 1,
fsm_get_state_name( &ps->fsm ),
fsm_get_state_name( &ps->lpdc.txSetupFSM ),
txEventsStr,
fsm_get_state_name( &ps->lpdc.rxSetupFSM ),
rxEventsStr,
ps->calib.bitslide_ps
);
}
}
}
int hal_port_enable_tracking(const char *port_name)
......@@ -715,7 +750,7 @@ int hal_port_all_ports_initialized(void) {
int i;
for (i = 0; i < HAL_MAX_PORTS; i++) {
if ( ps->in_use && ps->portStates.state==HAL_PORT_STATE_INIT ) {
if ( ps->in_use && fsm_get_state( &ps->fsm ) ==HAL_PORT_STATE_INIT ) {
// This port has not finished its initialization state
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