Feature/mstp zero config option (#564)
* Added a MS/TP zero-config (automatically choose an unused MAC address) using an algorithm that starts with MAC=64 and waits for a random number of PFM (minimum of 8 plus modulo 64) before attempting to choose a MAC sequentially from 64..127. The confirmation uses a 128-bit UUID with the MSTP Test Request frame. The modifications are in src/bacnet/datalink/mstp.c and src/bacnet/datalink/dlmstp.c modules enabling any device to use zero-config if enabled. A working demonstration is in the ports/stm32f4xx for the NUCLEO board. Complete unit testing is included. Options include lurking forever (wait for a router or another master node before joining) or lurking for a minimum time (enables self forming automatic MAC addressing device nodes).
This commit is contained in:
@@ -52,7 +52,7 @@ static HANDLE Receive_Packet_Flag;
|
||||
HANDLE Received_Frame_Flag;
|
||||
static DLMSTP_PACKET Transmit_Packet;
|
||||
/* local MS/TP port data - shared with RS-485 */
|
||||
volatile struct mstp_port_struct_t MSTP_Port;
|
||||
static struct mstp_port_struct_t MSTP_Port;
|
||||
/* buffers needed by mstp port struct */
|
||||
static uint8_t TxBuffer[DLMSTP_MPDU_MAX];
|
||||
static uint8_t RxBuffer[DLMSTP_MPDU_MAX];
|
||||
@@ -62,11 +62,12 @@ static uint32_t TimeBeginPeriod;
|
||||
/* 1-millisecond target resolution */
|
||||
#define TARGET_RESOLUTION 1
|
||||
|
||||
static uint16_t Timer_Silence(void)
|
||||
static uint16_t Timer_Silence(void *arg)
|
||||
{
|
||||
uint32_t now = timeGetTime();
|
||||
uint32_t delta_time = 0;
|
||||
|
||||
(void)arg;
|
||||
if (SilenceStartTime < now) {
|
||||
delta_time = now - SilenceStartTime;
|
||||
} else {
|
||||
@@ -79,8 +80,9 @@ static uint16_t Timer_Silence(void)
|
||||
return (uint16_t)delta_time;
|
||||
}
|
||||
|
||||
static void Timer_Silence_Reset(void)
|
||||
static void Timer_Silence_Reset(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
SilenceStartTime = timeGetTime();
|
||||
}
|
||||
|
||||
@@ -241,7 +243,7 @@ void dlmstp_fill_bacnet_address(BACNET_ADDRESS *src, uint8_t mstp_address)
|
||||
}
|
||||
|
||||
/* for the MS/TP state machine to use for putting received data */
|
||||
uint16_t MSTP_Put_Receive(volatile struct mstp_port_struct_t *mstp_port)
|
||||
uint16_t MSTP_Put_Receive(struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
BOOL rc;
|
||||
@@ -266,7 +268,7 @@ uint16_t MSTP_Put_Receive(volatile struct mstp_port_struct_t *mstp_port)
|
||||
/* for the MS/TP state machine to use for getting data to send */
|
||||
/* Return: amount of PDU data */
|
||||
uint16_t MSTP_Get_Send(
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0;
|
||||
uint8_t destination = 0; /* destination address */
|
||||
@@ -303,7 +305,7 @@ uint16_t MSTP_Get_Send(
|
||||
* @param nbytes - number of bytes of data to send
|
||||
*/
|
||||
void MSTP_Send_Frame(
|
||||
volatile struct mstp_port_struct_t *mstp_port,
|
||||
struct mstp_port_struct_t *mstp_port,
|
||||
uint8_t * buffer,
|
||||
uint16_t nbytes)
|
||||
{
|
||||
@@ -420,7 +422,7 @@ bool dlmstp_compare_data_expecting_reply(uint8_t *request_pdu,
|
||||
|
||||
/* Get the reply to a DATA_EXPECTING_REPLY frame, or nothing */
|
||||
uint16_t MSTP_Get_Reply(
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
uint8_t destination = 0; /* destination address */
|
||||
|
||||
@@ -51,7 +51,7 @@ static HANDLE Receive_Packet_Flag;
|
||||
HANDLE Received_Frame_Flag;
|
||||
static DLMSTP_PACKET Transmit_Packet;
|
||||
/* local MS/TP port data - shared with RS-485 */
|
||||
volatile struct mstp_port_struct_t MSTP_Port;
|
||||
struct mstp_port_struct_t MSTP_Port;
|
||||
/* buffers needed by mstp port struct */
|
||||
static uint8_t TxBuffer[DLMSTP_MPDU_MAX];
|
||||
static uint8_t RxBuffer[DLMSTP_MPDU_MAX];
|
||||
@@ -71,11 +71,13 @@ static struct mstimer Silence_Timer;
|
||||
/* Timer that indicates line silence - and functions */
|
||||
static uint32_t Timer_Silence(void *pArg)
|
||||
{
|
||||
(void)pArg;
|
||||
return mstimer_elapsed(&Silence_Timer);
|
||||
}
|
||||
|
||||
static void Timer_Silence_Reset(void *pArg)
|
||||
{
|
||||
(void)pArg;
|
||||
mstimer_set(&Silence_Timer, 0);
|
||||
}
|
||||
|
||||
@@ -226,7 +228,7 @@ void dlmstp_fill_bacnet_address(BACNET_ADDRESS *src, uint8_t mstp_address)
|
||||
}
|
||||
|
||||
/* for the MS/TP state machine to use for putting received data */
|
||||
uint16_t MSTP_Put_Receive(volatile struct mstp_port_struct_t *mstp_port)
|
||||
uint16_t MSTP_Put_Receive(struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
BOOL rc;
|
||||
@@ -252,7 +254,7 @@ uint16_t MSTP_Put_Receive(volatile struct mstp_port_struct_t *mstp_port)
|
||||
/* for the MS/TP state machine to use for getting data to send */
|
||||
/* Return: amount of PDU data */
|
||||
uint16_t MSTP_Get_Send(
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0;
|
||||
uint8_t destination = 0; /* destination address */
|
||||
@@ -288,7 +290,7 @@ uint16_t MSTP_Get_Send(
|
||||
* @param nbytes - number of bytes of data to send
|
||||
*/
|
||||
void MSTP_Send_Frame(
|
||||
volatile struct mstp_port_struct_t *mstp_port,
|
||||
struct mstp_port_struct_t *mstp_port,
|
||||
uint8_t * buffer,
|
||||
uint16_t nbytes)
|
||||
{
|
||||
@@ -405,7 +407,7 @@ static bool dlmstp_compare_data_expecting_reply(uint8_t *request_pdu,
|
||||
|
||||
/* Get the reply to a DATA_EXPECTING_REPLY frame, or nothing */
|
||||
uint16_t MSTP_Get_Reply(
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
uint8_t destination = 0; /* destination address */
|
||||
|
||||
+2
-2
@@ -421,7 +421,7 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
|
||||
|
||||
/* Transmits a Frame on the wire */
|
||||
void RS485_Send_Frame(
|
||||
volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||
struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||
uint8_t *buffer, /* frame to send (up to 501 bytes of data) */
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
@@ -453,7 +453,7 @@ void RS485_Send_Frame(
|
||||
}
|
||||
|
||||
/* called by timer, interrupt(?) or other thread */
|
||||
void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port)
|
||||
void RS485_Check_UART_Data(struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
char lpBuf[1];
|
||||
DWORD dwRead = 0;
|
||||
|
||||
+2
-2
@@ -58,13 +58,13 @@ extern "C" {
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
void RS485_Send_Frame(
|
||||
volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||
struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
|
||||
uint16_t nbytes); /* number of bytes of data (up to 501) */
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
void RS485_Check_UART_Data(
|
||||
volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
|
||||
struct mstp_port_struct_t *mstp_port); /* port specific data */
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
uint32_t RS485_Get_Baud_Rate(
|
||||
|
||||
Reference in New Issue
Block a user