1
0
mirror of https://github.com/stargieg/bacnet-stack synced 2025-10-26 23:35:52 +08:00
This commit is contained in:
Patrick Grimm
2013-03-21 22:53:31 +01:00
parent 5668c55fca
commit 01349ec9e8
843 changed files with 190207 additions and 0 deletions

275
ports/rtos32/bip-init.c Normal file
View File

@@ -0,0 +1,275 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2005 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#include <stdint.h> /* for standard integer types uint8_t etc. */
#include <stdbool.h> /* for the standard bool type. */
#include "bacdcode.h"
#include "bip.h"
static int interface = SOCKET_ERROR; /* SOCKET_ERROR means no open interface */
/*-----------------------------------*/
static void Error(
const char *Msg)
{
int Code = WSAGetLastError();
#ifdef HOST
printf("%s, error code: %i\n", Msg, Code);
#else
printf("%s, error code: %s\n", Msg, xn_geterror_string(Code));
#endif
exit(1);
}
#ifndef HOST
/*-----------------------------------*/
void InterfaceCleanup(
void)
{
if (interface != SOCKET_ERROR) {
xn_interface_close(interface);
interface = SOCKET_ERROR;
#if DEVICE_ID == PRISM_PCMCIA_DEVICE
RTPCShutDown();
#endif
}
}
static void NetInitialize(
void)
/* initialize the TCP/IP stack */
{
int Result;
#ifndef HOST
if (!RTKDebugVersion()) /* switch of all diagnostics and error messages of RTIP-32 */
xn_callbacks()->cb_wr_screen_string_fnc = NULL;
#ifdef RTUSB_VER
RTURegisterCallback(USBAX172); /* ax172 and ax772 drivers */
RTURegisterCallback(USBAX772);
RTURegisterCallback(USBKeyboard); /* support USB keyboards */
FindUSBControllers(); /* install USB host controllers */
Sleep(2000); /* give the USB stack time to enumerate devices */
#endif
#ifdef DHCP
XN_REGISTER_DHCP_CLI() /* and optionally the DHCP client */
#endif
Result = xn_rtip_init(); /* Initialize the RTIP stack */
if (Result != 0)
Error("xn_rtip_init failed");
atexit(InterfaceCleanup); /* make sure the driver is shut down properly */
RTCallDebugger(RT_DBG_CALLRESET, (DWORD) exit, 0); /* even if we get restarted by the debugger */
Result = BIND_DRIVER(MINOR_0); /* tell RTIP what Ethernet driver we want (see netcfg.h) */
if (Result != 0)
Error("driver initialization failed");
#if DEVICE_ID == PRISM_PCMCIA_DEVICE
/* if this is a PCMCIA device, start the PCMCIA driver */
if (RTPCInit(-1, 0, 2, NULL) == 0)
Error("No PCMCIA controller found");
#endif
/* Open the interface */
interface =
xn_interface_open_config(DEVICE_ID, MINOR_0, ED_IO_ADD, ED_IRQ,
ED_MEM_ADD);
if (interface == SOCKET_ERROR)
Error("xn_interface_open_config failed");
else {
struct _iface_info ii;
#ifdef BACDL_ETHERNET
BACNET_ADDRESS my_address;
unsigned i;
#endif
xn_interface_info(interface, &ii);
printf
("Interface opened, MAC address: %02x-%02x-%02x-%02x-%02x-%02x\n",
ii.my_ethernet_address[0], ii.my_ethernet_address[1],
ii.my_ethernet_address[2], ii.my_ethernet_address[3],
ii.my_ethernet_address[4], ii.my_ethernet_address[5]);
#ifdef BACDL_ETHERNET
for (i = 0; i < 6; i++) {
my_address.mac[i] = ii.my_ethernet_address[i];
}
ethernet_set_my_address(&my_address);
#endif
}
#if DEVICE_ID == PRISM_PCMCIA_DEVICE || DEVICE_ID == PRISM_DEVICE
xn_wlan_setup(interface, /* iface_no: value returned by xn_interface_open_config() */
"network name", /* SSID : network name set in the access point */
"station name", /* Name : name of this node */
0, /* Channel : 0 for access points, 1..14 for ad-hoc */
0, /* KeyIndex: 0 .. 3 */
"12345", /* WEP Key : key to use (5 or 13 bytes) */
0); /* Flags : see manual and Wlanapi.h for details */
Sleep(1000); /* wireless devices need a little time before they can be used */
#endif /* WLAN device */
#if defined(AUTO_IP) /* use xn_autoip() to get an IP address */
Result = xn_autoip(interface, MinIP, MaxIP, NetMask, TargetIP);
if (Result == SOCKET_ERROR)
Error("xn_autoip failed");
else {
printf("Auto-assigned IP address %i.%i.%i.%i\n", TargetIP[0],
TargetIP[1], TargetIP[2], TargetIP[3]);
/* define default gateway and DNS server */
xn_rt_add(RT_DEFAULT, ip_ffaddr, DefaultGateway, 1, interface, RT_INF);
xn_set_server_list((DWORD *) DNSServer, 1);
}
#elif defined(DHCP) /* use DHCP */
{
DHCP_param param[] = { {SUBNET_MASK, 1}
, {DNS_OP, 1}
, {ROUTER_OPTION, 1}
};
DHCP_session DS;
DHCP_conf DC;
xn_init_dhcp_conf(&DC); /* load default DHCP options */
DC.plist = param; /* add MASK, DNS, and gateway options */
DC.plist_entries = sizeof(param) / sizeof(param[0]);
printf("Contacting DHCP server, please wait...\n");
Result = xn_dhcp(interface, &DS, &DC); /* contact DHCP server */
if (Result == SOCKET_ERROR)
Error("xn_dhcp failed");
memcpy(TargetIP, DS.client_ip, 4);
printf("My IP address is: %i.%i.%i.%i\n", TargetIP[0], TargetIP[1],
TargetIP[2], TargetIP[3]);
}
#else
/* Set the IP address and interface */
printf("Using static IP address %i.%i.%i.%i\n", TargetIP[0], TargetIP[1],
TargetIP[2], TargetIP[3]);
Result = xn_set_ip(interface, TargetIP, NetMask);
/* define default gateway and DNS server */
xn_rt_add(RT_DEFAULT, ip_ffaddr, DefaultGateway, 1, interface, RT_INF);
xn_set_server_list((DWORD *) DNSServer, 1);
#endif
#else /* HOST defined, run on Windows */
WSADATA wd;
Result = WSAStartup(0x0101, &wd);
#endif
if (Result != 0)
Error("TCP/IP stack initialization failed");
}
#endif
/******************************************************************
* DESCRIPTION: Converts the byte stored address to an inet address
* RETURN: none
* ALGORITHM: none
* NOTES: none
******************************************************************/
static void RTIP_To_Network_Address(
BYTE * octet_address,
struct in_addr *addr)
{
uint32_t ip_address = 0; /* for decoding the subnet mask */
decode_unsigned32(octet_address, &ip_address);
addr->s_addr = htonl(ip_address);
return;
}
static void set_broadcast_address(
uint32_t net_address)
{
long broadcast_address = 0;
long mask = 0;
/* Note: sometimes INADDR_BROADCAST does not let me get
any unicast messages. Not sure why... */
#if USE_INADDR
(void) net_address;
bip_set_broadcast_addr(INADDR_BROADCAST);
#else
if (IN_CLASSA(ntohl(net_address)))
broadcast_address =
(ntohl(net_address) & ~IN_CLASSA_HOST) | IN_CLASSA_HOST;
else if (IN_CLASSB(ntohl(net_address)))
broadcast_address =
(ntohl(net_address) & ~IN_CLASSB_HOST) | IN_CLASSB_HOST;
else if (IN_CLASSC(ntohl(net_address)))
broadcast_address =
(ntohl(net_address) & ~IN_CLASSC_HOST) | IN_CLASSC_HOST;
else if (IN_CLASSD(ntohl(net_address)))
broadcast_address =
(ntohl(net_address) & ~IN_CLASSD_HOST) | IN_CLASSD_HOST;
else
broadcast_address = INADDR_BROADCAST;
bip_set_broadcast_addr(htonl(broadcast_address));
#endif
}
bool bip_init(
char *ifname)
{
int rv = 0; /* return from socket lib calls */
struct sockaddr_in sin = { -1 };
int value = 1;
int sock_fd = -1;
struct in_addr my_addr;
(void) ifname;
NetInitialize();
RTIP_To_Network_Address(TargetIP, &my_addr);
bip_set_addr(my_addr.s_addr);
set_broadcast_address(my_addr.s_addr);
bip_set_port(htons((0xBAC0));
/* assumes that the driver has already been initialized */
sock_fd = socket(AF_INET, SOCK_DGRAM, IPROTO_UDP);
bip_set_socket(sock_fd);
if (sock_fd < 0)
return false;
/* bind the socket to the local port number and IP address */
sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = bip_get_port(); memset(&(sin.sin_zero), '\0', 8);
rv =
bind(sock_fd, (const struct sockaddr *) &sin, sizeof(struct sockaddr));
if (rv < 0) {
close(sock_fd); bip_set_socket(-1); return false;}
return true;}

282
ports/rtos32/dlmstp.c Normal file
View File

@@ -0,0 +1,282 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* 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 <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#if PRINT_ENABLED
#include <stdio.h>
#endif
#include "bacdef.h"
#include "mstp.h"
#include "dlmstp.h"
#include "rs485.h"
#include "npdu.h"
/* receive buffer */
static DLMSTP_PACKET Receive_Buffer;
/* temp buffer for NPDU insertion */
static uint8_t PDU_Buffer[MAX_MPDU];
/* local MS/TP port data */
static volatile struct mstp_port_struct_t MSTP_Port;
void dlmstp_init(
char *ifname)
{
(void) ifname;
/* initialize buffer */
Receive_Buffer.ready = false;
Receive_Buffer.pdu_len = 0;
/* initialize hardware */
RS485_Initialize();
MSTP_Init(&MSTP_Port, MSTP_Port.This_Station);
}
void dlmstp_cleanup(
void)
{
/* nothing to do for static buffers */
}
/* returns number of bytes sent on success, zero on failure */
int dlmstp_send_pdu(
BACNET_ADDRESS * dest, /* destination address */
BACNET_NPDU_DATA * npdu_data, /* network information */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len)
{ /* number of bytes of data */
int bytes_sent = 0;
uint8_t frame_type = 0;
uint8_t destination = 0; /* destination address */
BACNET_ADDRESS src;
unsigned mtu_len = 0;
if (MSTP_Port.TxReady == false) {
if (npdu_data->confirmed_message)
MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
else
MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
/* load destination MAC address */
if (dest && dest->mac_len == 1) {
destination = dest->mac[0];
} else {
#if PRINT_ENABLED
fprintf(stderr, "mstp: invalid destination MAC address!\n");
#endif
return -2;
}
/* header len */
mtu_len = MAX_HEADER - 2 /* data crc */ ;
if ((MAX_HEADER + pdu_len) > MAX_MPDU) {
#if PRINT_ENABLED
fprintf(stderr, "mstp: PDU is too big to send!\n");
#endif
return -4;
}
memmove(&PDU_Buffer[mtu_len], pdu, pdu_len);
mtu_len += pdu_len;
bytes_sent =
MSTP_Create_Frame((uint8_t *) & MSTP_Port.TxBuffer[0],
sizeof(MSTP_Port.TxBuffer), MSTP_Port.TxFrameType, destination,
MSTP_Port.This_Station, &PDU_Buffer[0], mtu_len);
MSTP_Port.TxLength = bytes_sent;
MSTP_Port.TxReady = true;
}
return bytes_sent;
}
/* called about once a millisecond */
void dlmstp_millisecond_timer(
void)
{
MSTP_Millisecond_Timer(&MSTP_Port);
}
/* returns the number of octets in the PDU, or zero on failure */
/* This function is expecting to be polled. */
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)
{
uint16_t pdu_len = 0;
(void) timeout;
/* only do receive state machine while we don't have a frame */
if ((MSTP_Port.ReceivedValidFrame == false) &&
(MSTP_Port.ReceivedInvalidFrame == false)) {
RS485_Check_UART_Data(&MSTP_Port);
MSTP_Receive_Frame_FSM(&MSTP_Port);
}
/* only do master state machine while rx is idle */
if (MSTP_Port.receive_state == MSTP_RECEIVE_STATE_IDLE) {
if (This_Station <= DEFAULT_MAX_MASTER) {
while (MSTP_Master_Node_FSM(&MSTP_Port)) {
};
}
}
/* see if there is a packet available */
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;
}
void dlmstp_fill_bacnet_address(
BACNET_ADDRESS * src,
uint8_t mstp_address)
{
int i = 0;
if (mstp_address == MSTP_BROADCAST_ADDRESS) {
/* mac_len = 0 if broadcast address */
src->mac_len = 0;
src->mac[0] = 0;
} else {
src->mac_len = 1;
src->mac[0] = mstp_address;
}
/* fill with 0's starting with index 1; index 0 filled above */
for (i = 1; i < MAX_MAC_LEN; i++) {
src->mac[i] = 0;
}
src->net = 0;
src->len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) {
src->adr[i] = 0;
}
}
/* for the MS/TP state machine to use for putting received data */
uint16_t dlmstp_put_receive(
uint8_t src, /* source MS/TP address */
uint8_t * pdu, /* PDU data */
uint16_t pdu_len)
{
if (Receive_Buffer.ready) {
/* FIXME: what to do when we miss a message? */
pdu_len = 0;
} else if (pdu_len < sizeof(Receive_Buffer.pdu)) {
dlmstp_fill_bacnet_address(&Receive_Buffer.address, src);
Receive_Buffer.pdu_len = pdu_len;
memmove(Receive_Buffer.pdu, pdu, pdu_len);
Receive_Buffer.ready = true;
} else {
/* FIXME: message too large? */
pdu_len = 0;
}
return pdu_len;
}
void dlmstp_set_my_address(
uint8_t mac_address)
{
/* FIXME: Master Nodes can only have address 1-127 */
MSTP_Port.This_Station = mac_address;
return;
}
/* 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 */
/* pass the token. Max_Info_Frames may have different values on different */
/* nodes. This may be used to allocate more or less of the available link */
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
/* node, its value shall be 1. */
void dlmstp_set_max_info_frames(
unsigned max_info_frames)
{
MSTP_Port.Nmax_info_frames = max_info_frames;
return;
}
unsigned dlmstp_max_info_frames(
void)
{
return MSTP_Port.Nmax_info_frames;
}
/* This parameter represents the value of the Max_Master property of the */
/* node's Device object. The value of Max_Master specifies the highest */
/* 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_master(
uint8_t max_master)
{
MSTP_Port.Nmax_master = max_master;
return;
}
uint8_t dlmstp_max_master(
void)
{
return MSTP_Port.Nmax_master;
}
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 */
my_address->len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) {
my_address->adr[i] = 0;
}
return;
}
void dlmstp_get_broadcast_address(
BACNET_ADDRESS * dest)
{ /* destination address */
int i = 0; /* counter */
if (dest) {
dest->mac_len = 1;
dest->mac[0] = MSTP_BROADCAST_ADDRESS;
dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* len=0 denotes broadcast address */
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = 0;
}
}
return;
}

