diff --git a/bacnet-stack/dlmstp.h b/bacnet-stack/dlmstp.h index 10f1d1ce..eb2c4dd1 100644 --- a/bacnet-stack/dlmstp.h +++ b/bacnet-stack/dlmstp.h @@ -73,12 +73,6 @@ extern "C" { uint16_t max_pdu, /* amount of space available in the PDU */ unsigned timeout); /* milliseconds to wait for a packet */ - /* function for MS/TP state machine to use to get a packet - to transmit. It returns the number of bytes in the - packet, or 0 if none. */ - int dlmstp_get_transmit_pdu(BACNET_ADDRESS * dest, /* destination address */ - uint8_t * pdu); /* any data to be sent - may be null */ - /* This parameter represents the value of the Max_Info_Frames property of */ /* the node's Device object. The value of Max_Info_Frames specifies the */ /* maximum number of information frames the node may send before it must */ @@ -94,7 +88,7 @@ extern "C" { /* allowable address for master nodes. The value of Max_Master shall be */ /* less than or equal to 127. If Max_Master is not writable in a node, */ /* its value shall be 127. */ - void dlmstp_set_max_info_frames(uint8_t max_master); + void dlmstp_set_max_master(uint8_t max_master); uint8_t dlmstp_max_master(void); void dlmstp_set_my_address(uint8_t my_address); diff --git a/bacnet-stack/mstp.c b/bacnet-stack/mstp.c index b5aa758e..08392e02 100644 --- a/bacnet-stack/mstp.c +++ b/bacnet-stack/mstp.c @@ -50,7 +50,6 @@ #include "bytes.h" #include "crc.h" #include "rs485.h" -#include "ringbuf.h" /* MS/TP Frame Format */ /* All frames are of the following format: */ @@ -128,14 +127,17 @@ const unsigned Tusage_delay = 15; /* larger values for this timeout, not to exceed 100 milliseconds.) */ const unsigned Tusage_timeout = 20; -/* creates the 8 octet frame header */ -unsigned MSTP_Create_Frame_Header(uint8_t * buffer, /* where frame is loaded */ +unsigned MSTP_Create_Frame(uint8_t * buffer, /* where frame is loaded */ unsigned 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 source, /* source address */ + uint8_t * data, /* any data to be sent - may be null */ + unsigned 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 */ + unsigned index = 0; /* used to load the data portion of the frame */ /* not enough to do a header */ if (buffer_len < 8) @@ -155,53 +157,24 @@ unsigned MSTP_Create_Frame_Header(uint8_t * buffer, /* where frame is loaded crc8 = CRC_Calc_Header(buffer[6], crc8); buffer[7] = ~crc8; - return 8; /* returns the frame length */ -} - -/* copies the PDU to a buffer while calculating its CRC checksum - The CRC checksum is appended to the last two octets. */ -unsigned MSTP_Copy_PDU_CRC(uint8_t * buffer, /* where frame is loaded */ - unsigned buffer_len, /* amount of space available */ - uint16_t crc16, /* used to calculate the crc value */ - uint8_t * data, /* any data to be sent - may be null */ - unsigned data_len) -{ - unsigned index = 0; /* offset into the buffer */ - - if (buffer && data && data_len && ((data_len + 2) < buffer_len)) - { - for (index = 0; index < data_len; index++) - { - buffer[index] = data[index]; - crc16 = CRC_Calc_Data(buffer[index], crc16); - } - - crc16 = ~crc16; - buffer[data_len] = LO_BYTE(crc16); - buffer[data_len + 1] = HI_BYTE(crc16); - index = data_len + 2; + index = 8; + while (data_len && data && (index < buffer_len)) { + buffer[index] = *data; + crc16 = CRC_Calc_Data(buffer[index], crc16); + data++; + index++; + data_len--; } - - return index; -} - -unsigned MSTP_Create_Frame(uint8_t * buffer, /* where frame is loaded */ - unsigned 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 */ - unsigned data_len) -{ /* number of bytes of data (up to 501) */ - uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */ - unsigned index = 0; /* used to load the data portion of the frame */ - - index = MSTP_Create_Frame_Header(buffer, buffer_len, frame_type, - destination, source); - if (data && data_len) - { - index += MSTP_Copy_PDU_CRC(&buffer[index], buffer_len - index, - crc16, data, data_len); + /* append the data CRC if necessary */ + if (index > 8) { + if ((index + 2) <= buffer_len) { + crc16 = ~crc16; + buffer[index] = LO_BYTE(crc16); + index++; + buffer[index] = HI_BYTE(crc16); + index++; + } else + return 0; } return index; /* returns the frame length */ @@ -214,10 +187,10 @@ void MSTP_Create_And_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, uint8_t * data, /* any data to be sent - may be null */ unsigned data_len) { /* number of bytes of data (up to 501) */ - uint8_t buffer[MAX_MPDU] = { 0 }; + uint8_t buffer[MAX_MPDU] = {0}; /* buffer for sending */ uint16_t len = 0; /* number of bytes to send */ - len = (uint16_t) MSTP_Create_Frame(buffer, /* where frame is loaded */ + len = (uint16_t) MSTP_Create_Frame(&buffer[0], /* where frame is loaded */ sizeof(buffer), /* amount of space available */ frame_type, /* type of frame to send - see defines */ destination, /* destination address */ @@ -225,7 +198,9 @@ void MSTP_Create_And_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, data, /* any data to be sent - may be null */ data_len); /* number of bytes of data (up to 501) */ - RS485_Send_Frame(mstp_port, buffer, len); + RS485_Send_Frame(mstp_port, &buffer[0], len); + RS485_Process_Tx_Message(); + while (RS485_Tx_Complete()) {/* FIXME: watchdog? */}; } /* Millisecond Timer - called every millisecond */ @@ -543,6 +518,8 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port) void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) { + int mtu_len = 0; + int frame_type = 0; switch (mstp_port->master_state) { case MSTP_MASTER_STATE_INITIALIZE: @@ -669,31 +646,40 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) /* proprietary frames. */ case MSTP_MASTER_STATE_USE_TOKEN: /* NothingToSend */ - /* FIXME: If there is no data frame awaiting transmission, */ + if (!mstp_port->TxReady) { mstp_port->FrameCount = mstp_port->Nmax_info_frames; mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; } - /* SendNoWait */ - /* FIXME: If there is a frame awaiting transmission that */ - /* is of type Test_Response, BACnet Data Not Expecting Reply, */ - /* or a proprietary type that does not expect a reply, */ -/* { */ -/* // transmit the data frame */ -/* MSTP_Create_And_Send_Frame(?????????????); */ -/* FrameCount++; */ -/* mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; */ -/* } */ - /* SendAndWait */ - /* FIXME: If there is a frame awaiting transmission that is of */ - /* type Test_Request, BACnet Data Expecting Reply, or */ - /* a proprietary type that expects a reply, */ -/* { */ -/* // transmit the data frame */ -/* MSTP_Create_And_Send_Frame(); */ -/* FrameCount++; */ -/* mstp_port->master_state = MSTP_MASTER_STATE_WAIT_FOR_REPLY; */ -/* } */ + else + { + RS485_Send_Frame( + mstp_port, + &mstp_port->TxBuffer[0], + mstp_port->TxLength); + RS485_Process_Tx_Message(); + while (RS485_Tx_Complete()) {/* FIXME: watchdog? */}; + mstp_port->TxReady = false; + mstp_port->FrameCount++; + /* SendNoWait */ + /* There is a frame awaiting transmission that */ + /* is of type Test_Response, BACnet Data Not Expecting Reply, */ + /* or a proprietary type that does not expect a reply, */ + if ((mstp_port->TxFrameType == FRAME_TYPE_TEST_RESPONSE) || + (mstp_port->TxFrameType == FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY)) + { + mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; + } + /* SendAndWait */ + /* If there is a frame awaiting transmission that is of */ + /* type Test_Request, BACnet Data Expecting Reply, or */ + /* a proprietary type that expects a reply, */ + else if ((mstp_port->TxFrameType == FRAME_TYPE_TEST_REQUEST) || + (mstp_port->TxFrameType == FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY)) + { + mstp_port->master_state = MSTP_MASTER_STATE_WAIT_FOR_REPLY; + } + } /* In the WAIT_FOR_REPLY state, the node waits for */ /* a reply from another node. */ case MSTP_MASTER_STATE_WAIT_FOR_REPLY: diff --git a/bacnet-stack/mstp.h b/bacnet-stack/mstp.h index 7db177cc..4b53fd91 100644 --- a/bacnet-stack/mstp.h +++ b/bacnet-stack/mstp.h @@ -64,6 +64,9 @@ /* of a Proprietary frame shall be in the range of 2 to 501 octets. */ #define FRAME_TYPE_PROPRIETARY_MIN 128 #define FRAME_TYPE_PROPRIETARY_MAX 255 +/* The initial CRC16 checksum value */ +#define CRC16_INITIAL_VALUE (0xFFFF) + /* receive FSM states */ typedef enum { @@ -191,6 +194,13 @@ struct mstp_port_struct_t { /* less than or equal to 127. If Max_Master is not writable in a node, */ /* its value shall be 127. */ unsigned Nmax_master; + + /* An array of octets, used to store PDU octets prior to being transmitted. */ + /* This array is not used for passing token frames */ + uint8_t TxBuffer[MAX_MPDU]; + int TxLength; + bool TxReady; /* true if ready to be sent or received */ + uint8_t TxFrameType; /* type of message - needed by MS/TP */ }; #define DEFAULT_MAX_INFO_FRAMES 1 @@ -214,19 +224,13 @@ extern "C" { void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port); -/* creates the 8 octet frame header */ -unsigned MSTP_Create_Frame_Header(uint8_t * buffer, /* where frame is loaded */ +unsigned MSTP_Create_Frame(uint8_t * buffer, /* where frame is loaded */ unsigned 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 */ -/* copies the PDU to a buffer while calculating its CRC checksum - The CRC checksum is appended to the last two octets. */ -unsigned MSTP_Copy_PDU_CRC(uint8_t * buffer, /* where frame is loaded */ - unsigned buffer_len, /* amount of space available */ - uint16_t crc16, /* used to calculate the crc value */ + uint8_t source, /* source address */ uint8_t * data, /* any data to be sent - may be null */ - unsigned data_len); + unsigned data_len); /* number of bytes of data (up to 501) */ #ifdef __cplusplus diff --git a/bacnet-stack/ports/pic18/BACnet-Server.mcp b/bacnet-stack/ports/pic18/BACnet-Server.mcp index cf4a4372..09d643ec 100644 --- a/bacnet-stack/ports/pic18/BACnet-Server.mcp +++ b/bacnet-stack/ports/pic18/BACnet-Server.mcp @@ -67,7 +67,6 @@ file_047=no file_048=no file_049=no file_050=no -file_051=no [FILE_INFO] file_000=C:\code\bacnet-stack\abort.c file_001=C:\code\bacnet-stack\apdu.c @@ -83,14 +82,14 @@ file_010=C:\code\bacnet-stack\mstp.c file_011=C:\code\bacnet-stack\npdu.c file_012=C:\code\bacnet-stack\rd.c file_013=C:\code\bacnet-stack\reject.c -file_014=C:\code\bacnet-stack\ringbuf.c -file_015=C:\code\bacnet-stack\rp.c -file_016=C:\code\bacnet-stack\whois.c -file_017=C:\code\bacnet-stack\demo\handler\h_dcc.c -file_018=C:\code\bacnet-stack\demo\handler\h_rd.c -file_019=main.c -file_020=C:\code\bacnet-stack\demo\object\tiny_dev.c -file_021=dlmstp.c +file_014=C:\code\bacnet-stack\rp.c +file_015=C:\code\bacnet-stack\whois.c +file_016=C:\code\bacnet-stack\demo\handler\h_dcc.c +file_017=C:\code\bacnet-stack\demo\handler\h_rd.c +file_018=main.c +file_019=C:\code\bacnet-stack\demo\object\tiny_dev.c +file_020=dlmstp.c +file_021=rs485.c file_022=C:\code\bacnet-stack\wp.h file_023=C:\code\bacnet-stack\abort.h file_024=C:\code\bacnet-stack\apdu.h @@ -110,17 +109,16 @@ file_037=C:\code\bacnet-stack\mstp.h file_038=C:\code\bacnet-stack\npdu.h file_039=C:\code\bacnet-stack\rd.h file_040=C:\code\bacnet-stack\reject.h -file_041=C:\code\bacnet-stack\ringbuf.h -file_042=C:\code\bacnet-stack\rp.h -file_043=C:\code\bacnet-stack\rs485.h -file_044=C:\code\bacnet-stack\whois.h -file_045=C:\code\bacnet-stack\demo\handler\client.h -file_046=C:\code\bacnet-stack\demo\handler\handlers.h -file_047=C:\code\bacnet-stack\demo\object\ai.h -file_048=C:\code\bacnet-stack\demo\object\ao.h -file_049=C:\code\bacnet-stack\demo\object\device.h -file_050=stdbool.h -file_051=stdint.h +file_041=C:\code\bacnet-stack\rp.h +file_042=C:\code\bacnet-stack\rs485.h +file_043=C:\code\bacnet-stack\whois.h +file_044=C:\code\bacnet-stack\demo\handler\client.h +file_045=C:\code\bacnet-stack\demo\handler\handlers.h +file_046=C:\code\bacnet-stack\demo\object\ai.h +file_047=C:\code\bacnet-stack\demo\object\ao.h +file_048=C:\code\bacnet-stack\demo\object\device.h +file_049=stdbool.h +file_050=stdint.h [SUITE_INFO] suite_guid={5B7D72DD-9861-47BD-9F60-2BE967BF8416} suite_state= diff --git a/bacnet-stack/ports/pic18/BACnet-Server.mcw b/bacnet-stack/ports/pic18/BACnet-Server.mcw index c7ac1e2f..a2b34897 100644 Binary files a/bacnet-stack/ports/pic18/BACnet-Server.mcw and b/bacnet-stack/ports/pic18/BACnet-Server.mcw differ diff --git a/bacnet-stack/ports/pic18/dlmstp.c b/bacnet-stack/ports/pic18/dlmstp.c index 14576b86..3dad582e 100644 --- a/bacnet-stack/ports/pic18/dlmstp.c +++ b/bacnet-stack/ports/pic18/dlmstp.c @@ -31,23 +31,19 @@ #include "dlmstp.h" #include "rs485.h" #include "npdu.h" - -static DLMSTP_PACKET Receive_Buffer; -static DLMSTP_PACKET Transmit_Buffer; + +/* receive buffer */ +static DLMSTP_PACKET Receive_Buffer; +/* temp buffer for NPDU insertion */ static uint8_t PDU_Buffer[MAX_MPDU]; -/* local MS/TP port data */ -volatile struct mstp_port_struct_t MSTP_Port; /* port data */ +/* local MS/TP port data */ +static volatile struct mstp_port_struct_t MSTP_Port; void dlmstp_init(void) { /* initialize buffer */ Receive_Buffer.ready = false; - Receive_Buffer.data_expecting_reply = false; Receive_Buffer.pdu_len = 0; - /* initialize buffer */ - Transmit_Buffer.ready = false; - Transmit_Buffer.data_expecting_reply = false; - Transmit_Buffer.pdu_len = 0; /* initialize hardware */ RS485_Initialize(); MSTP_Init(&MSTP_Port, MSTP_Port.This_Station); @@ -66,16 +62,16 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */ { /* number of bytes of data */ bool status; int bytes_sent = 0; - int npdu_len = 0; + int npdu_len = 0; uint8_t frame_type = 0; uint8_t destination = 0; /* destination address */ BACNET_ADDRESS src; - if (Transmit_Buffer.ready == false) { + if (MSTP_Port.TxReady == false) { if (npdu_data->confirmed_message) - frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; + MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; else - frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY; + MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY; /* load destination MAC address */ if (dest && dest->mac_len == 1) { @@ -88,58 +84,28 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */ } dlmstp_get_my_address(&src); npdu_len = npdu_encode_pdu(&PDU_Buffer[0], dest, &src, npdu_data); - if ((8 + npdu_len + pdu_len) > MAX_MPDU) { + if ((8 /* header len */ + npdu_len + pdu_len) > MAX_MPDU) { #if PRINT_ENABLED fprintf(stderr, "mstp: PDU is too big to send!\n"); #endif return -4; - } - memcpy(&PDU_Buffer[npdu_len], pdu, pdu_len); -/* copies the PDU to a buffer while calculating its CRC checksum - The CRC checksum is appended to the last two octets. */ -unsigned MSTP_Copy_PDU_CRC(uint8_t * buffer, /* where frame is loaded */ - unsigned buffer_len, /* amount of space available */ - uint16_t crc16, /* used to calculate the crc value */ - uint8_t * data, /* any data to be sent - may be null */ - unsigned data_len); - + } + memmove(&PDU_Buffer[npdu_len], pdu, pdu_len); bytes_sent = MSTP_Create_Frame( - &Transmit_Buffer.pdu[0], - sizeof(Transmit_Buffer.pdu), - frame_type, + &MSTP_Port.TxBuffer[0], + sizeof(MSTP_Port.TxBuffer), + MSTP_Port.TxFrameType, destination, MSTP_Port.This_Station, &PDU_Buffer[0], - npdu_len + pdu_len); - Transmit_Buffer.ready = true; + npdu_len + pdu_len); + MSTP_Port.TxLength = bytes_sent; + MSTP_Port.TxReady = true; } return bytes_sent; } -/* function for MS/TP to use to get a packet to transmit - returns the number of bytes in the packet, or zero if none. */ -int dlmstp_get_transmit_pdu(BACNET_ADDRESS * dest, /* destination address */ - uint8_t * pdu) -{ /* any data to be sent - may be null */ - bool status; - DLMSTP_PACKET *packet; - unsigned pdu_len = 0; - - if (Transmit_Buffer.ready) { - memmove(dest, &packet->address, sizeof(packet->address)); - pdu_len = packet->pdu_len; - memmove(pdu, packet->pdu, sizeof(packet.pdu)); - } - - return pdu_len; -} - -int dlmstp_set_transmit_pdu_ready(bool ready) -{ - Transmit_Buffer.ready = ready; -} - void dlmstp_task(void) { RS485_Check_UART_Data(&MSTP_Port); @@ -161,16 +127,17 @@ uint16_t dlmstp_receive(BACNET_ADDRESS * src, /* source address */ uint8_t * pdu, /* PDU data */ uint16_t max_pdu, /* amount of space available in the PDU */ unsigned timeout) -{ - DLMSTP_PACKET *packet; - +{ + uint16_t pdu_len = 0; + (void) timeout; /* see if there is a packet available */ - if (!Ringbuf_Empty(&Receive_Buffer)) { - packet = (char *) Ringbuf_Pop_Front(&Receive_Buffer); - memmove(src, &packet->address, sizeof(packet->address)); - pdu_len = packet->pdu_len; - memmove(pdu, packet->pdu, max_pdu); + if (Receive_Buffer.ready) + { + memmove(src, &Receive_Buffer.address, sizeof(Receive_Buffer.address)); + pdu_len = Receive_Buffer.pdu_len; + memmove(&pdu[0], &Receive_Buffer.pdu[0], max_pdu); + Receive_Buffer.ready = false; } return pdu_len; @@ -181,17 +148,11 @@ uint16_t dlmstp_put_receive(BACNET_ADDRESS * src, /* source address */ uint8_t * pdu, /* PDU data */ uint16_t pdu_len) { - bool status; - int bytes_put = 0; + memmove(&Receive_Buffer.address, src, sizeof(Receive_Buffer.address)); + Receive_Buffer.pdu_len = pdu_len; + memmove(Receive_Buffer.pdu, pdu, sizeof(Receive_Buffer.pdu)); - memmove(&Temp_Packet.address, src, sizeof(Temp_Packet.address)); - Temp_Packet.pdu_len = pdu_len; - memmove(Temp_Packet.pdu, pdu, sizeof(Temp_Packet.pdu)); - status = Ringbuf_Put(&Receive_Buffer, &Temp_Packet); - if (status) - bytes_put = pdu_len; - - return bytes_put; + return pdu_len; } void dlmstp_set_my_address(uint8_t mac_address) @@ -226,7 +187,7 @@ unsigned dlmstp_max_info_frames(void) /* allowable address for master nodes. The value of Max_Master shall be */ /* less than or equal to 127. If Max_Master is not writable in a node, */ /* its value shall be 127. */ -void dlmstp_set_max_info_frames(uint8_t max_master) +void dlmstp_set_max_master(uint8_t max_master) { MSTP_Port.Nmax_master = max_master; @@ -240,6 +201,8 @@ uint8_t dlmstp_max_master(void) void dlmstp_get_my_address(BACNET_ADDRESS * my_address) { + int i = 0; /* counter */ + my_address->mac_len = 1; my_address->mac[0] = MSTP_Port.This_Station; my_address->net = 0; /* local only, no routing */ diff --git a/bacnet-stack/ports/pic18/rs485.c b/bacnet-stack/ports/pic18/rs485.c index 71460ed3..b472a430 100644 --- a/bacnet-stack/ports/pic18/rs485.c +++ b/bacnet-stack/ports/pic18/rs485.c @@ -207,6 +207,17 @@ void RS485_Process_Tx_Message(void) return; } +/**************************************************************************** +* DESCRIPTION: Returns the value of Transmit Complete flag. +* RETURN: none +* ALGORITHM: none +* NOTES: none +*****************************************************************************/ +bool RS485_Tx_Complete(void) +{ + return RS485_Flags.TransmitComplete; +} + /**************************************************************************** * DESCRIPTION: Checks for data on the receive UART, and handles errors * RETURN: none diff --git a/bacnet-stack/rs485.h b/bacnet-stack/rs485.h index 0409e8f3..ef9a22ff 100644 --- a/bacnet-stack/rs485.h +++ b/bacnet-stack/rs485.h @@ -53,6 +53,9 @@ extern "C" { void RS485_Process_Tx_Message(void); + bool RS485_Tx_Complete(void); + + #ifdef __cplusplus } #endif /* __cplusplus */