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:
@@ -48,7 +48,6 @@ CSRC = main.c \
|
||||
led.c \
|
||||
mstimer-init.c \
|
||||
netport.c \
|
||||
nvmdata.c \
|
||||
rs485.c \
|
||||
stack.c
|
||||
|
||||
|
||||
+49
-13
@@ -6,6 +6,7 @@
|
||||
* @copyright SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include <asf.h>
|
||||
#include "bacnet/basic/object/device.h"
|
||||
#include "bacnet/basic/sys/mstimer.h"
|
||||
#include "bacnet/datalink/datalink.h"
|
||||
#include "bacnet/datalink/dlmstp.h"
|
||||
@@ -14,12 +15,13 @@
|
||||
#include "led.h"
|
||||
#include "adc-hdw.h"
|
||||
#include "bacnet.h"
|
||||
#include "nvmdata.h"
|
||||
|
||||
static struct mstimer_callback_data_t BACnet_Callback;
|
||||
|
||||
/* MS/TP port */
|
||||
static struct mstp_port_struct_t MSTP_Port;
|
||||
static struct dlmstp_rs485_driver RS485_Driver = {
|
||||
static struct dlmstp_rs485_driver RS485_Driver = {
|
||||
.init = rs485_init,
|
||||
.send = rs485_bytes_send,
|
||||
.read = rs485_byte_available,
|
||||
@@ -27,17 +29,49 @@ static struct dlmstp_rs485_driver RS485_Driver = {
|
||||
.baud_rate = rs485_baud_rate,
|
||||
.baud_rate_set = rs485_baud_rate_set,
|
||||
.silence_milliseconds = rs485_silence_milliseconds,
|
||||
.silence_reset = rs485_silence_reset
|
||||
.silence_reset = rs485_silence_reset
|
||||
};
|
||||
static struct dlmstp_user_data_t MSTP_User_Data;
|
||||
static uint8_t Input_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
|
||||
*/
|
||||
static void dlmstp_configure(void)
|
||||
{
|
||||
uint8_t mac_address = 0;
|
||||
|
||||
/* initialize MSTP datalink layer */
|
||||
MSTP_Port.Nmax_info_frames = DLMSTP_MAX_INFO_FRAMES;
|
||||
MSTP_Port.Nmax_master = DLMSTP_MAX_MASTER;
|
||||
@@ -46,19 +80,21 @@ static void dlmstp_configure(void)
|
||||
MSTP_Port.OutputBuffer = Output_Buffer;
|
||||
MSTP_Port.OutputBufferSize = sizeof(Output_Buffer);
|
||||
/* user data */
|
||||
MSTP_Port.ZeroConfigEnabled = true;
|
||||
MSTP_Port.SlaveNodeEnabled = false;
|
||||
mac_address = dlmstp_mac_address();
|
||||
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_Port.UserData = &MSTP_User_Data;
|
||||
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();
|
||||
/* application initialization */
|
||||
rs485_baud_rate_set(38400);
|
||||
nvm_data_init();
|
||||
dlmstp_configure();
|
||||
bacnet_init();
|
||||
/* 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,13 +10,13 @@
|
||||
|
||||
#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) \
|
||||
eeprom_write_block((uint8_t *)(src),(uint8_t *)(dst), (size_t)(len))
|
||||
|
||||
#define nvm_read(src, dst, len) \
|
||||
eeprom_read_block((uint8_t *)dst, (const uint8_t *)(src),(size_t)(len))
|
||||
|
||||
|
||||
/*=============== EEPROM ================*/
|
||||
/* define EEPROM signature version */
|
||||
#define NVM_SIGNATURE 0
|
||||
@@ -54,14 +54,4 @@
|
||||
|
||||
/* free space 128..4096 */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void nvm_data_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
|
||||
@@ -210,6 +210,44 @@ uint32_t rs485_baud_rate(void)
|
||||
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
|
||||
*
|
||||
|
||||
@@ -25,6 +25,9 @@ void rs485_bytes_send(uint8_t *buffer, uint16_t nbytes);
|
||||
uint32_t rs485_baud_rate(void);
|
||||
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);
|
||||
void rs485_silence_reset(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user