345
ports/rtos32/ethernet.c Normal file
View File

@@ -0,0 +1,345 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* 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 <stdint.h> /* for standard integer types uint8_t etc. */
#include <stdbool.h> /* for the standard bool type. */
#include <stdio.h> /* for the standard bool type. */
#include <stdlib.h> /* for the standard bool type. */
#include <rttarget.h>
#include <rtk32.h>
#include <clock.h>
#include <socket.h>
#include <windows.h>
#include "ethernet.h"
#include "bacdcode.h"
#include "npdu.h"
/* commonly used comparison address for ethernet */
uint8_t Ethernet_Broadcast[MAX_MAC_LEN] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/* commonly used empty address for ethernet quick compare */
uint8_t Ethernet_Empty_MAC[MAX_MAC_LEN] = { 0, 0, 0, 0, 0, 0 };
/* my local device data - MAC address */
uint8_t Ethernet_MAC_Address[MAX_MAC_LEN] = { 0, 0, 0, 0, 0, 0 };
static SOCKET Ethernet_Socket = -1;
/* used for binding 802.2 */
static struct sockaddr Ethernet_Address = { 0 };
bool ethernet_valid(
void)
{
return (Ethernet_Socket != -1);
}
void ethernet_cleanup(
void)
{
if (ethernet_valid())
closesocket(Ethernet_Socket);
Ethernet_Socket = -1;
return;
}
bool ethernet_init(
char *interface_name)
{
int value = 1;
(void) interface_name;
/* setup the socket */
Ethernet_Socket = socket(AF_INET, SOCK_RAW, 0);
/*Ethernet_Socket = socket(AF_INET, SOCK_STREAM, 0); */
if (Ethernet_Socket < 0)
fprintf(stderr, "ethernet: failed to bind to socket!\r\n");
Ethernet_Address.sa_family = AF_INET;
memset(Ethernet_Address.sa_data, 0, sizeof(Ethernet_Address.sa_data));
if (bind(Ethernet_Socket, &Ethernet_Address,
sizeof(Ethernet_Address)) == SOCKET_ERROR)
fprintf(stderr, "ethernet: failed to bind to socket!\r\n");
/*setsockopt(Ethernet_Socket,SOL_SOCKET,SO_802_2,(char *)&value,sizeof(value)); */
return ethernet_valid();
}
/* function to send a packet out the 802.2 socket */
/* returns bytes sent on success, negative number on failure */
int ethernet_send(
BACNET_ADDRESS * dest, /* destination address */
BACNET_ADDRESS * src, /* source address */
BACNET_NPDU_DATA * npdu_data, /* network information */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len)
{ /* number of bytes of data */
int bytes = 0;
uint8_t mtu[MAX_MPDU] = { 0 };
int mtu_len = 0;
int i = 0;
(void) npdu_data;
/* don't waste time if the socket is not valid */
if (Ethernet_Socket < 0) {
fprintf(stderr, "ethernet: 802.2 socket is invalid!\n");
return -1;
}
/* load destination ethernet MAC address */
if (dest->mac_len == 6) {
for (i = 0; i < 6; i++) {
mtu[mtu_len] = dest->mac[i];
mtu_len++;
}
} else {
fprintf(stderr, "ethernet: invalid destination MAC address!\n");
return -2;
}
/* load source ethernet MAC address */
if (src->mac_len == 6) {
for (i = 0; i < 6; i++) {
mtu[mtu_len] = src->mac[i];
mtu_len++;
}
} else {
fprintf(stderr, "ethernet: invalid source MAC address!\n");
return -3;
}
if ((14 + 3 + pdu_len) > MAX_MPDU) {
fprintf(stderr, "ethernet: PDU is too big to send!\n");
return -4;
}
/* packet length */
mtu_len += encode_unsigned16(&mtu[12], 3 /*DSAP,SSAP,LLC */ + pdu_len);
/* Logical PDU portion */
mtu[mtu_len++] = 0x82; /* DSAP for BACnet */
mtu[mtu_len++] = 0x82; /* SSAP for BACnet */
mtu[mtu_len++] = 0x03; /* Control byte in header */
mtu_len = 17;
if ((mtu_len + pdu_len) > MAX_MPDU) {
fprintf(stderr, "ethernet: PDU is too big to send!\n");
return -4;
}
memcpy(&mtu[mtu_len], pdu, pdu_len);
mtu_len += pdu_len;
/* packet length - only the logical portion, not the address */
encode_unsigned16(&mtu[12], 3 + pdu_len);
/* Send the packet */
bytes = send(Ethernet_Socket, (const char *) &mtu, mtu_len, 0);
/* did it get sent? */
if (bytes < 0)
fprintf(stderr, "ethernet: Error sending packet: %s\n",
strerror(errno));
return bytes;
}
/* function to send a packet out the 802.2 socket */
/* returns bytes sent on success, negative number on failure */
int ethernet_send_pdu(
BACNET_ADDRESS * dest, /* destination address */
BACNET_NPDU_DATA * npdu_data, /* network information */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len)
{ /* number of bytes of data */
int i = 0; /* counter */
BACNET_ADDRESS src = { 0 }; /* source address */
for (i = 0; i < 6; i++) {
src.mac[i] = Ethernet_MAC_Address[i];
src.mac_len++;
}
/* FIXME: npdu_data? */
/* function to send a packet out the 802.2 socket */
/* returns 1 on success, 0 on failure */
return ethernet_send(dest, /* destination address */
&src, /* source address */
npdu_data, pdu, /* any data to be sent - may be null */
pdu_len); /* number of bytes of data */
}
/* receives an 802.2 framed packet */
/* returns the number of octets in the PDU, or zero on failure */
uint16_t ethernet_receive(
BACNET_ADDRESS * src, /* source address */
uint8_t * pdu, /* PDU data */
uint16_t max_pdu, /* amount of space available in the PDU */
unsigned timeout)
{ /* number of milliseconds to wait for a packet */
int received_bytes;
uint8_t buf[MAX_MPDU] = { 0 }; /* data */
uint16_t pdu_len = 0; /* return value */
fd_set read_fds;
int max;
struct timeval select_timeout;
/* Make sure the socket is open */
if (Ethernet_Socket <= 0)
return 0;
/* we could just use a non-blocking socket, but that consumes all
the CPU time. We can use a timeout; it is only supported as
a select. */
if (timeout >= 1000) {
select_timeout.tv_sec = timeout / 1000;
select_timeout.tv_usec =
1000 * (timeout - select_timeout.tv_sec * 1000);
} else {
select_timeout.tv_sec = 0;
select_timeout.tv_usec = 1000 * timeout;
}
FD_ZERO(&read_fds);
FD_SET(Ethernet_Socket, &read_fds);
max = Ethernet_Socket;
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0)
received_bytes = recv(Ethernet_Socket, (char *) &buf[0], MAX_MPDU, 0);
else
return 0;
/* See if there is a problem */
if (received_bytes < 0) {
/* EAGAIN Non-blocking I/O has been selected */
/* using O_NONBLOCK and no data */
/* was immediately available for reading. */
if (errno != EAGAIN)
fprintf(stderr, "ethernet: Read error in receiving packet: %s\n",
strerror(errno));
return 0;
}
if (received_bytes == 0)
return 0;
/* the signature of an 802.2 BACnet packet */
if ((buf[14] != 0x82) && (buf[15] != 0x82)) {
/*fprintf(stderr,"ethernet: Non-BACnet packet\n"); */
return 0;
}
/* copy the source address */
src->mac_len = 6;
memmove(src->mac, &buf[6], 6);
/* check destination address for when */
/* the Ethernet card is in promiscious mode */
if ((memcmp(&buf[0], Ethernet_MAC_Address, 6) != 0)
&& (memcmp(&buf[0], Ethernet_Broadcast, 6) != 0)) {
/*fprintf(stderr, "ethernet: This packet isn't for us\n"); */
return 0;
}
(void) decode_unsigned16(&buf[12], &pdu_len);
pdu_len -= 3 /* DSAP, SSAP, LLC Control */ ;
/* copy the buffer into the PDU */
if (pdu_len < max_pdu)
memmove(&pdu[0], &buf[17], pdu_len);
/* ignore packets that are too large */
/* client should check my max apdu first */
else
pdu_len = 0;
return pdu_len;
}
void ethernet_get_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0;
my_address->mac_len = 0;
for (i = 0; i < 6; i++) {
my_address->mac[i] = Ethernet_MAC_Address[i];
my_address->mac_len++;
}
my_address->net = 0; /* local only, no routing */
my_address->len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) {
my_address->adr[i] = 0;
}
return;
}
void ethernet_set_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0;
for (i = 0; i < 6; i++) {
Ethernet_MAC_Address[i] = my_address->mac[i];
}
return;
}
void ethernet_get_broadcast_address(
BACNET_ADDRESS * dest)
{ /* destination address */
int i = 0; /* counter */
if (dest) {
for (i = 0; i < 6; i++) {
dest->mac[i] = Ethernet_Broadcast[i];
}
dest->mac_len = 6;
dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* denotes broadcast address */
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = 0;
}
}
return;
}
void ethernet_debug_address(
const char *info,
BACNET_ADDRESS * dest)
{
int i = 0; /* counter */
if (info)
fprintf(stderr, "%s", info);
if (dest) {
fprintf(stderr, "Address:\n");
fprintf(stderr, " MAC Length=%d\n", dest->mac_len);
fprintf(stderr, " MAC Address=");
for (i = 0; i < MAX_MAC_LEN; i++) {
fprintf(stderr, "%02X ", (unsigned) dest->mac[i]);
}
fprintf(stderr, "\n");
fprintf(stderr, " Net=%hu\n", dest->net);
fprintf(stderr, " Len=%d\n", dest->len);
fprintf(stderr, " Adr=");
for (i = 0; i < MAX_MAC_LEN; i++) {
fprintf(stderr, "%02X ", (unsigned) dest->adr[i]);
}
fprintf(stderr, "\n");
}
return;
}

