Modified the MS/TP datalink on Linux to be able to run correctly as a datalink layer when built with the demos.
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#if PRINT_ENABLED
|
#if PRINT_ENABLED
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -58,6 +59,21 @@ void dlmstp_millisecond_timer(void)
|
|||||||
INCREMENT_AND_LIMIT_UINT16(MSTP_Port.SilenceTimer);
|
INCREMENT_AND_LIMIT_UINT16(MSTP_Port.SilenceTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *dlmstp_milliseconds_task(void *pArg)
|
||||||
|
{
|
||||||
|
struct timespec timeOut,remains;
|
||||||
|
|
||||||
|
timeOut.tv_sec = 0;
|
||||||
|
timeOut.tv_nsec = 1000000; /* 1 millisecond */
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
nanosleep(&timeOut, &remains);
|
||||||
|
dlmstp_millisecond_timer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void dlmstp_reinit(void)
|
void dlmstp_reinit(void)
|
||||||
{
|
{
|
||||||
//RS485_Reinit();
|
//RS485_Reinit();
|
||||||
@@ -66,54 +82,9 @@ void dlmstp_reinit(void)
|
|||||||
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
|
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dlmstp_init(void)
|
|
||||||
{
|
|
||||||
uint8_t data;
|
|
||||||
|
|
||||||
/* initialize buffer */
|
|
||||||
Receive_Buffer.ready = false;
|
|
||||||
Receive_Buffer.pdu_len = 0;
|
|
||||||
/* initialize hardware */
|
|
||||||
RS485_Initialize();
|
|
||||||
MSTP_Init(&MSTP_Port);
|
|
||||||
/* FIXME: implement your data storage */
|
|
||||||
data = 64;
|
|
||||||
#if 0
|
|
||||||
/* I2C_Read_Byte(
|
|
||||||
EEPROM_DEVICE_ADDRESS,
|
|
||||||
EEPROM_MSTP_MAC_ADDR); */
|
|
||||||
#endif
|
|
||||||
if (data <= 127)
|
|
||||||
MSTP_Port.This_Station = data;
|
|
||||||
else
|
|
||||||
dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
|
|
||||||
|
|
||||||
/* FIXME: implement your data storage */
|
|
||||||
data = 127;
|
|
||||||
#if 0
|
|
||||||
/* I2C_Read_Byte(
|
|
||||||
EEPROM_DEVICE_ADDRESS,
|
|
||||||
EEPROM_MSTP_MAX_MASTER_ADDR); */
|
|
||||||
#endif
|
|
||||||
if ((data <= 127) && (data >= MSTP_Port.This_Station))
|
|
||||||
MSTP_Port.Nmax_master = data;
|
|
||||||
else
|
|
||||||
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
|
|
||||||
/* FIXME: implement your data storage */
|
|
||||||
data = 1;
|
|
||||||
#if 0
|
|
||||||
/* I2C_Read_Byte(
|
|
||||||
EEPROM_DEVICE_ADDRESS,
|
|
||||||
EEPROM_MSTP_MAX_INFO_FRAMES_ADDR); */
|
|
||||||
#endif
|
|
||||||
if (data >= 1)
|
|
||||||
MSTP_Port.Nmax_info_frames = data;
|
|
||||||
else
|
|
||||||
dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dlmstp_cleanup(void)
|
void dlmstp_cleanup(void)
|
||||||
{
|
{
|
||||||
|
RS485_Cleanup();
|
||||||
/* nothing to do for static buffers */
|
/* nothing to do for static buffers */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,6 +313,41 @@ void dlmstp_get_broadcast_address(BACNET_ADDRESS * dest)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dlmstp_init(void)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
pthread_t hThread;
|
||||||
|
|
||||||
|
/* initialize buffer */
|
||||||
|
Receive_Buffer.ready = false;
|
||||||
|
Receive_Buffer.pdu_len = 0;
|
||||||
|
/* initialize hardware */
|
||||||
|
RS485_Initialize();
|
||||||
|
MSTP_Init(&MSTP_Port);
|
||||||
|
#if 0
|
||||||
|
/* FIXME: implement your data storage */
|
||||||
|
if (data <= 127)
|
||||||
|
MSTP_Port.This_Station = data;
|
||||||
|
else
|
||||||
|
dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
|
||||||
|
if ((data <= 127) && (data >= MSTP_Port.This_Station))
|
||||||
|
MSTP_Port.Nmax_master = data;
|
||||||
|
else
|
||||||
|
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
|
||||||
|
if (data >= 1)
|
||||||
|
MSTP_Port.Nmax_info_frames = data;
|
||||||
|
else
|
||||||
|
dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* start our MilliSec task */
|
||||||
|
rc = pthread_create(&hThread, NULL, dlmstp_milliseconds_task, NULL);
|
||||||
|
rc = pthread_create(&hThread, NULL, dlmstp_receive_fsm_task, NULL);
|
||||||
|
rc = pthread_create(&hThread, NULL, dlmstp_master_fsm_task, NULL);
|
||||||
|
|
||||||
|
atexit(dlmstp_cleanup);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TEST_DLMSTP
|
#ifdef TEST_DLMSTP
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@@ -356,25 +362,8 @@ void npdu_handler(
|
|||||||
fprintf(stderr, "NPDU: received PDU!\n");
|
fprintf(stderr, "NPDU: received PDU!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void *test_milliseconds_task(void *pArg)
|
|
||||||
{
|
|
||||||
struct timespec timeOut,remains;
|
|
||||||
|
|
||||||
timeOut.tv_sec = 0;
|
|
||||||
timeOut.tv_nsec = 1000000; /* 1 millisecond */
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
nanosleep(&timeOut, &remains);
|
|
||||||
dlmstp_millisecond_timer();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int rc = 0;
|
|
||||||
pthread_t hThread;
|
|
||||||
struct timespec timeOut,remains;
|
struct timespec timeOut,remains;
|
||||||
|
|
||||||
timeOut.tv_sec = 1;
|
timeOut.tv_sec = 1;
|
||||||
@@ -385,12 +374,10 @@ int main(int argc, char *argv[])
|
|||||||
RS485_Set_Interface(argv[1]);
|
RS485_Set_Interface(argv[1]);
|
||||||
}
|
}
|
||||||
RS485_Set_Baud_Rate(38400);
|
RS485_Set_Baud_Rate(38400);
|
||||||
dlmstp_init();
|
|
||||||
dlmstp_set_my_address(0x05);
|
dlmstp_set_my_address(0x05);
|
||||||
/* start our MilliSec task */
|
dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
|
||||||
rc = pthread_create(&hThread, NULL, test_milliseconds_task, NULL);
|
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
|
||||||
rc = pthread_create(&hThread, NULL, dlmstp_receive_fsm_task, NULL);
|
dlmstp_init();
|
||||||
rc = pthread_create(&hThread, NULL, dlmstp_master_fsm_task, NULL);
|
|
||||||
/* forever task */
|
/* forever task */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#if 0
|
#if 0
|
||||||
|
|||||||
@@ -1203,9 +1203,9 @@ bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t * mstp_port)
|
|||||||
return transition_now;
|
return transition_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* note: This_Station should be set with the MAC address */
|
/* note: This_Station assumed to be set with the MAC address */
|
||||||
/* note: Nmax_info_frames should be set */
|
/* note: Nmax_info_frames assumed to be set (default=1) */
|
||||||
/* note: Nmax_master should be set */
|
/* note: Nmax_master assumed to be set (default=127) */
|
||||||
void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port)
|
void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port)
|
||||||
{
|
{
|
||||||
int i; /*loop counter */
|
int i; /*loop counter */
|
||||||
|
|||||||
@@ -137,50 +137,6 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
|
|||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RS485_Initialize(void)
|
|
||||||
{
|
|
||||||
struct termios newtio;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Open device for reading and writing.
|
|
||||||
*/
|
|
||||||
RS485_Handle = open(RS485_Port_Name,
|
|
||||||
O_RDWR | O_NOCTTY | O_NDELAY );
|
|
||||||
if (RS485_Handle < 0) {
|
|
||||||
perror(RS485_Port_Name);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
/* non blocking for the read */
|
|
||||||
fcntl(RS485_Handle, F_SETFL, FNDELAY);
|
|
||||||
#else
|
|
||||||
/* effecient blocking for the read */
|
|
||||||
fcntl(RS485_Handle, F_SETFL, 0);
|
|
||||||
#endif
|
|
||||||
/* save current serial port settings */
|
|
||||||
tcgetattr(RS485_Handle,&RS485_oldtio);
|
|
||||||
/* clear struct for new port settings */
|
|
||||||
bzero(&newtio, sizeof(newtio));
|
|
||||||
/*
|
|
||||||
BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
|
|
||||||
CRTSCTS : output hardware flow control (only used if the cable has
|
|
||||||
all necessary lines. See sect. 7 of Serial-HOWTO)
|
|
||||||
CS8 : 8n1 (8bit,no parity,1 stopbit)
|
|
||||||
CLOCAL : local connection, no modem contol
|
|
||||||
CREAD : enable receiving characters
|
|
||||||
*/
|
|
||||||
newtio.c_cflag = RS485_Baud | CS8 | CLOCAL | CREAD;
|
|
||||||
/* Raw input */
|
|
||||||
newtio.c_iflag = 0;
|
|
||||||
/* Raw output */
|
|
||||||
newtio.c_oflag = 0;
|
|
||||||
/* no processing */
|
|
||||||
newtio.c_lflag = 0;
|
|
||||||
/* activate the settings for the port after flushing I/O */
|
|
||||||
tcsetattr(RS485_Handle,TCSAFLUSH,&newtio);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Transmits a Frame on the wire */
|
/* Transmits a Frame on the wire */
|
||||||
void RS485_Send_Frame(
|
void RS485_Send_Frame(
|
||||||
struct mstp_port_struct_t *mstp_port, /* port specific data */
|
struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||||
@@ -253,6 +209,52 @@ void RS485_Cleanup(void)
|
|||||||
close(RS485_Handle);
|
close(RS485_Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RS485_Initialize(void)
|
||||||
|
{
|
||||||
|
struct termios newtio;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Open device for reading and writing.
|
||||||
|
*/
|
||||||
|
RS485_Handle = open(RS485_Port_Name,
|
||||||
|
O_RDWR | O_NOCTTY | O_NDELAY );
|
||||||
|
if (RS485_Handle < 0) {
|
||||||
|
perror(RS485_Port_Name);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
/* non blocking for the read */
|
||||||
|
fcntl(RS485_Handle, F_SETFL, FNDELAY);
|
||||||
|
#else
|
||||||
|
/* effecient blocking for the read */
|
||||||
|
fcntl(RS485_Handle, F_SETFL, 0);
|
||||||
|
#endif
|
||||||
|
/* save current serial port settings */
|
||||||
|
tcgetattr(RS485_Handle,&RS485_oldtio);
|
||||||
|
/* clear struct for new port settings */
|
||||||
|
bzero(&newtio, sizeof(newtio));
|
||||||
|
/*
|
||||||
|
BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
|
||||||
|
CRTSCTS : output hardware flow control (only used if the cable has
|
||||||
|
all necessary lines. See sect. 7 of Serial-HOWTO)
|
||||||
|
CS8 : 8n1 (8bit,no parity,1 stopbit)
|
||||||
|
CLOCAL : local connection, no modem contol
|
||||||
|
CREAD : enable receiving characters
|
||||||
|
*/
|
||||||
|
newtio.c_cflag = RS485_Baud | CS8 | CLOCAL | CREAD;
|
||||||
|
/* Raw input */
|
||||||
|
newtio.c_iflag = 0;
|
||||||
|
/* Raw output */
|
||||||
|
newtio.c_oflag = 0;
|
||||||
|
/* no processing */
|
||||||
|
newtio.c_lflag = 0;
|
||||||
|
/* activate the settings for the port after flushing I/O */
|
||||||
|
tcsetattr(RS485_Handle,TCSAFLUSH,&newtio);
|
||||||
|
/* destructor */
|
||||||
|
atexit(RS485_Cleanup);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TEST_RS485
|
#ifdef TEST_RS485
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@@ -270,7 +272,6 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
RS485_Set_Baud_Rate(38400);
|
RS485_Set_Baud_Rate(38400);
|
||||||
RS485_Initialize();
|
RS485_Initialize();
|
||||||
atexit(RS485_Cleanup);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
written = write(RS485_Handle, wbuf, wlen);
|
written = write(RS485_Handle, wbuf, wlen);
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ extern "C" {
|
|||||||
volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
|
volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
|
||||||
uint32_t RS485_Get_Baud_Rate(void);
|
uint32_t RS485_Get_Baud_Rate(void);
|
||||||
bool RS485_Set_Baud_Rate(uint32_t baud);
|
bool RS485_Set_Baud_Rate(uint32_t baud);
|
||||||
|
void RS485_Cleanup(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user