Updated port for BACnet Development Kit.

This commit is contained in:
skarg
2009-05-11 22:32:06 +00:00
parent be4b33c099
commit 469627a6cf
28 changed files with 1758 additions and 211 deletions
+1 -1
View File
@@ -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;
+4 -2
View File
@@ -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 {
+4
View File
@@ -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
+2
View File
@@ -35,6 +35,8 @@
extern "C" {
#endif /* __cplusplus */
void Binary_Output_Init(void);
void Binary_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
+3
View File
@@ -44,6 +44,9 @@
extern "C" {
#endif /* __cplusplus */
void Device_Init(void);
void Device_Property_Lists(
const int **pRequired,
const int **pOptional,
+6 -5
View File
@@ -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
+37
View File
@@ -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 */
+1 -1
View File
@@ -1 +1 @@
<AVRStudio><MANAGEMENT><ProjectName>bacnet</ProjectName><Created>29-Apr-2009 08:16:53</Created><LastEdit>03-May-2009 15:12:17</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>29-Apr-2009 08:16:53</Created><Version>4</Version><Build>4, 15, 0, 623</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile></ObjectFile><EntryFile></EntryFile><SaveFolder>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET>JTAGICE mkII</CURRENT_TARGET><CURRENT_PART>ATmega644P.xml</CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM>Auto</COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>main.c</SOURCEFILE><SOURCEFILE>timer2.c</SOURCEFILE><SOURCEFILE>eeprom.c</SOURCEFILE><SOURCEFILE>init.c</SOURCEFILE><SOURCEFILE>input.c</SOURCEFILE><SOURCEFILE>led.c</SOURCEFILE><SOURCEFILE>rs485.c</SOURCEFILE><SOURCEFILE>seeprom.c</SOURCEFILE><SOURCEFILE>serial.c</SOURCEFILE><SOURCEFILE>stack.c</SOURCEFILE><SOURCEFILE>dlmstp.c</SOURCEFILE><SOURCEFILE>bo.c</SOURCEFILE><SOURCEFILE>bi.c</SOURCEFILE><SOURCEFILE>ai.c</SOURCEFILE><SOURCEFILE>device.c</SOURCEFILE><SOURCEFILE>h_rp.c</SOURCEFILE><SOURCEFILE>h_wp.c</SOURCEFILE><OTHERFILE>Makefile</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>default</NAME><USESEXTERNALMAKEFILE>YES</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE>Makefile</EXTERNALMAKEFILE><PART>atmega644p</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>bacnet.elf</OUTPUTFILENAME><OUTPUTDIR>default\</OUTPUTDIR><ISDIRTY>1</ISDIRTY><OPTIONS/><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums</OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>default</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR-20090313\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR-20090313\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><ProjectFiles><Files><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\main.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\timer2.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\eeprom.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\init.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\input.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\led.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\rs485.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\seeprom.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\serial.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\stack.c</Name></Files></ProjectFiles><IOView><usergroups/><sort sorted="0" column="0" ordername="0" orderaddress="0" ordergroup="0"/></IOView><Files><File00000><FileId>00000</FileId><FileName>main.c</FileName><Status>1</Status></File00000></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio>
<AVRStudio><MANAGEMENT><ProjectName>bacnet</ProjectName><Created>29-Apr-2009 08:16:53</Created><LastEdit>11-May-2009 13:31:34</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>29-Apr-2009 08:16:53</Created><Version>4</Version><Build>4, 15, 0, 623</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile></ObjectFile><EntryFile></EntryFile><SaveFolder>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET>JTAGICE mkII</CURRENT_TARGET><CURRENT_PART>ATmega644P.xml</CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM>Auto</COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>main.c</SOURCEFILE><SOURCEFILE>timer2.c</SOURCEFILE><SOURCEFILE>eeprom.c</SOURCEFILE><SOURCEFILE>init.c</SOURCEFILE><SOURCEFILE>input.c</SOURCEFILE><SOURCEFILE>led.c</SOURCEFILE><SOURCEFILE>rs485.c</SOURCEFILE><SOURCEFILE>seeprom.c</SOURCEFILE><SOURCEFILE>serial.c</SOURCEFILE><SOURCEFILE>stack.c</SOURCEFILE><SOURCEFILE>dlmstp.c</SOURCEFILE><SOURCEFILE>bo.c</SOURCEFILE><SOURCEFILE>bi.c</SOURCEFILE><SOURCEFILE>ai.c</SOURCEFILE><SOURCEFILE>device.c</SOURCEFILE><SOURCEFILE>h_rp.c</SOURCEFILE><SOURCEFILE>h_wp.c</SOURCEFILE><HEADERFILE>timer.h</HEADERFILE><HEADERFILE>eeprom.h</HEADERFILE><HEADERFILE>hardware.h</HEADERFILE><HEADERFILE>iar2gcc.h</HEADERFILE><HEADERFILE>init.h</HEADERFILE><HEADERFILE>input.h</HEADERFILE><HEADERFILE>led.h</HEADERFILE><HEADERFILE>nvdata.h</HEADERFILE><HEADERFILE>rs485.h</HEADERFILE><HEADERFILE>seeprom.h</HEADERFILE><HEADERFILE>serial.h</HEADERFILE><OTHERFILE>Makefile</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>default</NAME><USESEXTERNALMAKEFILE>YES</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE>Makefile</EXTERNALMAKEFILE><PART>atmega644p</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>bacnet.elf</OUTPUTFILENAME><OUTPUTDIR>default\</OUTPUTDIR><ISDIRTY>1</ISDIRTY><OPTIONS/><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums</OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>default</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR-20090313\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR-20090313\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><ProjectFiles><Files><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\main.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\timer2.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\eeprom.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\init.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\input.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\led.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\rs485.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\seeprom.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\serial.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\stack.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\dlmstp.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\bo.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\bi.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\ai.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\device.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\h_rp.c</Name><Name>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\h_wp.c</Name></Files></ProjectFiles><IOView><usergroups/><sort sorted="0" column="0" ordername="1" orderaddress="1" ordergroup="1"/></IOView><Files><File00000><FileId>00000</FileId><FileName>main.c</FileName><Status>1</Status></File00000></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio>
+40
View File
@@ -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)
{
-89
View File
@@ -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
+64 -24
View File
@@ -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;
@@ -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 <http://savannah.nongnu.org/projects/avrdude>
# 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
@@ -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 <avr/io.h>
#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
@@ -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 <inavr.h>
# 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<<SPMEN) );
# ifndef LARGE_MEMORY
# define _LOAD_PROGRAM_MEMORY(addr) __load_program_memory( (const unsigned char __flash *) (addr) )
# define _FILL_TEMP_WORD(addr,data) __AddrToZWordToR1R0ByteToSPMCR_SPM( (void __flash *) (addr), data, 0x01 )
# define _PAGE_ERASE(addr) __AddrToZByteToSPMCR_SPM( (void __flash *) (addr), 0x03 )
# define _PAGE_WRITE(addr) __AddrToZByteToSPMCR_SPM( (void __flash *) (addr), 0x05 )
# else /* LARGE_MEMORY */
# define _LOAD_PROGRAM_MEMORY(addr) __extended_load_program_memory( (const unsigned char __farflash *) (addr) )
# define _FILL_TEMP_WORD(addr,data) __AddrToZ24WordToR1R0ByteToSPMCR_SPM( (void __farflash *) (addr), data, 0x01 )
# define _PAGE_ERASE(addr) __AddrToZ24ByteToSPMCR_SPM( (void __farflash *) (addr), 0x03 )
# define _PAGE_WRITE(addr) __AddrToZ24ByteToSPMCR_SPM( (void __farflash *) (addr), 0x05 )
# endif /* LARGE_MEMORY */
#elif __GNUC__ > 0
/* AVR-GCC/avr-libc */
# include <avr/boot.h>
# include <avr/pgmspace.h>
# 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
@@ -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<<PROG_NO); // Enable pull-up on PROG_NO line on PROGPORT.
initbootuart(); // Initialize UART.
/* Branch to bootloader or application code? */
if( !(PROGPIN & (1<<PROG_NO)) ) // If PROGPIN is pulled low, enter programmingmode.
{
/* Main loop */
for(;;)
{
val=recchar(); // Wait for command character.
// Check autoincrement status.
if(val=='a')
{
sendchar('Y'); // Yes, we do autoincrement.
}
// Set address.
else if(val=='A') // Set address...
{ // NOTE: Flash addresses are given in words, not bytes.
address=(recchar()<<8) | recchar(); // Read address high and low byte.
sendchar('\r'); // Send OK back.
}
// Chip erase.
else if(val=='e')
{
for(address = 0; address < APP_END;address += PAGESIZE)
{ // NOTE: Here we use address as a byte-address, not word-address, for convenience.
_WAIT_FOR_SPM();
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#endif
_PAGE_ERASE( address );
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#endif
}
sendchar('\r'); // Send OK back.
}
#ifndef REMOVE_BLOCK_SUPPORT
// Check block load support.
else if(val=='b')
{
sendchar('Y'); // Report block load supported.
sendchar((BLOCKSIZE>>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<<EEMWE); // Write byte.
EECR |= (1<<EEWE);
while (EECR & (1<<EEWE)) // Wait for write operation to finish.
;
address++; // Auto-advance to next EEPROM byte.
sendchar('\r');// Send OK back.
}
// Read EEPROM memory.
else if (val == 'd')
{
EEARL = address; // Setup EEPROM address.
EEARH = (address >> 8);
EECR |= (1<<EERE); // Read byte...
sendchar(EEDR); // ...and send it back.
address++; // Auto-advance to next EEPROM byte.
}
#endif /* REMOVE_EEPROM_BYTE_SUPPORT */
#ifndef REMOVE_FUSE_AND_LOCK_BIT_SUPPORT
// Write lockbits.
else if(val=='l')
{
_WAIT_FOR_SPM();
_SET_LOCK_BITS( recchar() ); // Read and set lock bits.
sendchar('\r'); // Send OK back.
}
#if defined(_GET_LOCK_BITS)
// Read lock bits.
else if(val=='r')
{
_WAIT_FOR_SPM();
sendchar( _GET_LOCK_BITS() );
}
// Read fuse bits.
else if(val=='F')
{
_WAIT_FOR_SPM();
sendchar( _GET_LOW_FUSES() );
}
// Read high fuse bits.
else if(val=='N')
{
_WAIT_FOR_SPM();
sendchar( _GET_HIGH_FUSES() );
}
// Read extended fuse bits.
else if(val=='Q')
{
_WAIT_FOR_SPM();
sendchar( _GET_EXTENDED_FUSES() );
}
#endif /* defined(_GET_LOCK_BITS) */
#endif /* REMOVE_FUSE_AND_LOCK_BIT_SUPPORT */
#ifndef REMOVE_AVRPROG_SUPPORT
// Enter and leave programming mode.
else if((val=='P')||(val=='L'))
{
sendchar('\r'); // Nothing special to do, just answer OK.
}
// Exit bootloader.
else if(val=='E')
{
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
sendchar('\r');
funcptr(); // Jump to Reset vector 0x0000 in Application Section.
}
// Get programmer type.
else if (val=='p')
{
sendchar('S'); // Answer 'SERIAL'.
}
// Return supported device codes.
else if(val=='t')
{
#if PARTCODE+0 > 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<size;tempaddress++)
buffer[tempaddress] = recchar();
/* Then program the EEPROM */
_WAIT_FOR_SPM();
for( tempaddress=0; tempaddress < size; tempaddress++)
{
EEARL = *address; // Setup EEPROM address
EEARH = ((*address) >> 8);
EEDR = buffer[tempaddress]; // Get byte.
EECR |= (1<<EEMWE); // Write byte.
EECR |= (1<<EEWE);
while (EECR & (1<<EEWE)) // Wait for write operation to finish.
;
(*address)++; // Select next EEPROM byte
}
return '\r'; // Report programming OK
}
// Flash memory type.
else if(mem=='F')
{ // NOTE: For flash programming, 'address' is given in words.
(*address) <<= 1; // Convert address to bytes temporarily.
tempaddress = (*address); // Store address in page.
do
{
data = recchar();
data |= (recchar() << 8);
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#endif
_FILL_TEMP_WORD(*address,data);
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#endif
(*address)+=2; // Select next word in memory.
size -= 2; // Reduce number of bytes to write by two.
} while(size); // Loop until all bytes written.
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#endif
_PAGE_WRITE(tempaddress);
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#endif
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
(*address) >>= 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<<EERE); // Read EEPROM
sendchar(EEDR); // Transmit EEPROM dat ato PC
size--; // Decrease number of bytes to read
} while (size); // Repeat until all block has been read
}
// Flash memory type.
else if(mem=='F')
{
(*address) <<= 1; // Convert address to bytes temporarily.
do
{
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#endif
sendchar( _LOAD_PROGRAM_MEMORY(*address) );
sendchar( _LOAD_PROGRAM_MEMORY((*address)+1) );
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#endif
(*address) += 2; // Select next word in memory.
size -= 2; // Subtract two bytes from number of bytes to read
} while (size); // Repeat until all block has been read
(*address) >>= 1; // Convert address back to Flash words again.
}
}
#endif /* REMOVE_BLOCK_SUPPORT */
/* end of file */
@@ -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
@@ -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 <avr/io.h>
#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
@@ -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;
}
@@ -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 );
+153 -67
View File
@@ -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;
+2 -2
View File
@@ -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. */
+113
View File
@@ -0,0 +1,113 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#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;
}
Binary file not shown.
@@ -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;
}
}
}
+60 -9
View File
@@ -1,4 +1,4 @@
/**************************************************************************
/************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
@@ -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 <stdbool.h>
#include <stdint.h>
@@ -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(
+104
View File
@@ -0,0 +1,104 @@
/************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*************************************************************************/
#ifndef 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
+58 -6
View File
@@ -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);
}