24
ports/rtos32/hardware.cfg Normal file
View File

@@ -0,0 +1,24 @@
// * The target computer is IBM-PC-AT compatible.
// * There is a minimum of 4 MB of RAM installed.
#ifdef DEBUGDOS
Region RealModeVectors 0 1k RAM NoAccess // interrupt vectors
Region BIOSDataArea 1k 3k RAM ReadOnly // BIOS data area
Region DOSMem 4k 252k RAM
Region LowMem 256k 256k RAM
#else
Region = RealModeVectors 0, 4k, RAM, NoAccess // interrupt vectors
// note: locate only has 4k granularity so the 0-1k will be readonly
// Region = RealModeVectors 0, 1k, RAM, NoAccess // interrupt vectors
// Region = BIOSDataArea 1k, 3k, RAM, ReadOnly // BIOS data area
Region = LowMem 4k, 508k, RAM, Assign // Conventional memory
#endif
Region = MoreLowMem 512k, 128k, RAM, Assign // Reserved BIOS ext
Region = MonoText B0000h 4k, Device, ReadWrite // Mono text video mem
Region = ColorText B8000h, 4k, Device, ReadWrite // Text mode video ram
Region = DiskOnChip D0000h, 8k, Device, ReadWrite // Driver Ampro Card
Region = DiskOnChip1 E8000h, 32k, Device, ReadWrite // Driver WinSys Card
Region = HighMem 1M, 3M, RAM, Assign // 3mb ext mem on target
Virtual HeapMem 1G
Virtual StackMem 2G
Virtual ProgMem 3G

