From 9235ebeee291d47e3a53bb113fdfd570c20f59f0 Mon Sep 17 00:00:00 2001 From: skarg Date: Tue, 12 May 2009 20:25:31 +0000 Subject: [PATCH] Improved BACnet Development Kit object handling and storing to SEEPROM and EEPROM. Added device property to check C-Stack size and amount unused. --- bacnet-stack/include/bacenum.h | 2 +- bacnet-stack/ports/bdk-atxx4-mstp/Makefile | 1 + bacnet-stack/ports/bdk-atxx4-mstp/ai.c | 2 +- bacnet-stack/ports/bdk-atxx4-mstp/bo.c | 143 ++++++++++++++----- bacnet-stack/ports/bdk-atxx4-mstp/device.c | 7 + bacnet-stack/ports/bdk-atxx4-mstp/hardware.h | 7 + bacnet-stack/ports/bdk-atxx4-mstp/main.c | 30 +++- bacnet-stack/ports/bdk-atxx4-mstp/nvdata.h | 28 ++++ bacnet-stack/ports/bdk-atxx4-mstp/seeprom.c | 4 +- bacnet-stack/ports/bdk-atxx4-mstp/stack.c | 29 +++- bacnet-stack/ports/bdk-atxx4-mstp/stack.h | 48 +++++++ 11 files changed, 256 insertions(+), 45 deletions(-) create mode 100644 bacnet-stack/ports/bdk-atxx4-mstp/stack.h diff --git a/bacnet-stack/include/bacenum.h b/bacnet-stack/include/bacenum.h index 01fa1a0b..3cca74e0 100644 --- a/bacnet-stack/include/bacenum.h +++ b/bacnet-stack/include/bacenum.h @@ -396,7 +396,7 @@ typedef enum { BINARY_INACTIVE = 0, BINARY_ACTIVE = 1, MAX_BINARY_PV = 1, /* for validating incoming values */ - BINARY_NULL = 2 /* our homemade way of storing this info */ + BINARY_NULL = 255 /* our homemade way of storing this info */ } BACNET_BINARY_PV; typedef enum { diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/Makefile b/bacnet-stack/ports/bdk-atxx4-mstp/Makefile index 14e5cbeb..8b328de4 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/Makefile +++ b/bacnet-stack/ports/bdk-atxx4-mstp/Makefile @@ -40,6 +40,7 @@ BACNET_DEMO = ../../demo # local files for this project CSRC = main.c \ init.c \ + stack.c \ input.c \ serial.c \ rs485.c \ diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/ai.c b/bacnet-stack/ports/bdk-atxx4-mstp/ai.c index 7d6deb22..b3d36c2b 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/ai.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/ai.c @@ -33,7 +33,7 @@ #include "bacenum.h" #include "config.h" -/* Analog Input = Photocell */ +/* Analog Input */ #define MAX_ANALOG_INPUTS 2 #if (MAX_ANALOG_INPUTS > 9) #error Modify the Analog_Input_Name to handle multiple digits diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bo.c b/bacnet-stack/ports/bdk-atxx4-mstp/bo.c index 5dd0d605..1cb91ba8 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/bo.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/bo.c @@ -34,6 +34,7 @@ #include "config.h" /* the custom stuff */ #include "wp.h" #include "led.h" +#include "nvdata.h" #define MAX_BINARY_OUTPUTS 2 #if (MAX_BINARY_OUTPUTS > 9) @@ -44,13 +45,13 @@ /* the Relinquish Default value */ #define RELINQUISH_DEFAULT BINARY_INACTIVE /* Here is our Priority Array.*/ -static BACNET_BINARY_PV +static uint8_t Binary_Output_Level[MAX_BINARY_OUTPUTS][BACNET_MAX_PRIORITY]; /* 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]; +static uint8_t Out_Of_Service[MAX_BINARY_OUTPUTS]; /* polarity - normal or inverse */ -static BACNET_POLARITY Polarity[MAX_BINARY_OUTPUTS]; +static uint8_t Polarity[MAX_BINARY_OUTPUTS]; /* These three arrays are used by the ReadPropertyMultiple handler */ static const int Binary_Output_Properties_Required[] = { @@ -93,24 +94,51 @@ void Binary_Output_Property_Lists( return; } -void Binary_Output_Init( - void) +void Binary_Output_Level_Set( + unsigned int object_index, + unsigned int priority, + BACNET_BINARY_PV level) { - unsigned i, j; - static bool initialized = false; - - if (!initialized) { - initialized = true; - - /* initialize all the analog output priority arrays to NULL */ - for (i = 0; i < MAX_BINARY_OUTPUTS; i++) { - for (j = 0; j < BACNET_MAX_PRIORITY; j++) { - Binary_Output_Level[i][j] = BINARY_NULL; - } + if (object_index < MAX_BINARY_OUTPUTS) { + if (priority < BACNET_MAX_PRIORITY) { + Binary_Output_Level[object_index][priority] = (uint8_t)level; + seeprom_bytes_write( + NV_SEEPROM_BINARY_OUTPUT(object_index, + NV_SEEPROM_BO_PRIORITY_ARRAY_1+priority), + &Binary_Output_Level[object_index][priority], + 1); } } +} - return; +void Binary_Output_Polarity_Set( + unsigned int object_index, + BACNET_POLARITY polarity) +{ + if (object_index < MAX_BINARY_OUTPUTS) { + if (polarity < MAX_POLARITY) { + Polarity[object_index] = POLARITY_NORMAL; + seeprom_bytes_write( + NV_SEEPROM_BINARY_OUTPUT(object_index, + NV_SEEPROM_BO_POLARITY), + &Polarity[object_index], + 1); + } + } +} + +void Binary_Output_Out_Of_Service_Set( + unsigned int object_index, + bool flag) +{ + if (object_index < MAX_BINARY_OUTPUTS) { + Out_Of_Service[object_index] = flag; + seeprom_bytes_write( + NV_SEEPROM_BINARY_OUTPUT(object_index, + NV_SEEPROM_BO_OUT_OF_SERVICE), + &Out_Of_Service[object_index], + 1); + } } /* we simply have 0-n object instances. */ @@ -153,14 +181,15 @@ static BACNET_BINARY_PV Binary_Output_Present_Value( uint32_t object_instance) { BACNET_BINARY_PV value = RELINQUISH_DEFAULT; + BACNET_BINARY_PV current_value = RELINQUISH_DEFAULT; unsigned index = 0; unsigned i = 0; - Binary_Output_Init(); index = Binary_Output_Instance_To_Index(object_instance); if (index < MAX_BINARY_OUTPUTS) { for (i = 0; i < BACNET_MAX_PRIORITY; i++) { - if (Binary_Output_Level[index][i] != BINARY_NULL) { + current_value = Binary_Output_Level[index][i]; + if (current_value != BINARY_NULL) { value = Binary_Output_Level[index][i]; break; } @@ -177,7 +206,7 @@ static void Binary_Output_Sync( unsigned index = Binary_Output_Instance_To_Index(object_instance); if (index < MAX_BINARY_OUTPUTS) { - if (Binary_Output_Out_Of_Service[index]) { + if (Out_Of_Service[index]) { return; } if (Polarity[index] == POLARITY_REVERSE) { @@ -240,7 +269,6 @@ int Binary_Output_Encode_Property_APDU( unsigned i = 0; bool state = false; - Binary_Output_Init(); switch (property) { case PROP_OBJECT_IDENTIFIER: apdu_len = @@ -280,7 +308,7 @@ int Binary_Output_Encode_Property_APDU( break; case PROP_OUT_OF_SERVICE: object_index = Binary_Output_Instance_To_Index(object_instance); - state = Binary_Output_Out_Of_Service[object_index]; + state = Out_Of_Service[object_index]; apdu_len = encode_application_boolean(&apdu[0], state); break; case PROP_POLARITY: @@ -299,10 +327,10 @@ int Binary_Output_Encode_Property_APDU( Binary_Output_Instance_To_Index(object_instance); for (i = 0; i < BACNET_MAX_PRIORITY; i++) { /* FIXME: check if we have room before adding it to APDU */ - if (Binary_Output_Level[object_index][i] == BINARY_NULL) + present_value = Binary_Output_Level[object_index][i]; + if (present_value == BINARY_NULL) { len = encode_application_null(&apdu[apdu_len]); - else { - present_value = Binary_Output_Level[object_index][i]; + } else { len = encode_application_enumerated(&apdu[apdu_len], present_value); @@ -321,12 +349,11 @@ int Binary_Output_Encode_Property_APDU( object_index = Binary_Output_Instance_To_Index(object_instance); if (array_index <= BACNET_MAX_PRIORITY) { - if (Binary_Output_Level[object_index][array_index] == - BINARY_NULL) + present_value = + Binary_Output_Level[object_index][array_index]; + if (present_value == BINARY_NULL) { len = encode_application_null(&apdu[apdu_len]); - else { - present_value = - Binary_Output_Level[object_index][array_index]; + } else { len = encode_application_enumerated(&apdu[apdu_len], present_value); @@ -400,7 +427,7 @@ bool Binary_Output_Write_Property( (value.type.Enumerated <= MAX_BINARY_PV)) { level = (BACNET_BINARY_PV) value.type.Enumerated; priority--; - Binary_Output_Level[object_index][priority] = level; + Binary_Output_Level_Set(object_index, priority,level); Binary_Output_Sync(wp_data->object_instance); status = true; } else if (priority == 6) { @@ -418,9 +445,15 @@ bool Binary_Output_Write_Property( priority = wp_data->priority; if (priority && (priority <= BACNET_MAX_PRIORITY)) { priority--; - Binary_Output_Level[object_index][priority] = level; + Binary_Output_Level_Set(object_index, priority,level); Binary_Output_Sync(wp_data->object_instance); status = true; + } else if (priority == 6) { + /* Command priority 6 is reserved for use by Minimum On/Off + algorithm and may not be used for other purposes in any + object. */ + *error_class = ERROR_CLASS_PROPERTY; + *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; @@ -432,8 +465,8 @@ bool Binary_Output_Write_Property( break; case PROP_OUT_OF_SERVICE: if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) { - Binary_Output_Out_Of_Service[object_index] = - value.type.Boolean; + Binary_Output_Out_Of_Service_Set(object_index, + value.type.Boolean); Binary_Output_Sync(wp_data->object_instance); status = true; } else { @@ -443,9 +476,11 @@ bool Binary_Output_Write_Property( break; case PROP_POLARITY: if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) { - if (value.type.Enumerated <= MAX_POLARITY) { - Polarity[object_index] = - (BACNET_POLARITY)value.type.Enumerated; + if (value.type.Enumerated < MAX_POLARITY) { + Binary_Output_Polarity_Set(object_index, + value.type.Enumerated); + Binary_Output_Sync(wp_data->object_instance); + status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; @@ -463,3 +498,37 @@ bool Binary_Output_Write_Property( return status; } + +void Binary_Output_Init( + void) +{ + unsigned i, j; + + /* initialize all the analog output priority arrays to NULL */ + for (i = 0; i < MAX_BINARY_OUTPUTS; i++) { + seeprom_bytes_read( + NV_SEEPROM_BINARY_OUTPUT(i,NV_SEEPROM_BO_POLARITY), + &Polarity[i], + 1); + if (Polarity[i] >= MAX_POLARITY) { + Binary_Output_Polarity_Set(i, POLARITY_NORMAL); + } + seeprom_bytes_read( + NV_SEEPROM_BINARY_OUTPUT(i,NV_SEEPROM_BO_OUT_OF_SERVICE), + &Out_Of_Service[i], + 1); + if (Out_Of_Service[i] > 1) { + Binary_Output_Out_Of_Service_Set(i, false); + } + for (j = 0; j < BACNET_MAX_PRIORITY; j++) { + seeprom_bytes_read( + NV_SEEPROM_BINARY_OUTPUT(i, + NV_SEEPROM_BO_PRIORITY_ARRAY_1+j), + &Binary_Output_Level[i][j], + 1); + } + Binary_Output_Sync(i); + } + + return; +} diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/device.c b/bacnet-stack/ports/bdk-atxx4-mstp/device.c index 0a4e45b7..1c01d890 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/device.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/device.c @@ -35,6 +35,7 @@ #include "rs485.h" #include "version.h" #include "nvdata.h" +#include "stack.h" /* objects */ #include "device.h" #include "ai.h" @@ -495,6 +496,12 @@ int Device_Encode_Property_APDU( apdu_len = encode_application_unsigned(&apdu[0], dlmstp_max_master()); break; + case 512: + apdu_len = encode_application_unsigned(&apdu[0], stack_size()); + break; + case 513: + apdu_len = encode_application_unsigned(&apdu[0], stack_unused()); + break; default: *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_UNKNOWN_PROPERTY; diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/hardware.h b/bacnet-stack/ports/bdk-atxx4-mstp/hardware.h index 8425e0c3..ff2a68c2 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/hardware.h +++ b/bacnet-stack/ports/bdk-atxx4-mstp/hardware.h @@ -45,4 +45,11 @@ #include "iar2gcc.h" #include "bits.h" +/* SEEPROM is 24LC128 */ +//#define SEEPROM_PAGE_SIZE 128 +//#define SEEPROM_WORD_ADDRESS_16BIT 1 +/* SEEPROM is 24C16 */ +#define SEEPROM_PAGE_SIZE 16 +#define SEEPROM_WORD_ADDRESS_16BIT 0 + #endif diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/main.c b/bacnet-stack/ports/bdk-atxx4-mstp/main.c index 2371cf5c..3f3ef8fc 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/main.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/main.c @@ -27,10 +27,11 @@ #include #include "hardware.h" #include "init.h" +#include "stack.h" #include "timer.h" #include "input.h" #include "led.h" -#include "seeprom.h" +#include "nvdata.h" #include "timer.h" #include "dcc.h" #include "rs485.h" @@ -101,16 +102,41 @@ FUSES = LOCKBITS = LOCKBITS_DEFAULT; #endif +bool seeprom_version_test(void) +{ + uint16_t version = 0; + uint16_t id = 0; + bool status = false; + + seeprom_bytes_read(NV_SEEPROM_TYPE_0, (uint8_t *)&id, 2); + seeprom_bytes_read(NV_SEEPROM_VERSION_0, (uint8_t *)&version, 2); + + if ((id == SEEPROM_ID) && (version == SEEPROM_VERSION)) { + status = true; + } else { + version = SEEPROM_VERSION; + id = SEEPROM_ID; + seeprom_bytes_write(NV_SEEPROM_TYPE_0, (uint8_t *)&id, 2); + seeprom_bytes_write(NV_SEEPROM_VERSION_0, (uint8_t *)&version, 2); + } + + return status; +} + static void bacnet_init( void) { MSTP_MAC_Address = input_address(); dlmstp_set_mac_address(MSTP_MAC_Address); dlmstp_init(NULL); + + if (!seeprom_version_test()) { + /* invalid version data */ + } /* 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. */ diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/nvdata.h b/bacnet-stack/ports/bdk-atxx4-mstp/nvdata.h index 1cfdbccd..518c3288 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/nvdata.h +++ b/bacnet-stack/ports/bdk-atxx4-mstp/nvdata.h @@ -91,6 +91,34 @@ #define NV_EEPROM_DEVICE_NAME_31 41 #define NV_EEPROM_DEVICE_NAME_SIZE 32 +/*=============== SEEPROM ================*/ +#define NV_SEEPROM_BINARY_OUTPUT_OFFSET 32 +#define NV_SEEPROM_BINARY_OUTPUT_0 10 +#define NV_SEEPROM_BINARY_OUTPUT(n,p) \ + (NV_SEEPROM_BINARY_OUTPUT_0 + \ + (NV_SEEPROM_BINARY_OUTPUT_OFFSET * (n)) + (p)) +/* BO properties */ +#define NV_SEEPROM_BO_POLARITY 0 +#define NV_SEEPROM_BO_OUT_OF_SERVICE 1 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_1 2 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_2 3 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_3 4 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_4 5 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_5 6 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_6 7 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_7 8 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_8 9 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_9 10 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_10 11 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_11 12 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_12 13 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_13 14 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_14 15 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_15 16 +#define NV_SEEPROM_BO_PRIORITY_ARRAY_16 17 + + + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/seeprom.c b/bacnet-stack/ports/bdk-atxx4-mstp/seeprom.c index 92194963..8221ef8b 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/seeprom.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/seeprom.c @@ -97,7 +97,7 @@ /************************************************************************* * DESCRIPTION: Return bytes from SEEPROM memory at address * RETURN: number of bytes read, or -1 on error -* NOTES: The 24LC128 SEEPROM uses a two byte memory address +* NOTES: none **************************************************************************/ int seeprom_bytes_read( uint16_t eeaddr, /* SEEPROM starting memory address */ @@ -274,7 +274,7 @@ error: /************************************************************************* * DESCRIPTION: Write some data and wait until it is sent * RETURN: number of bytes written, or -1 on error -* NOTES: The 24LC128 SEEPROM uses a two byte memory address +* NOTES: none **************************************************************************/ int seeprom_bytes_write( uint16_t eeaddr, /* SEEPROM starting memory address */ diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/stack.c b/bacnet-stack/ports/bdk-atxx4-mstp/stack.c index 18d86177..1660254d 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/stack.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/stack.c @@ -29,10 +29,10 @@ extern uint8_t _end; extern uint8_t __stack; #define STACK_CANARY (0xC5) -void stack_paint( +void stack_init( void) __attribute__ ((naked)) __attribute__ ((section(".init1"))); -void stack_paint( +void stack_init( void) { #if 0 @@ -50,3 +50,28 @@ void stack_paint( " cpc r31,r25\n" " brlo .loop\n" " breq .loop"::); #endif } + +unsigned stack_size(void) +{ + return (&__stack) - (&_end); +} + +uint8_t stack_byte(unsigned offset) +{ + return *(&_end + offset); +} + +unsigned stack_unused(void) +{ + uint8_t *p = &_end; + unsigned count = 0; + + while (p <= &__stack) { + if ((*p) != STACK_CANARY) { + count = p - (&_end); + break; + } + p++; + } + return count; +} diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/stack.h b/bacnet-stack/ports/bdk-atxx4-mstp/stack.h new file mode 100644 index 00000000..cf97bb7f --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/stack.h @@ -0,0 +1,48 @@ +/************************************************************************** +* +* Copyright (C) 2009 Steve Karg +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +*********************************************************************/ +#ifndef STACK_H +#define STACK_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /* C stack checking */ + void stack_init(void); + + unsigned stack_size(void); + + uint8_t stack_byte(unsigned offset); + + unsigned stack_unused(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif + \ No newline at end of file