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.cMakefiledefaultYESMakefileatmega644p111bacnet.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.hMakefiledefaultYESMakefileatmega644p111bacnet.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); }