Feature/mstp extended frames (#529)

* added MSTP extended frames to bacnet/datalink/mstp.c module. Thank you, Simon!

* auto-size some FIFO buffers for MSTP

* add COBS library to MSTP builds

---------

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2023-11-08 15:54:18 -06:00
committed by GitHub
parent 2536d5a350
commit 1372e52aa7
22 changed files with 109 additions and 32 deletions
+24 -5
View File
@@ -18,25 +18,44 @@ The git repositories are hosted at the following sites:
### Added
- Added MSTP extended frames to src/datalink/mstp.c module used by mstpcap (#529)
- Added menu to release script (#506)
### Changed
- Change SubscribeCOV Cancellations to always reply with Result+ (#526)
- Allow processing of Who-Has when DCC initiation is disabled
### Fixed
- Fix BACnet/IP builds for BBMD clients without BBMD tables. (#523)
- Fix decoding empty array of complex type in RPM
- Fix device object ReinitializeDevice service handling examples of
no-password in the device. (#518)
- Fix DeviceCommunicationControl service handling example of
no-password in the device. (#518)
- Fix incorrect apdu_len calculation when encoding Recipient_List
which had resulted in malformed APDU. (#517)
- Fix reinitializing a bacnet stack on windows by checking
for valid socket before cleaning up WSA (#514)
- Fix a warning that 'device_id' is not used (#510)
- Added new linear.c to Microsoft Visual Studio project (#507)
## [1.3.1] - 2023-09-29
### Added
Added example Channel object WriteProperty callback into example Device objects. (#504)
Added Microsoft Visual Studio 2022 Community Edition solution to ports/win32 (#502)
Added details in apps/blinkt example about starting app with systemd (#505)
- Added example Channel object WriteProperty callback into example Device objects. (#504)
- Added Microsoft Visual Studio 2022 Community Edition solution to ports/win32 (#502)
- Added details in apps/blinkt example about starting app with systemd (#505)
### Fixed
Refactored WriteProperty of object-name property rules into example device object (#504)
- Refactored WriteProperty of object-name property rules into example device object (#504)
### Changed
Changed WriteProperty string property checker to ignore length check with zero option.(#504)
- Changed WriteProperty string property checker to ignore length check with zero option.(#504)
## [1.3.0] - 2023-09-28
+1
View File
@@ -392,6 +392,7 @@ add_library(${PROJECT_NAME}
$<$<BOOL:${BACDL_BIP}>:src/bacnet/datalink/bvlc.c>
$<$<BOOL:${BACDL_MSTP}>:src/bacnet/datalink/crc.h>
$<$<BOOL:${BACDL_MSTP}>:src/bacnet/datalink/crc.c>
$<$<BOOL:${BACDL_MSTP}>:src/bacnet/datalink/cobs.h>
$<$<BOOL:${BACDL_MSTP}>:src/bacnet/datalink/cobs.c>
src/bacnet/datalink/datalink.c
src/bacnet/datalink/datalink.h
+1
View File
@@ -19,6 +19,7 @@ SRC = main.c \
PORT_MSTP_SRC = \
$(BACNET_PORT_DIR)/rs485.c \
$(BACNET_PORT_DIR)/dlmstp.c \
$(BACNET_SRC_DIR)/bacnet/datalink/cobs.c \
$(BACNET_SRC_DIR)/bacnet/datalink/mstp.c \
$(BACNET_SRC_DIR)/bacnet/datalink/mstptext.c \
$(BACNET_SRC_DIR)/bacnet/datalink/crc.c
+1
View File
@@ -21,6 +21,7 @@ SRC = main.c \
PORT_MSTP_SRC = \
$(BACNET_PORT_DIR)/rs485.c \
$(BACNET_PORT_DIR)/dlmstp.c \
$(BACNET_SRC_DIR)/bacnet/datalink/cobs.c \
$(BACNET_SRC_DIR)/bacnet/datalink/mstp.c \
$(BACNET_SRC_DIR)/bacnet/datalink/mstptext.c \
$(BACNET_SRC_DIR)/bacnet/datalink/crc.c
+1
View File
@@ -29,6 +29,7 @@ PORT_ARCNET_SRC = \
PORT_MSTP_SRC = \
$(BACNET_PORT_DIR)/rs485.c \
$(BACNET_PORT_DIR)/dlmstp.c \
$(BACNET_SRC_DIR)/bacnet/datalink/cobs.c \
$(BACNET_SRC_DIR)/bacnet/datalink/mstp.c \
$(BACNET_SRC_DIR)/bacnet/datalink/mstptext.c \
$(BACNET_SRC_DIR)/bacnet/datalink/crc.c
+1
View File
@@ -23,6 +23,7 @@ SRCS = main.c \
${BACNET_SRC_DIR}/bacnet/basic/sys/filename.c \
${BACNET_SRC_DIR}/bacnet/basic/sys/mstimer.c \
${BACNET_SRC_DIR}/bacnet/basic/sys/ringbuf.c \
${BACNET_SRC_DIR}/bacnet/datalink/cobs.c \
${BACNET_SRC_DIR}/bacnet/datalink/mstp.c \
${BACNET_SRC_DIR}/bacnet/datalink/mstptext.c \
${BACNET_SRC_DIR}/bacnet/datalink/crc.c
+1
View File
@@ -19,6 +19,7 @@ SRC = main.c \
PORT_MSTP_SRC = \
$(BACNET_PORT_DIR)/rs485.c \
$(BACNET_PORT_DIR)/dlmstp.c \
$(BACNET_SRC_DIR)/bacnet/datalink/cobs.c \
$(BACNET_SRC_DIR)/bacnet/datalink/mstp.c \
$(BACNET_SRC_DIR)/bacnet/datalink/mstptext.c \
$(BACNET_SRC_DIR)/bacnet/datalink/crc.c
+1
View File
@@ -29,6 +29,7 @@ SRCS = main.c \
${BACNET_SOURCE_DIR}/basic/bbmd/h_bbmd.c \
${BACNET_SOURCE_DIR}/datalink/bvlc.c \
${BACNET_SOURCE_DIR}/basic/sys/fifo.c \
${BACNET_SOURCE_DIR}/datalink/cobs.c \
${BACNET_SOURCE_DIR}/datalink/mstp.c \
${BACNET_SOURCE_DIR}/datalink/mstptext.c \
${BACNET_SOURCE_DIR}/basic/sys/debug.c \
+1 -1
View File
@@ -48,7 +48,7 @@ static uint32_t Baud_Rate = 9600;
/* turnaround_time_milliseconds = (Tturnaround*1000UL)/Baud_Rate; */
/* buffer for storing received bytes - size must be power of two */
static uint8_t Receive_Buffer_Data[128];
static uint8_t Receive_Buffer_Data[256];
static FIFO_BUFFER Receive_Buffer;
static struct mstimer Silence_Timer;
+2 -2
View File
@@ -46,9 +46,9 @@ FIFO_BUFFER FIFO_Rx;
FIFO_BUFFER FIFO_Tx;
#pragma udata MSTPPortData
/* the buffer for receiving data (size must be a power of 2) */
volatile uint8_t RS485_Rx_Buffer[128];
volatile uint8_t RS485_Rx_Buffer[NEXT_POWER_OF_2(DLMSTP_MPDU_MAX)];
/* the buffer for sending data (size must be a power of 2) */
volatile uint8_t RS485_Tx_Buffer[128];
volatile uint8_t RS485_Tx_Buffer[NEXT_POWER_OF_2(DLMSTP_MPDU_MAX)];
#pragma udata
/****************************************************************************
+2 -2
View File
@@ -46,9 +46,9 @@ FIFO_BUFFER FIFO_Rx;
FIFO_BUFFER FIFO_Tx;
#pragma udata MSTPPortData
/* the buffer for receiving data (size must be a power of 2) */
volatile uint8_t RS485_Rx_Buffer[128];
volatile uint8_t RS485_Rx_Buffer[NEXT_POWER_OF_2(DLMSTP_MPDU_MAX)];
/* the buffer for sending data (size must be a power of 2) */
volatile uint8_t RS485_Tx_Buffer[128];
volatile uint8_t RS485_Tx_Buffer[NEXT_POWER_OF_2(DLMSTP_MPDU_MAX)];
#pragma udata
/****************************************************************************
+2 -1
View File
@@ -30,12 +30,13 @@
#include "hardware.h"
#include "bacnet/basic/sys/mstimer.h"
#include "bacnet/bits.h"
#include "bacnet/datalink/dlmstp.h"
#include "bacnet/basic/sys/fifo.h"
#include "led.h"
#include "rs485.h"
/* buffer for storing received bytes - size must be power of two */
static uint8_t Receive_Buffer_Data[512];
static uint8_t Receive_Buffer_Data[NEXT_POWER_OF_2(DLMSTP_MPDU_MAX)];
static FIFO_BUFFER Receive_Buffer;
/* amount of silence on the wire */
static struct mstimer Silence_Timer;
+1 -1
View File
@@ -137,7 +137,7 @@ OPTIMIZE_FLAGS += -DNDEBUG
BACNET_FLAGS = -DBACDL_MSTP=1
BACNET_FLAGS += -DBACAPP_ALL
BACNET_FLAGS += -DMAX_APDU=480
BACNET_FLAGS += -DMAX_APDU=1476
BACNET_FLAGS += -DBIG_ENDIAN=0
BACNET_FLAGS += -DMAX_TSM_TRANSACTIONS=0
BACNET_FLAGS += -DMAX_CHARACTER_STRING_BYTES=64
+1 -1
View File
@@ -224,7 +224,7 @@
<state>USE_STDPERIPH_DRIVER</state>
<state>STM32F4XX</state>
<state>BACDL_MSTP</state>
<state>MAX_APDU=480</state>
<state>MAX_APDU=1476</state>
<state>BIG_ENDIAN=0</state>
<state>MAX_TSM_TRANSACTIONS=1</state>
</option>
+5 -4
View File
@@ -33,17 +33,18 @@
#include "bacnet/basic/sys/mstimer.h"
#include "bacnet/bits.h"
#include "bacnet/basic/sys/fifo.h"
#include "bacnet/datalink/dlmstp.h"
#include "bacnet/datalink/mstpdef.h"
#include "rs485.h"
/* buffer for storing received bytes - size must be power of two */
/* BACnet DLMSTP_MPDU_MAX for MS/TP is 501 bytes */
static uint8_t Receive_Queue_Data[512];
/* BACnet DLMSTP_MPDU_MAX for MS/TP is 1501 bytes */
static uint8_t Receive_Queue_Data[NEXT_POWER_OF_2(DLMSTP_MPDU_MAX)];
static FIFO_BUFFER Receive_Queue;
/* buffer for storing bytes to transmit */
/* BACnet DLMSTP_MPDU_MAX for MS/TP is 501 bytes */
static uint8_t Transmit_Queue_Data[512];
/* BACnet DLMSTP_MPDU_MAX for MS/TP is 1501 bytes */
static uint8_t Transmit_Queue_Data[NEXT_POWER_OF_2(DLMSTP_MPDU_MAX)];
static FIFO_BUFFER Transmit_Queue;
/* baud rate of the UART interface */
@@ -201,6 +201,7 @@
<ClCompile Include="..\..\..\..\src\bacnet\lighting.c" />
<ClCompile Include="..\..\..\..\src\bacnet\lso.c" />
<ClCompile Include="..\..\..\..\src\bacnet\memcopy.c" />
<ClCompile Include="..\..\..\..\src\bacnet\datalink\cobs.c" />
<ClCompile Include="..\..\..\..\src\bacnet\datalink\mstp.c" />
<ClCompile Include="..\..\..\..\src\bacnet\datalink\mstptext.c" />
<ClCompile Include="..\..\..\..\src\bacnet\npdu.c" />
@@ -161,6 +161,7 @@
<ClCompile Include="..\..\..\..\src\bacnet\datalink\crc.c" />
<ClCompile Include="..\..\..\..\src\bacnet\datalink\datalink.c" />
<ClCompile Include="..\..\..\..\src\bacnet\datalink\dlenv.c" />
<ClCompile Include="..\..\..\..\src\bacnet\datalink\cobs.c" />
<ClCompile Include="..\..\..\..\src\bacnet\datalink\mstp.c" />
<ClCompile Include="..\..\..\..\src\bacnet\datalink\mstptext.c" />
<ClCompile Include="..\..\..\..\src\bacnet\datetime.c" />
+2 -1
View File
@@ -35,8 +35,9 @@
#include "sysclk.h"
#include "bacnet/basic/sys/fifo.h"
#include "bacnet/basic/sys/mstimer.h"
#include "led.h"
#include "bacnet/datalink/dlmstp.h"
#include "bacnet/datalink/mstpdef.h"
#include "led.h"
/* me! */
#include "rs485.h"
+13 -1
View File
@@ -80,7 +80,7 @@
/* Typical sizes are 50, 128, 206, 480, 1024, and 1476 octets */
/* This is used in constructing messages and to tell others our limits */
/* 50 is the minimum; adjust to your memory and physical layer constraints */
/* Lon=206, MS/TP=480, ARCNET=480, Ethernet=1476, BACnet/IP=1476 */
/* Lon=206, MS/TP=480 or 1476, ARCNET=480, Ethernet=1476, BACnet/IP=1476 */
#if !defined(MAX_APDU)
/* #define MAX_APDU 50 */
/* #define MAX_APDU 1476 */
@@ -96,6 +96,18 @@
#else
#define MAX_APDU 1476
#endif
#elif defined (BACDL_ARCNET)
#if defined(BACNET_SECURITY)
#define MAX_APDU 412
#else
#define MAX_APDU 480
#endif
#elif defined (BACDL_MSTP)
#if defined(BACNET_SECURITY)
#define MAX_APDU 412
#else
#define MAX_APDU 1476
#endif
#else
#if defined(BACNET_SECURITY)
#define MAX_APDU 412
+2
View File
@@ -483,6 +483,8 @@ void dlenv_maintenance_timer(uint16_t elapsed_seconds)
BBMD_Timer_Seconds = (uint16_t)BBMD_TTL_Seconds;
}
}
#else
(void)elapsed_seconds;
#endif
}
+39 -12
View File
@@ -56,6 +56,7 @@
#include "rs485.h"
#include "bacnet/datalink/mstptext.h"
#include "bacnet/npdu.h"
#include "bacnet/datalink/cobs.h"
#ifndef DEBUG_ENABLED
#define DEBUG_ENABLED 0
@@ -532,30 +533,56 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
mstp_port->DataCRC = CRC_Calc_Data(
mstp_port->DataRegister, mstp_port->DataCRC);
mstp_port->DataCRCActualMSB = mstp_port->DataRegister;
mstp_port->InputBuffer[mstp_port->Index] =
mstp_port->DataRegister;
mstp_port->Index++;
/* SKIP_DATA or DATA - no change in state */
} else if (mstp_port->Index == (mstp_port->DataLength + 1)) {
/* CRC2 */
mstp_port->InputBuffer[mstp_port->Index] =
mstp_port->DataRegister;
mstp_port->DataCRC = CRC_Calc_Data(
mstp_port->DataRegister, mstp_port->DataCRC);
mstp_port->DataCRCActualLSB = mstp_port->DataRegister;
printf_receive_data("%s",
mstptext_frame_type((unsigned)mstp_port->FrameType));
/* STATE DATA CRC - no need for new state */
/* indicate the complete reception of a valid frame */
if (mstp_port->DataCRC == 0xF0B8) {
if (mstp_port->receive_state ==
MSTP_RECEIVE_STATE_DATA) {
/* ForUs */
mstp_port->ReceivedValidFrame = true;
if ((mstp_port->FrameType ==
FRAME_TYPE_BACNET_EXTENDED_DATA_EXPECTING_REPLY) ||
(mstp_port->FrameType ==
FRAME_TYPE_BACNET_EXTENDED_DATA_NOT_EXPECTING_REPLY)) {
if (cobs_frame_decode(
&mstp_port->InputBuffer[mstp_port->Index + 1],
mstp_port->InputBufferSize,
mstp_port->InputBuffer, mstp_port->Index + 1)) {
if (mstp_port->receive_state ==
MSTP_RECEIVE_STATE_DATA) {
/* ForUs */
mstp_port->ReceivedValidFrame = true;
} else {
/* NotForUs */
mstp_port->ReceivedValidFrameNotForUs = true;
}
} else {
/* NotForUs */
mstp_port->ReceivedValidFrameNotForUs = true;
mstp_port->ReceivedInvalidFrame = true;
}
} else {
mstp_port->ReceivedInvalidFrame = true;
printf_receive_error("MSTP: Rx Data: BadCRC [%02X]\n",
mstp_port->DataRegister);
/* STATE DATA CRC - no need for new state */
/* indicate the complete reception of a valid frame */
if (mstp_port->DataCRC == 0xF0B8) {
if (mstp_port->receive_state ==
MSTP_RECEIVE_STATE_DATA) {
/* ForUs */
mstp_port->ReceivedValidFrame = true;
} else {
/* NotForUs */
mstp_port->ReceivedValidFrameNotForUs = true;
}
} else {
mstp_port->ReceivedInvalidFrame = true;
printf_receive_error(
"MSTP: Rx Data: BadCRC [%02X]\n",
mstp_port->DataRegister);
}
}
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
} else {
+6 -1
View File
@@ -75,7 +75,12 @@ static INDTEXT_DATA mstp_frame_type_text[] = { { FRAME_TYPE_TOKEN, "TOKEN" },
{ FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY, "BACNET_DATA_EXPECTING_REPLY" },
{ FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY,
"BACNET_DATA_NOT_EXPECTING_REPLY" },
{ FRAME_TYPE_REPLY_POSTPONED, "REPLY_POSTPONED" }, { 0, NULL } };
{ FRAME_TYPE_REPLY_POSTPONED, "REPLY_POSTPONED" },
{ FRAME_TYPE_BACNET_EXTENDED_DATA_EXPECTING_REPLY,
"BACNET_EXTENDED_DATA_EXPECTING_REPLY" },
{ FRAME_TYPE_BACNET_EXTENDED_DATA_NOT_EXPECTING_REPLY,
"BACNET_EXTENDED_DATA_NOT_EXPECTING_REPLY" },
{ FRAME_TYPE_IPV6_ENCAPSULATION, "IPV6_ENCAPSULATION" }, { 0, NULL } };
const char *mstptext_frame_type(unsigned index)
{