128
ports/rtos32/init.c Normal file
View File

@@ -0,0 +1,128 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* 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 <rttarget.h>
#include <rtkernel.h>
#include <windows.h>
extern void RTEmuInit(
void);
#ifdef _MSC_VER
#define VOIDEXPORT _declspec(dllexport) void __cdecl
#else
#define VOIDEXPORT void __export __cdecl
#endif
/* DISK SYSTEM */
#ifdef DOC /* include DiskOnChip driver */
#include <rtfiles.h>
#define RTF_MAX_FILES 16 /* support for more open files (default is 8) */
#define RTF_BUFFERS_IN_BSS /* we do not need file I/O before the run-time */
#include <rtfdata.c> /* system is initialized */
/*#define READ_HEAD_BUFFER_SIZE 2048+4 */
/*static BYTE ReadAheadBuffer[READ_HEAD_BUFFER_SIZE]; */
static RTFDrvFLPYData FLPYDriveAData = { 0 };
static RTFDrvDOCData DOCDriveData = { 0 };
static RTFDrvIDEData IDEDriveData = { 0 };
RTFDevice RTFDeviceList[] = {
/* type,number,flags,driver,driverdata */
{RTF_DEVICE_FLOPPY, 0, 0, &RTFDrvFloppy, &FLPYDriveAData},
{RTF_DEVICE_FDISK, 0, 0, &RTFDrvDOC, &DOCDriveData},
{RTF_DEVICE_FDISK, 0, 0, &RTFDrvIDE, &IDEDriveData},
{0, 0, 0, NULL, NULL}
};
#endif
/* END OF DISK SYSTEM */
/* RTTarget only defines 64 Win32 handles, which are not enough for BACstac */
/* the following code is from the RTTarget manual, page 106 */
#define MAXHANDLES 1024
#define MAXOBJECTS 1024
#define MAXTYPES 32
RTW32Handle RTHandleTable[MAXHANDLES] = { {0} };
int RTHandleCount = MAXHANDLES;
RTW32Object RTObjectTable[MAXOBJECTS] = { {0} };
int RTObjectCount = MAXOBJECTS;
RTW32Types RTTypeTable[MAXTYPES] = { {0} };
int RTTypeCount = MAXTYPES;
#if 0
/* We can embed some files in the RTB file, like a binary
file used for configuring a remote device, using
'Locate File filename HighMem' in the config (.CFG) file.
However, the default setup for RTFiles and RTTarget
doesn't include the RAM files, so we need to specify
that here, as well as the LPT, console, and FAT.
From RTFiles-32 manual, ch. 7, "Using RTFiles-32 with
RTTarget-32" */
RTFileSystem Console = { RT_FS_CONSOLE, 0, 0, &RTConsoleFileSystem };
RTFileSystem LPTFiles = { RT_FS_LPT_DEVICE, 0, 0, &RTLPTFileSystem };
/* logical drive Z: can be used to access the RAM drive */
RTFileSystem RAMFiles = { RT_FS_FILE, 1 << ('Z' - 'A'), 0, &RTRAMFileSystem };
/* logical drive A: through D: are reserved for FAT */
RTFileSystem FATFiles =
{ RT_FS_FILE | RT_FS_IS_DEFAULT, 0x0F, 0x03, &RTFilesFileSystem };
RTFileSystem *RTFileSystemList[] = {
&Console,
&LPTFiles,
&RAMFiles,
&FATFiles,
NULL,
};
#endif
/*-----------------------------------*/
VOIDEXPORT Init(
void)
{
(void) RTSetFlags(RT_MM_VIRTUAL, 1); /* this is the better method */
(void) RTCMOSExtendHeap(); /* get as much memory as we can */
RTCMOSSetSystemTime(); /* get the right date and time */
RTEmuInit(); /* set up floating point emulation */
/* pizza - RTHaltCPL3 appears to cause problems with file handling */
/*RTIdleHandler = (void RTTAPI *)RTHaltCPL3; // low power when idle */
/* not needed with pre-emptive */
/*RTKTimeSlice(2); // allow same priority task switch */
RTKConfig.Flags |= RF_PREEMPTIVE; /* preemptive multitasking */
RTKConfig.Flags |= RF_WIN32MUTEX_MUTEX; /* Win32 mutexes are RTK32 mutexes */
RTKConfig.Flags |= RF_FPCONTEXT; /* saves floating point context for tasks */
RTKConfig.HookedIRQs |= 1 << 1; /* hook the keyboard IRQ */
RTKConfig.DefaultTaskStackSize = 1024 * 8; /* for Win32 task stacks req = 0 */
}

168
ports/rtos32/main.c Normal file
View File

