diff --git a/bacnet-stack/demo/readprop/main.c b/bacnet-stack/demo/readprop/main.c
index f3abfb32..17db21dc 100644
--- a/bacnet-stack/demo/readprop/main.c
+++ b/bacnet-stack/demo/readprop/main.c
@@ -284,7 +284,7 @@ int main(int argc, char *argv[]) {
Target_Object_Property = strtol(argv[4], NULL, 0);
if (argc > 5)
Target_Object_Index = strtol(argv[5], NULL, 0);
- if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
+ if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
diff --git a/bacnet-stack/include/bacenum.h b/bacnet-stack/include/bacenum.h
index ba7f1149..01fa1a0b 100644
--- a/bacnet-stack/include/bacenum.h
+++ b/bacnet-stack/include/bacenum.h
@@ -644,7 +644,8 @@ typedef enum {
typedef enum {
POLARITY_NORMAL = 0,
- POLARITY_REVERSE = 1
+ POLARITY_REVERSE = 1,
+ MAX_POLARITY = 2
} BACNET_POLARITY;
typedef enum {
@@ -932,7 +933,8 @@ typedef enum {
CHARACTER_JISC_6226 = 2,
CHARACTER_UCS4 = 3,
CHARACTER_UCS2 = 4,
- CHARACTER_ISO8859 = 5
+ CHARACTER_ISO8859 = 5,
+ MAX_CHARACTER_STRING_ENCODING = 6
} BACNET_CHARACTER_STRING_ENCODING;
typedef enum {
diff --git a/bacnet-stack/include/bits.h b/bacnet-stack/include/bits.h
index 0e6357db..ecf2fe74 100644
--- a/bacnet-stack/include/bits.h
+++ b/bacnet-stack/include/bits.h
@@ -82,4 +82,8 @@
#define BITMASK_FLIP(x,y) ((x) ^= (y))
#define BITMASK_CHECK(x,y) ((x) & (y))
+#ifndef _BV
+#define _BV(x) (1<<(x))
+#endif
+
#endif
diff --git a/bacnet-stack/include/bo.h b/bacnet-stack/include/bo.h
index 846ab657..4cb90c89 100644
--- a/bacnet-stack/include/bo.h
+++ b/bacnet-stack/include/bo.h
@@ -35,6 +35,8 @@
extern "C" {
#endif /* __cplusplus */
+ void Binary_Output_Init(void);
+
void Binary_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
diff --git a/bacnet-stack/include/device.h b/bacnet-stack/include/device.h
index f98a9702..6421dd6d 100644
--- a/bacnet-stack/include/device.h
+++ b/bacnet-stack/include/device.h
@@ -44,6 +44,9 @@
extern "C" {
#endif /* __cplusplus */
+
+ void Device_Init(void);
+
void Device_Property_Lists(
const int **pRequired,
const int **pOptional,
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/Makefile b/bacnet-stack/ports/bdk-atxx4-mstp/Makefile
index 65aac914..14e5cbeb 100644
--- a/bacnet-stack/ports/bdk-atxx4-mstp/Makefile
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/Makefile
@@ -50,6 +50,8 @@ CSRC = main.c \
dlmstp.c \
h_wp.c \
h_rp.c \
+ h_rpm.c \
+ h_rd.c \
device.c \
ai.c \
bi.c \
@@ -59,7 +61,6 @@ CSRC = main.c \
DEMOSRC = $(BACNET_DEMO)/handler/txbuf.c \
$(BACNET_DEMO)/handler/h_npdu.c \
$(BACNET_DEMO)/handler/h_whois.c \
- $(BACNET_DEMO)/handler/h_rd.c \
$(BACNET_DEMO)/handler/h_dcc.c \
$(BACNET_DEMO)/handler/s_iam.c \
$(BACNET_DEMO)/handler/noserv.c
@@ -67,6 +68,7 @@ DEMOSRC = $(BACNET_DEMO)/handler/txbuf.c \
# core BACnet stack files
CORESRC = \
$(BACNET_CORE)/fifo.c \
+ $(BACNET_CORE)/memcopy.c \
$(BACNET_CORE)/crc.c \
$(BACNET_CORE)/apdu.c \
$(BACNET_CORE)/npdu.c \
@@ -77,9 +79,10 @@ CORESRC = \
$(BACNET_CORE)/iam.c \
$(BACNET_CORE)/dcc.c \
$(BACNET_CORE)/rp.c \
+ $(BACNET_CORE)/rd.c \
+ $(BACNET_CORE)/rpm.c \
$(BACNET_CORE)/wp.c \
$(BACNET_CORE)/whois.c \
- $(BACNET_CORE)/rd.c \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/abort.c \
$(BACNET_CORE)/reject.c \
@@ -97,8 +100,6 @@ CORESRC = \
# $(BACNET_CORE)/cov.c \
# $(BACNET_CORE)/iam/iam_client.c \
# $(BACNET_CORE)/ihave.c \
-# $(BACNET_CORE)/rd.c \
-# $(BACNET_CORE)/rpm.c \
# $(BACNET_CORE)/timesync.c \
# $(BACNET_CORE)/whohas.c \
# $(BACNET_CORE)/filename.c \
@@ -129,7 +130,7 @@ DEFINES =
## Compile options common for all C compilation units.
BFLAGS = -DBACDL_MSTP
-BFLAGS += -DMAX_APDU=50
+BFLAGS += -DMAX_APDU=128
BFLAGS += -DBIG_ENDIAN=0
BFLAGS += -DMAX_TSM_TRANSACTIONS=0
#BFLAGS += -DCRC_USE_TABLE
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/ai.c b/bacnet-stack/ports/bdk-atxx4-mstp/ai.c
index ff329247..7d6deb22 100644
--- a/bacnet-stack/ports/bdk-atxx4-mstp/ai.c
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/ai.c
@@ -39,6 +39,43 @@
#error Modify the Analog_Input_Name to handle multiple digits
#endif
+/* These three arrays are used by the ReadPropertyMultiple handler */
+static const int Analog_Input_Properties_Required[] = {
+ PROP_OBJECT_IDENTIFIER,
+ PROP_OBJECT_NAME,
+ PROP_OBJECT_TYPE,
+ PROP_PRESENT_VALUE,
+ PROP_STATUS_FLAGS,
+ PROP_EVENT_STATE,
+ PROP_OUT_OF_SERVICE,
+ PROP_UNITS,
+ -1
+};
+
+static const int Analog_Input_Properties_Optional[] = {
+ PROP_DESCRIPTION,
+ -1
+};
+
+static const int Analog_Input_Properties_Proprietary[] = {
+ -1
+};
+
+void Analog_Input_Property_Lists(
+ const int **pRequired,
+ const int **pOptional,
+ const int **pProprietary)
+{
+ if (pRequired)
+ *pRequired = Analog_Input_Properties_Required;
+ if (pOptional)
+ *pOptional = Analog_Input_Properties_Optional;
+ if (pProprietary)
+ *pProprietary = Analog_Input_Properties_Proprietary;
+
+ return;
+}
+
static uint8_t Present_Value[MAX_ANALOG_INPUTS];
/* we simply have 0-n object instances. Yours might be */
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bacnet.aps b/bacnet-stack/ports/bdk-atxx4-mstp/bacnet.aps
index 4736fd42..396188fc 100644
--- a/bacnet-stack/ports/bdk-atxx4-mstp/bacnet.aps
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/bacnet.aps
@@ -1 +1 @@
-bacnet29-Apr-2009 08:16:5303-May-2009 15:12:17241029-Apr-2009 08:16:5344, 15, 0, 623AVR GCCD:\code\bacnet-stack\ports\bdk-atxx4-mstp\JTAGICE mkIIATmega644P.xmlfalseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31Auto000main.ctimer2.ceeprom.cinit.cinput.cled.crs485.cseeprom.cserial.cstack.cdlmstp.cbo.cbi.cai.cdevice.ch_rp.ch_wp.cMakefiledefaultYESMakefileatmega644p11
bacnet.elfdefault\1-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enumsdefault1C:\WinAVR-20090313\bin\avr-gcc.exeC:\WinAVR-20090313\utils\bin\make.exeD:\code\bacnet-stack\ports\bdk-atxx4-mstp\main.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\timer2.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\eeprom.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\init.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\input.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\led.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\rs485.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\seeprom.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\serial.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\stack.c00000main.c1
+bacnet29-Apr-2009 08:16:5311-May-2009 13:31:34241029-Apr-2009 08:16:5344, 15, 0, 623AVR GCCD:\code\bacnet-stack\ports\bdk-atxx4-mstp\JTAGICE mkIIATmega644P.xmlfalseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31Auto000main.ctimer2.ceeprom.cinit.cinput.cled.crs485.cseeprom.cserial.cstack.cdlmstp.cbo.cbi.cai.cdevice.ch_rp.ch_wp.ctimer.heeprom.hhardware.hiar2gcc.hinit.hinput.hled.hnvdata.hrs485.hseeprom.hserial.hMakefiledefaultYESMakefileatmega644p11
bacnet.elfdefault\1-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enumsdefault1C:\WinAVR-20090313\bin\avr-gcc.exeC:\WinAVR-20090313\utils\bin\make.exeD:\code\bacnet-stack\ports\bdk-atxx4-mstp\main.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\timer2.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\eeprom.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\init.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\input.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\led.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\rs485.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\seeprom.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\serial.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\stack.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\dlmstp.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\bo.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\bi.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\ai.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\device.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\h_rp.cD:\code\bacnet-stack\ports\bdk-atxx4-mstp\h_wp.c00000main.c1
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bi.c b/bacnet-stack/ports/bdk-atxx4-mstp/bi.c
index 65d4163c..37421245 100644
--- a/bacnet-stack/ports/bdk-atxx4-mstp/bi.c
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/bi.c
@@ -40,6 +40,46 @@
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
+/* These three arrays are used by the ReadPropertyMultiple handler */
+static const int Binary_Input_Properties_Required[] = {
+ PROP_OBJECT_IDENTIFIER,
+ PROP_OBJECT_NAME,
+ PROP_OBJECT_TYPE,
+ PROP_PRESENT_VALUE,
+ PROP_STATUS_FLAGS,
+ PROP_EVENT_STATE,
+ PROP_OUT_OF_SERVICE,
+ PROP_POLARITY,
+ -1
+};
+
+static const int Binary_Input_Properties_Optional[] = {
+ PROP_DESCRIPTION,
+ -1
+};
+
+static const int Binary_Input_Properties_Proprietary[] = {
+ -1
+};
+
+void Binary_Input_Property_Lists(
+ const int **pRequired,
+ const int **pOptional,
+ const int **pProprietary)
+{
+ if (pRequired) {
+ *pRequired = Binary_Input_Properties_Required;
+ }
+ if (pOptional) {
+ *pOptional = Binary_Input_Properties_Optional;
+ }
+ if (pProprietary) {
+ *pProprietary = Binary_Input_Properties_Proprietary;
+ }
+
+ return;
+}
+
static void Binary_Input_Initialize(
void)
{
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bits.h b/bacnet-stack/ports/bdk-atxx4-mstp/bits.h
deleted file mode 100644
index 2a9b62d2..00000000
--- a/bacnet-stack/ports/bdk-atxx4-mstp/bits.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*####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 BITS_H
-#define BITS_H
-
-/********************************************************************
-* Bit Masks
-*********************************************************************/
-#define BIT0 (0x01)
-#define BIT1 (0x02)
-#define BIT2 (0x04)
-#define BIT3 (0x08)
-#define BIT4 (0x10)
-#define BIT5 (0x20)
-#define BIT6 (0x40)
-#define BIT7 (0x80)
-#define BIT8 (0x0100)
-#define BIT9 (0x0200)
-#define BIT10 (0x0400)
-#define BIT11 (0x0800)
-#define BIT12 (0x1000)
-#define BIT13 (0x2000)
-#define BIT14 (0x4000)
-#define BIT15 (0x8000)
-#define BIT16 (0x010000UL)
-#define BIT17 (0x020000UL)
-#define BIT18 (0x040000UL)
-#define BIT19 (0x080000UL)
-#define BIT20 (0x100000UL)
-#define BIT21 (0x200000UL)
-#define BIT22 (0x400000UL)
-#define BIT23 (0x800000UL)
-#define BIT24 (0x01000000UL)
-#define BIT25 (0x02000000UL)
-#define BIT26 (0x04000000UL)
-#define BIT27 (0x08000000UL)
-#define BIT28 (0x10000000UL)
-#define BIT29 (0x20000000UL)
-#define BIT30 (0x40000000UL)
-#define BIT31 (0x80000000UL)
-
-/* a=register, b=bit number to act upon 0-n */
-#define BIT_SET(a,b) ((a) |= (1<<(b)))
-#define BIT_CLEAR(a,b) ((a) &= ~(1<<(b)))
-#define BIT_FLIP(a,b) ((a) ^= (1<<(b)))
-#define BIT_CHECK(a,b) ((a) & (1<<(b)))
-
-/* x=target variable, y=mask */
-#define BITMASK_SET(x,y) ((x) |= (y))
-#define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
-#define BITMASK_FLIP(x,y) ((x) ^= (y))
-#define BITMASK_CHECK(x,y) ((x) & (y))
-
-#ifndef _BV
-#define _BV(x) (1<<(x))
-#endif
-
-#endif
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bo.c b/bacnet-stack/ports/bdk-atxx4-mstp/bo.c
index 1c111dbd..5dd0d605 100644
--- a/bacnet-stack/ports/bdk-atxx4-mstp/bo.c
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/bo.c
@@ -33,8 +33,9 @@
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#include "wp.h"
+#include "led.h"
-#define MAX_BINARY_OUTPUTS 8
+#define MAX_BINARY_OUTPUTS 2
#if (MAX_BINARY_OUTPUTS > 9)
#error Modify the Binary_Output_Name to handle multiple digits
#endif
@@ -48,6 +49,8 @@ static BACNET_BINARY_PV
/* Writable out-of-service allows others to play with our Present Value */
/* without changing the physical output */
static bool Binary_Output_Out_Of_Service[MAX_BINARY_OUTPUTS];
+/* polarity - normal or inverse */
+static BACNET_POLARITY Polarity[MAX_BINARY_OUTPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Output_Properties_Required[] = {
@@ -167,6 +170,44 @@ static BACNET_BINARY_PV Binary_Output_Present_Value(
return value;
}
+static void Binary_Output_Sync(
+ uint32_t object_instance)
+{
+ BACNET_BINARY_PV pv = Binary_Output_Present_Value(object_instance);
+ unsigned index = Binary_Output_Instance_To_Index(object_instance);
+
+ if (index < MAX_BINARY_OUTPUTS) {
+ if (Binary_Output_Out_Of_Service[index]) {
+ return;
+ }
+ if (Polarity[index] == POLARITY_REVERSE) {
+ if (pv == BINARY_INACTIVE) {
+ pv = BINARY_ACTIVE;
+ } else if (pv == BINARY_ACTIVE) {
+ pv = BINARY_INACTIVE;
+ }
+ }
+ switch (index) {
+ case 0:
+ if (pv == BINARY_INACTIVE) {
+ led_off(LED_3);
+ } else if (pv == BINARY_ACTIVE) {
+ led_on(LED_3);
+ }
+ break;
+ case 1:
+ if (pv == BINARY_INACTIVE) {
+ led_off(LED_4);
+ } else if (pv == BINARY_ACTIVE) {
+ led_on(LED_4);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
/* note: the object name must be unique within this device */
char *Binary_Output_Name(
uint32_t object_instance)
@@ -195,7 +236,6 @@ int Binary_Output_Encode_Property_APDU(
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
- BACNET_POLARITY polarity = POLARITY_NORMAL;
unsigned object_index = 0;
unsigned i = 0;
bool state = false;
@@ -244,8 +284,8 @@ int Binary_Output_Encode_Property_APDU(
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_POLARITY:
- /* FIXME: figure out the polarity */
- apdu_len = encode_application_enumerated(&apdu[0], polarity);
+ apdu_len = encode_application_enumerated(&apdu[0],
+ Polarity[object_index]);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
@@ -336,7 +376,8 @@ bool Binary_Output_Write_Property(
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
- if (!Binary_Output_Valid_Instance(wp_data->object_instance)) {
+ object_index = Binary_Output_Instance_To_Index(wp_data->object_instance);
+ if (object_index >= MAX_BINARY_OUTPUTS) {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
@@ -358,16 +399,9 @@ bool Binary_Output_Write_Property(
(priority != 6 /* reserved */ ) &&
(value.type.Enumerated <= MAX_BINARY_PV)) {
level = (BACNET_BINARY_PV) value.type.Enumerated;
- object_index =
- Binary_Output_Instance_To_Index(wp_data->
- object_instance);
priority--;
Binary_Output_Level[object_index][priority] = level;
- /* Note: you could set the physical output here if we
- are the highest priority.
- However, if Out of Service is TRUE, then don't set the
- physical output. This comment may apply to the
- main loop (i.e. check out of service before changing output) */
+ Binary_Output_Sync(wp_data->object_instance);
status = true;
} else if (priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
@@ -381,18 +415,11 @@ bool Binary_Output_Write_Property(
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = BINARY_NULL;
- object_index =
- Binary_Output_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Output_Level[object_index][priority] = level;
- /* Note: you could set the physical output here to the next
- highest priority, or to the relinquish default if no
- priorities are set.
- However, if Out of Service is TRUE, then don't set the
- physical output. This comment may apply to the
- main loop (i.e. check out of service before changing output) */
+ Binary_Output_Sync(wp_data->object_instance);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
@@ -405,17 +432,30 @@ bool Binary_Output_Write_Property(
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
- object_index =
- Binary_Output_Instance_To_Index(wp_data->object_instance);
Binary_Output_Out_Of_Service[object_index] =
value.type.Boolean;
+ Binary_Output_Sync(wp_data->object_instance);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
- default:
+ case PROP_POLARITY:
+ if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
+ if (value.type.Enumerated <= MAX_POLARITY) {
+ Polarity[object_index] =
+ (BACNET_POLARITY)value.type.Enumerated;
+ } else {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ }
+ } else {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_INVALID_DATA_TYPE;
+ }
+ break;
+ default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/Makefile b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/Makefile
new file mode 100644
index 00000000..c0d49662
--- /dev/null
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/Makefile
@@ -0,0 +1,231 @@
+# Hey Emacs, this is a -*- makefile -*-
+
+# AVR-GCC Makefile template, derived from the WinAVR template (which
+# is public domain), believed to be neutral to any flavor of "make"
+# (GNU make, BSD make, SysV make)
+
+
+MCU = atmega644p
+FORMAT = ihex
+TARGET = bootloader
+SRC = main.c serial.c
+ASRC =
+OPT = s
+BASEADDR = 0xF800
+
+# Name of this Makefile (used for "make depend").
+MAKEFILE = Makefile
+
+# Debugging format.
+# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
+# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
+DEBUG = stabs
+
+# Compiler flag to set the C Standard level.
+# c89 - "ANSI" C
+# gnu89 - c89 plus GCC extensions
+# c99 - ISO C99 standard (not yet fully implemented)
+# gnu99 - c99 plus GCC extensions
+CSTANDARD = -std=gnu99
+
+# Place -D or -U options here
+CDEFS =
+#CDEFS += -DREMOVE_FLASH_BYTE_SUPPORT
+#CDEFS += -DREMOVE_EEPROM_BYTE_SUPPORT
+#CDEFS += -DREMOVE_FUSE_AND_LOCK_BIT_SUPPORT
+#CDEFS += -DREMOVE_AVRPROG_SUPPORT
+#CDEFS += -DREMOVE_BLOCK_SUPPORT
+
+# Place -I options here
+CINCS =
+
+
+CDEBUG = -g$(DEBUG)
+CWARN = -Wall -Wstrict-prototypes
+CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
+CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CSTANDARD) $(CTUNING) $(CEXTRA)
+
+
+#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
+
+
+#Additional libraries.
+
+# Minimalistic printf version
+PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
+
+# Floating point printf version (requires MATH_LIB = -lm below)
+PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
+
+PRINTF_LIB =
+
+# Minimalistic scanf version
+SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
+
+# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
+SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
+
+SCANF_LIB =
+
+MATH_LIB = -lm
+
+# External memory options
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# used for variables (.data/.bss) and heap (malloc()).
+#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# only used for heap (malloc()).
+#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
+
+EXTMEMOPTS =
+
+#LDMAP = $(LDFLAGS) -Wl,-Map=$(TARGET).map,--cref
+LDFLAGS = -Ttext=$(BASEADDR) $(EXTMEMOPTS) $(LDMAP) $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
+
+
+# Programming support using avrdude. Settings and variables.
+
+AVRDUDE_PROGRAMMER = stk500
+AVRDUDE_PORT = /dev/ttya
+
+AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
+#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
+
+
+# Uncomment the following if you want avrdude's erase cycle counter.
+# Note that this counter needs to be initialized first using -Yn,
+# see avrdude manual.
+#AVRDUDE_ERASE_COUNTER = -y
+
+# Uncomment the following if you do /not/ wish a verification to be
+# performed after programming the device.
+#AVRDUDE_NO_VERIFY = -V
+
+# Increase verbosity level. Please use this when submitting bug
+# reports about avrdude. See
+# to submit bug reports.
+#AVRDUDE_VERBOSE = -v -v
+
+AVRDUDE_BASIC = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
+AVRDUDE_FLAGS = $(AVRDUDE_BASIC) $(AVRDUDE_NO_VERIFY) $(AVRDUDE_VERBOSE) $(AVRDUDE_ERASE_COUNTER)
+
+
+CC = avr-gcc
+OBJCOPY = avr-objcopy
+OBJDUMP = avr-objdump
+SIZE = avr-size
+NM = avr-nm
+AVRDUDE = avrdude
+REMOVE = rm -f
+MV = mv -f
+
+# Define all object files.
+OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
+
+# Define all listing files.
+LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
+ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
+
+
+# Default target.
+all: build
+
+build: elf hex eep
+
+elf: $(TARGET).elf
+hex: $(TARGET).hex
+eep: $(TARGET).eep
+lss: $(TARGET).lss
+sym: $(TARGET).sym
+
+
+# Program the device.
+program: $(TARGET).hex $(TARGET).eep
+ $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
+
+
+
+
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
+COFFCONVERT=$(OBJCOPY) --debugging \
+--change-section-address .data-0x800000 \
+--change-section-address .bss-0x800000 \
+--change-section-address .noinit-0x800000 \
+--change-section-address .eeprom-0x810000
+
+
+coff: $(TARGET).elf
+ $(COFFCONVERT) -O coff-avr $(TARGET).elf $(TARGET).cof
+
+
+extcoff: $(TARGET).elf
+ $(COFFCONVERT) -O coff-ext-avr $(TARGET).elf $(TARGET).cof
+
+
+.SUFFIXES: .elf .hex .eep .lss .sym
+
+.elf.hex:
+ $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
+
+.elf.eep:
+ -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+ --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
+
+# Create extended listing file from ELF output file.
+.elf.lss:
+ $(OBJDUMP) -h -S $< > $@
+
+# Create a symbol table from ELF output file.
+.elf.sym:
+ $(NM) -n $< > $@
+
+
+
+# Link: create ELF output file from object files.
+$(TARGET).elf: $(OBJ)
+ $(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
+
+
+# Compile: create object files from C source files.
+.c.o:
+ $(CC) -c $(ALL_CFLAGS) $< -o $@
+
+
+# Compile: create assembler files from C source files.
+.c.s:
+ $(CC) -S $(ALL_CFLAGS) $< -o $@
+
+
+# Assemble: create object files from assembler source files.
+.S.o:
+ $(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+
+
+# Target: clean project.
+clean:
+ $(REMOVE) $(TARGET).hex $(TARGET).eep $(TARGET).cof $(TARGET).elf \
+ $(TARGET).map $(TARGET).sym $(TARGET).lss \
+ $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d)
+
+depend:
+ if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
+ then \
+ sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
+ $(MAKEFILE).$$$$ && \
+ $(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
+ fi
+ echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
+ >> $(MAKEFILE); \
+ $(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE)
+
+.PHONY: all build elf hex eep lss sym program coff extcoff clean depend
+
+
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/defines.h b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/defines.h
new file mode 100644
index 00000000..80ccaafd
--- /dev/null
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/defines.h
@@ -0,0 +1,46 @@
+/* definitions generated by preprocessor, copy into defines.h */
+#ifndef PPINC
+#define _ATMEGA644P // device select: _ATMEGAxxxx
+#define _B2048 // boot size select: _Bxxxx (words), powers of two only
+#ifdef __ICCAVR__
+#include "iom644.h"
+#endif
+#if __GNUC__
+#include
+#endif
+
+/* define pin for enter-self-prog-mode */
+#define PROGPORT PORTB
+#define PROGPIN PINB
+#define PROG_NO PB0
+
+/* baud rate register value calculation */
+#define CPU_FREQ 18430000
+#define BAUD_RATE 115200
+#define BRREG_VALUE 9
+
+/* definitions for UART control */
+#define BAUD_RATE_LOW_REG UBRR1
+#define UART_CONTROL_REG UCSR1B
+#define ENABLE_TRANSMITTER_BIT TXEN1
+#define ENABLE_RECEIVER_BIT RXEN1
+#define UART_STATUS_REG UCSR1A
+#define TRANSMIT_COMPLETE_BIT TXC1
+#define RECEIVE_COMPLETE_BIT RXC1
+#define UART_DATA_REG UDR1
+
+/* definitions for SPM control */
+#define SPMCR_REG SPMCSR
+#define PAGESIZE 256
+#define APP_END 61440
+//#define LARGE_MEMORY
+
+/* definitions for device recognition */
+#define PARTCODE 0
+#define SIGNATURE_BYTE_1 0x1E
+#define SIGNATURE_BYTE_2 0x96
+#define SIGNATURE_BYTE_3 0x0A
+
+/* indicate that preprocessor result is included */
+#define PPINC
+#endif
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/flash.h b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/flash.h
new file mode 100644
index 00000000..f3433b2c
--- /dev/null
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/flash.h
@@ -0,0 +1,74 @@
+/*****************************************************************************
+*
+* Atmel Corporation
+*
+* File : flash.h
+* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
+* Revision : $Revision: 1.7 $
+* Date : $Date: Tuesday, June 07, 200 $
+* Updated by : $Author: raapeland $
+*
+* Support mail : avr@atmel.com
+*
+* Target platform : All AVRs with bootloader support
+*
+* AppNote : AVR109 - Self-programming
+*
+* Description : Flash operations for AVR109 Self-programming
+****************************************************************************/
+
+#if defined(__ICCAVR__)
+
+/* IAR Embedded Workbench */
+# include
+
+# define _GET_LOCK_BITS() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0001, 0x09 )
+# define _GET_LOW_FUSES() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0000, 0x09 )
+# define _GET_HIGH_FUSES() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0003, 0x09 )
+# define _GET_EXTENDED_FUSES() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0002, 0x09 )
+# define _SET_LOCK_BITS(data) __DataToR0ByteToSPMCR_SPM( data, 0x09 )
+# define _ENABLE_RWW_SECTION() __DataToR0ByteToSPMCR_SPM( 0x00, 0x11 )
+
+# define _WAIT_FOR_SPM() while( SPMCR_REG & (1< 0
+
+/* AVR-GCC/avr-libc */
+# include
+# include
+
+# if defined(GET_LOCK_BITS) /* avr-libc >= 1.2.5 */
+# define _GET_LOCK_BITS() boot_lock_fuse_bits_get(GET_LOCK_BITS)
+# define _GET_LOW_FUSES() boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS)
+# define _GET_HIGH_FUSES() boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS)
+# define _GET_EXTENDED_FUSES() boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS)
+# endif /* defined(GET_LOCK_BITS) */
+# define _SET_LOCK_BITS(data) boot_lock_bits_set(~data)
+# define _ENABLE_RWW_SECTION() boot_rww_enable()
+
+# define _WAIT_FOR_SPM() boot_spm_busy_wait()
+
+# ifndef LARGE_MEMORY
+# define _LOAD_PROGRAM_MEMORY(addr) pgm_read_byte_near(addr)
+# else /* LARGE_MEMORY */
+# define _LOAD_PROGRAM_MEMORY(addr) pgm_read_byte_far(addr)
+# endif /* LARGE_MEMORY */
+# define _FILL_TEMP_WORD(addr,data) boot_page_fill(addr, data)
+# define _PAGE_ERASE(addr) boot_page_erase(addr)
+# define _PAGE_WRITE(addr) boot_page_write(addr)
+
+#else
+# error "Don't know your compiler."
+#endif
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/main.c b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/main.c
new file mode 100644
index 00000000..f247d973
--- /dev/null
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/main.c
@@ -0,0 +1,496 @@
+/*****************************************************************************
+*
+* Atmel Corporation
+*
+* File : main.c
+* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
+* Revision : $Revision: 1.7 $
+* Date : $Date: Tuesday, June 07, 200 $
+* Updated by : $Author: raapeland $
+*
+* Support mail : avr@atmel.com
+*
+* Target platform : All AVRs with bootloader support
+*
+* AppNote : AVR109 - Self-programming
+*
+* Description : This Program allows an AVR with bootloader capabilities to
+* Read/write its own Flash/EEprom. To enter Programming mode
+* an input pin is checked. If this pin is pulled low, programming mode
+* is entered. If not, normal execution is done from $0000
+* "reset" vector in Application area.
+*
+* Preparations : Use the preprocessor.xls file for obtaining a customized
+* defines.h file and linker-file code-segment definition for
+* the device you are compiling for.
+****************************************************************************/
+#include "defines.h"
+#include "serial.h"
+#include "flash.h"
+
+
+
+/* Uncomment the following to save code space */
+//#define REMOVE_AVRPROG_SUPPORT
+//#define REMOVE_FUSE_AND_LOCK_BIT_SUPPORT
+//#define REMOVE_BLOCK_SUPPORT
+//#define REMOVE_EEPROM_BYTE_SUPPORT
+//#define REMOVE_FLASH_BYTE_SUPPORT
+
+/*
+ * GCC doesn't optimize long int arithmetics very clever. As the
+ * address only needs to be larger than 16 bits for the ATmega128 and
+ * above (where flash consumptions isn't much of an issue as the
+ * entire boot loader will still fit even into the smallest possible
+ * boot loader section), save space by using a 16-bit variable for the
+ * smaller devices.
+ */
+#ifdef LARGE_MEMORY
+# define ADDR_T unsigned long
+#else /* !LARGE_MEMORY */
+# define ADDR_T unsigned int
+#endif /* LARGE_MEMORY */
+
+#ifndef REMOVE_BLOCK_SUPPORT
+unsigned char BlockLoad(unsigned int size, unsigned char mem, ADDR_T *address);
+void BlockRead(unsigned int size, unsigned char mem, ADDR_T *address);
+
+/* BLOCKSIZE should be chosen so that the following holds: BLOCKSIZE*n = PAGESIZE, where n=1,2,3... */
+#define BLOCKSIZE PAGESIZE
+
+#endif /* REMOVE_BLOCK_SUPPORT */
+
+#ifdef __ICCAVR__
+__C_task void main(void)
+#else /* ! __ICCAVR__ */
+int main(void)
+#endif /* __ICCAVR__ */
+
+{
+ ADDR_T address;
+ unsigned int temp_int;
+ unsigned char val;
+
+
+ /* Initialization */
+ void (*funcptr)( void ) = 0x0000; // Set up function pointer to RESET vector.
+ PROGPORT |= (1<>8) & 0xFF); // MSB first.
+ sendchar(BLOCKSIZE&0xFF); // Report BLOCKSIZE (bytes).
+ }
+
+
+ // Start block load.
+ else if(val=='B')
+ {
+ temp_int = (recchar()<<8) | recchar(); // Get block size.
+ val = recchar(); // Get memtype.
+ sendchar( BlockLoad(temp_int,val,&address) ); // Block load.
+ }
+
+
+ // Start block read.
+ else if(val=='g')
+ {
+ temp_int = (recchar()<<8) | recchar(); // Get block size.
+ val = recchar(); // Get memtype
+ BlockRead(temp_int,val,&address); // Block read
+ }
+#endif /* REMOVE_BLOCK_SUPPORT */
+
+#ifndef REMOVE_FLASH_BYTE_SUPPORT
+ // Read program memory.
+ else if(val=='R')
+ {
+ // Send high byte, then low byte of flash word.
+ _WAIT_FOR_SPM();
+ _ENABLE_RWW_SECTION();
+#ifdef __ICCAVR__
+#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
+#endif
+ sendchar( _LOAD_PROGRAM_MEMORY( (address << 1)+1 ) );
+ sendchar( _LOAD_PROGRAM_MEMORY( (address << 1)+0 ) );
+#ifdef __ICCAVR__
+#pragma diag_default=Pe1053 // Back to default.
+#endif
+
+ address++; // Auto-advance to next Flash word.
+ }
+
+
+ // Write program memory, low byte.
+ else if(val=='c')
+ { // NOTE: Always use this command before sending high byte.
+ temp_int=recchar(); // Get low byte for later _FILL_TEMP_WORD.
+ sendchar('\r'); // Send OK back.
+ }
+
+
+ // Write program memory, high byte.
+ else if(val=='C')
+ {
+ temp_int |= (recchar()<<8); // Get and insert high byte.
+ _WAIT_FOR_SPM();
+#ifdef __ICCAVR__
+#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
+#endif
+ _FILL_TEMP_WORD( (address << 1), temp_int ); // Convert word-address to byte-address and fill.
+#ifdef __ICCAVR__
+#pragma diag_default=Pe1053 // Back to default.
+#endif
+ address++; // Auto-advance to next Flash word.
+ sendchar('\r'); // Send OK back.
+ }
+
+
+ // Write page.
+ else if(val== 'm')
+ {
+ if( address >= (APP_END>>1) ) // Protect bootloader area.
+ {
+ sendchar('?');
+ } else
+ {
+ _WAIT_FOR_SPM();
+#ifdef __ICCAVR__
+#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
+#endif
+ _PAGE_WRITE( address << 1 ); // Convert word-address to byte-address and write.
+#ifdef __ICCAVR__
+#pragma diag_default=Pe1053 // Back to default.
+#endif
+ }
+
+ sendchar('\r'); // Send OK back.
+ }
+#endif /* REMOVE_FLASH_BYTE_SUPPORT */
+
+#ifndef REMOVE_EEPROM_BYTE_SUPPORT
+ // Write EEPROM memory.
+ else if (val == 'D')
+ {
+ _WAIT_FOR_SPM();
+ EEARL = address; // Setup EEPROM address.
+ EEARH = (address >> 8);
+ EEDR = recchar(); // Get byte.
+ EECR |= (1<> 8);
+ EECR |= (1< 0
+ sendchar( PARTCODE ); // Supports only this device, of course.
+#endif /* PARTCODE */
+ sendchar( 0 ); // Send list terminator.
+ }
+
+
+ // Set LED, clear LED and set device type.
+ else if((val=='x')||(val=='y')||(val=='T'))
+ {
+ recchar(); // Ignore the command and it's parameter.
+ sendchar('\r'); // Send OK back.
+ }
+#endif /* REMOVE_AVRPROG_SUPPORT */
+
+ // Return programmer identifier.
+ else if(val=='S')
+ {
+ sendchar('A'); // Return 'AVRBOOT'.
+ sendchar('V'); // Software identifier (aka programmer signature) is always 7 characters.
+ sendchar('R');
+ sendchar('B');
+ sendchar('O');
+ sendchar('O');
+ sendchar('T');
+ }
+
+
+ // Return software version.
+ else if(val=='V')
+ {
+ sendchar('1');
+ sendchar('5');
+ }
+
+
+ // Return signature bytes.
+ else if(val=='s')
+ {
+ sendchar( SIGNATURE_BYTE_3 );
+ sendchar( SIGNATURE_BYTE_2 );
+ sendchar( SIGNATURE_BYTE_1 );
+ }
+
+
+ // The last command to accept is ESC (synchronization).
+ else if(val!=0x1b) // If not ESC, then it is unrecognized...
+ {
+ sendchar('?');
+ }
+ } // end: for(;;)
+ }
+ else
+ {
+ _WAIT_FOR_SPM();
+ _ENABLE_RWW_SECTION();
+ funcptr(); // Jump to Reset vector 0x0000 in Application Section.
+ }
+} // end: main
+
+
+#ifndef REMOVE_BLOCK_SUPPORT
+unsigned char BlockLoad(unsigned int size, unsigned char mem, ADDR_T *address)
+{
+ unsigned char buffer[BLOCKSIZE];
+ unsigned int data;
+ ADDR_T tempaddress;
+
+ // EEPROM memory type.
+ if(mem=='E')
+ {
+ /* Fill buffer first, as EEPROM is too slow to copy with UART speed */
+ for(tempaddress=0;tempaddress> 8);
+ EEDR = buffer[tempaddress]; // Get byte.
+ EECR |= (1<>= 1; // Convert address back to Flash words again.
+ return '\r'; // Report programming OK
+ }
+
+ // Invalid memory type?
+ else
+ {
+ return '?';
+ }
+}
+
+
+void BlockRead(unsigned int size, unsigned char mem, ADDR_T *address)
+{
+ // EEPROM memory type.
+ if (mem=='E') // Read EEPROM
+ {
+ do
+ {
+ EEARL = *address; // Setup EEPROM address
+ EEARH = ((*address) >> 8);
+ (*address)++; // Select next EEPROM byte
+ EECR |= (1<>= 1; // Convert address back to Flash words again.
+ }
+}
+#endif /* REMOVE_BLOCK_SUPPORT */
+
+
+/* end of file */
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/parts.txt b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/parts.txt
new file mode 100644
index 00000000..b9d06010
--- /dev/null
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/parts.txt
@@ -0,0 +1,24 @@
+#Extracted from "Part definitions" of preprocessor.xls
+#dev include pagesz nrwwpag totpag avr910 sig1 sig2 sig3 baudlo uartc uarts txen rxen txc rxc udr spmcr
+ATmega8 iom8.h 32 32 128 0x77 0x1E 0x93 0x07 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
+ATmega8515 iom8515.h 32 32 128 0x3B 0x1E 0x93 0x06 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
+ATmega8535 iom8535.h 32 32 128 0x6A 0x1E 0x93 0x08 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
+ATmega88 iom88.h 32 32 128 0x1E 0x93 0x0A UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
+ATmega16 iom16.h 64 16 128 0x75 0x1E 0x94 0x03 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
+ATmega162 iom162.h 64 16 128 0x63 0x1E 0x94 0x04 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCR
+ATmega163 iom163.h 64 16 128 0x66 0x1E 0x94 0x02 UBRRLO UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
+ATmega165 iom165.h 64 16 128 0x1E 0x94 0x07 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
+ATmega168 iom168.h 64 16 128 0x1E 0x94 0x06 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
+ATmega169 iom169.h 64 16 128 0x79 0x1E 0x94 0x05 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
+ATmega32 iom32.h 64 32 256 0x7F 0x1E 0x95 0x02 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
+ATmega323 iom323.h 64 16 256 0x73 0x1E 0x95 0x01 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
+ATmega329 iom329.h 64 32 256 0x1E 0x95 0x03 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
+ATmega3290 iom3290.h 64 32 256 0x1E 0x95 0x04 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
+ATmega64 iom64.h 128 32 256 0x46 0x1E 0x96 0x02 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCR
+ATmega644 iom644.h 128 32 256 0x1E 0x96 0x09 UBRR0 UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
+ATmega644P iom644.h 128 32 256 0x1E 0x96 0x0A UBRR1 UCSR1B UCSR1A TXEN1 RXEN1 TXC1 RXC1 UDR1 SPMCSR
+ATmega649 iom649.h 128 32 256 0x1E 0x96 0x03 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
+ATmega6490 iom6490.h 128 32 256 0x1E 0x96 0x04 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
+ATmega128 iom128.h 128 32 512 0x44 0x1E 0x97 0x02 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
+ATmega128_1 iom128.h 128 32 512 0x44 0x1E 0x97 0x02 UBRR1L UCSR1B UCSR1A TXEN1 RXEN1 TXC1 RXC1 UDR1 SPMCSR
+
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/preprocessor.sh b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/preprocessor.sh
new file mode 100644
index 00000000..0a8db489
--- /dev/null
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/preprocessor.sh
@@ -0,0 +1,171 @@
+#! /bin/sh
+
+# Equivalent script to what preprocessor.xls might do.
+#
+# Run e.g. like
+# sh preprocessor.sh ATmega128 4096 PORTD PD4 3686400 9600 > defines.h
+#
+# Written by Joerg Wunsch, 2005-07-29
+
+PARTFILE=parts.txt
+
+usage()
+{
+ echo "usage: preprocessor.sh device bootsize progport prog_no cpu_freq baud_rate" >& 2
+ exit 1
+}
+
+if [ $# -ne 6 ]
+then
+ usage
+fi
+
+if [ ! -f ${PARTFILE} ]
+then
+ echo "part definition file ${PARTFILE} not found" >& 2
+ exit 1
+fi
+
+device="$1"
+bootsize="$2"
+progport="$3"
+prog_no="$4"
+cpu_freq="$5"
+baud_rate="$6"
+
+# is there a device at all?
+if grep -i "^${device} " ${PARTFILE} >/dev/null
+then
+ :
+else
+ echo "device ${device} not found in ${PARTFILE}" >& 2
+ exit 1
+fi
+devupper=`echo $device | tr '[a-z]' '[A-Z]'`
+
+# find an awk to use, out of nawk, gawk, or awk
+AWK=none
+for name in nawk gawk awk
+do
+ set -- `type $name 2>/dev/null`
+ if [ "x$2" = 'xis' ]
+ then
+ AWK=$name
+ break
+ fi
+done
+if [ $AWK = 'none' ]
+then
+ echo "Sorry, no useable awk found" >& 2
+ exit 1
+fi
+
+# OK, now get the individual fields. Unfortunately, the AVR910 device ID
+# is optional, and the shell cannot parse that natively. Use awk to
+# re-order the fields, and sort the avr910 column last (so we'll get an
+# empty variable in read if it is not present).
+set -- `grep -i "^${device} " ${PARTFILE} |\
+${AWK} -F ' ' \
+'{print $1 " " $2 " " $3 " " $4 " " $5 " " $7 " " $8 " " $9 " " $10 " " $11 " " $12 " " $13 " " $14 " " $15 " " $16 " " $17 " " $18 " " $6; exit}'`
+dev=$1
+include=$2
+pagesz=$3
+nrwwpag=$4
+totpag=$5
+sig1=$6
+sig2=$7
+sig3=$8
+baudlo=$9
+shift 9
+uartc=$1
+uarts=$2
+txen=$3
+rxen=$4
+txc=$5
+rxc=$6
+udr=$7
+spmcr=$8
+avr910=$9
+
+# Verify boot size
+pagebytes=`expr $pagesz \* 2`
+maxboot=`expr $nrwwpag \* $pagebytes`
+bootbytes=`expr 2 \* $bootsize` || exit 1
+if [ \( $bootbytes -ne $maxboot \) -a \
+ \( $bootbytes -ne `expr $maxboot / 4` \) -a \
+ \( $bootbytes -ne `expr $maxboot / 2` \) -a \
+ \( $bootbytes -ne `expr $maxboot \* 3 / 4` \) ]
+then
+ echo "Invalid boot size ${bootsize}, valid: `expr $maxboot / 8`, `expr $maxboot / 4`, `expr $maxboot \* 3 / 8`, `expr $maxboot / 2` words" >& 2
+ exit 1
+fi
+
+if p=`expr $progport : 'PORT\(.\)'`
+then
+ : # ok
+else
+ echo "Invalid port name ${progport}, must be PORTx" >& 2
+ exit 1
+fi
+progpin="PIN$p"
+
+brreg=`expr $cpu_freq / \( 16 \* $baud_rate \) - 1` || exit 1
+memsize=`expr $totpag \* $pagebytes`
+append=`expr $memsize - $bootbytes`
+
+echo "/* definitions generated by preprocessor, copy into defines.h */
+#ifndef PPINC
+#define _${devupper} // device select: _ATMEGAxxxx
+#define _B${bootsize} // boot size select: _Bxxxx (words), powers of two only
+#ifdef __ICCAVR__
+#include \"${include}\"
+#endif
+#if __GNUC__
+#include
+#endif
+
+/* define pin for enter-self-prog-mode */
+#define PROGPORT ${progport}
+#define PROGPIN ${progpin}
+#define PROG_NO ${prog_no}
+
+/* baud rate register value calculation */
+#define CPU_FREQ ${cpu_freq}
+#define BAUD_RATE ${baud_rate}
+#define BRREG_VALUE ${brreg}
+
+/* definitions for UART control */
+#define BAUD_RATE_LOW_REG ${baudlo}
+#define UART_CONTROL_REG ${uartc}
+#define ENABLE_TRANSMITTER_BIT ${txen}
+#define ENABLE_RECEIVER_BIT ${rxen}
+#define UART_STATUS_REG ${uarts}
+#define TRANSMIT_COMPLETE_BIT ${txc}
+#define RECEIVE_COMPLETE_BIT ${rxc}
+#define UART_DATA_REG ${udr}
+
+/* definitions for SPM control */
+#define SPMCR_REG ${spmcr}
+#define PAGESIZE ${pagebytes}
+#define APP_END ${append}"
+
+if [ $memsize -gt 65536 ]
+then
+ echo "#define LARGE_MEMORY"
+else
+ echo "//#define LARGE_MEMORY"
+fi
+
+echo "
+/* definitions for device recognition */
+#define PARTCODE ${avr910}
+#define SIGNATURE_BYTE_1 ${sig1}
+#define SIGNATURE_BYTE_2 ${sig2}
+#define SIGNATURE_BYTE_3 ${sig3}
+
+/* indicate that preprocessor result is included */
+#define PPINC
+#endif"
+
+echo "(IAR) Replace all code segment definitions in the linker file with the following line:" >& 2
+${AWK} 'BEGIN {printf "-Z(CODE)INTVEC,FAR_F,SWITCH,CODE=%X-%X\n", '$append', '$memsize' - 1; exit}' >& 2
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/preprocessor.xls b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/preprocessor.xls
new file mode 100644
index 00000000..5bed7ef3
Binary files /dev/null and b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/preprocessor.xls differ
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/serial.c b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/serial.c
new file mode 100644
index 00000000..59b0c8b3
--- /dev/null
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/serial.c
@@ -0,0 +1,42 @@
+/*****************************************************************************
+*
+* Atmel Corporation
+*
+* File : serial.c
+* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
+* Revision : $Revision: 1.7 $
+* Date : $Date: Tuesday, June 07, 200 $
+* Updated by : $Author: raapeland $
+*
+* Support mail : avr@atmel.com
+*
+* Target platform : All AVRs with bootloader support
+*
+* AppNote : AVR109 - Self-programming
+*
+* Description : UART communication routines
+****************************************************************************/
+#include "defines.h"
+
+
+void initbootuart(void)
+{
+ BAUD_RATE_LOW_REG = BRREG_VALUE;
+ UART_CONTROL_REG = (1 << ENABLE_RECEIVER_BIT) |
+ (1 << ENABLE_TRANSMITTER_BIT); // enable receive and transmit
+}
+
+
+void sendchar(unsigned char c)
+{
+ UART_DATA_REG = c; // prepare transmission
+ while (!(UART_STATUS_REG & (1 << TRANSMIT_COMPLETE_BIT)));// wait until byte sendt
+ UART_STATUS_REG |= (1 << TRANSMIT_COMPLETE_BIT); // delete TXCflag
+}
+
+
+unsigned char recchar(void)
+{
+ while(!(UART_STATUS_REG & (1 << RECEIVE_COMPLETE_BIT))); // wait for data
+ return UART_DATA_REG;
+}
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/serial.h b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/serial.h
new file mode 100644
index 00000000..c7a78aa7
--- /dev/null
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/bootloader/serial.h
@@ -0,0 +1,22 @@
+/*****************************************************************************
+*
+* Atmel Corporation
+*
+* File : serial.h
+* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
+* Revision : $Revision: 1.7 $
+* Date : $Date: Tuesday, June 07, 200 $
+* Updated by : $Author: raapeland $
+*
+* Support mail : avr@atmel.com
+*
+* Target platform : All AVRs with bootloader support
+*
+* AppNote : AVR109 - Self-programming
+*
+* Description : Header file for serial.c
+****************************************************************************/
+
+void initbootuart( void );
+void sendchar( unsigned char );
+unsigned char recchar( void );
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/device.c b/bacnet-stack/ports/bdk-atxx4-mstp/device.c
index 9187421b..0a4e45b7 100644
--- a/bacnet-stack/ports/bdk-atxx4-mstp/device.c
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/device.c
@@ -34,6 +34,7 @@
#include "datalink.h"
#include "rs485.h"
#include "version.h"
+#include "nvdata.h"
/* objects */
#include "device.h"
#include "ai.h"
@@ -44,13 +45,69 @@
properties that are writable or that may change.
The properties that are constant can be hard coded
into the read-property encoding. */
-static uint32_t Object_Instance_Number = BACNET_MAX_INSTANCE;
-static char Object_Name[32] = "bdk-atxx4-mstp";
+static uint32_t Object_Instance_Number;
+static uint8_t Object_Name[NV_EEPROM_DEVICE_NAME_SIZE];
+static uint8_t Object_Name_Encoding;
+static uint8_t Object_Name_Length;
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
-BACNET_REINITIALIZED_STATE_OF_DEVICE Reinitialize_State =
+static BACNET_REINITIALIZED_STATE_OF_DEVICE Reinitialize_State =
REINITIALIZED_STATE_IDLE;
+
+/* These three arrays are used by the ReadPropertyMultiple handler */
+static const int Device_Properties_Required[] = {
+ PROP_OBJECT_IDENTIFIER,
+ PROP_OBJECT_NAME,
+ PROP_OBJECT_TYPE,
+ PROP_SYSTEM_STATUS,
+ PROP_VENDOR_NAME,
+ PROP_VENDOR_IDENTIFIER,
+ PROP_MODEL_NAME,
+ PROP_FIRMWARE_REVISION,
+ PROP_APPLICATION_SOFTWARE_VERSION,
+ PROP_PROTOCOL_VERSION,
+ PROP_PROTOCOL_REVISION,
+ PROP_PROTOCOL_SERVICES_SUPPORTED,
+ PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED,
+ PROP_OBJECT_LIST,
+ PROP_MAX_APDU_LENGTH_ACCEPTED,
+ PROP_SEGMENTATION_SUPPORTED,
+ PROP_APDU_TIMEOUT,
+ PROP_NUMBER_OF_APDU_RETRIES,
+#if defined(BACDL_MSTP)
+ PROP_MAX_MASTER,
+ PROP_MAX_INFO_FRAMES,
+#endif
+ PROP_DEVICE_ADDRESS_BINDING,
+ PROP_DATABASE_REVISION,
+ -1
+};
+static const int Device_Properties_Optional[] = {
+ PROP_DESCRIPTION,
+ PROP_PROTOCOL_CONFORMANCE_CLASS,
+ -1
+};
+
+static const int Device_Properties_Proprietary[] = {
+ -1
+};
+
+void Device_Property_Lists(
+ const int **pRequired,
+ const int **pOptional,
+ const int **pProprietary)
+{
+ if (pRequired)
+ *pRequired = Device_Properties_Required;
+ if (pOptional)
+ *pOptional = Device_Properties_Optional;
+ if (pProprietary)
+ *pProprietary = Device_Properties_Proprietary;
+
+ return;
+}
+
void Device_Reinit(
void)
{
@@ -63,11 +120,43 @@ void Device_Init(
{
Reinitialize_State = REINITIALIZED_STATE_IDLE;
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
- /* FIXME: Get the data from the eeprom */
- /* I2C_Read_Block(EEPROM_DEVICE_ADDRESS,
- (char *)&Object_Instance_Number,
- sizeof(Object_Instance_Number),
- EEPROM_BACNET_ID_ADDR); */
+ /* Get the data from the eeprom */
+ eeprom_bytes_read(
+ NV_EEPROM_DEVICE_0,
+ (uint8_t *)&Object_Instance_Number,
+ sizeof(Object_Instance_Number));
+ if (Object_Instance_Number >= BACNET_MAX_INSTANCE) {
+ Object_Instance_Number = 0;
+ eeprom_bytes_write(
+ NV_EEPROM_DEVICE_0,
+ (uint8_t *)&Object_Instance_Number,
+ sizeof(Object_Instance_Number));
+ }
+ eeprom_bytes_read(
+ NV_EEPROM_DEVICE_NAME_ENCODING,
+ &Object_Name_Encoding,
+ 1);
+ eeprom_bytes_read(
+ NV_EEPROM_DEVICE_NAME_LENGTH,
+ &Object_Name_Length,
+ 1);
+ eeprom_bytes_read(
+ NV_EEPROM_DEVICE_NAME_0,
+ (uint8_t *)&Object_Name[0],
+ NV_EEPROM_DEVICE_NAME_SIZE);
+ if ((Object_Name_Encoding >= MAX_CHARACTER_STRING_ENCODING) ||
+ (Object_Name_Length > NV_EEPROM_DEVICE_NAME_SIZE)) {
+ Object_Name_Encoding = CHARACTER_ANSI_X34;
+ Object_Name_Length = 0;
+ eeprom_bytes_write(
+ NV_EEPROM_DEVICE_NAME_ENCODING,
+ &Object_Name_Encoding,
+ 1);
+ eeprom_bytes_write(
+ NV_EEPROM_DEVICE_NAME_LENGTH,
+ &Object_Name_Length,
+ 1);
+ }
}
/* methods to manipulate the data */
@@ -84,12 +173,10 @@ bool Device_Set_Object_Instance_Number(
if (object_id <= BACNET_MAX_INSTANCE) {
Object_Instance_Number = object_id;
- /* FIXME: Write the data to the eeprom */
- /* I2C_Write_Block(
- EEPROM_DEVICE_ADDRESS,
- (char *)&Object_Instance_Number,
- sizeof(Object_Instance_Number),
- EEPROM_BACNET_ID_ADDR); */
+ eeprom_bytes_write(
+ NV_EEPROM_DEVICE_0,
+ (uint8_t *)&Object_Instance_Number,
+ sizeof(Object_Instance_Number));
} else
status = false;
@@ -237,8 +324,6 @@ int Device_Encode_Property_APDU(
int object_type = 0;
uint32_t instance = 0;
unsigned count = 0;
- BACNET_TIME local_time;
- BACNET_DATE local_date;
/* FIXME: change the hardcoded names to suit your application */
switch (property) {
@@ -248,7 +333,10 @@ int Device_Encode_Property_APDU(
Object_Instance_Number);
break;
case PROP_OBJECT_NAME:
- characterstring_init_ansi(&char_string, Object_Name);
+ characterstring_init(&char_string,
+ Object_Name_Encoding,
+ (char *)&Object_Name[0],
+ Object_Name_Length);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -256,7 +344,7 @@ int Device_Encode_Property_APDU(
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
break;
case PROP_DESCRIPTION:
- characterstring_init_ansi(&char_string, "BACnet Demo");
+ characterstring_init_ansi(&char_string, "BACnet Development Kit");
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -276,7 +364,7 @@ int Device_Encode_Property_APDU(
Device_Vendor_Identifier());
break;
case PROP_MODEL_NAME:
- characterstring_init_ansi(&char_string, "GNU Demo");
+ characterstring_init_ansi(&char_string, "bdk-atxx4-mstp");
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -290,11 +378,6 @@ int Device_Encode_Property_APDU(
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
- case PROP_LOCATION:
- characterstring_init_ansi(&char_string, "USA");
- apdu_len =
- encode_application_character_string(&apdu[0], &char_string);
- break;
case PROP_PROTOCOL_VERSION:
apdu_len =
encode_application_unsigned(&apdu[0],
@@ -330,10 +413,9 @@ int Device_Encode_Property_APDU(
}
/* FIXME: indicate the objects that YOU support */
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
- bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
- bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
+ bitstring_set_bit(&bit_string, OBJECT_BINARY_OUTPUT, true);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_OBJECT_LIST:
@@ -413,30 +495,6 @@ int Device_Encode_Property_APDU(
apdu_len =
encode_application_unsigned(&apdu[0], dlmstp_max_master());
break;
- case PROP_LOCAL_TIME:
- /* FIXME: if you support time */
- local_time.hour = 0;
- local_time.min = 0;
- local_time.sec = 0;
- local_time.hundredths = 0;
- apdu_len = encode_application_time(&apdu[0], &local_time);
- break;
- case PROP_UTC_OFFSET:
- /* Note: BACnet Time Zone is inverse of everybody else */
- apdu_len = encode_application_signed(&apdu[0], 5 /* EST */ );
- break;
- case PROP_LOCAL_DATE:
- /* FIXME: if you support date */
- local_date.year = 2006; /* AD */
- local_date.month = 4; /* Jan=1..Dec=12 */
- local_date.day = 11; /* 1..31 */
- local_date.wday = 0; /* 1=Mon..7=Sun */
- apdu_len = encode_application_date(&apdu[0], &local_date);
- break;
- case PROP_DAYLIGHT_SAVINGS_STATUS:
- /* FIXME: if you support time/date */
- apdu_len = encode_application_boolean(&apdu[0], false);
- break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
@@ -515,27 +573,55 @@ bool Device_Write_Property(
break;
case PROP_OBJECT_NAME:
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
- uint8_t encoding;
- size_t len;
-
- encoding =
- characterstring_encoding(&value.type.Character_String);
- len = characterstring_length(&value.type.Character_String);
- if (encoding == CHARACTER_ANSI_X34) {
- if (len <= 20) {
- /* FIXME: set the name */
- /* Display_Set_Name(
- characterstring_value(&value.type.Character_String)); */
- /* FIXME: All the object names in a device must be unique.
- Disallow setting the Device Object Name to any objects in
- the device. */
- } else {
+ size_t length =
+ characterstring_length(&value.type.Character_String);
+ if (length < NV_EEPROM_DEVICE_NAME_SIZE) {
+ uint8_t encoding =
+ characterstring_encoding(&value.type.Character_String);
+ if (encoding < MAX_CHARACTER_STRING_ENCODING) {
+ uint8_t i;
+ char *pCharString;
+ Object_Name_Encoding = encoding;
+ Object_Name_Length = length;
+ eeprom_bytes_write(
+ NV_EEPROM_DEVICE_NAME_ENCODING,
+ &Object_Name_Encoding,
+ 1);
+ eeprom_bytes_write(
+ NV_EEPROM_DEVICE_NAME_LENGTH,
+ &Object_Name_Length,
+ 1);
+ pCharString =
+ characterstring_value(&value.type.Character_String);
+ for (i = 0; i < Object_Name_Length; i++) {
+ Object_Name[i] = pCharString[i];
+ }
+ eeprom_bytes_write(
+ NV_EEPROM_DEVICE_NAME_0,
+ (uint8_t *)&Object_Name[0],
+ length);
+ status = true;
+ } else {
*error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
+ *error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
- *error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
+ *error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
+ }
+ } else {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_INVALID_DATA_TYPE;
+ }
+ break;
+ case 9600:
+ if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
+ if ((value.type.Unsigned_Int > 115200) &&
+ (rs485_baud_rate_set(value.type.Unsigned_Int))) {
+ status = true;
+ } else {
+ *error_class = ERROR_CLASS_PROPERTY;
+ *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c b/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c
index cd17ced0..62af6916 100644
--- a/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c
@@ -157,13 +157,13 @@ static uint8_t This_Station;
/* 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. */
-static uint8_t Nmax_info_frames;
+static uint8_t Nmax_info_frames = 1;
/* 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. */
-static uint8_t Nmax_master;
+static uint8_t Nmax_master = 127;
/* An array of octets, used to store octets for transmitting */
/* OutputBuffer is indexed from 0 to OutputBufferSize-1. */
/* The MAX_PDU size of a frame is MAX_APDU + MAX_NPDU octets. */
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/h_rd.c b/bacnet-stack/ports/bdk-atxx4-mstp/h_rd.c
new file mode 100644
index 00000000..b26d3edc
--- /dev/null
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/h_rd.c
@@ -0,0 +1,113 @@
+/**************************************************************************
+*
+* Copyright (C) 2009 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
+#include "config.h"
+#include "txbuf.h"
+#include "bacdef.h"
+#include "bacdcode.h"
+#include "bacerror.h"
+#include "apdu.h"
+#include "npdu.h"
+#include "abort.h"
+#include "reject.h"
+#include "rd.h"
+
+static char *Password = "rehmite";
+static BACNET_CHARACTER_STRING My_Password;
+
+void handler_reinitialize_device(
+ uint8_t * service_request,
+ uint16_t service_len,
+ BACNET_ADDRESS * src,
+ BACNET_CONFIRMED_SERVICE_DATA * service_data)
+{
+ BACNET_REINITIALIZED_STATE state;
+ BACNET_CHARACTER_STRING their_password;
+ int len = 0;
+ int pdu_len = 0;
+ BACNET_NPDU_DATA npdu_data;
+ int bytes_sent = 0;
+ BACNET_ADDRESS my_address;
+
+ /* encode the NPDU portion of the packet */
+ datalink_get_my_address(&my_address);
+ npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
+ pdu_len =
+ npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
+ &npdu_data);
+ if (service_data->segmented_message) {
+ len =
+ abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
+ service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
+ true);
+ goto RD_ABORT;
+ }
+ /* decode the service request only */
+ len =
+ rd_decode_service_request(service_request, service_len, &state,
+ &their_password);
+ /* bad decoding or something we didn't understand - send an abort */
+ if (len < 0) {
+ len =
+ abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
+ service_data->invoke_id, ABORT_REASON_OTHER, true);
+ goto RD_ABORT;
+ }
+ /* check the data from the request */
+ if (state >= MAX_BACNET_REINITIALIZED_STATE) {
+ len =
+ reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
+ service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION);
+ } else {
+ characterstring_init_ansi(&My_Password, Password);
+ if (characterstring_same(&their_password, &My_Password)) {
+ len =
+ encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
+ service_data->invoke_id,
+ SERVICE_CONFIRMED_REINITIALIZE_DEVICE);
+ /* FIXME: now you can reboot, restart, quit, or something clever */
+ /* Note: you can use a mix of state and password to do specific stuff */
+ /* Note: if you don't do something clever like actually restart,
+ you probably should clear any DCC status and timeouts */
+ /* Note: you probably need to send the reply BEFORE restarting */
+ } else {
+ len =
+ bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
+ service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
+ ERROR_CLASS_SERVICES, ERROR_CODE_PASSWORD_FAILURE);
+ }
+ }
+RD_ABORT:
+ pdu_len += len;
+ bytes_sent =
+ datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
+ pdu_len);
+
+ return;
+}
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/hardware.ods b/bacnet-stack/ports/bdk-atxx4-mstp/hardware.ods
index 9b971244..3e2ab070 100644
Binary files a/bacnet-stack/ports/bdk-atxx4-mstp/hardware.ods and b/bacnet-stack/ports/bdk-atxx4-mstp/hardware.ods differ
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/input.c b/bacnet-stack/ports/bdk-atxx4-mstp/input.c
index 52173fc5..6c401668 100644
--- a/bacnet-stack/ports/bdk-atxx4-mstp/input.c
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/input.c
@@ -38,11 +38,6 @@ void input_task(
} else {
if (old_value != Address_Switch) {
Address_Switch = old_value;
-#if defined(BACDL_MSTP)
-// dlmstp_set_mac_address(Address_Switch);
-#endif
-// Device_Set_Object_Instance_Number(86000 + Address_Switch);
-// Send_I_Am_Flag = true;
}
}
}
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/main.c b/bacnet-stack/ports/bdk-atxx4-mstp/main.c
index dac96e61..dca4fc5f 100644
--- a/bacnet-stack/ports/bdk-atxx4-mstp/main.c
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/main.c
@@ -1,4 +1,4 @@
-/**************************************************************************
+/************************************************************************
*
* Copyright (C) 2009 Steve Karg
*
@@ -21,7 +21,7 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
-*********************************************************************/
+*************************************************************************/
#include
#include
@@ -54,25 +54,72 @@ static uint8_t MSTP_MAC_Address;
/* For porting to IAR, see:
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
+#if defined(__GNUC__)
+/* AVR fuse settings */
+FUSES =
+{
+ /* External Ceramic Resonator - configuration */
+ /* Full Swing Crystal Oscillator Clock Selection */
+ /* Ceramic resonator, slowly rising power 1K CK 14CK + 65 ms */
+ /* note: fuses are enabled by clearing the bit, so
+ any fuses listed below are cleared fuses. */
+ .low = (FUSE_CKSEL3 &
+ FUSE_SUT0 &
+ FUSE_SUT1),
+
+ /* FIXME: bootrst */
+ /* BOOTSZ configuration:
+ BOOTSZ1 BOOTSZ0 Boot Size
+ ------- ------- ---------
+ 1 1 512
+ 1 0 1024
+ 0 1 2048
+ 0 0 4096
+ */
+ /* note: fuses are enabled by clearing the bit, so
+ any fuses listed below are cleared fuses. */
+ .high = (
+ FUSE_BOOTSZ1 &
+ FUSE_BOOTRST &
+ FUSE_EESAVE &
+ FUSE_SPIEN &
+ FUSE_JTAGEN),
+
+ /* Brown-out detection VCC=2.7V */
+ /* BODLEVEL configuration
+ BODLEVEL2 BODLEVEL1 BODLEVEL0 Voltage
+ --------- --------- --------- --------
+ 1 1 1 disabled
+ 1 1 0 1.8V
+ 1 0 1 2.7V
+ 1 0 0 4.3V
+ */
+ /* note: fuses are enabled by clearing the bit, so
+ any fuses listed below are cleared fuses. */
+ .extended = (FUSE_BODLEVEL1 & FUSE_BODLEVEL0),
+};
+/* AVR lock bits - unlocked */
+LOCKBITS = LOCKBITS_DEFAULT;
+#endif
+
static void bacnet_init(
void)
{
-#if defined(BACDL_MSTP)
MSTP_MAC_Address = input_address();
- /* configure the BACnet Datalink */
- rs485_baud_rate_set(9600);
- dlmstp_set_max_master(127);
- dlmstp_set_max_info_frames(1);
dlmstp_set_mac_address(MSTP_MAC_Address);
dlmstp_init(NULL);
-#endif
- Device_Set_Object_Instance_Number(4194303);
+ /* initialize objects */
+ Device_Init();
+ Binary_Output_Init();
+
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* Set the handlers for any confirmed services that we support. */
/* 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_READ_PROP_MULTIPLE,
+ handler_read_property_multiple);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
handler_reinitialize_device);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
@@ -94,6 +141,7 @@ static void bacnet_task(void)
mstp_mac_address = input_address();
if (MSTP_MAC_Address != mstp_mac_address) {
MSTP_MAC_Address = mstp_mac_address;
+ dlmstp_set_mac_address(MSTP_MAC_Address);
Send_I_Am(&Handler_Transmit_Buffer[0]);
}
if (timer_elapsed_seconds(TIMER_DCC, 1)) {
@@ -113,6 +161,8 @@ void idle_init(void)
void idle_task(void)
{
+#if 0
+ /* blink the leds */
if (timer_elapsed_seconds(TIMER_LED_3, 1)) {
timer_reset(TIMER_LED_3);
led_toggle(LED_3);
@@ -121,6 +171,7 @@ void idle_task(void)
timer_reset(TIMER_LED_4);
led_toggle(LED_4);
}
+#endif
}
int main(
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/nvdata.h b/bacnet-stack/ports/bdk-atxx4-mstp/nvdata.h
new file mode 100644
index 00000000..1cfdbccd
--- /dev/null
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/nvdata.h
@@ -0,0 +1,104 @@
+/************************************************************************
+*
+* Copyright (C) 2009 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.
+*
+*************************************************************************/
+#ifndef NVDATA_H
+#define NVDATA_H
+
+#include "seeprom.h"
+#include "eeprom.h"
+
+/* data version - use to check valid version */
+#define SEEPROM_ID 0xBAC0
+#define SEEPROM_VERSION 0x0001
+
+#define SEEPROM_BYTES_MAX (2*1024)
+
+/* list of SEEPROM addresses */
+/* note to developers: define each byte,
+ even if they are not used explicitly */
+#define NV_SEEPROM_TYPE_0 0
+#define NV_SEEPROM_TYPE_1 1
+#define NV_SEEPROM_VERSION_0 2
+#define NV_SEEPROM_VERSION_1 3
+/* --- */
+/* define the MAC, BAUD, MAX Master, Device Instance internal
+ so that bootloader *could* use them. */
+/* note: MAC could come from DIP switch, or be in non-volatile memory */
+#define NV_EEPROM_MAC 0
+/* 9=9.6k, 19=19.2k, 38=38.4k, 57=57.6k, 76=76.8k, 115=115.2k */
+#define NV_EEPROM_BAUD_K 1
+#define NV_EEPROM_MAX_MASTER 2
+/* device instance is only 22 bits - easier if we use 32 bits */
+#define NV_EEPROM_DEVICE_0 3
+#define NV_EEPROM_DEVICE_1 4
+#define NV_EEPROM_DEVICE_2 5
+#define NV_EEPROM_DEVICE_3 6
+/* Device Name */
+#define NV_EEPROM_DEVICE_NAME_LENGTH 8
+#define NV_EEPROM_DEVICE_NAME_ENCODING 9
+#define NV_EEPROM_DEVICE_NAME_0 10
+#define NV_EEPROM_DEVICE_NAME_1 11
+#define NV_EEPROM_DEVICE_NAME_2 12
+#define NV_EEPROM_DEVICE_NAME_3 13
+#define NV_EEPROM_DEVICE_NAME_4 14
+#define NV_EEPROM_DEVICE_NAME_5 15
+#define NV_EEPROM_DEVICE_NAME_6 16
+#define NV_EEPROM_DEVICE_NAME_7 17
+#define NV_EEPROM_DEVICE_NAME_8 18
+#define NV_EEPROM_DEVICE_NAME_9 19
+#define NV_EEPROM_DEVICE_NAME_10 20
+#define NV_EEPROM_DEVICE_NAME_11 21
+#define NV_EEPROM_DEVICE_NAME_12 22
+#define NV_EEPROM_DEVICE_NAME_13 23
+#define NV_EEPROM_DEVICE_NAME_14 24
+#define NV_EEPROM_DEVICE_NAME_15 25
+#define NV_EEPROM_DEVICE_NAME_16 26
+#define NV_EEPROM_DEVICE_NAME_17 27
+#define NV_EEPROM_DEVICE_NAME_18 28
+#define NV_EEPROM_DEVICE_NAME_19 29
+#define NV_EEPROM_DEVICE_NAME_20 30
+#define NV_EEPROM_DEVICE_NAME_21 31
+#define NV_EEPROM_DEVICE_NAME_22 32
+#define NV_EEPROM_DEVICE_NAME_23 33
+#define NV_EEPROM_DEVICE_NAME_24 34
+#define NV_EEPROM_DEVICE_NAME_25 35
+#define NV_EEPROM_DEVICE_NAME_26 36
+#define NV_EEPROM_DEVICE_NAME_27 37
+#define NV_EEPROM_DEVICE_NAME_28 38
+#define NV_EEPROM_DEVICE_NAME_29 39
+#define NV_EEPROM_DEVICE_NAME_30 40
+#define NV_EEPROM_DEVICE_NAME_31 41
+#define NV_EEPROM_DEVICE_NAME_SIZE 32
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/rs485.c b/bacnet-stack/ports/bdk-atxx4-mstp/rs485.c
index c16ce208..7fadea85 100644
--- a/bacnet-stack/ports/bdk-atxx4-mstp/rs485.c
+++ b/bacnet-stack/ports/bdk-atxx4-mstp/rs485.c
@@ -28,6 +28,7 @@
#include "fifo.h"
#include "timer.h"
#include "led.h"
+#include "nvdata.h"
/* baud rate */
static uint32_t Baud_Rate = 9600;
@@ -152,10 +153,19 @@ uint32_t rs485_baud_rate(
return Baud_Rate;
}
+static void rs485_baud_rate_configure(void)
+{
+ /* 2x speed mode */
+ BIT_SET(UCSR0A, U2X0);
+ /* configure baud rate */
+ UBRR0 = (F_CPU / (8UL * Baud_Rate)) - 1;
+}
+
bool rs485_baud_rate_set(
uint32_t baud)
{
bool valid = true;
+ uint8_t baud_k = 0;
switch (baud) {
case 9600:
@@ -165,11 +175,13 @@ bool rs485_baud_rate_set(
case 76800:
case 115200:
Baud_Rate = baud;
- /* 2x speed mode */
- BIT_SET(UCSR0A, U2X0);
- /* configure baud rate */
- UBRR0 = (F_CPU / (8UL * Baud_Rate)) - 1;
- /* FIXME: store the baud rate */
+ rs485_baud_rate_configure();
+ /* store the baud rate */
+ baud_k = baud/1000;
+ eeprom_bytes_write(
+ NV_EEPROM_BAUD_K,
+ &baud_k,
+ 1);
break;
default:
valid = false;
@@ -195,13 +207,53 @@ static void rs485_usart_init(void)
BIT_CLEAR(PRR, PRUSART0);
}
+static void rs485_init_nvdata(void)
+{
+ uint8_t baud_k = 9; /* from EEPROM value */
+
+ eeprom_bytes_read(
+ NV_EEPROM_BAUD_K,
+ &baud_k,
+ 1);
+ switch (baud_k) {
+ case 9:
+ Baud_Rate = 9600;
+ break;
+ case 19:
+ Baud_Rate = 19200;
+ break;
+ case 38:
+ Baud_Rate = 38400;
+ break;
+ case 57:
+ Baud_Rate = 57600;
+ break;
+ case 76:
+ Baud_Rate = 76800;
+ break;
+ case 115:
+ Baud_Rate = 115200;
+ break;
+ default:
+ /* not configured yet */
+ Baud_Rate = 38400;
+ baud_k = 38400/1000;
+ eeprom_bytes_write(
+ NV_EEPROM_BAUD_K,
+ &baud_k,
+ 1);
+ break;
+ }
+ rs485_baud_rate_configure();
+}
+
void rs485_init(void)
{
FIFO_Init(&Receive_Buffer, &Receive_Buffer_Data[0],
(unsigned)sizeof(Receive_Buffer_Data));
rs485_rts_init();
rs485_usart_init();
- rs485_baud_rate_set(Baud_Rate);
+ rs485_init_nvdata();
rs485_receiver_enable();
rs485_rts_enable(false);
}