/* ********************************************************************************************************* * uC/CPU * CPU CONFIGURATION & PORT LAYER * * Copyright 2004-2020 Silicon Laboratories Inc. www.silabs.com * * SPDX-License-Identifier: APACHE-2.0 * * This software is subject to an open source license and is distributed by * Silicon Laboratories Inc. pursuant to the terms of the Apache License, * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. * ********************************************************************************************************* */ /* ********************************************************************************************************* * * CORE CPU MODULE * * Filename : cpu_core.c * Version : v1.32.00 ********************************************************************************************************* */ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #define MICRIUM_SOURCE #define CPU_CORE_MODULE #include "cpu_core.h" #if (CPU_CFG_CACHE_MGMT_EN == DEF_ENABLED) #include "cpu_cache.h" #endif /* ********************************************************************************************************* * LOCAL DEFINES ********************************************************************************************************* */ /* Pop cnt algorithm csts. */ #define CRC_UTIL_POPCNT_MASK01010101_32 0x55555555u #define CRC_UTIL_POPCNT_MASK00110011_32 0x33333333u #define CRC_UTIL_POPCNT_MASK00001111_32 0x0F0F0F0Fu #define CRC_UTIL_POPCNT_POWERSOF256_32 0x01010101u /* ********************************************************************************************************* * LOCAL CONSTANTS ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL DATA TYPES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL TABLES ********************************************************************************************************* */ /* ********************************************************************************************************* * CPU COUNT LEAD ZEROs LOOKUP TABLE * * Note(s) : (1) Index into bit pattern table determines the number of leading zeros in an 8-bit value : * * b07 b06 b05 b04 b03 b02 b01 b00 # Leading Zeros * --- --- --- --- --- --- --- --- --------------- * 1 x x x x x x x 0 * 0 1 x x x x x x 1 * 0 0 1 x x x x x 2 * 0 0 0 1 x x x x 3 * 0 0 0 0 1 x x x 4 * 0 0 0 0 0 1 x x 5 * 0 0 0 0 0 0 1 x 6 * 0 0 0 0 0 0 0 1 7 * 0 0 0 0 0 0 0 0 8 ********************************************************************************************************* */ #if (!(defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) || \ (CPU_CFG_DATA_SIZE_MAX > CPU_CFG_DATA_SIZE)) static const CPU_INT08U CPU_CntLeadZerosTbl[256] = { /* Data vals : */ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 8u, 7u, 6u, 6u, 5u, 5u, 5u, 5u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, /* 0x00 to 0x0F */ 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, /* 0x10 to 0x1F */ 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, /* 0x20 to 0x2F */ 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, /* 0x30 to 0x3F */ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x40 to 0x4F */ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x50 to 0x5F */ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x60 to 0x6F */ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x70 to 0x7F */ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0x80 to 0x8F */ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0x90 to 0x9F */ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xA0 to 0xAF */ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xB0 to 0xBF */ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xC0 to 0xCF */ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xD0 to 0xDF */ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xE0 to 0xEF */ 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u /* 0xF0 to 0xFF */ }; #endif /* ********************************************************************************************************* * LOCAL GLOBAL VARIABLES ********************************************************************************************************* */ CPU_INT32U const CPU_EndiannessTest = 0x12345678LU; /* Variable to test CPU endianness. */ /* ********************************************************************************************************* * LOCAL FUNCTION PROTOTYPES ********************************************************************************************************* */ #if (CPU_CFG_NAME_EN == DEF_ENABLED) /* ---------------- CPU NAME FNCTS ---------------- */ static void CPU_NameInit (void); #endif /* ----------------- CPU TS FNCTS ----------------- */ #if ((CPU_CFG_TS_EN == DEF_ENABLED) || \ (CPU_CFG_TS_TMR_EN == DEF_ENABLED)) static void CPU_TS_Init (void); #endif #ifdef CPU_CFG_INT_DIS_MEAS_EN /* ---------- CPU INT DIS TIME MEAS FNCTS --------- */ static void CPU_IntDisMeasInit (void); static CPU_TS_TMR CPU_IntDisMeasMaxCalc(CPU_TS_TMR time_tot_cnts); #endif /* ********************************************************************************************************* * LOCAL CONFIGURATION ERRORS ********************************************************************************************************* */ /* ********************************************************************************************************* * CPU_Init() * * Description : (1) Initialize CPU module : * * (a) Initialize CPU timestamps * (b) Initialize CPU interrupts disabled time measurements * (c) Initialize CPU host name * * * Argument(s) : none. * * Return(s) : none. * * Note(s) : (2) CPU_Init() MUST be called ... : * * (a) ONLY ONCE from a product's application; ... * (b) BEFORE product's application calls any core CPU module function(s) * * (3) The following initialization functions MUST be sequenced as follows : * * (a) CPU_TS_Init() SHOULD precede ALL calls to other CPU timestamp functions * * (b) CPU_IntDisMeasInit() SHOULD precede ALL calls to CPU_CRITICAL_ENTER()/CPU_CRITICAL_EXIT() * & other CPU interrupts disabled time measurement functions ********************************************************************************************************* */ void CPU_Init (void) { /* --------------------- INIT TS ---------------------- */ #if ((CPU_CFG_TS_EN == DEF_ENABLED) || \ (CPU_CFG_TS_TMR_EN == DEF_ENABLED)) CPU_TS_Init(); /* See Note #3a. */ #endif /* -------------- INIT INT DIS TIME MEAS -------------- */ #ifdef CPU_CFG_INT_DIS_MEAS_EN CPU_IntDisMeasInit(); /* See Note #3b. */ #endif /* ------------------ INIT CPU NAME ------------------- */ #if (CPU_CFG_NAME_EN == DEF_ENABLED) CPU_NameInit(); #endif #if (CPU_CFG_CACHE_MGMT_EN == DEF_ENABLED) CPU_Cache_Init(); #endif } /* ********************************************************************************************************* * CPU_SW_Exception() * * Description : Trap unrecoverable software exception. * * Argument(s) : none. * * Return(s) : none. * * Note(s) : (1) CPU_SW_Exception() deadlocks the current code execution -- whether multi-tasked/ * -processed/-threaded or single-threaded -- when the current code execution cannot * gracefully recover or report a fault or exception condition. * * See also 'cpu_core.h CPU_SW_EXCEPTION() Note #1'. ********************************************************************************************************* */ void CPU_SW_Exception (void) { for (;;) { ; } } /* ********************************************************************************************************* * CPU_NameClr() * * Description : Clear CPU Name. * * Argument(s) : none. * * Return(s) : none. * * Note(s) : none. ********************************************************************************************************* */ #if (CPU_CFG_NAME_EN == DEF_ENABLED) void CPU_NameClr (void) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); Mem_Clr((void *)&CPU_Name[0], (CPU_SIZE_T) CPU_CFG_NAME_SIZE); CPU_CRITICAL_EXIT(); } #endif /* ********************************************************************************************************* * CPU_NameGet() * * Description : Get CPU host name. * * Argument(s) : p_name Pointer to an ASCII character array that will receive the return CPU host * name ASCII string from this function (see Note #1). * * p_err Pointer to variable that will receive the return error code from this function : * * CPU_ERR_NONE CPU host name successfully returned. * CPU_ERR_NULL_PTR Argument 'p_name' passed a NULL pointer. * * Return(s) : none. * * Note(s) : (1) The size of the ASCII character array that will receive the return CPU host name * ASCII string : * * (a) MUST be greater than or equal to the current CPU host name's ASCII string * size including the terminating NULL character; * (b) SHOULD be greater than or equal to CPU_CFG_NAME_SIZE ********************************************************************************************************* */ #if (CPU_CFG_NAME_EN == DEF_ENABLED) void CPU_NameGet (CPU_CHAR *p_name, CPU_ERR *p_err) { CPU_SR_ALLOC(); if (p_err == (CPU_ERR *)0) { CPU_SW_EXCEPTION(;); } if (p_name == (CPU_CHAR *)0) { *p_err = CPU_ERR_NULL_PTR; return; } CPU_CRITICAL_ENTER(); (void)Str_Copy_N(p_name, &CPU_Name[0], CPU_CFG_NAME_SIZE); CPU_CRITICAL_EXIT(); *p_err = CPU_ERR_NONE; } #endif /* ********************************************************************************************************* * CPU_NameSet() * * Description : Set CPU host name. * * Argument(s) : p_name Pointer to CPU host name to set. * * p_err Pointer to variable that will receive the return error code from this function : * * CPU_ERR_NONE CPU host name successfully set. * CPU_ERR_NULL_PTR Argument 'p_name' passed a NULL pointer. * CPU_ERR_NAME_SIZE Invalid CPU host name size (see Note #1). * * Return(s) : none. * * Note(s) : (1) 'p_name' ASCII string size, including the terminating NULL character, MUST be less * than or equal to CPU_CFG_NAME_SIZE. ********************************************************************************************************* */ #if (CPU_CFG_NAME_EN == DEF_ENABLED) void CPU_NameSet (const CPU_CHAR *p_name, CPU_ERR *p_err) { CPU_SIZE_T len; CPU_SR_ALLOC(); if (p_err == (CPU_ERR *)0) { CPU_SW_EXCEPTION(;); } if (p_name == (const CPU_CHAR *)0) { *p_err = CPU_ERR_NULL_PTR; return; } len = Str_Len_N(p_name, CPU_CFG_NAME_SIZE); if (len < CPU_CFG_NAME_SIZE) { /* If cfg name len < max name size, ... */ CPU_CRITICAL_ENTER(); (void)Str_Copy_N(&CPU_Name[0], /* ... copy cfg name to CPU host name. */ p_name, CPU_CFG_NAME_SIZE); CPU_CRITICAL_EXIT(); *p_err = CPU_ERR_NONE; } else { *p_err = CPU_ERR_NAME_SIZE; } } #endif /* ********************************************************************************************************* * CPU_TS_Get32() * * Description : Get current 32-bit CPU timestamp. * * Argument(s) : none. * * Return(s) : Current 32-bit CPU timestamp (in timestamp timer counts). * * Note(s) : (1) When applicable, the amount of time measured by CPU timestamps is calculated by * either of the following equations : * * (a) Time measured = Number timer counts * Timer period * * where * * Number timer counts Number of timer counts measured * Timer period Timer's period in some units of * (fractional) seconds * Time measured Amount of time measured, in same * units of (fractional) seconds * as the Timer period * * Number timer counts * (b) Time measured = --------------------- * Timer frequency * * where * * Number timer counts Number of timer counts measured * Timer frequency Timer's frequency in some units * of counts per second * Time measured Amount of time measured, in seconds * * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c1'. * * (2) In case the CPU timestamp timer has lower precision than the 32-bit CPU timestamp; * its precision is extended via periodic updates by accumulating the deltas of the * timestamp timer count values into the higher-precision 32-bit CPU timestamp. * * (3) After initialization, 'CPU_TS_32_Accum' & 'CPU_TS_32_TmrPrev' MUST ALWAYS * be accessed AND updated exclusively with interrupts disabled -- but NOT * with critical sections. ********************************************************************************************************* */ #if (CPU_CFG_TS_32_EN == DEF_ENABLED) CPU_TS32 CPU_TS_Get32 (void) { CPU_TS32 ts; #if (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32) CPU_TS_TMR tmr_cur; CPU_TS_TMR tmr_delta; CPU_SR_ALLOC(); #endif #if (CPU_CFG_TS_TMR_SIZE >= CPU_WORD_SIZE_32) ts = (CPU_TS32)CPU_TS_TmrRd(); /* Get cur ts tmr val (in 32-bit ts cnts). */ #else CPU_INT_DIS(); tmr_cur = (CPU_TS_TMR) CPU_TS_TmrRd(); /* Get cur ts tmr val (in ts tmr cnts). */ tmr_delta = (CPU_TS_TMR)(tmr_cur - CPU_TS_32_TmrPrev); /* Calc delta ts tmr cnts. */ CPU_TS_32_Accum += (CPU_TS32 ) tmr_delta; /* Inc ts by delta ts tmr cnts (see Note #2). */ CPU_TS_32_TmrPrev = (CPU_TS_TMR) tmr_cur; /* Save cur ts tmr cnts for next update. */ ts = (CPU_TS32 ) CPU_TS_32_Accum; CPU_INT_EN(); #endif return (ts); } #endif /* ********************************************************************************************************* * CPU_TS_Get64() * * Description : Get current 64-bit CPU timestamp. * * Argument(s) : none. * * Return(s) : Current 64-bit CPU timestamp (in timestamp timer counts). * * Note(s) : (1) When applicable, the amount of time measured by CPU timestamps is calculated by * either of the following equations : * * (a) Time measured = Number timer counts * Timer period * * where * * Number timer counts Number of timer counts measured * Timer period Timer's period in some units of * (fractional) seconds * Time measured Amount of time measured, in same * units of (fractional) seconds * as the Timer period * * Number timer counts * (b) Time measured = --------------------- * Timer frequency * * where * * Number timer counts Number of timer counts measured * Timer frequency Timer's frequency in some units * of counts per second * Time measured Amount of time measured, in seconds * * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c1'. * * (2) In case the CPU timestamp timer has lower precision than the 64-bit CPU timestamp; * its precision is extended via periodic updates by accumulating the deltas of the * timestamp timer count values into the higher-precision 64-bit CPU timestamp. * * (3) After initialization, 'CPU_TS_64_Accum' & 'CPU_TS_64_TmrPrev' MUST ALWAYS * be accessed AND updated exclusively with interrupts disabled -- but NOT * with critical sections. ********************************************************************************************************* */ #if (CPU_CFG_TS_64_EN == DEF_ENABLED) CPU_TS64 CPU_TS_Get64 (void) { CPU_TS64 ts; #if (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64) CPU_TS_TMR tmr_cur; CPU_TS_TMR tmr_delta; CPU_SR_ALLOC(); #endif #if (CPU_CFG_TS_TMR_SIZE >= CPU_WORD_SIZE_64) ts = (CPU_TS64)CPU_TS_TmrRd(); /* Get cur ts tmr val (in 64-bit ts cnts). */ #else CPU_INT_DIS(); tmr_cur = (CPU_TS_TMR) CPU_TS_TmrRd(); /* Get cur ts tmr val (in ts tmr cnts). */ tmr_delta = (CPU_TS_TMR)(tmr_cur - CPU_TS_64_TmrPrev); /* Calc delta ts tmr cnts. */ CPU_TS_64_Accum += (CPU_TS64 ) tmr_delta; /* Inc ts by delta ts tmr cnts (see Note #2). */ CPU_TS_64_TmrPrev = (CPU_TS_TMR) tmr_cur; /* Save cur ts tmr cnts for next update. */ ts = (CPU_TS64 ) CPU_TS_64_Accum; CPU_INT_EN(); #endif return (ts); } #endif /* ********************************************************************************************************* * CPU_TS_Update() * * Description : Update current CPU timestamp(s). * * Argument(s) : none. * * Return(s) : none. * * Note(s) : (1) (a) CPU timestamp(s) MUST be updated periodically by some application (or BSP) time * handler in order to (adequately) maintain CPU timestamp(s)' time. * * (b) CPU timestamp(s) MUST be updated more frequently than the CPU timestamp timer * overflows; otherwise, CPU timestamp(s) will lose time. * * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c2'. ********************************************************************************************************* */ #if (CPU_CFG_TS_EN == DEF_ENABLED) void CPU_TS_Update (void) { #if ((CPU_CFG_TS_32_EN == DEF_ENABLED) && \ (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)) (void)CPU_TS_Get32(); #endif #if ((CPU_CFG_TS_64_EN == DEF_ENABLED) && \ (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64)) (void)CPU_TS_Get64(); #endif } #endif /* ********************************************************************************************************* * CPU_TS_TmrFreqGet() * * Description : Get CPU timestamp's timer frequency. * * Argument(s) : p_err Pointer to variable that will receive the return error code from this function : * * CPU_ERR_NONE CPU timestamp's timer frequency successfully * returned. * CPU_ERR_TS_FREQ_INVALID CPU timestamp's timer frequency invalid &/or * NOT yet configured. * * Return(s) : CPU timestamp's timer frequency (in Hertz), if NO error(s). * * 0, otherwise. * * Note(s) : none. ********************************************************************************************************* */ #if (CPU_CFG_TS_TMR_EN == DEF_ENABLED) CPU_TS_TMR_FREQ CPU_TS_TmrFreqGet (CPU_ERR *p_err) { CPU_TS_TMR_FREQ freq_hz; if (p_err == (CPU_ERR *)0) { CPU_SW_EXCEPTION(0); } freq_hz = CPU_TS_TmrFreq_Hz; *p_err = (freq_hz != 0u) ? CPU_ERR_NONE : CPU_ERR_TS_FREQ_INVALID; return (freq_hz); } #endif /* ********************************************************************************************************* * CPU_TS_TmrFreqSet() * * Description : Set CPU timestamp's timer frequency. * * Argument(s) : freq_hz Frequency (in Hertz) to set for CPU timestamp's timer. * * Return(s) : none. * * Note(s) : (1) (a) (1) CPU timestamp timer frequency is NOT required for internal CPU timestamp * operations but may OPTIONALLY be configured by CPU_TS_TmrInit() or other * application/BSP initialization functions. * * (2) CPU timestamp timer frequency MAY be used with optional CPU_TSxx_to_uSec() * to convert CPU timestamps from timer counts into microseconds. * * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2a'. * * (b) CPU timestamp timer period SHOULD be less than the typical measured time but MUST * be less than the maximum measured time; otherwise, timer resolution inadequate to * measure desired times. * * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2b'. ********************************************************************************************************* */ #if (CPU_CFG_TS_TMR_EN == DEF_ENABLED) void CPU_TS_TmrFreqSet (CPU_TS_TMR_FREQ freq_hz) { CPU_TS_TmrFreq_Hz = freq_hz; } #endif /* ********************************************************************************************************* * CPU_IntDisMeasMaxCurReset() * * Description : Reset current maximum interrupts disabled time. * * Argument(s) : none. * * Return(s) : Maximum interrupts disabled time (in CPU timestamp timer counts) before resetting. * * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c' * & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'. * * Note(s) : (1) After initialization, 'CPU_IntDisMeasMaxCur_cnts' MUST ALWAYS be accessed * exclusively with interrupts disabled -- but NOT with critical sections. ********************************************************************************************************* */ #ifdef CPU_CFG_INT_DIS_MEAS_EN CPU_TS_TMR CPU_IntDisMeasMaxCurReset (void) { CPU_TS_TMR time_max_cnts; CPU_SR_ALLOC(); time_max_cnts = CPU_IntDisMeasMaxCurGet(); CPU_INT_DIS(); CPU_IntDisMeasMaxCur_cnts = 0u; CPU_INT_EN(); return (time_max_cnts); } #endif /* ********************************************************************************************************* * CPU_IntDisMeasMaxCurGet() * * Description : Get current maximum interrupts disabled time. * * Argument(s) : none. * * Return(s) : Current maximum interrupts disabled time (in CPU timestamp timer counts). * * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c' * & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'. * * Note(s) : (1) After initialization, 'CPU_IntDisMeasMaxCur_cnts' MUST ALWAYS be accessed * exclusively with interrupts disabled -- but NOT with critical sections. ********************************************************************************************************* */ #ifdef CPU_CFG_INT_DIS_MEAS_EN CPU_TS_TMR CPU_IntDisMeasMaxCurGet (void) { CPU_TS_TMR time_tot_cnts; CPU_TS_TMR time_max_cnts; CPU_SR_ALLOC(); CPU_INT_DIS(); time_tot_cnts = CPU_IntDisMeasMaxCur_cnts; CPU_INT_EN(); time_max_cnts = CPU_IntDisMeasMaxCalc(time_tot_cnts); return (time_max_cnts); } #endif /* ********************************************************************************************************* * CPU_IntDisMeasMaxGet() * * Description : Get (non-resetable) maximum interrupts disabled time. * * Argument(s) : none. * * Return(s) : (Non-resetable) maximum interrupts disabled time (in CPU timestamp timer counts). * * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c' * & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'. * * Note(s) : (1) After initialization, 'CPU_IntDisMeasMax_cnts' MUST ALWAYS be accessed * exclusively with interrupts disabled -- but NOT with critical sections. ********************************************************************************************************* */ #ifdef CPU_CFG_INT_DIS_MEAS_EN CPU_TS_TMR CPU_IntDisMeasMaxGet (void) { CPU_TS_TMR time_tot_cnts; CPU_TS_TMR time_max_cnts; CPU_SR_ALLOC(); CPU_INT_DIS(); time_tot_cnts = CPU_IntDisMeasMax_cnts; CPU_INT_EN(); time_max_cnts = CPU_IntDisMeasMaxCalc(time_tot_cnts); return (time_max_cnts); } #endif /* ********************************************************************************************************* * CPU_IntDisMeasStart() * * Description : Start interrupts disabled time measurement. * * Argument(s) : none. * * Return(s) : none. * * Note(s) : none. ********************************************************************************************************* */ #ifdef CPU_CFG_INT_DIS_MEAS_EN void CPU_IntDisMeasStart (void) { CPU_IntDisMeasCtr++; if (CPU_IntDisNestCtr == 0u) { /* If ints NOT yet dis'd, ... */ CPU_IntDisMeasStart_cnts = CPU_TS_TmrRd(); /* ... get ints dis'd start time. */ } CPU_IntDisNestCtr++; } #endif /* ********************************************************************************************************* * CPU_IntDisMeasStop() * * Description : Stop interrupts disabled time measurement. * * Argument(s) : none. * * Return(s) : none. * * Note(s) : (1) (a) The total amount of time interrupts are disabled by system &/or application code * during critical sections is calculated by the following equations : * * (1) When interrupts disabled time measurements are disabled : * * * | CRITICAL | | CRITICAL | * |<- SECTION ->| |<- SECTION ->| * | ENTER | | EXIT | * * Disable Enable * Interrupts Interrupts * * || || || || * || || || || * || | ||<------------------------->|| | || * || |<->|| | ||<----->| || * || | | || | || | | || * | | | | | * interrupts time interrupts * disabled interrupts |enabled * | disabled | * | (via application) | * time time * interrupts interrupts * disabled ovrhd enabled ovrhd * * * (A) time = [ time - time ] - time * interrupts [ interrupts interrupts ] total * disabled [ enabled disabled ] ovrhd * (via application) * * * (B) time = time + time * total interrupts interrupts * ovrhd enabled ovrhd disabled ovrhd * * * where * * time time interrupts are disabled between * interrupts first critical section enter & * disabled last critical section exit (i.e. * (via application) minus total overhead time) * * time time when interrupts are disabled * interrupts * disabled * * time time when interrupts are enabled * interrupts * enabled * * * time total overhead time to disable/enable * total interrupts during critical section * ovrhd enter & exit * * time total overhead time to disable interrupts * interrupts during critical section enter * disabled ovrhd * * time total overhead time to enable interrupts * interrupts during critical section exit * enabled ovrhd * * * (2) When interrupts disabled time measurements are enabled : * * * | | | | * |<----- CRITICAL SECTION ENTER ----->| |<------- CRITICAL SECTION EXIT ------->| * | | | | * * Time Time * Disable Measurement Measurement Enable * Interrupts Start Stop Interrupts * * || | || || | || * || | || || | || * || | | ||<------------------------->|| | | || * || | | |<----------->|| | ||<------------->| | | || * || | | | | || | || | | | | || * | | | | | | | * interrupts get | time | get interrupts * disabled start time | interrupts | stop time enabled * meas | disabled | meas * time (via application) time * start meas stop meas * ovrhd ovrhd * * * (A) time = [ time - time ] - time * interrupts [ stop start ] total meas * disabled [ meas meas ] ovrhd * (via application) * * * (B) time = time + time * total meas start meas stop meas * ovrhd ovrhd ovrhd * * * where * * time time interrupts are disabled between first * interrupts critical section enter & last critical * disabled section exit (i.e. minus measurement * (via application) overhead time; however, this does NOT * include any overhead time to disable * or enable interrupts during critical * section enter & exit) * * time time of disable interrupts start time * start measurement (in timer counts) * meas * * time time of disable interrupts stop time * stop measurement (in timer counts) * meas * * * time total overhead time to start/stop disabled * total meas interrupts time measurements (in timer * ovrhd counts) * * time total overhead time after getting start * start meas time until end of start measurement * ovrhd function (in timer counts) * * time total overhead time from beginning of stop * stop meas measurement function until after getting * ovrhd stop time (in timer counts) * * * (b) (1) (A) In order to correctly handle unsigned subtraction overflows of start times * from stop times, CPU timestamp timer count values MUST be returned via * word-size-configurable 'CPU_TS_TMR' data type. * * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2a'. * * (B) Since unsigned subtraction of start times from stop times assumes increasing * values, timestamp timer count values MUST increase with each time count. * * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2b'. * * (2) (A) To expedite & reduce interrupts disabled time measurement overhead; only the * subtraction of start times from stop times is performed. * * (B) The final calculations to subtract the interrupts disabled time measurement * overhead is performed asynchronously in appropriate API functions. * * See also 'CPU_IntDisMeasMaxCalc() Note #1b'. ********************************************************************************************************* */ #ifdef CPU_CFG_INT_DIS_MEAS_EN void CPU_IntDisMeasStop (void) { CPU_TS_TMR time_ints_disd_cnts; CPU_IntDisNestCtr--; if (CPU_IntDisNestCtr == 0u) { /* If ints NO longer dis'd, ... */ CPU_IntDisMeasStop_cnts = CPU_TS_TmrRd(); /* ... get ints dis'd stop time & ... */ /* ... calc ints dis'd tot time (see Note #1b2A). */ time_ints_disd_cnts = CPU_IntDisMeasStop_cnts - CPU_IntDisMeasStart_cnts; /* Calc max ints dis'd times. */ if (CPU_IntDisMeasMaxCur_cnts < time_ints_disd_cnts) { CPU_IntDisMeasMaxCur_cnts = time_ints_disd_cnts; } if (CPU_IntDisMeasMax_cnts < time_ints_disd_cnts) { CPU_IntDisMeasMax_cnts = time_ints_disd_cnts; } } } #endif /* ********************************************************************************************************* * CPU_CntLeadZeros() * * Description : Count the number of contiguous, most-significant, leading zero bits in a data value. * * Argument(s) : val Data value to count leading zero bits. * * Return(s) : Number of contiguous, most-significant, leading zero bits in 'val', if NO error(s). * * DEF_INT_CPU_U_MAX_VAL, otherwise. * * Note(s) : (1) (a) Supports the following data value sizes : * * (1) 8-bits * (2) 16-bits * (3) 32-bits * (4) 64-bits * * See also 'cpu_def.h CPU WORD CONFIGURATION Note #1'. * * (b) (1) For 8-bit values : * * b07 b06 b05 b04 b03 b02 b01 b00 # Leading Zeros * --- --- --- --- --- --- --- --- --------------- * 1 x x x x x x x 0 * 0 1 x x x x x x 1 * 0 0 1 x x x x x 2 * 0 0 0 1 x x x x 3 * 0 0 0 0 1 x x x 4 * 0 0 0 0 0 1 x x 5 * 0 0 0 0 0 0 1 x 6 * 0 0 0 0 0 0 0 1 7 * 0 0 0 0 0 0 0 0 8 * * * (2) For 16-bit values : * * b15 b14 b13 ... b04 b03 b02 b01 b00 # Leading Zeros * --- --- --- --- --- --- --- --- --------------- * 1 x x x x x x x 0 * 0 1 x x x x x x 1 * 0 0 1 x x x x x 2 * : : : : : : : : : * : : : : : : : : : * 0 0 0 1 x x x x 11 * 0 0 0 0 1 x x x 12 * 0 0 0 0 0 1 x x 13 * 0 0 0 0 0 0 1 x 14 * 0 0 0 0 0 0 0 1 15 * 0 0 0 0 0 0 0 0 16 * * (3) For 32-bit values : * * b31 b30 b29 ... b04 b03 b02 b01 b00 # Leading Zeros * --- --- --- --- --- --- --- --- --------------- * 1 x x x x x x x 0 * 0 1 x x x x x x 1 * 0 0 1 x x x x x 2 * : : : : : : : : : * : : : : : : : : : * 0 0 0 1 x x x x 27 * 0 0 0 0 1 x x x 28 * 0 0 0 0 0 1 x x 29 * 0 0 0 0 0 0 1 x 30 * 0 0 0 0 0 0 0 1 31 * 0 0 0 0 0 0 0 0 32 * * * (4) For 64-bit values : * * b63 b62 b61 ... b04 b03 b02 b01 b00 # Leading Zeros * --- --- --- --- --- --- --- --- --------------- * 1 x x x x x x x 0 * 0 1 x x x x x x 1 * 0 0 1 x x x x x 2 * : : : : : : : : : * : : : : : : : : : * 0 0 0 1 x x x x 59 * 0 0 0 0 1 x x x 60 * 0 0 0 0 0 1 x x 61 * 0 0 0 0 0 0 1 x 62 * 0 0 0 0 0 0 0 1 63 * 0 0 0 0 0 0 0 0 64 * * * See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE Note #1'. ********************************************************************************************************* */ #ifndef CPU_CFG_LEAD_ZEROS_ASM_PRESENT CPU_DATA CPU_CntLeadZeros (CPU_DATA val) { CPU_DATA nbr_lead_zeros; #if (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_08) nbr_lead_zeros = CPU_CntLeadZeros08((CPU_INT08U)val); #elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_16) nbr_lead_zeros = CPU_CntLeadZeros16((CPU_INT16U)val); #elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_32) nbr_lead_zeros = CPU_CntLeadZeros32((CPU_INT32U)val); #elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_64) nbr_lead_zeros = CPU_CntLeadZeros64((CPU_INT64U)val); #else /* See Note #1a. */ nbr_lead_zeros = DEF_INT_CPU_U_MAX_VAL; #endif return (nbr_lead_zeros); } #endif /* ********************************************************************************************************* * CPU_CntLeadZeros08() * * Description : Count the number of contiguous, most-significant, leading zero bits in an 8-bit data value. * * Argument(s) : val Data value to count leading zero bits. * * Return(s) : Number of contiguous, most-significant, leading zero bits in 'val'. * * Note(s) : (1) Supports 8-bit values : * * b07 b06 b05 b04 b03 b02 b01 b00 # Leading Zeros * --- --- --- --- --- --- --- --- --------------- * 1 x x x x x x x 0 * 0 1 x x x x x x 1 * 0 0 1 x x x x x 2 * 0 0 0 1 x x x x 3 * 0 0 0 0 1 x x x 4 * 0 0 0 0 0 1 x x 5 * 0 0 0 0 0 0 1 x 6 * 0 0 0 0 0 0 0 1 7 * 0 0 0 0 0 0 0 0 8 * * * See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE Note #1'. ********************************************************************************************************* */ #if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_08) CPU_DATA CPU_CntLeadZeros08 (CPU_INT08U val) { #if (!((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_08))) CPU_DATA ix; #endif CPU_DATA nbr_lead_zeros; /* ---------- ASM-OPTIMIZED ----------- */ #if ((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_08)) nbr_lead_zeros = CPU_CntLeadZeros((CPU_DATA)val); nbr_lead_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_08) * DEF_OCTET_NBR_BITS; #else /* ----------- C-OPTIMIZED ------------ */ /* Chk bits [07:00] : */ /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 0 bits */ nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix]); /* .. plus nbr msb lead zeros = 0 bits.*/ #endif return (nbr_lead_zeros); } #endif /* ********************************************************************************************************* * CPU_CntLeadZeros16() * * Description : Count the number of contiguous, most-significant, leading zero bits in a 16-bit data value. * * Argument(s) : val Data value to count leading zero bits. * * Return(s) : Number of contiguous, most-significant, leading zero bits in 'val'. * * Note(s) : (1) Supports 16-bit values : * * b15 b14 b13 ... b04 b03 b02 b01 b00 # Leading Zeros * --- --- --- --- --- --- --- --- --------------- * 1 x x x x x x x 0 * 0 1 x x x x x x 1 * 0 0 1 x x x x x 2 * : : : : : : : : : * : : : : : : : : : * 0 0 0 1 x x x x 11 * 0 0 0 0 1 x x x 12 * 0 0 0 0 0 1 x x 13 * 0 0 0 0 0 0 1 x 14 * 0 0 0 0 0 0 0 1 15 * 0 0 0 0 0 0 0 0 16 * * * See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE Note #1'. ********************************************************************************************************* */ #if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_16) CPU_DATA CPU_CntLeadZeros16 (CPU_INT16U val) { #if (!((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_16))) CPU_DATA ix; #endif CPU_DATA nbr_lead_zeros; /* ---------- ASM-OPTIMIZED ----------- */ #if ((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_16)) nbr_lead_zeros = CPU_CntLeadZeros((CPU_DATA)val); nbr_lead_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_16) * DEF_OCTET_NBR_BITS; #else /* ----------- C-OPTIMIZED ------------ */ if (val > 0x00FFu) { /* Chk bits [15:08] : */ val >>= 8u; /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 8 bits */ nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix]); /* .. plus nbr msb lead zeros = 0 bits.*/ } else { /* Chk bits [07:00] : */ /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 0 bits */ nbr_lead_zeros = (CPU_DATA)((CPU_DATA)CPU_CntLeadZerosTbl[ix] + 8u); /* .. plus nbr msb lead zeros = 8 bits.*/ } #endif return (nbr_lead_zeros); } #endif /* ********************************************************************************************************* * CPU_CntLeadZeros32() * * Description : Count the number of contiguous, most-significant, leading zero bits in a 32-bit data value. * * Argument(s) : val Data value to count leading zero bits. * * Return(s) : Number of contiguous, most-significant, leading zero bits in 'val'. * * Note(s) : (1) Supports 32-bit values : * * b31 b30 b29 ... b04 b03 b02 b01 b00 # Leading Zeros * --- --- --- --- --- --- --- --- --------------- * 1 x x x x x x x 0 * 0 1 x x x x x x 1 * 0 0 1 x x x x x 2 * : : : : : : : : : * : : : : : : : : : * 0 0 0 1 x x x x 27 * 0 0 0 0 1 x x x 28 * 0 0 0 0 0 1 x x 29 * 0 0 0 0 0 0 1 x 30 * 0 0 0 0 0 0 0 1 31 * 0 0 0 0 0 0 0 0 32 * * * See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE Note #1'. ********************************************************************************************************* */ #if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_32) CPU_DATA CPU_CntLeadZeros32 (CPU_INT32U val) { #if (!((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_32))) CPU_DATA ix; #endif CPU_DATA nbr_lead_zeros; /* ---------- ASM-OPTIMIZED ----------- */ #if ((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_32)) nbr_lead_zeros = CPU_CntLeadZeros((CPU_DATA)val); nbr_lead_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_32) * DEF_OCTET_NBR_BITS; #else /* ----------- C-OPTIMIZED ------------ */ if (val > 0x0000FFFFu) { if (val > 0x00FFFFFFu) { /* Chk bits [31:24] : */ val >>= 24u; /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 24 bits */ nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix]); /* .. plus nbr msb lead zeros = 0 bits.*/ } else { /* Chk bits [23:16] : */ val >>= 16u; /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 16 bits */ nbr_lead_zeros = (CPU_DATA)((CPU_DATA)CPU_CntLeadZerosTbl[ix] + 8u);/* .. plus nbr msb lead zeros = 8 bits.*/ } } else { if (val > 0x000000FFu) { /* Chk bits [15:08] : */ val >>= 8u; /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 8 bits */ nbr_lead_zeros = (CPU_DATA)((CPU_DATA)CPU_CntLeadZerosTbl[ix] + 16u);/* .. plus nbr msb lead zeros = 16 bits.*/ } else { /* Chk bits [07:00] : */ /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 0 bits */ nbr_lead_zeros = (CPU_DATA)((CPU_DATA)CPU_CntLeadZerosTbl[ix] + 24u);/* .. plus nbr msb lead zeros = 24 bits.*/ } } #endif return (nbr_lead_zeros); } #endif /* ********************************************************************************************************* * CPU_CntLeadZeros64() * * Description : Count the number of contiguous, most-significant, leading zero bits in a 64-bit data value. * * Argument(s) : val Data value to count leading zero bits. * * Return(s) : Number of contiguous, most-significant, leading zero bits in 'val'. * * Note(s) : (1) Supports 64-bit values : * * b63 b62 b61 ... b04 b03 b02 b01 b00 # Leading Zeros * --- --- --- --- --- --- --- --- --------------- * 1 x x x x x x x 0 * 0 1 x x x x x x 1 * 0 0 1 x x x x x 2 * : : : : : : : : : * : : : : : : : : : * 0 0 0 1 x x x x 59 * 0 0 0 0 1 x x x 60 * 0 0 0 0 0 1 x x 61 * 0 0 0 0 0 0 1 x 62 * 0 0 0 0 0 0 0 1 63 * 0 0 0 0 0 0 0 0 64 * * * See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE Note #1'. ********************************************************************************************************* */ #if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_64) CPU_DATA CPU_CntLeadZeros64 (CPU_INT64U val) { #if (!((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_64))) CPU_DATA ix; #endif CPU_DATA nbr_lead_zeros; /* ---------- ASM-OPTIMIZED ----------- */ #if ((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_64)) nbr_lead_zeros = CPU_CntLeadZeros((CPU_DATA)val); nbr_lead_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_64) * DEF_OCTET_NBR_BITS; #else /* ----------- C-OPTIMIZED ------------ */ if (val > 0x00000000FFFFFFFFuLL) { if (val > 0x0000FFFFFFFFFFFFuLL) { if (val > 0x00FFFFFFFFFFFFFFuLL) { /* Chk bits [63:56] : */ val >>= 56u; /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 56 bits */ nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix]); /* .. plus nbr msb lead zeros = 0 bits.*/ } else { /* Chk bits [55:48] : */ val >>= 48u; /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 48 bits */ nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 8u);/* .. plus nbr msb lead zeros = 8 bits.*/ } } else { if (val > 0x000000FFFFFFFFFFuLL) { /* Chk bits [47:40] : */ val >>= 40u; /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 40 bits */ nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 16u);/* .. plus nbr msb lead zeros = 16 bits.*/ } else { /* Chk bits [39:32] : */ val >>= 32u; /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 32 bits */ nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 24u);/* .. plus nbr msb lead zeros = 24 bits.*/ } } } else { if (val > 0x000000000000FFFFuLL) { if (val > 0x0000000000FFFFFFuLL) { /* Chk bits [31:24] : */ val >>= 24u; /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 24 bits */ nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 32u);/* .. plus nbr msb lead zeros = 32 bits.*/ } else { /* Chk bits [23:16] : */ val >>= 16u; /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 16 bits */ nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 40u);/* .. plus nbr msb lead zeros = 40 bits.*/ } } else { if (val > 0x00000000000000FFuLL) { /* Chk bits [15:08] : */ val >>= 8u; /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 8 bits */ nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 48u);/* .. plus nbr msb lead zeros = 48 bits.*/ } else { /* Chk bits [07:00] : */ /* .. Nbr lead zeros = .. */ ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 0 bits */ nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 56u);/* .. plus nbr msb lead zeros = 56 bits.*/ } } } #endif return (nbr_lead_zeros); } #endif /* ********************************************************************************************************* * CPU_CntTrailZeros() * * Description : Count the number of contiguous, least-significant, trailing zero bits in a data value. * * Argument(s) : val Data value to count trailing zero bits. * * Return(s) : Number of contiguous, least-significant, trailing zero bits in 'val'. * * Note(s) : (1) (a) Supports the following data value sizes : * * (1) 8-bits * (2) 16-bits * (3) 32-bits * (4) 64-bits * * See also 'cpu_def.h CPU WORD CONFIGURATION Note #1'. * * (b) (1) For 8-bit values : * * b07 b06 b05 b04 b03 b02 b01 b00 # Trailing Zeros * --- --- --- --- --- --- --- --- ---------------- * x x x x x x x 1 0 * x x x x x x 1 0 1 * x x x x x 1 0 0 2 * x x x x 1 0 0 0 3 * x x x 1 0 0 0 0 4 * x x 1 0 0 0 0 0 5 * x 1 0 0 0 0 0 0 6 * 1 0 0 0 0 0 0 0 7 * 0 0 0 0 0 0 0 0 8 * * * (2) For 16-bit values : * * b15 b14 b13 b12 b11 ... b02 b01 b00 # Trailing Zeros * --- --- --- --- --- --- --- --- ---------------- * x x x x x x x 1 0 * x x x x x x 1 0 1 * x x x x x 1 0 0 2 * : : : : : : : : : * : : : : : : : : : * x x x x 1 0 0 0 11 * x x x 1 0 0 0 0 12 * x x 1 0 0 0 0 0 13 * x 1 0 0 0 0 0 0 14 * 1 0 0 0 0 0 0 0 15 * 0 0 0 0 0 0 0 0 16 * * * (3) For 32-bit values : * * b31 b30 b29 b28 b27 ... b02 b01 b00 # Trailing Zeros * --- --- --- --- --- --- --- --- ---------------- * x x x x x x x 1 0 * x x x x x x 1 0 1 * x x x x x 1 0 0 2 * : : : : : : : : : * : : : : : : : : : * x x x x 1 0 0 0 27 * x x x 1 0 0 0 0 28 * x x 1 0 0 0 0 0 29 * x 1 0 0 0 0 0 0 30 * 1 0 0 0 0 0 0 0 31 * 0 0 0 0 0 0 0 0 32 * * * (4) For 64-bit values : * * b63 b62 b61 b60 b59 ... b02 b01 b00 # Trailing Zeros * --- --- --- --- --- --- --- --- ---------------- * x x x x x x x 1 0 * x x x x x x 1 0 1 * x x x x x 1 0 0 2 * : : : : : : : : : * : : : : : : : : : * x x x x 1 0 0 0 59 * x x x 1 0 0 0 0 60 * x x 1 0 0 0 0 0 61 * x 1 0 0 0 0 0 0 62 * 1 0 0 0 0 0 0 0 63 * 0 0 0 0 0 0 0 0 64 * * (2) For non-zero values, the returned number of contiguous, least-significant, trailing * zero bits is also equivalent to the bit position of the least-significant set bit. * * (3) 'val' SHOULD be validated for non-'0' PRIOR to all other counting zero calculations : * * (a) CPU_CntTrailZeros()'s final conditional statement calculates 'val's number of * trailing zeros based on its return data size, 'CPU_CFG_DATA_SIZE', & 'val's * calculated number of lead zeros ONLY if the initial 'val' is non-'0' : * * if (val != 0u) { * nbr_trail_zeros = ((CPU_CFG_DATA_SIZE * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros; * } else { * nbr_trail_zeros = nbr_lead_zeros; * } * * Therefore, initially validating all non-'0' values avoids having to conditionally * execute the final 'if' statement. ********************************************************************************************************* */ #ifndef CPU_CFG_TRAIL_ZEROS_ASM_PRESENT CPU_DATA CPU_CntTrailZeros (CPU_DATA val) { CPU_DATA val_bit_mask; CPU_DATA nbr_lead_zeros; CPU_DATA nbr_trail_zeros; if (val == 0u) { /* Rtn ALL val bits as zero'd (see Note #3). */ return ((CPU_DATA)(CPU_CFG_DATA_SIZE * DEF_OCTET_NBR_BITS)); } val_bit_mask = val & ((CPU_DATA)~val + 1u); /* Zero/clr all bits EXCEPT least-sig set bit. */ nbr_lead_zeros = CPU_CntLeadZeros(val_bit_mask); /* Cnt nbr lead 0s. */ /* Calc nbr trail 0s = (nbr val bits - 1) - nbr lead 0s.*/ nbr_trail_zeros = ((CPU_DATA)((CPU_CFG_DATA_SIZE * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros); return (nbr_trail_zeros); } #endif /* ********************************************************************************************************* * CPU_CntTrailZeros08() * * Description : Count the number of contiguous, least-significant, trailing zero bits in an 8-bit data value. * * Argument(s) : val Data value to count trailing zero bits. * * Return(s) : Number of contiguous, least-significant, trailing zero bits in 'val'. * * Note(s) : (1) Supports 8-bit values : * * b07 b06 b05 b04 b03 b02 b01 b00 # Trailing Zeros * --- --- --- --- --- --- --- --- ---------------- * x x x x x x x 1 0 * x x x x x x 1 0 1 * x x x x x 1 0 0 2 * x x x x 1 0 0 0 3 * x x x 1 0 0 0 0 4 * x x 1 0 0 0 0 0 5 * x 1 0 0 0 0 0 0 6 * 1 0 0 0 0 0 0 0 7 * 0 0 0 0 0 0 0 0 8 * * * (2) For non-zero values, the returned number of contiguous, least-significant, trailing * zero bits is also equivalent to the bit position of the least-significant set bit. * * (3) 'val' SHOULD be validated for non-'0' PRIOR to all other counting zero calculations : * * (a) For assembly-optimized implementations, CPU_CntTrailZeros() returns 'val's * number of trailing zeros via CPU's native data size, 'CPU_CFG_DATA_SIZE'. * If the returned number of zeros exceeds CPU_CntTrailZeros08()'s 8-bit return * data size, then the returned number of zeros must be offset by the difference * between CPU_CntTrailZeros()'s & CPU_CntTrailZeros08()'s return data size : * * nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val); * if (nbr_trail_zeros > (CPU_WORD_SIZE_08 * DEF_OCTET_NBR_BITS)) { * nbr_trail_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_08) * DEF_OCTET_NBR_BITS; * } * * However, this ONLY occurs for an initial 'val' of '0' since all non-'0' 8-bit * values would return a number of trailing zeros less than or equal to 8 bits. * * Therefore, initially validating all non-'0' values prior to calling assembly- * optimized CPU_CntTrailZeros() avoids having to offset the number of returned * trailing zeros by the difference in CPU data size and 8-bit data value bits. * * (b) For CPU_CntTrailZeros08()'s C implementation, the final conditional statement * calculates 'val's number of trailing zeros based on CPU_CntTrailZeros08()'s * 8-bit return data size & 'val's calculated number of lead zeros ONLY if the * initial 'val' is non-'0' : * * if (val != 0u) { * nbr_trail_zeros = ((CPU_WORD_SIZE_08 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros; * } else { * nbr_trail_zeros = nbr_lead_zeros; * } * * Therefore, initially validating all non-'0' values avoids having to conditionally * execute the final 'if' statement. ********************************************************************************************************* */ #if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_08) CPU_DATA CPU_CntTrailZeros08 (CPU_INT08U val) { #if (!((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_08))) CPU_INT08U val_bit_mask; CPU_DATA nbr_lead_zeros; #endif CPU_DATA nbr_trail_zeros; if (val == 0u) { /* Rtn ALL val bits as zero'd (see Note #3). */ return ((CPU_DATA)(CPU_WORD_SIZE_08 * DEF_OCTET_NBR_BITS)); } /* ------------------ ASM-OPTIMIZED ------------------- */ #if ((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_08)) nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val); #else /* ------------------- C-OPTIMIZED -------------------- */ val_bit_mask = val & ((CPU_INT08U)~val + 1u); /* Zero/clr all bits EXCEPT least-sig set bit. */ nbr_lead_zeros = CPU_CntLeadZeros08(val_bit_mask); /* Cnt nbr lead 0s. */ /* Calc nbr trail 0s = (nbr val bits - 1) - nbr lead 0s.*/ nbr_trail_zeros = ((CPU_DATA)((CPU_WORD_SIZE_08 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros); #endif return (nbr_trail_zeros); } #endif /* ********************************************************************************************************* * CPU_CntTrailZeros16() * * Description : Count the number of contiguous, least-significant, trailing zero bits in a 16-bit data value. * * Argument(s) : val Data value to count trailing zero bits. * * Return(s) : Number of contiguous, least-significant, trailing zero bits in 'val'. * * Note(s) : (1) Supports 16-bit values : * * b15 b14 b13 b12 b11 ... b02 b01 b00 # Trailing Zeros * --- --- --- --- --- --- --- --- ---------------- * x x x x x x x 1 0 * x x x x x x 1 0 1 * x x x x x 1 0 0 2 * : : : : : : : : : * : : : : : : : : : * x x x x 1 0 0 0 11 * x x x 1 0 0 0 0 12 * x x 1 0 0 0 0 0 13 * x 1 0 0 0 0 0 0 14 * 1 0 0 0 0 0 0 0 15 * 0 0 0 0 0 0 0 0 16 * * * (2) For non-zero values, the returned number of contiguous, least-significant, trailing * zero bits is also equivalent to the bit position of the least-significant set bit. * * (3) 'val' SHOULD be validated for non-'0' PRIOR to all other counting zero calculations : * * (a) For assembly-optimized implementations, CPU_CntTrailZeros() returns 'val's * number of trailing zeros via CPU's native data size, 'CPU_CFG_DATA_SIZE'. * If the returned number of zeros exceeds CPU_CntTrailZeros16()'s 16-bit return * data size, then the returned number of zeros must be offset by the difference * between CPU_CntTrailZeros()'s & CPU_CntTrailZeros16()'s return data size : * * nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val); * if (nbr_trail_zeros > (CPU_WORD_SIZE_16 * DEF_OCTET_NBR_BITS)) { * nbr_trail_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_16) * DEF_OCTET_NBR_BITS; * } * * However, this ONLY occurs for an initial 'val' of '0' since all non-'0' 16-bit * values would return a number of trailing zeros less than or equal to 16 bits. * * Therefore, initially validating all non-'0' values prior to calling assembly- * optimized CPU_CntTrailZeros() avoids having to offset the number of returned * trailing zeros by the difference in CPU data size and 16-bit data value bits. * * (b) For CPU_CntTrailZeros16()'s C implementation, the final conditional statement * calculates 'val's number of trailing zeros based on CPU_CntTrailZeros16()'s * 16-bit return data size & 'val's calculated number of lead zeros ONLY if the * initial 'val' is non-'0' : * * if (val != 0u) { * nbr_trail_zeros = ((CPU_WORD_SIZE_16 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros; * } else { * nbr_trail_zeros = nbr_lead_zeros; * } * * Therefore, initially validating all non-'0' values avoids having to conditionally * execute the final 'if' statement. ********************************************************************************************************* */ #if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_16) CPU_DATA CPU_CntTrailZeros16 (CPU_INT16U val) { #if (!((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_16))) CPU_INT16U val_bit_mask; CPU_DATA nbr_lead_zeros; #endif CPU_DATA nbr_trail_zeros; if (val == 0u) { /* Rtn ALL val bits as zero'd (see Note #3). */ return ((CPU_DATA)(CPU_WORD_SIZE_16 * DEF_OCTET_NBR_BITS)); } /* ------------------ ASM-OPTIMIZED ------------------- */ #if ((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_16)) nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val); #else /* ------------------- C-OPTIMIZED -------------------- */ val_bit_mask = val & ((CPU_INT16U)~val + 1u); /* Zero/clr all bits EXCEPT least-sig set bit. */ nbr_lead_zeros = CPU_CntLeadZeros16(val_bit_mask); /* Cnt nbr lead 0s. */ /* Calc nbr trail 0s = (nbr val bits - 1) - nbr lead 0s.*/ nbr_trail_zeros = ((CPU_DATA)((CPU_WORD_SIZE_16 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros); #endif return (nbr_trail_zeros); } #endif /* ********************************************************************************************************* * CPU_CntTrailZeros32() * * Description : Count the number of contiguous, least-significant, trailing zero bits in a 32-bit data value. * * Argument(s) : val Data value to count trailing zero bits. * * Return(s) : Number of contiguous, least-significant, trailing zero bits in 'val'. * * Note(s) : (1) Supports 32-bit values : * * b31 b30 b29 b28 b27 ... b02 b01 b00 # Trailing Zeros * --- --- --- --- --- --- --- --- ---------------- * x x x x x x x 1 0 * x x x x x x 1 0 1 * x x x x x 1 0 0 2 * : : : : : : : : : * : : : : : : : : : * x x x x 1 0 0 0 27 * x x x 1 0 0 0 0 28 * x x 1 0 0 0 0 0 29 * x 1 0 0 0 0 0 0 30 * 1 0 0 0 0 0 0 0 31 * 0 0 0 0 0 0 0 0 32 * * * (2) For non-zero values, the returned number of contiguous, least-significant, trailing * zero bits is also equivalent to the bit position of the least-significant set bit. * * (3) 'val' SHOULD be validated for non-'0' PRIOR to all other counting zero calculations : * * (a) For assembly-optimized implementations, CPU_CntTrailZeros() returns 'val's * number of trailing zeros via CPU's native data size, 'CPU_CFG_DATA_SIZE'. * If the returned number of zeros exceeds CPU_CntTrailZeros32()'s 32-bit return * data size, then the returned number of zeros must be offset by the difference * between CPU_CntTrailZeros()'s & CPU_CntTrailZeros32()'s return data size : * * nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val); * if (nbr_trail_zeros > (CPU_WORD_SIZE_32 * DEF_OCTET_NBR_BITS)) { * nbr_trail_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_32) * DEF_OCTET_NBR_BITS; * } * * However, this ONLY occurs for an initial 'val' of '0' since all non-'0' 32-bit * values would return a number of trailing zeros less than or equal to 32 bits. * * Therefore, initially validating all non-'0' values prior to calling assembly- * optimized CPU_CntTrailZeros() avoids having to offset the number of returned * trailing zeros by the difference in CPU data size and 32-bit data value bits. * * (b) For CPU_CntTrailZeros32()'s C implementation, the final conditional statement * calculates 'val's number of trailing zeros based on CPU_CntTrailZeros32()'s * 32-bit return data size & 'val's calculated number of lead zeros ONLY if the * initial 'val' is non-'0' : * * if (val != 0u) { * nbr_trail_zeros = ((CPU_WORD_SIZE_32 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros; * } else { * nbr_trail_zeros = nbr_lead_zeros; * } * * Therefore, initially validating all non-'0' values avoids having to conditionally * execute the final 'if' statement. ********************************************************************************************************* */ #if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_32) CPU_DATA CPU_CntTrailZeros32 (CPU_INT32U val) { #if (!((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_32))) CPU_INT32U val_bit_mask; CPU_DATA nbr_lead_zeros; #endif CPU_DATA nbr_trail_zeros; if (val == 0u) { /* Rtn ALL val bits as zero'd (see Note #3). */ return ((CPU_DATA)(CPU_WORD_SIZE_32 * DEF_OCTET_NBR_BITS)); } /* ------------------ ASM-OPTIMIZED ------------------- */ #if ((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_32)) nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val); #else /* ------------------- C-OPTIMIZED -------------------- */ val_bit_mask = val & ((CPU_INT32U)~val + 1u); /* Zero/clr all bits EXCEPT least-sig set bit. */ nbr_lead_zeros = CPU_CntLeadZeros32(val_bit_mask); /* Cnt nbr lead 0s. */ /* Calc nbr trail 0s = (nbr val bits - 1) - nbr lead 0s.*/ nbr_trail_zeros = ((CPU_DATA)((CPU_WORD_SIZE_32 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros); #endif return (nbr_trail_zeros); } #endif /* ********************************************************************************************************* * CPU_CntTrailZeros64() * * Description : Count the number of contiguous, least-significant, trailing zero bits in a 64-bit data value. * * Argument(s) : val Data value to count trailing zero bits. * * Return(s) : Number of contiguous, least-significant, trailing zero bits in 'val'. * * Note(s) : (1) Supports 64-bit values : * * b63 b62 b61 b60 b59 ... b02 b01 b00 # Trailing Zeros * --- --- --- --- --- --- --- --- ---------------- * x x x x x x x 1 0 * x x x x x x 1 0 1 * x x x x x 1 0 0 2 * : : : : : : : : : * : : : : : : : : : * x x x x 1 0 0 0 59 * x x x 1 0 0 0 0 60 * x x 1 0 0 0 0 0 61 * x 1 0 0 0 0 0 0 62 * 1 0 0 0 0 0 0 0 63 * 0 0 0 0 0 0 0 0 64 * * * (2) For non-zero values, the returned number of contiguous, least-significant, trailing * zero bits is also equivalent to the bit position of the least-significant set bit. * * (3) 'val' SHOULD be validated for non-'0' PRIOR to all other counting zero calculations : * * (a) For assembly-optimized implementations, CPU_CntTrailZeros() returns 'val's * number of trailing zeros via CPU's native data size, 'CPU_CFG_DATA_SIZE'. * If the returned number of zeros exceeds CPU_CntTrailZeros64()'s 64-bit return * data size, then the returned number of zeros must be offset by the difference * between CPU_CntTrailZeros()'s & CPU_CntTrailZeros64()'s return data size : * * nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val); * if (nbr_trail_zeros > (CPU_WORD_SIZE_64 * DEF_OCTET_NBR_BITS)) { * nbr_trail_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_64) * DEF_OCTET_NBR_BITS; * } * * However, this ONLY occurs for an initial 'val' of '0' since all non-'0' 64-bit * values would return a number of trailing zeros less than or equal to 64 bits. * * Therefore, initially validating all non-'0' values prior to calling assembly- * optimized CPU_CntTrailZeros() avoids having to offset the number of returned * trailing zeros by the difference in CPU data size and 64-bit data value bits. * * (b) For CPU_CntTrailZeros64()'s C implementation, the final conditional statement * calculates 'val's number of trailing zeros based on CPU_CntTrailZeros64()'s * 64-bit return data size & 'val's calculated number of lead zeros ONLY if the * initial 'val' is non-'0' : * * if (val != 0u) { * nbr_trail_zeros = ((CPU_WORD_SIZE_64 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros; * } else { * nbr_trail_zeros = nbr_lead_zeros; * } * * Therefore, initially validating all non-'0' values avoids having to conditionally * execute the final 'if' statement. ********************************************************************************************************* */ #if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_64) CPU_DATA CPU_CntTrailZeros64 (CPU_INT64U val) { #if (!((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_64))) CPU_INT64U val_bit_mask; CPU_DATA nbr_lead_zeros; #endif CPU_DATA nbr_trail_zeros; if (val == 0u) { /* Rtn ALL val bits as zero'd (see Note #3). */ return ((CPU_DATA)(CPU_WORD_SIZE_64 * DEF_OCTET_NBR_BITS)); } /* ------------------ ASM-OPTIMIZED ------------------- */ #if ((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \ (CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_64)) nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val); #else /* ------------------- C-OPTIMIZED -------------------- */ val_bit_mask = val & ((CPU_INT64U)~val + 1u); /* Zero/clr all bits EXCEPT least-sig set bit. */ nbr_lead_zeros = CPU_CntLeadZeros64(val_bit_mask); /* Cnt nbr lead 0s. */ /* Calc nbr trail 0s = (nbr val bits - 1) - nbr lead 0s.*/ nbr_trail_zeros = ((CPU_DATA)((CPU_WORD_SIZE_64 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros); #endif return (nbr_trail_zeros); } #endif /* ********************************************************************************************************* * CRCUtil_PopCnt_32() * * Description : Compute population count (hamming weight) for value (number of bits set). * * Argument(s) : value Value to compute population count on. * * * Return(s) : value's population count. * * Note(s) : (1) Algorithm taken from en.wikipedia.org/wiki/Hamming_weight ********************************************************************************************************* */ CPU_INT08U CPU_PopCnt32 (CPU_INT32U value) { CPU_INT32U even_cnt; CPU_INT32U odd_cnt; CPU_INT32U result; odd_cnt = (value >> 1u) & CRC_UTIL_POPCNT_MASK01010101_32; /* 2-bits pieces. */ result = value - odd_cnt; /* Same result as result=odd_cnt+(value & 0x55555555). */ even_cnt = result & CRC_UTIL_POPCNT_MASK00110011_32; /* 4-bits pieces. */ odd_cnt = (result >> 2u) & CRC_UTIL_POPCNT_MASK00110011_32; result = even_cnt + odd_cnt; even_cnt = result & CRC_UTIL_POPCNT_MASK00001111_32; /* 8-bits pieces. */ odd_cnt = (result >> 4u) & CRC_UTIL_POPCNT_MASK00001111_32; result = even_cnt + odd_cnt; result = (result * CRC_UTIL_POPCNT_POWERSOF256_32) >> 24u; return ((CPU_INT08U)result); } /* ********************************************************************************************************* * CPU_StatReset() * * Description : Reset all performance monitors. * * Argument(s) : none. * * Return(s) : none. * * Note(s) : Critical section provided by caller. ********************************************************************************************************* */ #if (CPU_CFG_PERF_MON_EN == DEF_ENABLED) void CPU_StatReset (void) { #ifdef CPU_CFG_INT_DIS_MEAS_EN CPU_IntDisMeasMax_cnts = 0u; #endif } #endif /* ********************************************************************************************************* ********************************************************************************************************* * LOCAL FUNCTIONS ********************************************************************************************************* ********************************************************************************************************* */ /* ********************************************************************************************************* * CPU_NameInit() * * Description : Initialize CPU Name. * * Argument(s) : none. * * Return(s) : none. * * Note(s) : none. ********************************************************************************************************* */ #if (CPU_CFG_NAME_EN == DEF_ENABLED) static void CPU_NameInit (void) { CPU_NameClr(); } #endif /* ********************************************************************************************************* * CPU_TS_Init() * * Description : (1) Initialize CPU timestamp : * * (a) Initialize/start CPU timestamp timer See Note #1 * (b) Initialize CPU timestamp controls * * * Argument(s) : none. * * Return(s) : none. * * Note(s) : (1) The following initialization MUST be sequenced as follows : * * (a) CPU_TS_TmrFreq_Hz MUST be initialized prior to CPU_TS_TmrInit() * (b) CPU_TS_TmrInit() SHOULD precede calls to all other CPU timestamp functions; * otherwise, invalid time measurements may be calculated/ * returned. * * See also 'CPU_Init() Note #3a'. ********************************************************************************************************* */ #if ((CPU_CFG_TS_EN == DEF_ENABLED) || \ (CPU_CFG_TS_TMR_EN == DEF_ENABLED)) static void CPU_TS_Init (void) { #if (((CPU_CFG_TS_32_EN == DEF_ENABLED ) && \ (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)) || \ ((CPU_CFG_TS_64_EN == DEF_ENABLED ) && \ (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64))) CPU_TS_TMR ts_tmr_cnts; #endif /* ----------------- INIT CPU TS TMR ------------------ */ #if (CPU_CFG_TS_TMR_EN == DEF_ENABLED) CPU_TS_TmrFreq_Hz = 0u; /* Init/clr ts tmr freq (see Note #1a). */ CPU_TS_TmrInit(); /* Init & start ts tmr (see Note #1b). */ #endif /* ------------------- INIT CPU TS -------------------- */ #if (((CPU_CFG_TS_32_EN == DEF_ENABLED ) && \ (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)) || \ ((CPU_CFG_TS_64_EN == DEF_ENABLED ) && \ (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64))) ts_tmr_cnts = CPU_TS_TmrRd(); /* Get init ts tmr val (in ts tmr cnts). */ #endif #if ((CPU_CFG_TS_32_EN == DEF_ENABLED) && \ (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)) CPU_TS_32_Accum = 0u; /* Init 32-bit accum'd ts. */ CPU_TS_32_TmrPrev = ts_tmr_cnts; /* Init 32-bit ts prev tmr val. */ #endif #if ((CPU_CFG_TS_64_EN == DEF_ENABLED) && \ (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64)) CPU_TS_64_Accum = 0u; /* Init 64-bit accum'd ts. */ CPU_TS_64_TmrPrev = ts_tmr_cnts; /* Init 64-bit ts prev tmr val. */ #endif } #endif /* ********************************************************************************************************* * CPU_IntDisMeasInit() * * Description : (1) Initialize interrupts disabled time measurements feature : * * (a) Initialize interrupts disabled time measurement controls * (b) Calculate interrupts disabled time measurement overhead * * * Argument(s) : none. * * Return(s) : none. * * Note(s) : (2) CPU_IntDisMeasInit() SHOULD precede ALL calls to CPU_CRITICAL_ENTER()/CPU_CRITICAL_EXIT() * & other CPU interrupts disabled time measurement functions; otherwise, invalid interrupts * disabled time measurements may be calculated/returned. * * See also 'CPU_Init() Note #3b'. * * (3) (a) (1) Interrupts disabled time measurement overhead performed multiple times to calculate * a rounded average with better accuracy, hopefully of +/- one timer count. * * (2) However, a single overhead time measurement is recommended, even for instruction- * cache-enabled CPUs, since critical sections are NOT typically called within * instruction-cached loops. Thus a single non-cached/non-averaged time measurement * is a more realistic overhead for the majority of non-cached interrupts disabled * time measurements. * * (b) Interrupts MUST be disabled while measuring the interrupts disabled time measurement * overhead; otherwise, overhead measurements could be interrupted which would incorrectly * calculate an inflated overhead time which would then incorrectly calculate deflated * interrupts disabled times. ********************************************************************************************************* */ #ifdef CPU_CFG_INT_DIS_MEAS_EN static void CPU_IntDisMeasInit (void) { CPU_TS_TMR time_meas_tot_cnts; CPU_INT16U i; CPU_SR_ALLOC(); /* ----------- INIT INT DIS TIME MEAS CTRLS ----------- */ CPU_IntDisMeasCtr = 0u; CPU_IntDisNestCtr = 0u; CPU_IntDisMeasStart_cnts = 0u; CPU_IntDisMeasStop_cnts = 0u; CPU_IntDisMeasMaxCur_cnts = 0u; CPU_IntDisMeasMax_cnts = 0u; CPU_IntDisMeasOvrhd_cnts = 0u; /* ----------- CALC INT DIS TIME MEAS OVRHD ----------- */ time_meas_tot_cnts = 0u; CPU_INT_DIS(); /* Ints MUST be dis'd for ovrhd calc (see Note #3b). */ for (i = 0u; i < CPU_CFG_INT_DIS_MEAS_OVRHD_NBR; i++) { CPU_IntDisMeasMaxCur_cnts = 0u; CPU_IntDisMeasStart(); /* Perform multiple consecutive start/stop time meas's */ CPU_IntDisMeasStop(); time_meas_tot_cnts += CPU_IntDisMeasMaxCur_cnts; /* ... & sum time meas max's ... */ } /* ... to calc avg time meas ovrhd (see Note #3a). */ CPU_IntDisMeasOvrhd_cnts = (time_meas_tot_cnts + (CPU_CFG_INT_DIS_MEAS_OVRHD_NBR / 2u)) / CPU_CFG_INT_DIS_MEAS_OVRHD_NBR; CPU_IntDisMeasMaxCur_cnts = 0u; /* Reset max ints dis'd times. */ CPU_IntDisMeasMax_cnts = 0u; CPU_INT_EN(); } #endif /* ********************************************************************************************************* * CPU_IntDisMeasMaxCalc() * * Description : Calculate maximum interrupts disabled time. * * Argument(s) : time_tot_cnts Total interrupt disabled time, in timer counts. * * Return(s) : Maximum interrupts disabled time (in CPU timestamp timer counts). * * Note(s) : (1) (a) The total amount of time interrupts are disabled by system &/or application code * during critical sections is calculated by the following equations : * * (1) time = [ time - time ] - time * interrupts [ stop start ] total meas * disabled [ meas meas ] ovrhd * (via application) * * * (2) time = time + time * total meas start meas stop meas * ovrhd ovrhd ovrhd * * * where * * time time interrupts are disabled between * interrupts first critical section enter & * disabled last critical section exit minus * (via application) time measurement overhead * * time time of disable interrupts start time * start measurement (in timer counts) * meas * * time time of disable interrupts stop time * stop measurement (in timer counts) * meas * * time total overhead time to start/stop disabled * total meas interrupts time measurements (in timer * ovrhd counts) * * time total overhead time after getting start * start meas time until end of start measurement * ovrhd function (in timer counts) * * time total overhead time from beginning of stop * stop meas measurement function until after getting * ovrhd stop time (in timer counts) * * * (b) To expedite & reduce interrupts disabled time measurement overhead, the final * calculations to subtract the interrupts disabled time measurement overhead is * performed asynchronously in API functions. * * See also 'CPU_IntDisMeasStop() Note #1b2'. * * (c) The amount of time interrupts are disabled is calculated by either of the * following equations : * * (1) Interrupts disabled time = Number timer counts * Timer period * * where * * Number timer counts Number of timer counts measured * Timer period Timer's period in some units of * (fractional) seconds * Interrupts disabled time Amount of time interrupts are * disabled, in same units of * (fractional) seconds as the * Timer period * * Number timer counts * (2) Interrupts disabled time = --------------------- * Timer frequency * * where * * Number timer counts Number of timer counts measured * Timer frequency Timer's frequency in some units * of counts per second * Interrupts disabled time Amount of time interrupts are * disabled, in seconds * * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c' * & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'. * * (2) Although it is not typical, it is possible for an interrupts disabled time * measurement to be less than the interrupts disabled time measurement overhead; * especially if the overhead was calculated with a single, non-cached measurement * & critical sections are called within instruction-cached loops. ********************************************************************************************************* */ #ifdef CPU_CFG_INT_DIS_MEAS_EN static CPU_TS_TMR CPU_IntDisMeasMaxCalc (CPU_TS_TMR time_tot_cnts) { CPU_TS_TMR time_max_cnts; time_max_cnts = time_tot_cnts; if (time_max_cnts > CPU_IntDisMeasOvrhd_cnts) { /* If max ints dis'd time > ovrhd time, ... */ time_max_cnts -= CPU_IntDisMeasOvrhd_cnts; /* ... adj max ints dis'd time by ovrhd time; ... */ } else { /* ... else max ints dis'd time < ovrhd time, ... */ time_max_cnts = 0u; /* ... clr max ints dis'd time (see Note #2). */ } return (time_max_cnts); } #endif