@@ -0,0 +1,168 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* 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.
*
*********************************************************************/
/* This is one way to use the embedded BACnet stack under RTOS-32 */
/* compiled with Borland C++ 5.02 */
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <conio.h> /* for kbhit */
#include "config.h"
#include "bacdef.h"
#include "npdu.h"
#include "apdu.h"
#include "device.h"
#include "handlers.h"
#include "datalink.h"
#include "iam.h"
#include "txbuf.h"
/* RTOS-32 */
#include "rtkernel.h"
#if defined(RTK32_VER)
#define _USER32_
#define _KERNEL32_
#include <windows.h>
#include <rttarget.h> /* for RTCMOSSetSystemTime */
#include <rtfiles.h> /* file system */
#include <rtfsys.h> /* file system */
#include <Rttbios.h>
#endif
#include <rtcom.h> /* serial port driver */
#include <itimer.h> /* time measurement & timer interrupt rate control */
#include <rtkeybrd.h> /* interrupt handler for the keyboard */
/* buffers used for transmit and receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* set the handler for all the services we don't implement */
/* It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
handler_write_property);
}
void millisecond_task(
void)
{
Time ticks = 0; /* task cycle */
int i = 0; /* loop counter */
ticks = RTKGetTime() + MilliSecsToTicks(1);
while (TRUE) {
RTKDelayUntil(ticks);
dlmstp_millisecond_timer();
ticks += MilliSecsToTicks(1);
}
}
void RTOS_Initialize(
void)
{
/* allow OS to setup IRQ 1 by using a dummy call */
(void) kbhit();
RTKernelInit(5); /* get the kernel going */
RTKeybrdInit();
/*(void)CPUMoniInit(); /* not needed - just monitor idle task */ */
RTComInit();
ITimerInit();
if (RTCallDebugger(RT_DBG_MONITOR, 0, 0) != -1) {
/* Win32 structured exception - if no handler is
installed, TerminateProcess() will be called,
which will reboot - a good thing in our case. */
RTRaiseCPUException(0); /* Divide Error DIV and IDIV instructions. */
RTRaiseCPUException(1); /* Debug Any code or data reference. */
RTRaiseCPUException(2); /* NMI */
RTRaiseCPUException(3); /* Breakpoint INT 3 instruction. */
RTRaiseCPUException(4); /* Overflow INTO instruction. */
RTRaiseCPUException(5); /* BOUND Range Exceeded BOUND instruction. */
RTRaiseCPUException(6); /* Invalid Opcode (Undefined Opcode) */
/* RTRaiseCPUException(7); // Device Not Available (No Math Coprocessor) */
RTRaiseCPUException(8); /* Double Fault any exception instruction,NMI,INTR. */
RTRaiseCPUException(9); /* Co-Processor overrun */
RTRaiseCPUException(10); /* Invalid TSS Task switch or TSS access. */
RTRaiseCPUException(11); /* Segment Not Present Loading segment registers */
RTRaiseCPUException(12); /* Stack Seg Fault Stack ops /SS reg loads. */
RTRaiseCPUException(13); /* General Protection Any memory reference */
RTRaiseCPUException(14); /* Page Fault Any memory reference. */
RTRaiseCPUException(15); /* reserved */
RTRaiseCPUException(16); /* Floating-Point Error (Math Fault) */
}
/* setup 1ms timer tick */
SetTimerIntVal(1000);
/* per recommendation in manual */
RTKDelay(1);
RTCMOSSetSystemTime(); /* get the right time-of-day */
/* create timer tick task */
RTKCreateTask(millisecond_task, 16, 1024 * 8, "millisec task");
}
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
unsigned timeout = 100; /* milliseconds */
(void) argc;
(void) argv;
Device_Set_Object_Instance_Number(126);
Init_Service_Handlers();
RTOS_Initialize();
/* init the physical layer */
#ifdef BACDL_MSTP
dlmstp_set_my_address(0x05);
#endif
datalink_init(NULL);
Send_I_Am(&Handler_Transmit_Buffer[0]);
/* loop forever */
for (;;) {
/* input */
/* returns 0 bytes on timeout */
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
/* output */
/* blink LEDs, Turn on or off outputs, etc */
}
}

199
ports/rtos32/makefile.mak Normal file
View File

@@ -0,0 +1,199 @@
#
# Simple makefile to build an RTB executable for RTOS-32
#
# This makefile assumes Borland bcc32 development environment
# on Windows NT/9x/2000/XP
#
!ifndef RTOS32_DIR
RTOS32_DIR_Not_Defined:
@echo .
@echo You must define environment variable RTOS32_DIR to compile.
!endif
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = bacnet
PRODUCT_RTB = $(PRODUCT).rtb
PRODUCT_EXE = $(PRODUCT).exe
# Choose the Data Link Layer to Enable
#DEFINES = -DDOC;BIG_ENDIAN=0;TSM_ENABLED=1;PRINT_ENABLED=1;BACDL_BIP=1
#DEFINES = -DDOC;BIG_ENDIAN=0;TSM_ENABLED=1;PRINT_ENABLED=1;BACDL_ETHERNET=1
#DEFINES = -DDOC;BIG_ENDIAN=0;TSM_ENABLED=1;PRINT_ENABLED=1;BACDL_ARCNET=1
DEFINES = -DDOC;BIG_ENDIAN=0;TSM_ENABLED=1;PRINT_ENABLED=0;BACDL_MSTP=1
SRCS = main.c \
ethernet.c \
bip-init.c \
dlmstp.c \
rs485.c \
init.c \
..\..\bip.c \
..\..\mstp.c \
..\..\crc.c \
..\..\demo\handler\h_iam.c \
..\..\demo\handler\h_npdu.c \
..\..\demo\handler\h_whois.c \
..\..\demo\handler\h_wp.c \
..\..\demo\handler\h_rp.c \
..\..\demo\handler\noserv.c \
..\..\demo\handler\txbuf.c \
..\..\demo\handler\s_iam.c \
..\..\demo\handler\s_rp.c \
..\..\demo\handler\s_whois.c \
..\..\bacdcode.c \
..\..\bacstr.c \
..\..\bactext.c \
..\..\indtext.c \
..\..\bacapp.c \
..\..\bigend.c \
..\..\whois.c \
..\..\dcc.c \
..\..\iam.c \
..\..\rp.c \
..\..\wp.c \
..\..\arf.c \
..\..\awf.c \
..\..\demo\object\bacfile.c \
..\..\demo\object\device.c \
..\..\demo\object\ai.c \
..\..\demo\object\ao.c \
..\..\demo\object\av.c \
..\..\demo\object\bi.c \
..\..\demo\object\bo.c \
..\..\demo\object\bv.c \
..\..\demo\object\lsp.c \
..\..\demo\object\mso.c \
..\..\datalink.c \
..\..\tsm.c \
..\..\address.c \
..\..\abort.c \
..\..\reject.c \
..\..\bacerror.c \
..\..\apdu.c \
..\..\npdu.c
OBJS = $(SRCS:.c=.obj)
# Compiler definitions
#
CC = $(BORLAND_DIR)\bin\bcc32 +bcc32.cfg
LINK = $(BORLAND_DIR)\bin\tlink32
#LINK = $(BORLAND_DIR)\bin\ilink32
TLIB = $(BORLAND_DIR)\bin\tlib
LOCATE = $(RTOS32_DIR)\bin\rtloc
#
# Include directories
#
CC_DIR = $(BORLAND_DIR)\BIN
INCL_DIRS = -I$(BORLAND_DIR)\include;$(RTOS32_DIR)\include;..\..\include;..\..\demo\handler\;..\..\demo\object\;.
CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES)
# Libraries
#
RTOS32_LIB_DIR = $(RTOS32_DIR)\libbc
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBDIR = $(RTOS32_LIB_DIR);$(C_LIB_DIR)
LIBS = $(RTOS32_LIB_DIR)\RTFILES.LIB \
$(RTOS32_LIB_DIR)\RTFSK32.LIB \
$(RTOS32_LIB_DIR)\DRVDOC.LIB \
$(RTOS32_LIB_DIR)\RTIP.LIB \
$(RTOS32_LIB_DIR)\RTK32.LIB \
$(RTOS32_LIB_DIR)\FLTEMUMT.LIB \
$(RTOS32_LIB_DIR)\DRVRT32.LIB \
$(RTOS32_LIB_DIR)\RTEMUMT.LIB \
$(RTOS32_LIB_DIR)\RTT32.LIB \
$(RTOS32_LIB_DIR)\RTTHEAP.LIB \
#$(C_LIB_DIR)\DPMI32.lib \
$(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib
#
# Main target
#
# This should be the first one in the makefile
all : $(PRODUCT_RTB) monitor.rtb
monitor.rtb: monitor.cfg hardware.cfg
$(LOCATE) monitor
# debug using COM3 (ISA Card) as the debug port
# boot from floppy
debugcom3: hardware.cfg software.cfg $(PRODUCT_RTB) monitor.rtb
$(LOCATE) -DDEBUGCOM3 monitor
$(LOCATE) -d- -DMONITOR -DDEBUGCOM3 $(PRODUCT) software.cfg
$(PRODUCT_RTB): bcc32.cfg hardware.cfg software.cfg $(PRODUCT_EXE)
@echo Running Locate on $(PRODUCT)
$(LOCATE) $(PRODUCT) software.cfg
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&) because command line is too long
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(LINKER_LIB) -m -c -s -v @&&| # temp response file, starts with |
$(BORLAND_DIR)\lib\c0x32.obj $** # $** lists each dependency
$<
$*.map
$(LIBS)
| # end of temp response file
#
# Utilities
clean :
@echo Deleting obj files, $(PRODUCT_EXE), $(PRODUCT_RTB) and map files.
del *.obj
del ..\..\*.obj
del $(PRODUCT_EXE)
del $(PRODUCT_RTB)
del *.map
del bcc32.cfg
install : $(PRODUCT)
copy $(PRODUCT) ..\bin
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) -o$@ $<
# Compiler configuration file
bcc32.cfg :
Copy &&|
$(CFLAGS)
-c
#-g2 #stop after gN warnings
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile

