/************************************************************************** * * Copyright (c) 2020-2025 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file Utilities.c * * @author (last) Sean Nash * @date (last) 07-Oct-2023 * * @author (original) Sean * @date (original) 17-Feb-2020 * ***************************************************************************/ #include // For memcpy #include "Common.h" #include "FPGA.h" #include "Timers.h" #include "Utilities.h" /** * @addtogroup Utilities * @{ */ // ********** private definitions ********** #define INITIAL_CRC16_VAL 0xFFFF ///< Seed for 16-bit CRC function. #define INITIAL_CRC08_VAL 0x00 ///< Seed for 8-bit CRC function. #define HEX_LETTER_TO_NUMBER_CONV 0x37 ///< Hex letter (i.e. A) to number conversion. #define STR_TO_HEX_CONV_MAX_BYTES 8 ///< String to hex conversion maximum allowed bytes. #define SEMAPHORE_IN_USE_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Taken semaphore timeout in milliseconds. // ********** private data ********** /// Semaphore data structure typedef struct { U32 semaphoreStartTimeMS; ///< Semaphore start time in milliseconds. volatile BOOL isSemaphoreTaken; ///< Flag to indicate whether the semaphore is taken or not. } SEMAPHORE_STATUS_T; /// CRC-32 look-up table. const U32 CRC32_TABLE[] = { 0x00000000, 0x1EDC6F41, 0x3DB8DE82, 0x2364B1C3, 0x7B71BD04, 0x65ADD245, 0x46C96386, 0x58150CC7, 0xF6E37A08, 0xE83F1549, 0xCB5BA48A, 0xD587CBCB, 0x8D92C70C, 0x934EA84D, 0xB02A198E, 0xAEF676CF, 0xF31A9B51, 0xEDC6F410, 0xCEA245D3, 0xD07E2A92, 0x886B2655, 0x96B74914, 0xB5D3F8D7, 0xAB0F9796, 0x05F9E159, 0x1B258E18, 0x38413FDB, 0x269D509A, 0x7E885C5D, 0x6054331C, 0x433082DF, 0x5DECED9E, 0xF8E959E3, 0xE63536A2, 0xC5518761, 0xDB8DE820, 0x8398E4E7, 0x9D448BA6, 0xBE203A65, 0xA0FC5524, 0x0E0A23EB, 0x10D64CAA, 0x33B2FD69, 0x2D6E9228, 0x757B9EEF, 0x6BA7F1AE, 0x48C3406D, 0x561F2F2C, 0x0BF3C2B2, 0x152FADF3, 0x364B1C30, 0x28977371, 0x70827FB6, 0x6E5E10F7, 0x4D3AA134, 0x53E6CE75, 0xFD10B8BA, 0xE3CCD7FB, 0xC0A86638, 0xDE740979, 0x866105BE, 0x98BD6AFF, 0xBBD9DB3C, 0xA505B47D, 0xEF0EDC87, 0xF1D2B3C6, 0xD2B60205, 0xCC6A6D44, 0x947F6183, 0x8AA30EC2, 0xA9C7BF01, 0xB71BD040, 0x19EDA68F, 0x0731C9CE, 0x2455780D, 0x3A89174C, 0x629C1B8B, 0x7C4074CA, 0x5F24C509, 0x41F8AA48, 0x1C1447D6, 0x02C82897, 0x21AC9954, 0x3F70F615, 0x6765FAD2, 0x79B99593, 0x5ADD2450, 0x44014B11, 0xEAF73DDE, 0xF42B529F, 0xD74FE35C, 0xC9938C1D, 0x918680DA, 0x8F5AEF9B, 0xAC3E5E58, 0xB2E23119, 0x17E78564, 0x093BEA25, 0x2A5F5BE6, 0x348334A7, 0x6C963860, 0x724A5721, 0x512EE6E2, 0x4FF289A3, 0xE104FF6C, 0xFFD8902D, 0xDCBC21EE, 0xC2604EAF, 0x9A754268, 0x84A92D29, 0xA7CD9CEA, 0xB911F3AB, 0xE4FD1E35, 0xFA217174, 0xD945C0B7, 0xC799AFF6, 0x9F8CA331, 0x8150CC70, 0xA2347DB3, 0xBCE812F2, 0x121E643D, 0x0CC20B7C, 0x2FA6BABF, 0x317AD5FE, 0x696FD939, 0x77B3B678, 0x54D707BB, 0x4A0B68FA, 0xC0C1D64F, 0xDE1DB90E, 0xFD7908CD, 0xE3A5678C, 0xBBB06B4B, 0xA56C040A, 0x8608B5C9, 0x98D4DA88, 0x3622AC47, 0x28FEC306, 0x0B9A72C5, 0x15461D84, 0x4D531143, 0x538F7E02, 0x70EBCFC1, 0x6E37A080, 0x33DB4D1E, 0x2D07225F, 0x0E63939C, 0x10BFFCDD, 0x48AAF01A, 0x56769F5B, 0x75122E98, 0x6BCE41D9, 0xC5383716, 0xDBE45857, 0xF880E994, 0xE65C86D5, 0xBE498A12, 0xA095E553, 0x83F15490, 0x9D2D3BD1, 0x38288FAC, 0x26F4E0ED, 0x0590512E, 0x1B4C3E6F, 0x435932A8, 0x5D855DE9, 0x7EE1EC2A, 0x603D836B, 0xCECBF5A4, 0xD0179AE5, 0xF3732B26, 0xEDAF4467, 0xB5BA48A0, 0xAB6627E1, 0x88029622, 0x96DEF963, 0xCB3214FD, 0xD5EE7BBC, 0xF68ACA7F, 0xE856A53E, 0xB043A9F9, 0xAE9FC6B8, 0x8DFB777B, 0x9327183A, 0x3DD16EF5, 0x230D01B4, 0x0069B077, 0x1EB5DF36, 0x46A0D3F1, 0x587CBCB0, 0x7B180D73, 0x65C46232, 0x2FCF0AC8, 0x31136589, 0x1277D44A, 0x0CABBB0B, 0x54BEB7CC, 0x4A62D88D, 0x6906694E, 0x77DA060F, 0xD92C70C0, 0xC7F01F81, 0xE494AE42, 0xFA48C103, 0xA25DCDC4, 0xBC81A285, 0x9FE51346, 0x81397C07, 0xDCD59199, 0xC209FED8, 0xE16D4F1B, 0xFFB1205A, 0xA7A42C9D, 0xB97843DC, 0x9A1CF21F, 0x84C09D5E, 0x2A36EB91, 0x34EA84D0, 0x178E3513, 0x09525A52, 0x51475695, 0x4F9B39D4, 0x6CFF8817, 0x7223E756, 0xD726532B, 0xC9FA3C6A, 0xEA9E8DA9, 0xF442E2E8, 0xAC57EE2F, 0xB28B816E, 0x91EF30AD, 0x8F335FEC, 0x21C52923, 0x3F194662, 0x1C7DF7A1, 0x02A198E0, 0x5AB49427, 0x4468FB66, 0x670C4AA5, 0x79D025E4, 0x243CC87A, 0x3AE0A73B, 0x198416F8, 0x075879B9, 0x5F4D757E, 0x41911A3F, 0x62F5ABFC, 0x7C29C4BD, 0xD2DFB272, 0xCC03DD33, 0xEF676CF0, 0xF1BB03B1, 0xA9AE0F76, 0xB7726037, 0x9416D1F4, 0x8ACABEB5, }; /// CRC-16 look-up table. const U16 CRC16_TABLE[] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; /// CRC-8 look-up table. const U08 CRC8_TABLE[] = { 0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46, 67, 114, 33, 16, 135, 182, 229, 212, 250, 203, 152, 169, 62, 15, 92, 109, 134, 183, 228, 213, 66, 115, 32, 17, 63, 14, 93, 108, 251, 202, 153, 168, 197, 244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47, 184, 137, 218, 235, 61, 12, 95, 110, 249, 200, 155, 170, 132, 181, 230, 215, 64, 113, 34, 19, 126, 79, 28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80, 187, 138, 217, 232, 127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149, 248, 201, 154, 171, 60, 13, 94, 111, 65, 112, 35, 18, 133, 180, 231, 214, 122, 75, 24, 41, 190, 143, 220, 237, 195, 242, 161, 144, 7, 54, 101, 84, 57, 8, 91, 106, 253, 204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23, 252, 205, 158, 175, 56, 9, 90, 107, 69, 116, 39, 22, 129, 176, 227, 210, 191, 142, 221, 236, 123, 74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145, 71, 118, 37, 20, 131, 178, 225, 208, 254, 207, 156, 173, 58, 11, 88, 105, 4, 53, 102, 87, 192, 241, 162, 147, 189, 140, 223, 238, 121, 72, 27, 42, 193, 240, 163, 146, 5, 52, 103, 86, 120, 73, 26, 43, 188, 141, 222, 239, 130, 179, 224, 209, 70, 119, 36, 21, 59, 10, 89, 104, 255, 206, 157, 172 }; // variables for time windowed counts (counts # of instances in a specific window of time) static BOOL timeWindowedCountsInitialized[ NUM_OF_TIME_WINDOWED_COUNTS ]; ///< Initialized flags for time windowed counts static U32 timeWindowedCountsMaxCount[ NUM_OF_TIME_WINDOWED_COUNTS ]; ///< Max. counts for time windowed counts static U32 timeWindowedCountsWindowMs[ NUM_OF_TIME_WINDOWED_COUNTS ]; ///< Time windows (in ms) for time windowed counts static U32 timeWindowedCounts[ NUM_OF_TIME_WINDOWED_COUNTS ][ MAX_TIME_WINDOWED_COUNT ]; ///< Time stamps for instances for time windowed counts static U32 timeWindowedCountIndexes[ NUM_OF_TIME_WINDOWED_COUNTS ]; ///< List indexes for time windowed counts static U32 timeWindowedCountCounts[ NUM_OF_TIME_WINDOWED_COUNTS ]; ///< Current counts for time windowed counts static SEMAPHORE_STATUS_T sempahoreStatus[ NUM_OF_SEMAPHORES ]; /*********************************************************************//** * @brief * The crc32 function calculates a 32-bit CRC for a given range of bytes * in memory. Poly = 0x1EDC6F41. Not reflected. Initial value = 0x00000000. * @details Inputs: CRC32_TABLE[] * @details Outputs: none * @param initialValue initial CRC seed value * @param address pointer to start address of memory range to calculate CRC for * @param len number of bytes in the memory range to calculate CRC for * @return CRC as a U32 *************************************************************************/ U32 crc32( U32 const initialValue, const U08 *address, U32 len ) { U32 crc = initialValue; while ( len-- > 0 ) { crc = ( crc << SHIFT_8_BITS_FOR_BYTE_SHIFT ) ^ CRC32_TABLE[ *address ^ ( crc >> SHIFT_24_BITS ) ]; address++; } return crc; } /*********************************************************************//** * @brief * The crc16 function calculates a 16-bit CRC for a given range of bytes * in memory. Poly = 0x1021. Not reflected. Initial value = 0xFFFF. * @details Inputs: CRC16_TABLE[] * @details Outputs: none * @param address pointer to start address of memory range to calculate CRC for * @param len number of bytes in the memory range to calculate CRC for * @return CRC as a U16 *************************************************************************/ U16 crc16( const U08 *address, U32 len ) { U16 crc = INITIAL_CRC16_VAL; while ( len-- > 0 ) { crc = ( crc << SHIFT_8_BITS_FOR_BYTE_SHIFT ) ^ CRC16_TABLE[ *address ^ ( ( crc >> SHIFT_8_BITS_FOR_BYTE_SHIFT ) & MASK_OFF_MSB ) ]; address++; } return crc; } /*********************************************************************//** * @brief * The crc8 function calculates a 8-bit CRC for a given range of bytes * in memory. * @details Inputs: CRC8_TABLE[] * @details Outputs: none * @param address pointer to start address of memory range to calculate CRC for * @param len number of bytes in the memory range to calculate CRC for * @return CRC as a U08 *************************************************************************/ U08 crc8( const U08 *address, U32 len ) { U08 crc = INITIAL_CRC08_VAL; while ( len-- > 0 ) { crc = CRC8_TABLE[ (*address) ^ crc ]; address++; } return crc; } /*********************************************************************//** * @brief * The crc4 function calculates a 4-bit CRC for a given range of bytes * in memory. * @details Inputs: none * @details Outputs: none * @param buffer pointer to start address of memory range to calculate CRC for * @param byteCount number of bytes in the memory range to calculate CRC for * @return CRC as a U08 *************************************************************************/ U08 crc4( U16* buffer, U32 byteCount ) { U32 count; U08 nBit; U32 nRem = 0; for ( count = 0; count < byteCount; count++ ) { if ( 1 == ( count % 2 ) ) { nRem ^= (U16)( buffer[ count >> 1 ] & MASK_OFF_MSB ); } else { nRem ^= (U16)( buffer[ count >> 1 ] >> SHIFT_8_BITS_FOR_BYTE_SHIFT ); } for ( nBit = SHIFT_8_BITS_FOR_BYTE_SHIFT; nBit > 0; nBit-- ) { if ( nRem & 0x8000 ) { nRem = ( nRem << 1 ) ^ 0x3000; } else { nRem = ( nRem << 1 ); } } } nRem = ( 0x000F & ( nRem >> 12 ) ); return ( nRem ^ 0x00 ); } /*********************************************************************//** * @brief * The u32DiffWithWrap function calculates the difference between two given * unsigned 32-bit numbers. If the second (ending) number is less than the * first (starting) number, then the difference is calculated with a wrap past * 32-bit full scale to zero. * @details Inputs: none * @details Outputs: none * @param start first number to compute difference for * @param end second number to compute difference for * @return the difference between the two given numbers *************************************************************************/ U32 u32DiffWithWrap( U32 start, U32 end ) { U32 result = ( end >= start ? end - start : ( HEX_32_BIT_FULL_SCALE - start ) + end + 1 ); return result; } /*********************************************************************//** * @brief * The u16BiDiffWithWrap function calculates the difference between two given * unsigned 16-bit numbers. This version of function returns a signed value * to allow for a negative difference. * @details Inputs: none * @details Outputs: none * @param start first number to compute difference for * @param end second number to compute difference for * @return the difference between the two given numbers *************************************************************************/ S32 u32BiDiffWithWrap( U32 start, U32 end ) { S32 result; U32 incDelta = ( end >= start ? end - start : ( HEX_32_BIT_FULL_SCALE - start ) + end + 1 ); U32 decDelta = HEX_32_BIT_FULL_SCALE - incDelta + 1; if ( incDelta < decDelta ) { result = (S32)incDelta; } else { result = (S32)decDelta * -1; } return result; } /*********************************************************************//** * @brief * The u16DiffWithWrap function calculates the difference between two given * unsigned 16-bit numbers. If the second (ending) number is less than the * first (starting) number, then the difference is calculated with a wrap past * 16-bit full scale to zero. * @details Inputs: none * @details Outputs: none * @param start first number to compute difference for * @param end second number to compute difference for * @return the difference between the two given numbers *************************************************************************/ U16 u16DiffWithWrap( U16 start, U16 end ) { U16 result = ( end >= start ? end - start : ( HEX_64_K - start ) + end ); return result; } /*********************************************************************//** * @brief * The u16BiDiffWithWrap function calculates the difference between two given * unsigned 16-bit numbers. This version of function returns a signed value * to allow for a negative difference. * @details Inputs: none * @details Outputs: none * @param start first number to compute difference for * @param end second number to compute difference for * @return the difference between the two given numbers *************************************************************************/ S16 u16BiDiffWithWrap( U16 start, U16 end ) { S16 result; U16 incDelta = ( end >= start ? end - start : ( HEX_64_K - start ) + end ); U16 decDelta = HEX_64_K - incDelta; if ( incDelta < decDelta ) { result = (S16)incDelta; } else { result = (S16)decDelta * -1; } return result; } /*********************************************************************//** * @brief * The initTimeWindowedCount function initializes a given time windowed count. * @details Inputs: timeWindowedCountsMaxCount, timeWindowedCountsInitialized * @details Outputs: timeWindowedCountsMaxCount, timeWindowedCountsInitialized, alarm if * software fault occurred * @param cnt ID of the time windowed count to initialize * @param maxCnt maximum number of instances in the time window for this count * @param winMs number of ms in the time window for this count * @return none *************************************************************************/ void initTimeWindowedCount( TIME_WINDOWED_COUNT_T cnt, U32 maxCnt, U32 winMs ) { if ( ( cnt < NUM_OF_TIME_WINDOWED_COUNTS ) && ( maxCnt <= MAX_TIME_WINDOWED_COUNT ) ) { U32 i; // initialize a time windowed count timeWindowedCountsMaxCount[ cnt ] = maxCnt; timeWindowedCountsWindowMs[ cnt ] = winMs; timeWindowedCountIndexes[ cnt ] = 0; timeWindowedCountCounts[ cnt ] = 0; for ( i = 0; i < MAX_TIME_WINDOWED_COUNT; i++ ) { timeWindowedCounts[ cnt ][ i ] = 0; } timeWindowedCountsInitialized[ cnt ] = TRUE; } else { if ( cnt < NUM_OF_TIME_WINDOWED_COUNTS ) { timeWindowedCountsInitialized[ cnt ] = FALSE; #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_INVALID_WIN_MAX_COUNT, maxCnt ) #else SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_INVALID_WIN_MAX_COUNT, maxCnt ) #endif } else { #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_INVALID_WIN_COUNT, cnt ) #else SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_INVALID_WIN_COUNT, cnt ) #endif } } } /*********************************************************************//** * @brief * The incTimeWindowedCount function adds a new instance to a given time * windowed count. Must call initTimeWindowedCount() prior to calling this * function for a given time windowed count. * *Note - thread protection not provided - assumed function will be called * by one task for a given time windowed count. * @details Inputs: timeWindowedCounts, timeWindowedCountIndexes, timeWindowedCountCounts * @details Outputs: timeWindowedCounts, timeWindowedCountIndexes, timeWindowedCountCounts, * alarm if a software fault occurred * @param cnt ID of the time windowed count to add an instance to * @return TRUE if this instances brings the count to the maximum within * this counts time window, otherwise FALSE *************************************************************************/ BOOL incTimeWindowedCount( TIME_WINDOWED_COUNT_T cnt ) { BOOL result = FALSE; U32 timeInMS; if ( ( cnt < NUM_OF_TIME_WINDOWED_COUNTS ) && ( TRUE == timeWindowedCountsInitialized[ cnt ] ) ) { // Replace timestamp of oldest instance in list with this new one timeWindowedCounts[ cnt ][ timeWindowedCountIndexes[ cnt ] ] = getMSTimerCount(); // move index to next position in list (may wrap) timeWindowedCountIndexes[ cnt ] = INC_WRAP( timeWindowedCountIndexes[ cnt ], 0, timeWindowedCountsMaxCount[ cnt ] - 1 ); // update list count timeWindowedCountCounts[ cnt ] = INC_CAP( timeWindowedCountCounts[ cnt ], timeWindowedCountsMaxCount[ cnt ] ); // check if too many instances within time window timeInMS = calcTimeSince( timeWindowedCounts[ cnt ][ timeWindowedCountIndexes[ cnt ] ] ); if ( ( timeWindowedCountCounts[ cnt ] >= timeWindowedCountsMaxCount[ cnt ] ) && ( timeInMS <= timeWindowedCountsWindowMs[ cnt ] ) ) { result = TRUE; } } else { #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_TIME_WINDOWED_COUNT_ERROR, cnt ); #else SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_UTIL_TIME_WINDOWED_COUNT_ERROR, cnt ); #endif } return result; } /*********************************************************************//** * @brief * The getCriticalData function gets the value for a given critical data * record. The integrity of the critical data is checked first. If the * critical data record fails the integrity check, a fault is triggered. * @details Inputs: none * @details Outputs: alarm if HD critical error occurred * @param data Ptr to a critical data record * @return The data from a critical data record *************************************************************************/ CRITICAL_DATAS_T getCriticalData( CRITICAL_DATA_T *data ) { CRITICAL_DATAS_T result; CRITICAL_DATA_T d; _disable_IRQ(); d = *data; _enable_IRQ(); result = d.data; // verify data integrity if ( ( ~d.data.uInt != d.comp ) || ( isCriticalDataInRange( &d ) != TRUE ) || ( d.set != TRUE ) || ( data->typ >= NUM_OF_CRITICAL_DATA_TYPES ) ) { result.uInt = 0; #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_CRITICAL_DATA_ERROR, (U32)&data[0], 0 ) #else SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_CRITICAL_DATA_ERROR, (U32)&data[0], 0 ) #endif } return result; } /*********************************************************************//** * @brief * The isCriticalDataInRange function determines whether a critical data * value is within the range set for that critical data. * @details Inputs: none * @details Outputs: none * @param data Ptr to a critical data record * @return TRUE if given data is in range, FALSE if not *************************************************************************/ BOOL isCriticalDataInRange( CRITICAL_DATA_T *data ) { BOOL result = FALSE; if ( CRITICAL_DATA_TYPE_F32 == data->typ ) { if ( ( data->data.sFlt >= data->minimum.sFlt ) && ( data->data.sFlt <= data->maximum.sFlt ) ) { result = TRUE; } } else if ( CRITICAL_DATA_TYPE_S32 == data->typ ) { if ( ( data->data.sInt >= data->minimum.sInt ) && ( data->data.sInt <= data->maximum.sInt ) ) { result = TRUE; } } else { if ( ( data->data.uInt >= data->minimum.uInt ) && ( data->data.uInt <= data->maximum.uInt ) ) { result = TRUE; } } return result; } /*********************************************************************//** * @brief * The setCriticalData function sets the value for a given critical data * record. * @details Inputs: none * @details Outputs: alarm if HD critical error occurred * @param data Ptr to a critical data record * @param value a value to set * @return TRUE if set was successful, FALSE if not (out of range) *************************************************************************/ BOOL setCriticalData( CRITICAL_DATA_T *data, CRITICAL_DATAS_T value ) { BOOL result = FALSE; if ( data->typ < NUM_OF_CRITICAL_DATA_TYPES ) { CRITICAL_DATA_T tmp = *data; // test set on temporary data record so it can have its range pre-checked tmp.data = value; if ( TRUE == isCriticalDataInRange( &tmp ) ) { _disable_IRQ(); data->data = value; data->comp = ~data->data.uInt; data->set = TRUE; _enable_IRQ(); result = TRUE; } } else { #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_CRITICAL_DATA_ERROR, (U32)&data[0], 1 ) #else SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_CRITICAL_DATA_ERROR, (U32)&data[0], 1 ) #endif } return result; } /*********************************************************************//** * @brief * The resetCriticalData function resets a critical data record. * @details Inputs: none * @details Outputs: Given critical data record is reset to unset w/ default value. * @param data Ptr to a critical data record * @return none *************************************************************************/ void resetCriticalData( CRITICAL_DATA_T *data ) { _disable_IRQ(); data->set = FALSE; data->data.uInt = data->defValue.uInt; data->comp = ~data->data.uInt; _enable_IRQ(); } /*********************************************************************//** * @brief * The hexStrToDec function convert hex string to decimal value. * @details Inputs: none * @details Outputs: none * @param valuePtr pointer to hex string to convert * @param convValuePtr pointer to the provided buffer to write the converted * values back * @param size size of the hex string to convert * @return TRUE if the characters were accepted, otherwise FALSE *************************************************************************/ BOOL hexStrToDec( U08 const * const valuePtr, U32* convValuePtr, U08 size ) { U08 ii; U08 value; U32 result = 0; BOOL status = TRUE; if ( size <= STR_TO_HEX_CONV_MAX_BYTES ) { // If the provided size is less than the maximum allowed, loop through the list for conversion for ( ii = 0; ii < size; ++ii ) { value = valuePtr[ ii ]; switch( value ) { case ASCII_CODE_NUMBER_ZERO: case ASCII_CODE_NUMBER_ONE: case ASCII_CODE_NUMBER_TWO: case ASCII_CODE_NUMBER_THREE: case ASCII_CODE_NUMBER_FOUR: case ASCII_CODE_NUMBER_FIVE: case ASCII_CODE_NUMBER_SIX: case ASCII_CODE_NUMBER_SEVEN: case ASCII_CODE_NUMBER_EIGHT: case ASCII_CODE_NUMBER_NINE: // If the hex string is a number, subtract the number from hex zero to get a number // Shift the results by a nibble and add the calculated number. // For instance, if the value = 0x36 - 0x30 = the value becomes 6 value = ( value - ASCII_CODE_NUMBER_ZERO ); result = ( result << SHIFT_BITS_BY_4 ) | value; break; case ASCII_CODE_LETTER_A: case ASCII_CODE_LETTER_B: case ASCII_CODE_LETTER_C: case ASCII_CODE_LETTER_D: case ASCII_CODE_LETTER_E: case ASCII_CODE_LETTER_F: // If the value is from A-F for the hex values, subtract the value from 0x37. // This converts the letters from A to F to 10 to 15. // For instance if the read value is 0x43 ( Hex C ) - 0x37 = 12 (decimal) value = ( value - HEX_LETTER_TO_NUMBER_CONV ); result = ( result << SHIFT_BITS_BY_4 ) | value; break; default: status = FALSE; // Do nothing since the character is not accepted. break; } } // Set the processed value to the provided buffer, but only if // the conversion was successful if (TRUE == status) { *convValuePtr = result; } } return status; } /*********************************************************************//** * @brief * The isCriticalDataSet function checks if the critical data has been set. * @details Inputs: none * @details Outputs: None * @param data Ptr to a critical data record * @return TRUE if critical data has been set, FALSE if not *************************************************************************/ BOOL isCriticalDataSet( CRITICAL_DATA_T *data ) { BOOL result = FALSE; CRITICAL_DATA_T d; _disable_IRQ(); d = *data; _enable_IRQ(); // verify data integrity if (( d.set != FALSE ) ) { result = TRUE; } return result; } /*********************************************************************//** * @brief * The initSemaphores function initializes the semaphores * @details Inputs: none * @details Outputs: sempahoreStatus * @return none *************************************************************************/ void initSemaphores( void ) { U08 i; for ( i = 0; i < NUM_OF_SEMAPHORES; i++ ) { memset( &sempahoreStatus[ i ], 0x0, sizeof( SEMAPHORE_STATUS_T ) ); } } /*********************************************************************//** * @brief * The getSemaphore function gets a semaphore for the requested semaphore. * @details Inputs: none * @details Outputs: sempahoreStatus * @param s which is the semaphore to be taken * @return TRUE if semaphore is available and now it is taken otherwise, FALSE *************************************************************************/ BOOL getSemaphore( SEMAPHORE_T s ) { BOOL result = FALSE; _disable_IRQ(); if ( FALSE == sempahoreStatus[ s ].isSemaphoreTaken ) { sempahoreStatus[ s ].semaphoreStartTimeMS = getMSTimerCount(); sempahoreStatus[ s ].isSemaphoreTaken = TRUE; result = TRUE; } else if ( TRUE == didTimeout( sempahoreStatus[ s ].semaphoreStartTimeMS, SEMAPHORE_IN_USE_TIMEOUT_MS ) ) { #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_SEMAPHORE_IN_USE_TIMEOUT, (U32)s ) #endif #ifdef _HD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_SEMAPHORE_IN_USE_TIMEOUT, (U32)s ) #endif } _enable_IRQ(); return result; } /*********************************************************************//** * @brief * The releaseSemaphore function releases a semaphore that was previously taken * for a job. * @details Inputs: none * @details Outputs: sempahoreStatus * @param s which is the semaphore to be released * @return none *************************************************************************/ void releaseSemaphore( SEMAPHORE_T s ) { if ( TRUE == sempahoreStatus[ s ].isSemaphoreTaken ) { sempahoreStatus[ s ].isSemaphoreTaken = FALSE; } } /*********************************************************************//** * @brief * The isSemaphoreReleased function returns the status of a taken semaphore * @details Inputs: none * @details Outputs: sempahoreStatus * @param s which is the semaphore to check * @return status of the semaphore *************************************************************************/ BOOL isSemaphoreReleased( SEMAPHORE_T s ) { return ( TRUE == sempahoreStatus[ s ].isSemaphoreTaken ? FALSE : TRUE ); } /**@}*/