Added MSTP extended frame transmit. (#531)

* Added MSTP extended frame transmit to bacnet/datalink/mstp.c and ports/stm32f4xx/dlmstp.c modules.

* Changed RS485_Send_Frame to MSTP_Send_Frame in mstp.c

---------

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2023-11-12 09:49:37 -06:00
committed by GitHub
parent 1372e52aa7
commit 3c94580bee
16 changed files with 391 additions and 84 deletions
+1
View File
@@ -60,6 +60,7 @@ BACNET_SRC = \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
$(BACNET_CORE)/bacstr.c \
$(BACNET_CORE)/datalink/cobs.c \
$(BACNET_CORE)/datalink/crc.c \
$(BACNET_CORE)/datetime.c \
$(BACNET_CORE)/dcc.c \
+3
View File
@@ -1138,6 +1138,9 @@
</group>
<group>
<name>BACnet Datalink</name>
<file>
<name>$PROJ_DIR$\..\..\src\bacnet\datalink\cobs.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\src\bacnet\datalink\crc.c</name>
</file>
+83 -22
View File
@@ -37,10 +37,11 @@
#include <stddef.h>
#include <string.h>
#include "bacnet/bacdef.h"
#include "bacnet/datalink/cobs.h"
#include "bacnet/datalink/crc.h"
#include "bacnet/datalink/dlmstp.h"
#include "bacnet/datalink/mstpdef.h"
#include "rs485.h"
#include "bacnet/datalink/crc.h"
#include "bacnet/npdu.h"
#include "bacnet/bits.h"
#include "bacnet/bytes.h"
@@ -363,6 +364,10 @@ static uint16_t MSTP_Create_Frame(uint8_t *buffer,
uint16_t crc16 = 0xFFFF;
/* used to load the data portion of the frame */
uint16_t index = 0;
/* length of the COBS encoded frame */
uint16_t cobs_len;
/* true for COBS BACnet frames */
bool cobs_bacnet_frame = false;
/* not enough to do a header */
if (buffer_size < 8)
@@ -381,25 +386,58 @@ static uint16_t MSTP_Create_Frame(uint8_t *buffer,
buffer[6] = data_len & 0xFF;
crc8 = CRC_Calc_Header(buffer[6], crc8);
buffer[7] = ~crc8;
index = 8;
while (data_len && data && (index < buffer_size)) {
buffer[index] = *data;
crc16 = CRC_Calc_Data(buffer[index], crc16);
data++;
index++;
data_len--;
}
/* append the data CRC if necessary */
if (index > 8) {
if ((index + 2) <= buffer_size) {
crc16 = ~crc16;
buffer[index] = crc16 & 0xFF; /* LSB first */
index++;
buffer[index] = crc16 >> 8;
index++;
} else
if ((data_len > 501) || ((frame_type >= Nmin_COBS_type) &&
(frame_type <= Nmax_COBS_type))) {
/* COBS encoded frame */
if (frame_type == FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY) {
frame_type = FRAME_TYPE_BACNET_EXTENDED_DATA_EXPECTING_REPLY;
cobs_bacnet_frame = true;
} else if (frame_type == FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY) {
frame_type = FRAME_TYPE_BACNET_EXTENDED_DATA_NOT_EXPECTING_REPLY;
cobs_bacnet_frame = true;
} else if ((frame_type < Nmin_COBS_type) ||
(frame_type > Nmax_COBS_type)) {
/* I'm sorry, Dave, I'm afraid I can't do that. */
return 0;
}
cobs_len = cobs_frame_encode(buffer, buffer_size, data, data_len);
/* check the results of COBs encoding for validity */
if (cobs_bacnet_frame) {
if (cobs_len < Nmin_COBS_length_BACnet) {
return 0;
} else if (cobs_len > Nmax_COBS_length_BACnet) {
return 0;
}
} else {
if (cobs_len < Nmin_COBS_length) {
return 0;
} else if (cobs_len > Nmax_COBS_length) {
return 0;
}
}
/* for COBS, we must subtract two before use as the
MS/TP frame length field since CRC32 is 2 bytes longer
than CRC16 in original MSTP and non-COBS devices need
to be able to ingest the entire frame */
index = index + cobs_len - 2;
} else if (data_len > 0) {
while (data_len && data && (index < buffer_size)) {
buffer[index] = *data;
crc16 = CRC_Calc_Data(buffer[index], crc16);
data++;
index++;
data_len--;
}
if ((index + 2) > buffer_size) {
return 0;
}
crc16 = ~crc16;
buffer[index] = crc16 & 0xFF; /* LSB first */
index++;
buffer[index] = crc16 >> 8;
index++;
}
return index; /* returns the frame length */
@@ -653,13 +691,37 @@ static void MSTP_Receive_Frame_FSM(void)
} else if (Index == DataLength) {
/* CRC1 */
DataCRC = CRC_Calc_Data(DataRegister, DataCRC);
if (Index < InputBufferSize) {
InputBuffer[Index] = DataRegister;
}
Index++;
} else if (Index == (DataLength + 1)) {
/* CRC2 */
DataCRC = CRC_Calc_Data(DataRegister, DataCRC);
/* STATE DATA CRC - no need for new state */
/* indicate the complete reception of a valid frame */
if (DataCRC == 0xF0B8) {
if (Index < InputBufferSize) {
InputBuffer[Index] = DataRegister;
}
if ((FrameType >= Nmin_COBS_type) &&
(FrameType <= Nmax_COBS_type)) {
if (((Index+1) < InputBufferSize) &&
cobs_frame_decode(
&InputBuffer[Index + 1],
InputBufferSize,
InputBuffer, Index + 1)) {
if (Receive_State ==
MSTP_RECEIVE_STATE_DATA) {
/* ForUs */
MSTP_Flag.ReceivedValidFrame = true;
} else {
/* NotForUs */
MSTP_Flag.ReceivedValidFrameNotForUs = true;
}
} else {
MSTP_Flag.ReceivedInvalidFrame = true;
}
} else if (DataCRC == 0xF0B8) {
/* STATE DATA CRC - no need for new state */
/* indicate the complete reception of a valid frame */
if (Receive_State == MSTP_RECEIVE_STATE_DATA) {
/* ForUs */
MSTP_Flag.ReceivedValidFrame = true;
@@ -678,7 +740,6 @@ static void MSTP_Receive_Frame_FSM(void)
Frame_Rx_Callback(source, destination, frame,
InputBuffer, DataLength);
}
} else {
MSTP_Flag.ReceivedInvalidFrame = true;
}