diff --git a/ports/at91sam7s/dlmstp.c b/ports/at91sam7s/dlmstp.c index 607a8230..c2bbde89 100644 --- a/ports/at91sam7s/dlmstp.c +++ b/ports/at91sam7s/dlmstp.c @@ -1276,7 +1276,10 @@ uint16_t dlmstp_receive(BACNET_ADDRESS *src, /* source address */ } /* if there is a packet that needs processed, do it now. */ if (MSTP_Flag.ReceivePacketPending) { - MSTP_Flag.ReceivePacketPending = false; + if (This_Station <= 127) { + /* master nodes clear immediately */ + MSTP_Flag.ReceivePacketPending = false; + } pdu_len = DataLength; src->mac_len = 1; src->mac[0] = SourceAddress; diff --git a/ports/bdk-atxx4-mstp/dlmstp.c b/ports/bdk-atxx4-mstp/dlmstp.c index 750d6bb9..8d0a11f7 100644 --- a/ports/bdk-atxx4-mstp/dlmstp.c +++ b/ports/bdk-atxx4-mstp/dlmstp.c @@ -1309,7 +1309,10 @@ uint16_t dlmstp_receive(BACNET_ADDRESS *src, /* source address */ } /* if there is a packet that needs processed, do it now. */ if (MSTP_Flag.ReceivePacketPending) { - MSTP_Flag.ReceivePacketPending = false; + if (This_Station <= 127) { + /* master nodes clear immediately */ + MSTP_Flag.ReceivePacketPending = false; + } pdu_len = DataLength; src->mac_len = 1; src->mac[0] = SourceAddress; diff --git a/ports/stm32f10x/dlmstp.c b/ports/stm32f10x/dlmstp.c index 458b9f11..a0b8b056 100644 --- a/ports/stm32f10x/dlmstp.c +++ b/ports/stm32f10x/dlmstp.c @@ -733,68 +733,70 @@ static void MSTP_Receive_Frame_FSM(void) static void MSTP_Slave_Node_FSM(void) { - /* destination address */ - uint8_t destination; - /* source address */ - uint8_t source; - /* any data to be sent - may be null */ - uint8_t *data; - /* amount of data to be sent - may be 0 */ - uint16_t data_len; - /* packet from the PDU Queue */ - struct dlmstp_packet *pkt; - - if (MSTP_Flag.ReceivedInvalidFrame) { + Master_State = MSTP_MASTER_STATE_IDLE; + if (MSTP_Flag.ReceivedInvalidFrame == true) { /* ReceivedInvalidFrame */ /* invalid frame was received */ MSTP_Flag.ReceivedInvalidFrame = false; } else if (MSTP_Flag.ReceivedValidFrame) { + MSTP_Flag.ReceivedValidFrame = false; switch (FrameType) { case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { - /* The ANSWER_DATA_REQUEST state is entered when a */ - /* BACnet Data Expecting Reply, a Test_Request, or */ - /* a proprietary frame that expects a reply is received. */ - pkt = (struct dlmstp_packet *)Ringbuf_Peek(&PDU_Queue); - if (pkt != NULL) { - MSTP_Send_Frame(pkt->frame_type, pkt->address.mac[0], - This_Station, (uint8_t *)&pkt->pdu[0], - pkt->pdu_len); - Master_State = MSTP_MASTER_STATE_IDLE; - /* clear our flag we were holding for comparison */ - MSTP_Flag.ReceivedValidFrame = false; - /* clear the queue */ - (void)Ringbuf_Pop(&PDU_Queue, NULL); - } else if (rs485_silence_elapsed(Treply_delay)) { - /* If no reply will be available from the higher layers - within Treply_delay after the reception of the final - octet of the requesting frame (the mechanism used - to determine this is a local matter), then no reply - is possible. */ - MSTP_Flag.ReceivedValidFrame = false; - } - } else { - /* no reply when addressed as Broadcast */ - MSTP_Flag.ReceivedValidFrame = false; + /* indicate successful reception to the higher layers */ + MSTP_Flag.ReceivePacketPending = true; } break; case FRAME_TYPE_TEST_REQUEST: - MSTP_Flag.ReceivedValidFrame = false; - destination = SourceAddress; - source = This_Station; - data = &InputBuffer[0]; - data_len = DataLength; - MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE, destination, source, - data, data_len); + MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE, SourceAddress, + This_Station, &InputBuffer[0], DataLength); break; case FRAME_TYPE_TOKEN: case FRAME_TYPE_POLL_FOR_MASTER: case FRAME_TYPE_TEST_RESPONSE: case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: default: - MSTP_Flag.ReceivedValidFrame = false; break; } + } else if (MSTP_Flag.ReceivePacketPending) { + if (!Ringbuf_Empty(&PDU_Queue)) { + /* packet from the PDU Queue */ + struct mstp_pdu_packet *pkt; + /* did the frame in the queue match the last request? */ + bool matched; + + pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&PDU_Queue); + matched = dlmstp_compare_data_expecting_reply(&InputBuffer[0], + DataLength, SourceAddress, &pkt->buffer[0], pkt->length, + pkt->destination_mac); + if (matched) { + /* Reply */ + /* If a reply is available from the higher layers */ + /* within Treply_delay after the reception of the */ + /* final octet of the requesting frame */ + /* (the mechanism used to determine this is a local matter), */ + /* then call MSTP_Send_Frame to transmit the reply frame */ + /* and enter the IDLE state to wait for the next frame. */ + uint8_t frame_type; + if (pkt->data_expecting_reply) { + frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; + } else { + frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY; + } + MSTP_Send_Frame(frame_type, pkt->destination_mac, This_Station, + (uint8_t *)&pkt->buffer[0], pkt->length); + (void)Ringbuf_Pop(&PDU_Queue, NULL); + } + /* clear our flag we were holding for comparison */ + MSTP_Flag.ReceivePacketPending = false; + } else if ((rs485_silence_elapsed(Treply_delay))) { + /* If no reply will be available from the higher layers + within Treply_delay after the reception of the final octet + of the requesting frame (the mechanism used to determine + this is a local matter), then no reply is possible. */ + /* clear our flag we were holding for comparison */ + MSTP_Flag.ReceivePacketPending = false; + } } } @@ -1645,7 +1647,10 @@ uint16_t dlmstp_receive(BACNET_ADDRESS *src, /* source address */ if (This_Station != 255) { /* if there is a packet that needs processed, do it now. */ if (MSTP_Flag.ReceivePacketPending) { - MSTP_Flag.ReceivePacketPending = false; + if (This_Station <= 127) { + /* master nodes clear immediately */ + MSTP_Flag.ReceivePacketPending = false; + } pdu_len = DataLength; src->mac_len = 1; src->mac[0] = SourceAddress; diff --git a/ports/stm32f4xx/dlmstp.c b/ports/stm32f4xx/dlmstp.c index 105a75c1..c07b46f4 100644 --- a/ports/stm32f4xx/dlmstp.c +++ b/ports/stm32f4xx/dlmstp.c @@ -776,68 +776,64 @@ void log_master_state(MSTP_MASTER_STATE state) static void MSTP_Slave_Node_FSM(void) { - /* destination address */ - uint8_t destination; - /* source address */ - uint8_t source; - /* any data to be sent - may be null */ - uint8_t *data; - /* amount of data to be sent - may be 0 */ - uint16_t data_len; - /* packet from the PDU Queue */ - struct dlmstp_packet *pkt; - - if (MSTP_Flag.ReceivedInvalidFrame) { + Master_State = MSTP_MASTER_STATE_IDLE; + if (MSTP_Flag.ReceivedInvalidFrame == true) { /* ReceivedInvalidFrame */ /* invalid frame was received */ MSTP_Flag.ReceivedInvalidFrame = false; } else if (MSTP_Flag.ReceivedValidFrame) { + MSTP_Flag.ReceivedValidFrame = false; switch (FrameType) { case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { - /* The ANSWER_DATA_REQUEST state is entered when a */ - /* BACnet Data Expecting Reply, a Test_Request, or */ - /* a proprietary frame that expects a reply is received. */ - pkt = (struct dlmstp_packet *)Ringbuf_Peek(&PDU_Queue); - if (pkt != NULL) { - MSTP_Send_Frame(pkt->frame_type, pkt->address.mac[0], - This_Station, (uint8_t *)&pkt->pdu[0], - pkt->pdu_len); - Master_State = MSTP_MASTER_STATE_IDLE; - /* clear our flag we were holding for comparison */ - MSTP_Flag.ReceivedValidFrame = false; - /* clear the queue */ - (void)Ringbuf_Pop(&PDU_Queue, NULL); - } else if (rs485_silence_elapsed(Treply_delay)) { - /* If no reply will be available from the higher layers - within Treply_delay after the reception of the final - octet of the requesting frame (the mechanism used - to determine this is a local matter), then no reply - is possible. */ - MSTP_Flag.ReceivedValidFrame = false; - } - } else { - /* no reply when addressed as Broadcast */ - MSTP_Flag.ReceivedValidFrame = false; + /* indicate successful reception to the higher layers */ + MSTP_Flag.ReceivePacketPending = true; } break; case FRAME_TYPE_TEST_REQUEST: - MSTP_Flag.ReceivedValidFrame = false; - destination = SourceAddress; - source = This_Station; - data = &InputBuffer[0]; - data_len = DataLength; - MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE, destination, source, - data, data_len); + MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE, SourceAddress, + This_Station, &InputBuffer[0], DataLength); break; case FRAME_TYPE_TOKEN: case FRAME_TYPE_POLL_FOR_MASTER: case FRAME_TYPE_TEST_RESPONSE: case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: default: - MSTP_Flag.ReceivedValidFrame = false; break; } + } else if (MSTP_Flag.ReceivePacketPending) { + if (!Ringbuf_Empty(&PDU_Queue)) { + /* packet from the PDU Queue */ + struct dlmstp_packet *pkt; + /* did the frame in the queue match the last request? */ + bool matched; + + pkt = (struct dlmstp_packet *)Ringbuf_Peek(&PDU_Queue); + matched = dlmstp_compare_data_expecting_reply(&InputBuffer[0], + DataLength, SourceAddress, &pkt->pdu[0], pkt->pdu_len, + pkt->address.mac[0]); + if (matched) { + /* Reply */ + /* If a reply is available from the higher layers */ + /* within Treply_delay after the reception of the */ + /* final octet of the requesting frame */ + /* (the mechanism used to determine this is a local matter), */ + /* then call MSTP_Send_Frame to transmit the reply frame */ + /* and enter the IDLE state to wait for the next frame. */ + MSTP_Send_Frame(pkt->frame_type, pkt->address.mac[0], + This_Station, pkt->pdu, pkt->pdu_len); + (void)Ringbuf_Pop(&PDU_Queue, NULL); + } + /* clear our flag we were holding for comparison */ + MSTP_Flag.ReceivePacketPending = false; + } else if ((rs485_silence_elapsed(Treply_delay))) { + /* If no reply will be available from the higher layers + within Treply_delay after the reception of the final octet + of the requesting frame (the mechanism used to determine + this is a local matter), then no reply is possible. */ + /* clear our flag we were holding for comparison */ + MSTP_Flag.ReceivePacketPending = false; + } } } @@ -1511,7 +1507,10 @@ uint16_t dlmstp_receive( } /* if there is a packet that needs processed, do it now. */ if (MSTP_Flag.ReceivePacketPending) { - MSTP_Flag.ReceivePacketPending = false; + if (This_Station <= 127) { + /* master nodes clear immediately */ + MSTP_Flag.ReceivePacketPending = false; + } Statistics.receive_pdu_counter++; pdu_len = DataLength; src->mac_len = 1; diff --git a/ports/xplained/dlmstp.c b/ports/xplained/dlmstp.c index 9f51131b..0f387b79 100644 --- a/ports/xplained/dlmstp.c +++ b/ports/xplained/dlmstp.c @@ -634,75 +634,70 @@ void log_master_state(MSTP_MASTER_STATE state) static void MSTP_Slave_Node_FSM(void) { - /* destination address */ - uint8_t destination; - /* source address */ - uint8_t source; - /* any data to be sent - may be null */ - uint8_t *data; - /* amount of data to be sent - may be 0 */ - uint16_t data_len; - /* packet from the PDU Queue */ - struct mstp_pdu_packet *pkt; - - if (MSTP_Flag.ReceivedInvalidFrame) { + Master_State = MSTP_MASTER_STATE_IDLE; + if (MSTP_Flag.ReceivedInvalidFrame == true) { /* ReceivedInvalidFrame */ /* invalid frame was received */ MSTP_Flag.ReceivedInvalidFrame = false; } else if (MSTP_Flag.ReceivedValidFrame) { + MSTP_Flag.ReceivedValidFrame = false; switch (FrameType) { case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { - /* The ANSWER_DATA_REQUEST state is entered when a */ - /* BACnet Data Expecting Reply, a Test_Request, or */ - /* a proprietary frame that expects a reply is received. */ - pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&PDU_Queue); - if (pkt != NULL) { - uint8_t frame_type; - if (pkt->data_expecting_reply) { - frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; - } else { - frame_type = - FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY; - } - MSTP_Send_Frame(frame_type, pkt->destination_mac, - This_Station, (uint8_t *)&pkt->buffer[0], - pkt->length); - Master_State = MSTP_MASTER_STATE_IDLE; - /* clear our flag we were holding for comparison */ - MSTP_Flag.ReceivedValidFrame = false; - /* clear the queue */ - (void)Ringbuf_Pop(&PDU_Queue, NULL); - } else if (rs485_silence_elapsed(Treply_delay)) { - /* If no reply will be available from the higher layers - within Treply_delay after the reception of the final - octet of the requesting frame (the mechanism used - to determine this is a local matter), then no reply - is possible. */ - MSTP_Flag.ReceivedValidFrame = false; - } - } else { - /* no reply when addressed as Broadcast */ - MSTP_Flag.ReceivedValidFrame = false; + /* indicate successful reception to the higher layers */ + MSTP_Flag.ReceivePacketPending = true; } break; case FRAME_TYPE_TEST_REQUEST: - MSTP_Flag.ReceivedValidFrame = false; - destination = SourceAddress; - source = This_Station; - data = &InputBuffer[0]; - data_len = DataLength; - MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE, destination, source, - data, data_len); + MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE, SourceAddress, + This_Station, &InputBuffer[0], DataLength); break; case FRAME_TYPE_TOKEN: case FRAME_TYPE_POLL_FOR_MASTER: case FRAME_TYPE_TEST_RESPONSE: case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: default: - MSTP_Flag.ReceivedValidFrame = false; break; } + } else if (MSTP_Flag.ReceivePacketPending) { + if (!Ringbuf_Empty(&PDU_Queue)) { + /* packet from the PDU Queue */ + struct mstp_pdu_packet *pkt; + /* did the frame in the queue match the last request? */ + bool matched; + + pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&PDU_Queue); + matched = dlmstp_compare_data_expecting_reply(&InputBuffer[0], + DataLength, SourceAddress, &pkt->buffer[0], pkt->length, + pkt->destination_mac); + if (matched) { + /* Reply */ + /* If a reply is available from the higher layers */ + /* within Treply_delay after the reception of the */ + /* final octet of the requesting frame */ + /* (the mechanism used to determine this is a local matter), */ + /* then call MSTP_Send_Frame to transmit the reply frame */ + /* and enter the IDLE state to wait for the next frame. */ + uint8_t frame_type; + if (pkt->data_expecting_reply) { + frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; + } else { + frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY; + } + MSTP_Send_Frame(frame_type, pkt->destination_mac, This_Station, + (uint8_t *)&pkt->buffer[0], pkt->length); + (void)Ringbuf_Pop(&PDU_Queue, NULL); + } + /* clear our flag we were holding for comparison */ + MSTP_Flag.ReceivePacketPending = false; + } else if ((rs485_silence_elapsed(Treply_delay))) { + /* If no reply will be available from the higher layers + within Treply_delay after the reception of the final octet + of the requesting frame (the mechanism used to determine + this is a local matter), then no reply is possible. */ + /* clear our flag we were holding for comparison */ + MSTP_Flag.ReceivePacketPending = false; + } } } @@ -1370,7 +1365,10 @@ uint16_t dlmstp_receive( } /* if there is a packet that needs processed, do it now. */ if (MSTP_Flag.ReceivePacketPending) { - MSTP_Flag.ReceivePacketPending = false; + if (This_Station <= 127) { + /* master nodes clear immediately */ + MSTP_Flag.ReceivePacketPending = false; + } pdu_len = DataLength; src->mac_len = 1; src->mac[0] = SourceAddress;