| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cpu_core.c
Go to the documentation of this file.
1 /*
2 *********************************************************************************************************
3 * uC/CPU
4 * CPU CONFIGURATION & PORT LAYER
5 *
6 * (c) Copyright 2004-2011; Micrium, Inc.; Weston, FL
7 *
8 * All rights reserved. Protected by international copyright laws.
9 *
10 * uC/CPU is provided in source form to registered licensees ONLY. It is
11 * illegal to distribute this source code to any third party unless you receive
12 * written permission by an authorized Micrium representative. Knowledge of
13 * the source code may NOT be used to develop a similar product.
14 *
15 * Please help us continue to provide the Embedded community with the finest
16 * software available. Your honesty is greatly appreciated.
17 *
18 * You can contact us at www.micrium.com.
19 *********************************************************************************************************
20 */
21
22 /*
23 *********************************************************************************************************
24 *
25 * CORE CPU MODULE
26 *
27 * Filename : cpu_core.c
28 * Version : V1.28.00
29 * Programmer(s) : SR
30 * ITJ
31 *********************************************************************************************************
32 */
33
34
35 /*
36 *********************************************************************************************************
37 * INCLUDE FILES
38 *********************************************************************************************************
39 */
40
41 #define CPU_CORE_MODULE
42 #include <cpu_core.h>
43
44
45 /*$PAGE*/
46 /*
47 *********************************************************************************************************
48 * LOCAL DEFINES
49 *********************************************************************************************************
50 */
51
52
53 /*
54 *********************************************************************************************************
55 * LOCAL CONSTANTS
56 *********************************************************************************************************
57 */
58
59
60 /*
61 *********************************************************************************************************
62 * LOCAL DATA TYPES
63 *********************************************************************************************************
64 */
65
66
67 /*
68 *********************************************************************************************************
69 * LOCAL TABLES
70 *********************************************************************************************************
71 */
72
73 /*
74 *********************************************************************************************************
75 * CPU COUNT LEAD ZEROs LOOKUP TABLE
76 *
77 * Note(s) : (1) Index into bit pattern table determines the number of leading zeros in an 8-bit value :
78 *
79 * b07 b06 b05 b04 b03 b02 b01 b00 # Leading Zeros
80 * --- --- --- --- --- --- --- --- ---------------
81 * 1 x x x x x x x 0
82 * 0 1 x x x x x x 1
83 * 0 0 1 x x x x x 2
84 * 0 0 0 1 x x x x 3
85 * 0 0 0 0 1 x x x 4
86 * 0 0 0 0 0 1 x x 5
87 * 0 0 0 0 0 0 1 x 6
88 * 0 0 0 0 0 0 0 1 7
89 * 0 0 0 0 0 0 0 0 8
90 *********************************************************************************************************
91 */
92
93 #ifndef CPU_CFG_LEAD_ZEROS_ASM_PRESENT
94 static const CPU_INT08U CPU_CntLeadZerosTbl[256] = { /* Data vals : */
95 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
96 8u, 7u, 6u, 6u, 5u, 5u, 5u, 5u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, /* 0x00 to 0x0F */
97 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, /* 0x10 to 0x1F */
98 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, /* 0x20 to 0x2F */
99 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, /* 0x30 to 0x3F */
100 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x40 to 0x4F */
101 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x50 to 0x5F */
102 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x60 to 0x6F */
103 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x70 to 0x7F */
104 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0x80 to 0x8F */
105 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0x90 to 0x9F */
106 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xA0 to 0xAF */
107 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xB0 to 0xBF */
108 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xC0 to 0xCF */
109 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xD0 to 0xDF */
110 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xE0 to 0xEF */
111 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u /* 0xF0 to 0xFF */
112 };
113 #endif
114
115
116 /*$PAGE*/
117 /*
118 *********************************************************************************************************
119 * LOCAL GLOBAL VARIABLES
120 *********************************************************************************************************
121 */
122
123
124 /*
125 *********************************************************************************************************
126 * LOCAL FUNCTION PROTOTYPES
127 *********************************************************************************************************
128 */
129
130 #if (CPU_CFG_NAME_EN == DEF_ENABLED) /* ---------------- CPU NAME FNCTS ---------------- */
131 static void CPU_NameInit (void);
132 #endif
133
134
135 /* ----------------- CPU TS FNCTS ----------------- */
136 #if ((CPU_CFG_TS_EN == DEF_ENABLED) || \
137 (CPU_CFG_TS_TMR_EN == DEF_ENABLED))
138 static void CPU_TS_Init (void);
139 #endif
140
141
142 #ifdef CPU_CFG_INT_DIS_MEAS_EN /* ---------- CPU INT DIS TIME MEAS FNCTS --------- */
143 static void CPU_IntDisMeasInit (void);
144
145 static CPU_TS_TMR CPU_IntDisMeasMaxCalc(CPU_TS_TMR time_tot_cnts);
146 #endif
147
148
149 /*
150 *********************************************************************************************************
151 * LOCAL CONFIGURATION ERRORS
152 *********************************************************************************************************
153 */
154
155
156 /*$PAGE*/
157 /*
158 *********************************************************************************************************
159 * CPU_Init()
160 *
161 * Description : (1) Initialize CPU module :
162 *
163 * (a) Initialize CPU timestamps
164 * (b) Initialize CPU interrupts disabled time measurements
165 * (c) Initialize CPU host name
166 *
167 *
168 * Argument(s) : none.
169 *
170 * Return(s) : none.
171 *
172 * Caller(s) : Your Product's Application.
173 *
174 * This function is a CPU initialization function & MAY be called by application/
175 * initialization function(s).
176 *
177 * Note(s) : (2) CPU_Init() MUST be called ... :
178 *
179 * (a) ONLY ONCE from a product's application; ...
180 * (b) BEFORE product's application calls any core CPU module function(s)
181 *
182 * (3) The following initialization functions MUST be sequenced as follows :
183 *
184 * (a) CPU_TS_Init() SHOULD precede ALL calls to other CPU timestamp functions
185 *
186 * (b) CPU_IntDisMeasInit() SHOULD precede ALL calls to CPU_CRITICAL_ENTER()/CPU_CRITICAL_EXIT()
187 * & other CPU interrupts disabled time measurement functions
188 *********************************************************************************************************
189 */
190
191 void CPU_Init (void)
192 {
193 /* --------------------- INIT TS ---------------------- */
194 #if ((CPU_CFG_TS_EN == DEF_ENABLED) || \
195 (CPU_CFG_TS_TMR_EN == DEF_ENABLED))
196 CPU_TS_Init(); /* See Note #3a. */
197 #endif
198 /* -------------- INIT INT DIS TIME MEAS -------------- */
199 #ifdef CPU_CFG_INT_DIS_MEAS_EN
200 CPU_IntDisMeasInit(); /* See Note #3b. */
201 #endif
202
203 /* ------------------ INIT CPU NAME ------------------- */
204 #if (CPU_CFG_NAME_EN == DEF_ENABLED)
205 CPU_NameInit();
206 #endif
207 }
208
209
210 /*$PAGE*/
211 /*
212 *********************************************************************************************************
213 * CPU_SW_Exception()
214 *
215 * Description : Trap unrecoverable software exception.
216 *
217 * Argument(s) : none.
218 *
219 * Return(s) : none.
220 *
221 * Caller(s) : various.
222 *
223 * Note(s) : (1) CPU_SW_Exception() deadlocks the current code execution -- whether multi-tasked/
224 * -processed/-threaded or single-threaded -- when the current code execution cannot
225 * gracefully recover or report a fault or exception condition.
226 *
227 * See also 'cpu_core.h CPU_SW_EXCEPTION() Note #1'.
228 *********************************************************************************************************
229 */
230
231 void CPU_SW_Exception (void)
232 {
233 while (DEF_ON) {
234 ;
235 }
236 }
237
238
239 /*$PAGE*/
240 /*
241 *********************************************************************************************************
242 * CPU_NameClr()
243 *
244 * Description : Clear CPU Name.
245 *
246 * Argument(s) : none.
247 *
248 * Return(s) : none.
249 *
250 * Caller(s) : CPU_NameInit(),
251 * Application.
252 *
253 * This function is a CPU module application interface (API) function & MAY be called by
254 * application function(s).
255 *
256 * Note(s) : none.
257 *********************************************************************************************************
258 */
259
260 #if (CPU_CFG_NAME_EN == DEF_ENABLED)
261 void CPU_NameClr (void)
262 {
263 CPU_SR_ALLOC();
264
265
266 CPU_CRITICAL_ENTER();
267 Mem_Clr((void *)&CPU_Name[0],
268 (CPU_SIZE_T) CPU_CFG_NAME_SIZE);
269 CPU_CRITICAL_EXIT();
270 }
271 #endif
272
273
274 /*$PAGE*/
275 /*
276 *********************************************************************************************************
277 * CPU_NameGet()
278 *
279 * Description : Get CPU host name.
280 *
281 * Argument(s) : p_name Pointer to an ASCII character array that will receive the return CPU host
282 * name ASCII string from this function (see Note #1).
283 *
284 * p_err Pointer to variable that will receive the return error code from this function :
285 *
286 * CPU_ERR_NONE CPU host name successfully returned.
287 * CPU_ERR_NULL_PTR Argument 'p_name' passed a NULL pointer.
288 *
289 * Return(s) : none.
290 *
291 * Caller(s) : Application.
292 *
293 * This function is a CPU module application interface (API) function & MAY be called by
294 * application function(s).
295 *
296 * Note(s) : (1) The size of the ASCII character array that will receive the return CPU host name
297 * ASCII string :
298 *
299 * (a) MUST be greater than or equal to the current CPU host name's ASCII string
300 * size including the terminating NULL character;
301 * (b) SHOULD be greater than or equal to CPU_CFG_NAME_SIZE
302 *********************************************************************************************************
303 */
304
305 #if (CPU_CFG_NAME_EN == DEF_ENABLED)
306 void CPU_NameGet (CPU_CHAR *p_name,
307 CPU_ERR *p_err)
308 {
309 CPU_SR_ALLOC();
310
311
312 if (p_err == (CPU_ERR *)0) {
313 CPU_SW_EXCEPTION(;);
314 }
315
316 if (p_name == (CPU_CHAR *)0) {
317 *p_err = CPU_ERR_NULL_PTR;
318 return;
319 }
320
321 CPU_CRITICAL_ENTER();
322 (void)Str_Copy_N(p_name,
323 &CPU_Name[0],
324 CPU_CFG_NAME_SIZE);
325 CPU_CRITICAL_EXIT();
326
327 *p_err = CPU_ERR_NONE;
328 }
329 #endif
330
331
332 /*$PAGE*/
333 /*
334 *********************************************************************************************************
335 * CPU_NameSet()
336 *
337 * Description : Set CPU host name.
338 *
339 * Argument(s) : p_name Pointer to CPU host name to set.
340 *
341 * p_err Pointer to variable that will receive the return error code from this function :
342 *
343 * CPU_ERR_NONE CPU host name successfully set.
344 * CPU_ERR_NULL_PTR Argument 'p_name' passed a NULL pointer.
345 * CPU_ERR_NAME_SIZE Invalid CPU host name size (see Note #1).
346 *
347 * Return(s) : none.
348 *
349 * Caller(s) : Application.
350 *
351 * This function is a CPU module application interface (API) function & MAY be called by
352 * application function(s).
353 *
354 * Note(s) : (1) 'p_name' ASCII string size, including the terminating NULL character, MUST be less
355 * than or equal to CPU_CFG_NAME_SIZE.
356 *********************************************************************************************************
357 */
358
359 #if (CPU_CFG_NAME_EN == DEF_ENABLED)
360 void CPU_NameSet (const CPU_CHAR *p_name,
361 CPU_ERR *p_err)
362 {
363 CPU_SIZE_T len;
364 CPU_SR_ALLOC();
365
366
367 if (p_err == (CPU_ERR *)0) {
368 CPU_SW_EXCEPTION(;);
369 }
370
371 if (p_name == (const CPU_CHAR *)0) {
372 *p_err = CPU_ERR_NULL_PTR;
373 return;
374 }
375
376 len = Str_Len_N(p_name,
377 CPU_CFG_NAME_SIZE);
378 if (len < CPU_CFG_NAME_SIZE) { /* If cfg name len < max name size, ... */
379 CPU_CRITICAL_ENTER();
380 (void)Str_Copy_N(&CPU_Name[0], /* ... copy cfg name to CPU host name. */
381 p_name,
382 CPU_CFG_NAME_SIZE);
383 CPU_CRITICAL_EXIT();
384 *p_err = CPU_ERR_NONE;
385
386 } else {
387 *p_err = CPU_ERR_NAME_SIZE;
388 }
389 }
390 #endif
391
392
393 /*$PAGE*/
394 /*
395 *********************************************************************************************************
396 * CPU_TS_Get32()
397 *
398 * Description : Get current 32-bit CPU timestamp.
399 *
400 * Argument(s) : none.
401 *
402 * Return(s) : Current 32-bit CPU timestamp (in timestamp timer counts).
403 *
404 * Caller(s) : Application.
405 *
406 * This function is a CPU module application interface (API) function & MAY be called by
407 * application function(s).
408 *
409 * Note(s) : (1) When applicable, the amount of time measured by CPU timestamps is calculated by
410 * either of the following equations :
411 *
412 * (a) Time measured = Number timer counts * Timer period
413 *
414 * where
415 *
416 * Number timer counts Number of timer counts measured
417 * Timer period Timer's period in some units of
418 * (fractional) seconds
419 * Time measured Amount of time measured, in same
420 * units of (fractional) seconds
421 * as the Timer period
422 *
423 * Number timer counts
424 * (b) Time measured = ---------------------
425 * Timer frequency
426 *
427 * where
428 *
429 * Number timer counts Number of timer counts measured
430 * Timer frequency Timer's frequency in some units
431 * of counts per second
432 * Time measured Amount of time measured, in seconds
433 *
434 * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c1'.
435 *
436 * (2) In case the CPU timestamp timer has lower precision than the 32-bit CPU timestamp;
437 * its precision is extended via periodic updates by accumulating the deltas of the
438 * timestamp timer count values into the higher-precision 32-bit CPU timestamp.
439 *
440 * (3) After initialization, 'CPU_TS_32_Accum' & 'CPU_TS_32_TmrPrev' MUST ALWAYS
441 * be accessed AND updated exclusively with interrupts disabled -- but NOT
442 * with critical sections.
443 *********************************************************************************************************
444 */
445
446 #if (CPU_CFG_TS_32_EN == DEF_ENABLED)
447 CPU_TS32 CPU_TS_Get32 (void)
448 {
449 CPU_TS32 ts;
450 #if (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)
451 CPU_TS_TMR tmr_cur;
452 CPU_TS_TMR tmr_delta;
453 CPU_SR_ALLOC();
454 #endif
455
456
457 #if (CPU_CFG_TS_TMR_SIZE >= CPU_WORD_SIZE_32)
458 ts = (CPU_TS32)CPU_TS_TmrRd(); /* Get cur ts tmr val (in 32-bit ts cnts). */
459
460 #else
461 CPU_INT_DIS();
462 tmr_cur = (CPU_TS_TMR) CPU_TS_TmrRd(); /* Get cur ts tmr val (in ts tmr cnts). */
463 tmr_delta = (CPU_TS_TMR)(tmr_cur - CPU_TS_32_TmrPrev); /* Calc delta ts tmr cnts. */
464 CPU_TS_32_Accum += (CPU_TS32 ) tmr_delta; /* Inc ts by delta ts tmr cnts (see Note #2). */
465 CPU_TS_32_TmrPrev = (CPU_TS_TMR) tmr_cur; /* Save cur ts tmr cnts for next update. */
466 ts = (CPU_TS32 ) CPU_TS_32_Accum;
467 CPU_INT_EN();
468 #endif
469
470 return (ts);
471 }
472 #endif
473
474
475 /*$PAGE*/
476 /*
477 *********************************************************************************************************
478 * CPU_TS_Get64()
479 *
480 * Description : Get current 64-bit CPU timestamp.
481 *
482 * Argument(s) : none.
483 *
484 * Return(s) : Current 64-bit CPU timestamp (in timestamp timer counts).
485 *
486 * Caller(s) : Application.
487 *
488 * This function is a CPU module application interface (API) function & MAY be called by
489 * application function(s).
490 *
491 * Note(s) : (1) When applicable, the amount of time measured by CPU timestamps is calculated by
492 * either of the following equations :
493 *
494 * (a) Time measured = Number timer counts * Timer period
495 *
496 * where
497 *
498 * Number timer counts Number of timer counts measured
499 * Timer period Timer's period in some units of
500 * (fractional) seconds
501 * Time measured Amount of time measured, in same
502 * units of (fractional) seconds
503 * as the Timer period
504 *
505 * Number timer counts
506 * (b) Time measured = ---------------------
507 * Timer frequency
508 *
509 * where
510 *
511 * Number timer counts Number of timer counts measured
512 * Timer frequency Timer's frequency in some units
513 * of counts per second
514 * Time measured Amount of time measured, in seconds
515 *
516 * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c1'.
517 *
518 * (2) In case the CPU timestamp timer has lower precision than the 64-bit CPU timestamp;
519 * its precision is extended via periodic updates by accumulating the deltas of the
520 * timestamp timer count values into the higher-precision 64-bit CPU timestamp.
521 *
522 * (3) After initialization, 'CPU_TS_64_Accum' & 'CPU_TS_64_TmrPrev' MUST ALWAYS
523 * be accessed AND updated exclusively with interrupts disabled -- but NOT
524 * with critical sections.
525 *********************************************************************************************************
526 */
527
528 #if (CPU_CFG_TS_64_EN == DEF_ENABLED)
529 CPU_TS64 CPU_TS_Get64 (void)
530 {
531 CPU_TS64 ts;
532 #if (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64)
533 CPU_TS_TMR tmr_cur;
534 CPU_TS_TMR tmr_delta;
535 CPU_SR_ALLOC();
536 #endif
537
538
539 #if (CPU_CFG_TS_TMR_SIZE >= CPU_WORD_SIZE_64)
540 ts = (CPU_TS64)CPU_TS_TmrRd(); /* Get cur ts tmr val (in 64-bit ts cnts). */
541
542 #else
543 CPU_INT_DIS();
544 tmr_cur = (CPU_TS_TMR) CPU_TS_TmrRd(); /* Get cur ts tmr val (in ts tmr cnts). */
545 tmr_delta = (CPU_TS_TMR)(tmr_cur - CPU_TS_64_TmrPrev); /* Calc delta ts tmr cnts. */
546 CPU_TS_64_Accum += (CPU_TS64 ) tmr_delta; /* Inc ts by delta ts tmr cnts (see Note #2). */
547 CPU_TS_64_TmrPrev = (CPU_TS_TMR) tmr_cur; /* Save cur ts tmr cnts for next update. */
548 ts = (CPU_TS64 ) CPU_TS_64_Accum;
549 CPU_INT_EN();
550 #endif
551
552 return (ts);
553 }
554 #endif
555
556
557 /*$PAGE*/
558 /*
559 *********************************************************************************************************
560 * CPU_TS_Update()
561 *
562 * Description : Update current CPU timestamp(s).
563 *
564 * Argument(s) : none.
565 *
566 * Return(s) : none.
567 *
568 * Caller(s) : Application/BSP periodic time handler (see Note #1).
569 *
570 * This function is a CPU timestamp BSP function & SHOULD be called only by appropriate
571 * application/BSP function(s).
572 *
573 * Note(s) : (1) (a) CPU timestamp(s) MUST be updated periodically by some application (or BSP) time
574 * handler in order to (adequately) maintain CPU timestamp(s)' time.
575 *
576 * (b) CPU timestamp(s) MUST be updated more frequently than the CPU timestamp timer
577 * overflows; otherwise, CPU timestamp(s) will lose time.
578 *
579 * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c2'.
580 *********************************************************************************************************
581 */
582
583 #if (CPU_CFG_TS_EN == DEF_ENABLED)
584 void CPU_TS_Update (void)
585 {
586 #if ((CPU_CFG_TS_32_EN == DEF_ENABLED) && \
587 (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32))
588 (void)CPU_TS_Get32();
589 #endif
590
591 #if ((CPU_CFG_TS_64_EN == DEF_ENABLED) && \
592 (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64))
593 (void)CPU_TS_Get64();
594 #endif
595 }
596 #endif
597
598
599 /*$PAGE*/
600 /*
601 *********************************************************************************************************
602 * CPU_TS_TmrFreqGet()
603 *
604 * Description : Get CPU timestamp's timer frequency.
605 *
606 * Argument(s) : p_err Pointer to variable that will receive the return error code from this function :
607 *
608 * CPU_ERR_NONE CPU timestamp's timer frequency successfully
609 * returned.
610 * CPU_ERR_TS_FREQ_INVALID CPU timestamp's timer frequency invalid &/or
611 * NOT yet configured.
612 *
613 * Return(s) : CPU timestamp's timer frequency (in Hertz), if NO error(s).
614 *
615 * 0, otherwise.
616 *
617 * Caller(s) : Application.
618 *
619 * This function is a CPU module application interface (API) function & MAY be called by
620 * application function(s).
621 *
622 * Note(s) : none.
623 *********************************************************************************************************
624 */
625
626 #if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
627 CPU_TS_TMR_FREQ CPU_TS_TmrFreqGet (CPU_ERR *p_err)
628 {
629 CPU_TS_TMR_FREQ freq_hz;
630
631
632 if (p_err == (CPU_ERR *)0) {
633 CPU_SW_EXCEPTION(;);
634 }
635
636 freq_hz = CPU_TS_TmrFreq_Hz;
637 *p_err = (freq_hz != 0) ? CPU_ERR_NONE : CPU_ERR_TS_FREQ_INVALID;
638
639 return (freq_hz);
640 }
641 #endif
642
643
644 /*$PAGE*/
645 /*
646 *********************************************************************************************************
647 * CPU_TS_TmrFreqSet()
648 *
649 * Description : Set CPU timestamp's timer frequency.
650 *
651 * Argument(s) : freq_hz Frequency (in Hertz) to set for CPU timestamp's timer.
652 *
653 * Return(s) : none.
654 *
655 * Caller(s) : CPU_TS_TmrInit(),
656 * Application/BSP initialization function(s).
657 *
658 * This function is a CPU module BSP function & SHOULD be called only by appropriate
659 * application/BSP function(s) [see Note #1].
660 *
661 * Note(s) : (1) (a) (1) CPU timestamp timer frequency is NOT required for internal CPU timestamp
662 * operations but may OPTIONALLY be configured by CPU_TS_TmrInit() or other
663 * application/BSP initialization functions.
664 *
665 * (2) CPU timestamp timer frequency MAY be used with optional CPU_TSxx_to_uSec()
666 * to convert CPU timestamps from timer counts into microseconds.
667 *
668 * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2a'.
669 *
670 * (b) CPU timestamp timer period SHOULD be less than the typical measured time but MUST
671 * be less than the maximum measured time; otherwise, timer resolution inadequate to
672 * measure desired times.
673 *
674 * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2b'.
675 *********************************************************************************************************
676 */
677
678 #if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
679 void CPU_TS_TmrFreqSet (CPU_TS_TMR_FREQ freq_hz)
680 {
681 CPU_TS_TmrFreq_Hz = freq_hz;
682 }
683 #endif
684
685
686 /*$PAGE*/
687 /*
688 *********************************************************************************************************
689 * CPU_IntDisMeasMaxCurReset()
690 *
691 * Description : Reset current maximum interrupts disabled time.
692 *
693 * Argument(s) : none.
694 *
695 * Return(s) : Maximum interrupts disabled time (in CPU timestamp timer counts) before resetting.
696 *
697 * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c'
698 * & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'.
699 *
700 * Caller(s) : Application.
701 *
702 * This function is a CPU module application interface (API) function & MAY be called
703 * by application function(s).
704 *
705 * Note(s) : (1) After initialization, 'CPU_IntDisMeasMaxCur_cnts' MUST ALWAYS be accessed
706 * exclusively with interrupts disabled -- but NOT with critical sections.
707 *********************************************************************************************************
708 */
709
710 #ifdef CPU_CFG_INT_DIS_MEAS_EN
711 CPU_TS_TMR CPU_IntDisMeasMaxCurReset (void)
712 {
713 CPU_TS_TMR time_max_cnts;
714 CPU_SR_ALLOC();
715
716
717 time_max_cnts = CPU_IntDisMeasMaxCurGet();
718 CPU_INT_DIS();
719 CPU_IntDisMeasMaxCur_cnts = 0u;
720 CPU_INT_EN();
721
722 return (time_max_cnts);
723 }
724 #endif
725
726
727 /*$PAGE*/
728 /*
729 *********************************************************************************************************
730 * CPU_IntDisMeasMaxCurGet()
731 *
732 * Description : Get current maximum interrupts disabled time.
733 *
734 * Argument(s) : none.
735 *
736 * Return(s) : Current maximum interrupts disabled time (in CPU timestamp timer counts).
737 *
738 * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c'
739 * & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'.
740 *
741 * Caller(s) : CPU_IntDisMeasMaxCurReset(),
742 * Application.
743 *
744 * This function is a CPU module application interface (API) function & MAY be called
745 * by application function(s).
746 *
747 * Note(s) : (1) After initialization, 'CPU_IntDisMeasMaxCur_cnts' MUST ALWAYS be accessed
748 * exclusively with interrupts disabled -- but NOT with critical sections.
749 *********************************************************************************************************
750 */
751
752 #ifdef CPU_CFG_INT_DIS_MEAS_EN
753 CPU_TS_TMR CPU_IntDisMeasMaxCurGet (void)
754 {
755 CPU_TS_TMR time_tot_cnts;
756 CPU_TS_TMR time_max_cnts;
757 CPU_SR_ALLOC();
758
759
760 CPU_INT_DIS();
761 time_tot_cnts = CPU_IntDisMeasMaxCur_cnts;
762 CPU_INT_EN();
763 time_max_cnts = CPU_IntDisMeasMaxCalc(time_tot_cnts);
764
765 return (time_max_cnts);
766 }
767 #endif
768
769
770 /*$PAGE*/
771 /*
772 *********************************************************************************************************
773 * CPU_IntDisMeasMaxGet()
774 *
775 * Description : Get (non-resetable) maximum interrupts disabled time.
776 *
777 * Argument(s) : none.
778 *
779 * Return(s) : (Non-resetable) maximum interrupts disabled time (in CPU timestamp timer counts).
780 *
781 * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c'
782 * & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'.
783 *
784 * Caller(s) : CPU_IntDisMeasInit(),
785 * Application.
786 *
787 * This function is a CPU module application interface (API) function & MAY be called
788 * by application function(s).
789 *
790 * Note(s) : (1) After initialization, 'CPU_IntDisMeasMax_cnts' MUST ALWAYS be accessed
791 * exclusively with interrupts disabled -- but NOT with critical sections.
792 *********************************************************************************************************
793 */
794
795 #ifdef CPU_CFG_INT_DIS_MEAS_EN
796 CPU_TS_TMR CPU_IntDisMeasMaxGet (void)
797 {
798 CPU_TS_TMR time_tot_cnts;
799 CPU_TS_TMR time_max_cnts;
800 CPU_SR_ALLOC();
801
802
803 CPU_INT_DIS();
804 time_tot_cnts = CPU_IntDisMeasMax_cnts;
805 CPU_INT_EN();
806 time_max_cnts = CPU_IntDisMeasMaxCalc(time_tot_cnts);
807
808 return (time_max_cnts);
809 }
810 #endif
811
812
813 /*$PAGE*/
814 /*
815 *********************************************************************************************************
816 * CPU_IntDisMeasStart()
817 *
818 * Description : Start interrupts disabled time measurement.
819 *
820 * Argument(s) : none.
821 *
822 * Return(s) : none.
823 *
824 * Caller(s) : CPU_CRITICAL_ENTER().
825 *
826 * This function is an INTERNAL CPU module function & MUST NOT be called by application
827 * function(s).
828 *
829 * Note(s) : none.
830 *********************************************************************************************************
831 */
832
833 #ifdef CPU_CFG_INT_DIS_MEAS_EN
834 void CPU_IntDisMeasStart (void)
835 {
836 CPU_IntDisMeasCtr++;
837 if (CPU_IntDisNestCtr == 0u) { /* If ints NOT yet dis'd, ... */
838 CPU_IntDisMeasStart_cnts = CPU_TS_TmrRd(); /* ... get ints dis'd start time. */
839 }
840 CPU_IntDisNestCtr++;
841 }
842 #endif
843
844
845 /*$PAGE*/
846 /*
847 *********************************************************************************************************
848 * CPU_IntDisMeasStop()
849 *
850 * Description : Stop interrupts disabled time measurement.
851 *
852 * Argument(s) : none.
853 *
854 * Return(s) : none.
855 *
856 * Caller(s) : CPU_CRITICAL_EXIT().
857 *
858 * This function is an INTERNAL CPU module function & MUST NOT be called by application
859 * function(s).
860 *
861 * Note(s) : (1) (a) The total amount of time interrupts are disabled by system &/or application code
862 * during critical sections is calculated by the following equations :
863 *
864 * (1) When interrupts disabled time measurements are disabled :
865 *
866 *
867 * | CRITICAL | | CRITICAL |
868 * |<- SECTION ->| |<- SECTION ->|
869 * | ENTER | | EXIT |
870 *
871 * Disable Enable
872 * Interrupts Interrupts
873 *
874 * || || || ||
875 * || || || ||
876 * || | ||<------------------------->|| | ||
877 * || |<->|| | ||<----->| ||
878 * || | | || | || | | ||
879 * | | | | |
880 * interrupts time interrupts
881 * disabled interrupts |enabled
882 * | disabled |
883 * | (via application) |
884 * time time
885 * interrupts interrupts
886 * disabled ovrhd enabled ovrhd
887 *
888 *
889 * (A) time = [ time - time ] - time
890 * interrupts [ interrupts interrupts ] total
891 * disabled [ enabled disabled ] ovrhd
892 * (via application)
893 *
894 *
895 * (B) time = time + time
896 * total interrupts interrupts
897 * ovrhd enabled ovrhd disabled ovrhd
898 *
899 *
900 * where
901 *
902 * time time interrupts are disabled between
903 * interrupts first critical section enter &
904 * disabled last critical section exit (i.e.
905 * (via application) minus total overhead time)
906 *
907 * time time when interrupts are disabled
908 * interrupts
909 * disabled
910 *
911 * time time when interrupts are enabled
912 * interrupts
913 * enabled
914 *
915 *
916 * time total overhead time to disable/enable
917 * total interrupts during critical section
918 * ovrhd enter & exit
919 *
920 * time total overhead time to disable interrupts
921 * interrupts during critical section enter
922 * disabled ovrhd
923 *
924 * time total overhead time to enable interrupts
925 * interrupts during critical section exit
926 * enabled ovrhd
927 *
928 *$PAGE*
929 *
930 * (2) When interrupts disabled time measurements are enabled :
931 *
932 *
933 * | | | |
934 * |<----- CRITICAL SECTION ENTER ----->| |<------- CRITICAL SECTION EXIT ------->|
935 * | | | |
936 *
937 * Time Time
938 * Disable Measurement Measurement Enable
939 * Interrupts Start Stop Interrupts
940 *
941 * || | || || | ||
942 * || | || || | ||
943 * || | | ||<------------------------->|| | | ||
944 * || | | |<----------->|| | ||<------------->| | | ||
945 * || | | | | || | || | | | | ||
946 * | | | | | | |
947 * interrupts get | time | get interrupts
948 * disabled start time | interrupts | stop time enabled
949 * meas | disabled | meas
950 * time (via application) time
951 * start meas stop meas
952 * ovrhd ovrhd
953 *
954 *
955 * (A) time = [ time - time ] - time
956 * interrupts [ stop start ] total meas
957 * disabled [ meas meas ] ovrhd
958 * (via application)
959 *
960 *
961 * (B) time = time + time
962 * total meas start meas stop meas
963 * ovrhd ovrhd ovrhd
964 *
965 *
966 * where
967 *
968 * time time interrupts are disabled between first
969 * interrupts critical section enter & last critical
970 * disabled section exit (i.e. minus measurement
971 * (via application) overhead time; however, this does NOT
972 * include any overhead time to disable
973 * or enable interrupts during critical
974 * section enter & exit)
975 *
976 * time time of disable interrupts start time
977 * start measurement (in timer counts)
978 * meas
979 *
980 * time time of disable interrupts stop time
981 * stop measurement (in timer counts)
982 * meas
983 *
984 *
985 * time total overhead time to start/stop disabled
986 * total meas interrupts time measurements (in timer
987 * ovrhd counts)
988 *
989 * time total overhead time after getting start
990 * start meas time until end of start measurement
991 * ovrhd function (in timer counts)
992 *
993 * time total overhead time from beginning of stop
994 * stop meas measurement function until after getting
995 * ovrhd stop time (in timer counts)
996 *
997 *
998 *$PAGE*
999 * (b) (1) (A) In order to correctly handle unsigned subtraction overflows of start times
1000 * from stop times, CPU timestamp timer count values MUST be returned via
1001 * word-size-configurable 'CPU_TS_TMR' data type.
1002 *
1003 * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2a'.
1004 *
1005 * (B) Since unsigned subtraction of start times from stop times assumes increasing
1006 * values, timestamp timer count values MUST increase with each time count.
1007 *
1008 * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2b'.
1009 *
1010 * (2) (A) To expedite & reduce interrupts disabled time measurement overhead; only the
1011 * subtraction of start times from stop times is performed.
1012 *
1013 * (B) The final calculations to subtract the interrupts disabled time measurement
1014 * overhead is performed asynchronously in appropriate API functions.
1015 *
1016 * See also 'CPU_IntDisMeasMaxCalc() Note #1b'.
1017 *********************************************************************************************************
1018 */
1019
1020 #ifdef CPU_CFG_INT_DIS_MEAS_EN
1021 void CPU_IntDisMeasStop (void)
1022 {
1023 CPU_TS_TMR time_ints_disd_cnts;
1024
1025
1026 CPU_IntDisNestCtr--;
1027 if (CPU_IntDisNestCtr == 0u) { /* If ints NO longer dis'd, ... */
1028 CPU_IntDisMeasStop_cnts = CPU_TS_TmrRd(); /* ... get ints dis'd stop time & ... */
1029 /* ... calc ints dis'd tot time (see Note #1b2A). */
1030 time_ints_disd_cnts = CPU_IntDisMeasStop_cnts -
1031 CPU_IntDisMeasStart_cnts;
1032 /* Calc max ints dis'd times. */
1033 if (CPU_IntDisMeasMaxCur_cnts < time_ints_disd_cnts) {
1034 CPU_IntDisMeasMaxCur_cnts = time_ints_disd_cnts;
1035 }
1036 if (CPU_IntDisMeasMax_cnts < time_ints_disd_cnts) {
1037 CPU_IntDisMeasMax_cnts = time_ints_disd_cnts;
1038 }
1039 }
1040 }
1041 #endif
1042
1043
1044 /*$PAGE*/
1045 /*
1046 *********************************************************************************************************
1047 * CPU_CntLeadZeros()
1048 *
1049 * Description : Count the number of contiguous, most-significant, leading zero bits in a data value.
1050 *
1051 * Argument(s) : val Data value to count leading zero bits.
1052 *
1053 * Return(s) : Number of contiguous, most-significant, leading zero bits in 'val', if NO error(s).
1054 *
1055 * 0, otherwise.
1056 *
1057 * Caller(s) : Application.
1058 *
1059 * This function is an INTERNAL CPU module function but MAY be called by application function(s).
1060 *
1061 * Note(s) : (1) (a) Supports the following data value sizes :
1062 *
1063 * (1) 8-bits
1064 * (2) 16-bits
1065 * (3) 32-bits
1066 * (4) 64-bits
1067 *
1068 * See also 'cpu_def.h CPU WORD CONFIGURATION Note #1'.
1069 *
1070 * (b) (1) For 8-bit values :
1071 *
1072 * b07 b06 b05 b04 b03 b02 b01 b00 # Leading Zeros
1073 * --- --- --- --- --- --- --- --- ---------------
1074 * 1 x x x x x x x 0
1075 * 0 1 x x x x x x 1
1076 * 0 0 1 x x x x x 2
1077 * 0 0 0 1 x x x x 3
1078 * 0 0 0 0 1 x x x 4
1079 * 0 0 0 0 0 1 x x 5
1080 * 0 0 0 0 0 0 1 x 6
1081 * 0 0 0 0 0 0 0 1 7
1082 * 0 0 0 0 0 0 0 0 8
1083 *
1084 *
1085 * (2) For 16-bit values :
1086 *
1087 * b15 b14 b13 ... b04 b03 b02 b01 b00 # Leading Zeros
1088 * --- --- --- --- --- --- --- --- ---------------
1089 * 1 x x x x x x x 0
1090 * 0 1 x x x x x x 1
1091 * 0 0 1 x x x x x 2
1092 * : : : : : : : : :
1093 * : : : : : : : : :
1094 * 0 0 0 1 x x x x 11
1095 * 0 0 0 0 1 x x x 12
1096 * 0 0 0 0 0 1 x x 13
1097 * 0 0 0 0 0 0 1 x 14
1098 * 0 0 0 0 0 0 0 1 15
1099 * 0 0 0 0 0 0 0 0 16
1100 *
1101 *
1102 * (3) For 32-bit values :
1103 *
1104 * b31 b30 b29 ... b04 b03 b02 b01 b00 # Leading Zeros
1105 * --- --- --- --- --- --- --- --- ---------------
1106 * 1 x x x x x x x 0
1107 * 0 1 x x x x x x 1
1108 * 0 0 1 x x x x x 2
1109 * : : : : : : : : :
1110 * : : : : : : : : :
1111 * 0 0 0 1 x x x x 27
1112 * 0 0 0 0 1 x x x 28
1113 * 0 0 0 0 0 1 x x 29
1114 * 0 0 0 0 0 0 1 x 30
1115 * 0 0 0 0 0 0 0 1 31
1116 * 0 0 0 0 0 0 0 0 32
1117 *
1118 *$PAGE*
1119 * (4) For 64-bit values :
1120 *
1121 * b63 b62 b61 ... b04 b03 b02 b01 b00 # Leading Zeros
1122 * --- --- --- --- --- --- --- --- ---------------
1123 * 1 x x x x x x x 0
1124 * 0 1 x x x x x x 1
1125 * 0 0 1 x x x x x 2
1126 * : : : : : : : : :
1127 * : : : : : : : : :
1128 * 0 0 0 1 x x x x 59
1129 * 0 0 0 0 1 x x x 60
1130 * 0 0 0 0 0 1 x x 61
1131 * 0 0 0 0 0 0 1 x 62
1132 * 0 0 0 0 0 0 0 1 63
1133 * 0 0 0 0 0 0 0 0 64
1134 *
1135 *
1136 * See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE Note #1'.
1137 *********************************************************************************************************
1138 */
1139
1140 #ifndef CPU_CFG_LEAD_ZEROS_ASM_PRESENT
1141 CPU_DATA CPU_CntLeadZeros (CPU_DATA val)
1142 {
1143 CPU_DATA nbr_lead_zeros;
1144 CPU_INT08U ix;
1145
1146
1147 #if (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_08) /* ---------- 8-BIT DATA VAL --------- */
1148 /* Chk bits [07:00] : */
1149 /* .. Nbr lead zeros = .. */
1150 ix = (CPU_INT08U)(val >> 0u); /* .. lookup tbl ix = 'val' >> 0 bits */
1151 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 0u); /* .. plus nbr msb lead zeros = 0 bits.*/
1152
1153
1154 #elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_16) /* ---------- 16-BIT DATA VAL --------- */
1155 if (val > 0x00FFu) { /* Chk bits [15:08] : */
1156 /* .. Nbr lead zeros = .. */
1157 ix = (CPU_INT08U)(val >> 8u); /* .. lookup tbl ix = 'val' >> 8 bits */
1158 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 0u); /* .. plus nbr msb lead zeros = 0 bits.*/
1159
1160 } else { /* Chk bits [07:00] : */
1161 /* .. Nbr lead zeros = .. */
1162 ix = (CPU_INT08U)(val >> 0u); /* .. lookup tbl ix = 'val' >> 0 bits */
1163 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 8u); /* .. plus nbr msb lead zeros = 8 bits.*/
1164 }
1165
1166
1167 #elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_32) /* ---------- 32-BIT DATA VAL --------- */
1168 if (val > 0x0000FFFFu) {
1169 if (val > 0x00FFFFFFu) { /* Chk bits [31:24] : */
1170 /* .. Nbr lead zeros = .. */
1171 ix = (CPU_INT08U)(val >> 24u); /* .. lookup tbl ix = 'val' >> 24 bits */
1172 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 0u); /* .. plus nbr msb lead zeros = 0 bits.*/
1173
1174 } else { /* Chk bits [23:16] : */
1175 /* .. Nbr lead zeros = .. */
1176 ix = (CPU_INT08U)(val >> 16u); /* .. lookup tbl ix = 'val' >> 16 bits */
1177 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 8u); /* .. plus nbr msb lead zeros = 8 bits.*/
1178 }
1179
1180 } else {
1181 if (val > 0x000000FFu) { /* Chk bits [15:08] : */
1182 /* .. Nbr lead zeros = .. */
1183 ix = (CPU_INT08U)(val >> 8u); /* .. lookup tbl ix = 'val' >> 8 bits */
1184 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 16u); /* .. plus nbr msb lead zeros = 16 bits.*/
1185
1186 } else { /* Chk bits [07:00] : */
1187 /* .. Nbr lead zeros = .. */
1188 ix = (CPU_INT08U)(val >> 0u); /* .. lookup tbl ix = 'val' >> 0 bits */
1189 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 24u); /* .. plus nbr msb lead zeros = 24 bits.*/
1190 }
1191 }
1192
1193 /*$PAGE*/
1194 #elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_64) /* ---------- 64-BIT DATA VAL --------- */
1195 if (val > 0x00000000FFFFFFFFu) {
1196 if (val > 0x0000FFFFFFFFFFFFu) {
1197 if (val > 0x00FFFFFFFFFFFFFFu) { /* Chk bits [63:56] : */
1198 /* .. Nbr lead zeros = .. */
1199 ix = (CPU_INT08U)(val >> 56u); /* .. lookup tbl ix = 'val' >> 56 bits */
1200 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 0u); /* .. plus nbr msb lead zeros = 0 bits.*/
1201
1202 } else { /* Chk bits [55:48] : */
1203 /* .. Nbr lead zeros = .. */
1204 ix = (CPU_INT08U)(val >> 48u); /* .. lookup tbl ix = 'val' >> 48 bits */
1205 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 8u); /* .. plus nbr msb lead zeros = 8 bits.*/
1206 }
1207
1208 } else {
1209 if (val > 0x000000FFFFFFFFFFu) { /* Chk bits [47:40] : */
1210 /* .. Nbr lead zeros = .. */
1211 ix = (CPU_INT08U)(val >> 40u); /* .. lookup tbl ix = 'val' >> 40 bits */
1212 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 16u); /* .. plus nbr msb lead zeros = 16 bits.*/
1213
1214 } else { /* Chk bits [39:32] : */
1215 /* .. Nbr lead zeros = .. */
1216 ix = (CPU_INT08U)(val >> 32u); /* .. lookup tbl ix = 'val' >> 32 bits */
1217 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 24u); /* .. plus nbr msb lead zeros = 24 bits.*/
1218 }
1219 }
1220
1221 } else {
1222 if (val > 0x000000000000FFFFu) {
1223 if (val > 0x0000000000FFFFFFu) { /* Chk bits [31:24] : */
1224 /* .. Nbr lead zeros = .. */
1225 ix = (CPU_INT08U)(val >> 24u); /* .. lookup tbl ix = 'val' >> 24 bits */
1226 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 32u); /* .. plus nbr msb lead zeros = 32 bits.*/
1227
1228 } else { /* Chk bits [23:16] : */
1229 /* .. Nbr lead zeros = .. */
1230 ix = (CPU_INT08U)(val >> 16u); /* .. lookup tbl ix = 'val' >> 16 bits */
1231 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 40u); /* .. plus nbr msb lead zeros = 40 bits.*/
1232 }
1233
1234 } else {
1235 if (val > 0x00000000000000FFu) { /* Chk bits [15:08] : */
1236 /* .. Nbr lead zeros = .. */
1237 ix = (CPU_INT08U)(val >> 8u); /* .. lookup tbl ix = 'val' >> 8 bits */
1238 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 48u); /* .. plus nbr msb lead zeros = 48 bits.*/
1239
1240 } else { /* Chk bits [07:00] : */
1241 /* .. Nbr lead zeros = .. */
1242 ix = (CPU_INT08U)(val >> 0u); /* .. lookup tbl ix = 'val' >> 0 bits */
1243 nbr_lead_zeros = (CPU_DATA )(CPU_CntLeadZerosTbl[ix] + 56u); /* .. plus nbr msb lead zeros = 56 bits.*/
1244 }
1245 }
1246 }
1247
1248
1249 #else /* See Note #1a. */
1250 (void)&ix;
1251 nbr_lead_zeros = 0u;
1252 #endif
1253
1254 return (nbr_lead_zeros);
1255 }
1256 #endif
1257
1258
1259 /*$PAGE*/
1260 /*
1261 *********************************************************************************************************
1262 *********************************************************************************************************
1263 * LOCAL FUNCTIONS
1264 *********************************************************************************************************
1265 *********************************************************************************************************
1266 */
1267
1268 /*
1269 *********************************************************************************************************
1270 * CPU_NameInit()
1271 *
1272 * Description : Initialize CPU Name.
1273 *
1274 * Argument(s) : none.
1275 *
1276 * Return(s) : none.
1277 *
1278 * Caller(s) : CPU_Init().
1279 *
1280 * Note(s) : none.
1281 *********************************************************************************************************
1282 */
1283
1284 #if (CPU_CFG_NAME_EN == DEF_ENABLED)
1285 static void CPU_NameInit (void)
1286 {
1287 CPU_NameClr();
1288 }
1289 #endif
1290
1291
1292 /*$PAGE*/
1293 /*
1294 *********************************************************************************************************
1295 * CPU_TS_Init()
1296 *
1297 * Description : (1) Initialize CPU timestamp :
1298 *
1299 * (a) Initialize/start CPU timestamp timer See Note #1
1300 * (b) Initialize CPU timestamp controls
1301 *
1302 *
1303 * Argument(s) : none.
1304 *
1305 * Return(s) : none.
1306 *
1307 * Caller(s) : CPU_Init().
1308 *
1309 * Note(s) : (1) The following initialization MUST be sequenced as follows :
1310 *
1311 * (a) CPU_TS_TmrFreq_Hz MUST be initialized prior to CPU_TS_TmrInit()
1312 * (b) CPU_TS_TmrInit() SHOULD precede calls to all other CPU timestamp functions;
1313 * otherwise, invalid time measurements may be calculated/
1314 * returned.
1315 *
1316 * See also 'CPU_Init() Note #3a'.
1317 *********************************************************************************************************
1318 */
1319
1320 #if ((CPU_CFG_TS_EN == DEF_ENABLED) || \
1321 (CPU_CFG_TS_TMR_EN == DEF_ENABLED))
1322 static void CPU_TS_Init (void)
1323 {
1324 #if (((CPU_CFG_TS_32_EN == DEF_ENABLED ) && \
1325 (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)) || \
1326 ((CPU_CFG_TS_64_EN == DEF_ENABLED ) && \
1327 (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64)))
1328 CPU_TS_TMR ts_tmr_cnts;
1329 #endif
1330
1331
1332 /* ----------------- INIT CPU TS TMR ------------------ */
1333 #if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
1334 CPU_TS_TmrFreq_Hz = 0u; /* Init/clr ts tmr freq (see Note #1a). */
1335 CPU_TS_TmrInit(); /* Init & start ts tmr (see Note #1b). */
1336 #endif
1337
1338
1339 /* ------------------- INIT CPU TS -------------------- */
1340 #if (((CPU_CFG_TS_32_EN == DEF_ENABLED ) && \
1341 (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)) || \
1342 ((CPU_CFG_TS_64_EN == DEF_ENABLED ) && \
1343 (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64)))
1344 ts_tmr_cnts = CPU_TS_TmrRd(); /* Get init ts tmr val (in ts tmr cnts). */
1345 #endif
1346
1347 #if ((CPU_CFG_TS_32_EN == DEF_ENABLED) && \
1348 (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32))
1349 CPU_TS_32_Accum = 0u; /* Init 32-bit accum'd ts. */
1350 CPU_TS_32_TmrPrev = ts_tmr_cnts; /* Init 32-bit ts prev tmr val. */
1351 #endif
1352
1353 #if ((CPU_CFG_TS_64_EN == DEF_ENABLED) && \
1354 (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64))
1355 CPU_TS_64_Accum = 0u; /* Init 64-bit accum'd ts. */
1356 CPU_TS_64_TmrPrev = ts_tmr_cnts; /* Init 64-bit ts prev tmr val. */
1357 #endif
1358 }
1359 #endif
1360
1361
1362 /*$PAGE*/
1363 /*
1364 *********************************************************************************************************
1365 * CPU_IntDisMeasInit()
1366 *
1367 * Description : (1) Initialize interrupts disabled time measurements feature :
1368 *
1369 * (a) Initialize interrupts disabled time measurement controls
1370 * (b) Calculate interrupts disabled time measurement overhead
1371 *
1372 *
1373 * Argument(s) : none.
1374 *
1375 * Return(s) : none.
1376 *
1377 * Caller(s) : CPU_Init().
1378 *
1379 * Note(s) : (2) CPU_IntDisMeasInit() SHOULD precede ALL calls to CPU_CRITICAL_ENTER()/CPU_CRITICAL_EXIT()
1380 * & other CPU interrupts disabled time measurement functions; otherwise, invalid interrupts
1381 * disabled time measurements may be calculated/returned.
1382 *
1383 * See also 'CPU_Init() Note #3b'.
1384 *
1385 * (3) (a) (1) Interrupts disabled time measurement overhead performed multiple times to calculate
1386 * a rounded average with better accuracy, hopefully of +/- one timer count.
1387 *
1388 * (2) However, a single overhead time measurement is recommended, even for instruction-
1389 * cache-enabled CPUs, since critical sections are NOT typically called within
1390 * instruction-cached loops. Thus, a single non-cached/non-averaged time measurement
1391 * is a more realistic overhead for the majority of non-cached interrupts disabled
1392 * time measurements.
1393 *
1394 * (b) Interrupts MUST be disabled while measuring the interrupts disabled time measurement
1395 * overhead; otherwise, overhead measurements could be interrupted which would incorrectly
1396 * calculate an inflated overhead time which would then incorrectly calculate deflated
1397 * interrupts disabled times.
1398 *********************************************************************************************************
1399 */
1400
1401 #ifdef CPU_CFG_INT_DIS_MEAS_EN
1402 static void CPU_IntDisMeasInit (void)
1403 {
1404 CPU_TS_TMR time_meas_tot_cnts;
1405 CPU_INT16U i;
1406 CPU_SR_ALLOC();
1407
1408 /* ----------- INIT INT DIS TIME MEAS CTRLS ----------- */
1409 CPU_IntDisMeasCtr = 0u;
1410 CPU_IntDisNestCtr = 0u;
1411 CPU_IntDisMeasStart_cnts = 0u;
1412 CPU_IntDisMeasStop_cnts = 0u;
1413 CPU_IntDisMeasMaxCur_cnts = 0u;
1414 CPU_IntDisMeasMax_cnts = 0u;
1415 CPU_IntDisMeasOvrhd_cnts = 0u;
1416
1417 /* ----------- CALC INT DIS TIME MEAS OVRHD ----------- */
1418 time_meas_tot_cnts = 0u;
1419 CPU_INT_DIS(); /* Ints MUST be dis'd for ovrhd calc (see Note #3b). */
1420 for (i = 0u; i < CPU_CFG_INT_DIS_MEAS_OVRHD_NBR; i++) {
1421 CPU_IntDisMeasMaxCur_cnts = 0u;
1422 CPU_IntDisMeasStart(); /* Perform multiple consecutive start/stop time meas's */
1423 CPU_IntDisMeasStop();
1424 time_meas_tot_cnts += CPU_IntDisMeasMaxCur_cnts; /* ... & sum time meas max's ... */
1425 }
1426 /* ... to calc avg time meas ovrhd (see Note #3a). */
1427 CPU_IntDisMeasOvrhd_cnts = (time_meas_tot_cnts + (CPU_CFG_INT_DIS_MEAS_OVRHD_NBR / 2))
1428 / CPU_CFG_INT_DIS_MEAS_OVRHD_NBR;
1429 CPU_IntDisMeasMaxCur_cnts = 0u; /* Reset max ints dis'd times. */
1430 CPU_IntDisMeasMax_cnts = 0u;
1431 CPU_INT_EN();
1432 }
1433 #endif
1434
1435
1436 /*$PAGE*/
1437 /*
1438 *********************************************************************************************************
1439 * CPU_IntDisMeasMaxCalc()
1440 *
1441 * Description : Calculate maximum interrupts disabled time.
1442 *
1443 * Argument(s) : time_tot_cnts Total interrupt disabled time, in timer counts.
1444 *
1445 * Return(s) : Maximum interrupts disabled time (in CPU timestamp timer counts).
1446 *
1447 * Caller(s) : CPU_IntDisMeasMaxCurGet(),
1448 * CPU_IntDisMeasMaxGet().
1449 *
1450 * Note(s) : (1) (a) The total amount of time interrupts are disabled by system &/or application code
1451 * during critical sections is calculated by the following equations :
1452 *
1453 * (1) time = [ time - time ] - time
1454 * interrupts [ stop start ] total meas
1455 * disabled [ meas meas ] ovrhd
1456 * (via application)
1457 *
1458 *
1459 * (2) time = time + time
1460 * total meas start meas stop meas
1461 * ovrhd ovrhd ovrhd
1462 *
1463 *
1464 * where
1465 *
1466 * time time interrupts are disabled between
1467 * interrupts first critical section enter &
1468 * disabled last critical section exit minus
1469 * (via application) time measurement overhead
1470 *
1471 * time time of disable interrupts start time
1472 * start measurement (in timer counts)
1473 * meas
1474 *
1475 * time time of disable interrupts stop time
1476 * stop measurement (in timer counts)
1477 * meas
1478 *
1479 * time total overhead time to start/stop disabled
1480 * total meas interrupts time measurements (in timer
1481 * ovrhd counts)
1482 *
1483 * time total overhead time after getting start
1484 * start meas time until end of start measurement
1485 * ovrhd function (in timer counts)
1486 *
1487 * time total overhead time from beginning of stop
1488 * stop meas measurement function until after getting
1489 * ovrhd stop time (in timer counts)
1490 *
1491 *
1492 * (b) To expedite & reduce interrupts disabled time measurement overhead, the final
1493 * calculations to subtract the interrupts disabled time measurement overhead is
1494 * performed asynchronously in API functions.
1495 *
1496 * See also 'CPU_IntDisMeasStop() Note #1b2'.
1497 *$PAGE*
1498 * (c) The amount of time interrupts are disabled is calculated by either of the
1499 * following equations :
1500 *
1501 * (1) Interrupts disabled time = Number timer counts * Timer period
1502 *
1503 * where
1504 *
1505 * Number timer counts Number of timer counts measured
1506 * Timer period Timer's period in some units of
1507 * (fractional) seconds
1508 * Interrupts disabled time Amount of time interrupts are
1509 * disabled, in same units of
1510 * (fractional) seconds as the
1511 * Timer period
1512 *
1513 * Number timer counts
1514 * (2) Interrupts disabled time = ---------------------
1515 * Timer frequency
1516 *
1517 * where
1518 *
1519 * Number timer counts Number of timer counts measured
1520 * Timer frequency Timer's frequency in some units
1521 * of counts per second
1522 * Interrupts disabled time Amount of time interrupts are
1523 * disabled, in seconds
1524 *
1525 * See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c'
1526 * & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'.
1527 *
1528 * (2) Although it is not typical, it is possible for an interrupts disabled time
1529 * measurement to be less than the interrupts disabled time measurement overhead;
1530 * especially if the overhead was calculated with a single, non-cached measurement
1531 * & critical sections are called within instruction-cached loops.
1532 *********************************************************************************************************
1533 */
1534
1535 #ifdef CPU_CFG_INT_DIS_MEAS_EN
1536 static CPU_TS_TMR CPU_IntDisMeasMaxCalc (CPU_TS_TMR time_tot_cnts)
1537 {
1538 CPU_TS_TMR time_max_cnts;
1539
1540
1541 time_max_cnts = time_tot_cnts;
1542 if (time_max_cnts > CPU_IntDisMeasOvrhd_cnts) { /* If max ints dis'd time > ovrhd time, ... */
1543 time_max_cnts -= CPU_IntDisMeasOvrhd_cnts; /* ... adj max ints dis'd time by ovrhd time; ... */
1544 } else { /* ... else max ints dis'd time < ovrhd time, ... */
1545 time_max_cnts = 0u; /* ... clr max ints dis'd time (see Note #2). */
1546 }
1547
1548 return (time_max_cnts);
1549 }
1550 #endif
1551