47
ports/rtos32/monitor.cfg Normal file
View File

@@ -0,0 +1,47 @@
// Configuration files for the RTTarget-32 Debug Monitor and Borland C/C++.
// Some general parameters for this file are:
//
// * The default disk boot code is used to boot the system from
// a floppy disk, hard disk, or ROM disk.
// * Pageing is enabled.
// * The program privilege level is set to 3 for maximum protection.
// * Boot code and the Monitor are placed in low (conventional) memory.
// * The target PC is assumed to have a color display.
// * The target PC uses COM1 to communicated with the host.
// * 115200 baud is used for host - target communication.
@HARDWARE.CFG // pull in hardware definitions
Locate BootCode BIOSBOOT.EXE LowMem // boot from disk
Locate BootData BootData LowMem 0 16 // boot stuff must be in conventional memory
Locate DiskBuffer DiskIO LowMem 16k 16k // needed by disk boot code
CPL = 0
Locate Section CODE LowMem 1 // Monitor's code section
Locate Header Monitor LowMem 0 4 // and header
Locate Section DATA LowMem 2 // data section
Locate Stack Stack LowMem 1k 4 // and a small stack, no heap
Locate PageTable Pages LowMem
Locate DecompCode Expand LowMem // include decompression stuff
Locate DecompData ExBuffer LowMem
Locate Copy CODE LowMem // compress everything
Locate Copy DATA LowMem // ditto
Locate Copy Pages LowMem // ditto
#ifdef DEBUGCOM1
COMPort COM1 115200 // use COM1 with 115200 baud
VideoRAM = None // program output sent to debugger - clrscr() crashes it.
#elifdef DEBUGCOM3
COMPort COM3 115200 9 // use COM3 IRQ9 115200 baud - Everex EV170 serial card
//VideoRAM = ColorText // program output sent to Graphic Card
VideoRAM = None // program output sent to debugger - clrscr() crashes it.
#else
COMPort COM3 115200 9 // use COM3 IRQ9 115200 baud - Everex EV170 serial card
VideoRAM = ColorText // program output sent to Graphic Card
#endif
IgnoreMsg "No heap" // the monitor does not need a heap

1278
ports/rtos32/mstp.c Normal file

File diff suppressed because it is too large Load Diff

193
ports/rtos32/mstp.h Normal file
View File

@@ -0,0 +1,193 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2004 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307
USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#ifndef MSTP_H
#define MSTP_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "bacdef.h"
#include "mstpdef.h"
#include "dlmstp.h"
struct mstp_port_struct_t {
MSTP_RECEIVE_STATE receive_state;
/* When a master node is powered up or reset, */
/* it shall unconditionally enter the INITIALIZE state. */
MSTP_MASTER_STATE master_state;
/* A Boolean flag set to TRUE by the Receive State Machine */
/* if an error is detected during the reception of a frame. */
/* Set to FALSE by the main state machine. */
unsigned ReceiveError:1;
/* There is data in the buffer */
unsigned DataAvailable:1;
unsigned FramingError:1; /* TRUE if we got a framing error */
unsigned ReceivedInvalidFrame:1;
/* A Boolean flag set to TRUE by the Receive State Machine */
/* if a valid frame is received. */
/* Set to FALSE by the main state machine. */
unsigned ReceivedValidFrame:1;
/* A Boolean flag set to TRUE by the master machine if this node is the */
/* only known master node. */
unsigned SoleMaster:1;
/* After receiving a frame this value will be TRUE until Tturnaround */
/* has expired */
unsigned Turn_Around_Waiting:1;
/* stores the latest received data */
uint8_t DataRegister;
/* Used to accumulate the CRC on the data field of a frame. */
uint16_t DataCRC;
/* Used to store the data length of a received frame. */
unsigned DataLength;
/* Used to store the destination address of a received frame. */
uint8_t DestinationAddress;
/* Used to count the number of received octets or errors. */
/* This is used in the detection of link activity. */
/* Compared to Nmin_octets */
uint8_t EventCount;
/* Used to store the frame type of a received frame. */
uint8_t FrameType;
/* The number of frames sent by this node during a single token hold. */
/* When this counter reaches the value Nmax_info_frames, the node must */
/* pass the token. */
unsigned FrameCount;
/* Used to accumulate the CRC on the header of a frame. */
uint8_t HeaderCRC;
/* Used as an index by the Receive State Machine, up to a maximum value of */
/* InputBufferSize. */
unsigned Index;
/* An array of octets, used to store octets as they are received. */
/* InputBuffer is indexed from 0 to InputBufferSize-1. */
/* The maximum size of a frame is 501 octets. */
uint8_t InputBuffer[MAX_MPDU];
/* "Next Station," the MAC address of the node to which This Station passes */
/* the token. If the Next_Station is unknown, Next_Station shall be equal to */
/* This_Station. */
uint8_t Next_Station;
/* "Poll Station," the MAC address of the node to which This Station last */
/* sent a Poll For Master. This is used during token maintenance. */
uint8_t Poll_Station;
/* A counter of transmission retries used for Token and Poll For Master */
/* transmission. */
unsigned RetryCount;
/* A timer with nominal 5 millisecond resolution used to measure and */
/* generate silence on the medium between octets. It is incremented by a */
/* timer process and is cleared by the Receive State Machine when activity */
/* is detected and by the SendFrame procedure as each octet is transmitted. */
/* Since the timer resolution is limited and the timer is not necessarily */
/* synchronized to other machine events, a timer value of N will actually */
/* denote intervals between N-1 and N */
uint16_t SilenceTimer;
/* A timer used to measure and generate Reply Postponed frames. It is */
/* incremented by a timer process and is cleared by the Master Node State */
/* Machine when a Data Expecting Reply Answer activity is completed. */
uint16_t ReplyPostponedTimer;
/* Used to store the Source Address of a received frame. */
uint8_t SourceAddress;
/* The number of tokens received by this node. When this counter reaches the */
/* value Npoll, the node polls the address range between TS and NS for */
/* additional master nodes. TokenCount is set to zero at the end of the */
/* polling process. */
unsigned TokenCount;
/* "This Station," the MAC address of this node. TS is generally read from a */
/* hardware DIP switch, or from nonvolatile memory. Valid values for TS are */
/* 0 to 254. The value 255 is used to denote broadcast when used as a */
/* destination address but is not allowed as a value for TS. */
uint8_t This_Station;
/* 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 */
/* pass the token. Max_Info_Frames may have different values on different */
/* nodes. This may be used to allocate more or less of the available link */
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
/* node, its value shall be 1. */
unsigned Nmax_info_frames;
/* This parameter represents the value of the Max_Master property of the */
/* node's Device object. The value of Max_Master specifies the highest */
/* 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. */
unsigned Nmax_master;
/* An array of octets, used to store PDU octets prior to being transmitted. */
/* This array is only used for APDU messages */
uint8_t TxBuffer[MAX_MPDU];
unsigned TxLength;
bool TxReady; /* true if ready to be sent or received */
uint8_t TxFrameType; /* type of message - needed by MS/TP */
};
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void MSTP_Init(
volatile struct mstp_port_struct_t *mstp_port,
uint8_t this_station_mac);
void MSTP_Millisecond_Timer(
volatile struct mstp_port_struct_t
*mstp_port);
void MSTP_Receive_Frame_FSM(
volatile struct mstp_port_struct_t
*mstp_port);
bool MSTP_Master_Node_FSM(
volatile struct mstp_port_struct_t
*mstp_port);
/* returns true if line is active */
bool MSTP_Line_Active(
volatile struct mstp_port_struct_t *mstp_port);
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) */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

