From 2e51778790d8dd23aca37959c5d4bac087bee43b Mon Sep 17 00:00:00 2001 From: petermcs Date: Mon, 30 Apr 2012 10:14:18 +0000 Subject: [PATCH] Add facility to adjust the services and and other features supported via config.h. This is to reduce code size in embedded builds where the compiler does not do a great job in removing functions that are never called. This is particularly useful for simple server only applications where decoding of response packets and encoding of requests are not required for example. Also added possibility for RMP of encoding large items in-line in the response packet so that the object RP handlers know how much space they really have without the need for a full APDU buffer being maintained. --- bacnet-stack/include/config.h | 83 +++++++++++++++++++++++++++++++++++ bacnet-stack/src/abort.c | 2 + bacnet-stack/src/bacapp.c | 4 ++ bacnet-stack/src/bacdcode.c | 7 +++ bacnet-stack/src/bacerror.c | 2 + bacnet-stack/src/bacint.c | 3 +- bacnet-stack/src/bacreal.c | 3 ++ bacnet-stack/src/bacstr.c | 2 + bacnet-stack/src/dcc.c | 3 +- bacnet-stack/src/ihave.c | 3 ++ bacnet-stack/src/memcopy.c | 23 +++++----- bacnet-stack/src/rd.c | 3 +- bacnet-stack/src/reject.c | 2 + bacnet-stack/src/rp.c | 4 ++ bacnet-stack/src/rpm.c | 15 ++++++- bacnet-stack/src/timesync.c | 3 +- bacnet-stack/src/wp.c | 3 +- 17 files changed, 148 insertions(+), 17 deletions(-) diff --git a/bacnet-stack/include/config.h b/bacnet-stack/include/config.h index 6157e6e6..dd43a739 100644 --- a/bacnet-stack/include/config.h +++ b/bacnet-stack/include/config.h @@ -160,4 +160,87 @@ #define MAX_OCTET_STRING_BYTES (MAX_APDU-6) #endif +/* +** Control the selection of services etc to enable code size reduction for those +** compiler suites which do not handle removing of unused functions in modules +** so well. +** +** We will start with the A type services code first as these are least likely +** to be required in embedded systems using the stack. +*/ + +/* +** First we see if this is a test build and enable all the services as they +** may be required. +** +** Note: I've left everything enabled here in the main config.h. You would +** use a local copy of config.h with settings configured for your needs to +** make use of the code space reductions. +**/ + +#ifdef TEST + #define BACNET_SVC_I_HAVE_A 1 + #define BACNET_SVC_WP_A 1 + #define BACNET_SVC_RP_A 1 + #define BACNET_SVC_RPM_A 1 + #define BACNET_SVC_DCC_A 1 + #define BACNET_SVC_RD_A 1 + #define BACNET_SVC_SERVER 0 + #define BACNET_USE_OCTETSTRING 1 + #define BACNET_USE_DOUBLE 1 + #define BACNET_USE_SIGNED 1 +#else /* Otherwise define our working set - all enabled here to avoid breaking things */ + #define BACNET_SVC_I_HAVE_A 1 + #define BACNET_SVC_WP_A 1 + #define BACNET_SVC_RP_A 1 + #define BACNET_SVC_RPM_A 1 + #define BACNET_SVC_DCC_A 1 + #define BACNET_SVC_RD_A 1 + #define BACNET_SVC_SERVER 0 + #define BACNET_USE_OCTETSTRING 1 + #define BACNET_USE_DOUBLE 1 + #define BACNET_USE_SIGNED 1 +#endif + +/* Do them one by one */ + #ifndef BACNET_SVC_I_HAVE_A /* Do we send I_Have requests? */ + #define BACNET_SVC_I_HAVE_A 0 + #endif + + #ifndef BACNET_SVC_WP_A /* Do we send WriteProperty requests? */ + #define BACNET_SVC_WP_A 0 + #endif + + #ifndef BACNET_SVC_RP_A /* Do we send ReadProperty requests? */ + #define BACNET_SVC_RP_A 0 + #endif + + #ifndef BACNET_SVC_RPM_A /* Do we send ReadPropertyMultiple requests? */ + #define BACNET_SVC_RPM_A 0 + #endif + + #ifndef BACNET_SVC_DCC_A /* Do we send DeviceCommunicationControl requests? */ + #define BACNET_SVC_DCC_A 0 + #endif + + #ifndef BACNET_SVC_RD_A /* Do we send ReinitialiseDevice requests? */ + #define BACNET_SVC_RD_A 0 + #endif + + #ifndef BACNET_SVC_SERVER /* Are we a pure server type device? */ + #define BACNET_SVC_SERVER 1 + #endif + + #ifndef BACNET_USE_OCTETSTRING /* Do we need any octet strings? */ + #define BACNET_USE_OCTETSTRING 0 + #endif + + #ifndef BACNET_USE_DOUBLE /* Do we need any doubles? */ + #define BACNET_USE_DOUBLE 0 + #endif + + #ifndef BACNET_USE_SIGNED /* Do we need any signed integers */ + #define BACNET_USE_SIGNED 0 + #endif + #endif diff --git a/bacnet-stack/src/abort.c b/bacnet-stack/src/abort.c index 381bdb56..c59bb26e 100644 --- a/bacnet-stack/src/abort.c +++ b/bacnet-stack/src/abort.c @@ -97,6 +97,7 @@ int abort_encode_apdu( return apdu_len; } +#if !BACNET_SVC_SERVER /* decode the service request only */ int abort_decode_service_request( uint8_t * apdu, @@ -115,6 +116,7 @@ int abort_decode_service_request( return len; } +#endif #ifdef TEST #include diff --git a/bacnet-stack/src/bacapp.c b/bacnet-stack/src/bacapp.c index 3376ec57..51619c49 100644 --- a/bacnet-stack/src/bacapp.c +++ b/bacnet-stack/src/bacapp.c @@ -49,6 +49,10 @@ /** @file bacapp.c Utilities for the BACnet_Application_Data_Value */ +#if defined(_MSC_VER) +#define snprintf _snprintf +#endif + int bacapp_encode_application_data( uint8_t * apdu, BACNET_APPLICATION_DATA_VALUE * value) diff --git a/bacnet-stack/src/bacdcode.c b/bacnet-stack/src/bacdcode.c index aec57507..571f757a 100644 --- a/bacnet-stack/src/bacdcode.c +++ b/bacnet-stack/src/bacdcode.c @@ -866,6 +866,8 @@ int encode_application_object_id( return len; } +#if BACNET_USE_OCTETSTRING + /* from clause 20.2.8 Encoding of an Octet String Value */ /* returns the number of apdu bytes consumed */ int encode_octet_string( @@ -981,6 +983,7 @@ int decode_context_octet_string( return len; } +#endif /* from clause 20.2.9 Encoding of a Character String Value */ /* returns the number of apdu bytes consumed */ @@ -1305,6 +1308,7 @@ int encode_context_enumerated( return len; } +#if BACNET_USE_SIGNED /* from clause 20.2.5 Encoding of a Signed Integer Value */ /* and 20.2.1 General Rules for Encoding BACnet Tags */ /* returns the number of apdu bytes consumed */ @@ -1425,6 +1429,7 @@ int encode_context_signed( return len; } +#endif /* from clause 20.2.6 Encoding of a Real Number Value */ /* and 20.2.1 General Rules for Encoding BACnet Tags */ @@ -1457,6 +1462,7 @@ int encode_context_real( return len; } +#if BACNET_USE_DOUBLE /* from clause 20.2.7 Encoding of a Double Precision Real Number Value */ /* and 20.2.1 General Rules for Encoding BACnet Tags */ /* returns the number of apdu bytes consumed */ @@ -1489,6 +1495,7 @@ int encode_context_double( return len; } +#endif /* from clause 20.2.13 Encoding of a Time Value */ /* and 20.2.1 General Rules for Encoding BACnet Tags */ diff --git a/bacnet-stack/src/bacerror.c b/bacnet-stack/src/bacerror.c index a918a90c..ad05321c 100644 --- a/bacnet-stack/src/bacerror.c +++ b/bacnet-stack/src/bacerror.c @@ -63,6 +63,7 @@ int bacerror_encode_apdu( return apdu_len; } +#if !BACNET_SVC_SERVER /* decode the application class and code */ int bacerror_decode_error_class_and_code( uint8_t * apdu, @@ -123,6 +124,7 @@ int bacerror_decode_service_request( return len; } +#endif #ifdef TEST #include diff --git a/bacnet-stack/src/bacint.c b/bacnet-stack/src/bacint.c index bfb4ec5a..32018b1d 100644 --- a/bacnet-stack/src/bacint.c +++ b/bacnet-stack/src/bacint.c @@ -113,6 +113,7 @@ int decode_unsigned32( return 4; } +#if BACNET_USE_SIGNED int encode_signed8( uint8_t * apdu, int8_t value) @@ -219,7 +220,7 @@ int decode_signed32( return 4; } - +#endif /* end of decoding_encoding.c */ #ifdef TEST #include diff --git a/bacnet-stack/src/bacreal.c b/bacnet-stack/src/bacreal.c index e6e44bb9..87cd2006 100644 --- a/bacnet-stack/src/bacreal.c +++ b/bacnet-stack/src/bacreal.c @@ -138,6 +138,8 @@ int encode_bacnet_real( return 4; } +#if BACNET_USE_DOUBLE + /* from clause 20.2.7 Encoding of a Double Precision Real Number Value */ /* returns the number of apdu bytes consumed */ int decode_double( @@ -241,6 +243,7 @@ int decode_context_double( } return len; } +#endif /* end of decoding_encoding.c */ #ifdef TEST diff --git a/bacnet-stack/src/bacstr.c b/bacnet-stack/src/bacstr.c index 0aade918..acae817b 100644 --- a/bacnet-stack/src/bacstr.c +++ b/bacnet-stack/src/bacstr.c @@ -615,6 +615,7 @@ bool characterstring_valid( return valid; } +#if BACNET_USE_OCTETSTRING /* returns false if the string exceeds capacity initialize by using value=NULL */ bool octetstring_init( @@ -799,6 +800,7 @@ bool octetstring_value_same( return false; } +#endif #ifdef TEST #include diff --git a/bacnet-stack/src/dcc.c b/bacnet-stack/src/dcc.c index 965b0f5d..39310cf5 100644 --- a/bacnet-stack/src/dcc.c +++ b/bacnet-stack/src/dcc.c @@ -124,7 +124,7 @@ bool dcc_set_status_duration( return valid; } - +#if BACNET_SVC_DCC_A /* encode service */ int dcc_encode_apdu( uint8_t * apdu, @@ -161,6 +161,7 @@ int dcc_encode_apdu( return apdu_len; } +#endif /* decode the service request only */ int dcc_decode_service_request( diff --git a/bacnet-stack/src/ihave.c b/bacnet-stack/src/ihave.c index 665d5212..724e7532 100644 --- a/bacnet-stack/src/ihave.c +++ b/bacnet-stack/src/ihave.c @@ -70,6 +70,8 @@ int ihave_encode_apdu( return apdu_len; } +#if BACNET_SVC_I_HAVE_A + /* decode the service request only */ int ihave_decode_service_request( uint8_t * apdu, @@ -135,6 +137,7 @@ int ihave_decode_apdu( return len; } +#endif #ifdef TEST #include diff --git a/bacnet-stack/src/memcopy.c b/bacnet-stack/src/memcopy.c index e507a008..8da372a3 100644 --- a/bacnet-stack/src/memcopy.c +++ b/bacnet-stack/src/memcopy.c @@ -33,6 +33,7 @@ ####COPYRIGHTEND####*/ #include #include "memcopy.h" +#include /** @file memcopy.c Custom memcopy function */ @@ -45,20 +46,22 @@ size_t memcopy( size_t len, /* amount of data to copy */ size_t max) { /* total size of destination */ - size_t i; - size_t copy_len = 0; - char *s1, *s2; +// size_t i; +// size_t copy_len = 0; +// char *s1, *s2; - s1 = dest; - s2 = src; +// s1 = dest; +// s2 = src; if (len <= (max - offset)) { - for (i = 0; i < len; i++) { - s1[offset + i] = s2[i]; - copy_len++; - } + memcpy(&((char *)dest)[offset], src, len); + return(len); +// for (i = 0; i < len; i++) { +// s1[offset + i] = s2[i]; +// copy_len++; +// } } - return copy_len; + return 0; } #ifdef TEST diff --git a/bacnet-stack/src/rd.c b/bacnet-stack/src/rd.c index 73f8db74..19b36cb1 100644 --- a/bacnet-stack/src/rd.c +++ b/bacnet-stack/src/rd.c @@ -38,7 +38,7 @@ #include "rd.h" /** @file rd.c Encode/Decode Reinitialize Device APDUs */ - +#if BACNET_SVC_RD_A /* encode service */ int rd_encode_apdu( uint8_t * apdu, @@ -68,6 +68,7 @@ int rd_encode_apdu( return apdu_len; } +#endif /* decode the service request only */ int rd_decode_service_request( diff --git a/bacnet-stack/src/reject.c b/bacnet-stack/src/reject.c index 163e0bea..1aea4d0b 100644 --- a/bacnet-stack/src/reject.c +++ b/bacnet-stack/src/reject.c @@ -110,6 +110,7 @@ int reject_encode_apdu( return apdu_len; } +#if !BACNET_SVC_SERVER /* decode the service request only */ int reject_decode_service_request( uint8_t * apdu, @@ -128,6 +129,7 @@ int reject_decode_service_request( return len; } +#endif #ifdef TEST #include diff --git a/bacnet-stack/src/rp.c b/bacnet-stack/src/rp.c index e00b0e1a..65a98fde 100644 --- a/bacnet-stack/src/rp.c +++ b/bacnet-stack/src/rp.c @@ -39,6 +39,7 @@ /** @file rp.c Encode/Decode Read Property and RP ACKs */ +#if BACNET_SVC_RP_A /* encode service */ int rp_encode_apdu( uint8_t * apdu, @@ -73,6 +74,7 @@ int rp_encode_apdu( return apdu_len; } +#endif /* decode the service request only */ int rp_decode_service_request( @@ -213,6 +215,7 @@ int rp_ack_encode_apdu( } +#if BACNET_SVC_RP_A /** Decode the ReadProperty reply and store the result for one Property in a * BACNET_READ_PROPERTY_DATA structure. * This leaves the value(s) in the application_data buffer to be decoded later; @@ -275,6 +278,7 @@ int rp_ack_decode_service_request( return len; } +#endif #ifdef TEST #include diff --git a/bacnet-stack/src/rpm.c b/bacnet-stack/src/rpm.c index 3c644ad3..dfdf0003 100644 --- a/bacnet-stack/src/rpm.c +++ b/bacnet-stack/src/rpm.c @@ -42,6 +42,7 @@ /** @file rpm.c Encode/Decode Read Property Multiple and RPM ACKs */ +#if BACNET_SVC_RPM_A /* encode the initial portion of the service */ int rpm_encode_apdu_init( uint8_t * apdu, @@ -199,6 +200,8 @@ int rpm_encode_apdu( return apdu_len; } +#endif + /* decode the object portion of the service request only. Bails out if * tags are wrong or missing/incomplete */ @@ -379,8 +382,12 @@ int rpm_ack_encode_apdu_object_property_value( if (apdu) { /* Tag 4: propertyValue */ apdu_len += encode_opening_tag(&apdu[apdu_len], 4); - for (len = 0; len < application_data_len; len++) { - apdu[apdu_len++] = application_data[len]; + if (application_data == &apdu[apdu_len]) { /* Is Data already in place? */ + apdu_len += application_data_len; /* Yes, step over data */ + } else { /* No, copy data in */ + for (len = 0; len < application_data_len; len++) { + apdu[apdu_len++] = application_data[len]; + } } apdu_len += encode_closing_tag(&apdu[apdu_len], 4); } @@ -419,6 +426,8 @@ int rpm_ack_encode_apdu_object_end( return apdu_len; } +#if BACNET_SVC_RPM_A + /* decode the object portion of the service request only */ int rpm_ack_decode_object_id( uint8_t * apdu, @@ -509,6 +518,8 @@ int rpm_ack_decode_object_property( return (int) len; } +#endif + #ifdef TEST #include #include diff --git a/bacnet-stack/src/timesync.c b/bacnet-stack/src/timesync.c index c6f66622..04deacd1 100644 --- a/bacnet-stack/src/timesync.c +++ b/bacnet-stack/src/timesync.c @@ -39,7 +39,7 @@ #include "timesync.h" /** @file timesync.c Encode/Decode TimeSync APDUs */ - +#if BACNET_SVC_TS_A /* encode service */ int timesync_encode_apdu_service( uint8_t * apdu, @@ -80,6 +80,7 @@ int timesync_encode_apdu( return timesync_encode_apdu_service(apdu, SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION, my_date, my_time); } +#endif /* decode the service request only */ int timesync_decode_service_request( diff --git a/bacnet-stack/src/wp.c b/bacnet-stack/src/wp.c index 2c9c033f..1109ecfa 100644 --- a/bacnet-stack/src/wp.c +++ b/bacnet-stack/src/wp.c @@ -38,7 +38,7 @@ #include "wp.h" /** @file wp.c Encode/Decode BACnet Write Property APDUs */ - +#if BACNET_SVC_WP_A /* encode service */ int wp_encode_apdu( uint8_t * apdu, @@ -88,6 +88,7 @@ int wp_encode_apdu( return apdu_len; } +#endif /* decode the service request only */ /* FIXME: there could be various error messages returned