Updated port for BACnet Development Kit.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void Binary_Output_Init(void);
|
||||
|
||||
void Binary_Output_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
void Device_Init(void);
|
||||
|
||||
void Device_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 @@
|
||||
<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,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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Binary file not shown.
@@ -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 );
|
||||
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user