80
ports/rtos32/net.h Normal file
View File

@@ -0,0 +1,80 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* 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.
*
*********************************************************************/
#ifndef NET_H
#define NET_H
/* network file for RTOS-32 from On-Time */
#define WIN32_LEAN_AND_MEAN
#define STRICT
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include "bip.h"
#ifndef HOST
#include <rtipapi.h>
#include "netcfg.h"
#include <rttarget.h>
#include <rtk32.h>
#include <clock.h>
#include <socket.h>
/*
* Definitions of bits in internet address integers.
* On subnets, the decomposition of addresses to host and net parts
* is done according to subnet mask, not the masks here.
*/
#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0)
#define IN_CLASSA_NET 0xff000000
#define IN_CLASSA_NSHIFT 24
#define IN_CLASSA_HOST 0x00ffffff
#define IN_CLASSA_MAX 128
#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000)
#define IN_CLASSB_NET 0xffff0000
#define IN_CLASSB_NSHIFT 16
#define IN_CLASSB_HOST 0x0000ffff
#define IN_CLASSB_MAX 65536
#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000)
#define IN_CLASSC_NET 0xffffff00
#define IN_CLASSC_NSHIFT 8
#define IN_CLASSC_HOST 0x000000ff
#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */
#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */
#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */
#define IN_MULTICAST(i) IN_CLASSD(i)
#else
#include <winsock.h>
#endif
#define close closesocket
typedef size_t socklen_t;
#endif

104
ports/rtos32/netcfg.h Normal file
View File

@@ -0,0 +1,104 @@
/**************************************************************************/
/* */
/* File: NetCfg.h Copyright (c) 1996,2004 */
/* Version: 4.0 On Time Informatik GmbH */
/* */
/* */
/* On Time /////////////----- */
/* Informatik GmbH ///////////// */
/* --------------------------------------------------///////////// */
/* Real-Time and System Software */
/* */
/**************************************************************************/
/* Network environment configuration file for the On Time RTOS-32 RTIP-32
demos.
By default, the RTIP-32 demos use static IP address assignment. If this is
not what you want, uncomment either #define AUTO_IP or #define DHCP. In all
cases, make sure the IP addresses (NetMask, TargetIP, DefaultGateway,
DNSServer, etc) given in the respective section below are all correct for
your select and LAN configuration. If you choose to use DHCP, the library
Dhcpc.lib must also be linked.
Please define symbol DEVICE_ID to match your target's ethernet
card and make sure that the card's hardware resource assigments are
correct (for PCI cards, the drivers will determine this information
automatically).
*/
/* #define AUTO_IP // use xn_autoip() to get an IP address */
/* #define DHCP // if you enable this, you must also link library dhcpc.lib */
#if defined(AUTO_IP) /* use xn_autoip() to get an IP address */
static BYTE TargetIP[] = { 0, 0, 0, 0 }; /* will be filled at run-time */
static BYTE NetMask[] = { 255, 255, 255, 0 };
static BYTE MinIP[] = { 192, 168, 0, 128 };
static BYTE MaxIP[] = { 192, 168, 0, 255 };
static BYTE DefaultGateway[] = { 192, 168, 0, 1 }; /* set to zero if not available or required */
static BYTE DNSServer[] = { 192, 168, 0, 1 }; /* ditto */
#elif defined(DHCP) /* use DHCP */
#include <dhcpcapi.h>
static BYTE TargetIP[] = { 0, 0, 0, 0 }; /* will be filled at run-time */
#else /* static IP address assignment (default) */
static BYTE TargetIP[] = { 192, 168, 0, 50 };
static BYTE NetMask[] = { 255, 255, 255, 0 };
static BYTE DefaultGateway[] = { 192, 168, 0, 1 }; /* set to zero if not available or required */
static BYTE DNSServer[] = { 192, 168, 0, 1 }; /* ditto */
#endif
#define DEVICE_ID DAVICOM_DEVICE /* define your device type here */
#ifndef DEVICE_ID
#error You must define Ethernet driver/resources and IP address/net mask here
#endif
/* The following values are ignored for PCI devices (the BIOS supplies */
/* them), but they must be set correctly for ISA/PCMCIA systems and for */
/* PCI devices if you do not have a BIOS */
#define ED_IO_ADD 0x300 /* I/O address of the device */
#define ED_IRQ 5 /* IRQ of the device */
#define ED_MEM_ADD 0 /* Memory Window (only some devices) */
/* Define function to pull in the required driver */
#if DEVICE_ID == NE2000_DEVICE
#define BIND_DRIVER xn_bind_ne2000
#elif DEVICE_ID == N83815_DEVICE
#define BIND_DRIVER xn_bind_n83815
#elif DEVICE_ID == TC90X_DEVICE
#define BIND_DRIVER xn_bind_tc90x
#elif DEVICE_ID == SMC91C9X_DEVICE
#define BIND_DRIVER xn_bind_smc91c9x
#elif DEVICE_ID == LANCE_DEVICE
#define BIND_DRIVER xn_bind_rtlance
#elif DEVICE_ID == LANCE_ISA_DEVICE
#define BIND_DRIVER xn_bind_lance_isa
#elif DEVICE_ID == LAN_CS89X0_DEVICE
#define BIND_DRIVER xn_bind_cs
#elif DEVICE_ID == I82559_DEVICE
#define BIND_DRIVER xn_bind_i82559
#elif DEVICE_ID == R8139_DEVICE
#define BIND_DRIVER xn_bind_r8139
#elif DEVICE_ID == DAVICOM_DEVICE
#define BIND_DRIVER xn_bind_davicom
#elif DEVICE_ID == RHINE_DEVICE
#define BIND_DRIVER xn_bind_rhine
#elif DEVICE_ID == AX172_DEVICE
#include <rtusb.h> /* must also link Rtusb.lib and UsbInit.cpp */
#define BIND_DRIVER xn_bind_ax172
#elif DEVICE_ID == AX772_DEVICE
#include <rtusb.h> /* must also link Rtusb.lib and UsbInit.cpp */
#define BIND_DRIVER xn_bind_ax772
#elif DEVICE_ID == PRISM_DEVICE
#include <wlanapi.h> /* must also link Wlan.lib */
#define BIND_DRIVER xn_bind_prism
#elif DEVICE_ID == PRISM_PCMCIA_DEVICE
#include <rtpcmcia.h>
#include <wlanapi.h> /* must also link Wlan.lib */
#define BIND_DRIVER xn_bind_prism_pcmcia
#else
#error Invalid DEVICE_ID value
#endif

