Feature/mstp valid frame not for us stats (#1053)

* Fixed ISO C90 forbids mixed declarations and code warning.

* Fixed the MS/TP invalid frame counter that was incremented for valid frames not for us.
This commit is contained in:
Steve Karg
2025-08-01 09:58:45 -05:00
committed by GitHub
parent 1bebd6ac81
commit 4095a7f335
15 changed files with 198 additions and 25 deletions
+2 -1
View File
@@ -831,8 +831,9 @@ void dlenv_maintenance_timer(uint16_t elapsed_seconds)
dlmstp_fill_statistics(&statistics);
fprintf(
stderr,
"MSTP: Frames Rx:%u/%u Tx:%u PDU Rx:%u Tx:%u Lost:%u\n",
"MSTP: Frames Rx:%u/%u/%u Tx:%u PDU Rx:%u Tx:%u Lost:%u\n",
statistics.receive_valid_frame_counter,
statistics.receive_valid_frame_not_for_us_counter,
statistics.receive_invalid_frame_counter,
statistics.transmit_frame_counter,
statistics.receive_pdu_counter,
+32 -2
View File
@@ -372,7 +372,8 @@ uint16_t dlmstp_receive(
}
/* only do receive state machine while we don't have a frame */
while ((MSTP_Port->ReceivedValidFrame == false) &&
(MSTP_Port->ReceivedInvalidFrame == false)) {
(MSTP_Port->ReceivedInvalidFrame == false) &&
(MSTP_Port->ReceivedValidFrameNotForUs == false)) {
MSTP_Port->DataAvailable = driver->read(&data_register);
if (MSTP_Port->DataAvailable) {
MSTP_Port->DataRegister = data_register;
@@ -388,7 +389,8 @@ uint16_t dlmstp_receive(
break;
}
}
if (MSTP_Port->ReceivedValidFrame || MSTP_Port->ReceivedInvalidFrame) {
if (MSTP_Port->ReceivedValidFrame || MSTP_Port->ReceivedInvalidFrame ||
MSTP_Port->ReceivedValidFrameNotForUs) {
/* delay after reception before transmitting - per MS/TP spec */
milliseconds = MSTP_Port->SilenceTimer(MSTP_Port);
if (milliseconds < MSTP_Port->Tturnaround_timeout) {
@@ -405,6 +407,15 @@ uint16_t dlmstp_receive(
MSTP_Port->DataLength);
}
}
if (MSTP_Port->ReceivedValidFrameNotForUs) {
user->Statistics.receive_valid_frame_not_for_us_counter++;
if (user->Valid_Frame_Not_For_Us_Rx_Callback) {
user->Valid_Frame_Not_For_Us_Rx_Callback(
MSTP_Port->SourceAddress, MSTP_Port->DestinationAddress,
MSTP_Port->FrameType, MSTP_Port->InputBuffer,
MSTP_Port->DataLength);
}
}
if (MSTP_Port->ReceivedInvalidFrame) {
user->Statistics.receive_invalid_frame_counter++;
if (user->Invalid_Frame_Rx_Callback) {
@@ -885,6 +896,25 @@ void dlmstp_set_frame_rx_complete_callback(
user->Valid_Frame_Rx_Callback = cb_func;
}
/**
* @brief Set the MS/TP Frame Complete callback
* @param cb_func - callback function to be called when a frame is received
*/
void dlmstp_set_frame_not_for_us_rx_complete_callback(
dlmstp_hook_frame_rx_complete_cb cb_func)
{
struct dlmstp_user_data_t *user;
if (!MSTP_Port) {
return;
}
user = MSTP_Port->UserData;
if (!user) {
return;
}
user->Valid_Frame_Not_For_Us_Rx_Callback = cb_func;
}
/**
* @brief Set the MS/TP Frame Complete callback
* @param cb_func - callback function to be called when a frame is received
+5
View File
@@ -38,6 +38,7 @@ typedef struct dlmstp_statistics {
uint32_t transmit_frame_counter;
uint32_t receive_valid_frame_counter;
uint32_t receive_invalid_frame_counter;
uint32_t receive_valid_frame_not_for_us_counter;
uint32_t transmit_pdu_counter;
uint32_t receive_pdu_counter;
uint32_t lost_token_counter;
@@ -101,6 +102,7 @@ struct dlmstp_user_data_t {
struct dlmstp_rs485_driver *RS485_Driver;
dlmstp_hook_frame_rx_start_cb Preamble_Callback;
dlmstp_hook_frame_rx_complete_cb Valid_Frame_Rx_Callback;
dlmstp_hook_frame_rx_complete_cb Valid_Frame_Not_For_Us_Rx_Callback;
dlmstp_hook_frame_rx_complete_cb Invalid_Frame_Rx_Callback;
uint32_t Valid_Frame_Milliseconds;
/* the PDU Queue is made of Nmax_info_frames x dlmstp_packet's */
@@ -230,6 +232,9 @@ BACNET_STACK_EXPORT
void dlmstp_set_frame_rx_complete_callback(
dlmstp_hook_frame_rx_complete_cb cb_func);
BACNET_STACK_EXPORT
void dlmstp_set_frame_not_for_us_rx_complete_callback(
dlmstp_hook_frame_rx_complete_cb cb_func);
BACNET_STACK_EXPORT
void dlmstp_set_invalid_frame_rx_complete_callback(
dlmstp_hook_frame_rx_complete_cb cb_func);
+48 -14
View File
@@ -450,7 +450,7 @@ void MSTP_Receive_Frame_FSM(struct mstp_port_struct_t *mstp_port)
mstp_port->ReceivedValidFrame = true;
} else {
/* NotForUs */
mstp_port->ReceivedInvalidFrame = true;
mstp_port->ReceivedValidFrameNotForUs = true;
}
/* wait for the start of the next frame. */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
@@ -563,25 +563,34 @@ void MSTP_Receive_Frame_FSM(struct mstp_port_struct_t *mstp_port)
&mstp_port->InputBuffer[mstp_port->Index + 1],
mstp_port->InputBufferSize, mstp_port->InputBuffer,
mstp_port->Index + 1);
if ((mstp_port->DataLength > 0) &&
(mstp_port->receive_state ==
MSTP_RECEIVE_STATE_DATA)) {
if (mstp_port->DataLength > 0) {
/* GoodCRC */
mstp_port->ReceivedValidFrame = true;
if (mstp_port->receive_state ==
MSTP_RECEIVE_STATE_DATA) {
/* ForUs */
mstp_port->ReceivedValidFrame = true;
} else {
/* NotForUs */
mstp_port->ReceivedValidFrameNotForUs = true;
}
} else {
/* Done */
/* BadCRC */
mstp_port->ReceivedInvalidFrame = true;
printf_receive_error(
"MSTP: Rx Data: BadCRC [%02X]\n",
mstp_port->DataRegister);
}
} else {
/* STATE DATA CRC - no need for new state */
if (mstp_port->DataCRC == 0xF0B8) {
/* GoodCRC */
if (mstp_port->receive_state ==
MSTP_RECEIVE_STATE_DATA) {
/* GoodCRC */
/* ForUs */
mstp_port->ReceivedValidFrame = true;
} else {
/* Done */
mstp_port->ReceivedInvalidFrame = true;
/* NotForUs */
mstp_port->ReceivedValidFrameNotForUs = true;
}
} else {
/* BadCRC */
@@ -691,6 +700,11 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port)
/* invalid frame was received */
/* wait for the next frame - remain in IDLE */
mstp_port->ReceivedInvalidFrame = false;
} else if (mstp_port->ReceivedValidFrameNotForUs == true) {
/* ReceivedValidFrameNotForUs */
/* valid frame was received, but not for this node */
/* wait for the next frame - remain in IDLE */
mstp_port->ReceivedValidFrameNotForUs = false;
} else if (mstp_port->ReceivedValidFrame == true) {
printf_master(
"MSTP: ReceivedValidFrame "
@@ -783,6 +797,7 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port)
/* set the receive frame flags to false in case we received
some bytes and had a timeout for some reason */
mstp_port->ReceivedInvalidFrame = false;
mstp_port->ReceivedValidFrameNotForUs = false;
mstp_port->ReceivedValidFrame = false;
transition_now = true;
}
@@ -848,10 +863,11 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port)
/* of the initial value of FrameCount.) */
transition_now = true;
} else {
if (mstp_port->ReceivedInvalidFrame == true) {
/* InvalidFrame */
/* error in frame reception */
if ((mstp_port->ReceivedInvalidFrame == true) ||
(mstp_port->ReceivedValidFrameNotForUs == true)) {
/* InvalidFrame in this state */
mstp_port->ReceivedInvalidFrame = false;
mstp_port->ReceivedValidFrameNotForUs = false;
mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
transition_now = true;
} else if (mstp_port->ReceivedValidFrame == true) {
@@ -1123,7 +1139,8 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port)
} else if (
(mstp_port->SilenceTimer((void *)mstp_port) >
mstp_port->Tusage_timeout) ||
(mstp_port->ReceivedInvalidFrame == true)) {
(mstp_port->ReceivedInvalidFrame == true) ||
(mstp_port->ReceivedValidFrameNotForUs == true)) {
if (mstp_port->SoleMaster == true) {
/* SoleMaster */
/* There was no valid reply to the periodic poll */
@@ -1169,6 +1186,7 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port)
}
}
mstp_port->ReceivedInvalidFrame = false;
mstp_port->ReceivedValidFrameNotForUs = false;
}
break;
case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST:
@@ -1246,6 +1264,10 @@ void MSTP_Slave_Node_FSM(struct mstp_port_struct_t *mstp_port)
/* ReceivedInvalidFrame */
/* invalid frame was received */
mstp_port->ReceivedInvalidFrame = false;
} else if (mstp_port->ReceivedValidFrameNotForUs) {
/* ReceivedValidFrameNotForUs */
/* valid frame was received, but not for this node */
mstp_port->ReceivedValidFrameNotForUs = false;
} else if (mstp_port->ReceivedValidFrame) {
mstp_port->ReceivedValidFrame = false;
switch (mstp_port->FrameType) {
@@ -1438,8 +1460,11 @@ static void MSTP_Zero_Config_State_Idle(struct mstp_port_struct_t *mstp_port)
mstp_port->Poll_Count = 0;
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_LURK;
} else if (mstp_port->ReceivedInvalidFrame) {
/* InvalidFrame */
/* IdleInvalidFrame */
mstp_port->ReceivedInvalidFrame = false;
} else if (mstp_port->ReceivedValidFrameNotForUs) {
/* IdleValidFrameNotForUs */
mstp_port->ReceivedValidFrameNotForUs = false;
} else if (mstp_port->Zero_Config_Silence > 0) {
if (mstp_port->SilenceTimer((void *)mstp_port) >
mstp_port->Zero_Config_Silence) {
@@ -1509,6 +1534,9 @@ static void MSTP_Zero_Config_State_Lurk(struct mstp_port_struct_t *mstp_port)
} else if (mstp_port->ReceivedInvalidFrame) {
/* LurkInvalidFrame */
mstp_port->ReceivedInvalidFrame = false;
} else if (mstp_port->ReceivedValidFrameNotForUs) {
/* LurkValidFrameNotForUs */
mstp_port->ReceivedValidFrameNotForUs = false;
} else if (mstp_port->Zero_Config_Silence > 0) {
if (mstp_port->SilenceTimer((void *)mstp_port) >
mstp_port->Zero_Config_Silence) {
@@ -1557,6 +1585,9 @@ static void MSTP_Zero_Config_State_Claim(struct mstp_port_struct_t *mstp_port)
} else if (mstp_port->ReceivedInvalidFrame) {
/* ClaimInvalidFrame */
mstp_port->ReceivedInvalidFrame = false;
} else if (mstp_port->ReceivedValidFrameNotForUs) {
/* ClaimValidFrameNotForUs */
mstp_port->ReceivedValidFrameNotForUs = false;
} else if (mstp_port->Zero_Config_Silence > 0) {
/* ClaimTimeout */
if (mstp_port->SilenceTimer((void *)mstp_port) >
@@ -1617,6 +1648,9 @@ static void MSTP_Zero_Config_State_Confirm(struct mstp_port_struct_t *mstp_port)
} else if (mstp_port->ReceivedInvalidFrame) {
/* ConfirmationInvalidFrame */
mstp_port->ReceivedInvalidFrame = false;
} else if (mstp_port->ReceivedValidFrameNotForUs) {
/* ConfirmationValidFrameNotForUs */
mstp_port->ReceivedValidFrameNotForUs = false;
} else if (
mstp_port->SilenceTimer((void *)mstp_port) >=
mstp_port->Treply_timeout) {
+7
View File
@@ -39,8 +39,15 @@ struct mstp_port_struct_t {
unsigned ReceiveError : 1;
/* There is data in the buffer */
unsigned DataAvailable : 1;
/* A Boolean flag set to TRUE by the Receive State Machine */
/* if an invalid frame is received. */
/* Set to FALSE by the main state machine. */
unsigned ReceivedInvalidFrame : 1;
/* A Boolean flag set to TRUE by the Receive State Machine */
/* if a valid frame is not for us */
/* Set to FALSE by the main state machine. */
unsigned ReceivedValidFrameNotForUs : 1;
/* A Boolean flag set to TRUE by the Receive State Machine */
/* if a valid frame is received. */
/* Set to FALSE by the Master or Slave Node state machine. */
unsigned ReceivedValidFrame : 1;