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
+24 -11
View File
@@ -18,13 +18,18 @@ 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 MSTP extended frames transmit to src/datalink/mstp.c
and ports/stm32f4xx/dlmstp.c modules (#531)
- 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
- Changed SubscribeCOV Cancellations to always reply with Result+ (#526)
- Changed Who-Has to process when DCC initiation is disabled
- Changed mstp.c external API to remove rs485.h dependency
for send frame. (#531)
### Fixed
@@ -55,30 +60,38 @@ The git repositories are hosted at the following sites:
### 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
### Added
- Added [feature#14] EventTimeStamp decoding from ReadPropertyMultiple app. (#503)
- Added Channel, Color, Color Temperature, & Lighting Output demo app with Blinkt! (#503)
- Added pipeline build of piface and blinkt apps with Raspberry Pi OS image. (#503)
- Added Channel, Color, Color Temperature, & Lighting Output demo
app with Blinkt! (#503)
- Added pipeline build of piface and blinkt apps with Raspberry Pi
OS image. (#503)
- Added linear interpolation library functions used in fading and ramping. (#503)
### Changed
- Added Device timer API to feed elapsed milliseconds to children objects. (#503)
- Changed gitignore to ease the maintainenance of source files in app folder. (#503)
- Changed example server app device simulator to use mstimer instead of OS time. (#503)
- Added Device timer API to feed elapsed milliseconds to children
objects. (#503)
- Changed gitignore to ease the maintainenance of source files in
app folder. (#503)
- Changed example server app device simulator to use mstimer instead
of OS time. (#503)
- Changed example channel object to be dynamically created or deleted. (#503)
- Changed example channel object to handle color & color temperature objects. (#503)
- Changed example channel object to handle color & color temperature
objects. (#503)
### Fixed
- Fixed datetime decode of invalid application tag. (#495)
- Fixed extraneous SO_BINDTODEVICE error message in Linux BIP. (#498)
- Fixed example Color, Color Temperature, and Lighting object fade, ramp, and step. (#503)
- Fixed example Color, Color Temperature, and Lighting object fade,
ramp, and step. (#503)
- Fixed and secured BACnetXYcolor and ColorCommand codecs. (#503)
## [1.2.0] - 2023-09-11
+16
View File
@@ -430,6 +430,22 @@ uint16_t MSTP_Get_Send(
return 0;
}
/**
* @brief Send an MSTP frame
* @param mstp_port - port specific data
* @param buffer - data to send
* @param nbytes - number of bytes of data to send
*/
void MSTP_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port,
uint8_t * buffer,
uint16_t nbytes)
{
(void)mstp_port;
(void)buffer;
(void)nbytes;
}
uint16_t MSTP_Get_Reply(
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
{ /* milliseconds to wait for a packet */
+16
View File
@@ -164,6 +164,7 @@ static uint32_t Timer_Silence(void *pArg)
struct timespec now, diff;
int32_t res;
(void)pArg;
clock_gettime(CLOCK_MONOTONIC, &now);
timespec_subtract(&diff, &now, &start);
res = ((diff.tv_sec) * 1000 + (diff.tv_nsec) / 1000000);
@@ -173,6 +174,7 @@ static uint32_t Timer_Silence(void *pArg)
static void Timer_Silence_Reset(void *pArg)
{
(void)pArg;
clock_gettime(CLOCK_MONOTONIC, &start);
}
@@ -412,6 +414,20 @@ uint16_t MSTP_Get_Send(
return pdu_len;
}
/**
* @brief Send an MSTP frame
* @param mstp_port - port specific data
* @param buffer - data to send
* @param nbytes - number of bytes of data to send
*/
void MSTP_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port,
uint8_t * buffer,
uint16_t nbytes)
{
RS485_Send_Frame(mstp_port, buffer, nbytes);
}
static bool dlmstp_compare_data_expecting_reply(uint8_t *request_pdu,
uint16_t request_pdu_len,
uint8_t src_address,
+14
View File
@@ -384,6 +384,20 @@ uint16_t MSTP_Get_Send(
return pdu_len;
}
/**
* @brief Send an MSTP frame
* @param mstp_port - port specific data
* @param buffer - data to send
* @param nbytes - number of bytes of data to send
*/
void MSTP_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port,
uint8_t * buffer,
uint16_t nbytes)
{
RS485_Send_Frame(mstp_port, buffer, nbytes);
}
bool dlmstp_compare_data_expecting_reply(uint8_t *request_pdu,
uint16_t request_pdu_len,
uint8_t src_address,
+16
View File
@@ -100,6 +100,22 @@ uint16_t MSTP_Get_Send(
return 0;
}
/**
* @brief Send an MSTP frame
* @param mstp_port - port specific data
* @param buffer - data to send
* @param nbytes - number of bytes of data to send
*/
void MSTP_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port,
uint8_t * buffer,
uint16_t nbytes)
{
(void)mstp_port;
(void)buffer;
(void)nbytes;
}
uint16_t MSTP_Get_Reply(
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
{ /* milliseconds to wait for a packet */
+16
View File
@@ -125,6 +125,22 @@ uint16_t MSTP_Get_Send(
return 0;
}
/**
* @brief Send an MSTP frame
* @param mstp_port - port specific data
* @param buffer - data to send
* @param nbytes - number of bytes of data to send
*/
void MSTP_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port,
uint8_t * buffer,
uint16_t nbytes)
{
(void)mstp_port;
(void)buffer;
(void)nbytes;
}
uint16_t MSTP_Get_Reply(
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
{ /* milliseconds to wait for a packet */
+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>
+70 -9
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,8 +386,43 @@ 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;
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);
@@ -390,16 +430,14 @@ static uint16_t MSTP_Create_Frame(uint8_t *buffer,
index++;
data_len--;
}
/* append the data CRC if necessary */
if (index > 8) {
if ((index + 2) <= buffer_size) {
if ((index + 2) > buffer_size) {
return 0;
}
crc16 = ~crc16;
buffer[index] = crc16 & 0xFF; /* LSB first */
index++;
buffer[index] = crc16 >> 8;
index++;
} else
return 0;
}
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);
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 (DataCRC == 0xF0B8) {
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;
}
+14
View File
@@ -296,6 +296,20 @@ uint16_t MSTP_Get_Send(
return pdu_len;
}
/**
* @brief Send an MSTP frame
* @param mstp_port - port specific data
* @param buffer - data to send
* @param nbytes - number of bytes of data to send
*/
void MSTP_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port,
uint8_t * buffer,
uint16_t nbytes)
{
RS485_Send_Frame(mstp_port, buffer, nbytes);
}
bool dlmstp_compare_data_expecting_reply(uint8_t *request_pdu,
uint16_t request_pdu_len,
uint8_t src_address,
+14
View File
@@ -281,6 +281,20 @@ uint16_t MSTP_Get_Send(
return pdu_len;
}
/**
* @brief Send an MSTP frame
* @param mstp_port - port specific data
* @param buffer - data to send
* @param nbytes - number of bytes of data to send
*/
void MSTP_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port,
uint8_t * buffer,
uint16_t nbytes)
{
RS485_Send_Frame(mstp_port, buffer, nbytes);
}
static bool dlmstp_compare_data_expecting_reply(uint8_t *request_pdu,
uint16_t request_pdu_len,
uint8_t src_address,
+16
View File
@@ -130,6 +130,22 @@ uint16_t MSTP_Get_Send(
return 0;
}
/**
* @brief Send an MSTP frame
* @param mstp_port - port specific data
* @param buffer - data to send
* @param nbytes - number of bytes of data to send
*/
void MSTP_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port,
uint8_t * buffer,
uint16_t nbytes)
{
(void)mstp_port;
(void)buffer;
(void)nbytes;
}
uint16_t MSTP_Get_Reply(
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
{ /* milliseconds to wait for a packet */
+4 -4
View File
@@ -77,7 +77,7 @@ uint32_t cobs_crc32k(uint8_t dataValue, uint32_t crc32kValue)
/**
* @brief Encodes 'length' octets of data located at 'from' and
* writes one or more COBS code blocks at 'to', removing
* writes one or more COBS code blocks at 'buffer', removing
* any 0x55 octets that may present be in the encoded data.
* @param buffer - encoded buffer
* @param buffer_size - encoded buffer size
@@ -154,7 +154,7 @@ size_t cobs_encode(uint8_t *buffer,
}
/**
* @brief Encodes 'length' octets of client data located at 'from' and writes
* the COBS-encoded Encoded Data and Encoded CRC-32K fields at 'to'.
* the COBS-encoded Encoded Data and Encoded CRC-32K fields at 'buffer'.
* @param buffer - encoded buffer
* @param buffer_size - encoded buffer size
* @param from - buffer to encode
@@ -206,7 +206,7 @@ size_t cobs_frame_encode(
/**
* @brief Decodes 'length' octets of data located at 'from' and
* writes the original client data at 'to', restoring any
* writes the original client data at 'buffer', restoring any
* 'mask' octets that may present in the encoded data.
* @param buffer - decoded buffer
* @param buffer_size - decoded buffer size
@@ -266,7 +266,7 @@ size_t cobs_decode(uint8_t *buffer,
/**
* Decodes Encoded Data and Encoded CRC-32K fields at 'from' and
* writes the decoded client data at 'to'. Assumes 'length' contains
* writes the decoded client data at 'buffer'. Assumes 'length' contains
* the actual combined length of these fields in octets (that is, the
* MS/TP header Length field plus two).
* @param buffer - decoded buffer
+32
View File
@@ -33,6 +33,38 @@
/* inclusive extra bytes needed for APDU */
#define COBS_ENCODED_SIZE(a) ((a)+((a)/254)+1)
/* The first COBS-encoded Frame Type value: 32. */
#define Nmin_COBS_type 32
/* The last COBS-encoded Frame Type value: 127. */
#define Nmax_COBS_type 127
/* The minimum valid Length value of any COBS-encoded frame: 5.
The theoretical minimum Length is calculated as follows:
COBS-encoded frames must contain at least one data octet.
The minimum COBS encoding overhead for the Encoded Data
field is one octet. The size of the Encoded CRC-32K field
is always five octets. Adding the lengths of these fields
and subtracting two (for backward compatibility) results
in a minimum Length value of five (1 + 1 + 5 - 2). In practice,
the minimum Length value is determined by the network-layer
client and is likely to be larger (e.g., for BACnet the minimum
Length is 502 + 1 + 3 = 506. */
#define Nmin_COBS_length 5
#define Nmin_COBS_length_BACnet 506
/* The maximum valid Length value of any COBS-encoded frame: 2043.
The theoretical maximum Length is calculated as follows:
the largest data parameter that any future network client
may specify is 2032 octets (this is near the limit of the
CRC-32K's maximum error-detection capability). The worst-case
COBS encoding overhead for the Encoded Data field would be
2032 / 254 = 8 octets. Adding in the size adjustment for the
Encoded CRC-32K results in a maximum Length value of
2032 + 8 + 3 = 2043. In practice, the maximum Length value is
determined by the network-layer client and is likely to be
smaller (e.g., for BACnet the maximum Length is 1497 + 6 + 3 = 1506. */
#define Nmax_COBS_length 2043
#define Nmax_COBS_length_BACnet 1506
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
+102 -34
View File
@@ -51,12 +51,11 @@
#if PRINT_ENABLED
#include <stdio.h>
#endif
#include "bacnet/datalink/cobs.h"
#include "bacnet/datalink/crc.h"
#include "bacnet/datalink/mstp.h"
#include "crc.h"
#include "rs485.h"
#include "bacnet/datalink/mstptext.h"
#include "bacnet/npdu.h"
#include "bacnet/datalink/cobs.h"
#ifndef DEBUG_ENABLED
#define DEBUG_ENABLED 0
@@ -199,23 +198,48 @@ void MSTP_Fill_BACnet_Address(BACNET_ADDRESS *src, uint8_t mstp_address)
}
}
uint16_t MSTP_Create_Frame(uint8_t *buffer, /* where frame is loaded */
uint16_t buffer_len, /* amount of space available */
uint8_t frame_type, /* type of frame to send - see defines */
uint8_t destination, /* destination address */
uint8_t source, /* source address */
uint8_t *data, /* any data to be sent - may be null */
/**
* @brief Create an MS/TP Frame
*
* All MS/TP frames are of the following format:
* Preamble: two octet preamble: X`55', X`FF'
* Frame Type: one octet
* Destination Address: one octet address
* Source Address: one octet address
* Length: two octets, most significant octet first, of the Data field
* Header CRC: one octet
* Data: (present only if Length is non-zero)
* Data CRC: (present only if Length is non-zero) two octets,
* least significant octet first
* (pad): (optional) at most one octet of padding: X'FF'
*
* @param buffer - where frame is loaded
* @param buffer_size - amount of space available in the buffer
* @param frame_type - type of frame to send - see defines
* @param destination - destination address
* @param source - source address
* @param data - any data to be sent - may be null
* @param data_len - number of bytes of data (up to 501)
* @return number of bytes encoded, or 0 on error
*/
uint16_t MSTP_Create_Frame(uint8_t *buffer,
uint16_t buffer_size,
uint8_t frame_type,
uint8_t destination,
uint8_t source,
uint8_t *data,
uint16_t data_len)
{ /* number of bytes of data (up to 501) */
{
uint8_t crc8 = 0xFF; /* used to calculate the crc value */
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
uint16_t index = 0; /* used to load the data portion of the frame */
uint16_t cobs_len; /* length of the COBS encoded frame */
bool cobs_bacnet_frame = false; /* true for COBS BACnet frames */
/* not enough to do a header */
if (buffer_len < 8) {
if (buffer_size < 8) {
return 0;
}
buffer[0] = 0x55;
buffer[1] = 0xFF;
buffer[2] = frame_type;
@@ -229,46 +253,87 @@ uint16_t MSTP_Create_Frame(uint8_t *buffer, /* where frame is loaded */
buffer[6] = data_len & 0xFF;
crc8 = CRC_Calc_Header(buffer[6], crc8);
buffer[7] = ~crc8;
index = 8;
while (data_len && data && (index < buffer_len)) {
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--;
}
/* append the data CRC if necessary */
if (index > 8) {
if ((index + 2) <= buffer_len) {
if ((index + 2) > buffer_size) {
return 0;
}
crc16 = ~crc16;
buffer[index] = crc16 & 0xFF; /* LSB first */
index++;
buffer[index] = crc16 >> 8;
index++;
} else {
return 0;
}
}
return index; /* returns the frame length */
}
/**
* @brief Send an MS/TP Frame
* @param mstp_port - port to send from
* @param frame_type - type of frame to send - see defines
* @param destination - destination address
* @param source - source address
* @param data - any data to be sent - may be null
* @param data_len - number of bytes of data (up to 501)
*/
void MSTP_Create_And_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port, /* port to send from */
uint8_t frame_type, /* type of frame to send - see defines */
uint8_t destination, /* destination address */
uint8_t source, /* source address */
uint8_t *data, /* any data to be sent - may be null */
volatile struct mstp_port_struct_t *mstp_port,
uint8_t frame_type,
uint8_t destination,
uint8_t source,
uint8_t *data,
uint16_t data_len)
{ /* number of bytes of data (up to 501) */
{
uint16_t len = 0; /* number of bytes to send */
len = MSTP_Create_Frame((uint8_t *)&mstp_port->OutputBuffer[0],
mstp_port->OutputBufferSize, frame_type, destination, source, data,
data_len);
RS485_Send_Frame(mstp_port, (uint8_t *)&mstp_port->OutputBuffer[0], len);
MSTP_Send_Frame(mstp_port, (uint8_t *)&mstp_port->OutputBuffer[0], len);
/* FIXME: be sure to reset SilenceTimer() after each octet is sent! */
}
@@ -533,23 +598,26 @@ 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;
if (mstp_port->Index < mstp_port->InputBufferSize) {
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 */
if (mstp_port->Index < mstp_port->InputBufferSize) {
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));
if ((mstp_port->FrameType ==
FRAME_TYPE_BACNET_EXTENDED_DATA_EXPECTING_REPLY) ||
(mstp_port->FrameType ==
FRAME_TYPE_BACNET_EXTENDED_DATA_NOT_EXPECTING_REPLY)) {
if (((mstp_port->Index+1) < mstp_port->InputBufferSize) &&
(mstp_port->FrameType >= Nmin_COBS_type) &&
(mstp_port->FrameType <= Nmax_COBS_type)) {
if (cobs_frame_decode(
&mstp_port->InputBuffer[mstp_port->Index + 1],
mstp_port->InputBufferSize,
@@ -756,7 +824,7 @@ bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
} else {
uint8_t frame_type = mstp_port->OutputBuffer[2];
uint8_t destination = mstp_port->OutputBuffer[3];
RS485_Send_Frame(mstp_port,
MSTP_Send_Frame(mstp_port,
(uint8_t *)&mstp_port->OutputBuffer[0], (uint16_t)length);
mstp_port->FrameCount++;
switch (frame_type) {
@@ -1135,7 +1203,7 @@ bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
/* then call MSTP_Create_And_Send_Frame to transmit the reply
* frame */
/* and enter the IDLE state to wait for the next frame. */
RS485_Send_Frame(mstp_port,
MSTP_Send_Frame(mstp_port,
(uint8_t *)&mstp_port->OutputBuffer[0], (uint16_t)length);
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
/* clear our flag we were holding for comparison */
@@ -1207,7 +1275,7 @@ void MSTP_Slave_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
* reply frame */
/* and enter the IDLE state to wait for the next frame.
*/
RS485_Send_Frame(mstp_port,
MSTP_Send_Frame(mstp_port,
(uint8_t *)&mstp_port->OutputBuffer[0],
(uint16_t)length);
/* clear our flag we were holding for comparison */
+7
View File
@@ -220,6 +220,7 @@ extern "C" {
/* functions used by the MS/TP state machine to put or get data */
/* FIXME: developer must implement these in their DLMSTP module */
BACNET_STACK_EXPORT
uint16_t MSTP_Put_Receive(
volatile struct mstp_port_struct_t *mstp_port);
@@ -238,6 +239,12 @@ extern "C" {
volatile struct mstp_port_struct_t *mstp_port,
unsigned timeout); /* milliseconds to wait for a packet */
BACNET_STACK_EXPORT
void MSTP_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port,
uint8_t * buffer,
uint16_t nbytes);
#ifdef __cplusplus
}
#endif /* __cplusplus */