228
ports/rtos32/rs485.c Normal file
View File

@@ -0,0 +1,228 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* 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.
*
*********************************************************************/
#if PRINT_ENABLED
#define PRINT_ENABLED_RS485 1
#else
#define PRINT_ENABLED_RS485 0
#endif
#include <stdint.h>
#include <rtkernel.h>
#include <rtcom.h>
#include <itimer.h>
#if PRINT_ENABLED_RS485
#include <stdio.h>
#endif
#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 = 9600;
/* io base address */
static long RS485_Base = 0;
/* hardware IRQ number */
static long RS485_IRQ_Number = 0;
#if PRINT_ENABLED_RS485
static FineTime RS485_Debug_Transmit_Timer;
#endif
#if PRINT_ENABLED_RS485
void RS485_Print_Frame(
int port,
FineTime timer,
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
uint16_t nbytes)
{
uint16_t i; /* byte counter */
unsigned long duration; /* measures the time from last output to this one */
unsigned long seconds;
unsigned long milliseconds;
duration = ElapsedMilliSecs(timer);
seconds = duration / 1000U;
milliseconds = duration - (seconds * 1000U);
fprintf(stderr, "%0lu.%03lu: COM%d:", seconds, milliseconds, port + 1);
for (i = 0; i < nbytes; i++) {
unsigned value;
value = buffer[i];
fprintf(stderr, " %02X", value);
}
fprintf(stderr, "\n");
fflush(stderr);
}
#endif
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 int TestCOMPort(
int Base)
{ /* base address of UART */
int i;
for (i = 0; i < 256; i++) {
RTOut(Base + 7, (BYTE) i); /* write scratch register */
RTOut(Base + 1, RTIn(Base + 1)); /* read/write IER */
if (RTIn(Base + 7) != i) /* check scratch register */
return FALSE;
}
return TRUE;
}
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 */
if (!TestCOMPort(base))
return;
/* 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);
#if PRINT_ENABLED_RS485
fprintf(stderr, "RS485: COM%d Enabled\r\n", port + 1);
#endif
return;
}
void RS485_Initialize(
void)
{
#if PRINT_ENABLED_RS485
MarkTime(&RS485_Debug_Transmit_Timer);
#endif
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 */
/* fixme: wait turnaround time */
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);
/* SilenceTimer is cleared by the Receive State Machine when
activity is detected and by the SendFrame procedure as each
octet is transmitted. */
mstp_port->SilenceTimer = 0;
#if PRINT_ENABLED_RS485
RS485_Print_Frame(RS485_Port, RS485_Debug_Transmit_Timer, buffer, /* frame to send (up to 501 bytes of data) */
nbytes);
MarkTime(&RS485_Debug_Transmit_Timer);
#endif
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 = 1; /* milliseconds to wait for a character */
static Duration ticks = 0; /* duration to wait for data */
if (mstp_port->ReceiveError) {
/* wait for state machine to clear this */
RTKScheduler();
}
/* wait for state machine to read from the DataRegister */
else if (!mstp_port->DataAvailable) {
if (!ticks) {
ticks = MilliSecsToTicks(timeout);
if (!ticks)
ticks = 1;
}
/* check for data */
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;
}
}
} else
RTKScheduler();
}

60
ports/rtos32/rs485.h Normal file
View File

@@ -0,0 +1,60 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2004 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307
USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#ifndef RS485_H
#define RS485_H
#include <stdint.h>
#include "mstp.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void RS485_Initialize(
void);
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) */
void RS485_Check_UART_Data(
volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

3
ports/rtos32/setvars.bat Normal file
View File

@@ -0,0 +1,3 @@
set BORLAND_DIR=\bc5
set RTOS32_DIR=\code\rtos32

61
ports/rtos32/software.cfg Normal file
View File

@@ -0,0 +1,61 @@
// Configuration files for the application and Borland C/C++.
// Some general parameters for this file are:
// * The program will run under the control of the debugger or is
// downloaded using RTRun.
// * Paging is enabled.
// * The program privilege level is set to 3 for maximum protection.
// * Boot code and the Monitor are placed in low (conventional) memory.
// * The program is placed in high (extended) memory.
// * Unused low memory is remapped and appended to the high memory area.
// * The Turbo Debugger symbol tables are pulled in to support
// task positions at source level.
@HARDWARE.CFG
// Either use the monitor, or create bootable code.
#ifdef MONITOR
Reserve Monitor // leave room for Debug Monitor
#elifdef DEBUGDOS
Locate BootCode BIOSBOOT.EXE LowMem // boot from disk
Locate BootData BootData LowMem // must be in conventional mem
Locate DiskBuffer DiskIO LowMem 16k 16k // needed by disk boot code
NoFPU=0 // Check FPU
CPL = 3 // normal priveleges
VideoRAM ColorText // program output sent to Graphic Card
#else
Locate BootCode BIOSBOOT.EXE LowMem // boot from disk
Locate BootData BootData LowMem 0 16 // must be in conventional mem
Locate DiskBuffer DiskIO LowMem 16k 16k // needed by disk boot code
NoFPU=0 // Check FPU
CPL = 3 // normal priveleges
// VideoRAM ColorText // program output sent to Graphic Card
VideoRAM None // program output sent to file and host
#endif
FillRAM HeapMem // remap unused RAM
Locate Header Header LowMem // application header
Locate PageTable Paging LowMem 20k // paging to use this
Locate NTSection CODE ProgMem->HighMem // code section
Locate NTSection DATA ProgMem->HighMem // data section
Locate NTSection .tls ProgMem->HighMem // TLS data section
Locate NTSection .rdata ProgMem->HighMem // TLS directory
Locate Stack Stack StackMem->LowMem 6k // stack space for main()
Locate Heap Heap HeapMem // and the rest for the heap
// Compression needed if we are short on disk space - but shortens download
// Note that this is discardable, unless we use -d- option of RTLoc
Locate DecompCode Expand LowMem // include decompression stuff
Locate DecompData ExBuffer LowMem
Locate Copy Paging LowMem // compress Paging
Locate Copy CODE HighMem // compress CODE
Locate Copy DATA HighMem // compress DATA
Locate Nothing FloppyDMA MoreLowMem 18k 64k ReadWrite // floppy driver
Init _Init // do some standard initializations (see init.c)
CommandLine "bacnet.exe"

28
ports/rtos32/stdbool.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef STDBOOL_H
#define STDBOOL_H
/* C99 Boolean types for compilers without C99 support */
#ifndef __cplusplus
typedef char _Bool;
#ifndef bool
#define bool _Bool
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#define __bool_true_false_are_defined 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#endif

19
ports/rtos32/stdint.h Normal file
View File

@@ -0,0 +1,19 @@
/* Defines the standard integer types that are used in code */
/* for the x86 processor and Borland Compiler */
#ifndef STDINT_H
#define STDINT_H
#include <stddef.h>
typedef unsigned char uint8_t; /* 1 byte 0 to 255 */
typedef signed char int8_t; /* 1 byte -127 to 127 */
typedef unsigned short uint16_t; /* 2 bytes 0 to 65535 */
typedef signed short int16_t; /* 2 bytes -32767 to 32767 */
/*typedef unsigned short long uint24_t; // 3 bytes 0 to 16777215 */
typedef unsigned long uint32_t; /* 4 bytes 0 to 4294967295 */
typedef signed long int32_t; /* 4 bytes -2147483647 to 2147483647 */
/* typedef signed long long int64_t; */
/* typedef unsigned long long uint64_t; */
#endif /* STDINT_H */