Refactor/mstp zero config state machine (#676)
* Changed MS/TP master node self destination checks to be located in receive FSM * Changed MSTP zero configuration: modified comments for state transition names; modified next station increment; refactored the UUID rand() to not be required by common zero config implementation; added more unit tests. * Added another context to MS/TP user data to allow additional user data
This commit is contained in:
@@ -77,7 +77,7 @@ static struct my_object_functions {
|
|||||||
properties that are writable or that may change.
|
properties that are writable or that may change.
|
||||||
The properties that are constant can be hard coded
|
The properties that are constant can be hard coded
|
||||||
into the read-property encoding. */
|
into the read-property encoding. */
|
||||||
static uint32_t Object_Instance_Number = 103;
|
static uint32_t Object_Instance_Number = BACNET_MAX_INSTANCE;
|
||||||
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
||||||
static BACNET_CHARACTER_STRING My_Object_Name;
|
static BACNET_CHARACTER_STRING My_Object_Name;
|
||||||
static uint32_t Database_Revision;
|
static uint32_t Database_Revision;
|
||||||
@@ -453,9 +453,8 @@ void Device_Init(object_functions_t *object_table)
|
|||||||
pObject++;
|
pObject++;
|
||||||
}
|
}
|
||||||
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
|
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
|
||||||
if (Object_Instance_Number >= BACNET_MAX_INSTANCE) {
|
if (Object_Instance_Number > BACNET_MAX_INSTANCE) {
|
||||||
Object_Instance_Number = 103;
|
Object_Instance_Number = BACNET_MAX_INSTANCE;
|
||||||
srand(Object_Instance_Number);
|
|
||||||
}
|
}
|
||||||
characterstring_init_ansi(&My_Object_Name, "stm32-design-challenge-103");
|
characterstring_init_ansi(&My_Object_Name, "stm32-design-challenge-103");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,11 +25,13 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "bacnet/basic/sys/mstimer.h"
|
#include "bacnet/basic/sys/mstimer.h"
|
||||||
#include "bacnet/datalink/datalink.h"
|
#include "bacnet/datalink/datalink.h"
|
||||||
#include "bacnet/datalink/dlmstp.h"
|
#include "bacnet/datalink/dlmstp.h"
|
||||||
#include "bacnet/datalink/mstp.h"
|
#include "bacnet/datalink/mstp.h"
|
||||||
|
#include "bacnet/basic/object/device.h"
|
||||||
#include "rs485.h"
|
#include "rs485.h"
|
||||||
#include "led.h"
|
#include "led.h"
|
||||||
#include "bacnet.h"
|
#include "bacnet.h"
|
||||||
@@ -144,6 +146,7 @@ static void mstp_configure(void)
|
|||||||
/* user data */
|
/* user data */
|
||||||
MSTP_Port.ZeroConfigEnabled = true;
|
MSTP_Port.ZeroConfigEnabled = true;
|
||||||
MSTP_Port.SlaveNodeEnabled = false;
|
MSTP_Port.SlaveNodeEnabled = false;
|
||||||
|
MSTP_Zero_Config_UUID_Init(&MSTP_Port);
|
||||||
MSTP_User_Data.RS485_Driver = &RS485_Driver;
|
MSTP_User_Data.RS485_Driver = &RS485_Driver;
|
||||||
MSTP_Port.UserData = &MSTP_User_Data;
|
MSTP_Port.UserData = &MSTP_User_Data;
|
||||||
dlmstp_init((char *)&MSTP_Port);
|
dlmstp_init((char *)&MSTP_Port);
|
||||||
@@ -163,6 +166,7 @@ static void mstp_configure(void)
|
|||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
struct mstimer Blink_Timer;
|
struct mstimer Blink_Timer;
|
||||||
|
uint32_t Object_Instance_Number = 103;
|
||||||
|
|
||||||
/*At this stage the microcontroller clock setting is already configured,
|
/*At this stage the microcontroller clock setting is already configured,
|
||||||
this is done through SystemInit() function which is called from startup
|
this is done through SystemInit() function which is called from startup
|
||||||
@@ -178,6 +182,10 @@ int main(void)
|
|||||||
mstimer_init();
|
mstimer_init();
|
||||||
lse_init();
|
lse_init();
|
||||||
led_init();
|
led_init();
|
||||||
|
/* FIXME: get device instance from EEPROM */
|
||||||
|
(void)Device_Set_Object_Instance_Number(Object_Instance_Number);
|
||||||
|
/* seed libc random number generator */
|
||||||
|
srand(Object_Instance_Number);
|
||||||
/* initialize MSTP datalink layer */
|
/* initialize MSTP datalink layer */
|
||||||
mstp_configure();
|
mstp_configure();
|
||||||
/* initialize application layer*/
|
/* initialize application layer*/
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ static uint32_t Database_Revision;
|
|||||||
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
|
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
|
||||||
static const char *Reinit_Password = "stm32f4xx";
|
static const char *Reinit_Password = "stm32f4xx";
|
||||||
static const char *BACnet_Version = BACNET_VERSION_TEXT;
|
static const char *BACnet_Version = BACNET_VERSION_TEXT;
|
||||||
|
static uint8_t Device_UUID[16];
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||||
static const int Device_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
|
static const int Device_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
|
||||||
@@ -94,7 +95,8 @@ static const int Device_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
|
|||||||
PROP_DATABASE_REVISION, -1 };
|
PROP_DATABASE_REVISION, -1 };
|
||||||
|
|
||||||
static const int Device_Properties_Optional[] = { PROP_DESCRIPTION,
|
static const int Device_Properties_Optional[] = { PROP_DESCRIPTION,
|
||||||
PROP_LOCATION, PROP_MAX_MASTER, PROP_MAX_INFO_FRAMES, -1 };
|
PROP_LOCATION, PROP_MAX_MASTER, PROP_MAX_INFO_FRAMES, PROP_DEVICE_UUID,
|
||||||
|
-1 };
|
||||||
|
|
||||||
static const int Device_Properties_Proprietary[] = { -1 };
|
static const int Device_Properties_Proprietary[] = { -1 };
|
||||||
|
|
||||||
@@ -398,6 +400,71 @@ void Device_Inc_Database_Revision(void)
|
|||||||
Database_Revision++;
|
Database_Revision++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a UUID for storing the unique identifier of this device
|
||||||
|
* @note A Universally Unique IDentifier (UUID) - also called a
|
||||||
|
* Global Unique IDentifier (GUID) - is a 128-bit value, see RFC 4122.
|
||||||
|
*
|
||||||
|
* 4.4. Algorithms for Creating a UUID from Truly Random or
|
||||||
|
* Pseudo-Random Numbers
|
||||||
|
*
|
||||||
|
* The version 4 UUID is meant for generating UUIDs from truly-random or
|
||||||
|
* pseudo-random numbers.
|
||||||
|
*
|
||||||
|
* The algorithm is as follows:
|
||||||
|
*
|
||||||
|
* o Set the two most significant bits (bits 6 and 7) of the
|
||||||
|
* clock_seq_hi_and_reserved to zero and one, respectively.
|
||||||
|
*
|
||||||
|
* o Set the four most significant bits (bits 12 through 15) of the
|
||||||
|
* time_hi_and_version field to the 4-bit version number from
|
||||||
|
* Section 4.1.3.
|
||||||
|
*
|
||||||
|
* o Set all the other bits to randomly (or pseudo-randomly) chosen
|
||||||
|
* values.
|
||||||
|
*/
|
||||||
|
void Device_UUID_Init(void)
|
||||||
|
{
|
||||||
|
unsigned i = 0;
|
||||||
|
|
||||||
|
/* 1. Generate 16 random bytes = 128 bits */
|
||||||
|
for (i = 0; i < sizeof(Device_UUID); i++) {
|
||||||
|
Device_UUID[i] = rand() % 255;
|
||||||
|
}
|
||||||
|
/* 2. Adjust certain bits according to RFC 4122 section 4.4.
|
||||||
|
This just means do the following
|
||||||
|
(a) set the high nibble of the 7th byte equal to 4 and
|
||||||
|
(b) set the two most significant bits of the 9th byte to 10'B,
|
||||||
|
so the high nibble will be one of {8,9,A,B}.
|
||||||
|
From http://www.cryptosys.net/pki/Uuid.c.html */
|
||||||
|
Device_UUID[6] = 0x40 | (Device_UUID[6] & 0x0f);
|
||||||
|
Device_UUID[8] = 0x80 | (Device_UUID[8] & 0x3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the UUID for this device
|
||||||
|
* @param new_uuid [in] The new UUID to set
|
||||||
|
* @param length [in] The length of the new UUID
|
||||||
|
*/
|
||||||
|
void Device_UUID_Set(uint8_t *new_uuid, size_t length)
|
||||||
|
{
|
||||||
|
if (new_uuid && (length == sizeof(Device_UUID))) {
|
||||||
|
memcpy(Device_UUID, new_uuid, sizeof(Device_UUID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the UUID for this device
|
||||||
|
* @param uuid [out] The UUID of this device
|
||||||
|
* @param length [in] The length of the UUID
|
||||||
|
*/
|
||||||
|
void Device_UUID_Get(uint8_t *uuid, size_t length)
|
||||||
|
{
|
||||||
|
if (uuid && (length == sizeof(Device_UUID))) {
|
||||||
|
memcpy(uuid, Device_UUID, sizeof(Device_UUID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Get the total count of objects supported by this Device Object.
|
/** Get the total count of objects supported by this Device Object.
|
||||||
* @note Since many network clients depend on the object list
|
* @note Since many network clients depend on the object list
|
||||||
* for discovery, it must be consistent!
|
* for discovery, it must be consistent!
|
||||||
@@ -586,6 +653,7 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
|
|||||||
int apdu_len = 0; /* return value */
|
int apdu_len = 0; /* return value */
|
||||||
BACNET_BIT_STRING bit_string = { 0 };
|
BACNET_BIT_STRING bit_string = { 0 };
|
||||||
BACNET_CHARACTER_STRING char_string = { 0 };
|
BACNET_CHARACTER_STRING char_string = { 0 };
|
||||||
|
BACNET_OCTET_STRING octet_string = { 0 };
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
uint8_t *apdu = NULL;
|
uint8_t *apdu = NULL;
|
||||||
@@ -713,6 +781,10 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
|
|||||||
apdu_len =
|
apdu_len =
|
||||||
encode_application_unsigned(&apdu[0], dlmstp_max_master());
|
encode_application_unsigned(&apdu[0], dlmstp_max_master());
|
||||||
break;
|
break;
|
||||||
|
case PROP_DEVICE_UUID:
|
||||||
|
octetstring_init(&octet_string, Device_UUID, sizeof(Device_UUID));
|
||||||
|
apdu_len = encode_application_octet_string(&apdu[0], &octet_string);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||||
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
|
|||||||
+19
-15
@@ -90,6 +90,24 @@ int main(void)
|
|||||||
led_init();
|
led_init();
|
||||||
rs485_init();
|
rs485_init();
|
||||||
mstimer_set(&Blink_Timer, 500);
|
mstimer_set(&Blink_Timer, 500);
|
||||||
|
/* FIXME: get the device ID from EEPROM */
|
||||||
|
Device_Set_Object_Instance_Number(103);
|
||||||
|
/* seed stdlib rand() with device-id to get pseudo consistent
|
||||||
|
zero-config poll slot, or use hardware RNG to get a more random slot */
|
||||||
|
#ifdef BACNET_ZERO_CONFIG_RNG_HARDWARE
|
||||||
|
/* enable the random number generator hardware */
|
||||||
|
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
|
||||||
|
RNG_Cmd(ENABLE);
|
||||||
|
while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) {
|
||||||
|
/* wait for 32-bit random number to generate */
|
||||||
|
}
|
||||||
|
srand(RNG_GetRandomNumber());
|
||||||
|
#else
|
||||||
|
srand(Device_Object_Instance_Number());
|
||||||
|
#endif
|
||||||
|
/* initialize the Device UUID from rand() */
|
||||||
|
Device_UUID_Init();
|
||||||
|
Device_UUID_Get(MSTP_Port.UUID, sizeof(MSTP_Port.UUID));
|
||||||
/* initialize MSTP datalink layer */
|
/* initialize MSTP datalink layer */
|
||||||
MSTP_Port.Nmax_info_frames = DLMSTP_MAX_INFO_FRAMES;
|
MSTP_Port.Nmax_info_frames = DLMSTP_MAX_INFO_FRAMES;
|
||||||
MSTP_Port.Nmax_master = DLMSTP_MAX_MASTER;
|
MSTP_Port.Nmax_master = DLMSTP_MAX_MASTER;
|
||||||
@@ -104,6 +122,7 @@ int main(void)
|
|||||||
MSTP_Port.UserData = &MSTP_User_Data;
|
MSTP_Port.UserData = &MSTP_User_Data;
|
||||||
dlmstp_init((char *)&MSTP_Port);
|
dlmstp_init((char *)&MSTP_Port);
|
||||||
if (MSTP_Port.ZeroConfigEnabled) {
|
if (MSTP_Port.ZeroConfigEnabled) {
|
||||||
|
/* set node to monitor address */
|
||||||
dlmstp_set_mac_address(255);
|
dlmstp_set_mac_address(255);
|
||||||
} else {
|
} else {
|
||||||
/* FIXME: get the address from hardware DIP or from EEPROM */
|
/* FIXME: get the address from hardware DIP or from EEPROM */
|
||||||
@@ -113,21 +132,6 @@ int main(void)
|
|||||||
dlmstp_set_baud_rate(DLMSTP_BAUD_RATE_DEFAULT);
|
dlmstp_set_baud_rate(DLMSTP_BAUD_RATE_DEFAULT);
|
||||||
/* initialize application layer*/
|
/* initialize application layer*/
|
||||||
bacnet_init();
|
bacnet_init();
|
||||||
/* FIXME: get the device ID from EEPROM */
|
|
||||||
Device_Set_Object_Instance_Number(103);
|
|
||||||
/* seed stdlib rand() with device-id to get pweudo consisten
|
|
||||||
zero-config poll slot, or use hardware RNG to get a more random slot */
|
|
||||||
#ifdef BACNET_ZERO_CONFIG_RNG_HARDWARE
|
|
||||||
/* enable the random number generator hardware */
|
|
||||||
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
|
|
||||||
RNG_Cmd(ENABLE);
|
|
||||||
while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) {
|
|
||||||
/* wait for 32-bit random number to generate */
|
|
||||||
}
|
|
||||||
srand(RNG_GetRandomNumber());
|
|
||||||
#else
|
|
||||||
srand(Device_Object_Instance_Number());
|
|
||||||
#endif
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (mstimer_expired(&Blink_Timer)) {
|
if (mstimer_expired(&Blink_Timer)) {
|
||||||
mstimer_reset(&Blink_Timer);
|
mstimer_reset(&Blink_Timer);
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ CSRC = main.c \
|
|||||||
led.c \
|
led.c \
|
||||||
mstimer-init.c \
|
mstimer-init.c \
|
||||||
netport.c \
|
netport.c \
|
||||||
nvmdata.c \
|
|
||||||
rs485.c \
|
rs485.c \
|
||||||
stack.c
|
stack.c
|
||||||
|
|
||||||
|
|||||||
+47
-11
@@ -6,6 +6,7 @@
|
|||||||
* @copyright SPDX-License-Identifier: MIT
|
* @copyright SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
#include <asf.h>
|
#include <asf.h>
|
||||||
|
#include "bacnet/basic/object/device.h"
|
||||||
#include "bacnet/basic/sys/mstimer.h"
|
#include "bacnet/basic/sys/mstimer.h"
|
||||||
#include "bacnet/datalink/datalink.h"
|
#include "bacnet/datalink/datalink.h"
|
||||||
#include "bacnet/datalink/dlmstp.h"
|
#include "bacnet/datalink/dlmstp.h"
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
#include "led.h"
|
#include "led.h"
|
||||||
#include "adc-hdw.h"
|
#include "adc-hdw.h"
|
||||||
#include "bacnet.h"
|
#include "bacnet.h"
|
||||||
|
#include "nvmdata.h"
|
||||||
|
|
||||||
static struct mstimer_callback_data_t BACnet_Callback;
|
static struct mstimer_callback_data_t BACnet_Callback;
|
||||||
|
|
||||||
@@ -33,11 +35,43 @@ static struct dlmstp_user_data_t MSTP_User_Data;
|
|||||||
static uint8_t Input_Buffer[DLMSTP_MPDU_MAX];
|
static uint8_t Input_Buffer[DLMSTP_MPDU_MAX];
|
||||||
static uint8_t Output_Buffer[DLMSTP_MPDU_MAX];
|
static uint8_t Output_Buffer[DLMSTP_MPDU_MAX];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes some data from non-volatile memory module
|
||||||
|
*/
|
||||||
|
static void nvm_data_init(void)
|
||||||
|
{
|
||||||
|
uint32_t device_id = 127;
|
||||||
|
uint8_t max_master = 127;
|
||||||
|
uint8_t mac_address = 127;
|
||||||
|
uint8_t kbaud_rate = 38;
|
||||||
|
|
||||||
|
nvm_read(NVM_BAUD_K, &kbaud_rate, 1);
|
||||||
|
rs485_kbaud_rate_set(kbaud_rate);
|
||||||
|
|
||||||
|
nvm_read(NVM_MAC_ADDRESS, &mac_address, 1);
|
||||||
|
dlmstp_set_mac_address(mac_address);
|
||||||
|
nvm_read(NVM_MAX_MASTER, &max_master, 1);
|
||||||
|
if (max_master > 127) {
|
||||||
|
max_master = 127;
|
||||||
|
}
|
||||||
|
dlmstp_set_max_master(max_master);
|
||||||
|
|
||||||
|
/* Get the device ID from the EEPROM */
|
||||||
|
nvm_read(NVM_DEVICE_0, (uint8_t *)&device_id, sizeof(device_id));
|
||||||
|
if (device_id < BACNET_MAX_INSTANCE) {
|
||||||
|
Device_Set_Object_Instance_Number(device_id);
|
||||||
|
} else {
|
||||||
|
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief MS/TP configuraiton
|
* @brief MS/TP configuraiton
|
||||||
*/
|
*/
|
||||||
static void dlmstp_configure(void)
|
static void dlmstp_configure(void)
|
||||||
{
|
{
|
||||||
|
uint8_t mac_address = 0;
|
||||||
|
|
||||||
/* initialize MSTP datalink layer */
|
/* initialize MSTP datalink layer */
|
||||||
MSTP_Port.Nmax_info_frames = DLMSTP_MAX_INFO_FRAMES;
|
MSTP_Port.Nmax_info_frames = DLMSTP_MAX_INFO_FRAMES;
|
||||||
MSTP_Port.Nmax_master = DLMSTP_MAX_MASTER;
|
MSTP_Port.Nmax_master = DLMSTP_MAX_MASTER;
|
||||||
@@ -46,19 +80,21 @@ static void dlmstp_configure(void)
|
|||||||
MSTP_Port.OutputBuffer = Output_Buffer;
|
MSTP_Port.OutputBuffer = Output_Buffer;
|
||||||
MSTP_Port.OutputBufferSize = sizeof(Output_Buffer);
|
MSTP_Port.OutputBufferSize = sizeof(Output_Buffer);
|
||||||
/* user data */
|
/* user data */
|
||||||
MSTP_Port.ZeroConfigEnabled = true;
|
mac_address = dlmstp_mac_address();
|
||||||
MSTP_Port.SlaveNodeEnabled = false;
|
if (mac_address == 255) {
|
||||||
|
MSTP_Port.ZeroConfigEnabled = true;
|
||||||
|
} else {
|
||||||
|
MSTP_Port.ZeroConfigEnabled = false;
|
||||||
|
}
|
||||||
|
if (mac_address <= 127) {
|
||||||
|
MSTP_Port.SlaveNodeEnabled = false;
|
||||||
|
} else {
|
||||||
|
MSTP_Port.SlaveNodeEnabled = true;
|
||||||
|
}
|
||||||
|
MSTP_Zero_Config_UUID_Init(&MSTP_Port);
|
||||||
MSTP_User_Data.RS485_Driver = &RS485_Driver;
|
MSTP_User_Data.RS485_Driver = &RS485_Driver;
|
||||||
MSTP_Port.UserData = &MSTP_User_Data;
|
MSTP_Port.UserData = &MSTP_User_Data;
|
||||||
dlmstp_init((char *)&MSTP_Port);
|
dlmstp_init((char *)&MSTP_Port);
|
||||||
if (MSTP_Port.ZeroConfigEnabled) {
|
|
||||||
dlmstp_set_mac_address(255);
|
|
||||||
} else {
|
|
||||||
/* FIXME: get the address from hardware DIP or from EEPROM */
|
|
||||||
dlmstp_set_mac_address(1);
|
|
||||||
}
|
|
||||||
/* FIXME: get the baud rate from hardware DIP or from EEPROM */
|
|
||||||
dlmstp_set_baud_rate(DLMSTP_BAUD_RATE_DEFAULT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,7 +123,7 @@ int main(void)
|
|||||||
}
|
}
|
||||||
cpu_irq_enable();
|
cpu_irq_enable();
|
||||||
/* application initialization */
|
/* application initialization */
|
||||||
rs485_baud_rate_set(38400);
|
nvm_data_init();
|
||||||
dlmstp_configure();
|
dlmstp_configure();
|
||||||
bacnet_init();
|
bacnet_init();
|
||||||
/* run forever - timed tasks */
|
/* run forever - timed tasks */
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief Store and retrieve non-volatile data
|
|
||||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
|
||||||
* @date 2013
|
|
||||||
* @copyright SPDX-License-Identifier: MIT
|
|
||||||
*/
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "nvmdata.h"
|
|
||||||
#include "bacnet/datalink/dlmstp.h"
|
|
||||||
#include "bacnet/basic/object/device.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the non-volatile memory module
|
|
||||||
*/
|
|
||||||
void nvm_data_init(void)
|
|
||||||
{
|
|
||||||
uint32_t device_id = 127;
|
|
||||||
uint8_t max_master = 127;
|
|
||||||
uint8_t mac_address = 127;
|
|
||||||
|
|
||||||
nvm_read(NVM_MAC_ADDRESS, &mac_address, 1);
|
|
||||||
if (mac_address == 255) {
|
|
||||||
/* uninitialized */
|
|
||||||
mac_address = 123;
|
|
||||||
}
|
|
||||||
dlmstp_set_mac_address(mac_address);
|
|
||||||
nvm_read(NVM_MAX_MASTER, &max_master, 1);
|
|
||||||
if (max_master > 127) {
|
|
||||||
max_master = 127;
|
|
||||||
}
|
|
||||||
dlmstp_set_max_master(max_master);
|
|
||||||
/* Get the device ID from the EEPROM */
|
|
||||||
nvm_read(NVM_DEVICE_0, (uint8_t *)&device_id, sizeof(device_id));
|
|
||||||
if (device_id < BACNET_MAX_INSTANCE) {
|
|
||||||
Device_Set_Object_Instance_Number(device_id);
|
|
||||||
} else {
|
|
||||||
Device_Set_Object_Instance_Number(mac_address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#include <avr/eeprom.h>
|
#include <avr/eeprom.h>
|
||||||
|
|
||||||
/* compatible functions could put in nvm.h to abstract more */
|
/* compatible functions could put in header to abstract more */
|
||||||
#define nvm_write(dst, src, len) \
|
#define nvm_write(dst, src, len) \
|
||||||
eeprom_write_block((uint8_t *)(src),(uint8_t *)(dst), (size_t)(len))
|
eeprom_write_block((uint8_t *)(src),(uint8_t *)(dst), (size_t)(len))
|
||||||
|
|
||||||
@@ -54,14 +54,4 @@
|
|||||||
|
|
||||||
/* free space 128..4096 */
|
/* free space 128..4096 */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
void nvm_data_init(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -210,6 +210,44 @@ uint32_t rs485_baud_rate(void)
|
|||||||
return Baud_Rate;
|
return Baud_Rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the baud in kili-baud
|
||||||
|
* @param baud_k baud rate in approximate kilobaud
|
||||||
|
*/
|
||||||
|
bool rs485_kbaud_rate_set(uint8_t baud_k)
|
||||||
|
{
|
||||||
|
uint32_t baud = 38400;
|
||||||
|
|
||||||
|
if (baud_k == 255) {
|
||||||
|
baud = 38400;
|
||||||
|
} else if (baud_k >= 115) {
|
||||||
|
baud = 115200;
|
||||||
|
} else if (baud_k >= 76) {
|
||||||
|
baud = 76800;
|
||||||
|
} else if (baud_k >= 57) {
|
||||||
|
baud = 57600;
|
||||||
|
} else if (baud_k >= 38) {
|
||||||
|
baud = 38400;
|
||||||
|
} else if (baud_k >= 19) {
|
||||||
|
baud = 19200;
|
||||||
|
} else if (baud_k >= 9) {
|
||||||
|
baud = 9600;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rs485_baud_rate_set(baud);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts baud in bps to kili-baud
|
||||||
|
*
|
||||||
|
* @param baud - baud rate in bps
|
||||||
|
* @return: baud rate in approximate kilo-baud
|
||||||
|
*/
|
||||||
|
uint8_t rs485_kbaud_rate(void)
|
||||||
|
{
|
||||||
|
return Baud_Rate/1000;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the RS-485 baud rate
|
* Initialize the RS-485 baud rate
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ void rs485_bytes_send(uint8_t *buffer, uint16_t nbytes);
|
|||||||
uint32_t rs485_baud_rate(void);
|
uint32_t rs485_baud_rate(void);
|
||||||
bool rs485_baud_rate_set(uint32_t baud);
|
bool rs485_baud_rate_set(uint32_t baud);
|
||||||
|
|
||||||
|
bool rs485_kbaud_rate_set(uint8_t baud_k);
|
||||||
|
uint8_t rs485_kbaud_rate(void);
|
||||||
|
|
||||||
uint32_t rs485_silence_milliseconds(void);
|
uint32_t rs485_silence_milliseconds(void);
|
||||||
void rs485_silence_reset(void);
|
void rs485_silence_reset(void);
|
||||||
|
|
||||||
|
|||||||
@@ -322,6 +322,18 @@ extern "C" {
|
|||||||
bool Device_Valid_Object_Instance_Number(
|
bool Device_Valid_Object_Instance_Number(
|
||||||
uint32_t object_id);
|
uint32_t object_id);
|
||||||
|
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
|
void Device_UUID_Init(
|
||||||
|
void);
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
|
void Device_UUID_Set(
|
||||||
|
uint8_t *new_uuid,
|
||||||
|
size_t length);
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
|
void Device_UUID_Get(
|
||||||
|
uint8_t *uuid,
|
||||||
|
size_t length);
|
||||||
|
|
||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
unsigned Device_Object_List_Count(
|
unsigned Device_Object_List_Count(
|
||||||
void);
|
void);
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ struct dlmstp_rs485_driver {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A structure of BACnet Port Data for BACnet MS/TP
|
* An example structure of user data for BACnet MS/TP
|
||||||
*/
|
*/
|
||||||
struct dlmstp_user_data_t {
|
struct dlmstp_user_data_t {
|
||||||
struct dlmstp_statistics Statistics;
|
struct dlmstp_statistics Statistics;
|
||||||
@@ -107,6 +107,7 @@ struct dlmstp_user_data_t {
|
|||||||
struct dlmstp_packet PDU_Buffer[DLMSTP_MAX_INFO_FRAMES];
|
struct dlmstp_packet PDU_Buffer[DLMSTP_MAX_INFO_FRAMES];
|
||||||
bool Initialized;
|
bool Initialized;
|
||||||
bool ReceivePacketPending;
|
bool ReceivePacketPending;
|
||||||
|
void *Context;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* callback to signify the receipt of a preamble */
|
/* callback to signify the receipt of a preamble */
|
||||||
|
|||||||
+70
-31
@@ -452,12 +452,19 @@ void MSTP_Receive_Frame_FSM(struct mstp_port_struct_t *mstp_port)
|
|||||||
} else {
|
} else {
|
||||||
if (mstp_port->DataLength == 0) {
|
if (mstp_port->DataLength == 0) {
|
||||||
/* NoData */
|
/* NoData */
|
||||||
printf_receive_data("%s",
|
if ((mstp_port->DestinationAddress ==
|
||||||
mstptext_frame_type(
|
mstp_port->This_Station) ||
|
||||||
|
(mstp_port->DestinationAddress ==
|
||||||
|
MSTP_BROADCAST_ADDRESS) ||
|
||||||
|
(mstp_port->This_Station ==
|
||||||
|
MSTP_BROADCAST_ADDRESS)) {
|
||||||
|
printf_receive_data("%s",
|
||||||
|
mstptext_frame_type(
|
||||||
(unsigned)mstp_port->FrameType));
|
(unsigned)mstp_port->FrameType));
|
||||||
/* indicate that a frame with no data has been
|
/* indicate that a frame with no data has been
|
||||||
* received */
|
* received */
|
||||||
mstp_port->ReceivedValidFrame = true;
|
mstp_port->ReceivedValidFrame = true;
|
||||||
|
}
|
||||||
/* wait for the start of the next frame. */
|
/* wait for the start of the next frame. */
|
||||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||||
} else {
|
} else {
|
||||||
@@ -465,6 +472,8 @@ void MSTP_Receive_Frame_FSM(struct mstp_port_struct_t *mstp_port)
|
|||||||
if ((mstp_port->DestinationAddress ==
|
if ((mstp_port->DestinationAddress ==
|
||||||
mstp_port->This_Station) ||
|
mstp_port->This_Station) ||
|
||||||
(mstp_port->DestinationAddress ==
|
(mstp_port->DestinationAddress ==
|
||||||
|
MSTP_BROADCAST_ADDRESS) ||
|
||||||
|
(mstp_port->This_Station ==
|
||||||
MSTP_BROADCAST_ADDRESS)) {
|
MSTP_BROADCAST_ADDRESS)) {
|
||||||
if (mstp_port->DataLength <=
|
if (mstp_port->DataLength <=
|
||||||
mstp_port->InputBufferSize) {
|
mstp_port->InputBufferSize) {
|
||||||
@@ -641,9 +650,12 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port)
|
|||||||
if (mstp_port->This_Station != 255) {
|
if (mstp_port->This_Station != 255) {
|
||||||
/* indicate that the next station is unknown */
|
/* indicate that the next station is unknown */
|
||||||
mstp_port->Next_Station = mstp_port->This_Station;
|
mstp_port->Next_Station = mstp_port->This_Station;
|
||||||
|
/* Send a Poll For Master since we just received
|
||||||
|
the token */
|
||||||
mstp_port->Poll_Station = (mstp_port->Next_Station + 1) %
|
mstp_port->Poll_Station = (mstp_port->Next_Station + 1) %
|
||||||
(mstp_port->Zero_Config_Max_Master + 1);
|
(mstp_port->Zero_Config_Max_Master + 1);
|
||||||
mstp_port->TokenCount = Npoll;
|
mstp_port->TokenCount = Npoll;
|
||||||
|
mstp_port->RetryCount = 0;
|
||||||
mstp_port->EventCount = 0;
|
mstp_port->EventCount = 0;
|
||||||
mstp_port->SoleMaster = true;
|
mstp_port->SoleMaster = true;
|
||||||
MSTP_Create_And_Send_Frame(mstp_port,
|
MSTP_Create_And_Send_Frame(mstp_port,
|
||||||
@@ -689,14 +701,12 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port)
|
|||||||
mstp_port->master_state = MSTP_MASTER_STATE_INITIALIZE;
|
mstp_port->master_state = MSTP_MASTER_STATE_INITIALIZE;
|
||||||
}
|
}
|
||||||
mstp_port->ReceivedValidFrame = false;
|
mstp_port->ReceivedValidFrame = false;
|
||||||
} else if ((mstp_port->DestinationAddress ==
|
} else {
|
||||||
mstp_port->This_Station) ||
|
|
||||||
(mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS)) {
|
|
||||||
/* destined for me! */
|
/* destined for me! */
|
||||||
switch (mstp_port->FrameType) {
|
switch (mstp_port->FrameType) {
|
||||||
case FRAME_TYPE_TOKEN:
|
case FRAME_TYPE_TOKEN:
|
||||||
/* ReceivedToken */
|
/* ReceivedToken */
|
||||||
/* tokens can't be broadcast */
|
/* tokens cannot be broadcast */
|
||||||
if (mstp_port->DestinationAddress ==
|
if (mstp_port->DestinationAddress ==
|
||||||
MSTP_BROADCAST_ADDRESS) {
|
MSTP_BROADCAST_ADDRESS) {
|
||||||
break;
|
break;
|
||||||
@@ -1336,6 +1346,33 @@ void MSTP_Zero_Config_UUID_Init(struct mstp_port_struct_t *mstp_port)
|
|||||||
mstp_port->UUID[8] = 0x80 | (mstp_port->UUID[8] & 0x3f);
|
mstp_port->UUID[8] = 0x80 | (mstp_port->UUID[8] & 0x3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Increment the Zero Configuration Station address
|
||||||
|
* @param station the current station address in the range of min..max
|
||||||
|
* @return the next station address
|
||||||
|
*/
|
||||||
|
unsigned MSTP_Zero_Config_Station_Increment(unsigned station)
|
||||||
|
{
|
||||||
|
unsigned next_station;
|
||||||
|
|
||||||
|
if (station < Nmin_poll_station) {
|
||||||
|
next_station = Nmin_poll_station;
|
||||||
|
} else {
|
||||||
|
#ifdef MSTP_ZERO_CONFIG_STATION_INCREMENT_MODULO
|
||||||
|
/* as defined by specification language */
|
||||||
|
next_station = Nmin_poll_station +
|
||||||
|
((station + 1) % ((Nmax_poll_station - Nmin_poll_station) + 1));
|
||||||
|
#else
|
||||||
|
next_station = station + 1;
|
||||||
|
if (next_station > Nmax_poll_station) {
|
||||||
|
next_station = Nmin_poll_station;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return next_station;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The ZERO_CONFIGURATION_INIT state is entered when
|
* @brief The ZERO_CONFIGURATION_INIT state is entered when
|
||||||
* ZeroConfigurationMode is TRUE
|
* ZeroConfigurationMode is TRUE
|
||||||
@@ -1350,13 +1387,12 @@ static void MSTP_Zero_Config_State_Init(struct mstp_port_struct_t *mstp_port)
|
|||||||
}
|
}
|
||||||
mstp_port->Poll_Count = 0;
|
mstp_port->Poll_Count = 0;
|
||||||
mstp_port->Zero_Config_Station = Nmin_poll_station;
|
mstp_port->Zero_Config_Station = Nmin_poll_station;
|
||||||
mstp_port->Npoll_slot = 1 + (rand() % Nmax_poll_slot);
|
mstp_port->Npoll_slot = 1 + (mstp_port->UUID[0] % Nmax_poll_slot);
|
||||||
/* basic silence timeout is the dropped token time plus
|
/* basic silence timeout is the dropped token time plus
|
||||||
one Tslot after the last master node. Add one Tslot of
|
one Tslot after the last master node. Add one Tslot of
|
||||||
silence timeout per zero config priority slot */
|
silence timeout per zero config priority slot */
|
||||||
slots = 128 + mstp_port->Npoll_slot;
|
slots = 128 + mstp_port->Npoll_slot;
|
||||||
mstp_port->Zero_Config_Silence = Tno_token + Tslot * slots;
|
mstp_port->Zero_Config_Silence = Tno_token + Tslot * slots;
|
||||||
MSTP_Zero_Config_UUID_Init(mstp_port);
|
|
||||||
mstp_port->Zero_Config_Max_Master = 0;
|
mstp_port->Zero_Config_Max_Master = 0;
|
||||||
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_IDLE;
|
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_IDLE;
|
||||||
}
|
}
|
||||||
@@ -1426,23 +1462,23 @@ static void MSTP_Zero_Config_State_Lurk(struct mstp_port_struct_t *mstp_port)
|
|||||||
if (src == mstp_port->Zero_Config_Station) {
|
if (src == mstp_port->Zero_Config_Station) {
|
||||||
/* AddressInUse */
|
/* AddressInUse */
|
||||||
/* monitor PFM from the next address */
|
/* monitor PFM from the next address */
|
||||||
mstp_port->Zero_Config_Station++;
|
mstp_port->Zero_Config_Station =
|
||||||
if (mstp_port->Zero_Config_Station > Nmax_poll_station) {
|
MSTP_Zero_Config_Station_Increment(
|
||||||
/* start again from first */
|
mstp_port->Zero_Config_Station);
|
||||||
mstp_port->Zero_Config_Station = Nmin_poll_station;
|
|
||||||
}
|
|
||||||
mstp_port->Poll_Count = 0;
|
mstp_port->Poll_Count = 0;
|
||||||
} else if ((frame == FRAME_TYPE_POLL_FOR_MASTER) &&
|
} else if ((frame == FRAME_TYPE_POLL_FOR_MASTER) &&
|
||||||
(dst == mstp_port->Zero_Config_Station)) {
|
(dst == mstp_port->Zero_Config_Station)) {
|
||||||
mstp_port->Poll_Count++;
|
/* calculate this node poll count priority number */
|
||||||
/* calculate this node poll count priority */
|
|
||||||
count = Nmin_poll + mstp_port->Npoll_slot;
|
count = Nmin_poll + mstp_port->Npoll_slot;
|
||||||
if (mstp_port->Poll_Count == count) {
|
if (mstp_port->Poll_Count == count) {
|
||||||
/* ClaimAddress */
|
/* PollResponse */
|
||||||
MSTP_Create_And_Send_Frame(mstp_port,
|
MSTP_Create_And_Send_Frame(mstp_port,
|
||||||
FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER, src,
|
FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER, src,
|
||||||
mstp_port->Zero_Config_Station, NULL, 0);
|
mstp_port->Zero_Config_Station, NULL, 0);
|
||||||
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_CLAIM;
|
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_CLAIM;
|
||||||
|
} else {
|
||||||
|
/* CountFrame */
|
||||||
|
mstp_port->Poll_Count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (mstp_port->ReceivedInvalidFrame) {
|
} else if (mstp_port->ReceivedInvalidFrame) {
|
||||||
@@ -1470,7 +1506,6 @@ static void MSTP_Zero_Config_State_Claim(struct mstp_port_struct_t *mstp_port)
|
|||||||
if (!mstp_port) {
|
if (!mstp_port) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* */
|
|
||||||
if (mstp_port->ReceivedValidFrame) {
|
if (mstp_port->ReceivedValidFrame) {
|
||||||
mstp_port->ReceivedValidFrame = false;
|
mstp_port->ReceivedValidFrame = false;
|
||||||
dst = mstp_port->DestinationAddress;
|
dst = mstp_port->DestinationAddress;
|
||||||
@@ -1479,11 +1514,9 @@ static void MSTP_Zero_Config_State_Claim(struct mstp_port_struct_t *mstp_port)
|
|||||||
if (src == mstp_port->Zero_Config_Station) {
|
if (src == mstp_port->Zero_Config_Station) {
|
||||||
/* ClaimAddressInUse */
|
/* ClaimAddressInUse */
|
||||||
/* monitor PFM from the next address */
|
/* monitor PFM from the next address */
|
||||||
mstp_port->Zero_Config_Station++;
|
mstp_port->Zero_Config_Station =
|
||||||
if (mstp_port->Zero_Config_Station > Nmax_poll_station) {
|
MSTP_Zero_Config_Station_Increment(
|
||||||
/* start again from first */
|
mstp_port->Zero_Config_Station);
|
||||||
mstp_port->Zero_Config_Station = Nmin_poll_station;
|
|
||||||
}
|
|
||||||
mstp_port->Poll_Count = 0;
|
mstp_port->Poll_Count = 0;
|
||||||
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_LURK;
|
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_LURK;
|
||||||
} else if (frame == FRAME_TYPE_TOKEN) {
|
} else if (frame == FRAME_TYPE_TOKEN) {
|
||||||
@@ -1499,7 +1532,7 @@ static void MSTP_Zero_Config_State_Claim(struct mstp_port_struct_t *mstp_port)
|
|||||||
/* ClaimInvalidFrame */
|
/* ClaimInvalidFrame */
|
||||||
mstp_port->ReceivedInvalidFrame = false;
|
mstp_port->ReceivedInvalidFrame = false;
|
||||||
} else if (mstp_port->Zero_Config_Silence > 0) {
|
} else if (mstp_port->Zero_Config_Silence > 0) {
|
||||||
/* ClaimLostToken */
|
/* ClaimTimeout */
|
||||||
if (mstp_port->SilenceTimer((void *)mstp_port) >
|
if (mstp_port->SilenceTimer((void *)mstp_port) >
|
||||||
mstp_port->Zero_Config_Silence) {
|
mstp_port->Zero_Config_Silence) {
|
||||||
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_IDLE;
|
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_IDLE;
|
||||||
@@ -1550,13 +1583,14 @@ static void MSTP_Zero_Config_State_Confirm(struct mstp_port_struct_t *mstp_port)
|
|||||||
} else if (src == mstp_port->Zero_Config_Station) {
|
} else if (src == mstp_port->Zero_Config_Station) {
|
||||||
/* ConfirmationAddressInUse */
|
/* ConfirmationAddressInUse */
|
||||||
/* monitor PFM from the next address */
|
/* monitor PFM from the next address */
|
||||||
mstp_port->Zero_Config_Station++;
|
mstp_port->Zero_Config_Station =
|
||||||
if (mstp_port->Zero_Config_Station > Nmax_poll_station) {
|
MSTP_Zero_Config_Station_Increment(
|
||||||
/* start again from first */
|
mstp_port->Zero_Config_Station);
|
||||||
mstp_port->Zero_Config_Station = Nmin_poll_station;
|
|
||||||
}
|
|
||||||
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_LURK;
|
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_LURK;
|
||||||
}
|
}
|
||||||
|
} else if (mstp_port->ReceivedInvalidFrame) {
|
||||||
|
/* ConfirmationInvalidFrame */
|
||||||
|
mstp_port->ReceivedInvalidFrame = false;
|
||||||
} else if (mstp_port->SilenceTimer((void *)mstp_port) >=
|
} else if (mstp_port->SilenceTimer((void *)mstp_port) >=
|
||||||
mstp_port->Treply_timeout) {
|
mstp_port->Treply_timeout) {
|
||||||
/* ConfirmationTimeout */
|
/* ConfirmationTimeout */
|
||||||
@@ -1625,9 +1659,14 @@ void MSTP_Init(struct mstp_port_struct_t *mstp_port)
|
|||||||
mstp_port->Treply_delay = DEFAULT_Treply_delay;
|
mstp_port->Treply_delay = DEFAULT_Treply_delay;
|
||||||
mstp_port->Treply_timeout = DEFAULT_Treply_timeout;
|
mstp_port->Treply_timeout = DEFAULT_Treply_timeout;
|
||||||
mstp_port->Tusage_timeout = DEFAULT_Tusage_timeout;
|
mstp_port->Tusage_timeout = DEFAULT_Tusage_timeout;
|
||||||
|
mstp_port->SlaveNodeEnabled = false;
|
||||||
/* FIXME: point to functions */
|
/* FIXME: point to functions */
|
||||||
mstp_port->SilenceTimer = Timer_Silence;
|
mstp_port->SilenceTimer = Timer_Silence;
|
||||||
mstp_port->SilenceTimerReset = Timer_Silence_Reset;
|
mstp_port->SilenceTimerReset = Timer_Silence_Reset;
|
||||||
|
/* FIXME: set these in your dlmstp if you are zero-config */
|
||||||
|
mstp_port->ZeroConfigEnabled = true;
|
||||||
|
/* use the libc srand() and rand() generated random number*/
|
||||||
|
MSTP_Zero_Config_UUID_Init(&MSTP_Port);
|
||||||
#endif
|
#endif
|
||||||
if ((mstp_port->Tframe_abort < 6) || (mstp_port->Tframe_abort > 100)) {
|
if ((mstp_port->Tframe_abort < 6) || (mstp_port->Tframe_abort > 100)) {
|
||||||
mstp_port->Tframe_abort = DEFAULT_Tframe_abort;
|
mstp_port->Tframe_abort = DEFAULT_Tframe_abort;
|
||||||
|
|||||||
@@ -271,6 +271,9 @@ void MSTP_Fill_BACnet_Address(BACNET_ADDRESS *src, uint8_t mstp_address);
|
|||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
void MSTP_Zero_Config_UUID_Init(struct mstp_port_struct_t *mstp_port);
|
void MSTP_Zero_Config_UUID_Init(struct mstp_port_struct_t *mstp_port);
|
||||||
|
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
|
unsigned MSTP_Zero_Config_Station_Increment(unsigned station);
|
||||||
|
|
||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
void MSTP_Zero_Config_FSM(struct mstp_port_struct_t *mstp_port);
|
void MSTP_Zero_Config_FSM(struct mstp_port_struct_t *mstp_port);
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ add_compile_definitions(
|
|||||||
BIG_ENDIAN=0
|
BIG_ENDIAN=0
|
||||||
CONFIG_ZTEST=1
|
CONFIG_ZTEST=1
|
||||||
BACDL_MSTP=1
|
BACDL_MSTP=1
|
||||||
|
MSTP_ZERO_CONFIG_STATION_INCREMENT_MODULO
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
|
|||||||
@@ -643,6 +643,7 @@ static void testZeroConfigNode_Init(struct mstp_port_struct_t *mstp_port)
|
|||||||
/* configure for Zero Config */
|
/* configure for Zero Config */
|
||||||
mstp_port->ZeroConfigEnabled = true;
|
mstp_port->ZeroConfigEnabled = true;
|
||||||
mstp_port->This_Station = 255;
|
mstp_port->This_Station = 255;
|
||||||
|
MSTP_Zero_Config_UUID_Init(mstp_port);
|
||||||
|
|
||||||
MSTP_Init(mstp_port);
|
MSTP_Init(mstp_port);
|
||||||
zassert_true(mstp_port->master_state == MSTP_MASTER_STATE_INITIALIZE, NULL);
|
zassert_true(mstp_port->master_state == MSTP_MASTER_STATE_INITIALIZE, NULL);
|
||||||
@@ -1055,6 +1056,7 @@ static void testZeroConfigNode_Test_LURK_ClaimLostToken(
|
|||||||
static void testZeroConfigNodeFSM(void)
|
static void testZeroConfigNodeFSM(void)
|
||||||
{
|
{
|
||||||
struct mstp_port_struct_t MSTP_Port = { 0 }; /* port data */
|
struct mstp_port_struct_t MSTP_Port = { 0 }; /* port data */
|
||||||
|
unsigned station, next_station, test_station;
|
||||||
|
|
||||||
/* test case: timeout event */
|
/* test case: timeout event */
|
||||||
testZeroConfigNode_Init(&MSTP_Port);
|
testZeroConfigNode_Init(&MSTP_Port);
|
||||||
@@ -1117,6 +1119,27 @@ static void testZeroConfigNodeFSM(void)
|
|||||||
testZeroConfigNode_Test_IDLE_ValidFrame(&MSTP_Port);
|
testZeroConfigNode_Test_IDLE_ValidFrame(&MSTP_Port);
|
||||||
testZeroConfigNode_Test_LURK_Claim(&MSTP_Port);
|
testZeroConfigNode_Test_LURK_Claim(&MSTP_Port);
|
||||||
testZeroConfigNode_Test_LURK_ClaimLostToken(&MSTP_Port);
|
testZeroConfigNode_Test_LURK_ClaimLostToken(&MSTP_Port);
|
||||||
|
/* test next station rollover */
|
||||||
|
station = 0;
|
||||||
|
test_station = Nmin_poll_station;
|
||||||
|
next_station = MSTP_Zero_Config_Station_Increment(station);
|
||||||
|
zassert_equal(next_station, test_station, "station=%u next_station=%u",
|
||||||
|
station, next_station);
|
||||||
|
station = Nmin_poll_station;
|
||||||
|
test_station = Nmin_poll_station + 1;
|
||||||
|
next_station = MSTP_Zero_Config_Station_Increment(station);
|
||||||
|
zassert_equal(next_station, test_station, "station=%u next_station=%u",
|
||||||
|
station, next_station);
|
||||||
|
station = Nmax_poll_station - 1;
|
||||||
|
test_station = Nmax_poll_station;
|
||||||
|
next_station = MSTP_Zero_Config_Station_Increment(station);
|
||||||
|
zassert_equal(next_station, test_station,"station=%u next_station=%u",
|
||||||
|
station, next_station);
|
||||||
|
station = Nmax_poll_station;
|
||||||
|
test_station = Nmin_poll_station;
|
||||||
|
next_station = MSTP_Zero_Config_Station_Increment(station);
|
||||||
|
zassert_equal(next_station, test_station, "station=%u next_station=%u",
|
||||||
|
station, next_station);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user