Added MS/TP automatic baudrate detection option into the core MS/TP state machine. (#900)

This commit is contained in:
Steve Karg
2025-02-03 15:10:31 -06:00
committed by GitHub
parent c5b129e9ab
commit 19ef7f74cd
12 changed files with 471 additions and 11 deletions
+109 -7
View File
@@ -648,7 +648,9 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port)
}
switch (mstp_port->master_state) {
case MSTP_MASTER_STATE_INITIALIZE:
if (mstp_port->ZeroConfigEnabled) {
if (mstp_port->CheckAutoBaud) {
MSTP_Auto_Baud_FSM(mstp_port);
} else if (mstp_port->ZeroConfigEnabled) {
MSTP_Zero_Config_FSM(mstp_port);
if (mstp_port->This_Station != 255) {
/* indicate that the next station is unknown */
@@ -1430,8 +1432,8 @@ static void MSTP_Zero_Config_State_Idle(struct mstp_port_struct_t *mstp_port)
return;
}
if (mstp_port->ReceivedValidFrame) {
/* IdleValidFrame */
/* next state will clear the frame flags */
/* MonitorPFM */
mstp_port->Poll_Count = 0;
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_LURK;
} else if (mstp_port->ReceivedInvalidFrame) {
@@ -1482,7 +1484,7 @@ static void MSTP_Zero_Config_State_Lurk(struct mstp_port_struct_t *mstp_port)
}
}
if (src == mstp_port->Zero_Config_Station) {
/* AddressInUse */
/* LurkAddressInUse */
/* monitor PFM from the next address */
mstp_port->Zero_Config_Station = MSTP_Zero_Config_Station_Increment(
mstp_port->Zero_Config_Station);
@@ -1493,23 +1495,23 @@ static void MSTP_Zero_Config_State_Lurk(struct mstp_port_struct_t *mstp_port)
/* calculate this node poll count priority number */
count = Nmin_poll + mstp_port->Npoll_slot;
if (mstp_port->Poll_Count == count) {
/* PollResponse */
/* LurkPollResponse */
MSTP_Create_And_Send_Frame(
mstp_port, FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER, src,
mstp_port->Zero_Config_Station, NULL, 0);
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_CLAIM;
} else {
/* CountFrame */
/* LurkCountFrame */
mstp_port->Poll_Count++;
}
}
} else if (mstp_port->ReceivedInvalidFrame) {
/* InvalidFrame */
/* LurkInvalidFrame */
mstp_port->ReceivedInvalidFrame = false;
} else if (mstp_port->Zero_Config_Silence > 0) {
if (mstp_port->SilenceTimer((void *)mstp_port) >
mstp_port->Zero_Config_Silence) {
/* LurkingTimeout */
/* LurkTimeout */
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_IDLE;
}
}
@@ -1660,6 +1662,106 @@ void MSTP_Zero_Config_FSM(struct mstp_port_struct_t *mstp_port)
}
}
/**
* @brief Get the baud rate for auto-baud at a given index
* @param baud_rate_index the index of the baud rate
* @return the baud rate at the index
* @note A modulo operation keeps the index within the bounds of the array of
* baud rates.
*/
uint32_t MSTP_Auto_Baud_Rate(unsigned baud_rate_index)
{
const uint32_t TestBaudrates[6] = {
115200, 76800, 57600, 38400, 19200, 9600
};
unsigned index;
index = baud_rate_index % ARRAY_SIZE(TestBaudrates);
return TestBaudrates[index];
}
/**
* @brief The MSTP_AUTO_BAUD_STATE_INIT state is entered when
* CheckAutoBaud is TRUE
* @param mstp_port the context of the MSTP port
*/
static void MSTP_Auto_Baud_State_Init(struct mstp_port_struct_t *mstp_port)
{
uint32_t baud;
if (!mstp_port) {
return;
}
mstp_port->ValidFrames = 0;
mstp_port->BaudRateIndex = 0;
mstp_port->ValidFrameTimerReset((void *)mstp_port);
baud = MSTP_Auto_Baud_Rate(mstp_port->BaudRateIndex);
mstp_port->BaudRateSet(baud);
mstp_port->Auto_Baud_State = MSTP_AUTO_BAUD_STATE_IDLE;
}
/**
* @brief The MSTP_AUTO_BAUD_STATE_IDLE state is entered when
* CheckAutoBaud is TRUE and waits for good frames or timeout
* @param mstp_port the context of the MSTP port
*/
static void MSTP_Auto_Baud_State_Idle(struct mstp_port_struct_t *mstp_port)
{
uint32_t baud;
if (!mstp_port) {
return;
}
if (mstp_port->ReceivedValidFrame) {
/* IdleValidFrame */
mstp_port->ValidFrames++;
if (mstp_port->ValidFrames >= 4) {
/* GoodBaudRate */
mstp_port->CheckAutoBaud = false;
mstp_port->Auto_Baud_State = MSTP_AUTO_BAUD_STATE_USE;
}
mstp_port->ReceivedValidFrame = false;
} else if (mstp_port->ReceivedInvalidFrame) {
/* IdleInvalidFrame */
mstp_port->ValidFrames = 0;
mstp_port->ReceivedInvalidFrame = false;
} else if (mstp_port->ValidFrameTimer((void *)mstp_port) >= 5000UL) {
/* IdleTimeout */
mstp_port->BaudRateIndex++;
baud = MSTP_Auto_Baud_Rate(mstp_port->BaudRateIndex);
mstp_port->BaudRateSet(baud);
mstp_port->ValidFrames = 0;
mstp_port->ValidFrameTimerReset((void *)mstp_port);
}
}
/**
* @brief Finite State Machine for the Auto Baud Rate process
* @param mstp_port the context of the MSTP port
*/
void MSTP_Auto_Baud_FSM(struct mstp_port_struct_t *mstp_port)
{
if (!mstp_port) {
return;
}
if (!mstp_port->CheckAutoBaud) {
return;
}
switch (mstp_port->Auto_Baud_State) {
case MSTP_AUTO_BAUD_STATE_INIT:
MSTP_Auto_Baud_State_Init(mstp_port);
break;
case MSTP_AUTO_BAUD_STATE_IDLE:
MSTP_Auto_Baud_State_Idle(mstp_port);
break;
case MSTP_AUTO_BAUD_STATE_USE:
break;
default:
break;
}
}
/* note: This_Station assumed to be set with the MAC address */
/* note: Nmax_info_frames assumed to be set (default=1) */
/* note: Nmax_master assumed to be set (default=127) */