diff --git a/bacnet-stack/ports/rtos32/main.c b/bacnet-stack/ports/rtos32/main.c index 671ac694..84f279ee 100644 --- a/bacnet-stack/ports/rtos32/main.c +++ b/bacnet-stack/ports/rtos32/main.c @@ -37,20 +37,35 @@ #ifdef BACDL_ETHERNET #include "ethernet.h" #define bacdl_receive ethernet_receive + #include "net.h" + #ifndef HOST + #include "netcfg.h" + #endif #endif #ifdef BACDL_BIP #include "bip.h" #define bacdl_receive bip_receive + #include "net.h" + #ifndef HOST + #include "netcfg.h" + #endif #endif -#include "net.h" -#ifndef HOST - #include "netcfg.h" +#ifdef BACDL_MSTP + #include "mstp.h" + #include "rs485.h" + #define bacdl_receive bip_receive #endif +#if (defined(BACDL_ETHERNET) || defined(BACDL_BIP)) static int interface = SOCKET_ERROR; // SOCKET_ERROR means no open interface +#endif // buffers used for transmit and receive static uint8_t Rx_Buf[MAX_MPDU] = {0}; +#ifdef BACDL_MSTP +volatile struct mstp_port_struct_t MSTP_Port; // port data +static uint8_t MSTP_MAC_Address = 0x05; // local MAC address +#endif static void Init_Device_Parameters(void) { @@ -88,6 +103,7 @@ static void Init_Service_Handlers(void) WritePropertyHandler); } +#if (defined(BACDL_ETHERNET) || defined(BACDL_BIP)) /*-----------------------------------*/ static void Error(const char * Msg) { @@ -241,6 +257,7 @@ static void NetInitialize(void) if (Result != 0) Error("TCP/IP stack initialization failed"); } +#endif int main(int argc, char *argv[]) { @@ -253,31 +270,45 @@ int main(int argc, char *argv[]) Init_Device_Parameters(); Init_Service_Handlers(); // init the physical layer - NetInitialize(); #ifdef BACDL_BIP + NetInitialize(); bip_set_address(TargetIP[0], TargetIP[1], TargetIP[2], TargetIP[3]); if (!bip_init()) return 1; #endif #ifdef BACDL_ETHERNET + NetInitialize(); if (!ethernet_init(NULL)) return 1; #endif + #ifdef BACDL_MSTP + RS485_Initialize(); + MSTP_Init(&MSTP_Port,MSTP_MAC_Address); + #endif // loop forever for (;;) { // input + #ifdef BACDL_MSTP + MSTP_Millisecond_Timer(&MSTP_Port); + // note: also called by RS-485 Receive ISR + RS485_Check_UART_Data(&MSTP_Port); + MSTP_Receive_Frame_FSM(&MSTP_Port); + #endif + #if (defined(BACDL_ETHERNET) || defined(BACDL_BIP)) // returns 0 bytes on timeout pdu_len = bacdl_receive( &src, &Rx_Buf[0], MAX_MPDU, timeout); + #endif // process + if (pdu_len) { npdu_handler( @@ -291,6 +322,9 @@ int main(int argc, char *argv[]) Send_IAm(); } // output + #ifdef BACDL_MSTP + MSTP_Master_Node_FSM(&MSTP_Port); + #endif // blink LEDs, Turn on or off outputs, etc } diff --git a/bacnet-stack/ports/rtos32/makefile.mak b/bacnet-stack/ports/rtos32/makefile.mak index 14b43073..2b054643 100644 --- a/bacnet-stack/ports/rtos32/makefile.mak +++ b/bacnet-stack/ports/rtos32/makefile.mak @@ -21,7 +21,14 @@ PRODUCT = bacnet PRODUCT_RTB = $(PRODUCT).rtb PRODUCT_EXE = $(PRODUCT).exe -SRCS = init.c main.c ethernet.c bip.c \ +# Choose the Data Link Layer to Enable +#DEFINES = -DDOC;BACDL_BIP=1 +#DEFINES = -DDOC;BACDL_ETHERNET=1 +DEFINES = -DDOC;BACDL_MSTP=1 + +SRCS = init.c main.c ethernet.c bip.c rs485.c \ + ..\..\mstp.c \ + ..\..\crc.c \ ..\..\handlers.c \ ..\..\bacdcode.c \ ..\..\bigend.c \ @@ -52,8 +59,6 @@ LOCATE = $(RTOS32_DIR)\bin\rtloc CC_DIR = $(BORLAND_DIR)\BIN CC_INCLDIR = $(BORLAND_DIR)\include INCL_DIRS = -I$(BORLAND_DIR)\include;$(RTOS32_DIR)\include;../../; -#DEFINES = -DDOC;BACDL_BIP=1 -DEFINES = -DDOC;BACDL_ETHERNET=1 CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES) diff --git a/bacnet-stack/ports/rtos32/rs485.c b/bacnet-stack/ports/rtos32/rs485.c new file mode 100644 index 00000000..15f81578 --- /dev/null +++ b/bacnet-stack/ports/rtos32/rs485.c @@ -0,0 +1,161 @@ +/************************************************************************** +* +* Copyright (C) 2005 Steve Karg +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +*********************************************************************/ + +#include +#include +#include +#include +#include "mstp.h" + +// note: use the RTKernel-C API so that it can use this library + +#define RS485_IO_ENABLE(p) ModemControl(p,0,DTR); +#define RS485_TRANSMIT_ENABLE(p) ModemControl(p,1,RTS); +#define RS485_RECEIVE_ENABLE(p) ModemControl(p,0,RTS); + +/* COM port number - COM1 = 0 */ +static int RS485_Port = COM2; +/* baud rate */ +static long RS485_Baud = 38400; +/* io base address */ +static long RS485_Base = 0; +/* hardware IRQ number */ +static long RS485_IRQ_Number = 0; + +static void RS485_Standard_Port_Settings(long port, long *pIRQ, long *pBase) +{ + switch (port) + { + case COM1: + *pBase = (long)0x3F8; + *pIRQ = 4L; + break; + case COM2: + *pBase = (long)0x2F8; + *pIRQ = 3L; + break; + case COM3: + *pBase = (long)0x3E8; + *pIRQ = 4L; + break; + case COM4: + *pBase = (long)0x2E8; + *pIRQ = 3L; + break; + default: + break; + } +} + +static RS485_Open_Port( + int port, /* COM port number - COM1 = 0 */ + long baud, /* baud rate */ + unsigned base, /* io base address */ + int irq) /* hardware IRQ number */ +{ + /* setup the COM IO */ + SetIOBase(port, base); + SetIRQ(port, irq); + + if (irq < 8) + RTKIRQTopPriority(irq,9); + + InitPort(port, baud, PARITY_NONE, 1, 8); + + if (HasFIFO(port)) + EnableFIFO(port,8); + EnableCOMInterrupt(port, 1024*4); + + /* enable the 485 via the DTR pin */ + RS485_IO_ENABLE(port); + RS485_RECEIVE_ENABLE(port); + + return; +} + +void RS485_Initialize(void) +{ + RS485_Standard_Port_Settings(RS485_Port, &RS485_IRQ_Number, &RS485_Base); + RS485_Open_Port(RS485_Port, RS485_Baud, RS485_Base, RS485_IRQ_Number); +} + +void RS485_Send_Frame( + volatile 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) +{ + bool status = true; // return value + + (void)mstp_port; + RS485_TRANSMIT_ENABLE(RS485_Port); + SendBlock(RS485_Port, (char *)buffer, nbytes); + /* need to wait at least 9600 baud * 512 bytes = 54mS */ + (void)WaitSendBufferEmpty(RS485_Port,MilliSecsToTicks(200)); + while (!(LineStatus(RS485_Port) & TX_SHIFT_EMPTY)) + RTKScheduler(); + RS485_RECEIVE_ENABLE(RS485_Port); + + return; +} + +void RS485_Check_UART_Data( + volatile struct mstp_port_struct_t *mstp_port) // port specific data +{ + COMData com_data = 0; /* byte from COM driver */ + unsigned timeout = 10; // milliseconds to wait for a character + Duration ticks; /* duration to wait for data */ + + if (mstp_port->ReceiveError) + { + // wait for state machine to clear this + } + // wait for state machine to read from the DataRegister + else if (!mstp_port->DataAvailable) + { + // check for data + ticks = MilliSecsToTicks(timeout); + if (!ticks) + ticks = 1; + if (RTKGetTimed(ReceiveBuffer[RS485_Port],&com_data,ticks)) + { + // if error, + if (com_data & (COM_OVERRUN << 8)) + mstp_port->ReceiveError = true; + else if (com_data & (COM_FRAME << 8)) + mstp_port->ReceiveError = true; + else + { + mstp_port->DataRegister = com_data & 0x00FF; + mstp_port->DataAvailable = true; + } + } + } +} + +void RS485_Process_Tx_Message(void) +{ + // nothing to do +} +