樊春春 vor 2 Jahren
Ursprung
Commit
a0f546985b
67 geänderte Dateien mit 39843 neuen und 536 gelöschten Zeilen
  1. 70 0
      MiddleWare/uCOS_II/UCOS-BSP/bsp.c
  2. 90 0
      MiddleWare/uCOS_II/UCOS-BSP/bsp.h
  3. 376 0
      MiddleWare/uCOS_II/UCOS-BSP/cpu_bsp.c
  4. 745 0
      MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/GNU/cpu.h
  5. 290 0
      MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/GNU/cpu_a.S
  6. 749 0
      MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/GNU/cpu_c.c
  7. 754 0
      MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/IAR/cpu.h
  8. 281 0
      MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/IAR/cpu_a.asm
  9. 746 0
      MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/IAR/cpu_c.c
  10. 748 0
      MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/RealView/cpu.h
  11. 286 0
      MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/RealView/cpu_a.asm
  12. 751 0
      MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/RealView/cpu_c.c
  13. 2387 0
      MiddleWare/uCOS_II/uC-CPU/cpu_core.c
  14. 1032 0
      MiddleWare/uCOS_II/uC-CPU/cpu_core.h
  15. 220 0
      MiddleWare/uCOS_II/uC-CPU/cpu_def.h
  16. 309 0
      MiddleWare/uCOS_II/uC-LIB/Ports/ARM-Cortex-M4/GNU/lib_mem_a.S
  17. 306 0
      MiddleWare/uCOS_II/uC-LIB/Ports/ARM-Cortex-M4/IAR/lib_mem_a.asm
  18. 312 0
      MiddleWare/uCOS_II/uC-LIB/Ports/ARM-Cortex-M4/RealView/lib_mem_a.asm
  19. 655 0
      MiddleWare/uCOS_II/uC-LIB/lib_ascii.c
  20. 842 0
      MiddleWare/uCOS_II/uC-LIB/lib_ascii.h
  21. 1344 0
      MiddleWare/uCOS_II/uC-LIB/lib_def.h
  22. 281 0
      MiddleWare/uCOS_II/uC-LIB/lib_math.c
  23. 298 0
      MiddleWare/uCOS_II/uC-LIB/lib_math.h
  24. 2842 0
      MiddleWare/uCOS_II/uC-LIB/lib_mem.c
  25. 1412 0
      MiddleWare/uCOS_II/uC-LIB/lib_mem.h
  26. 4041 0
      MiddleWare/uCOS_II/uC-LIB/lib_str.c
  27. 429 0
      MiddleWare/uCOS_II/uC-LIB/lib_str.h
  28. 189 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/GNU/os_cpu.h
  29. 315 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/GNU/os_cpu_a.S
  30. 488 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/GNU/os_cpu_c.c
  31. 327 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/GNU/os_dbg.c
  32. 189 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/IAR/os_cpu.h
  33. 306 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/IAR/os_cpu_a.asm
  34. 624 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/IAR/os_cpu_c.c
  35. 315 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/IAR/os_dbg.c
  36. 193 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/RealView/os_cpu.h
  37. 315 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/RealView/os_cpu_a.asm
  38. 507 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/RealView/os_cpu_c.c
  39. 330 0
      MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/RealView/os_dbg.c
  40. 29 0
      MiddleWare/uCOS_II/uCOS-II/Source/os.h
  41. 2092 0
      MiddleWare/uCOS_II/uCOS-II/Source/os_core.c
  42. 1231 0
      MiddleWare/uCOS_II/uCOS-II/Source/os_flag.c
  43. 654 0
      MiddleWare/uCOS_II/uCOS-II/Source/os_mbox.c
  44. 462 0
      MiddleWare/uCOS_II/uCOS-II/Source/os_mem.c
  45. 763 0
      MiddleWare/uCOS_II/uCOS-II/Source/os_mutex.c
  46. 901 0
      MiddleWare/uCOS_II/uCOS-II/Source/os_q.c
  47. 637 0
      MiddleWare/uCOS_II/uCOS-II/Source/os_sem.c
  48. 1343 0
      MiddleWare/uCOS_II/uCOS-II/Source/os_task.c
  49. 265 0
      MiddleWare/uCOS_II/uCOS-II/Source/os_time.c
  50. 1089 0
      MiddleWare/uCOS_II/uCOS-II/Source/os_tmr.c
  51. 1970 0
      MiddleWare/uCOS_II/uCOS-II/Source/ucos_ii.h
  52. 1 1
      User/Bsp/LED/led.c
  53. 1 1
      User/Bsp/LED/led.h
  54. 6 0
      User/Bsp/bsp.c
  55. 0 0
      User/Bsp/interface/interface.c
  56. 216 0
      User/Bsp/interface/interface.h
  57. 252 0
      User/UCOS-CONFIG/app_hooks.c
  58. 215 0
      User/UCOS-CONFIG/cpu_cfg.h
  59. 59 0
      User/UCOS-CONFIG/includes.h
  60. 171 0
      User/UCOS-CONFIG/lib_cfg.h
  61. 141 0
      User/UCOS-CONFIG/os_cfg.h
  62. 91 7
      User/main.c
  63. 11 0
      User/main.h
  64. 7 7
      User/stm32f4xx_it.c
  65. 42 41
      User/stm32f4xx_it.h
  66. 477 477
      User/system_stm32f4xx.c
  67. 23 2
      platformio.ini

+ 70 - 0
MiddleWare/uCOS_II/UCOS-BSP/bsp.c

@@ -0,0 +1,70 @@
+/*
+*********************************************************************************************************
+*                                            EXAMPLE CODE
+*
+*               This file is provided as an example on how to use Micrium products.
+*
+*               Please feel free to use any application code labeled as 'EXAMPLE CODE' in
+*               your application products.  Example code may be used as is, in whole or in
+*               part, or may be used as a reference only. This file can be modified as
+*               required to meet the end-product requirements.
+*
+*               Please help us continue to provide the Embedded community with the finest
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                    MICRIUM BOARD SUPPORT PACKAGE
+*
+*                                     ST Microelectronics STM32
+*                                              on the
+*
+*                                         STM3240G-EVAL
+*                                        Evaluation Board
+*
+* Filename      : bsp.c
+* Version       : V1.00
+* Programmer(s) : FF
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                             INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#define BSP_MODULE
+#include <bsp.h>
+
+/*
+*********************************************************************************************************
+*                                            BSP_CPU_ClkFreq()
+*
+* Description : Read CPU registers to determine the CPU clock frequency of the chip.
+*
+* Argument(s) : none.
+*
+* Return(s)   : The CPU clock frequency, in Hz.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+CPU_INT32U BSP_CPU_ClkFreq(void)
+{
+     // CPU_INT32U hclk_freq;
+     RCC_ClocksTypeDef RCC_Clocks;
+     RCC_GetClocksFreq(&RCC_Clocks);
+     // hclk_freq = RCC_GetClocksFreq(HCLK_Frequency);
+     return (RCC_Clocks.HCLK_Frequency);
+}

+ 90 - 0
MiddleWare/uCOS_II/UCOS-BSP/bsp.h

@@ -0,0 +1,90 @@
+/*
+*********************************************************************************************************
+*                                            EXAMPLE CODE
+*
+*               This file is provided as an example on how to use Micrium products.
+*
+*               Please feel free to use any application code labeled as 'EXAMPLE CODE' in
+*               your application products.  Example code may be used as is, in whole or in
+*               part, or may be used as a reference only. This file can be modified as
+*               required to meet the end-product requirements.
+*
+*               Please help us continue to provide the Embedded community with the finest
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                    MICRIUM BOARD SUPPORT PACKAGE
+*
+*                                     ST Microelectronics STM32
+*                                              on the
+*
+*                                         STM3240G-EVAL
+*                                        Evaluation Board
+*
+* Filename      : bsp.h
+* Version       : V1.00
+* Programmer(s) : FF
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                                 MODULE
+*
+* Note(s) : (1) This header file is protected from multiple pre-processor inclusion through use of the
+*               BSP present pre-processor macro definition.
+*
+*           (2) This file and its dependencies requires IAR v6.20 or later to be compiled.
+*
+*********************************************************************************************************
+*/
+
+#ifndef BSP_PRESENT
+#define BSP_PRESENT
+
+/*
+*********************************************************************************************************
+*                                                 EXTERNS
+*********************************************************************************************************
+*/
+
+#ifdef BSP_MODULE
+#define BSP_EXT
+#else
+#define BSP_EXT extern
+#endif
+
+/*
+*********************************************************************************************************
+*                                              INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#include <cpu.h>
+#include <cpu_core.h>
+#include <lib_def.h>
+#include "stm32f4xx.h"
+
+/*
+*********************************************************************************************************
+*                                           FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+CPU_INT32U BSP_CPU_ClkFreq(void);
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*********************************************************************************************************
+*/
+
+#endif /* End of module include.                               */

+ 376 - 0
MiddleWare/uCOS_II/UCOS-BSP/cpu_bsp.c

@@ -0,0 +1,376 @@
+/*
+*********************************************************************************************************
+*                                                uC/CPU
+*                                    CPU CONFIGURATION & PORT LAYER
+*
+*                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*
+*               uC/CPU is provided in source form to registered licensees ONLY.  It is
+*               illegal to distribute this source code to any third party unless you receive
+*               written permission by an authorized Micrium representative.  Knowledge of
+*               the source code may NOT be used to develop a similar product.
+*
+*               Please help us continue to provide the Embedded community with the finest
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                               CPU BOARD SUPPORT PACKAGE (BSP) FUNCTIONS
+*
+*                                              TEMPLATE
+*
+* Filename      : cpu_bsp.c
+* Version       : V1.30.02
+* Programmer(s) : ITJ
+*                 JBL
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#define    CPU_BSP_MODULE
+#include  <cpu_core.h>
+
+#include  <bsp.h>
+
+/*
+*********************************************************************************************************
+*                                             REGISTERS
+*********************************************************************************************************
+*/
+
+#define  CPU_REG_DEM_CR                       (*(CPU_REG32 *)0xE000EDFC)
+#define  CPU_REG_DWT_CR                       (*(CPU_REG32 *)0xE0001000)
+#define  CPU_REG_DWT_CYCCNT                   (*(CPU_REG32 *)0xE0001004)
+#define  CPU_REG_DBGMCU_CR                    (*(CPU_REG32 *)0xE0042004)
+
+/*
+*********************************************************************************************************
+*                                            REGISTER BITS
+*********************************************************************************************************
+*/
+
+#define  CPU_DBGMCU_CR_TRACE_IOEN_MASK                   0x10
+#define  CPU_DBGMCU_CR_TRACE_MODE_ASYNC                  0x00
+#define  CPU_DBGMCU_CR_TRACE_MODE_SYNC_01                0x40
+#define  CPU_DBGMCU_CR_TRACE_MODE_SYNC_02                0x80
+#define  CPU_DBGMCU_CR_TRACE_MODE_SYNC_04                0xC0
+#define  CPU_DBGMCU_CR_TRACE_MODE_MASK                   0xC0
+
+#define  CPU_BIT_DEM_CR_TRCENA                    DEF_BIT_24
+
+#define  CPU_BIT_DWT_CR_CYCCNTENA                 DEF_BIT_00
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL DEFINES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                           LOCAL CONSTANTS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          LOCAL DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL TABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                       LOCAL GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                      LOCAL FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                     LOCAL CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          CPU_TS_TmrInit()
+*
+* Description : Initialize & start CPU timestamp timer.
+*
+* Argument(s) : none.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : CPU_TS_Init().
+*
+*               This function is an INTERNAL CPU module function & MUST be implemented by application/
+*               BSP function(s) [see Note #1] but MUST NOT be called by application function(s).
+*
+* Note(s)     : (1) CPU_TS_TmrInit() is an application/BSP function that MUST be defined by the developer
+*                   if either of the following CPU features is enabled :
+*
+*                   (a) CPU timestamps
+*                   (b) CPU interrupts disabled time measurements
+*
+*                   See 'cpu_cfg.h  CPU TIMESTAMP CONFIGURATION  Note #1'
+*                     & 'cpu_cfg.h  CPU INTERRUPTS DISABLED TIME MEASUREMENT CONFIGURATION  Note #1a'.
+*
+*               (2) (a) Timer count values MUST be returned via word-size-configurable 'CPU_TS_TMR'
+*                       data type.
+*
+*                       (1) If timer has more bits, truncate timer values' higher-order bits greater
+*                           than the configured 'CPU_TS_TMR' timestamp timer data type word size.
+*
+*                       (2) Since the timer MUST NOT have less bits than the configured 'CPU_TS_TMR'
+*                           timestamp timer data type word size; 'CPU_CFG_TS_TMR_SIZE' MUST be
+*                           configured so that ALL bits in 'CPU_TS_TMR' data type are significant.
+*
+*                           In other words, if timer size is not a binary-multiple of 8-bit octets
+*                           (e.g. 20-bits or even 24-bits), then the next lower, binary-multiple
+*                           octet word size SHOULD be configured (e.g. to 16-bits).  However, the
+*                           minimum supported word size for CPU timestamp timers is 8-bits.
+*
+*                       See also 'cpu_cfg.h   CPU TIMESTAMP CONFIGURATION  Note #2'
+*                              & 'cpu_core.h  CPU TIMESTAMP DATA TYPES     Note #1'.
+*
+*                   (b) Timer SHOULD be an 'up'  counter whose values increase with each time count.
+*
+*                   (c) When applicable, 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_TS_TmrRd()  Note #2'.
+*********************************************************************************************************
+*/
+
+#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
+void  CPU_TS_TmrInit (void)
+{
+    CPU_INT32U  fclk_freq;
+
+
+    fclk_freq = BSP_CPU_ClkFreq();
+
+    CPU_REG_DEM_CR     |= (CPU_INT32U)CPU_BIT_DEM_CR_TRCENA;    /* Enable Cortex-M4's DWT CYCCNT reg.                   */
+    CPU_REG_DWT_CYCCNT  = (CPU_INT32U)0u;
+    CPU_REG_DWT_CR     |= (CPU_INT32U)CPU_BIT_DWT_CR_CYCCNTENA;
+
+    CPU_TS_TmrFreqSet((CPU_TS_TMR_FREQ)fclk_freq);
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                           CPU_TS_TmrRd()
+*
+* Description : Get current CPU timestamp timer count value.
+*
+* Argument(s) : none.
+*
+* Return(s)   : Timestamp timer count (see Notes #2a & #2b).
+*
+* Caller(s)   : CPU_TS_Init(),
+*               CPU_TS_Get32(),
+*               CPU_TS_Get64(),
+*               CPU_IntDisMeasStart(),
+*               CPU_IntDisMeasStop().
+*
+*               This function is an INTERNAL CPU module function & MUST be implemented by application/
+*               BSP function(s) [see Note #1] but SHOULD NOT be called by application function(s).
+*
+* Note(s)     : (1) CPU_TS_TmrRd() is an application/BSP function that MUST be defined by the developer
+*                   if either of the following CPU features is enabled :
+*
+*                   (a) CPU timestamps
+*                   (b) CPU interrupts disabled time measurements
+*
+*                   See 'cpu_cfg.h  CPU TIMESTAMP CONFIGURATION  Note #1'
+*                     & 'cpu_cfg.h  CPU INTERRUPTS DISABLED TIME MEASUREMENT CONFIGURATION  Note #1a'.
+*
+*               (2) (a) Timer count values MUST be returned via word-size-configurable 'CPU_TS_TMR'
+*                       data type.
+*
+*                       (1) If timer has more bits, truncate timer values' higher-order bits greater
+*                           than the configured 'CPU_TS_TMR' timestamp timer data type word size.
+*
+*                       (2) Since the timer MUST NOT have less bits than the configured 'CPU_TS_TMR'
+*                           timestamp timer data type word size; 'CPU_CFG_TS_TMR_SIZE' MUST be
+*                           configured so that ALL bits in 'CPU_TS_TMR' data type are significant.
+*
+*                           In other words, if timer size is not a binary-multiple of 8-bit octets
+*                           (e.g. 20-bits or even 24-bits), then the next lower, binary-multiple
+*                           octet word size SHOULD be configured (e.g. to 16-bits).  However, the
+*                           minimum supported word size for CPU timestamp timers is 8-bits.
+*
+*                       See also 'cpu_cfg.h   CPU TIMESTAMP CONFIGURATION  Note #2'
+*                              & 'cpu_core.h  CPU TIMESTAMP DATA TYPES     Note #1'.
+*
+*                   (b) Timer SHOULD be an 'up'  counter whose values increase with each time count.
+*
+*                       (1) If timer is a 'down' counter whose values decrease with each time count,
+*                           then the returned timer value MUST be ones-complemented.
+*
+*                   (c) (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
+*
+*                       (2) 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.
+*********************************************************************************************************
+*/
+
+#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
+CPU_TS_TMR  CPU_TS_TmrRd (void)
+{
+    CPU_TS_TMR  ts_tmr_cnts;
+
+
+    ts_tmr_cnts = (CPU_TS_TMR)CPU_REG_DWT_CYCCNT;
+
+    return (ts_tmr_cnts);
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                         CPU_TSxx_to_uSec()
+*
+* Description : Convert a 32-/64-bit CPU timestamp from timer counts to microseconds.
+*
+* Argument(s) : ts_cnts   CPU timestamp (in timestamp timer counts [see Note #2aA]).
+*
+* Return(s)   : Converted CPU timestamp (in microseconds           [see Note #2aD]).
+*
+* Caller(s)   : Application.
+*
+*               This function is an (optional) CPU module application programming interface (API)
+*               function which MAY be implemented by application/BSP function(s) [see Note #1] &
+*               MAY be called by application function(s).
+*
+* Note(s)     : (1) CPU_TS32_to_uSec()/CPU_TS64_to_uSec() are application/BSP functions that MAY be
+*                   optionally defined by the developer when either of the following CPU features is
+*                   enabled :
+*
+*                   (a) CPU timestamps
+*                   (b) CPU interrupts disabled time measurements
+*
+*                   See 'cpu_cfg.h  CPU TIMESTAMP CONFIGURATION  Note #1'
+*                     & 'cpu_cfg.h  CPU INTERRUPTS DISABLED TIME MEASUREMENT CONFIGURATION  Note #1a'.
+*
+*               (2) (a) The amount of time measured by CPU timestamps is calculated by either of
+*                       the following equations :
+*
+*                                                                        10^6 microseconds
+*                       (1) Time measured  =   Number timer counts   *  -------------------  *  Timer period
+*                                                                            1 second
+*
+*                                              Number timer counts       10^6 microseconds
+*                       (2) Time measured  =  ---------------------  *  -------------------
+*                                                Timer frequency             1 second
+*
+*                               where
+*
+*                                   (A) Number timer counts     Number of timer counts measured
+*                                   (B) Timer frequency         Timer's frequency in some units
+*                                                                   of counts per second
+*                                   (C) Timer period            Timer's period in some units of
+*                                                                   (fractional)  seconds
+*                                   (D) Time measured           Amount of time measured,
+*                                                                   in microseconds
+*
+*                   (b) 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.
+*
+*                   (c) Specific implementations may convert any number of CPU_TS32 or CPU_TS64 bits
+*                       -- up to 32 or 64, respectively -- into microseconds.
+*********************************************************************************************************
+*/
+
+#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
+CPU_INT64U  CPU_TS32_to_uSec (CPU_TS32  ts_cnts)
+{
+    CPU_INT64U  ts_us;
+    CPU_INT64U  fclk_freq;
+
+
+    fclk_freq = BSP_CPU_ClkFreq();
+    ts_us     = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);
+
+    return (ts_us);
+}
+#endif
+
+
+#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
+CPU_INT64U  CPU_TS64_to_uSec (CPU_TS64  ts_cnts)
+{
+    CPU_INT64U  ts_us;
+    CPU_INT64U  fclk_freq;
+
+
+    fclk_freq = BSP_CPU_ClkFreq();
+    ts_us     = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);
+
+    return (ts_us);
+}
+#endif
+

+ 745 - 0
MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/GNU/cpu.h

@@ -0,0 +1,745 @@
+/*
+*********************************************************************************************************
+*                                                uC/CPU
+*                                    CPU CONFIGURATION & PORT LAYER
+*
+*                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*
+*               uC/CPU is provided in source form to registered licensees ONLY.  It is 
+*               illegal to distribute this source code to any third party unless you receive 
+*               written permission by an authorized Micrium representative.  Knowledge of 
+*               the source code may NOT be used to develop a similar product.
+*
+*               Please help us continue to provide the Embedded community with the finest 
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                            CPU PORT FILE
+*
+*                                            ARM-Cortex-M4
+*                                            GNU C Compiler
+*
+* Filename      : cpu.h
+* Version       : V1.30.02.00
+* Programmer(s) : JJL
+*                 BAN
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*
+* Note(s) : (1) This CPU header file is protected from multiple pre-processor inclusion through use of 
+*               the  CPU module present pre-processor macro definition.
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_MODULE_PRESENT                                     /* See Note #1.                                         */
+#define  CPU_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*                                          CPU INCLUDE FILES
+*
+* Note(s) : (1) The following CPU files are located in the following directories :
+*
+*               (a) \<Your Product Application>\cpu_cfg.h
+*
+*               (b) (1) \<CPU-Compiler Directory>\cpu_def.h
+*                   (2) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.*
+*
+*                       where
+*                               <Your Product Application>      directory path for Your Product's Application
+*                               <CPU-Compiler Directory>        directory path for common   CPU-compiler software
+*                               <cpu>                           directory name for specific CPU
+*                               <compiler>                      directory name for specific compiler
+*
+*           (2) Compiler MUST be configured to include as additional include path directories :
+*
+*               (a) '\<Your Product Application>\' directory                            See Note #1a
+*
+*               (b) (1) '\<CPU-Compiler Directory>\'                  directory         See Note #1b1
+*                   (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory         See Note #1b2
+*
+*           (3) Since NO custom library modules are included, 'cpu.h' may ONLY use configurations from
+*               CPU configuration file 'cpu_cfg.h' that do NOT reference any custom library definitions.
+*
+*               In other words, 'cpu.h' may use 'cpu_cfg.h' configurations that are #define'd to numeric
+*               constants or to NULL (i.e. NULL-valued #define's); but may NOT use configurations to
+*               custom library #define's (e.g. DEF_DISABLED or DEF_ENABLED).
+*********************************************************************************************************
+*/
+
+#include  <cpu_def.h>
+#include  <cpu_cfg.h>                                           /* See Note #3.                                         */
+
+#ifdef __cplusplus
+extern  "C" {
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                    CONFIGURE STANDARD DATA TYPES
+*
+* Note(s) : (1) Configure standard data types according to CPU-/compiler-specifications.
+*
+*           (2) (a) (1) 'CPU_FNCT_VOID' data type defined to replace the commonly-used function pointer
+*                       data type of a pointer to a function which returns void & has no arguments.
+*
+*                   (2) Example function pointer usage :
+*
+*                           CPU_FNCT_VOID  FnctName;
+*
+*                           FnctName();
+*
+*               (b) (1) 'CPU_FNCT_PTR'  data type defined to replace the commonly-used function pointer
+*                       data type of a pointer to a function which returns void & has a single void
+*                       pointer argument.
+*
+*                   (2) Example function pointer usage :
+*
+*                           CPU_FNCT_PTR   FnctName;
+*                           void          *p_obj
+*
+*                           FnctName(p_obj);
+*********************************************************************************************************
+*/
+
+typedef            void        CPU_VOID;
+typedef            char        CPU_CHAR;                        /*  8-bit character                                     */
+typedef  unsigned  char        CPU_BOOLEAN;                     /*  8-bit boolean or logical                            */
+typedef  unsigned  char        CPU_INT08U;                      /*  8-bit unsigned integer                              */
+typedef    signed  char        CPU_INT08S;                      /*  8-bit   signed integer                              */
+typedef  unsigned  short       CPU_INT16U;                      /* 16-bit unsigned integer                              */
+typedef    signed  short       CPU_INT16S;                      /* 16-bit   signed integer                              */
+typedef  unsigned  int         CPU_INT32U;                      /* 32-bit unsigned integer                              */
+typedef    signed  int         CPU_INT32S;                      /* 32-bit   signed integer                              */
+typedef  unsigned  long  long  CPU_INT64U;                      /* 64-bit unsigned integer                              */
+typedef    signed  long  long  CPU_INT64S;                      /* 64-bit   signed integer                              */
+
+typedef            float       CPU_FP32;                        /* 32-bit floating point                                */
+typedef            double      CPU_FP64;                        /* 64-bit floating point                                */
+
+
+typedef  volatile  CPU_INT08U  CPU_REG08;                       /*  8-bit register                                      */
+typedef  volatile  CPU_INT16U  CPU_REG16;                       /* 16-bit register                                      */
+typedef  volatile  CPU_INT32U  CPU_REG32;                       /* 32-bit register                                      */
+typedef  volatile  CPU_INT64U  CPU_REG64;                       /* 64-bit register                                      */
+
+
+typedef            void      (*CPU_FNCT_VOID)(void);            /* See Note #2a.                                        */
+typedef            void      (*CPU_FNCT_PTR )(void *p_obj);     /* See Note #2b.                                        */
+
+
+/*
+*********************************************************************************************************
+*                                       CPU WORD CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_ADDR_SIZE, CPU_CFG_DATA_SIZE, & CPU_CFG_DATA_SIZE_MAX with CPU's &/or 
+*               compiler's word sizes :
+*
+*                   CPU_WORD_SIZE_08             8-bit word size
+*                   CPU_WORD_SIZE_16            16-bit word size
+*                   CPU_WORD_SIZE_32            32-bit word size
+*                   CPU_WORD_SIZE_64            64-bit word size
+*
+*           (2) Configure CPU_CFG_ENDIAN_TYPE with CPU's data-word-memory order :
+*
+*               (a) CPU_ENDIAN_TYPE_BIG         Big-   endian word order (CPU words' most  significant
+*                                                                         octet @ lowest memory address)
+*               (b) CPU_ENDIAN_TYPE_LITTLE      Little-endian word order (CPU words' least significant
+*                                                                         octet @ lowest memory address)
+*********************************************************************************************************
+*/
+
+                                                                /* Define  CPU         word sizes (see Note #1) :       */
+#define  CPU_CFG_ADDR_SIZE              CPU_WORD_SIZE_32        /* Defines CPU address word size  (in octets).          */
+#define  CPU_CFG_DATA_SIZE              CPU_WORD_SIZE_32        /* Defines CPU data    word size  (in octets).          */
+#define  CPU_CFG_DATA_SIZE_MAX          CPU_WORD_SIZE_64        /* Defines CPU maximum word size  (in octets).          */
+
+#define  CPU_CFG_ENDIAN_TYPE            CPU_ENDIAN_TYPE_LITTLE  /* Defines CPU data    word-memory order (see Note #2). */
+
+
+/*
+*********************************************************************************************************
+*                                 CONFIGURE CPU ADDRESS & DATA TYPES
+*********************************************************************************************************
+*/
+
+                                                                /* CPU address type based on address bus size.          */
+#if     (CPU_CFG_ADDR_SIZE == CPU_WORD_SIZE_32)
+typedef  CPU_INT32U  CPU_ADDR;
+#elif   (CPU_CFG_ADDR_SIZE == CPU_WORD_SIZE_16)
+typedef  CPU_INT16U  CPU_ADDR;
+#else
+typedef  CPU_INT08U  CPU_ADDR;
+#endif
+
+                                                                /* CPU data    type based on data    bus size.          */
+#if     (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_32)
+typedef  CPU_INT32U  CPU_DATA;
+#elif   (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_16)
+typedef  CPU_INT16U  CPU_DATA;
+#else
+typedef  CPU_INT08U  CPU_DATA;
+#endif
+
+
+typedef  CPU_DATA    CPU_ALIGN;                                 /* Defines CPU data-word-alignment size.                */
+typedef  CPU_ADDR    CPU_SIZE_T;                                /* Defines CPU standard 'size_t'   size.                */
+
+
+/*
+*********************************************************************************************************
+*                                       CPU STACK CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_STK_GROWTH in 'cpu.h' with CPU's stack growth order :
+*
+*               (a) CPU_STK_GROWTH_LO_TO_HI     CPU stack pointer increments to the next higher  stack
+*                                                   memory address after data is pushed onto the stack
+*               (b) CPU_STK_GROWTH_HI_TO_LO     CPU stack pointer decrements to the next lower   stack
+*                                                   memory address after data is pushed onto the stack
+*
+*           (2) Configure CPU_CFG_STK_ALIGN_BYTES with the highest minimum alignement required for
+*               cpu stacks.
+*
+*               (a) ARM Procedure Calls Standard requires an 8 bytes stack alignment.
+*********************************************************************************************************
+*/
+
+#define  CPU_CFG_STK_GROWTH       CPU_STK_GROWTH_HI_TO_LO       /* Defines CPU stack growth order (see Note #1).        */
+
+#define  CPU_CFG_STK_ALIGN_BYTES  (8u)                          /* Defines CPU stack alignment in bytes. (see Note #2). */
+
+typedef  CPU_INT32U               CPU_STK;                      /* Defines CPU stack data type.                         */
+typedef  CPU_ADDR                 CPU_STK_SIZE;                 /* Defines CPU stack size data type.                    */
+
+
+/*
+*********************************************************************************************************
+*                                   CRITICAL SECTION CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_CRITICAL_METHOD with CPU's/compiler's critical section method :
+*
+*                                                       Enter/Exit critical sections by ...
+*
+*                   CPU_CRITICAL_METHOD_INT_DIS_EN      Disable/Enable interrupts
+*                   CPU_CRITICAL_METHOD_STATUS_STK      Push/Pop       interrupt status onto stack
+*                   CPU_CRITICAL_METHOD_STATUS_LOCAL    Save/Restore   interrupt status to local variable
+*
+*               (a) CPU_CRITICAL_METHOD_INT_DIS_EN  is NOT a preferred method since it does NOT support
+*                   multiple levels of interrupts.  However, with some CPUs/compilers, this is the only
+*                   available method.
+*
+*               (b) CPU_CRITICAL_METHOD_STATUS_STK    is one preferred method since it supports multiple
+*                   levels of interrupts.  However, this method assumes that the compiler provides C-level
+*                   &/or assembly-level functionality for the following :
+*
+*                     ENTER CRITICAL SECTION :
+*                       (1) Push/save   interrupt status onto a local stack
+*                       (2) Disable     interrupts
+*
+*                     EXIT  CRITICAL SECTION :
+*                       (3) Pop/restore interrupt status from a local stack
+*
+*               (c) CPU_CRITICAL_METHOD_STATUS_LOCAL  is one preferred method since it supports multiple
+*                   levels of interrupts.  However, this method assumes that the compiler provides C-level
+*                   &/or assembly-level functionality for the following :
+*
+*                     ENTER CRITICAL SECTION :
+*                       (1) Save    interrupt status into a local variable
+*                       (2) Disable interrupts
+*
+*                     EXIT  CRITICAL SECTION :
+*                       (3) Restore interrupt status from a local variable
+*
+*           (2) Critical section macro's most likely require inline assembly.  If the compiler does NOT
+*               allow inline assembly in C source files, critical section macro's MUST call an assembly
+*               subroutine defined in a 'cpu_a.asm' file located in the following software directory :
+*
+*                   \<CPU-Compiler Directory>\<cpu>\<compiler>\
+*
+*                       where
+*                               <CPU-Compiler Directory>    directory path for common   CPU-compiler software
+*                               <cpu>                       directory name for specific CPU
+*                               <compiler>                  directory name for specific compiler
+*
+*           (3) (a) To save/restore interrupt status, a local variable 'cpu_sr' of type 'CPU_SR' MAY need
+*                   to be declared (e.g. if 'CPU_CRITICAL_METHOD_STATUS_LOCAL' method is configured).
+*
+*                   (1) 'cpu_sr' local variable SHOULD be declared via the CPU_SR_ALLOC() macro which, if 
+*                        used, MUST be declared following ALL other local variables.
+*
+*                        Example :
+*
+*                           void  Fnct (void)
+*                           {
+*                               CPU_INT08U  val_08;
+*                               CPU_INT16U  val_16;
+*                               CPU_INT32U  val_32;
+*                               CPU_SR_ALLOC();         MUST be declared after ALL other local variables
+*                                   :
+*                                   :
+*                           }
+*
+*               (b) Configure 'CPU_SR' data type with the appropriate-sized CPU data type large enough to
+*                   completely store the CPU's/compiler's status word.
+*********************************************************************************************************
+*/
+                                                                /* Configure CPU critical method      (see Note #1) :   */
+#define  CPU_CFG_CRITICAL_METHOD    CPU_CRITICAL_METHOD_STATUS_LOCAL
+
+typedef  CPU_INT32U                 CPU_SR;                     /* Defines   CPU status register size (see Note #3b).   */
+
+                                                                /* Allocates CPU status register word (see Note #3a).   */
+#if     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
+#define  CPU_SR_ALLOC()             CPU_SR  cpu_sr = (CPU_SR)0
+#else
+#define  CPU_SR_ALLOC()
+#endif
+
+
+
+#define  CPU_INT_DIS()         do { cpu_sr = CPU_SR_Save(); } while (0) /* Save    CPU status word & disable interrupts.*/
+#define  CPU_INT_EN()          do { CPU_SR_Restore(cpu_sr); } while (0) /* Restore CPU status word.                     */
+
+
+#ifdef   CPU_CFG_INT_DIS_MEAS_EN
+                                                                        /* Disable interrupts, ...                      */
+                                                                        /* & start interrupts disabled time measurement.*/
+#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS();         \
+                                    CPU_IntDisMeasStart(); }  while (0)
+                                                                        /* Stop & measure   interrupts disabled time,   */
+                                                                        /* ...  & re-enable interrupts.                 */
+#define  CPU_CRITICAL_EXIT()   do { CPU_IntDisMeasStop();  \
+                                    CPU_INT_EN();          }  while (0)
+
+#else
+
+#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS(); } while (0)          /* Disable   interrupts.                        */
+#define  CPU_CRITICAL_EXIT()   do { CPU_INT_EN();  } while (0)          /* Re-enable interrupts.                        */
+
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                    MEMORY BARRIERS CONFIGURATION
+*
+* Note(s) : (1) (a) Configure memory barriers if required by the architecture.
+*
+*                   CPU_MB      Full memory barrier.
+*                   CPU_RMB     Read (Loads) memory barrier.
+*                   CPU_WMB     Write (Stores) memory barrier.
+*
+*********************************************************************************************************
+*/
+
+#define  CPU_MB()       __asm__ __volatile__ ("dsb" : : : "memory")
+#define  CPU_RMB()      __asm__ __volatile__ ("dsb" : : : "memory")
+#define  CPU_WMB()      __asm__ __volatile__ ("dsb" : : : "memory")
+
+
+/*
+*********************************************************************************************************
+*                                    CPU COUNT ZEROS CONFIGURATION
+*
+* Note(s) : (1) (a) Configure CPU_CFG_LEAD_ZEROS_ASM_PRESENT  to define count leading  zeros bits 
+*                   function(s) in :
+*
+*                   (1) 'cpu_a.asm',  if CPU_CFG_LEAD_ZEROS_ASM_PRESENT       #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable assembly-optimized function(s)
+*
+*                   (2) 'cpu_core.c', if CPU_CFG_LEAD_ZEROS_ASM_PRESENT   NOT #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable C-source-optimized function(s) otherwise
+*
+*               (b) Configure CPU_CFG_TRAIL_ZEROS_ASM_PRESENT to define count trailing zeros bits 
+*                   function(s) in :
+*
+*                   (1) 'cpu_a.asm',  if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT      #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable assembly-optimized function(s)
+*
+*                   (2) 'cpu_core.c', if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT  NOT #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable C-source-optimized function(s) otherwise
+*********************************************************************************************************
+*/
+
+                                                                /* Configure CPU count leading  zeros bits ...          */
+#define  CPU_CFG_LEAD_ZEROS_ASM_PRESENT                         /* ... assembly-version (see Note #1a).                 */
+
+                                                                /* Configure CPU count trailing zeros bits ...          */
+#define  CPU_CFG_TRAIL_ZEROS_ASM_PRESENT                        /* ... assembly-version (see Note #1b).                 */
+
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+void        CPU_IntDis       (void);
+void        CPU_IntEn        (void);
+
+void        CPU_IntSrcDis    (CPU_INT08U  pos);
+void        CPU_IntSrcEn     (CPU_INT08U  pos);
+void        CPU_IntSrcPendClr(CPU_INT08U  pos);
+CPU_INT16S  CPU_IntSrcPrioGet(CPU_INT08U  pos);
+void        CPU_IntSrcPrioSet(CPU_INT08U  pos,
+                              CPU_INT08U  prio);
+
+
+CPU_SR      CPU_SR_Save      (void);
+void        CPU_SR_Restore   (CPU_SR      cpu_sr);
+
+
+void        CPU_WaitForInt   (void);
+void        CPU_WaitForExcept(void);
+
+
+CPU_DATA    CPU_RevBits      (CPU_DATA    val);
+
+void        CPU_BitBandClr   (CPU_ADDR    addr,
+                              CPU_INT08U  bit_nbr);
+void        CPU_BitBandSet   (CPU_ADDR    addr,
+                              CPU_INT08U  bit_nbr);
+
+
+/*
+*********************************************************************************************************
+*                                          INTERRUPT SOURCES
+*********************************************************************************************************
+*/
+
+#define  CPU_INT_STK_PTR                                   0u
+#define  CPU_INT_RESET                                     1u
+#define  CPU_INT_NMI                                       2u
+#define  CPU_INT_HFAULT                                    3u
+#define  CPU_INT_MEM                                       4u
+#define  CPU_INT_BUSFAULT                                  5u
+#define  CPU_INT_USAGEFAULT                                6u
+#define  CPU_INT_RSVD_07                                   7u
+#define  CPU_INT_RSVD_08                                   8u
+#define  CPU_INT_RSVD_09                                   9u
+#define  CPU_INT_RSVD_10                                  10u
+#define  CPU_INT_SVCALL                                   11u
+#define  CPU_INT_DBGMON                                   12u
+#define  CPU_INT_RSVD_13                                  13u
+#define  CPU_INT_PENDSV                                   14u
+#define  CPU_INT_SYSTICK                                  15u
+#define  CPU_INT_EXT0                                     16u
+
+/*
+*********************************************************************************************************
+*                                            CPU REGISTERS
+*********************************************************************************************************
+*/
+
+#define  CPU_REG_NVIC_NVIC           (*((CPU_REG32 *)(0xE000E004)))             /* Int Ctrl'er Type Reg.                */
+#define  CPU_REG_NVIC_ST_CTRL        (*((CPU_REG32 *)(0xE000E010)))             /* SysTick Ctrl & Status Reg.           */
+#define  CPU_REG_NVIC_ST_RELOAD      (*((CPU_REG32 *)(0xE000E014)))             /* SysTick Reload      Value Reg.       */
+#define  CPU_REG_NVIC_ST_CURRENT     (*((CPU_REG32 *)(0xE000E018)))             /* SysTick Current     Value Reg.       */
+#define  CPU_REG_NVIC_ST_CAL         (*((CPU_REG32 *)(0xE000E01C)))             /* SysTick Calibration Value Reg.       */
+
+#define  CPU_REG_NVIC_SETEN(n)       (*((CPU_REG32 *)(0xE000E100 + (n) * 4u)))  /* IRQ Set En Reg.                      */
+#define  CPU_REG_NVIC_CLREN(n)       (*((CPU_REG32 *)(0xE000E180 + (n) * 4u)))  /* IRQ Clr En Reg.                      */
+#define  CPU_REG_NVIC_SETPEND(n)     (*((CPU_REG32 *)(0xE000E200 + (n) * 4u)))  /* IRQ Set Pending Reg.                 */
+#define  CPU_REG_NVIC_CLRPEND(n)     (*((CPU_REG32 *)(0xE000E280 + (n) * 4u)))  /* IRQ Clr Pending Reg.                 */
+#define  CPU_REG_NVIC_ACTIVE(n)      (*((CPU_REG32 *)(0xE000E300 + (n) * 4u)))  /* IRQ Active Reg.                      */
+#define  CPU_REG_NVIC_PRIO(n)        (*((CPU_REG32 *)(0xE000E400 + (n) * 4u)))  /* IRQ Prio Reg.                        */
+
+#define  CPU_REG_NVIC_CPUID          (*((CPU_REG32 *)(0xE000ED00)))             /* CPUID Base Reg.                      */
+#define  CPU_REG_NVIC_ICSR           (*((CPU_REG32 *)(0xE000ED04)))             /* Int Ctrl State  Reg.                 */
+#define  CPU_REG_NVIC_VTOR           (*((CPU_REG32 *)(0xE000ED08)))             /* Vect Tbl Offset Reg.                 */
+#define  CPU_REG_NVIC_AIRCR          (*((CPU_REG32 *)(0xE000ED0C)))             /* App Int/Reset Ctrl Reg.              */
+#define  CPU_REG_NVIC_SCR            (*((CPU_REG32 *)(0xE000ED10)))             /* System Ctrl Reg.                     */
+#define  CPU_REG_NVIC_CCR            (*((CPU_REG32 *)(0xE000ED14)))             /* Cfg    Ctrl Reg.                     */
+#define  CPU_REG_NVIC_SHPRI1         (*((CPU_REG32 *)(0xE000ED18)))             /* System Handlers  4 to  7 Prio.       */
+#define  CPU_REG_NVIC_SHPRI2         (*((CPU_REG32 *)(0xE000ED1C)))             /* System Handlers  8 to 11 Prio.       */
+#define  CPU_REG_NVIC_SHPRI3         (*((CPU_REG32 *)(0xE000ED20)))             /* System Handlers 12 to 15 Prio.       */
+#define  CPU_REG_NVIC_SHCSR          (*((CPU_REG32 *)(0xE000ED24)))             /* System Handler Ctrl & State Reg.     */
+#define  CPU_REG_NVIC_CFSR           (*((CPU_REG32 *)(0xE000ED28)))             /* Configurable Fault Status Reg.       */
+#define  CPU_REG_NVIC_HFSR           (*((CPU_REG32 *)(0xE000ED2C)))             /* Hard  Fault Status Reg.              */
+#define  CPU_REG_NVIC_DFSR           (*((CPU_REG32 *)(0xE000ED30)))             /* Debug Fault Status Reg.              */
+#define  CPU_REG_NVIC_MMFAR          (*((CPU_REG32 *)(0xE000ED34)))             /* Mem Manage Addr Reg.                 */
+#define  CPU_REG_NVIC_BFAR           (*((CPU_REG32 *)(0xE000ED38)))             /* Bus Fault  Addr Reg.                 */
+#define  CPU_REG_NVIC_AFSR           (*((CPU_REG32 *)(0xE000ED3C)))             /* Aux Fault Status Reg.                */
+
+#define  CPU_REG_NVIC_PFR0           (*((CPU_REG32 *)(0xE000ED40)))             /* Processor Feature Reg 0.             */
+#define  CPU_REG_NVIC_PFR1           (*((CPU_REG32 *)(0xE000ED44)))             /* Processor Feature Reg 1.             */
+#define  CPU_REG_NVIC_DFR0           (*((CPU_REG32 *)(0xE000ED48)))             /* Debug     Feature Reg 0.             */
+#define  CPU_REG_NVIC_AFR0           (*((CPU_REG32 *)(0xE000ED4C)))             /* Aux       Feature Reg 0.             */
+#define  CPU_REG_NVIC_MMFR0          (*((CPU_REG32 *)(0xE000ED50)))             /* Memory Model Feature Reg 0.          */
+#define  CPU_REG_NVIC_MMFR1          (*((CPU_REG32 *)(0xE000ED54)))             /* Memory Model Feature Reg 1.          */
+#define  CPU_REG_NVIC_MMFR2          (*((CPU_REG32 *)(0xE000ED58)))             /* Memory Model Feature Reg 2.          */
+#define  CPU_REG_NVIC_MMFR3          (*((CPU_REG32 *)(0xE000ED5C)))             /* Memory Model Feature Reg 3.          */
+#define  CPU_REG_NVIC_ISAFR0         (*((CPU_REG32 *)(0xE000ED60)))             /* ISA Feature Reg 0.                   */
+#define  CPU_REG_NVIC_ISAFR1         (*((CPU_REG32 *)(0xE000ED64)))             /* ISA Feature Reg 1.                   */
+#define  CPU_REG_NVIC_ISAFR2         (*((CPU_REG32 *)(0xE000ED68)))             /* ISA Feature Reg 2.                   */
+#define  CPU_REG_NVIC_ISAFR3         (*((CPU_REG32 *)(0xE000ED6C)))             /* ISA Feature Reg 3.                   */
+#define  CPU_REG_NVIC_ISAFR4         (*((CPU_REG32 *)(0xE000ED70)))             /* ISA Feature Reg 4.                   */
+#define  CPU_REG_NVIC_SW_TRIG        (*((CPU_REG32 *)(0xE000EF00)))             /* Software Trigger Int Reg.            */
+
+#define  CPU_REG_MPU_TYPE            (*((CPU_REG32 *)(0xE000ED90)))             /* MPU Type Reg.                        */
+#define  CPU_REG_MPU_CTRL            (*((CPU_REG32 *)(0xE000ED94)))             /* MPU Ctrl Reg.                        */
+#define  CPU_REG_MPU_REG_NBR         (*((CPU_REG32 *)(0xE000ED98)))             /* MPU Region Nbr Reg.                  */
+#define  CPU_REG_MPU_REG_BASE        (*((CPU_REG32 *)(0xE000ED9C)))             /* MPU Region Base Addr Reg.            */
+#define  CPU_REG_MPU_REG_ATTR        (*((CPU_REG32 *)(0xE000EDA0)))             /* MPU Region Attrib & Size Reg.        */
+
+#define  CPU_REG_DBG_CTRL            (*((CPU_REG32 *)(0xE000EDF0)))             /* Debug Halting Ctrl & Status Reg.     */
+#define  CPU_REG_DBG_SELECT          (*((CPU_REG32 *)(0xE000EDF4)))             /* Debug Core Reg Selector Reg.         */
+#define  CPU_REG_DBG_DATA            (*((CPU_REG32 *)(0xE000EDF8)))             /* Debug Core Reg Data     Reg.         */
+#define  CPU_REG_DBG_INT             (*((CPU_REG32 *)(0xE000EDFC)))             /* Debug Except & Monitor Ctrl Reg.     */
+
+
+/*
+*********************************************************************************************************
+*                                          CPU REGISTER BITS
+*********************************************************************************************************
+*/
+
+                                                                /* ---------- SYSTICK CTRL & STATUS REG BITS ---------- */
+#define  CPU_REG_NVIC_ST_CTRL_COUNTFLAG           0x00010000
+#define  CPU_REG_NVIC_ST_CTRL_CLKSOURCE           0x00000004
+#define  CPU_REG_NVIC_ST_CTRL_TICKINT             0x00000002
+#define  CPU_REG_NVIC_ST_CTRL_ENABLE              0x00000001
+
+
+                                                                /* -------- SYSTICK CALIBRATION VALUE REG BITS -------- */
+#define  CPU_REG_NVIC_ST_CAL_NOREF                0x80000000
+#define  CPU_REG_NVIC_ST_CAL_SKEW                 0x40000000
+
+                                                                /* -------------- INT CTRL STATE REG BITS ------------- */
+#define  CPU_REG_NVIC_ICSR_NMIPENDSET             0x80000000
+#define  CPU_REG_NVIC_ICSR_PENDSVSET              0x10000000
+#define  CPU_REG_NVIC_ICSR_PENDSVCLR              0x08000000
+#define  CPU_REG_NVIC_ICSR_PENDSTSET              0x04000000
+#define  CPU_REG_NVIC_ICSR_PENDSTCLR              0x02000000
+#define  CPU_REG_NVIC_ICSR_ISRPREEMPT             0x00800000
+#define  CPU_REG_NVIC_ICSR_ISRPENDING             0x00400000
+#define  CPU_REG_NVIC_ICSR_RETTOBASE              0x00000800
+
+                                                                /* ------------- VECT TBL OFFSET REG BITS ------------- */
+#define  CPU_REG_NVIC_VTOR_TBLBASE                0x20000000
+
+                                                                /* ------------ APP INT/RESET CTRL REG BITS ----------- */
+#define  CPU_REG_NVIC_AIRCR_ENDIANNESS            0x00008000
+#define  CPU_REG_NVIC_AIRCR_SYSRESETREQ           0x00000004
+#define  CPU_REG_NVIC_AIRCR_VECTCLRACTIVE         0x00000002
+#define  CPU_REG_NVIC_AIRCR_VECTRESET             0x00000001
+
+                                                                /* --------------- SYSTEM CTRL REG BITS --------------- */
+#define  CPU_REG_NVIC_SCR_SEVONPEND               0x00000010
+#define  CPU_REG_NVIC_SCR_SLEEPDEEP               0x00000004
+#define  CPU_REG_NVIC_SCR_SLEEPONEXIT             0x00000002
+
+                                                                /* ----------------- CFG CTRL REG BITS ---------------- */
+#define  CPU_REG_NVIC_CCR_STKALIGN                0x00000200
+#define  CPU_REG_NVIC_CCR_BFHFNMIGN               0x00000100
+#define  CPU_REG_NVIC_CCR_DIV_0_TRP               0x00000010
+#define  CPU_REG_NVIC_CCR_UNALIGN_TRP             0x00000008
+#define  CPU_REG_NVIC_CCR_USERSETMPEND            0x00000002
+#define  CPU_REG_NVIC_CCR_NONBASETHRDENA          0x00000001
+
+                                                                /* ------- SYSTEM HANDLER CTRL & STATE REG BITS ------- */
+#define  CPU_REG_NVIC_SHCSR_USGFAULTENA           0x00040000
+#define  CPU_REG_NVIC_SHCSR_BUSFAULTENA           0x00020000
+#define  CPU_REG_NVIC_SHCSR_MEMFAULTENA           0x00010000
+#define  CPU_REG_NVIC_SHCSR_SVCALLPENDED          0x00008000
+#define  CPU_REG_NVIC_SHCSR_BUSFAULTPENDED        0x00004000
+#define  CPU_REG_NVIC_SHCSR_MEMFAULTPENDED        0x00002000
+#define  CPU_REG_NVIC_SHCSR_USGFAULTPENDED        0x00001000
+#define  CPU_REG_NVIC_SHCSR_SYSTICKACT            0x00000800
+#define  CPU_REG_NVIC_SHCSR_PENDSVACT             0x00000400
+#define  CPU_REG_NVIC_SHCSR_MONITORACT            0x00000100
+#define  CPU_REG_NVIC_SHCSR_SVCALLACT             0x00000080
+#define  CPU_REG_NVIC_SHCSR_USGFAULTACT           0x00000008
+#define  CPU_REG_NVIC_SHCSR_BUSFAULTACT           0x00000002
+#define  CPU_REG_NVIC_SHCSR_MEMFAULTACT           0x00000001
+
+                                                                /* -------- CONFIGURABLE FAULT STATUS REG BITS -------- */
+#define  CPU_REG_NVIC_CFSR_DIVBYZERO              0x02000000
+#define  CPU_REG_NVIC_CFSR_UNALIGNED              0x01000000
+#define  CPU_REG_NVIC_CFSR_NOCP                   0x00080000
+#define  CPU_REG_NVIC_CFSR_INVPC                  0x00040000
+#define  CPU_REG_NVIC_CFSR_INVSTATE               0x00020000
+#define  CPU_REG_NVIC_CFSR_UNDEFINSTR             0x00010000
+#define  CPU_REG_NVIC_CFSR_BFARVALID              0x00008000
+#define  CPU_REG_NVIC_CFSR_STKERR                 0x00001000
+#define  CPU_REG_NVIC_CFSR_UNSTKERR               0x00000800
+#define  CPU_REG_NVIC_CFSR_IMPRECISERR            0x00000400
+#define  CPU_REG_NVIC_CFSR_PRECISERR              0x00000200
+#define  CPU_REG_NVIC_CFSR_IBUSERR                0x00000100
+#define  CPU_REG_NVIC_CFSR_MMARVALID              0x00000080
+#define  CPU_REG_NVIC_CFSR_MSTKERR                0x00000010
+#define  CPU_REG_NVIC_CFSR_MUNSTKERR              0x00000008
+#define  CPU_REG_NVIC_CFSR_DACCVIOL               0x00000002
+#define  CPU_REG_NVIC_CFSR_IACCVIOL               0x00000001
+
+                                                                /* ------------ HARD FAULT STATUS REG BITS ------------ */
+#define  CPU_REG_NVIC_HFSR_DEBUGEVT               0x80000000
+#define  CPU_REG_NVIC_HFSR_FORCED                 0x40000000
+#define  CPU_REG_NVIC_HFSR_VECTTBL                0x00000002
+
+                                                                /* ------------ DEBUG FAULT STATUS REG BITS ----------- */
+#define  CPU_REG_NVIC_DFSR_EXTERNAL               0x00000010
+#define  CPU_REG_NVIC_DFSR_VCATCH                 0x00000008
+#define  CPU_REG_NVIC_DFSR_DWTTRAP                0x00000004
+#define  CPU_REG_NVIC_DFSR_BKPT                   0x00000002
+#define  CPU_REG_NVIC_DFSR_HALTED                 0x00000001
+
+
+/*
+*********************************************************************************************************
+*                                          CPU REGISTER MASK
+*********************************************************************************************************
+*/
+
+#define  CPU_MSK_NVIC_ICSR_VECT_ACTIVE            0x000001FF
+
+
+/*
+*********************************************************************************************************
+*                                        CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_CFG_ADDR_SIZE
+#error  "CPU_CFG_ADDR_SIZE              not #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+
+#elif  ((CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_08) && \
+        (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_16) && \
+        (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_32) && \
+        (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_64))
+#error  "CPU_CFG_ADDR_SIZE        illegally #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+#endif
+
+
+#ifndef  CPU_CFG_DATA_SIZE
+#error  "CPU_CFG_DATA_SIZE              not #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+
+#elif  ((CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_08) && \
+        (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_16) && \
+        (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_32) && \
+        (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_64))
+#error  "CPU_CFG_DATA_SIZE        illegally #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+#endif
+
+
+#ifndef  CPU_CFG_DATA_SIZE_MAX
+#error  "CPU_CFG_DATA_SIZE_MAX          not #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+
+#elif  ((CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_08) && \
+        (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_16) && \
+        (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_32) && \
+        (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_64))
+#error  "CPU_CFG_DATA_SIZE_MAX    illegally #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+#endif
+
+
+
+#if     (CPU_CFG_DATA_SIZE_MAX < CPU_CFG_DATA_SIZE)
+#error  "CPU_CFG_DATA_SIZE_MAX    illegally #define'd in 'cpu.h' "
+#error  "                         [MUST be  >= CPU_CFG_DATA_SIZE]"
+#endif
+
+
+
+
+#ifndef  CPU_CFG_ENDIAN_TYPE
+#error  "CPU_CFG_ENDIAN_TYPE            not #define'd in 'cpu.h'   "
+#error  "                         [MUST be  CPU_ENDIAN_TYPE_BIG   ]"
+#error  "                         [     ||  CPU_ENDIAN_TYPE_LITTLE]"
+
+#elif  ((CPU_CFG_ENDIAN_TYPE != CPU_ENDIAN_TYPE_BIG   ) && \
+        (CPU_CFG_ENDIAN_TYPE != CPU_ENDIAN_TYPE_LITTLE))
+#error  "CPU_CFG_ENDIAN_TYPE      illegally #define'd in 'cpu.h'   "
+#error  "                         [MUST be  CPU_ENDIAN_TYPE_BIG   ]"
+#error  "                         [     ||  CPU_ENDIAN_TYPE_LITTLE]"
+#endif
+
+
+
+
+#ifndef  CPU_CFG_STK_GROWTH
+#error  "CPU_CFG_STK_GROWTH             not #define'd in 'cpu.h'    "
+#error  "                         [MUST be  CPU_STK_GROWTH_LO_TO_HI]"
+#error  "                         [     ||  CPU_STK_GROWTH_HI_TO_LO]"
+
+#elif  ((CPU_CFG_STK_GROWTH != CPU_STK_GROWTH_LO_TO_HI) && \
+        (CPU_CFG_STK_GROWTH != CPU_STK_GROWTH_HI_TO_LO))
+#error  "CPU_CFG_STK_GROWTH       illegally #define'd in 'cpu.h'    "
+#error  "                         [MUST be  CPU_STK_GROWTH_LO_TO_HI]"
+#error  "                         [     ||  CPU_STK_GROWTH_HI_TO_LO]"
+#endif
+
+
+
+
+#ifndef  CPU_CFG_CRITICAL_METHOD
+#error  "CPU_CFG_CRITICAL_METHOD        not #define'd in 'cpu.h'             "
+#error  "                         [MUST be  CPU_CRITICAL_METHOD_INT_DIS_EN  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_STK  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_LOCAL]"
+
+#elif  ((CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_INT_DIS_EN  ) && \
+        (CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_STATUS_STK  ) && \
+        (CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_STATUS_LOCAL))
+#error  "CPU_CFG_CRITICAL_METHOD  illegally #define'd in 'cpu.h'             "
+#error  "                         [MUST be  CPU_CRITICAL_METHOD_INT_DIS_EN  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_STK  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_LOCAL]"
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*
+* Note(s) : (1) See 'cpu.h  MODULE'.
+*********************************************************************************************************
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif                                                          /* End of CPU module include.                           */
+

+ 290 - 0
MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/GNU/cpu_a.S

@@ -0,0 +1,290 @@
+@********************************************************************************************************
+@                                                uC/CPU
+@                                    CPU CONFIGURATION & PORT LAYER
+@
+@                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+@
+@               All rights reserved.  Protected by international copyright laws.
+@
+@               uC/CPU is provided in source form to registered licensees ONLY.  It is
+@               illegal to distribute this source code to any third party unless you receive
+@               written permission by an authorized Micrium representative.  Knowledge of
+@               the source code may NOT be used to develop a similar product.
+@
+@               Please help us continue to provide the Embedded community with the finest
+@               software available.  Your honesty is greatly appreciated.
+@
+@               You can find our product's user manual, API reference, release notes and
+@               more information at https://doc.micrium.com.
+@               You can contact us at www.micrium.com.
+@********************************************************************************************************
+
+@********************************************************************************************************
+@
+@                                            CPU PORT FILE
+@
+@                                            ARM-Cortex-M4
+@                                            GNU C Compiler
+@
+@ Filename      : cpu_a.asm
+@ Version       : V1.30.02.00
+@ Programmer(s) : JJL
+@********************************************************************************************************
+
+
+@********************************************************************************************************
+@                                           PUBLIC FUNCTIONS
+@********************************************************************************************************
+
+        .global  CPU_IntDis
+        .global  CPU_IntEn
+
+        .global  CPU_SR_Save
+        .global  CPU_SR_Restore
+
+        .global  CPU_WaitForInt
+        .global  CPU_WaitForExcept
+
+
+        .global  CPU_CntLeadZeros
+        .global  CPU_CntTrailZeros
+        .global  CPU_RevBits
+
+
+@********************************************************************************************************
+@                                      CODE GENERATION DIRECTIVES
+@********************************************************************************************************
+
+.text
+.align 2
+.syntax unified
+
+
+@********************************************************************************************************
+@                                    DISABLE and ENABLE INTERRUPTS
+@
+@ Description: Disable/Enable interrupts.
+@
+@ Prototypes : void  CPU_IntDis(void);
+@              void  CPU_IntEn (void);
+@********************************************************************************************************
+
+.thumb_func
+CPU_IntDis:
+        CPSID   I
+        BX      LR
+
+.thumb_func
+CPU_IntEn:
+        CPSIE   I
+        BX      LR
+
+
+@********************************************************************************************************
+@                                      CRITICAL SECTION FUNCTIONS
+@
+@ Description : Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking, the
+@               state of the interrupt disable flag is stored in the local variable 'cpu_sr' & interrupts
+@               are then disabled ('cpu_sr' is allocated in all functions that need to disable interrupts).
+@               The previous interrupt state is restored by copying 'cpu_sr' into the CPU's status register.
+@
+@ Prototypes  : CPU_SR  CPU_SR_Save   (void);
+@               void    CPU_SR_Restore(CPU_SR  cpu_sr);
+@
+@ Note(s)     : (1) These functions are used in general like this :
+@
+@                       void  Task (void  *p_arg)
+@                       {
+@                           CPU_SR_ALLOC();                     /* Allocate storage for CPU status register */
+@                               :
+@                               :
+@                           CPU_CRITICAL_ENTER();               /* cpu_sr = CPU_SR_Save();                  */
+@                               :
+@                               :
+@                           CPU_CRITICAL_EXIT();                /* CPU_SR_Restore(cpu_sr);                  */
+@                               :
+@                       }
+@********************************************************************************************************
+
+.thumb_func
+CPU_SR_Save:
+        MRS     R0, PRIMASK                     @ Set prio int mask to mask all (except faults)
+        CPSID   I
+        BX      LR
+
+.thumb_func
+CPU_SR_Restore:                                  @ See Note #2.
+        MSR     PRIMASK, R0
+        BX      LR
+
+
+@********************************************************************************************************
+@                                         WAIT FOR INTERRUPT
+@
+@ Description : Enters sleep state, which will be exited when an interrupt is received.
+@
+@ Prototypes  : void  CPU_WaitForInt (void)
+@
+@ Argument(s) : none.
+@********************************************************************************************************
+
+.thumb_func
+CPU_WaitForInt:
+        WFI                                     @ Wait for interrupt
+        BX      LR
+
+
+@********************************************************************************************************
+@                                         WAIT FOR EXCEPTION
+@
+@ Description : Enters sleep state, which will be exited when an exception is received.
+@
+@ Prototypes  : void  CPU_WaitForExcept (void)
+@
+@ Argument(s) : none.
+@********************************************************************************************************
+
+.thumb_func
+CPU_WaitForExcept:
+        WFE                                     @ Wait for exception
+        BX      LR
+
+
+@********************************************************************************************************
+@                                         CPU_CntLeadZeros()
+@                                        COUNT LEADING ZEROS
+@
+@ Description : Counts the number of contiguous, most-significant, leading zero bits before the
+@                   first binary one bit in a data value.
+@
+@ Prototype   : CPU_DATA  CPU_CntLeadZeros(CPU_DATA  val);
+@
+@ Argument(s) : val         Data value to count leading zero bits.
+@
+@ Return(s)   : Number of contiguous, most-significant, leading zero bits in 'val'.
+@
+@ Caller(s)   : Application.
+@
+@               This function is an INTERNAL CPU module function but MAY be called by application
+@               function(s).
+@
+@ Note(s)     : (1) (a) Supports 32-bit data value size as configured by 'CPU_DATA' (see 'cpu.h
+@                       CPU WORD CONFIGURATION  Note #1').
+@
+@                   (b) 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
+@
+@
+@               (2) MUST be defined in 'cpu_a.asm' (or 'cpu_c.c') if CPU_CFG_LEAD_ZEROS_ASM_PRESENT is
+@                   #define'd in 'cpu_cfg.h' or 'cpu.h'.
+@********************************************************************************************************
+
+.thumb_func
+CPU_CntLeadZeros:
+        CLZ     R0, R0                          @ Count leading zeros
+        BX      LR
+
+
+@********************************************************************************************************
+@                                         CPU_CntTrailZeros()
+@                                        COUNT TRAILING ZEROS
+@
+@ Description : Counts the number of contiguous, least-significant, trailing zero bits before the
+@                   first binary one bit in a data value.
+@
+@ Prototype   : CPU_DATA  CPU_CntTrailZeros(CPU_DATA  val);
+@
+@ Argument(s) : val         Data value to count trailing zero bits.
+@
+@ Return(s)   : Number of contiguous, least-significant, trailing zero bits in 'val'.
+@
+@ Caller(s)   : Application.
+@
+@               This function is an INTERNAL CPU module function but MAY be called by application
+@               function(s).
+@
+@ Note(s)     : (1) (a) Supports 32-bit data value size as configured by 'CPU_DATA' (see 'cpu.h
+@                       CPU WORD CONFIGURATION  Note #1').
+@
+@                   (b) 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
+@
+@
+@               (2) MUST be defined in 'cpu_a.asm' (or 'cpu_c.c') if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT is
+@                   #define'd in 'cpu_cfg.h' or 'cpu.h'.
+@********************************************************************************************************
+
+.thumb_func
+CPU_CntTrailZeros:
+        RBIT    R0, R0                          @ Reverse bits
+        CLZ     R0, R0                          @ Count trailing zeros
+        BX      LR
+
+
+@********************************************************************************************************
+@                                            CPU_RevBits()
+@                                            REVERSE BITS
+@
+@ Description : Reverses the bits in a data value.
+@
+@ Prototypes  : CPU_DATA  CPU_RevBits(CPU_DATA  val);
+@
+@ Argument(s) : val         Data value to reverse bits.
+@
+@ Return(s)   : Value with all bits in 'val' reversed (see Note #1).
+@
+@ Caller(s)   : Application.
+@
+@               This function is an INTERNAL CPU module function but MAY be called by application function(s).
+@
+@ Note(s)     : (1) The final, reversed data value for 'val' is such that :
+@
+@                       'val's final bit  0       =  'val's original bit  N
+@                       'val's final bit  1       =  'val's original bit (N - 1)
+@                       'val's final bit  2       =  'val's original bit (N - 2)
+@
+@                               ...                           ...
+@
+@                       'val's final bit (N - 2)  =  'val's original bit  2
+@                       'val's final bit (N - 1)  =  'val's original bit  1
+@                       'val's final bit  N       =  'val's original bit  0
+@********************************************************************************************************
+
+.thumb_func
+CPU_RevBits:
+        RBIT    R0, R0                          @ Reverse bits
+        BX      LR
+
+
+@********************************************************************************************************
+@                                     CPU ASSEMBLY PORT FILE END
+@********************************************************************************************************
+
+.end
+

+ 749 - 0
MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/GNU/cpu_c.c

@@ -0,0 +1,749 @@
+/*
+*********************************************************************************************************
+*                                                uC/CPU
+*                                    CPU CONFIGURATION & PORT LAYER
+*
+*                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*
+*               uC/CPU is provided in source form to registered licensees ONLY.  It is 
+*               illegal to distribute this source code to any third party unless you receive 
+*               written permission by an authorized Micrium representative.  Knowledge of 
+*               the source code may NOT be used to develop a similar product.
+*
+*               Please help us continue to provide the Embedded community with the finest 
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                            CPU PORT FILE
+*
+*                                            ARM-Cortex-M4
+*                                            GNU C Compiler
+*
+* Filename      : cpu_c.c
+* Version       : V1.30.02.00
+* Programmer(s) : JJL
+*                 BAN
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#define   MICRIUM_SOURCE
+#include  <cpu.h>
+#include  <cpu_core.h>
+
+#include  <lib_def.h>
+
+#ifdef __cplusplus
+extern  "C" {
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL DEFINES
+*********************************************************************************************************
+*/
+
+#define  CPU_INT_SRC_POS_MAX                  ((((CPU_REG_NVIC_NVIC + 1) & 0x1F) * 32) + 16)
+
+#define  CPU_BIT_BAND_SRAM_REG_LO                 0x20000000
+#define  CPU_BIT_BAND_SRAM_REG_HI                 0x200FFFFF
+#define  CPU_BIT_BAND_SRAM_BASE                   0x22000000
+
+
+#define  CPU_BIT_BAND_PERIPH_REG_LO               0x40000000
+#define  CPU_BIT_BAND_PERIPH_REG_HI               0x400FFFFF
+#define  CPU_BIT_BAND_PERIPH_BASE                 0x42000000
+
+
+/*
+*********************************************************************************************************
+*                                           LOCAL CONSTANTS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          LOCAL DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL TABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                       LOCAL GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                      LOCAL FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                     LOCAL CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          CPU_BitBandClr()
+*
+* Description : Clear bit in bit-band region.
+*
+* Argument(s) : addr            Byte address in memory space.
+*
+*               bit_nbr         Bit number in byte.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+void  CPU_BitBandClr (CPU_ADDR    addr,
+                      CPU_INT08U  bit_nbr)
+{
+    CPU_ADDR  bit_word_off;
+    CPU_ADDR  bit_word_addr;
+
+
+    if ((addr >= CPU_BIT_BAND_SRAM_REG_LO) &&
+        (addr <= CPU_BIT_BAND_SRAM_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_SRAM_REG_LO  ) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_SRAM_BASE   + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 0;
+
+    } else if ((addr >= CPU_BIT_BAND_PERIPH_REG_LO) &&
+               (addr <= CPU_BIT_BAND_PERIPH_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_PERIPH_REG_LO) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_PERIPH_BASE + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 0;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                          CPU_BitBandSet()
+*
+* Description : Set bit in bit-band region.
+*
+* Argument(s) : addr            Byte address in memory space.
+*
+*               bit_nbr         Bit number in byte.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+void  CPU_BitBandSet (CPU_ADDR    addr,
+                      CPU_INT08U  bit_nbr)
+{
+    CPU_ADDR  bit_word_off;
+    CPU_ADDR  bit_word_addr;
+
+
+    if ((addr >= CPU_BIT_BAND_SRAM_REG_LO) &&
+        (addr <= CPU_BIT_BAND_SRAM_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_SRAM_REG_LO  ) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_SRAM_BASE   + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 1;
+
+    } else if ((addr >= CPU_BIT_BAND_PERIPH_REG_LO) &&
+               (addr <= CPU_BIT_BAND_PERIPH_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_PERIPH_REG_LO) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_PERIPH_BASE + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 1;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                           CPU_IntSrcDis()
+*
+* Description : Disable an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table :
+*
+*                           0       Invalid (see Note #1a).
+*                           1       Invalid (see Note #1b).
+*                           2       Non-maskable interrupt.
+*                           3       Hard Fault.
+*                           4       Memory Management.
+*                           5       Bus Fault.
+*                           6       Usage Fault.
+*                           7-10    Reserved.
+*                           11      SVCall
+*                           12      Debug monitor.
+*                           13      Reserved
+*                           14      PendSV.
+*                           15      SysTick.
+*                           16+     External Interrupt.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Several table positions do not contain interrupt sources :
+*
+*                   (a) Position 0 contains the stack pointer.
+*                   (b) Positions 7-10, 13 are reserved.
+*
+*               (2) Several interrupts cannot be disabled/enabled :
+*
+*                   (a) Reset.
+*                   (b) NMI.
+*                   (c) Hard fault.
+*                   (d) SVCall.
+*                   (e) Debug monitor.
+*                   (f) PendSV.
+*
+*               (3) The maximum Cortex-M4 table position is 256.  A particular Cortex-M4 may have fewer
+*                   than 240 external exceptions and, consequently, fewer than 256 table positions.
+*                   This function assumes that the specified table position is valid if the interrupt
+*                   controller type register's INTLINESNUM field is large enough so that the position
+*                   COULD be valid.
+*********************************************************************************************************
+*/
+
+void  CPU_IntSrcDis (CPU_INT08U  pos)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  pos_max;
+    CPU_INT08U  nbr;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+        case CPU_INT_SVCALL:                                    /* SVCall (see Note #2).                                */
+        case CPU_INT_DBGMON:                                    /* Debug monitor (see Note #2).                         */
+        case CPU_INT_PENDSV:                                    /* PendSV (see Note #2).                                */
+             break;
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_MEMFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_BUSFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_USGFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_ST_CTRL &= ~CPU_REG_NVIC_ST_CTRL_ENABLE;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 32;
+                 nbr   = (pos - 16) % 32;
+
+                 CPU_CRITICAL_ENTER();
+                 CPU_REG_NVIC_CLREN(group) = DEF_BIT(nbr);
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                           CPU_IntSrcEn()
+*
+* Description : Enable an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()  Note #1'.
+*
+*               (2) See 'CPU_IntSrcDis()  Note #2'.
+*
+*               (3) See 'CPU_IntSrcDis()  Note #3'.
+*********************************************************************************************************
+*/
+
+void  CPU_IntSrcEn (CPU_INT08U  pos)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+        case CPU_INT_SVCALL:                                    /* SVCall (see Note #2).                                */
+        case CPU_INT_DBGMON:                                    /* Debug monitor (see Note #2).                         */
+        case CPU_INT_PENDSV:                                    /* PendSV (see Note #2).                                */
+             break;
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_MEMFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_BUSFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_USGFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_ENABLE;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 32;
+                 nbr   = (pos - 16) % 32;
+
+                 CPU_CRITICAL_ENTER();
+                 CPU_REG_NVIC_SETEN(group) = DEF_BIT(nbr);
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                         CPU_IntSrcPendClr()
+*
+* Description : Clear a pending interrupt.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()  Note #1'.
+*
+*               (2) The pending status of several interrupts cannot be clear/set :
+*
+*                   (a) Reset.
+*                   (b) NMI.
+*                   (c) Hard fault.
+*                   (d) Memory Managment.
+*                   (e) Bus Fault.
+*                   (f) Usage Fault.
+*                   (g) SVCall.
+*                   (h) Debug monitor.
+*                   (i) PendSV.
+*                   (j) Systick 
+*
+*               (3) See 'CPU_IntSrcDis()  Note #3'.
+*********************************************************************************************************
+*/
+
+void  CPU_IntSrcPendClr (CPU_INT08U  pos)
+
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+        case CPU_INT_MEM:                                       /* Memory management (see Note #2).                     */
+        case CPU_INT_SVCALL:                                    /* SVCall (see Note #2).                                */
+        case CPU_INT_DBGMON:                                    /* Debug monitor (see Note #2).                         */
+        case CPU_INT_PENDSV:                                    /* PendSV (see Note #2).                                */
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             break;
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 32;
+                 nbr   = (pos - 16) % 32;
+
+                 CPU_CRITICAL_ENTER();
+                 CPU_REG_NVIC_CLRPEND(group) = DEF_BIT(nbr);
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                         CPU_IntSrcPrioSet()
+*
+* Description : Set priority of an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+*               prio    Priority.  Use a lower priority number for a higher priority.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()  Note #1'.
+*
+*               (2) Several interrupts priorities CANNOT be set :
+*
+*                   (a) Reset (always -3).
+*                   (b) NMI (always -2).
+*                   (c) Hard fault (always -1).
+*
+*               (3) See 'CPU_IntSrcDis()  Note #3'.
+*********************************************************************************************************
+*/
+
+void  CPU_IntSrcPrioSet (CPU_INT08U  pos,
+                         CPU_INT08U  prio)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_INT32U  temp;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+             break;
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI1;
+             temp                &= ~(DEF_OCTET_MASK << (0 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (0 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI1  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI1;
+             temp                &= ~(DEF_OCTET_MASK << (1 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (1 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI1  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI1;
+             temp                &= ~(DEF_OCTET_MASK << (2 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (2 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI1  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SVCALL:                                    /* SVCall.                                              */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI2;
+             temp                &= ~((CPU_INT32U)DEF_OCTET_MASK << (3 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio                       << (3 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI2  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_DBGMON:                                    /* Debug monitor.                                       */
+             CPU_CRITICAL_ENTER();
+             temp                = CPU_REG_NVIC_SHPRI3;
+             temp                &= ~(DEF_OCTET_MASK << (0 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (0 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI3  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_PENDSV:                                    /* PendSV.                                              */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI3;
+             temp                &= ~(DEF_OCTET_MASK << (2 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (2 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI3  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI3;
+             temp                &= ~((CPU_INT32U)DEF_OCTET_MASK << (3 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio                       << (3 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI3  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group                    = (pos - 16) / 4;
+                 nbr                      = (pos - 16) % 4;
+
+                 CPU_CRITICAL_ENTER();
+                 temp                     = CPU_REG_NVIC_PRIO(group);
+                 temp                    &= ~(DEF_OCTET_MASK << (nbr * DEF_OCTET_NBR_BITS));
+                 temp                    |=  (prio           << (nbr * DEF_OCTET_NBR_BITS));
+                 CPU_REG_NVIC_PRIO(group) = temp;
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                         CPU_IntSrcPrioGet()
+*
+* Description : Get priority of an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+* Return(s)   : Priority of interrupt source.  If the interrupt source specified is invalid, then
+*               DEF_INT_16S_MIN_VAL is returned.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()      Note #1'.
+*
+*               (2) See 'CPU_IntSrcPrioSet()  Note #2'.
+*
+*               (3) See 'CPU_IntSrcDis()      Note #3'.
+*********************************************************************************************************
+*/
+
+CPU_INT16S  CPU_IntSrcPrioGet (CPU_INT08U  pos)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_INT16S  prio;
+    CPU_INT32U  temp;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             prio = DEF_INT_16S_MIN_VAL;
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+             prio = -3;
+             break;
+
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+             prio = -2;
+             break;
+
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+             prio = -1;
+             break;
+
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI1;
+             prio = (temp >> (0 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI1;
+             prio = (temp >> (1 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI1;
+             prio = (temp >> (2 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SVCALL:                                    /* SVCall.                                              */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI2;
+             prio = (temp >> (3 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_DBGMON:                                    /* Debug monitor.                                       */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI3;
+             prio = (temp >> (0 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_PENDSV:                                    /* PendSV.                                              */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI3;
+             prio = (temp >> (2 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI3;
+             prio = (temp >> (3 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 4;
+                 nbr   = (pos - 16) % 4;
+
+                 CPU_CRITICAL_ENTER();
+                 temp  = CPU_REG_NVIC_PRIO(group);
+                 CPU_CRITICAL_EXIT();
+
+                 prio  = (temp >> (nbr * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             } else {
+                 prio  = DEF_INT_16S_MIN_VAL;
+             }
+             break;
+    }
+
+    return (prio);
+}
+
+#ifdef __cplusplus
+}
+#endif
+

+ 754 - 0
MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/IAR/cpu.h

@@ -0,0 +1,754 @@
+/*
+*********************************************************************************************************
+*                                                uC/CPU
+*                                    CPU CONFIGURATION & PORT LAYER
+*
+*                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*
+*               uC/CPU is provided in source form to registered licensees ONLY.  It is 
+*               illegal to distribute this source code to any third party unless you receive 
+*               written permission by an authorized Micrium representative.  Knowledge of 
+*               the source code may NOT be used to develop a similar product.
+*
+*               Please help us continue to provide the Embedded community with the finest 
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                            CPU PORT FILE
+*
+*                                            ARM-Cortex-M4
+*                                            IAR C Compiler
+*
+* Filename      : cpu.h
+* Version       : V1.30.02.00
+* Programmer(s) : JJL
+*                 BAN
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*
+* Note(s) : (1) This CPU header file is protected from multiple pre-processor inclusion through use of 
+*               the  CPU module present pre-processor macro definition.
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_MODULE_PRESENT                                     /* See Note #1.                                         */
+#define  CPU_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*                                          CPU INCLUDE FILES
+*
+* Note(s) : (1) The following CPU files are located in the following directories :
+*
+*               (a) \<Your Product Application>\cpu_cfg.h
+*
+*               (b) (1) \<CPU-Compiler Directory>\cpu_def.h
+*                   (2) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.*
+*
+*                       where
+*                               <Your Product Application>      directory path for Your Product's Application
+*                               <CPU-Compiler Directory>        directory path for common   CPU-compiler software
+*                               <cpu>                           directory name for specific CPU
+*                               <compiler>                      directory name for specific compiler
+*
+*           (2) Compiler MUST be configured to include as additional include path directories :
+*
+*               (a) '\<Your Product Application>\' directory                            See Note #1a
+*
+*               (b) (1) '\<CPU-Compiler Directory>\'                  directory         See Note #1b1
+*                   (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory         See Note #1b2
+*
+*           (3) Since NO custom library modules are included, 'cpu.h' may ONLY use configurations from
+*               CPU configuration file 'cpu_cfg.h' that do NOT reference any custom library definitions.
+*
+*               In other words, 'cpu.h' may use 'cpu_cfg.h' configurations that are #define'd to numeric
+*               constants or to NULL (i.e. NULL-valued #define's); but may NOT use configurations to
+*               custom library #define's (e.g. DEF_DISABLED or DEF_ENABLED).
+*********************************************************************************************************
+*/
+
+#include  <intrinsics.h>
+
+#include  <cpu_def.h>
+#include  <cpu_cfg.h>                                           /* See Note #3.                                         */
+
+#ifdef __cplusplus
+extern  "C" {
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                    CONFIGURE STANDARD DATA TYPES
+*
+* Note(s) : (1) Configure standard data types according to CPU-/compiler-specifications.
+*
+*           (2) (a) (1) 'CPU_FNCT_VOID' data type defined to replace the commonly-used function pointer
+*                       data type of a pointer to a function which returns void & has no arguments.
+*
+*                   (2) Example function pointer usage :
+*
+*                           CPU_FNCT_VOID  FnctName;
+*
+*                           FnctName();
+*
+*               (b) (1) 'CPU_FNCT_PTR'  data type defined to replace the commonly-used function pointer
+*                       data type of a pointer to a function which returns void & has a single void
+*                       pointer argument.
+*
+*                   (2) Example function pointer usage :
+*
+*                           CPU_FNCT_PTR   FnctName;
+*                           void          *p_obj
+*
+*                           FnctName(p_obj);
+*********************************************************************************************************
+*/
+
+typedef            void        CPU_VOID;
+typedef            char        CPU_CHAR;                        /*  8-bit character                                     */
+typedef  unsigned  char        CPU_BOOLEAN;                     /*  8-bit boolean or logical                            */
+typedef  unsigned  char        CPU_INT08U;                      /*  8-bit unsigned integer                              */
+typedef    signed  char        CPU_INT08S;                      /*  8-bit   signed integer                              */
+typedef  unsigned  short       CPU_INT16U;                      /* 16-bit unsigned integer                              */
+typedef    signed  short       CPU_INT16S;                      /* 16-bit   signed integer                              */
+typedef  unsigned  int         CPU_INT32U;                      /* 32-bit unsigned integer                              */
+typedef    signed  int         CPU_INT32S;                      /* 32-bit   signed integer                              */
+typedef  unsigned  long  long  CPU_INT64U;                      /* 64-bit unsigned integer                              */
+typedef    signed  long  long  CPU_INT64S;                      /* 64-bit   signed integer                              */
+
+typedef            float       CPU_FP32;                        /* 32-bit floating point                                */
+typedef            double      CPU_FP64;                        /* 64-bit floating point                                */
+
+
+typedef  volatile  CPU_INT08U  CPU_REG08;                       /*  8-bit register                                      */
+typedef  volatile  CPU_INT16U  CPU_REG16;                       /* 16-bit register                                      */
+typedef  volatile  CPU_INT32U  CPU_REG32;                       /* 32-bit register                                      */
+typedef  volatile  CPU_INT64U  CPU_REG64;                       /* 64-bit register                                      */
+
+
+typedef            void      (*CPU_FNCT_VOID)(void);            /* See Note #2a.                                        */
+typedef            void      (*CPU_FNCT_PTR )(void *p_obj);     /* See Note #2b.                                        */
+
+
+/*
+*********************************************************************************************************
+*                                       CPU WORD CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_ADDR_SIZE, CPU_CFG_DATA_SIZE, & CPU_CFG_DATA_SIZE_MAX with CPU's &/or 
+*               compiler's word sizes :
+*
+*                   CPU_WORD_SIZE_08             8-bit word size
+*                   CPU_WORD_SIZE_16            16-bit word size
+*                   CPU_WORD_SIZE_32            32-bit word size
+*                   CPU_WORD_SIZE_64            64-bit word size
+*
+*           (2) Configure CPU_CFG_ENDIAN_TYPE with CPU's data-word-memory order :
+*
+*               (a) CPU_ENDIAN_TYPE_BIG         Big-   endian word order (CPU words' most  significant
+*                                                                         octet @ lowest memory address)
+*               (b) CPU_ENDIAN_TYPE_LITTLE      Little-endian word order (CPU words' least significant
+*                                                                         octet @ lowest memory address)
+*********************************************************************************************************
+*/
+
+                                                                /* Define  CPU         word sizes (see Note #1) :       */
+#define  CPU_CFG_ADDR_SIZE              CPU_WORD_SIZE_32        /* Defines CPU address word size  (in octets).          */
+#define  CPU_CFG_DATA_SIZE              CPU_WORD_SIZE_32        /* Defines CPU data    word size  (in octets).          */
+#define  CPU_CFG_DATA_SIZE_MAX          CPU_WORD_SIZE_64        /* Defines CPU maximum word size  (in octets).          */
+
+#define  CPU_CFG_ENDIAN_TYPE            CPU_ENDIAN_TYPE_LITTLE  /* Defines CPU data    word-memory order (see Note #2). */
+
+
+/*
+*********************************************************************************************************
+*                                 CONFIGURE CPU ADDRESS & DATA TYPES
+*********************************************************************************************************
+*/
+
+                                                                /* CPU address type based on address bus size.          */
+#if     (CPU_CFG_ADDR_SIZE == CPU_WORD_SIZE_32)
+typedef  CPU_INT32U  CPU_ADDR;
+#elif   (CPU_CFG_ADDR_SIZE == CPU_WORD_SIZE_16)
+typedef  CPU_INT16U  CPU_ADDR;
+#else
+typedef  CPU_INT08U  CPU_ADDR;
+#endif
+
+                                                                /* CPU data    type based on data    bus size.          */
+#if     (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_32)
+typedef  CPU_INT32U  CPU_DATA;
+#elif   (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_16)
+typedef  CPU_INT16U  CPU_DATA;
+#else
+typedef  CPU_INT08U  CPU_DATA;
+#endif
+
+
+typedef  CPU_DATA    CPU_ALIGN;                                 /* Defines CPU data-word-alignment size.                */
+typedef  CPU_ADDR    CPU_SIZE_T;                                /* Defines CPU standard 'size_t'   size.                */
+
+
+/*
+*********************************************************************************************************
+*                                       CPU STACK CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_STK_GROWTH in 'cpu.h' with CPU's stack growth order :
+*
+*               (a) CPU_STK_GROWTH_LO_TO_HI     CPU stack pointer increments to the next higher  stack
+*                                                   memory address after data is pushed onto the stack
+*               (b) CPU_STK_GROWTH_HI_TO_LO     CPU stack pointer decrements to the next lower   stack
+*                                                   memory address after data is pushed onto the stack
+*
+*           (2) Configure CPU_CFG_STK_ALIGN_BYTES with the highest minimum alignement required for
+*               cpu stacks.
+*
+*               (a) ARM Procedure Calls Standard requires an 8 bytes stack alignment.
+*********************************************************************************************************
+*/
+
+#define  CPU_CFG_STK_GROWTH       CPU_STK_GROWTH_HI_TO_LO       /* Defines CPU stack growth order (see Note #1).        */
+
+#define  CPU_CFG_STK_ALIGN_BYTES  (8u)                          /* Defines CPU stack alignment in bytes. (see Note #2). */
+
+typedef  CPU_INT32U               CPU_STK;                      /* Defines CPU stack data type.                         */
+typedef  CPU_ADDR                 CPU_STK_SIZE;                 /* Defines CPU stack size data type.                    */
+
+
+/*
+*********************************************************************************************************
+*                                   CRITICAL SECTION CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_CRITICAL_METHOD with CPU's/compiler's critical section method :
+*
+*                                                       Enter/Exit critical sections by ...
+*
+*                   CPU_CRITICAL_METHOD_INT_DIS_EN      Disable/Enable interrupts
+*                   CPU_CRITICAL_METHOD_STATUS_STK      Push/Pop       interrupt status onto stack
+*                   CPU_CRITICAL_METHOD_STATUS_LOCAL    Save/Restore   interrupt status to local variable
+*
+*               (a) CPU_CRITICAL_METHOD_INT_DIS_EN  is NOT a preferred method since it does NOT support
+*                   multiple levels of interrupts.  However, with some CPUs/compilers, this is the only
+*                   available method.
+*
+*               (b) CPU_CRITICAL_METHOD_STATUS_STK    is one preferred method since it supports multiple
+*                   levels of interrupts.  However, this method assumes that the compiler provides C-level
+*                   &/or assembly-level functionality for the following :
+*
+*                     ENTER CRITICAL SECTION :
+*                       (1) Push/save   interrupt status onto a local stack
+*                       (2) Disable     interrupts
+*
+*                     EXIT  CRITICAL SECTION :
+*                       (3) Pop/restore interrupt status from a local stack
+*
+*               (c) CPU_CRITICAL_METHOD_STATUS_LOCAL  is one preferred method since it supports multiple
+*                   levels of interrupts.  However, this method assumes that the compiler provides C-level
+*                   &/or assembly-level functionality for the following :
+*
+*                     ENTER CRITICAL SECTION :
+*                       (1) Save    interrupt status into a local variable
+*                       (2) Disable interrupts
+*
+*                     EXIT  CRITICAL SECTION :
+*                       (3) Restore interrupt status from a local variable
+*
+*           (2) Critical section macro's most likely require inline assembly.  If the compiler does NOT
+*               allow inline assembly in C source files, critical section macro's MUST call an assembly
+*               subroutine defined in a 'cpu_a.asm' file located in the following software directory :
+*
+*                   \<CPU-Compiler Directory>\<cpu>\<compiler>\
+*
+*                       where
+*                               <CPU-Compiler Directory>    directory path for common   CPU-compiler software
+*                               <cpu>                       directory name for specific CPU
+*                               <compiler>                  directory name for specific compiler
+*
+*           (3) (a) To save/restore interrupt status, a local variable 'cpu_sr' of type 'CPU_SR' MAY need
+*                   to be declared (e.g. if 'CPU_CRITICAL_METHOD_STATUS_LOCAL' method is configured).
+*
+*                   (1) 'cpu_sr' local variable SHOULD be declared via the CPU_SR_ALLOC() macro which, if 
+*                        used, MUST be declared following ALL other local variables.
+*
+*                        Example :
+*
+*                           void  Fnct (void)
+*                           {
+*                               CPU_INT08U  val_08;
+*                               CPU_INT16U  val_16;
+*                               CPU_INT32U  val_32;
+*                               CPU_SR_ALLOC();         MUST be declared after ALL other local variables
+*                                   :
+*                                   :
+*                           }
+*
+*               (b) Configure 'CPU_SR' data type with the appropriate-sized CPU data type large enough to
+*                   completely store the CPU's/compiler's status word.
+*********************************************************************************************************
+*/
+                                                                /* Configure CPU critical method      (see Note #1) :   */
+#define  CPU_CFG_CRITICAL_METHOD    CPU_CRITICAL_METHOD_STATUS_LOCAL
+
+typedef  CPU_INT32U                 CPU_SR;                     /* Defines   CPU status register size (see Note #3b).   */
+
+                                                                /* Allocates CPU status register word (see Note #3a).   */
+#if     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
+#define  CPU_SR_ALLOC()             CPU_SR  cpu_sr = (CPU_SR)0
+#else
+#define  CPU_SR_ALLOC()
+#endif
+
+                                                                        /* Save    CPU status word & disable interrupts.*/
+#define  CPU_INT_DIS()         do { cpu_sr = __get_PRIMASK(); __disable_interrupt(); } while (0)
+#define  CPU_INT_EN()          do { __set_PRIMASK(cpu_sr); } while (0)  /* Restore CPU status word.                     */
+
+
+#ifdef   CPU_CFG_INT_DIS_MEAS_EN
+                                                                        /* Disable interrupts, ...                      */
+                                                                        /* & start interrupts disabled time measurement.*/
+#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS();         \
+                                    CPU_IntDisMeasStart(); }  while (0)
+                                                                        /* Stop & measure   interrupts disabled time,   */
+                                                                        /* ...  & re-enable interrupts.                 */
+#define  CPU_CRITICAL_EXIT()   do { CPU_IntDisMeasStop();  \
+                                    CPU_INT_EN();          }  while (0)
+
+#else
+
+#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS(); } while (0)          /* Disable   interrupts.                        */
+#define  CPU_CRITICAL_EXIT()   do { CPU_INT_EN();  } while (0)          /* Re-enable interrupts.                        */
+
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                    MEMORY BARRIERS CONFIGURATION
+*
+* Note(s) : (1) (a) Configure memory barriers if required by the architecture.
+*
+*                   CPU_MB      Full memory barrier.
+*                   CPU_RMB     Read (Loads) memory barrier.
+*                   CPU_WMB     Write (Stores) memory barrier.
+*
+*********************************************************************************************************
+*/
+
+#define  CPU_MB()       __DSB()
+#define  CPU_RMB()      __DSB()
+#define  CPU_WMB()      __DSB()
+
+
+/*
+*********************************************************************************************************
+*                                    CPU COUNT ZEROS CONFIGURATION
+*
+* Note(s) : (1) (a) Configure CPU_CFG_LEAD_ZEROS_ASM_PRESENT  to define count leading  zeros bits 
+*                   function(s) in :
+*
+*                   (1) 'cpu_a.asm',  if CPU_CFG_LEAD_ZEROS_ASM_PRESENT       #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable assembly-optimized function(s)
+*
+*                   (2) 'cpu_core.c', if CPU_CFG_LEAD_ZEROS_ASM_PRESENT   NOT #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable C-source-optimized function(s) otherwise
+*
+*               (b) Configure CPU_CFG_TRAIL_ZEROS_ASM_PRESENT to define count trailing zeros bits 
+*                   function(s) in :
+*
+*                   (1) 'cpu_a.asm',  if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT      #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable assembly-optimized function(s)
+*
+*                   (2) 'cpu_core.c', if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT  NOT #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable C-source-optimized function(s) otherwise
+*********************************************************************************************************
+*/
+
+                                                                /* Configure CPU count leading  zeros bits ...          */
+#define  CPU_CFG_LEAD_ZEROS_ASM_PRESENT                         /* ... assembly-version (see Note #1a).                 */
+
+                                                                /* Configure CPU count trailing zeros bits ...          */
+#define  CPU_CFG_TRAIL_ZEROS_ASM_PRESENT                        /* ... assembly-version (see Note #1b).                 */
+
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+void        CPU_IntDis       (void);
+void        CPU_IntEn        (void);
+
+void        CPU_IntSrcDis    (CPU_INT08U  pos);
+void        CPU_IntSrcEn     (CPU_INT08U  pos);
+void        CPU_IntSrcPendClr(CPU_INT08U  pos);
+CPU_INT16S  CPU_IntSrcPrioGet(CPU_INT08U  pos);
+void        CPU_IntSrcPrioSet(CPU_INT08U  pos,
+                              CPU_INT08U  prio);
+
+
+CPU_SR      CPU_SR_Save      (void);
+void        CPU_SR_Restore   (CPU_SR      cpu_sr);
+
+
+void        CPU_WaitForInt   (void);
+void        CPU_WaitForExcept(void);
+
+
+CPU_DATA    CPU_RevBits      (CPU_DATA    val);
+
+void        CPU_BitBandClr   (CPU_ADDR    addr,
+                              CPU_INT08U  bit_nbr);
+void        CPU_BitBandSet   (CPU_ADDR    addr,
+                              CPU_INT08U  bit_nbr);
+
+
+/*
+*********************************************************************************************************
+*                                          INTERRUPT SOURCES
+*********************************************************************************************************
+*/
+
+#define  CPU_INT_STK_PTR                                   0u
+#define  CPU_INT_RESET                                     1u
+#define  CPU_INT_NMI                                       2u
+#define  CPU_INT_HFAULT                                    3u
+#define  CPU_INT_MEM                                       4u
+#define  CPU_INT_BUSFAULT                                  5u
+#define  CPU_INT_USAGEFAULT                                6u
+#define  CPU_INT_RSVD_07                                   7u
+#define  CPU_INT_RSVD_08                                   8u
+#define  CPU_INT_RSVD_09                                   9u
+#define  CPU_INT_RSVD_10                                  10u
+#define  CPU_INT_SVCALL                                   11u
+#define  CPU_INT_DBGMON                                   12u
+#define  CPU_INT_RSVD_13                                  13u
+#define  CPU_INT_PENDSV                                   14u
+#define  CPU_INT_SYSTICK                                  15u
+#define  CPU_INT_EXT0                                     16u
+
+/*
+*********************************************************************************************************
+*                                            CPU REGISTERS
+*********************************************************************************************************
+*/
+
+#define  CPU_REG_NVIC_NVIC           (*((CPU_REG32 *)(0xE000E004)))             /* Int Ctrl'er Type Reg.                */
+#define  CPU_REG_NVIC_ST_CTRL        (*((CPU_REG32 *)(0xE000E010)))             /* SysTick Ctrl & Status Reg.           */
+#define  CPU_REG_NVIC_ST_RELOAD      (*((CPU_REG32 *)(0xE000E014)))             /* SysTick Reload      Value Reg.       */
+#define  CPU_REG_NVIC_ST_CURRENT     (*((CPU_REG32 *)(0xE000E018)))             /* SysTick Current     Value Reg.       */
+#define  CPU_REG_NVIC_ST_CAL         (*((CPU_REG32 *)(0xE000E01C)))             /* SysTick Calibration Value Reg.       */
+
+#define  CPU_REG_NVIC_SETEN(n)       (*((CPU_REG32 *)(0xE000E100 + (n) * 4u)))  /* IRQ Set En Reg.                      */
+#define  CPU_REG_NVIC_CLREN(n)       (*((CPU_REG32 *)(0xE000E180 + (n) * 4u)))  /* IRQ Clr En Reg.                      */
+#define  CPU_REG_NVIC_SETPEND(n)     (*((CPU_REG32 *)(0xE000E200 + (n) * 4u)))  /* IRQ Set Pending Reg.                 */
+#define  CPU_REG_NVIC_CLRPEND(n)     (*((CPU_REG32 *)(0xE000E280 + (n) * 4u)))  /* IRQ Clr Pending Reg.                 */
+#define  CPU_REG_NVIC_ACTIVE(n)      (*((CPU_REG32 *)(0xE000E300 + (n) * 4u)))  /* IRQ Active Reg.                      */
+#define  CPU_REG_NVIC_PRIO(n)        (*((CPU_REG32 *)(0xE000E400 + (n) * 4u)))  /* IRQ Prio Reg.                        */
+
+#define  CPU_REG_NVIC_CPUID          (*((CPU_REG32 *)(0xE000ED00)))             /* CPUID Base Reg.                      */
+#define  CPU_REG_NVIC_ICSR           (*((CPU_REG32 *)(0xE000ED04)))             /* Int Ctrl State  Reg.                 */
+#define  CPU_REG_NVIC_VTOR           (*((CPU_REG32 *)(0xE000ED08)))             /* Vect Tbl Offset Reg.                 */
+#define  CPU_REG_NVIC_AIRCR          (*((CPU_REG32 *)(0xE000ED0C)))             /* App Int/Reset Ctrl Reg.              */
+#define  CPU_REG_NVIC_SCR            (*((CPU_REG32 *)(0xE000ED10)))             /* System Ctrl Reg.                     */
+#define  CPU_REG_NVIC_CCR            (*((CPU_REG32 *)(0xE000ED14)))             /* Cfg    Ctrl Reg.                     */
+#define  CPU_REG_NVIC_SHPRI1         (*((CPU_REG32 *)(0xE000ED18)))             /* System Handlers  4 to  7 Prio.       */
+#define  CPU_REG_NVIC_SHPRI2         (*((CPU_REG32 *)(0xE000ED1C)))             /* System Handlers  8 to 11 Prio.       */
+#define  CPU_REG_NVIC_SHPRI3         (*((CPU_REG32 *)(0xE000ED20)))             /* System Handlers 12 to 15 Prio.       */
+#define  CPU_REG_NVIC_SHCSR          (*((CPU_REG32 *)(0xE000ED24)))             /* System Handler Ctrl & State Reg.     */
+#define  CPU_REG_NVIC_CFSR           (*((CPU_REG32 *)(0xE000ED28)))             /* Configurable Fault Status Reg.       */
+#define  CPU_REG_NVIC_HFSR           (*((CPU_REG32 *)(0xE000ED2C)))             /* Hard  Fault Status Reg.              */
+#define  CPU_REG_NVIC_DFSR           (*((CPU_REG32 *)(0xE000ED30)))             /* Debug Fault Status Reg.              */
+#define  CPU_REG_NVIC_MMFAR          (*((CPU_REG32 *)(0xE000ED34)))             /* Mem Manage Addr Reg.                 */
+#define  CPU_REG_NVIC_BFAR           (*((CPU_REG32 *)(0xE000ED38)))             /* Bus Fault  Addr Reg.                 */
+#define  CPU_REG_NVIC_AFSR           (*((CPU_REG32 *)(0xE000ED3C)))             /* Aux Fault Status Reg.                */
+#define  CPU_REG_NVIC_CPACR          (*((CPU_REG32 *)(0xE000ED88)))             /* Coprocessor Access Control Reg.      */
+
+#define  CPU_REG_NVIC_PFR0           (*((CPU_REG32 *)(0xE000ED40)))             /* Processor Feature Reg 0.             */
+#define  CPU_REG_NVIC_PFR1           (*((CPU_REG32 *)(0xE000ED44)))             /* Processor Feature Reg 1.             */
+#define  CPU_REG_NVIC_DFR0           (*((CPU_REG32 *)(0xE000ED48)))             /* Debug     Feature Reg 0.             */
+#define  CPU_REG_NVIC_AFR0           (*((CPU_REG32 *)(0xE000ED4C)))             /* Aux       Feature Reg 0.             */
+#define  CPU_REG_NVIC_MMFR0          (*((CPU_REG32 *)(0xE000ED50)))             /* Memory Model Feature Reg 0.          */
+#define  CPU_REG_NVIC_MMFR1          (*((CPU_REG32 *)(0xE000ED54)))             /* Memory Model Feature Reg 1.          */
+#define  CPU_REG_NVIC_MMFR2          (*((CPU_REG32 *)(0xE000ED58)))             /* Memory Model Feature Reg 2.          */
+#define  CPU_REG_NVIC_MMFR3          (*((CPU_REG32 *)(0xE000ED5C)))             /* Memory Model Feature Reg 3.          */
+#define  CPU_REG_NVIC_ISAFR0         (*((CPU_REG32 *)(0xE000ED60)))             /* ISA Feature Reg 0.                   */
+#define  CPU_REG_NVIC_ISAFR1         (*((CPU_REG32 *)(0xE000ED64)))             /* ISA Feature Reg 1.                   */
+#define  CPU_REG_NVIC_ISAFR2         (*((CPU_REG32 *)(0xE000ED68)))             /* ISA Feature Reg 2.                   */
+#define  CPU_REG_NVIC_ISAFR3         (*((CPU_REG32 *)(0xE000ED6C)))             /* ISA Feature Reg 3.                   */
+#define  CPU_REG_NVIC_ISAFR4         (*((CPU_REG32 *)(0xE000ED70)))             /* ISA Feature Reg 4.                   */
+#define  CPU_REG_NVIC_SW_TRIG        (*((CPU_REG32 *)(0xE000EF00)))             /* Software Trigger Int Reg.            */
+
+#define  CPU_REG_MPU_TYPE            (*((CPU_REG32 *)(0xE000ED90)))             /* MPU Type Reg.                        */
+#define  CPU_REG_MPU_CTRL            (*((CPU_REG32 *)(0xE000ED94)))             /* MPU Ctrl Reg.                        */
+#define  CPU_REG_MPU_REG_NBR         (*((CPU_REG32 *)(0xE000ED98)))             /* MPU Region Nbr Reg.                  */
+#define  CPU_REG_MPU_REG_BASE        (*((CPU_REG32 *)(0xE000ED9C)))             /* MPU Region Base Addr Reg.            */
+#define  CPU_REG_MPU_REG_ATTR        (*((CPU_REG32 *)(0xE000EDA0)))             /* MPU Region Attrib & Size Reg.        */
+
+#define  CPU_REG_DBG_CTRL            (*((CPU_REG32 *)(0xE000EDF0)))             /* Debug Halting Ctrl & Status Reg.     */
+#define  CPU_REG_DBG_SELECT          (*((CPU_REG32 *)(0xE000EDF4)))             /* Debug Core Reg Selector Reg.         */
+#define  CPU_REG_DBG_DATA            (*((CPU_REG32 *)(0xE000EDF8)))             /* Debug Core Reg Data     Reg.         */
+#define  CPU_REG_DBG_INT             (*((CPU_REG32 *)(0xE000EDFC)))             /* Debug Except & Monitor Ctrl Reg.     */
+
+#define  CPU_REG_SCB_FPCCR           (*((CPU_REG32 *)(0xE000EF34)))             /* Floating-Point Context Control Reg.  */
+#define  CPU_REG_SCB_FPCAR           (*((CPU_REG32 *)(0xE000EF38)))             /* Floating-Point Context Address Reg.  */
+#define  CPU_REG_SCB_FPDSCR          (*((CPU_REG32 *)(0xE000EF3C)))             /* FP Default Status Control Reg.       */
+
+
+/*
+*********************************************************************************************************
+*                                          CPU REGISTER BITS
+*********************************************************************************************************
+*/
+
+                                                                /* ---------- SYSTICK CTRL & STATUS REG BITS ---------- */
+#define  CPU_REG_NVIC_ST_CTRL_COUNTFLAG           0x00010000
+#define  CPU_REG_NVIC_ST_CTRL_CLKSOURCE           0x00000004
+#define  CPU_REG_NVIC_ST_CTRL_TICKINT             0x00000002
+#define  CPU_REG_NVIC_ST_CTRL_ENABLE              0x00000001
+
+
+                                                                /* -------- SYSTICK CALIBRATION VALUE REG BITS -------- */
+#define  CPU_REG_NVIC_ST_CAL_NOREF                0x80000000
+#define  CPU_REG_NVIC_ST_CAL_SKEW                 0x40000000
+
+                                                                /* -------------- INT CTRL STATE REG BITS ------------- */
+#define  CPU_REG_NVIC_ICSR_NMIPENDSET             0x80000000
+#define  CPU_REG_NVIC_ICSR_PENDSVSET              0x10000000
+#define  CPU_REG_NVIC_ICSR_PENDSVCLR              0x08000000
+#define  CPU_REG_NVIC_ICSR_PENDSTSET              0x04000000
+#define  CPU_REG_NVIC_ICSR_PENDSTCLR              0x02000000
+#define  CPU_REG_NVIC_ICSR_ISRPREEMPT             0x00800000
+#define  CPU_REG_NVIC_ICSR_ISRPENDING             0x00400000
+#define  CPU_REG_NVIC_ICSR_RETTOBASE              0x00000800
+
+                                                                /* ------------- VECT TBL OFFSET REG BITS ------------- */
+#define  CPU_REG_NVIC_VTOR_TBLBASE                0x20000000
+
+                                                                /* ------------ APP INT/RESET CTRL REG BITS ----------- */
+#define  CPU_REG_NVIC_AIRCR_ENDIANNESS            0x00008000
+#define  CPU_REG_NVIC_AIRCR_SYSRESETREQ           0x00000004
+#define  CPU_REG_NVIC_AIRCR_VECTCLRACTIVE         0x00000002
+#define  CPU_REG_NVIC_AIRCR_VECTRESET             0x00000001
+
+                                                                /* --------------- SYSTEM CTRL REG BITS --------------- */
+#define  CPU_REG_NVIC_SCR_SEVONPEND               0x00000010
+#define  CPU_REG_NVIC_SCR_SLEEPDEEP               0x00000004
+#define  CPU_REG_NVIC_SCR_SLEEPONEXIT             0x00000002
+
+                                                                /* ----------------- CFG CTRL REG BITS ---------------- */
+#define  CPU_REG_NVIC_CCR_STKALIGN                0x00000200
+#define  CPU_REG_NVIC_CCR_BFHFNMIGN               0x00000100
+#define  CPU_REG_NVIC_CCR_DIV_0_TRP               0x00000010
+#define  CPU_REG_NVIC_CCR_UNALIGN_TRP             0x00000008
+#define  CPU_REG_NVIC_CCR_USERSETMPEND            0x00000002
+#define  CPU_REG_NVIC_CCR_NONBASETHRDENA          0x00000001
+
+                                                                /* ------- SYSTEM HANDLER CTRL & STATE REG BITS ------- */
+#define  CPU_REG_NVIC_SHCSR_USGFAULTENA           0x00040000
+#define  CPU_REG_NVIC_SHCSR_BUSFAULTENA           0x00020000
+#define  CPU_REG_NVIC_SHCSR_MEMFAULTENA           0x00010000
+#define  CPU_REG_NVIC_SHCSR_SVCALLPENDED          0x00008000
+#define  CPU_REG_NVIC_SHCSR_BUSFAULTPENDED        0x00004000
+#define  CPU_REG_NVIC_SHCSR_MEMFAULTPENDED        0x00002000
+#define  CPU_REG_NVIC_SHCSR_USGFAULTPENDED        0x00001000
+#define  CPU_REG_NVIC_SHCSR_SYSTICKACT            0x00000800
+#define  CPU_REG_NVIC_SHCSR_PENDSVACT             0x00000400
+#define  CPU_REG_NVIC_SHCSR_MONITORACT            0x00000100
+#define  CPU_REG_NVIC_SHCSR_SVCALLACT             0x00000080
+#define  CPU_REG_NVIC_SHCSR_USGFAULTACT           0x00000008
+#define  CPU_REG_NVIC_SHCSR_BUSFAULTACT           0x00000002
+#define  CPU_REG_NVIC_SHCSR_MEMFAULTACT           0x00000001
+
+                                                                /* -------- CONFIGURABLE FAULT STATUS REG BITS -------- */
+#define  CPU_REG_NVIC_CFSR_DIVBYZERO              0x02000000
+#define  CPU_REG_NVIC_CFSR_UNALIGNED              0x01000000
+#define  CPU_REG_NVIC_CFSR_NOCP                   0x00080000
+#define  CPU_REG_NVIC_CFSR_INVPC                  0x00040000
+#define  CPU_REG_NVIC_CFSR_INVSTATE               0x00020000
+#define  CPU_REG_NVIC_CFSR_UNDEFINSTR             0x00010000
+#define  CPU_REG_NVIC_CFSR_BFARVALID              0x00008000
+#define  CPU_REG_NVIC_CFSR_STKERR                 0x00001000
+#define  CPU_REG_NVIC_CFSR_UNSTKERR               0x00000800
+#define  CPU_REG_NVIC_CFSR_IMPRECISERR            0x00000400
+#define  CPU_REG_NVIC_CFSR_PRECISERR              0x00000200
+#define  CPU_REG_NVIC_CFSR_IBUSERR                0x00000100
+#define  CPU_REG_NVIC_CFSR_MMARVALID              0x00000080
+#define  CPU_REG_NVIC_CFSR_MSTKERR                0x00000010
+#define  CPU_REG_NVIC_CFSR_MUNSTKERR              0x00000008
+#define  CPU_REG_NVIC_CFSR_DACCVIOL               0x00000002
+#define  CPU_REG_NVIC_CFSR_IACCVIOL               0x00000001
+
+                                                                /* ------------ HARD FAULT STATUS REG BITS ------------ */
+#define  CPU_REG_NVIC_HFSR_DEBUGEVT               0x80000000
+#define  CPU_REG_NVIC_HFSR_FORCED                 0x40000000
+#define  CPU_REG_NVIC_HFSR_VECTTBL                0x00000002
+
+                                                                /* ------------ DEBUG FAULT STATUS REG BITS ----------- */
+#define  CPU_REG_NVIC_DFSR_EXTERNAL               0x00000010
+#define  CPU_REG_NVIC_DFSR_VCATCH                 0x00000008
+#define  CPU_REG_NVIC_DFSR_DWTTRAP                0x00000004
+#define  CPU_REG_NVIC_DFSR_BKPT                   0x00000002
+#define  CPU_REG_NVIC_DFSR_HALTED                 0x00000001
+
+                                                                /* -------- COPROCESSOR ACCESS CONTROL REG BITS ------- */
+#define  CPU_REG_NVIC_CPACR_CP10_FULL_ACCESS      0x00300000
+#define  CPU_REG_NVIC_CPACR_CP11_FULL_ACCESS      0x00C00000
+
+/*
+*********************************************************************************************************
+*                                          CPU REGISTER MASK
+*********************************************************************************************************
+*/
+
+#define  CPU_MSK_NVIC_ICSR_VECT_ACTIVE            0x000001FF
+
+
+/*
+*********************************************************************************************************
+*                                        CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_CFG_ADDR_SIZE
+#error  "CPU_CFG_ADDR_SIZE              not #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+
+#elif  ((CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_08) && \
+        (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_16) && \
+        (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_32) && \
+        (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_64))
+#error  "CPU_CFG_ADDR_SIZE        illegally #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+#endif
+
+
+#ifndef  CPU_CFG_DATA_SIZE
+#error  "CPU_CFG_DATA_SIZE              not #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+
+#elif  ((CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_08) && \
+        (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_16) && \
+        (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_32) && \
+        (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_64))
+#error  "CPU_CFG_DATA_SIZE        illegally #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+#endif
+
+
+#ifndef  CPU_CFG_DATA_SIZE_MAX
+#error  "CPU_CFG_DATA_SIZE_MAX          not #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+
+#elif  ((CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_08) && \
+        (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_16) && \
+        (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_32) && \
+        (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_64))
+#error  "CPU_CFG_DATA_SIZE_MAX    illegally #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+#endif
+
+
+
+#if     (CPU_CFG_DATA_SIZE_MAX < CPU_CFG_DATA_SIZE)
+#error  "CPU_CFG_DATA_SIZE_MAX    illegally #define'd in 'cpu.h' "
+#error  "                         [MUST be  >= CPU_CFG_DATA_SIZE]"
+#endif
+
+
+
+
+#ifndef  CPU_CFG_ENDIAN_TYPE
+#error  "CPU_CFG_ENDIAN_TYPE            not #define'd in 'cpu.h'   "
+#error  "                         [MUST be  CPU_ENDIAN_TYPE_BIG   ]"
+#error  "                         [     ||  CPU_ENDIAN_TYPE_LITTLE]"
+
+#elif  ((CPU_CFG_ENDIAN_TYPE != CPU_ENDIAN_TYPE_BIG   ) && \
+        (CPU_CFG_ENDIAN_TYPE != CPU_ENDIAN_TYPE_LITTLE))
+#error  "CPU_CFG_ENDIAN_TYPE      illegally #define'd in 'cpu.h'   "
+#error  "                         [MUST be  CPU_ENDIAN_TYPE_BIG   ]"
+#error  "                         [     ||  CPU_ENDIAN_TYPE_LITTLE]"
+#endif
+
+
+
+
+#ifndef  CPU_CFG_STK_GROWTH
+#error  "CPU_CFG_STK_GROWTH             not #define'd in 'cpu.h'    "
+#error  "                         [MUST be  CPU_STK_GROWTH_LO_TO_HI]"
+#error  "                         [     ||  CPU_STK_GROWTH_HI_TO_LO]"
+
+#elif  ((CPU_CFG_STK_GROWTH != CPU_STK_GROWTH_LO_TO_HI) && \
+        (CPU_CFG_STK_GROWTH != CPU_STK_GROWTH_HI_TO_LO))
+#error  "CPU_CFG_STK_GROWTH       illegally #define'd in 'cpu.h'    "
+#error  "                         [MUST be  CPU_STK_GROWTH_LO_TO_HI]"
+#error  "                         [     ||  CPU_STK_GROWTH_HI_TO_LO]"
+#endif
+
+
+
+
+#ifndef  CPU_CFG_CRITICAL_METHOD
+#error  "CPU_CFG_CRITICAL_METHOD        not #define'd in 'cpu.h'             "
+#error  "                         [MUST be  CPU_CRITICAL_METHOD_INT_DIS_EN  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_STK  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_LOCAL]"
+
+#elif  ((CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_INT_DIS_EN  ) && \
+        (CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_STATUS_STK  ) && \
+        (CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_STATUS_LOCAL))
+#error  "CPU_CFG_CRITICAL_METHOD  illegally #define'd in 'cpu.h'             "
+#error  "                         [MUST be  CPU_CRITICAL_METHOD_INT_DIS_EN  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_STK  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_LOCAL]"
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*
+* Note(s) : (1) See 'cpu.h  MODULE'.
+*********************************************************************************************************
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif                                                          /* End of CPU module include.                           */
+

+ 281 - 0
MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/IAR/cpu_a.asm

@@ -0,0 +1,281 @@
+;********************************************************************************************************
+;                                                uC/CPU
+;                                    CPU CONFIGURATION & PORT LAYER
+;
+;                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+;
+;               All rights reserved.  Protected by international copyright laws.
+;
+;               uC/CPU is provided in source form to registered licensees ONLY.  It is 
+;               illegal to distribute this source code to any third party unless you receive 
+;               written permission by an authorized Micrium representative.  Knowledge of 
+;               the source code may NOT be used to develop a similar product.
+;
+;               Please help us continue to provide the Embedded community with the finest 
+;               software available.  Your honesty is greatly appreciated.
+;
+;               You can find our product's user manual, API reference, release notes and
+;               more information at https://doc.micrium.com.
+;               You can contact us at www.micrium.com.
+;********************************************************************************************************
+
+;********************************************************************************************************
+;
+;                                            CPU PORT FILE
+;
+;                                            ARM-Cortex-M4
+;                                            IAR C Compiler
+;
+; Filename      : cpu_a.asm
+; Version       : V1.30.02.00
+; Programmer(s) : JJL
+;********************************************************************************************************
+
+
+;********************************************************************************************************
+;                                           PUBLIC FUNCTIONS
+;********************************************************************************************************
+
+        PUBLIC  CPU_IntDis
+        PUBLIC  CPU_IntEn
+
+        PUBLIC  CPU_SR_Save
+        PUBLIC  CPU_SR_Restore
+
+        PUBLIC  CPU_WaitForInt
+        PUBLIC  CPU_WaitForExcept
+
+
+        PUBLIC  CPU_CntLeadZeros
+        PUBLIC  CPU_CntTrailZeros
+        PUBLIC  CPU_RevBits
+
+
+;********************************************************************************************************
+;                                      CODE GENERATION DIRECTIVES
+;********************************************************************************************************
+
+        RSEG CODE:CODE:NOROOT(2)
+        THUMB
+
+;********************************************************************************************************
+;                                    DISABLE and ENABLE INTERRUPTS
+;
+; Description: Disable/Enable interrupts.
+;
+; Prototypes : void  CPU_IntDis(void);
+;              void  CPU_IntEn (void);
+;********************************************************************************************************
+
+CPU_IntDis
+        CPSID   I
+        BX      LR
+
+
+CPU_IntEn
+        CPSIE   I
+        BX      LR
+
+
+;********************************************************************************************************
+;                                      CRITICAL SECTION FUNCTIONS
+;
+; Description : Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking, the
+;               state of the interrupt disable flag is stored in the local variable 'cpu_sr' & interrupts
+;               are then disabled ('cpu_sr' is allocated in all functions that need to disable interrupts).
+;               The previous interrupt state is restored by copying 'cpu_sr' into the CPU's status register.
+;
+; Prototypes  : CPU_SR  CPU_SR_Save   (void);
+;               void    CPU_SR_Restore(CPU_SR  cpu_sr);
+;
+; Note(s)     : (1) These functions are used in general like this :
+;
+;                       void  Task (void  *p_arg)
+;                       {
+;                           CPU_SR_ALLOC();                     /* Allocate storage for CPU status register */
+;                               :
+;                               :
+;                           CPU_CRITICAL_ENTER();               /* cpu_sr = CPU_SR_Save();                  */
+;                               :
+;                               :
+;                           CPU_CRITICAL_EXIT();                /* CPU_SR_Restore(cpu_sr);                  */
+;                               :
+;                       }
+;********************************************************************************************************
+
+CPU_SR_Save
+        MRS     R0, PRIMASK                     ; Set prio int mask to mask all (except faults)
+        CPSID   I
+        BX      LR
+
+
+CPU_SR_Restore                                  ; See Note #2.
+        MSR     PRIMASK, R0
+        BX      LR
+
+
+;********************************************************************************************************
+;                                         WAIT FOR INTERRUPT
+;
+; Description : Enters sleep state, which will be exited when an interrupt is received.
+;
+; Prototypes  : void  CPU_WaitForInt (void)
+;
+; Argument(s) : none.
+;********************************************************************************************************
+
+CPU_WaitForInt:
+        WFI                                     ; Wait for interrupt
+        BX      LR
+
+
+;********************************************************************************************************
+;                                         WAIT FOR EXCEPTION
+;
+; Description : Enters sleep state, which will be exited when an exception is received.
+;
+; Prototypes  : void  CPU_WaitForExcept (void)
+;
+; Argument(s) : none.
+;********************************************************************************************************
+
+CPU_WaitForExcept:
+        WFE                                     ; Wait for exception
+        BX      LR
+
+
+;********************************************************************************************************
+;                                         CPU_CntLeadZeros()
+;                                        COUNT LEADING ZEROS
+;
+; Description : Counts the number of contiguous, most-significant, leading zero bits before the 
+;                   first binary one bit in a data value.
+;
+; Prototype   : CPU_DATA  CPU_CntLeadZeros(CPU_DATA  val);
+;
+; Argument(s) : val         Data value to count leading zero bits.
+;
+; Return(s)   : Number of contiguous, most-significant, leading zero bits in 'val'.
+;
+; Caller(s)   : Application.
+;
+;               This function is an INTERNAL CPU module function but MAY be called by application 
+;               function(s).
+;
+; Note(s)     : (1) (a) Supports 32-bit data value size as configured by 'CPU_DATA' (see 'cpu.h  
+;                       CPU WORD CONFIGURATION  Note #1').
+;
+;                   (b) 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
+;
+;
+;               (2) MUST be defined in 'cpu_a.asm' (or 'cpu_c.c') if CPU_CFG_LEAD_ZEROS_ASM_PRESENT is 
+;                   #define'd in 'cpu_cfg.h' or 'cpu.h'.
+;********************************************************************************************************
+
+CPU_CntLeadZeros:
+        CLZ     R0, R0                          ; Count leading zeros
+        BX      LR
+
+
+;********************************************************************************************************
+;                                         CPU_CntTrailZeros()
+;                                        COUNT TRAILING ZEROS
+;
+; Description : Counts the number of contiguous, least-significant, trailing zero bits before the 
+;                   first binary one bit in a data value.
+;
+; Prototype   : CPU_DATA  CPU_CntTrailZeros(CPU_DATA  val);
+;
+; Argument(s) : val         Data value to count trailing zero bits.
+;
+; Return(s)   : Number of contiguous, least-significant, trailing zero bits in 'val'.
+;
+; Caller(s)   : Application.
+;
+;               This function is an INTERNAL CPU module function but MAY be called by application 
+;               function(s).
+;
+; Note(s)     : (1) (a) Supports 32-bit data value size as configured by 'CPU_DATA' (see 'cpu.h  
+;                       CPU WORD CONFIGURATION  Note #1').
+;
+;                   (b) 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
+;
+;
+;               (2) MUST be defined in 'cpu_a.asm' (or 'cpu_c.c') if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT is 
+;                   #define'd in 'cpu_cfg.h' or 'cpu.h'.
+;********************************************************************************************************
+
+CPU_CntTrailZeros:
+        RBIT    R0, R0                          ; Reverse bits
+        CLZ     R0, R0                          ; Count trailing zeros
+        BX      LR
+
+
+;********************************************************************************************************
+;                                            CPU_RevBits()
+;                                            REVERSE BITS
+;
+; Description : Reverses the bits in a data value.
+;
+; Prototypes  : CPU_DATA  CPU_RevBits(CPU_DATA  val);
+;
+; Argument(s) : val         Data value to reverse bits.
+;
+; Return(s)   : Value with all bits in 'val' reversed (see Note #1).
+;
+; Caller(s)   : Application.
+;
+;               This function is an INTERNAL CPU module function but MAY be called by application function(s).
+;
+; Note(s)     : (1) The final, reversed data value for 'val' is such that :
+;
+;                       'val's final bit  0       =  'val's original bit  N
+;                       'val's final bit  1       =  'val's original bit (N - 1)
+;                       'val's final bit  2       =  'val's original bit (N - 2)
+;
+;                               ...                           ...
+;
+;                       'val's final bit (N - 2)  =  'val's original bit  2
+;                       'val's final bit (N - 1)  =  'val's original bit  1
+;                       'val's final bit  N       =  'val's original bit  0
+;********************************************************************************************************
+
+CPU_RevBits:
+        RBIT    R0, R0                          ; Reverse bits
+        BX      LR
+
+
+;********************************************************************************************************
+;                                     CPU ASSEMBLY PORT FILE END
+;********************************************************************************************************
+
+        END
+

+ 746 - 0
MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/IAR/cpu_c.c

@@ -0,0 +1,746 @@
+/*
+*********************************************************************************************************
+*                                                uC/CPU
+*                                    CPU CONFIGURATION & PORT LAYER
+*
+*                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*
+*               uC/CPU is provided in source form to registered licensees ONLY.  It is 
+*               illegal to distribute this source code to any third party unless you receive 
+*               written permission by an authorized Micrium representative.  Knowledge of 
+*               the source code may NOT be used to develop a similar product.
+*
+*               Please help us continue to provide the Embedded community with the finest 
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                            CPU PORT FILE
+*
+*                                            ARM-Cortex-M4
+*                                            IAR C Compiler
+*
+* Filename      : cpu_c.c
+* Version       : V1.30.02.00
+* Programmer(s) : JJL
+*                 BAN
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#define    MICRIUM_SOURCE
+#include  <cpu.h>
+#include  <cpu_core.h>
+
+#include  <lib_def.h>
+
+#ifdef __cplusplus
+extern  "C" {
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL DEFINES
+*********************************************************************************************************
+*/
+
+#define  CPU_INT_SRC_POS_MAX                  ((((CPU_REG_NVIC_NVIC + 1) & 0x1F) * 32) + 16)
+
+#define  CPU_BIT_BAND_SRAM_REG_LO                 0x20000000
+#define  CPU_BIT_BAND_SRAM_REG_HI                 0x200FFFFF
+#define  CPU_BIT_BAND_SRAM_BASE                   0x22000000
+
+
+#define  CPU_BIT_BAND_PERIPH_REG_LO               0x40000000
+#define  CPU_BIT_BAND_PERIPH_REG_HI               0x400FFFFF
+#define  CPU_BIT_BAND_PERIPH_BASE                 0x42000000
+
+
+/*
+*********************************************************************************************************
+*                                           LOCAL CONSTANTS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          LOCAL DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL TABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                       LOCAL GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                      LOCAL FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                     LOCAL CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          CPU_BitBandClr()
+*
+* Description : Clear bit in bit-band region.
+*
+* Argument(s) : addr            Byte address in memory space.
+*
+*               bit_nbr         Bit number in byte.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+void  CPU_BitBandClr (CPU_ADDR    addr,
+                      CPU_INT08U  bit_nbr)
+{
+    CPU_ADDR  bit_word_off;
+    CPU_ADDR  bit_word_addr;
+
+
+    if ((addr >= CPU_BIT_BAND_SRAM_REG_LO) &&
+        (addr <= CPU_BIT_BAND_SRAM_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_SRAM_REG_LO  ) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_SRAM_BASE   + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 0;
+
+    } else if ((addr >= CPU_BIT_BAND_PERIPH_REG_LO) &&
+               (addr <= CPU_BIT_BAND_PERIPH_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_PERIPH_REG_LO) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_PERIPH_BASE + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 0;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                          CPU_BitBandSet()
+*
+* Description : Set bit in bit-band region.
+*
+* Argument(s) : addr            Byte address in memory space.
+*
+*               bit_nbr         Bit number in byte.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+void  CPU_BitBandSet (CPU_ADDR    addr,
+                      CPU_INT08U  bit_nbr)
+{
+    CPU_ADDR  bit_word_off;
+    CPU_ADDR  bit_word_addr;
+
+
+    if ((addr >= CPU_BIT_BAND_SRAM_REG_LO) &&
+        (addr <= CPU_BIT_BAND_SRAM_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_SRAM_REG_LO  ) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_SRAM_BASE   + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 1;
+
+    } else if ((addr >= CPU_BIT_BAND_PERIPH_REG_LO) &&
+               (addr <= CPU_BIT_BAND_PERIPH_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_PERIPH_REG_LO) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_PERIPH_BASE + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 1;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                           CPU_IntSrcDis()
+*
+* Description : Disable an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table :
+*
+*                           0       Invalid (see Note #1a).
+*                           1       Invalid (see Note #1b).
+*                           2       Non-maskable interrupt.
+*                           3       Hard Fault.
+*                           4       Memory Management.
+*                           5       Bus Fault.
+*                           6       Usage Fault.
+*                           7-10    Reserved.
+*                           11      SVCall
+*                           12      Debug monitor.
+*                           13      Reserved
+*                           14      PendSV.
+*                           15      SysTick.
+*                           16+     External Interrupt.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Several table positions do not contain interrupt sources :
+*
+*                   (a) Position 0 contains the stack pointer.
+*                   (b) Positions 7-10, 13 are reserved.
+*
+*               (2) Several interrupts cannot be disabled/enabled :
+*
+*                   (a) Reset.
+*                   (b) NMI.
+*                   (c) Hard fault.
+*                   (d) SVCall.
+*                   (e) Debug monitor.
+*                   (f) PendSV.
+*
+*               (3) The maximum Cortex-M3 table position is 256.  A particular Cortex-M3 may have fewer
+*                   than 240 external exceptions and, consequently, fewer than 256 table positions.
+*                   This function assumes that the specified table position is valid if the interrupt
+*                   controller type register's INTLINESNUM field is large enough so that the position
+*                   COULD be valid.
+*********************************************************************************************************
+*/
+void  CPU_IntSrcDis (CPU_INT08U  pos)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  pos_max;
+    CPU_INT08U  nbr;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+        case CPU_INT_SVCALL:                                    /* SVCall (see Note #2).                                */
+        case CPU_INT_DBGMON:                                    /* Debug monitor (see Note #2).                         */
+        case CPU_INT_PENDSV:                                    /* PendSV (see Note #2).                                */
+             break;
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_MEMFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_BUSFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_USGFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_ST_CTRL &= ~CPU_REG_NVIC_ST_CTRL_ENABLE;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 32;
+                 nbr   = (pos - 16) % 32;
+
+                 CPU_CRITICAL_ENTER();
+                 CPU_REG_NVIC_CLREN(group) = DEF_BIT(nbr);
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                           CPU_IntSrcEn()
+*
+* Description : Enable an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()  Note #1'.
+*
+*               (2) See 'CPU_IntSrcDis()  Note #2'.
+*
+*               (3) See 'CPU_IntSrcDis()  Note #3'.
+*********************************************************************************************************
+*/
+
+void  CPU_IntSrcEn (CPU_INT08U  pos)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+        case CPU_INT_SVCALL:                                    /* SVCall (see Note #2).                                */
+        case CPU_INT_DBGMON:                                    /* Debug monitor (see Note #2).                         */
+        case CPU_INT_PENDSV:                                    /* PendSV (see Note #2).                                */
+             break;
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_MEMFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_BUSFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_USGFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_ENABLE;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 32;
+                 nbr   = (pos - 16) % 32;
+
+                 CPU_CRITICAL_ENTER();
+                 CPU_REG_NVIC_SETEN(group) = DEF_BIT(nbr);
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+/*
+*********************************************************************************************************
+*                                         CPU_IntSrcPendClr()
+*
+* Description : Clear a pending interrupt.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()  Note #1'.
+*
+*               (2) The pending status of several interrupts cannot be clear/set :
+*
+*                   (a) Reset.
+*                   (b) NMI.
+*                   (c) Hard fault.
+*                   (d) Memory Managment.
+*                   (e) Bus Fault.
+*                   (f) Usage Fault.
+*                   (g) SVCall.
+*                   (h) Debug monitor.
+*                   (i) PendSV.
+*                   (j) Systick 
+*
+*               (3) See 'CPU_IntSrcDis()  Note #3'.
+*********************************************************************************************************
+*/
+
+void  CPU_IntSrcPendClr (CPU_INT08U  pos)
+
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+        case CPU_INT_MEM:                                       /* Memory management (see Note #2).                     */
+        case CPU_INT_SVCALL:                                    /* SVCall (see Note #2).                                */
+        case CPU_INT_DBGMON:                                    /* Debug monitor (see Note #2).                         */
+        case CPU_INT_PENDSV:                                    /* PendSV (see Note #2).                                */
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             break;
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 32;
+                 nbr   = (pos - 16) % 32;
+
+                 CPU_CRITICAL_ENTER();
+                 CPU_REG_NVIC_CLRPEND(group) = DEF_BIT(nbr);
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                         CPU_IntSrcPrioSet()
+*
+* Description : Set priority of an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+*               prio    Priority.  Use a lower priority number for a higher priority.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()  Note #1'.
+*
+*               (2) Several interrupts priorities CANNOT be set :
+*
+*                   (a) Reset (always -3).
+*                   (b) NMI (always -2).
+*                   (c) Hard fault (always -1).
+*
+*               (3) See 'CPU_IntSrcDis()  Note #3'.
+*********************************************************************************************************
+*/
+
+void  CPU_IntSrcPrioSet (CPU_INT08U  pos,
+                         CPU_INT08U  prio)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_INT32U  temp;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+             break;
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI1;
+             temp                &= ~(DEF_OCTET_MASK << (0 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (0 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI1  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI1;
+             temp                &= ~(DEF_OCTET_MASK << (1 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (1 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI1  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI1;
+             temp                &= ~(DEF_OCTET_MASK << (2 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (2 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI1  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SVCALL:                                    /* SVCall.                                              */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI2;
+             temp                &= ~((CPU_INT32U)DEF_OCTET_MASK << (3 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio                       << (3 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI2  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_DBGMON:                                    /* Debug monitor.                                       */
+             CPU_CRITICAL_ENTER();
+             temp                = CPU_REG_NVIC_SHPRI3;
+             temp                &= ~(DEF_OCTET_MASK << (0 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (0 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI3  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_PENDSV:                                    /* PendSV.                                              */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI3;
+             temp                &= ~(DEF_OCTET_MASK << (2 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (2 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI3  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI3;
+             temp                &= ~((CPU_INT32U)DEF_OCTET_MASK << (3 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio                       << (3 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI3  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group                    = (pos - 16) / 4;
+                 nbr                      = (pos - 16) % 4;
+
+                 CPU_CRITICAL_ENTER();
+                 temp                     = CPU_REG_NVIC_PRIO(group);
+                 temp                    &= ~(DEF_OCTET_MASK << (nbr * DEF_OCTET_NBR_BITS));
+                 temp                    |=  (prio           << (nbr * DEF_OCTET_NBR_BITS));
+                 CPU_REG_NVIC_PRIO(group) = temp;
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                         CPU_IntSrcPrioGet()
+*
+* Description : Get priority of an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+* Return(s)   : Priority of interrupt source.  If the interrupt source specified is invalid, then
+*               DEF_INT_16S_MIN_VAL is returned.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()      Note #1'.
+*
+*               (2) See 'CPU_IntSrcPrioSet()  Note #2'.
+*
+*               (3) See 'CPU_IntSrcDis()      Note #3'.
+*********************************************************************************************************
+*/
+
+CPU_INT16S  CPU_IntSrcPrioGet (CPU_INT08U  pos)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_INT16S  prio;
+    CPU_INT32U  temp;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             prio = DEF_INT_16S_MIN_VAL;
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+             prio = -3;
+             break;
+
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+             prio = -2;
+             break;
+
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+             prio = -1;
+             break;
+
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI1;
+             prio = (temp >> (0 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI1;
+             prio = (temp >> (1 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI1;
+             prio = (temp >> (2 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SVCALL:                                    /* SVCall.                                              */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI2;
+             prio = (temp >> (3 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_DBGMON:                                    /* Debug monitor.                                       */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI3;
+             prio = (temp >> (0 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_PENDSV:                                    /* PendSV.                                              */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI3;
+             prio = (temp >> (2 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI3;
+             prio = (temp >> (3 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 4;
+                 nbr   = (pos - 16) % 4;
+
+                 CPU_CRITICAL_ENTER();
+                 temp  = CPU_REG_NVIC_PRIO(group);
+                 CPU_CRITICAL_EXIT();
+
+                 prio  = (temp >> (nbr * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             } else {
+                 prio  = DEF_INT_16S_MIN_VAL;
+             }
+             break;
+    }
+
+    return (prio);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 748 - 0
MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/RealView/cpu.h

@@ -0,0 +1,748 @@
+/*
+*********************************************************************************************************
+*                                                uC/CPU
+*                                    CPU CONFIGURATION & PORT LAYER
+*
+*                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*
+*               uC/CPU is provided in source form to registered licensees ONLY.  It is 
+*               illegal to distribute this source code to any third party unless you receive 
+*               written permission by an authorized Micrium representative.  Knowledge of 
+*               the source code may NOT be used to develop a similar product.
+*
+*               Please help us continue to provide the Embedded community with the finest 
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                            CPU PORT FILE
+*
+*                                            ARM-Cortex-M4
+*                                      RealView Development Suite
+*                            RealView Microcontroller Development Kit (MDK)
+*                                       ARM Developer Suite (ADS)
+*                                            Keil uVision
+*
+* Filename      : cpu.h
+* Version       : V1.30.02.00
+* Programmer(s) : JJL
+*                 BAN
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*
+* Note(s) : (1) This CPU header file is protected from multiple pre-processor inclusion through use of 
+*               the  CPU module present pre-processor macro definition.
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_MODULE_PRESENT                                     /* See Note #1.                                         */
+#define  CPU_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*                                          CPU INCLUDE FILES
+*
+* Note(s) : (1) The following CPU files are located in the following directories :
+*
+*               (a) \<Your Product Application>\cpu_cfg.h
+*
+*               (b) (1) \<CPU-Compiler Directory>\cpu_def.h
+*                   (2) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.*
+*
+*                       where
+*                               <Your Product Application>      directory path for Your Product's Application
+*                               <CPU-Compiler Directory>        directory path for common   CPU-compiler software
+*                               <cpu>                           directory name for specific CPU
+*                               <compiler>                      directory name for specific compiler
+*
+*           (2) Compiler MUST be configured to include as additional include path directories :
+*
+*               (a) '\<Your Product Application>\' directory                            See Note #1a
+*
+*               (b) (1) '\<CPU-Compiler Directory>\'                  directory         See Note #1b1
+*                   (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory         See Note #1b2
+*
+*           (3) Since NO custom library modules are included, 'cpu.h' may ONLY use configurations from
+*               CPU configuration file 'cpu_cfg.h' that do NOT reference any custom library definitions.
+*
+*               In other words, 'cpu.h' may use 'cpu_cfg.h' configurations that are #define'd to numeric
+*               constants or to NULL (i.e. NULL-valued #define's); but may NOT use configurations to
+*               custom library #define's (e.g. DEF_DISABLED or DEF_ENABLED).
+*********************************************************************************************************
+*/
+
+#include  <cpu_def.h>
+#include  <cpu_cfg.h>                                           /* See Note #3.                                         */
+
+#ifdef __cplusplus
+extern  "C" {
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                    CONFIGURE STANDARD DATA TYPES
+*
+* Note(s) : (1) Configure standard data types according to CPU-/compiler-specifications.
+*
+*           (2) (a) (1) 'CPU_FNCT_VOID' data type defined to replace the commonly-used function pointer
+*                       data type of a pointer to a function which returns void & has no arguments.
+*
+*                   (2) Example function pointer usage :
+*
+*                           CPU_FNCT_VOID  FnctName;
+*
+*                           FnctName();
+*
+*               (b) (1) 'CPU_FNCT_PTR'  data type defined to replace the commonly-used function pointer
+*                       data type of a pointer to a function which returns void & has a single void
+*                       pointer argument.
+*
+*                   (2) Example function pointer usage :
+*
+*                           CPU_FNCT_PTR   FnctName;
+*                           void          *p_obj
+*
+*                           FnctName(p_obj);
+*********************************************************************************************************
+*/
+
+typedef            void        CPU_VOID;
+typedef            char        CPU_CHAR;                        /*  8-bit character                                     */
+typedef  unsigned  char        CPU_BOOLEAN;                     /*  8-bit boolean or logical                            */
+typedef  unsigned  char        CPU_INT08U;                      /*  8-bit unsigned integer                              */
+typedef    signed  char        CPU_INT08S;                      /*  8-bit   signed integer                              */
+typedef  unsigned  short       CPU_INT16U;                      /* 16-bit unsigned integer                              */
+typedef    signed  short       CPU_INT16S;                      /* 16-bit   signed integer                              */
+typedef  unsigned  int         CPU_INT32U;                      /* 32-bit unsigned integer                              */
+typedef    signed  int         CPU_INT32S;                      /* 32-bit   signed integer                              */
+typedef  unsigned  long  long  CPU_INT64U;                      /* 64-bit unsigned integer                              */
+typedef    signed  long  long  CPU_INT64S;                      /* 64-bit   signed integer                              */
+
+typedef            float       CPU_FP32;                        /* 32-bit floating point                                */
+typedef            double      CPU_FP64;                        /* 64-bit floating point                                */
+
+
+typedef  volatile  CPU_INT08U  CPU_REG08;                       /*  8-bit register                                      */
+typedef  volatile  CPU_INT16U  CPU_REG16;                       /* 16-bit register                                      */
+typedef  volatile  CPU_INT32U  CPU_REG32;                       /* 32-bit register                                      */
+typedef  volatile  CPU_INT64U  CPU_REG64;                       /* 64-bit register                                      */
+
+
+typedef            void      (*CPU_FNCT_VOID)(void);            /* See Note #2a.                                        */
+typedef            void      (*CPU_FNCT_PTR )(void *p_obj);     /* See Note #2b.                                        */
+
+
+/*
+*********************************************************************************************************
+*                                       CPU WORD CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_ADDR_SIZE, CPU_CFG_DATA_SIZE, & CPU_CFG_DATA_SIZE_MAX with CPU's &/or 
+*               compiler's word sizes :
+*
+*                   CPU_WORD_SIZE_08             8-bit word size
+*                   CPU_WORD_SIZE_16            16-bit word size
+*                   CPU_WORD_SIZE_32            32-bit word size
+*                   CPU_WORD_SIZE_64            64-bit word size
+*
+*           (2) Configure CPU_CFG_ENDIAN_TYPE with CPU's data-word-memory order :
+*
+*               (a) CPU_ENDIAN_TYPE_BIG         Big-   endian word order (CPU words' most  significant
+*                                                                         octet @ lowest memory address)
+*               (b) CPU_ENDIAN_TYPE_LITTLE      Little-endian word order (CPU words' least significant
+*                                                                         octet @ lowest memory address)
+*********************************************************************************************************
+*/
+
+                                                                /* Define  CPU         word sizes (see Note #1) :       */
+#define  CPU_CFG_ADDR_SIZE              CPU_WORD_SIZE_32        /* Defines CPU address word size  (in octets).          */
+#define  CPU_CFG_DATA_SIZE              CPU_WORD_SIZE_32        /* Defines CPU data    word size  (in octets).          */
+#define  CPU_CFG_DATA_SIZE_MAX          CPU_WORD_SIZE_64        /* Defines CPU maximum word size  (in octets).          */
+
+#define  CPU_CFG_ENDIAN_TYPE            CPU_ENDIAN_TYPE_LITTLE  /* Defines CPU data    word-memory order (see Note #2). */
+
+
+/*
+*********************************************************************************************************
+*                                 CONFIGURE CPU ADDRESS & DATA TYPES
+*********************************************************************************************************
+*/
+
+                                                                /* CPU address type based on address bus size.          */
+#if     (CPU_CFG_ADDR_SIZE == CPU_WORD_SIZE_32)
+typedef  CPU_INT32U  CPU_ADDR;
+#elif   (CPU_CFG_ADDR_SIZE == CPU_WORD_SIZE_16)
+typedef  CPU_INT16U  CPU_ADDR;
+#else
+typedef  CPU_INT08U  CPU_ADDR;
+#endif
+
+                                                                /* CPU data    type based on data    bus size.          */
+#if     (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_32)
+typedef  CPU_INT32U  CPU_DATA;
+#elif   (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_16)
+typedef  CPU_INT16U  CPU_DATA;
+#else
+typedef  CPU_INT08U  CPU_DATA;
+#endif
+
+
+typedef  CPU_DATA    CPU_ALIGN;                                 /* Defines CPU data-word-alignment size.                */
+typedef  CPU_ADDR    CPU_SIZE_T;                                /* Defines CPU standard 'size_t'   size.                */
+
+
+/*
+*********************************************************************************************************
+*                                       CPU STACK CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_STK_GROWTH in 'cpu.h' with CPU's stack growth order :
+*
+*               (a) CPU_STK_GROWTH_LO_TO_HI     CPU stack pointer increments to the next higher  stack
+*                                                   memory address after data is pushed onto the stack
+*               (b) CPU_STK_GROWTH_HI_TO_LO     CPU stack pointer decrements to the next lower   stack
+*                                                   memory address after data is pushed onto the stack
+*
+*           (2) Configure CPU_CFG_STK_ALIGN_BYTES with the highest minimum alignement required for
+*               cpu stacks.
+*
+*               (a) ARM Procedure Calls Standard requires an 8 bytes stack alignment.
+*********************************************************************************************************
+*/
+
+#define  CPU_CFG_STK_GROWTH       CPU_STK_GROWTH_HI_TO_LO       /* Defines CPU stack growth order (see Note #1).        */
+
+#define  CPU_CFG_STK_ALIGN_BYTES  (8u)                          /* Defines CPU stack alignment in bytes. (see Note #2). */
+
+typedef  CPU_INT32U               CPU_STK;                      /* Defines CPU stack data type.                         */
+typedef  CPU_ADDR                 CPU_STK_SIZE;                 /* Defines CPU stack size data type.                    */
+
+
+/*
+*********************************************************************************************************
+*                                   CRITICAL SECTION CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_CRITICAL_METHOD with CPU's/compiler's critical section method :
+*
+*                                                       Enter/Exit critical sections by ...
+*
+*                   CPU_CRITICAL_METHOD_INT_DIS_EN      Disable/Enable interrupts
+*                   CPU_CRITICAL_METHOD_STATUS_STK      Push/Pop       interrupt status onto stack
+*                   CPU_CRITICAL_METHOD_STATUS_LOCAL    Save/Restore   interrupt status to local variable
+*
+*               (a) CPU_CRITICAL_METHOD_INT_DIS_EN  is NOT a preferred method since it does NOT support
+*                   multiple levels of interrupts.  However, with some CPUs/compilers, this is the only
+*                   available method.
+*
+*               (b) CPU_CRITICAL_METHOD_STATUS_STK    is one preferred method since it supports multiple
+*                   levels of interrupts.  However, this method assumes that the compiler provides C-level
+*                   &/or assembly-level functionality for the following :
+*
+*                     ENTER CRITICAL SECTION :
+*                       (1) Push/save   interrupt status onto a local stack
+*                       (2) Disable     interrupts
+*
+*                     EXIT  CRITICAL SECTION :
+*                       (3) Pop/restore interrupt status from a local stack
+*
+*               (c) CPU_CRITICAL_METHOD_STATUS_LOCAL  is one preferred method since it supports multiple
+*                   levels of interrupts.  However, this method assumes that the compiler provides C-level
+*                   &/or assembly-level functionality for the following :
+*
+*                     ENTER CRITICAL SECTION :
+*                       (1) Save    interrupt status into a local variable
+*                       (2) Disable interrupts
+*
+*                     EXIT  CRITICAL SECTION :
+*                       (3) Restore interrupt status from a local variable
+*
+*           (2) Critical section macro's most likely require inline assembly.  If the compiler does NOT
+*               allow inline assembly in C source files, critical section macro's MUST call an assembly
+*               subroutine defined in a 'cpu_a.asm' file located in the following software directory :
+*
+*                   \<CPU-Compiler Directory>\<cpu>\<compiler>\
+*
+*                       where
+*                               <CPU-Compiler Directory>    directory path for common   CPU-compiler software
+*                               <cpu>                       directory name for specific CPU
+*                               <compiler>                  directory name for specific compiler
+*
+*           (3) (a) To save/restore interrupt status, a local variable 'cpu_sr' of type 'CPU_SR' MAY need
+*                   to be declared (e.g. if 'CPU_CRITICAL_METHOD_STATUS_LOCAL' method is configured).
+*
+*                   (1) 'cpu_sr' local variable SHOULD be declared via the CPU_SR_ALLOC() macro which, if 
+*                        used, MUST be declared following ALL other local variables.
+*
+*                        Example :
+*
+*                           void  Fnct (void)
+*                           {
+*                               CPU_INT08U  val_08;
+*                               CPU_INT16U  val_16;
+*                               CPU_INT32U  val_32;
+*                               CPU_SR_ALLOC();         MUST be declared after ALL other local variables
+*                                   :
+*                                   :
+*                           }
+*
+*               (b) Configure 'CPU_SR' data type with the appropriate-sized CPU data type large enough to
+*                   completely store the CPU's/compiler's status word.
+*********************************************************************************************************
+*/
+                                                                /* Configure CPU critical method      (see Note #1) :   */
+#define  CPU_CFG_CRITICAL_METHOD    CPU_CRITICAL_METHOD_STATUS_LOCAL
+
+typedef  CPU_INT32U                 CPU_SR;                     /* Defines   CPU status register size (see Note #3b).   */
+
+                                                                /* Allocates CPU status register word (see Note #3a).   */
+#if     (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
+#define  CPU_SR_ALLOC()             CPU_SR  cpu_sr = (CPU_SR)0
+#else
+#define  CPU_SR_ALLOC()
+#endif
+
+
+
+#define  CPU_INT_DIS()         do { cpu_sr = CPU_SR_Save(); } while (0) /* Save    CPU status word & disable interrupts.*/
+#define  CPU_INT_EN()          do { CPU_SR_Restore(cpu_sr); } while (0) /* Restore CPU status word.                     */
+
+
+#ifdef   CPU_CFG_INT_DIS_MEAS_EN
+                                                                        /* Disable interrupts, ...                      */
+                                                                        /* & start interrupts disabled time measurement.*/
+#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS();         \
+                                    CPU_IntDisMeasStart(); }  while (0)
+                                                                        /* Stop & measure   interrupts disabled time,   */
+                                                                        /* ...  & re-enable interrupts.                 */
+#define  CPU_CRITICAL_EXIT()   do { CPU_IntDisMeasStop();  \
+                                    CPU_INT_EN();          }  while (0)
+
+#else
+
+#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS(); } while (0)          /* Disable   interrupts.                        */
+#define  CPU_CRITICAL_EXIT()   do { CPU_INT_EN();  } while (0)          /* Re-enable interrupts.                        */
+
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                    MEMORY BARRIERS CONFIGURATION
+*
+* Note(s) : (1) (a) Configure memory barriers if required by the architecture.
+*
+*                   CPU_MB      Full memory barrier.
+*                   CPU_RMB     Read (Loads) memory barrier.
+*                   CPU_WMB     Write (Stores) memory barrier.
+*
+*********************************************************************************************************
+*/
+
+#define  CPU_MB()       __dsb(0xF)
+#define  CPU_RMB()      __dsb(0xF)
+#define  CPU_WMB()      __dsb(0xF)
+
+
+/*
+*********************************************************************************************************
+*                                    CPU COUNT ZEROS CONFIGURATION
+*
+* Note(s) : (1) (a) Configure CPU_CFG_LEAD_ZEROS_ASM_PRESENT  to define count leading  zeros bits 
+*                   function(s) in :
+*
+*                   (1) 'cpu_a.asm',  if CPU_CFG_LEAD_ZEROS_ASM_PRESENT       #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable assembly-optimized function(s)
+*
+*                   (2) 'cpu_core.c', if CPU_CFG_LEAD_ZEROS_ASM_PRESENT   NOT #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable C-source-optimized function(s) otherwise
+*
+*               (b) Configure CPU_CFG_TRAIL_ZEROS_ASM_PRESENT to define count trailing zeros bits 
+*                   function(s) in :
+*
+*                   (1) 'cpu_a.asm',  if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT      #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable assembly-optimized function(s)
+*
+*                   (2) 'cpu_core.c', if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT  NOT #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable C-source-optimized function(s) otherwise
+*********************************************************************************************************
+*/
+
+                                                                /* Configure CPU count leading  zeros bits ...          */
+#define  CPU_CFG_LEAD_ZEROS_ASM_PRESENT                         /* ... assembly-version (see Note #1a).                 */
+
+                                                                /* Configure CPU count trailing zeros bits ...          */
+#define  CPU_CFG_TRAIL_ZEROS_ASM_PRESENT                        /* ... assembly-version (see Note #1b).                 */
+
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+void        CPU_IntDis       (void);
+void        CPU_IntEn        (void);
+
+void        CPU_IntSrcDis    (CPU_INT08U  pos);
+void        CPU_IntSrcEn     (CPU_INT08U  pos);
+void        CPU_IntSrcPendClr(CPU_INT08U  pos);
+CPU_INT16S  CPU_IntSrcPrioGet(CPU_INT08U  pos);
+void        CPU_IntSrcPrioSet(CPU_INT08U  pos,
+                              CPU_INT08U  prio);
+
+
+CPU_SR      CPU_SR_Save      (void);
+void        CPU_SR_Restore   (CPU_SR      cpu_sr);
+
+
+void        CPU_WaitForInt   (void);
+void        CPU_WaitForExcept(void);
+
+
+CPU_DATA    CPU_RevBits      (CPU_DATA    val);
+
+void        CPU_BitBandClr   (CPU_ADDR    addr,
+                              CPU_INT08U  bit_nbr);
+void        CPU_BitBandSet   (CPU_ADDR    addr,
+                              CPU_INT08U  bit_nbr);
+
+
+/*
+*********************************************************************************************************
+*                                          INTERRUPT SOURCES
+*********************************************************************************************************
+*/
+
+#define  CPU_INT_STK_PTR                                   0u
+#define  CPU_INT_RESET                                     1u
+#define  CPU_INT_NMI                                       2u
+#define  CPU_INT_HFAULT                                    3u
+#define  CPU_INT_MEM                                       4u
+#define  CPU_INT_BUSFAULT                                  5u
+#define  CPU_INT_USAGEFAULT                                6u
+#define  CPU_INT_RSVD_07                                   7u
+#define  CPU_INT_RSVD_08                                   8u
+#define  CPU_INT_RSVD_09                                   9u
+#define  CPU_INT_RSVD_10                                  10u
+#define  CPU_INT_SVCALL                                   11u
+#define  CPU_INT_DBGMON                                   12u
+#define  CPU_INT_RSVD_13                                  13u
+#define  CPU_INT_PENDSV                                   14u
+#define  CPU_INT_SYSTICK                                  15u
+#define  CPU_INT_EXT0                                     16u
+
+/*
+*********************************************************************************************************
+*                                            CPU REGISTERS
+*********************************************************************************************************
+*/
+
+#define  CPU_REG_NVIC_NVIC           (*((CPU_REG32 *)(0xE000E004)))             /* Int Ctrl'er Type Reg.                */
+#define  CPU_REG_NVIC_ST_CTRL        (*((CPU_REG32 *)(0xE000E010)))             /* SysTick Ctrl & Status Reg.           */
+#define  CPU_REG_NVIC_ST_RELOAD      (*((CPU_REG32 *)(0xE000E014)))             /* SysTick Reload      Value Reg.       */
+#define  CPU_REG_NVIC_ST_CURRENT     (*((CPU_REG32 *)(0xE000E018)))             /* SysTick Current     Value Reg.       */
+#define  CPU_REG_NVIC_ST_CAL         (*((CPU_REG32 *)(0xE000E01C)))             /* SysTick Calibration Value Reg.       */
+
+#define  CPU_REG_NVIC_SETEN(n)       (*((CPU_REG32 *)(0xE000E100 + (n) * 4u)))  /* IRQ Set En Reg.                      */
+#define  CPU_REG_NVIC_CLREN(n)       (*((CPU_REG32 *)(0xE000E180 + (n) * 4u)))  /* IRQ Clr En Reg.                      */
+#define  CPU_REG_NVIC_SETPEND(n)     (*((CPU_REG32 *)(0xE000E200 + (n) * 4u)))  /* IRQ Set Pending Reg.                 */
+#define  CPU_REG_NVIC_CLRPEND(n)     (*((CPU_REG32 *)(0xE000E280 + (n) * 4u)))  /* IRQ Clr Pending Reg.                 */
+#define  CPU_REG_NVIC_ACTIVE(n)      (*((CPU_REG32 *)(0xE000E300 + (n) * 4u)))  /* IRQ Active Reg.                      */
+#define  CPU_REG_NVIC_PRIO(n)        (*((CPU_REG32 *)(0xE000E400 + (n) * 4u)))  /* IRQ Prio Reg.                        */
+
+#define  CPU_REG_NVIC_CPUID          (*((CPU_REG32 *)(0xE000ED00)))             /* CPUID Base Reg.                      */
+#define  CPU_REG_NVIC_ICSR           (*((CPU_REG32 *)(0xE000ED04)))             /* Int Ctrl State  Reg.                 */
+#define  CPU_REG_NVIC_VTOR           (*((CPU_REG32 *)(0xE000ED08)))             /* Vect Tbl Offset Reg.                 */
+#define  CPU_REG_NVIC_AIRCR          (*((CPU_REG32 *)(0xE000ED0C)))             /* App Int/Reset Ctrl Reg.              */
+#define  CPU_REG_NVIC_SCR            (*((CPU_REG32 *)(0xE000ED10)))             /* System Ctrl Reg.                     */
+#define  CPU_REG_NVIC_CCR            (*((CPU_REG32 *)(0xE000ED14)))             /* Cfg    Ctrl Reg.                     */
+#define  CPU_REG_NVIC_SHPRI1         (*((CPU_REG32 *)(0xE000ED18)))             /* System Handlers  4 to  7 Prio.       */
+#define  CPU_REG_NVIC_SHPRI2         (*((CPU_REG32 *)(0xE000ED1C)))             /* System Handlers  8 to 11 Prio.       */
+#define  CPU_REG_NVIC_SHPRI3         (*((CPU_REG32 *)(0xE000ED20)))             /* System Handlers 12 to 15 Prio.       */
+#define  CPU_REG_NVIC_SHCSR          (*((CPU_REG32 *)(0xE000ED24)))             /* System Handler Ctrl & State Reg.     */
+#define  CPU_REG_NVIC_CFSR           (*((CPU_REG32 *)(0xE000ED28)))             /* Configurable Fault Status Reg.       */
+#define  CPU_REG_NVIC_HFSR           (*((CPU_REG32 *)(0xE000ED2C)))             /* Hard  Fault Status Reg.              */
+#define  CPU_REG_NVIC_DFSR           (*((CPU_REG32 *)(0xE000ED30)))             /* Debug Fault Status Reg.              */
+#define  CPU_REG_NVIC_MMFAR          (*((CPU_REG32 *)(0xE000ED34)))             /* Mem Manage Addr Reg.                 */
+#define  CPU_REG_NVIC_BFAR           (*((CPU_REG32 *)(0xE000ED38)))             /* Bus Fault  Addr Reg.                 */
+#define  CPU_REG_NVIC_AFSR           (*((CPU_REG32 *)(0xE000ED3C)))             /* Aux Fault Status Reg.                */
+
+#define  CPU_REG_NVIC_PFR0           (*((CPU_REG32 *)(0xE000ED40)))             /* Processor Feature Reg 0.             */
+#define  CPU_REG_NVIC_PFR1           (*((CPU_REG32 *)(0xE000ED44)))             /* Processor Feature Reg 1.             */
+#define  CPU_REG_NVIC_DFR0           (*((CPU_REG32 *)(0xE000ED48)))             /* Debug     Feature Reg 0.             */
+#define  CPU_REG_NVIC_AFR0           (*((CPU_REG32 *)(0xE000ED4C)))             /* Aux       Feature Reg 0.             */
+#define  CPU_REG_NVIC_MMFR0          (*((CPU_REG32 *)(0xE000ED50)))             /* Memory Model Feature Reg 0.          */
+#define  CPU_REG_NVIC_MMFR1          (*((CPU_REG32 *)(0xE000ED54)))             /* Memory Model Feature Reg 1.          */
+#define  CPU_REG_NVIC_MMFR2          (*((CPU_REG32 *)(0xE000ED58)))             /* Memory Model Feature Reg 2.          */
+#define  CPU_REG_NVIC_MMFR3          (*((CPU_REG32 *)(0xE000ED5C)))             /* Memory Model Feature Reg 3.          */
+#define  CPU_REG_NVIC_ISAFR0         (*((CPU_REG32 *)(0xE000ED60)))             /* ISA Feature Reg 0.                   */
+#define  CPU_REG_NVIC_ISAFR1         (*((CPU_REG32 *)(0xE000ED64)))             /* ISA Feature Reg 1.                   */
+#define  CPU_REG_NVIC_ISAFR2         (*((CPU_REG32 *)(0xE000ED68)))             /* ISA Feature Reg 2.                   */
+#define  CPU_REG_NVIC_ISAFR3         (*((CPU_REG32 *)(0xE000ED6C)))             /* ISA Feature Reg 3.                   */
+#define  CPU_REG_NVIC_ISAFR4         (*((CPU_REG32 *)(0xE000ED70)))             /* ISA Feature Reg 4.                   */
+#define  CPU_REG_NVIC_SW_TRIG        (*((CPU_REG32 *)(0xE000EF00)))             /* Software Trigger Int Reg.            */
+
+#define  CPU_REG_MPU_TYPE            (*((CPU_REG32 *)(0xE000ED90)))             /* MPU Type Reg.                        */
+#define  CPU_REG_MPU_CTRL            (*((CPU_REG32 *)(0xE000ED94)))             /* MPU Ctrl Reg.                        */
+#define  CPU_REG_MPU_REG_NBR         (*((CPU_REG32 *)(0xE000ED98)))             /* MPU Region Nbr Reg.                  */
+#define  CPU_REG_MPU_REG_BASE        (*((CPU_REG32 *)(0xE000ED9C)))             /* MPU Region Base Addr Reg.            */
+#define  CPU_REG_MPU_REG_ATTR        (*((CPU_REG32 *)(0xE000EDA0)))             /* MPU Region Attrib & Size Reg.        */
+
+#define  CPU_REG_DBG_CTRL            (*((CPU_REG32 *)(0xE000EDF0)))             /* Debug Halting Ctrl & Status Reg.     */
+#define  CPU_REG_DBG_SELECT          (*((CPU_REG32 *)(0xE000EDF4)))             /* Debug Core Reg Selector Reg.         */
+#define  CPU_REG_DBG_DATA            (*((CPU_REG32 *)(0xE000EDF8)))             /* Debug Core Reg Data     Reg.         */
+#define  CPU_REG_DBG_INT             (*((CPU_REG32 *)(0xE000EDFC)))             /* Debug Except & Monitor Ctrl Reg.     */
+
+
+/*
+*********************************************************************************************************
+*                                          CPU REGISTER BITS
+*********************************************************************************************************
+*/
+
+                                                                /* ---------- SYSTICK CTRL & STATUS REG BITS ---------- */
+#define  CPU_REG_NVIC_ST_CTRL_COUNTFLAG           0x00010000
+#define  CPU_REG_NVIC_ST_CTRL_CLKSOURCE           0x00000004
+#define  CPU_REG_NVIC_ST_CTRL_TICKINT             0x00000002
+#define  CPU_REG_NVIC_ST_CTRL_ENABLE              0x00000001
+
+
+                                                                /* -------- SYSTICK CALIBRATION VALUE REG BITS -------- */
+#define  CPU_REG_NVIC_ST_CAL_NOREF                0x80000000
+#define  CPU_REG_NVIC_ST_CAL_SKEW                 0x40000000
+
+                                                                /* -------------- INT CTRL STATE REG BITS ------------- */
+#define  CPU_REG_NVIC_ICSR_NMIPENDSET             0x80000000
+#define  CPU_REG_NVIC_ICSR_PENDSVSET              0x10000000
+#define  CPU_REG_NVIC_ICSR_PENDSVCLR              0x08000000
+#define  CPU_REG_NVIC_ICSR_PENDSTSET              0x04000000
+#define  CPU_REG_NVIC_ICSR_PENDSTCLR              0x02000000
+#define  CPU_REG_NVIC_ICSR_ISRPREEMPT             0x00800000
+#define  CPU_REG_NVIC_ICSR_ISRPENDING             0x00400000
+#define  CPU_REG_NVIC_ICSR_RETTOBASE              0x00000800
+
+                                                                /* ------------- VECT TBL OFFSET REG BITS ------------- */
+#define  CPU_REG_NVIC_VTOR_TBLBASE                0x20000000
+
+                                                                /* ------------ APP INT/RESET CTRL REG BITS ----------- */
+#define  CPU_REG_NVIC_AIRCR_ENDIANNESS            0x00008000
+#define  CPU_REG_NVIC_AIRCR_SYSRESETREQ           0x00000004
+#define  CPU_REG_NVIC_AIRCR_VECTCLRACTIVE         0x00000002
+#define  CPU_REG_NVIC_AIRCR_VECTRESET             0x00000001
+
+                                                                /* --------------- SYSTEM CTRL REG BITS --------------- */
+#define  CPU_REG_NVIC_SCR_SEVONPEND               0x00000010
+#define  CPU_REG_NVIC_SCR_SLEEPDEEP               0x00000004
+#define  CPU_REG_NVIC_SCR_SLEEPONEXIT             0x00000002
+
+                                                                /* ----------------- CFG CTRL REG BITS ---------------- */
+#define  CPU_REG_NVIC_CCR_STKALIGN                0x00000200
+#define  CPU_REG_NVIC_CCR_BFHFNMIGN               0x00000100
+#define  CPU_REG_NVIC_CCR_DIV_0_TRP               0x00000010
+#define  CPU_REG_NVIC_CCR_UNALIGN_TRP             0x00000008
+#define  CPU_REG_NVIC_CCR_USERSETMPEND            0x00000002
+#define  CPU_REG_NVIC_CCR_NONBASETHRDENA          0x00000001
+
+                                                                /* ------- SYSTEM HANDLER CTRL & STATE REG BITS ------- */
+#define  CPU_REG_NVIC_SHCSR_USGFAULTENA           0x00040000
+#define  CPU_REG_NVIC_SHCSR_BUSFAULTENA           0x00020000
+#define  CPU_REG_NVIC_SHCSR_MEMFAULTENA           0x00010000
+#define  CPU_REG_NVIC_SHCSR_SVCALLPENDED          0x00008000
+#define  CPU_REG_NVIC_SHCSR_BUSFAULTPENDED        0x00004000
+#define  CPU_REG_NVIC_SHCSR_MEMFAULTPENDED        0x00002000
+#define  CPU_REG_NVIC_SHCSR_USGFAULTPENDED        0x00001000
+#define  CPU_REG_NVIC_SHCSR_SYSTICKACT            0x00000800
+#define  CPU_REG_NVIC_SHCSR_PENDSVACT             0x00000400
+#define  CPU_REG_NVIC_SHCSR_MONITORACT            0x00000100
+#define  CPU_REG_NVIC_SHCSR_SVCALLACT             0x00000080
+#define  CPU_REG_NVIC_SHCSR_USGFAULTACT           0x00000008
+#define  CPU_REG_NVIC_SHCSR_BUSFAULTACT           0x00000002
+#define  CPU_REG_NVIC_SHCSR_MEMFAULTACT           0x00000001
+
+                                                                /* -------- CONFIGURABLE FAULT STATUS REG BITS -------- */
+#define  CPU_REG_NVIC_CFSR_DIVBYZERO              0x02000000
+#define  CPU_REG_NVIC_CFSR_UNALIGNED              0x01000000
+#define  CPU_REG_NVIC_CFSR_NOCP                   0x00080000
+#define  CPU_REG_NVIC_CFSR_INVPC                  0x00040000
+#define  CPU_REG_NVIC_CFSR_INVSTATE               0x00020000
+#define  CPU_REG_NVIC_CFSR_UNDEFINSTR             0x00010000
+#define  CPU_REG_NVIC_CFSR_BFARVALID              0x00008000
+#define  CPU_REG_NVIC_CFSR_STKERR                 0x00001000
+#define  CPU_REG_NVIC_CFSR_UNSTKERR               0x00000800
+#define  CPU_REG_NVIC_CFSR_IMPRECISERR            0x00000400
+#define  CPU_REG_NVIC_CFSR_PRECISERR              0x00000200
+#define  CPU_REG_NVIC_CFSR_IBUSERR                0x00000100
+#define  CPU_REG_NVIC_CFSR_MMARVALID              0x00000080
+#define  CPU_REG_NVIC_CFSR_MSTKERR                0x00000010
+#define  CPU_REG_NVIC_CFSR_MUNSTKERR              0x00000008
+#define  CPU_REG_NVIC_CFSR_DACCVIOL               0x00000002
+#define  CPU_REG_NVIC_CFSR_IACCVIOL               0x00000001
+
+                                                                /* ------------ HARD FAULT STATUS REG BITS ------------ */
+#define  CPU_REG_NVIC_HFSR_DEBUGEVT               0x80000000
+#define  CPU_REG_NVIC_HFSR_FORCED                 0x40000000
+#define  CPU_REG_NVIC_HFSR_VECTTBL                0x00000002
+
+                                                                /* ------------ DEBUG FAULT STATUS REG BITS ----------- */
+#define  CPU_REG_NVIC_DFSR_EXTERNAL               0x00000010
+#define  CPU_REG_NVIC_DFSR_VCATCH                 0x00000008
+#define  CPU_REG_NVIC_DFSR_DWTTRAP                0x00000004
+#define  CPU_REG_NVIC_DFSR_BKPT                   0x00000002
+#define  CPU_REG_NVIC_DFSR_HALTED                 0x00000001
+
+
+/*
+*********************************************************************************************************
+*                                          CPU REGISTER MASK
+*********************************************************************************************************
+*/
+
+#define  CPU_MSK_NVIC_ICSR_VECT_ACTIVE            0x000001FF
+
+
+/*
+*********************************************************************************************************
+*                                        CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_CFG_ADDR_SIZE
+#error  "CPU_CFG_ADDR_SIZE              not #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+
+#elif  ((CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_08) && \
+        (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_16) && \
+        (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_32) && \
+        (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_64))
+#error  "CPU_CFG_ADDR_SIZE        illegally #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+#endif
+
+
+#ifndef  CPU_CFG_DATA_SIZE
+#error  "CPU_CFG_DATA_SIZE              not #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+
+#elif  ((CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_08) && \
+        (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_16) && \
+        (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_32) && \
+        (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_64))
+#error  "CPU_CFG_DATA_SIZE        illegally #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+#endif
+
+
+#ifndef  CPU_CFG_DATA_SIZE_MAX
+#error  "CPU_CFG_DATA_SIZE_MAX          not #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+
+#elif  ((CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_08) && \
+        (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_16) && \
+        (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_32) && \
+        (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_64))
+#error  "CPU_CFG_DATA_SIZE_MAX    illegally #define'd in 'cpu.h'               "
+#error  "                         [MUST be  CPU_WORD_SIZE_08   8-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_16  16-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_32  32-bit alignment]"
+#error  "                         [     ||  CPU_WORD_SIZE_64  64-bit alignment]"
+#endif
+
+
+
+#if     (CPU_CFG_DATA_SIZE_MAX < CPU_CFG_DATA_SIZE)
+#error  "CPU_CFG_DATA_SIZE_MAX    illegally #define'd in 'cpu.h' "
+#error  "                         [MUST be  >= CPU_CFG_DATA_SIZE]"
+#endif
+
+
+
+
+#ifndef  CPU_CFG_ENDIAN_TYPE
+#error  "CPU_CFG_ENDIAN_TYPE            not #define'd in 'cpu.h'   "
+#error  "                         [MUST be  CPU_ENDIAN_TYPE_BIG   ]"
+#error  "                         [     ||  CPU_ENDIAN_TYPE_LITTLE]"
+
+#elif  ((CPU_CFG_ENDIAN_TYPE != CPU_ENDIAN_TYPE_BIG   ) && \
+        (CPU_CFG_ENDIAN_TYPE != CPU_ENDIAN_TYPE_LITTLE))
+#error  "CPU_CFG_ENDIAN_TYPE      illegally #define'd in 'cpu.h'   "
+#error  "                         [MUST be  CPU_ENDIAN_TYPE_BIG   ]"
+#error  "                         [     ||  CPU_ENDIAN_TYPE_LITTLE]"
+#endif
+
+
+
+
+#ifndef  CPU_CFG_STK_GROWTH
+#error  "CPU_CFG_STK_GROWTH             not #define'd in 'cpu.h'    "
+#error  "                         [MUST be  CPU_STK_GROWTH_LO_TO_HI]"
+#error  "                         [     ||  CPU_STK_GROWTH_HI_TO_LO]"
+
+#elif  ((CPU_CFG_STK_GROWTH != CPU_STK_GROWTH_LO_TO_HI) && \
+        (CPU_CFG_STK_GROWTH != CPU_STK_GROWTH_HI_TO_LO))
+#error  "CPU_CFG_STK_GROWTH       illegally #define'd in 'cpu.h'    "
+#error  "                         [MUST be  CPU_STK_GROWTH_LO_TO_HI]"
+#error  "                         [     ||  CPU_STK_GROWTH_HI_TO_LO]"
+#endif
+
+
+
+
+#ifndef  CPU_CFG_CRITICAL_METHOD
+#error  "CPU_CFG_CRITICAL_METHOD        not #define'd in 'cpu.h'             "
+#error  "                         [MUST be  CPU_CRITICAL_METHOD_INT_DIS_EN  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_STK  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_LOCAL]"
+
+#elif  ((CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_INT_DIS_EN  ) && \
+        (CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_STATUS_STK  ) && \
+        (CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_STATUS_LOCAL))
+#error  "CPU_CFG_CRITICAL_METHOD  illegally #define'd in 'cpu.h'             "
+#error  "                         [MUST be  CPU_CRITICAL_METHOD_INT_DIS_EN  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_STK  ]"
+#error  "                         [     ||  CPU_CRITICAL_METHOD_STATUS_LOCAL]"
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*
+* Note(s) : (1) See 'cpu.h  MODULE'.
+*********************************************************************************************************
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif                                                          /* End of CPU module include.                           */
+

+ 286 - 0
MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/RealView/cpu_a.asm

@@ -0,0 +1,286 @@
+;********************************************************************************************************
+;                                                uC/CPU
+;                                    CPU CONFIGURATION & PORT LAYER
+;
+;                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+;
+;               All rights reserved.  Protected by international copyright laws.
+;
+;               uC/CPU is provided in source form to registered licensees ONLY.  It is 
+;               illegal to distribute this source code to any third party unless you receive 
+;               written permission by an authorized Micrium representative.  Knowledge of 
+;               the source code may NOT be used to develop a similar product.
+;
+;               Please help us continue to provide the Embedded community with the finest 
+;               software available.  Your honesty is greatly appreciated.
+;
+;               You can find our product's user manual, API reference, release notes and
+;               more information at https://doc.micrium.com.
+;               You can contact us at www.micrium.com.
+;********************************************************************************************************
+
+;********************************************************************************************************
+;
+;                                            CPU PORT FILE
+;
+;                                            ARM-Cortex-M4
+;                                      RealView Development Suite
+;                            RealView Microcontroller Development Kit (MDK)
+;                                       ARM Developer Suite (ADS)
+;                                            Keil uVision
+;
+; Filename      : cpu_a.asm
+; Version       : V1.30.02.00
+; Programmer(s) : JJL
+;********************************************************************************************************
+
+
+;********************************************************************************************************
+;                                           PUBLIC FUNCTIONS
+;********************************************************************************************************
+
+        EXPORT  CPU_IntDis
+        EXPORT  CPU_IntEn
+
+        EXPORT  CPU_SR_Save
+        EXPORT  CPU_SR_Restore
+
+        EXPORT  CPU_WaitForInt
+        EXPORT  CPU_WaitForExcept
+
+
+        EXPORT  CPU_CntLeadZeros
+        EXPORT  CPU_CntTrailZeros
+        EXPORT  CPU_RevBits
+
+
+;********************************************************************************************************
+;                                      CODE GENERATION DIRECTIVES
+;********************************************************************************************************
+
+        AREA |.text|, CODE, READONLY, ALIGN=2
+        THUMB
+        REQUIRE8
+        PRESERVE8
+
+;********************************************************************************************************
+;                                    DISABLE and ENABLE INTERRUPTS
+;
+; Description: Disable/Enable interrupts.
+;
+; Prototypes : void  CPU_IntDis(void);
+;              void  CPU_IntEn (void);
+;********************************************************************************************************
+
+CPU_IntDis
+        CPSID   I
+        BX      LR
+
+
+CPU_IntEn
+        CPSIE   I
+        BX      LR
+
+
+;********************************************************************************************************
+;                                      CRITICAL SECTION FUNCTIONS
+;
+; Description : Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking, the
+;               state of the interrupt disable flag is stored in the local variable 'cpu_sr' & interrupts
+;               are then disabled ('cpu_sr' is allocated in all functions that need to disable interrupts).
+;               The previous interrupt state is restored by copying 'cpu_sr' into the CPU's status register.
+;
+; Prototypes  : CPU_SR  CPU_SR_Save   (void);
+;               void    CPU_SR_Restore(CPU_SR  cpu_sr);
+;
+; Note(s)     : (1) These functions are used in general like this :
+;
+;                       void  Task (void  *p_arg)
+;                       {
+;                           CPU_SR_ALLOC();                     /* Allocate storage for CPU status register */
+;                               :
+;                               :
+;                           CPU_CRITICAL_ENTER();               /* cpu_sr = CPU_SR_Save();                  */
+;                               :
+;                               :
+;                           CPU_CRITICAL_EXIT();                /* CPU_SR_Restore(cpu_sr);                  */
+;                               :
+;                       }
+;********************************************************************************************************
+
+CPU_SR_Save
+        MRS     R0, PRIMASK                     ; Set prio int mask to mask all (except faults)
+        CPSID   I
+        BX      LR
+
+
+CPU_SR_Restore                                  ; See Note #2.
+        MSR     PRIMASK, R0
+        BX      LR
+
+
+;********************************************************************************************************
+;                                         WAIT FOR INTERRUPT
+;
+; Description : Enters sleep state, which will be exited when an interrupt is received.
+;
+; Prototypes  : void  CPU_WaitForInt (void)
+;
+; Argument(s) : none.
+;********************************************************************************************************
+
+CPU_WaitForInt
+        WFI                                     ; Wait for interrupt
+        BX      LR
+
+
+;********************************************************************************************************
+;                                         WAIT FOR EXCEPTION
+;
+; Description : Enters sleep state, which will be exited when an exception is received.
+;
+; Prototypes  : void  CPU_WaitForExcept (void)
+;
+; Argument(s) : none.
+;********************************************************************************************************
+
+CPU_WaitForExcept
+        WFE                                     ; Wait for exception
+        BX      LR
+
+
+;********************************************************************************************************
+;                                         CPU_CntLeadZeros()
+;                                        COUNT LEADING ZEROS
+;
+; Description : Counts the number of contiguous, most-significant, leading zero bits before the 
+;                   first binary one bit in a data value.
+;
+; Prototype   : CPU_DATA  CPU_CntLeadZeros(CPU_DATA  val);
+;
+; Argument(s) : val         Data value to count leading zero bits.
+;
+; Return(s)   : Number of contiguous, most-significant, leading zero bits in 'val'.
+;
+; Caller(s)   : Application.
+;
+;               This function is an INTERNAL CPU module function but MAY be called by application 
+;               function(s).
+;
+; Note(s)     : (1) (a) Supports 32-bit data value size as configured by 'CPU_DATA' (see 'cpu.h  
+;                       CPU WORD CONFIGURATION  Note #1').
+;
+;                   (b) 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
+;
+;
+;               (2) MUST be defined in 'cpu_a.asm' (or 'cpu_c.c') if CPU_CFG_LEAD_ZEROS_ASM_PRESENT is 
+;                   #define'd in 'cpu_cfg.h' or 'cpu.h'.
+;********************************************************************************************************
+
+CPU_CntLeadZeros
+        CLZ     R0, R0                          ; Count leading zeros
+        BX      LR
+
+
+;********************************************************************************************************
+;                                         CPU_CntTrailZeros()
+;                                        COUNT TRAILING ZEROS
+;
+; Description : Counts the number of contiguous, least-significant, trailing zero bits before the 
+;                   first binary one bit in a data value.
+;
+; Prototype   : CPU_DATA  CPU_CntTrailZeros(CPU_DATA  val);
+;
+; Argument(s) : val         Data value to count trailing zero bits.
+;
+; Return(s)   : Number of contiguous, least-significant, trailing zero bits in 'val'.
+;
+; Caller(s)   : Application.
+;
+;               This function is an INTERNAL CPU module function but MAY be called by application 
+;               function(s).
+;
+; Note(s)     : (1) (a) Supports 32-bit data value size as configured by 'CPU_DATA' (see 'cpu.h  
+;                       CPU WORD CONFIGURATION  Note #1').
+;
+;                   (b) 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
+;
+;
+;               (2) MUST be defined in 'cpu_a.asm' (or 'cpu_c.c') if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT is 
+;                   #define'd in 'cpu_cfg.h' or 'cpu.h'.
+;********************************************************************************************************
+
+CPU_CntTrailZeros
+        RBIT    R0, R0                          ; Reverse bits
+        CLZ     R0, R0                          ; Count trailing zeros
+        BX      LR
+
+
+;********************************************************************************************************
+;                                            CPU_RevBits()
+;                                            REVERSE BITS
+;
+; Description : Reverses the bits in a data value.
+;
+; Prototypes  : CPU_DATA  CPU_RevBits(CPU_DATA  val);
+;
+; Argument(s) : val         Data value to reverse bits.
+;
+; Return(s)   : Value with all bits in 'val' reversed (see Note #1).
+;
+; Caller(s)   : Application.
+;
+;               This function is an INTERNAL CPU module function but MAY be called by application function(s).
+;
+; Note(s)     : (1) The final, reversed data value for 'val' is such that :
+;
+;                       'val's final bit  0       =  'val's original bit  N
+;                       'val's final bit  1       =  'val's original bit (N - 1)
+;                       'val's final bit  2       =  'val's original bit (N - 2)
+;
+;                               ...                           ...
+;
+;                       'val's final bit (N - 2)  =  'val's original bit  2
+;                       'val's final bit (N - 1)  =  'val's original bit  1
+;                       'val's final bit  N       =  'val's original bit  0
+;********************************************************************************************************
+
+CPU_RevBits
+        RBIT    R0, R0                          ; Reverse bits
+        BX      LR
+
+
+;********************************************************************************************************
+;                                     CPU ASSEMBLY PORT FILE END
+;********************************************************************************************************
+
+        END
+

+ 751 - 0
MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/RealView/cpu_c.c

@@ -0,0 +1,751 @@
+/*
+*********************************************************************************************************
+*                                                uC/CPU
+*                                    CPU CONFIGURATION & PORT LAYER
+*
+*                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*
+*               uC/CPU is provided in source form to registered licensees ONLY.  It is 
+*               illegal to distribute this source code to any third party unless you receive 
+*               written permission by an authorized Micrium representative.  Knowledge of 
+*               the source code may NOT be used to develop a similar product.
+*
+*               Please help us continue to provide the Embedded community with the finest 
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                            CPU PORT FILE
+*
+*                                            ARM-Cortex-M4
+*                                      RealView Development Suite
+*                            RealView Microcontroller Development Kit (MDK)
+*                                       ARM Developer Suite (ADS)
+*                                            Keil uVision
+*
+* Filename      : cpu_c.c
+* Version       : V1.30.02.00
+* Programmer(s) : JJL
+*                 BAN
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#define   MICRIUM_SOURCE
+#include  <cpu.h>
+#include  <cpu_core.h>
+
+#include  <lib_def.h>
+
+#ifdef __cplusplus
+extern  "C" {
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL DEFINES
+*********************************************************************************************************
+*/
+
+#define  CPU_INT_SRC_POS_MAX                  ((((CPU_REG_NVIC_NVIC + 1) & 0x1F) * 32) + 16)
+
+#define  CPU_BIT_BAND_SRAM_REG_LO                 0x20000000
+#define  CPU_BIT_BAND_SRAM_REG_HI                 0x200FFFFF
+#define  CPU_BIT_BAND_SRAM_BASE                   0x22000000
+
+
+#define  CPU_BIT_BAND_PERIPH_REG_LO               0x40000000
+#define  CPU_BIT_BAND_PERIPH_REG_HI               0x400FFFFF
+#define  CPU_BIT_BAND_PERIPH_BASE                 0x42000000
+
+
+/*
+*********************************************************************************************************
+*                                           LOCAL CONSTANTS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          LOCAL DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL TABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                       LOCAL GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                      LOCAL FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                     LOCAL CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          CPU_BitBandClr()
+*
+* Description : Clear bit in bit-band region.
+*
+* Argument(s) : addr            Byte address in memory space.
+*
+*               bit_nbr         Bit number in byte.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+void  CPU_BitBandClr (CPU_ADDR    addr,
+                      CPU_INT08U  bit_nbr)
+{
+    CPU_ADDR  bit_word_off;
+    CPU_ADDR  bit_word_addr;
+
+
+    if ((addr >= CPU_BIT_BAND_SRAM_REG_LO) &&
+        (addr <= CPU_BIT_BAND_SRAM_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_SRAM_REG_LO  ) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_SRAM_BASE   + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 0;
+
+    } else if ((addr >= CPU_BIT_BAND_PERIPH_REG_LO) &&
+               (addr <= CPU_BIT_BAND_PERIPH_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_PERIPH_REG_LO) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_PERIPH_BASE + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 0;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                          CPU_BitBandSet()
+*
+* Description : Set bit in bit-band region.
+*
+* Argument(s) : addr            Byte address in memory space.
+*
+*               bit_nbr         Bit number in byte.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+void  CPU_BitBandSet (CPU_ADDR    addr,
+                      CPU_INT08U  bit_nbr)
+{
+    CPU_ADDR  bit_word_off;
+    CPU_ADDR  bit_word_addr;
+
+
+    if ((addr >= CPU_BIT_BAND_SRAM_REG_LO) &&
+        (addr <= CPU_BIT_BAND_SRAM_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_SRAM_REG_LO  ) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_SRAM_BASE   + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 1;
+
+    } else if ((addr >= CPU_BIT_BAND_PERIPH_REG_LO) &&
+               (addr <= CPU_BIT_BAND_PERIPH_REG_HI)) {
+        bit_word_off  = ((addr - CPU_BIT_BAND_PERIPH_REG_LO) * 32) + (bit_nbr * 4);
+        bit_word_addr = CPU_BIT_BAND_PERIPH_BASE + bit_word_off;
+
+      *(volatile CPU_INT32U *)(bit_word_addr) = 1;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                           CPU_IntSrcDis()
+*
+* Description : Disable an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table :
+*
+*                           0       Invalid (see Note #1a).
+*                           1       Invalid (see Note #1b).
+*                           2       Non-maskable interrupt.
+*                           3       Hard Fault.
+*                           4       Memory Management.
+*                           5       Bus Fault.
+*                           6       Usage Fault.
+*                           7-10    Reserved.
+*                           11      SVCall
+*                           12      Debug monitor.
+*                           13      Reserved
+*                           14      PendSV.
+*                           15      SysTick.
+*                           16+     External Interrupt.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Several table positions do not contain interrupt sources :
+*
+*                   (a) Position 0 contains the stack pointer.
+*                   (b) Positions 7-10, 13 are reserved.
+*
+*               (2) Several interrupts cannot be disabled/enabled :
+*
+*                   (a) Reset.
+*                   (b) NMI.
+*                   (c) Hard fault.
+*                   (d) SVCall.
+*                   (e) Debug monitor.
+*                   (f) PendSV.
+*
+*               (3) The maximum Cortex-M3 table position is 256.  A particular Cortex-M3 may have fewer
+*                   than 240 external exceptions and, consequently, fewer than 256 table positions.
+*                   This function assumes that the specified table position is valid if the interrupt
+*                   controller type register's INTLINESNUM field is large enough so that the position
+*                   COULD be valid.
+*********************************************************************************************************
+*/
+
+void  CPU_IntSrcDis (CPU_INT08U  pos)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  pos_max;
+    CPU_INT08U  nbr;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+        case CPU_INT_SVCALL:                                    /* SVCall (see Note #2).                                */
+        case CPU_INT_DBGMON:                                    /* Debug monitor (see Note #2).                         */
+        case CPU_INT_PENDSV:                                    /* PendSV (see Note #2).                                */
+             break;
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_MEMFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_BUSFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_USGFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_ST_CTRL &= ~CPU_REG_NVIC_ST_CTRL_ENABLE;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 32;
+                 nbr   = (pos - 16) % 32;
+
+                 CPU_CRITICAL_ENTER();
+                 CPU_REG_NVIC_CLREN(group) = DEF_BIT(nbr);
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                           CPU_IntSrcEn()
+*
+* Description : Enable an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()  Note #1'.
+*
+*               (2) See 'CPU_IntSrcDis()  Note #2'.
+*
+*               (3) See 'CPU_IntSrcDis()  Note #3'.
+*********************************************************************************************************
+*/
+
+void  CPU_IntSrcEn (CPU_INT08U  pos)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+        case CPU_INT_SVCALL:                                    /* SVCall (see Note #2).                                */
+        case CPU_INT_DBGMON:                                    /* Debug monitor (see Note #2).                         */
+        case CPU_INT_PENDSV:                                    /* PendSV (see Note #2).                                */
+             break;
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_MEMFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_BUSFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_USGFAULTENA;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_ENABLE;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 32;
+                 nbr   = (pos - 16) % 32;
+
+                 CPU_CRITICAL_ENTER();
+                 CPU_REG_NVIC_SETEN(group) = DEF_BIT(nbr);
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                         CPU_IntSrcPendClr()
+*
+* Description : Clear a pending interrupt.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()  Note #1'.
+*
+*               (2) The pending status of several interrupts cannot be clear/set :
+*
+*                   (a) Reset.
+*                   (b) NMI.
+*                   (c) Hard fault.
+*                   (d) Memory Managment.
+*                   (e) Bus Fault.
+*                   (f) Usage Fault.
+*                   (g) SVCall.
+*                   (h) Debug monitor.
+*                   (i) PendSV.
+*                   (j) Systick 
+*
+*               (3) See 'CPU_IntSrcDis()  Note #3'.
+*********************************************************************************************************
+*/
+
+void  CPU_IntSrcPendClr (CPU_INT08U  pos)
+
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+        case CPU_INT_MEM:                                       /* Memory management (see Note #2).                     */
+        case CPU_INT_SVCALL:                                    /* SVCall (see Note #2).                                */
+        case CPU_INT_DBGMON:                                    /* Debug monitor (see Note #2).                         */
+        case CPU_INT_PENDSV:                                    /* PendSV (see Note #2).                                */
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             break;
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 32;
+                 nbr   = (pos - 16) % 32;
+
+                 CPU_CRITICAL_ENTER();
+                 CPU_REG_NVIC_CLRPEND(group) = DEF_BIT(nbr);
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                         CPU_IntSrcPrioSet()
+*
+* Description : Set priority of an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+*               prio    Priority.  Use a lower priority number for a higher priority.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()  Note #1'.
+*
+*               (2) Several interrupts priorities CANNOT be set :
+*
+*                   (a) Reset (always -3).
+*                   (b) NMI (always -2).
+*                   (c) Hard fault (always -1).
+*
+*               (3) See 'CPU_IntSrcDis()  Note #3'.
+*********************************************************************************************************
+*/
+
+void  CPU_IntSrcPrioSet (CPU_INT08U  pos,
+                         CPU_INT08U  prio)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_INT32U  temp;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+             break;
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI1;
+             temp                &= ~(DEF_OCTET_MASK << (0 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (0 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI1  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI1;
+             temp                &= ~(DEF_OCTET_MASK << (1 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (1 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI1  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI1;
+             temp                &= ~(DEF_OCTET_MASK << (2 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (2 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI1  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SVCALL:                                    /* SVCall.                                              */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI2;
+             temp                &= ~((CPU_INT32U)DEF_OCTET_MASK << (3 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio                       << (3 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI2  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_DBGMON:                                    /* Debug monitor.                                       */
+             CPU_CRITICAL_ENTER();
+             temp                = CPU_REG_NVIC_SHPRI3;
+             temp                &= ~(DEF_OCTET_MASK << (0 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (0 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI3  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_PENDSV:                                    /* PendSV.                                              */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI3;
+             temp                &= ~(DEF_OCTET_MASK << (2 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio           << (2 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI3  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             temp                 = CPU_REG_NVIC_SHPRI3;
+             temp                &= ~((CPU_INT32U)DEF_OCTET_MASK << (3 * DEF_OCTET_NBR_BITS));
+             temp                |=  (prio                       << (3 * DEF_OCTET_NBR_BITS));
+             CPU_REG_NVIC_SHPRI3  = temp;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group                    = (pos - 16) / 4;
+                 nbr                      = (pos - 16) % 4;
+
+                 CPU_CRITICAL_ENTER();
+                 temp                     = CPU_REG_NVIC_PRIO(group);
+                 temp                    &= ~(DEF_OCTET_MASK << (nbr * DEF_OCTET_NBR_BITS));
+                 temp                    |=  (prio           << (nbr * DEF_OCTET_NBR_BITS));
+                 CPU_REG_NVIC_PRIO(group) = temp;
+                 CPU_CRITICAL_EXIT();
+             }
+             break;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                         CPU_IntSrcPrioGet()
+*
+* Description : Get priority of an interrupt source.
+*
+* Argument(s) : pos     Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()').
+*
+* Return(s)   : Priority of interrupt source.  If the interrupt source specified is invalid, then
+*               DEF_INT_16S_MIN_VAL is returned.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) See 'CPU_IntSrcDis()      Note #1'.
+*
+*               (2) See 'CPU_IntSrcPrioSet()  Note #2'.
+*
+*               (3) See 'CPU_IntSrcDis()      Note #3'.
+*********************************************************************************************************
+*/
+
+CPU_INT16S  CPU_IntSrcPrioGet (CPU_INT08U  pos)
+{
+    CPU_INT08U  group;
+    CPU_INT08U  nbr;
+    CPU_INT08U  pos_max;
+    CPU_INT16S  prio;
+    CPU_INT32U  temp;
+    CPU_SR_ALLOC();
+
+
+    switch (pos) {
+        case CPU_INT_STK_PTR:                                   /* ---------------- INVALID OR RESERVED --------------- */
+        case CPU_INT_RSVD_07:
+        case CPU_INT_RSVD_08:
+        case CPU_INT_RSVD_09:
+        case CPU_INT_RSVD_10:
+        case CPU_INT_RSVD_13:
+             prio = DEF_INT_16S_MIN_VAL;
+             break;
+
+
+                                                                /* ----------------- SYSTEM EXCEPTIONS ---------------- */
+        case CPU_INT_RESET:                                     /* Reset (see Note #2).                                 */
+             prio = -3;
+             break;
+
+        case CPU_INT_NMI:                                       /* Non-maskable interrupt (see Note #2).                */
+             prio = -2;
+             break;
+
+        case CPU_INT_HFAULT:                                    /* Hard fault (see Note #2).                            */
+             prio = -1;
+             break;
+
+
+        case CPU_INT_MEM:                                       /* Memory management.                                   */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI1;
+             prio = (temp >> (0 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+        case CPU_INT_BUSFAULT:                                  /* Bus fault.                                           */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI1;
+             prio = (temp >> (1 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+        case CPU_INT_USAGEFAULT:                                /* Usage fault.                                         */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI1;
+             prio = (temp >> (2 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SVCALL:                                    /* SVCall.                                              */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI2;
+             prio = (temp >> (3 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_DBGMON:                                    /* Debug monitor.                                       */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI3;
+             prio = (temp >> (0 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_PENDSV:                                    /* PendSV.                                              */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI3;
+             prio = (temp >> (2 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+        case CPU_INT_SYSTICK:                                   /* SysTick.                                             */
+             CPU_CRITICAL_ENTER();
+             temp = CPU_REG_NVIC_SHPRI3;
+             prio = (temp >> (3 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             CPU_CRITICAL_EXIT();
+             break;
+
+
+                                                                /* ---------------- EXTERNAL INTERRUPT ---------------- */
+        default:
+            pos_max = CPU_INT_SRC_POS_MAX;
+            if (pos < pos_max) {                                /* See Note #3.                                         */
+                 group = (pos - 16) / 4;
+                 nbr   = (pos - 16) % 4;
+
+                 CPU_CRITICAL_ENTER();
+                 temp  = CPU_REG_NVIC_PRIO(group);
+                 CPU_CRITICAL_EXIT();
+
+                 prio  = (temp >> (nbr * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK;
+             } else {
+                 prio  = DEF_INT_16S_MIN_VAL;
+             }
+             break;
+    }
+
+    return (prio);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 2387 - 0
MiddleWare/uCOS_II/uC-CPU/cpu_core.c

@@ -0,0 +1,2387 @@
+/*
+*********************************************************************************************************
+*                                                uC/CPU
+*                                    CPU CONFIGURATION & PORT LAYER
+*
+*                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*
+*               uC/CPU is provided in source form to registered licensees ONLY.  It is
+*               illegal to distribute this source code to any third party unless you receive
+*               written permission by an authorized Micrium representative.  Knowledge of
+*               the source code may NOT be used to develop a similar product.
+*
+*               Please help us continue to provide the Embedded community with the finest
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                           CORE CPU MODULE
+*
+* Filename      : cpu_core.c
+* Version       : V1.30.02
+* Programmer(s) : SR
+*                 ITJ
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#define    MICRIUM_SOURCE
+#define    CPU_CORE_MODULE
+#include  "cpu_core.h"
+
+#if defined(CPU_CFG_CACHE_MGMT_EN)
+#if (CPU_CFG_CACHE_MGMT_EN == DEF_ENABLED)
+#include  "cpu_cache.h"
+#endif
+#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.
+*
+* Caller(s)   : Your Product's Application.
+*
+*               This function is a CPU initialization function & MAY be called by application/
+*               initialization function(s).
+*
+* 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.
+*
+* Caller(s)   : various.
+*
+* 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)
+{
+    while (DEF_ON) {
+        ;
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                            CPU_NameClr()
+*
+* Description : Clear CPU Name.
+*
+* Argument(s) : none.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : CPU_NameInit(),
+*               Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY be 
+*               called by application function(s).
+*
+* 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.
+*
+* Caller(s)   : Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY 
+*               be called by application function(s).
+*
+* 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.
+*
+* Caller(s)   : Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY be 
+*               called by application function(s).
+*
+* 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).
+*
+* Caller(s)   : Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY 
+*               be called by application function(s).
+*
+* 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).
+*
+* Caller(s)   : Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY 
+*               be called by application function(s).
+*
+* 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.
+*
+* Caller(s)   : Application/BSP periodic time handler (see Note #1).
+*
+*               This function is a CPU timestamp BSP function & SHOULD be called only by appropriate
+*               application/BSP function(s).
+*
+* 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.
+*
+* Caller(s)   : Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY be 
+*               called by application function(s).
+*
+* 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(;);
+    }
+
+    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.
+*
+* Caller(s)   : CPU_TS_TmrInit(),
+*               Application/BSP initialization function(s).
+*
+*               This function is a CPU module BSP function & SHOULD be called only by appropriate
+*               application/BSP function(s) [see Note #1].
+*
+* 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'.
+*
+* Caller(s)   : Application.
+*
+*               This function is a CPU module application programming interface (API) function 
+*               & MAY be called by application function(s).
+*
+* 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'.
+*
+* Caller(s)   : CPU_IntDisMeasMaxCurReset(),
+*               Application.
+*
+*               This function is a CPU module application programming interface (API) function 
+*               & MAY be called by application function(s).
+*
+* 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'.
+*
+* Caller(s)   : CPU_IntDisMeasInit(),
+*               Application.
+*
+*               This function is a CPU module application programming interface (API) function 
+*               & MAY be called by application function(s).
+*
+* 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.
+*
+* Caller(s)   : CPU_CRITICAL_ENTER().
+*
+*               This function is an INTERNAL CPU module function & MUST NOT be called by application
+*               function(s).
+*
+* 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.
+*
+* Caller(s)   : CPU_CRITICAL_EXIT().
+*
+*               This function is an INTERNAL CPU module function & MUST NOT be called by application
+*               function(s).
+*
+* 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.
+*
+* Caller(s)   : CPU_CntTrailZeros(),
+*               Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY 
+*               be called by application function(s).
+*
+* 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'.
+*
+* Caller(s)   : CPU_CntLeadZeros(),
+*               CPU_CntTrailZeros08(),
+*               Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY be 
+*               called by application function(s).
+*
+* 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'.
+*
+* Caller(s)   : CPU_CntLeadZeros(),
+*               CPU_CntTrailZeros16(),
+*               Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY be 
+*               called by application function(s).
+*
+* 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] :                   */
+                                                                                /* .. Nbr lead zeros =               .. */
+        ix             = (CPU_DATA)((CPU_DATA)val >> 8u);                       /* .. 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'.
+*
+* Caller(s)   : CPU_CntLeadZeros(),
+*               CPU_CntTrailZeros32(),
+*               Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY be 
+*               called by application function(s).
+*
+* 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] :                   */
+                                                                                /* .. Nbr lead zeros =               .. */
+            ix             = (CPU_DATA)((CPU_DATA)(val >> 24u));                /* .. 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] :                   */
+                                                                                /* .. Nbr lead zeros =               .. */
+            ix             = (CPU_DATA)((CPU_DATA)(val >> 16u));                /* .. 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] :                   */
+                                                                                /* .. Nbr lead zeros =               .. */
+            ix             = (CPU_DATA)((CPU_DATA)(val >>  8u));                /* .. 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)((CPU_DATA)(val >>  0u));                /* .. 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'.
+*
+* Caller(s)   : CPU_CntLeadZeros(),
+*               CPU_CntTrailZeros64(),
+*               Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY be 
+*               called by application function(s).
+*
+* 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 > 0x00000000FFFFFFFFu) {
+        if (val > 0x0000FFFFFFFFFFFFu) {
+            if (val > 0x00FFFFFFFFFFFFFFu) {                                    /* Chk bits [63:56] :                   */
+                                                                                /* .. Nbr lead zeros =               .. */
+                ix             = (CPU_DATA)((CPU_INT64U)val >> 56u);            /* .. 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] :                   */
+                                                                                /* .. Nbr lead zeros =               .. */
+                ix             = (CPU_DATA)((CPU_INT64U)val >> 48u);            /* .. 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 > 0x000000FFFFFFFFFFu) {                                    /* Chk bits [47:40] :                   */
+                                                                                /* .. Nbr lead zeros =               .. */
+                ix             = (CPU_DATA)((CPU_INT64U)val >> 40u);            /* .. 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] :                   */
+                                                                                /* .. Nbr lead zeros =               .. */
+                ix             = (CPU_DATA)((CPU_INT64U)val >> 32u);            /* .. 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 > 0x000000000000FFFFu) {
+            if (val > 0x0000000000FFFFFFu) {                                    /* Chk bits [31:24] :                   */
+                                                                                /* .. Nbr lead zeros =               .. */
+                ix             = (CPU_DATA)((CPU_INT64U)val >> 24u);              /* .. 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] :                   */
+                                                                                /* .. Nbr lead zeros =               .. */
+                ix             = (CPU_DATA)((CPU_INT64U)val >> 16u);            /* .. 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 > 0x00000000000000FFu) {                                    /* Chk bits [15:08] :                   */
+                                                                                /* .. Nbr lead zeros =               .. */
+                ix             = (CPU_DATA)((CPU_INT64U)val >>  8u);            /* .. 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'.
+*
+* Caller(s)   : Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY 
+*               be called by application function(s).
+*
+* 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_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_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'.
+*
+* Caller(s)   : Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY be 
+*               called by application function(s).
+*
+* 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_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_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'.
+*
+* Caller(s)   : Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY be 
+*               called by application function(s).
+*
+* 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_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_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'.
+*
+* Caller(s)   : Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY be 
+*               called by application function(s).
+*
+* 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_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_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'.
+*
+* Caller(s)   : Application.
+*
+*               This function is a CPU module application programming interface (API) function & MAY be 
+*               called by application function(s).
+*
+* 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_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_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.
+*
+* Caller(s)   : various.
+*
+* Note(s)     : (1) Algorithm taken from http://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 (result);
+}
+
+
+/*
+*********************************************************************************************************
+*********************************************************************************************************
+*                                           LOCAL FUNCTIONS
+*********************************************************************************************************
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                           CPU_NameInit()
+*
+* Description : Initialize CPU Name.
+*
+* Argument(s) : none.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : CPU_Init().
+*
+* 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.
+*
+* Caller(s)   : CPU_Init().
+*
+* 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.
+*
+* Caller(s)   : CPU_Init().
+*
+* 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).
+*
+* Caller(s)   : CPU_IntDisMeasMaxCurGet(),
+*               CPU_IntDisMeasMaxGet().
+*
+* 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
+

+ 1032 - 0
MiddleWare/uCOS_II/uC-CPU/cpu_core.h

@@ -0,0 +1,1032 @@
+/*
+*********************************************************************************************************
+*                                                uC/CPU
+*                                    CPU CONFIGURATION & PORT LAYER
+*
+*                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*
+*               uC/CPU is provided in source form to registered licensees ONLY.  It is 
+*               illegal to distribute this source code to any third party unless you receive 
+*               written permission by an authorized Micrium representative.  Knowledge of 
+*               the source code may NOT be used to develop a similar product.
+*
+*               Please help us continue to provide the Embedded community with the finest 
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                           CORE CPU MODULE
+*
+* Filename      : cpu_core.h
+* Version       : V1.30.02
+* Programmer(s) : SR
+*                 ITJ
+*********************************************************************************************************
+* Note(s)       : (1) Assumes the following versions (or more recent) of software modules are included in 
+*                     the project build :
+*
+*                     (a) uC/LIB V1.35.00
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*
+* Note(s) : (1) This core CPU header file is protected from multiple pre-processor inclusion through use of 
+*               the  core CPU module present pre-processor macro definition.
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_CORE_MODULE_PRESENT                                /* See Note #1.                                         */
+#define  CPU_CORE_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*                                               EXTERNS
+*********************************************************************************************************
+*/
+
+#ifdef   CPU_CORE_MODULE
+#define  CPU_CORE_EXT
+#else
+#define  CPU_CORE_EXT  extern
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*
+* Note(s) : (1) CPU-configuration software files are located in the following directories :
+*
+*               (a) \<Your Product Application>\cpu_cfg.h
+*
+*               (b) (1) \<CPU-Compiler Directory>\cpu_*.*
+*                   (2) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.*
+*
+*                       where
+*                               <Your Product Application>      directory path for Your Product's Application
+*                               <CPU-Compiler Directory>        directory path for common CPU-compiler software
+*                               <cpu>                           directory name for specific processor (CPU)
+*                               <compiler>                      directory name for specific compiler
+*
+*           (2) NO compiler-supplied standard library functions SHOULD be used.
+*
+*               (a) Standard library functions are implemented in the custom library module(s) :
+*
+*                       \<Custom Library Directory>\lib_*.*
+*
+*                           where
+*                                   <Custom Library Directory>      directory path for custom library software
+*
+*           (3) Compiler MUST be configured to include as additional include path directories :
+*
+*               (a) '\<Your Product Application>\' directory                            See Note #1a
+*
+*               (b) (1) '\<CPU-Compiler Directory>\'                  directory         See Note #1b1
+*                   (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory         See Note #1b2
+*
+*               (c) '\<Custom Library Directory>\' directory                            See Note #2a
+*********************************************************************************************************
+*/
+
+#include  <cpu.h>
+#include  <lib_def.h>
+#include  <cpu_cfg.h>
+
+#if (CPU_CFG_NAME_EN == DEF_ENABLED)
+#include  <lib_mem.h>
+#include  <lib_str.h>
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          CPU CONFIGURATION
+*
+* Note(s) : (1) The following pre-processor directives correctly configure CPU parameters.  DO NOT MODIFY.
+*
+*           (2) CPU timestamp timer feature is required for :
+*
+*               (a) CPU timestamps
+*               (b) CPU interrupts disabled time measurement
+*
+*               See also 'cpu_cfg.h  CPU TIMESTAMP CONFIGURATION  Note #1'
+*                      & 'cpu_cfg.h  CPU INTERRUPTS DISABLED TIME MEASUREMENT CONFIGURATION  Note #1'.
+*********************************************************************************************************
+*/
+
+#ifdef   CPU_CFG_TS_EN
+#undef   CPU_CFG_TS_EN
+#endif
+
+
+#if    ((CPU_CFG_TS_32_EN == DEF_ENABLED) || \
+        (CPU_CFG_TS_64_EN == DEF_ENABLED))
+#define  CPU_CFG_TS_EN                          DEF_ENABLED
+#else
+#define  CPU_CFG_TS_EN                          DEF_DISABLED
+#endif
+
+#if    ((CPU_CFG_TS_EN == DEF_ENABLED) || \
+(defined(CPU_CFG_INT_DIS_MEAS_EN)))
+#define  CPU_CFG_TS_TMR_EN                      DEF_ENABLED
+#else
+#define  CPU_CFG_TS_TMR_EN                      DEF_DISABLED
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                               DEFINES
+*********************************************************************************************************
+*/
+
+#define  CPU_TIME_MEAS_NBR_MIN                             1u
+#define  CPU_TIME_MEAS_NBR_MAX                           128u
+
+
+/*
+*********************************************************************************************************
+*                                             DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                           CPU ERROR CODES
+*********************************************************************************************************
+*/
+
+typedef enum cpu_err {
+
+    CPU_ERR_NONE                            =         0u,
+    CPU_ERR_NULL_PTR                        =        10u,
+
+    CPU_ERR_NAME_SIZE                       =      1000u,
+
+    CPU_ERR_TS_FREQ_INVALID                 =      2000u
+
+} CPU_ERR;
+
+
+/*
+*********************************************************************************************************
+*                                      CPU TIMESTAMP DATA TYPES
+*
+* Note(s) : (1) CPU timestamp timer data type defined to the binary-multiple of 8-bit octets as configured 
+*               by 'CPU_CFG_TS_TMR_SIZE' (see 'cpu_cfg.h  CPU TIMESTAMP CONFIGURATION  Note #2').
+*********************************************************************************************************
+*/
+
+typedef  CPU_INT32U  CPU_TS32;
+typedef  CPU_INT64U  CPU_TS64;
+
+typedef  CPU_TS32    CPU_TS;                                    /* Req'd for backwards-compatibility.                   */
+
+
+#if     (CPU_CFG_TS_TMR_EN   == DEF_ENABLED)                    /* CPU ts tmr defined to cfg'd word size (see Note #1). */
+#if     (CPU_CFG_TS_TMR_SIZE == CPU_WORD_SIZE_08)
+typedef  CPU_INT08U  CPU_TS_TMR;
+#elif   (CPU_CFG_TS_TMR_SIZE == CPU_WORD_SIZE_16)
+typedef  CPU_INT16U  CPU_TS_TMR;
+#elif   (CPU_CFG_TS_TMR_SIZE == CPU_WORD_SIZE_64)
+typedef  CPU_INT64U  CPU_TS_TMR;
+#else                                                           /* CPU ts tmr dflt size = 32-bits.                      */
+typedef  CPU_INT32U  CPU_TS_TMR;
+#endif
+#endif
+
+
+/*
+*********************************************************************************************************
+*                               CPU TIMESTAMP TIMER FREQUENCY DATA TYPE
+*********************************************************************************************************
+*/
+
+typedef  CPU_INT32U  CPU_TS_TMR_FREQ;
+
+
+/*
+*********************************************************************************************************
+*                                          GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+#if    (CPU_CFG_NAME_EN   == DEF_ENABLED)
+CPU_CORE_EXT  CPU_CHAR         CPU_Name[CPU_CFG_NAME_SIZE];     /* CPU host name.                                       */
+#endif
+
+
+#if ((CPU_CFG_TS_32_EN    == DEF_ENABLED)  && \
+     (CPU_CFG_TS_TMR_SIZE <  CPU_WORD_SIZE_32))
+CPU_CORE_EXT  CPU_TS32         CPU_TS_32_Accum;                 /* 32-bit accum'd ts  (in ts tmr cnts).                 */
+CPU_CORE_EXT  CPU_TS_TMR       CPU_TS_32_TmrPrev;               /* 32-bit ts prev tmr (in ts tmr cnts).                 */
+#endif
+
+#if ((CPU_CFG_TS_64_EN    == DEF_ENABLED)  && \
+     (CPU_CFG_TS_TMR_SIZE <  CPU_WORD_SIZE_64))
+CPU_CORE_EXT  CPU_TS64         CPU_TS_64_Accum;                 /* 64-bit accum'd ts  (in ts tmr cnts).                 */
+CPU_CORE_EXT  CPU_TS_TMR       CPU_TS_64_TmrPrev;               /* 64-bit ts prev tmr (in ts tmr cnts).                 */
+#endif
+
+#if  (CPU_CFG_TS_TMR_EN   == DEF_ENABLED)
+CPU_CORE_EXT  CPU_TS_TMR_FREQ  CPU_TS_TmrFreq_Hz;               /* CPU ts tmr freq (in Hz).                             */
+#endif
+
+
+#ifdef  CPU_CFG_INT_DIS_MEAS_EN
+CPU_CORE_EXT  CPU_INT16U       CPU_IntDisMeasCtr;               /* Nbr tot    ints dis'd ctr.                           */
+CPU_CORE_EXT  CPU_INT16U       CPU_IntDisNestCtr;               /* Nbr nested ints dis'd ctr.                           */
+                                                                /* Ints dis'd time (in ts tmr cnts) : ...               */
+CPU_CORE_EXT  CPU_TS_TMR       CPU_IntDisMeasStart_cnts;        /* ...  start time.                                     */
+CPU_CORE_EXT  CPU_TS_TMR       CPU_IntDisMeasStop_cnts;         /* ...  stop  time.                                     */
+CPU_CORE_EXT  CPU_TS_TMR       CPU_IntDisMeasOvrhd_cnts;        /* ...        time meas ovrhd.                          */
+CPU_CORE_EXT  CPU_TS_TMR       CPU_IntDisMeasMaxCur_cnts;       /* ...     resetable max time dis'd.                    */
+CPU_CORE_EXT  CPU_TS_TMR       CPU_IntDisMeasMax_cnts;          /* ... non-resetable max time dis'd.                    */
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                               MACRO'S
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                         CPU_SW_EXCEPTION()
+*
+* Description : Trap unrecoverable software exception.
+*
+* Argument(s) : err_rtn_val     Error type &/or value of the calling function to return (see Note #2b).
+*
+* Return(s)   : none.
+*
+* Caller(s)   : various.
+*
+* 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.
+*
+*                   Example CPU_SW_EXCEPTION() call :
+*
+*                       void  Fnct (CPU_ERR  *p_err)
+*                       {
+*                           :
+*
+*                           if (p_err == (CPU_ERR *)0) {        If 'p_err' NULL, cannot return error ...
+*                               CPU_SW_EXCEPTION(;);            ... so trap invalid argument exception.
+*                           }
+*
+*                           :
+*                       }
+*
+*                   See also 'cpu_core.c  CPU_SW_Exception()  Note #1'.
+*
+*               (2) (a) CPU_SW_EXCEPTION()  MAY be developer-implemented to output &/or handle any error or 
+*                       exception conditions; but since CPU_SW_EXCEPTION() is intended to trap unrecoverable 
+*                       software  conditions, it is recommended that developer-implemented versions prevent 
+*                       execution of any code following calls to CPU_SW_EXCEPTION() by deadlocking the code 
+*                       (see Note #1).
+*
+*                           Example CPU_SW_EXCEPTION() :
+*
+*                               #define  CPU_SW_EXCEPTION(err_rtn_val)      do {                         \
+*                                                                               Log(__FILE__, __LINE__); \
+*                                                                               CPU_SW_Exception();      \
+*                                                                           } while (0)
+*
+*                   (b) (1) However, if execution of code following calls to CPU_SW_EXCEPTION() is required 
+*                           (e.g. for automated testing); it is recommended that the last statement in 
+*                           developer-implemented versions be to return from the current function to prevent 
+*                           possible software exception(s) in the current function from triggering CPU &/or 
+*                           hardware exception(s).
+*
+*                           Example CPU_SW_EXCEPTION() :
+*
+*                               #define  CPU_SW_EXCEPTION(err_rtn_val)      do {                         \
+*                                                                               Log(__FILE__, __LINE__); \
+*                                                                               return  err_rtn_val;     \
+*                                                                           } while (0)
+*
+*                           (A) Note that 'err_rtn_val' in the return statement MUST NOT be enclosed in 
+*                               parentheses.  This allows CPU_SW_EXCEPTION() to return from functions that 
+*                               return 'void', i.e. NO return type or value (see also Note #2b2A).
+*
+*                       (2) In order for CPU_SW_EXCEPTION() to return from functions with various return 
+*                           types/values, each caller function MUST pass an appropriate error return type 
+*                           & value to CPU_SW_EXCEPTION().
+*
+*                           (A) Note that CPU_SW_EXCEPTION()  MUST NOT be passed any return type or value 
+*                               for functions that return 'void', i.e. NO return type or value; but SHOULD 
+*                               instead be passed a single semicolon.  This prevents possible compiler 
+*                               warnings that CPU_SW_EXCEPTION() is passed too few arguments.  However, 
+*                               the compiler may warn that CPU_SW_EXCEPTION() does NOT prevent creating 
+*                               null statements on lines with NO other code statements.
+*
+*                           Example CPU_SW_EXCEPTION() calls :
+*
+*                               void  Fnct (CPU_ERR  *p_err)
+*                               {
+*                                   :
+*
+*                                   if (p_err == (CPU_ERR *)0) {
+*                                       CPU_SW_EXCEPTION(;);            Exception macro returns NO value
+*                                   }                                       (see Note #2b2A)
+*
+*                                   :
+*                               }
+*
+*                               CPU_BOOLEAN  Fnct (CPU_ERR  *p_err)
+*                               {
+*                                   :
+*
+*                                   if (p_err == (CPU_ERR *)0) {
+*                                       CPU_SW_EXCEPTION(DEF_FAIL);     Exception macro returns 'DEF_FAIL'
+*                                   }
+*
+*                                   :
+*                               }
+*
+*                               OBJ  *Fnct (CPU_ERR  *p_err)
+*                               {
+*                                   :
+*
+*                                   if (p_err == (CPU_ERR *)0) {
+*                                       CPU_SW_EXCEPTION((OBJ *)0);     Exception macro returns NULL 'OBJ *'
+*                                   }
+*
+*                                   :
+*                               }
+*
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_SW_EXCEPTION                                                       /* See Note #2.                         */
+#define  CPU_SW_EXCEPTION(err_rtn_val)              do {                    \
+                                                        CPU_SW_Exception(); \
+                                                    } while (0)
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                           CPU_VAL_UNUSED()
+*
+* Description : 
+*
+* Argument(s) : none.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : #### various.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+
+#define  CPU_VAL_UNUSED(val)        ((void)&(val));
+
+
+#define  CPU_VAL_IGNORED(val)       CPU_VAL_UNUSED(val)
+
+
+/*
+*********************************************************************************************************
+*                                          CPU_TYPE_CREATE()
+*
+* Description : Creates a generic type value.
+*
+* Argument(s) : char_1      1st ASCII character to create generic type value.
+*
+*               char_2      2nd ASCII character to create generic type value.
+*
+*               char_3      3rd ASCII character to create generic type value.
+*
+*               char_4      4th ASCII character to create generic type value.
+*
+* Return(s)   : 32-bit generic type value.
+*
+* Caller(s)   : various.
+*
+* Note(s)     : (1) (a) Generic type values should be #define'd with large, non-trivial values to trap 
+*                       & discard invalid/corrupted objects based on type value.
+*
+*                       In other words, by assigning large, non-trivial values to valid objects' type 
+*                       fields; the likelihood that an object with an unassigned &/or corrupted type 
+*                       field will contain a value is highly improbable & therefore the object itself 
+*                       will be trapped as invalid.
+*
+*                   (b) (1) CPU_TYPE_CREATE()  creates a 32-bit type value from four values.
+*
+*                       (2) Ideally, generic type values SHOULD be created from 'CPU_CHAR' characters to 
+*                           represent ASCII string abbreviations of the specific object types.  Memory 
+*                           displays of object type values will display the specific object types with 
+*                           their chosen ASCII names.
+*
+*                           Examples :
+*
+*                               #define  FILE_TYPE  CPU_TYPE_CREATE('F', 'I', 'L', 'E')
+*                               #define  BUF_TYPE   CPU_TYPE_CREATE('B', 'U', 'F', ' ')
+*********************************************************************************************************
+*/
+
+#if     (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
+#define  CPU_TYPE_CREATE(char_1, char_2, char_3, char_4)        (((CPU_INT32U)((CPU_INT08U)(char_1)) << (3u * DEF_OCTET_NBR_BITS)) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_2)) << (2u * DEF_OCTET_NBR_BITS)) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_3)) << (1u * DEF_OCTET_NBR_BITS)) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_4))))
+
+#else
+
+#if    ((CPU_CFG_DATA_SIZE   == CPU_WORD_SIZE_64) || \
+        (CPU_CFG_DATA_SIZE   == CPU_WORD_SIZE_32))
+#define  CPU_TYPE_CREATE(char_1, char_2, char_3, char_4)        (((CPU_INT32U)((CPU_INT08U)(char_1))) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_2)) << (1u * DEF_OCTET_NBR_BITS)) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_3)) << (2u * DEF_OCTET_NBR_BITS)) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_4)) << (3u * DEF_OCTET_NBR_BITS)))
+
+
+#elif   (CPU_CFG_DATA_SIZE   == CPU_WORD_SIZE_16)
+#define  CPU_TYPE_CREATE(char_1, char_2, char_3, char_4)        (((CPU_INT32U)((CPU_INT08U)(char_1)) << (2u * DEF_OCTET_NBR_BITS)) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_2)) << (3u * DEF_OCTET_NBR_BITS)) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_3))) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_4)) << (1u * DEF_OCTET_NBR_BITS)))
+
+#else                                                           /* Dflt CPU_WORD_SIZE_08.                               */
+#define  CPU_TYPE_CREATE(char_1, char_2, char_3, char_4)        (((CPU_INT32U)((CPU_INT08U)(char_1)) << (3u * DEF_OCTET_NBR_BITS)) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_2)) << (2u * DEF_OCTET_NBR_BITS)) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_3)) << (1u * DEF_OCTET_NBR_BITS)) | \
+                                                                 ((CPU_INT32U)((CPU_INT08U)(char_4))))
+#endif
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*
+* Note(s) : (1) CPU interrupts disabled time measurement functions prototyped/defined only if 
+*               CPU_CFG_INT_DIS_MEAS_EN  #define'd in 'cpu_cfg.h'.
+*
+*           (2) (a) CPU_CntLeadZeros()  defined in :
+*
+*                   (1) 'cpu_a.asm',  if CPU_CFG_LEAD_ZEROS_ASM_PRESENT       #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable assembly-optimized function(s)
+*
+*                   (2) 'cpu_core.c', if CPU_CFG_LEAD_ZEROS_ASM_PRESENT   NOT #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable C-source-optimized function(s)
+*
+*               (b) CPU_CntTrailZeros() defined in :
+*
+*                   (1) 'cpu_a.asm',  if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT      #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable assembly-optimized function(s)
+*
+*                   (2) 'cpu_core.c', if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT  NOT #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable C-source-optimized function(s)
+*********************************************************************************************************
+*/
+
+void             CPU_Init                 (void);
+
+void             CPU_SW_Exception         (void);
+
+
+
+#if (CPU_CFG_NAME_EN == DEF_ENABLED)                                    /* -------------- CPU NAME FNCTS -------------- */
+void             CPU_NameClr              (void);
+
+void             CPU_NameGet              (       CPU_CHAR  *p_name,
+                                                  CPU_ERR   *p_err);
+
+void             CPU_NameSet              (const  CPU_CHAR  *p_name,
+                                                  CPU_ERR   *p_err);
+#endif
+
+
+
+                                                                        /* --------------- CPU TS FNCTS --------------- */
+#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
+CPU_TS32         CPU_TS_Get32             (void);
+#endif
+
+#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
+CPU_TS64         CPU_TS_Get64             (void);
+#endif
+
+#if (CPU_CFG_TS_EN    == DEF_ENABLED)
+void             CPU_TS_Update            (void);
+#endif
+
+
+#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)                                  /* ------------- CPU TS TMR FNCTS ------------- */
+CPU_TS_TMR_FREQ  CPU_TS_TmrFreqGet        (CPU_ERR          *p_err);
+
+void             CPU_TS_TmrFreqSet        (CPU_TS_TMR_FREQ   freq_hz);
+#endif
+
+
+
+#ifdef  CPU_CFG_INT_DIS_MEAS_EN                                         /* -------- CPU INT DIS TIME MEAS FNCTS ------- */
+                                                                        /* See Note #1.                                 */
+CPU_TS_TMR       CPU_IntDisMeasMaxCurReset(void);
+
+CPU_TS_TMR       CPU_IntDisMeasMaxCurGet  (void);
+
+CPU_TS_TMR       CPU_IntDisMeasMaxGet     (void);
+
+
+void             CPU_IntDisMeasStart      (void);
+
+void             CPU_IntDisMeasStop       (void);
+#endif
+
+
+
+                                                                        /* ----------- CPU CNT ZEROS FNCTS ------------ */
+#ifdef  CPU_CFG_LEAD_ZEROS_ASM_PRESENT
+#ifdef __cplusplus
+extern  "C" {
+#endif
+#endif
+
+CPU_DATA         CPU_CntLeadZeros         (CPU_DATA    val);
+
+#ifdef  CPU_CFG_LEAD_ZEROS_ASM_PRESENT
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#if     (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_08)
+CPU_DATA         CPU_CntLeadZeros08       (CPU_INT08U  val);
+#endif
+#if     (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_16)
+CPU_DATA         CPU_CntLeadZeros16       (CPU_INT16U  val);
+#endif
+#if     (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_32)
+CPU_DATA         CPU_CntLeadZeros32       (CPU_INT32U  val);
+#endif
+#if     (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_64)
+CPU_DATA         CPU_CntLeadZeros64       (CPU_INT64U  val);
+#endif
+
+
+#ifdef  CPU_CFG_LEAD_ZEROS_ASM_PRESENT
+#ifdef __cplusplus
+extern  "C" {
+#endif
+#endif
+  
+CPU_DATA         CPU_CntTrailZeros        (CPU_DATA    val);
+
+#ifdef  CPU_CFG_LEAD_ZEROS_ASM_PRESENT
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#if     (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_08)
+CPU_DATA         CPU_CntTrailZeros08      (CPU_INT08U  val);
+#endif
+#if     (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_16)
+CPU_DATA         CPU_CntTrailZeros16      (CPU_INT16U  val);
+#endif
+#if     (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_32)
+CPU_DATA         CPU_CntTrailZeros32      (CPU_INT32U  val);
+#endif
+#if     (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_64)
+CPU_DATA         CPU_CntTrailZeros64      (CPU_INT64U  val);
+#endif
+
+CPU_INT08U       CPU_PopCnt32             (CPU_INT32U  value);
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*                                      DEFINED IN PRODUCT'S BSP
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                          CPU_TS_TmrInit()
+*
+* Description : Initialize & start CPU timestamp timer.
+*
+* Argument(s) : none.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : CPU_TS_Init().
+*
+*               This function is an INTERNAL CPU module function & MUST be implemented by application/
+*               BSP function(s) [see Note #1] but MUST NOT be called by application function(s).
+*
+* Note(s)     : (1) CPU_TS_TmrInit() is an application/BSP function that MUST be defined by the developer 
+*                   if either of the following CPU features is enabled :
+*
+*                   (a) CPU timestamps
+*                   (b) CPU interrupts disabled time measurements
+*
+*                   See 'cpu_cfg.h  CPU TIMESTAMP CONFIGURATION  Note #1'
+*                     & 'cpu_cfg.h  CPU INTERRUPTS DISABLED TIME MEASUREMENT CONFIGURATION  Note #1a'.
+*
+*               (2) (a) Timer count values MUST be returned via word-size-configurable 'CPU_TS_TMR' 
+*                       data type.
+*
+*                       (1) If timer has more bits, truncate timer values' higher-order bits greater 
+*                           than the configured 'CPU_TS_TMR' timestamp timer data type word size.
+*
+*                       (2) Since the timer MUST NOT have less bits than the configured 'CPU_TS_TMR' 
+*                           timestamp timer data type word size; 'CPU_CFG_TS_TMR_SIZE' MUST be 
+*                           configured so that ALL bits in 'CPU_TS_TMR' data type are significant.
+*
+*                           In other words, if timer size is not a binary-multiple of 8-bit octets 
+*                           (e.g. 20-bits or even 24-bits), then the next lower, binary-multiple 
+*                           octet word size SHOULD be configured (e.g. to 16-bits).  However, the 
+*                           minimum supported word size for CPU timestamp timers is 8-bits.
+*
+*                       See also 'cpu_cfg.h   CPU TIMESTAMP CONFIGURATION  Note #2'
+*                              & 'cpu_core.h  CPU TIMESTAMP DATA TYPES     Note #1'.
+*
+*                   (b) Timer SHOULD be an 'up'  counter whose values increase with each time count.
+*
+*                   (c) When applicable, 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_TS_TmrRd()  Note #2'.
+*********************************************************************************************************
+*/
+
+#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
+void  CPU_TS_TmrInit(void);
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                           CPU_TS_TmrRd()
+*
+* Description : Get current CPU timestamp timer count value.
+*
+* Argument(s) : none.
+*
+* Return(s)   : Timestamp timer count (see Notes #2a & #2b).
+*
+* Caller(s)   : CPU_TS_Init(),
+*               CPU_TS_Get32(),
+*               CPU_TS_Get64(),
+*               CPU_IntDisMeasStart(),
+*               CPU_IntDisMeasStop().
+*
+*               This function is an INTERNAL CPU module function & MUST be implemented by application/
+*               BSP function(s) [see Note #1] but SHOULD NOT be called by application function(s).
+*
+* Note(s)     : (1) CPU_TS_TmrRd() is an application/BSP function that MUST be defined by the developer 
+*                   if either of the following CPU features is enabled :
+*
+*                   (a) CPU timestamps
+*                   (b) CPU interrupts disabled time measurements
+*
+*                   See 'cpu_cfg.h  CPU TIMESTAMP CONFIGURATION  Note #1'
+*                     & 'cpu_cfg.h  CPU INTERRUPTS DISABLED TIME MEASUREMENT CONFIGURATION  Note #1a'.
+*
+*               (2) (a) Timer count values MUST be returned via word-size-configurable 'CPU_TS_TMR' 
+*                       data type.
+*
+*                       (1) If timer has more bits, truncate timer values' higher-order bits greater 
+*                           than the configured 'CPU_TS_TMR' timestamp timer data type word size.
+*
+*                       (2) Since the timer MUST NOT have less bits than the configured 'CPU_TS_TMR' 
+*                           timestamp timer data type word size; 'CPU_CFG_TS_TMR_SIZE' MUST be 
+*                           configured so that ALL bits in 'CPU_TS_TMR' data type are significant.
+*
+*                           In other words, if timer size is not a binary-multiple of 8-bit octets 
+*                           (e.g. 20-bits or even 24-bits), then the next lower, binary-multiple 
+*                           octet word size SHOULD be configured (e.g. to 16-bits).  However, the 
+*                           minimum supported word size for CPU timestamp timers is 8-bits.
+*
+*                       See also 'cpu_cfg.h   CPU TIMESTAMP CONFIGURATION  Note #2'
+*                              & 'cpu_core.h  CPU TIMESTAMP DATA TYPES     Note #1'.
+*
+*                   (b) Timer SHOULD be an 'up'  counter whose values increase with each time count.
+*
+*                       (1) If timer is a 'down' counter whose values decrease with each time count,
+*                           then the returned timer value MUST be ones-complemented.
+*
+*                   (c) (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
+*
+*                       (2) 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.
+*********************************************************************************************************
+*/
+
+#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
+CPU_TS_TMR  CPU_TS_TmrRd(void);
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                         CPU_TSxx_to_uSec()
+*
+* Description : Convert a 32-/64-bit CPU timestamp from timer counts to microseconds.
+*
+* Argument(s) : ts_cnts   CPU timestamp (in timestamp timer counts [see Note #2aA]).
+*
+* Return(s)   : Converted CPU timestamp (in microseconds           [see Note #2aD]).
+*
+* Caller(s)   : Application.
+*
+*               This function is an (optional) CPU module application programming interface (API) 
+*               function which MAY be implemented by application/BSP function(s) [see Note #1] & 
+*               MAY be called by application function(s).
+*
+* Note(s)     : (1) CPU_TS32_to_uSec()/CPU_TS64_to_uSec() are application/BSP functions that MAY be 
+*                   optionally defined by the developer when either of the following CPU features is 
+*                   enabled :
+*
+*                   (a) CPU timestamps
+*                   (b) CPU interrupts disabled time measurements
+*
+*                   See 'cpu_cfg.h  CPU TIMESTAMP CONFIGURATION  Note #1'
+*                     & 'cpu_cfg.h  CPU INTERRUPTS DISABLED TIME MEASUREMENT CONFIGURATION  Note #1a'.
+*
+*               (2) (a) The amount of time measured by CPU timestamps is calculated by either of 
+*                       the following equations :
+*
+*                                                                        10^6 microseconds
+*                       (1) Time measured  =   Number timer counts   *  -------------------  *  Timer period
+*                                                                            1 second
+*
+*                                              Number timer counts       10^6 microseconds
+*                       (2) Time measured  =  ---------------------  *  -------------------
+*                                                Timer frequency             1 second
+*
+*                               where
+*
+*                                   (A) Number timer counts     Number of timer counts measured
+*                                   (B) Timer frequency         Timer's frequency in some units 
+*                                                                   of counts per second
+*                                   (C) Timer period            Timer's period in some units of 
+*                                                                   (fractional)  seconds
+*                                   (D) Time measured           Amount of time measured, 
+*                                                                   in microseconds
+*
+*                   (b) 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.
+*
+*                   (c) Specific implementations may convert any number of CPU_TS32 or CPU_TS64 bits 
+*                       -- up to 32 or 64, respectively -- into microseconds.
+*********************************************************************************************************
+*/
+
+#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
+CPU_INT64U  CPU_TS32_to_uSec(CPU_TS32  ts_cnts);
+#endif
+
+#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
+CPU_INT64U  CPU_TS64_to_uSec(CPU_TS64  ts_cnts);
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                        CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_CFG_NAME_EN
+#error  "CPU_CFG_NAME_EN                       not #define'd in 'cpu_cfg.h'"
+#error  "                                [MUST be  DEF_ENABLED ]           "
+#error  "                                [     ||  DEF_DISABLED]           "
+
+#elif  ((CPU_CFG_NAME_EN != DEF_ENABLED ) && \
+        (CPU_CFG_NAME_EN != DEF_DISABLED))
+#error  "CPU_CFG_NAME_EN                 illegally #define'd in 'cpu_cfg.h'"
+#error  "                                [MUST be  DEF_ENABLED ]           "
+#error  "                                [     ||  DEF_DISABLED]           "
+
+
+#elif   (CPU_CFG_NAME_EN == DEF_ENABLED)
+
+#ifndef  CPU_CFG_NAME_SIZE
+#error  "CPU_CFG_NAME_SIZE                     not #define'd in 'cpu_cfg.h'"
+#error  "                                [MUST be  >=   1]                 "
+#error  "                                [     &&  <= 255]                 "
+
+#elif   (DEF_CHK_VAL(CPU_CFG_NAME_SIZE,            \
+                     1,                            \
+                     DEF_INT_08U_MAX_VAL) != DEF_OK)
+#error  "CPU_CFG_NAME_SIZE               illegally #define'd in 'cpu_cfg.h'"
+#error  "                                [MUST be  >=   1]                 "
+#error  "                                [     &&  <= 255]                 "
+#endif
+
+#endif
+
+
+
+
+#ifndef  CPU_CFG_TS_32_EN
+#error  "CPU_CFG_TS_32_EN                      not #define'd in 'cpu_cfg.h'"
+#error  "                                [MUST be  DEF_DISABLED]           "
+#error  "                                [     ||  DEF_ENABLED ]           "
+
+#elif  ((CPU_CFG_TS_32_EN != DEF_DISABLED) && \
+        (CPU_CFG_TS_32_EN != DEF_ENABLED ))
+#error  "CPU_CFG_TS_32_EN                illegally #define'd in 'cpu_cfg.h'"
+#error  "                                [MUST be  DEF_DISABLED]           "
+#error  "                                [     ||  DEF_ENABLED ]           "
+
+#endif
+
+
+#ifndef  CPU_CFG_TS_64_EN
+#error  "CPU_CFG_TS_64_EN                      not #define'd in 'cpu_cfg.h'"
+#error  "                                [MUST be  DEF_DISABLED]           "
+#error  "                                [     ||  DEF_ENABLED ]           "
+
+#elif  ((CPU_CFG_TS_64_EN != DEF_DISABLED) && \
+        (CPU_CFG_TS_64_EN != DEF_ENABLED ))
+#error  "CPU_CFG_TS_64_EN                illegally #define'd in 'cpu_cfg.h'"
+#error  "                                [MUST be  DEF_DISABLED]           "
+#error  "                                [     ||  DEF_ENABLED ]           "
+
+#endif
+
+                                                                /* Correctly configured in 'cpu_core.h'; DO NOT MODIFY. */
+#ifndef  CPU_CFG_TS_EN
+#error  "CPU_CFG_TS_EN                         not #define'd in 'cpu_core.h'"
+#error  "                                [MUST be  DEF_DISABLED]            "
+#error  "                                [     ||  DEF_ENABLED ]            "
+
+#elif  ((CPU_CFG_TS_EN != DEF_DISABLED) && \
+        (CPU_CFG_TS_EN != DEF_ENABLED ))
+#error  "CPU_CFG_TS_EN                   illegally #define'd in 'cpu_core.h'"
+#error  "                                [MUST be  DEF_DISABLED]            "
+#error  "                                [     ||  DEF_ENABLED ]            "
+
+#endif
+
+
+                                                                /* Correctly configured in 'cpu_core.h'; DO NOT MODIFY. */
+#ifndef  CPU_CFG_TS_TMR_EN
+#error  "CPU_CFG_TS_TMR_EN                     not #define'd in 'cpu_core.h'"
+#error  "                                [MUST be  DEF_DISABLED]            "
+#error  "                                [     ||  DEF_ENABLED ]            "
+
+#elif  ((CPU_CFG_TS_TMR_EN != DEF_DISABLED) && \
+        (CPU_CFG_TS_TMR_EN != DEF_ENABLED ))
+#error  "CPU_CFG_TS_TMR_EN               illegally #define'd in 'cpu_core.h'"
+#error  "                                [MUST be  DEF_DISABLED]            "
+#error  "                                [     ||  DEF_ENABLED ]            "
+
+
+#elif   (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
+
+#ifndef  CPU_CFG_TS_TMR_SIZE
+#error  "CPU_CFG_TS_TMR_SIZE                   not #define'd in 'cpu_cfg.h'       "
+#error  "                                [MUST be  CPU_WORD_SIZE_08   8-bit timer]"
+#error  "                                [     ||  CPU_WORD_SIZE_16  16-bit timer]"
+#error  "                                [     ||  CPU_WORD_SIZE_32  32-bit timer]"
+#error  "                                [     ||  CPU_WORD_SIZE_64  64-bit timer]"
+
+#elif  ((CPU_CFG_TS_TMR_SIZE != CPU_WORD_SIZE_08) && \
+        (CPU_CFG_TS_TMR_SIZE != CPU_WORD_SIZE_16) && \
+        (CPU_CFG_TS_TMR_SIZE != CPU_WORD_SIZE_32) && \
+        (CPU_CFG_TS_TMR_SIZE != CPU_WORD_SIZE_64))
+#error  "CPU_CFG_TS_TMR_SIZE             illegally #define'd in 'cpu_cfg.h'       "
+#error  "                                [MUST be  CPU_WORD_SIZE_08   8-bit timer]"
+#error  "                                [     ||  CPU_WORD_SIZE_16  16-bit timer]"
+#error  "                                [     ||  CPU_WORD_SIZE_32  32-bit timer]"
+#error  "                                [     ||  CPU_WORD_SIZE_64  64-bit timer]"
+#endif
+
+#endif
+
+
+
+#ifndef  CPU_CFG_INT_DIS_MEAS_EN
+#if 0                                                           /* Optionally configured in 'cpu_cfg.h'; DO NOT MODIFY. */
+#error  "CPU_CFG_INT_DIS_MEAS_EN               not #define'd in 'cpu_cfg.h'"
+#endif
+
+#else
+
+#ifndef  CPU_CFG_INT_DIS_MEAS_OVRHD_NBR
+#error  "CPU_CFG_INT_DIS_MEAS_OVRHD_NBR        not #define'd in 'cpu_cfg.h' "
+#error  "                                [MUST be  >= CPU_TIME_MEAS_NBR_MIN]"
+#error  "                                [     ||  <= CPU_TIME_MEAS_NBR_MAX]"
+
+#elif   (DEF_CHK_VAL(CPU_CFG_INT_DIS_MEAS_OVRHD_NBR, \
+                     CPU_TIME_MEAS_NBR_MIN,          \
+                     CPU_TIME_MEAS_NBR_MAX) != DEF_OK)
+#error  "CPU_CFG_INT_DIS_MEAS_OVRHD_NBR  illegally #define'd in 'cpu_cfg.h' "
+#error  "                                [MUST be  >= CPU_TIME_MEAS_NBR_MIN]"
+#error  "                                [     ||  <= CPU_TIME_MEAS_NBR_MAX]"
+
+#endif
+
+#endif
+
+
+
+
+#ifndef  CPU_CFG_LEAD_ZEROS_ASM_PRESENT
+#if 0                                                           /* Optionally configured in 'cpu_cfg.h'; DO NOT MODIFY. */
+#error  "CPU_CFG_LEAD_ZEROS_ASM_PRESENT        not #define'd in 'cpu.h'/'cpu_cfg.h'"
+#endif
+#endif
+
+
+#ifndef  CPU_CFG_TRAIL_ZEROS_ASM_PRESENT
+#if 0                                                           /* Optionally configured in 'cpu_cfg.h'; DO NOT MODIFY. */
+#error  "CPU_CFG_TRAIL_ZEROS_ASM_PRESENT       not #define'd in 'cpu.h'/'cpu_cfg.h'"
+#endif
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                    CPU PORT CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_CFG_ADDR_SIZE
+#error  "CPU_CFG_ADDR_SIZE      not #define'd in 'cpu.h'"
+#endif
+
+#ifndef  CPU_CFG_DATA_SIZE
+#error  "CPU_CFG_DATA_SIZE      not #define'd in 'cpu.h'"
+#endif
+
+#ifndef  CPU_CFG_DATA_SIZE_MAX
+#error  "CPU_CFG_DATA_SIZE_MAX  not #define'd in 'cpu.h'"
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                    LIBRARY CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+                                                                /* See 'cpu_core.h  Note #1a'.                          */
+#if     (LIB_VERSION < 13500u)
+#error  "LIB_VERSION  [SHOULD be >= V1.35.00]"
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*
+* Note(s) : (1) See 'cpu_core.h  MODULE'.
+*********************************************************************************************************
+*/
+
+#endif                                                          /* End of CPU core module include.                      */
+

+ 220 - 0
MiddleWare/uCOS_II/uC-CPU/cpu_def.h

@@ -0,0 +1,220 @@
+/*
+*********************************************************************************************************
+*                                                uC/CPU
+*                                    CPU CONFIGURATION & PORT LAYER
+*
+*                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*
+*               uC/CPU is provided in source form to registered licensees ONLY.  It is 
+*               illegal to distribute this source code to any third party unless you receive 
+*               written permission by an authorized Micrium representative.  Knowledge of 
+*               the source code may NOT be used to develop a similar product.
+*
+*               Please help us continue to provide the Embedded community with the finest 
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                      CPU CONFIGURATION DEFINES
+*
+* Filename      : cpu_def.h
+* Version       : V1.30.02
+* Programmer(s) : ITJ
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*
+* Note(s) : (1) This CPU definition header file is protected from multiple pre-processor inclusion 
+*               through use of the CPU definition module present pre-processor macro definition.
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_DEF_MODULE_PRESENT
+#define  CPU_DEF_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*                                   CORE CPU MODULE VERSION NUMBER
+*
+* Note(s) : (1) (a) The core CPU module software version is denoted as follows :
+*
+*                       Vx.yy.zz
+*
+*                           where
+*                                   V               denotes 'Version' label
+*                                   x               denotes     major software version revision number
+*                                   yy              denotes     minor software version revision number
+*                                   zz              denotes sub-minor software version revision number
+*
+*               (b) The software version label #define is formatted as follows :
+*
+*                       ver = x.yyzz * 100 * 100
+*
+*                           where
+*                                   ver             denotes software version number scaled as an integer value
+*                                   x.yyzz          denotes software version number, where the unscaled integer 
+*                                                       portion denotes the major version number & the unscaled 
+*                                                       fractional portion denotes the (concatenated) minor 
+*                                                       version numbers
+*********************************************************************************************************
+*/
+
+#define  CPU_CORE_VERSION                              13002u   /* See Note #1.                                         */
+
+
+/*
+*********************************************************************************************************
+*                                       CPU WORD CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_ADDR_SIZE & CPU_CFG_DATA_SIZE in 'cpu.h' with CPU's word sizes :
+*
+*                   CPU_WORD_SIZE_08             8-bit word size
+*                   CPU_WORD_SIZE_16            16-bit word size
+*                   CPU_WORD_SIZE_32            32-bit word size
+*                   CPU_WORD_SIZE_64            64-bit word size
+*
+*           (2) Configure CPU_CFG_ENDIAN_TYPE in 'cpu.h' with CPU's data-word-memory order :
+*
+*               (a) CPU_ENDIAN_TYPE_BIG         Big-   endian word order (CPU words' most  significant
+*                                                                         octet @ lowest memory address)
+*               (b) CPU_ENDIAN_TYPE_LITTLE      Little-endian word order (CPU words' least significant
+*                                                                         octet @ lowest memory address)
+*********************************************************************************************************
+*/
+
+                                                        /* ---------------------- CPU WORD SIZE ----------------------- */
+#define  CPU_WORD_SIZE_08                          1u   /*  8-bit word size (in octets).                                */
+#define  CPU_WORD_SIZE_16                          2u   /* 16-bit word size (in octets).                                */
+#define  CPU_WORD_SIZE_32                          4u   /* 32-bit word size (in octets).                                */
+#define  CPU_WORD_SIZE_64                          8u   /* 64-bit word size (in octets).                                */
+
+
+                                                        /* ------------------ CPU WORD-ENDIAN ORDER ------------------- */
+#define  CPU_ENDIAN_TYPE_NONE                      0u
+#define  CPU_ENDIAN_TYPE_BIG                       1u   /* Big-   endian word order (see Note #1a).                     */
+#define  CPU_ENDIAN_TYPE_LITTLE                    2u   /* Little-endian word order (see Note #1b).                     */
+
+
+/*
+*********************************************************************************************************
+*                                       CPU STACK CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_STK_GROWTH in 'cpu.h' with CPU's stack growth order :
+*
+*               (a) CPU_STK_GROWTH_LO_TO_HI     CPU stack pointer increments to the next higher  stack 
+*                                                   memory address after data is pushed onto the stack
+*               (b) CPU_STK_GROWTH_HI_TO_LO     CPU stack pointer decrements to the next lower   stack 
+*                                                   memory address after data is pushed onto the stack
+*********************************************************************************************************
+*/
+
+                                                        /* ------------------ CPU STACK GROWTH ORDER ------------------ */
+#define  CPU_STK_GROWTH_NONE                       0u
+#define  CPU_STK_GROWTH_LO_TO_HI                   1u   /* CPU stk incs towards higher mem addrs (see Note #1a).        */
+#define  CPU_STK_GROWTH_HI_TO_LO                   2u   /* CPU stk decs towards lower  mem addrs (see Note #1b).        */
+
+
+/*
+*********************************************************************************************************
+*                                   CRITICAL SECTION CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_CRITICAL_METHOD with CPU's/compiler's critical section method :
+*
+*                                                       Enter/Exit critical sections by ...
+*
+*                   CPU_CRITICAL_METHOD_INT_DIS_EN      Disable/Enable interrupts
+*                   CPU_CRITICAL_METHOD_STATUS_STK      Push/Pop       interrupt status onto stack
+*                   CPU_CRITICAL_METHOD_STATUS_LOCAL    Save/Restore   interrupt status to local variable
+*
+*               (a) CPU_CRITICAL_METHOD_INT_DIS_EN  is NOT a preferred method since it does NOT support
+*                   multiple levels of interrupts.  However, with some CPUs/compilers, this is the only
+*                   available method.
+*
+*               (b) CPU_CRITICAL_METHOD_STATUS_STK    is one preferred method since it supports multiple
+*                   levels of interrupts.  However, this method assumes that the compiler provides C-level
+*                   &/or assembly-level functionality for the following :
+*
+*                     ENTER CRITICAL SECTION :
+*                       (1) Push/save   interrupt status onto a local stack
+*                       (2) Disable     interrupts
+*
+*                     EXIT  CRITICAL SECTION :
+*                       (3) Pop/restore interrupt status from a local stack
+*
+*               (c) CPU_CRITICAL_METHOD_STATUS_LOCAL  is one preferred method since it supports multiple
+*                   levels of interrupts.  However, this method assumes that the compiler provides C-level
+*                   &/or assembly-level functionality for the following :
+*
+*                     ENTER CRITICAL SECTION :
+*                       (1) Save    interrupt status into a local variable
+*                       (2) Disable interrupts
+*
+*                     EXIT  CRITICAL SECTION :
+*                       (3) Restore interrupt status from a local variable
+*
+*           (2) Critical section macro's most likely require inline assembly.  If the compiler does NOT
+*               allow inline assembly in C source files, critical section macro's MUST call an assembly
+*               subroutine defined in a 'cpu_a.asm' file located in the following software directory :
+*
+*                   \<CPU-Compiler Directory>\<cpu>\<compiler>\
+*
+*                       where
+*                               <CPU-Compiler Directory>    directory path for common   CPU-compiler software
+*                               <cpu>                       directory name for specific CPU
+*                               <compiler>                  directory name for specific compiler
+*
+*           (3) (a) To save/restore interrupt status, a local variable 'cpu_sr' of type 'CPU_SR' MAY need 
+*                   to be declared (e.g. if 'CPU_CRITICAL_METHOD_STATUS_LOCAL' method is configured).
+*
+*                   (1) 'cpu_sr' local variable SHOULD be declared via the CPU_SR_ALLOC() macro which, 
+*                        if used, MUST be declared following ALL other local variables (see any 'cpu.h  
+*                        CRITICAL SECTION CONFIGURATION  Note #3a1').
+*
+*                        Example :
+*
+*                           void  Fnct (void)
+*                           {
+*                               CPU_INT08U  val_08;
+*                               CPU_INT16U  val_16;
+*                               CPU_INT32U  val_32;
+*                               CPU_SR_ALLOC();         MUST be declared after ALL other local variables
+*                                   :
+*                                   :
+*                           }
+*
+*               (b) Configure 'CPU_SR' data type with the appropriate-sized CPU data type large enough to 
+*                   completely store the CPU's/compiler's status word.
+*********************************************************************************************************
+*/
+
+                                                        /* --------------- CPU CRITICAL SECTION METHODS --------------- */
+#define  CPU_CRITICAL_METHOD_NONE                  0u   /*                                                              */
+#define  CPU_CRITICAL_METHOD_INT_DIS_EN            1u   /* DIS/EN       ints                    (see Note #1a).         */
+#define  CPU_CRITICAL_METHOD_STATUS_STK            2u   /* Push/Pop     int status onto stk     (see Note #1b).         */
+#define  CPU_CRITICAL_METHOD_STATUS_LOCAL          3u   /* Save/Restore int status to local var (see Note #1c).         */
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*
+* Note(s) : (1) See 'cpu_def.h  MODULE'.
+*********************************************************************************************************
+*/
+
+#endif                                                  /* End of CPU def module include.                               */
+

+ 309 - 0
MiddleWare/uCOS_II/uC-LIB/Ports/ARM-Cortex-M4/GNU/lib_mem_a.S

@@ -0,0 +1,309 @@
+@********************************************************************************************************
+@                                                uC/LIB
+@                                        CUSTOM LIBRARY MODULES
+@
+@                          (c) Copyright 2004-2011; Micrium, Inc.; Weston, FL
+@
+@               All rights reserved.  Protected by international copyright laws.
+@
+@               uC/LIB is provided in source form to registered licensees ONLY.  It is
+@               illegal to distribute this source code to any third party unless you receive
+@               written permission by an authorized Micrium representative.  Knowledge of
+@               the source code may NOT be used to develop a similar product.
+@
+@               Please help us continue to provide the Embedded community with the finest
+@               software available.  Your honesty is greatly appreciated.
+@
+@               You can contact us at www.micrium.com.
+@********************************************************************************************************
+
+
+@********************************************************************************************************
+@
+@                                     STANDARD MEMORY OPERATIONS
+@
+@                                           ARM-Cortex-M4
+@                                           GNU Compiler
+@
+@ Filename      : lib_mem_a.s
+@ Version       : V1.38.01.00
+@ Programmer(s) : JDH
+@                 DC
+@********************************************************************************************************
+@ Note(s)       : (1) NO compiler-supplied standard library functions are used in library or product software.
+@
+@                     (a) ALL standard library functions are implemented in the custom library modules :
+@
+@                         (1) \<Custom Library Directory>\lib*.*
+@
+@                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+@
+@                               where
+@                                       <Custom Library Directory>      directory path for custom library software
+@                                       <cpu>                           directory name for specific processor (CPU)
+@                                       <compiler>                      directory name for specific compiler
+@
+@                     (b) Product-specific library functions are implemented in individual products.
+@
+@                 (2) Assumes ARM CPU mode configured for Little Endian.
+@********************************************************************************************************
+
+
+@********************************************************************************************************
+@                                           PUBLIC FUNCTIONS
+@********************************************************************************************************
+
+.global  Mem_Copy
+
+
+@********************************************************************************************************
+@                                      CODE GENERATION DIRECTIVES
+@********************************************************************************************************
+
+.text
+.align 2
+.thumb
+.syntax unified
+
+@$PAGE
+@********************************************************************************************************
+@                                             Mem_Copy()
+@
+@ Description : Copy data octets from one buffer to another buffer.
+@
+@ Argument(s) : pdest       Pointer to destination memory buffer.
+@
+@               psrc        Pointer to source      memory buffer.
+@
+@               size        Number of data buffer octets to copy.
+@
+@ Return(s)   : none.
+@
+@ Caller(s)   : Application.
+@
+@ Note(s)     : (1) Null copies allowed (i.e. 0-octet size).
+@
+@               (2) Memory buffers NOT checked for overlapping.
+@
+@               (3) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
+@                   address boundary.
+@
+@               (4) ARM Cortex-M3 processors use a subset of the ARM Thumb-2 instruction set which does
+@                   NOT support 16-bit conditional branch instructions but ONLY supports 8-bit conditional
+@                   branch instructions.
+@
+@                   Therefore, branches exceeding 8-bit, signed, relative offsets :
+@
+@                   (a) CANNOT be implemented with     conditional branches@ but ...
+@                   (b) MUST   be implemented with non-conditional branches.
+@********************************************************************************************************
+
+@ void  Mem_Copy (void        *pdest,       @  ==>  R0
+@                 void        *psrc,        @  ==>  R1
+@                 CPU_SIZE_T   size)        @  ==>  R2
+
+.thumb_func
+Mem_Copy:
+        CMP         R0, #0
+        BNE         Mem_Copy_1
+        BX          LR                      @ return if pdest == NULL
+
+Mem_Copy_1:
+        CMP         R1, #0
+        BNE         Mem_Copy_2
+        BX          LR                      @ return if psrc  == NULL
+
+Mem_Copy_2:
+        CMP         R2, #0
+        BNE         Mem_Copy_3
+        BX          LR                      @ return if size  == 0
+
+Mem_Copy_3:
+        STMFD       SP!, {R3-R12}           @ save registers on stack
+
+
+@$PAGE
+Chk_Align_32:                               @ check if both dest & src 32-bit aligned
+        AND         R3, R0, #0x03
+        AND         R4, R1, #0x03
+        CMP         R3, R4
+        BNE         Chk_Align_16            @ not 32-bit aligned, check for 16-bit alignment
+
+        RSB         R3, R3, #0x04           @ compute 1-2-3 pre-copy bytes (to align to the next 32-bit boundary)
+        AND         R3, R3, #0x03
+
+Pre_Copy_1:
+        CMP         R3, #1                  @ copy 1-2-3 bytes (to align to the next 32-bit boundary)
+        BCC         Copy_32_1               @ start real 32-bit copy
+        CMP         R2, #1                  @ check if any more data to copy
+        BCS         Pre_Copy_1_Cont
+        B           Mem_Copy_END            @           no more data to copy (see Note #4b)
+
+Pre_Copy_1_Cont:
+        LDRB        R4, [R1], #1
+        STRB        R4, [R0], #1
+        SUB         R3, R3, #1
+        SUB         R2, R2, #1
+        B           Pre_Copy_1
+
+
+Chk_Align_16:                               @ check if both dest & src 16-bit aligned
+        AND         R3, R0, #0x01
+        AND         R4, R1, #0x01
+        CMP         R3, R4
+        BEQ         Pre_Copy_2
+        B           Copy_08_1               @ not 16-bit aligned, start 8-bit copy (see Note #4b)
+
+Pre_Copy_2:
+        CMP         R3, #1                  @ copy 1 byte (to align to the next 16-bit boundary)
+        BCC         Copy_16_1               @ start real 16-bit copy
+
+        LDRB        R4, [R1], #1
+        STRB        R4, [R0], #1
+        SUB         R3, R3, #1
+        SUB         R2, R2, #1
+        B           Pre_Copy_2
+
+
+Copy_32_1:
+        CMP         R2, #360                @ Copy 9 chunks of 10 32-bit words (360 octets per loop)
+        BCC         Copy_32_2
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        SUB         R2, R2, #360
+        B           Copy_32_1
+
+Copy_32_2:
+        CMP         R2, #(04*10*01)         @ Copy chunks of 10 32-bit words (40 octets per loop)
+        BCC         Copy_32_3
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        SUB         R2, R2, #(04*10*01)
+        B           Copy_32_2
+
+Copy_32_3:
+        CMP         R2, #(04*01*01)         @ Copy remaining 32-bit words
+        BCC         Copy_16_1
+        LDR         R3, [R1], #4
+        STR         R3, [R0], #4
+        SUB         R2, R2, #(04*01*01)
+        B           Copy_32_3
+
+@$PAGE
+Copy_16_1:
+        CMP         R2, #(02*01*16)         @ Copy chunks of 16 16-bit words (32 bytes per loop)
+        BCC         Copy_16_2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        SUB         R2, R2, #(02*01*16)
+        B           Copy_16_1
+
+Copy_16_2:
+        CMP         R2, #(02*01*01)         @ Copy remaining 16-bit words
+        BCC         Copy_08_1
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        SUB         R2, R2, #(02*01*01)
+        B           Copy_16_2
+
+@$PAGE
+Copy_08_1:
+        CMP         R2, #(01*01*16)         @ Copy chunks of 16 8-bit words (16 bytes per loop)
+        BCC         Copy_08_2
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        SUB         R2, R2, #(01*01*16)
+        B           Copy_08_1
+
+Copy_08_2:
+        CMP         R2, #(01*01*01)         @ Copy remaining 8-bit words
+        BCC         Mem_Copy_END
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        SUB         R2, R2, #(01*01*01)
+        B           Copy_08_2
+
+
+Mem_Copy_END:
+        LDMFD       SP!, {R3-R12}           @ restore registers from stack
+        BX          LR                      @ return
+
+
+.end
+

+ 306 - 0
MiddleWare/uCOS_II/uC-LIB/Ports/ARM-Cortex-M4/IAR/lib_mem_a.asm

@@ -0,0 +1,306 @@
+;********************************************************************************************************
+;                                                uC/LIB
+;                                        CUSTOM LIBRARY MODULES
+;
+;                          (c) Copyright 2004-2011; Micrium, Inc.; Weston, FL
+;
+;               All rights reserved.  Protected by international copyright laws.
+;
+;               uC/LIB is provided in source form to registered licensees ONLY.  It is
+;               illegal to distribute this source code to any third party unless you receive
+;               written permission by an authorized Micrium representative.  Knowledge of
+;               the source code may NOT be used to develop a similar product.
+;
+;               Please help us continue to provide the Embedded community with the finest
+;               software available.  Your honesty is greatly appreciated.
+;
+;               You can contact us at www.micrium.com.
+;********************************************************************************************************
+
+
+;********************************************************************************************************
+;
+;                                     STANDARD MEMORY OPERATIONS
+;
+;                                           ARM-Cortex-M4
+;                                           IAR Compiler
+;
+; Filename      : lib_mem_a.asm
+; Version       : V1.38.01.00
+; Programmer(s) : JDH
+;                 BAN
+;********************************************************************************************************
+; Note(s)       : (1) NO compiler-supplied standard library functions are used in library or product software.
+;
+;                     (a) ALL standard library functions are implemented in the custom library modules :
+;
+;                         (1) \<Custom Library Directory>\lib*.*
+;
+;                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+;
+;                               where
+;                                       <Custom Library Directory>      directory path for custom library software
+;                                       <cpu>                           directory name for specific processor (CPU)
+;                                       <compiler>                      directory name for specific compiler
+;
+;                     (b) Product-specific library functions are implemented in individual products.
+;
+;                 (2) Assumes ARM CPU mode configured for Little Endian.
+;********************************************************************************************************
+
+
+;********************************************************************************************************
+;                                           PUBLIC FUNCTIONS
+;********************************************************************************************************
+
+        PUBLIC  Mem_Copy
+
+
+;********************************************************************************************************
+;                                      CODE GENERATION DIRECTIVES
+;********************************************************************************************************
+
+        RSEG CODE:CODE:NOROOT(2)
+
+
+;$PAGE
+;********************************************************************************************************
+;                                             Mem_Copy()
+;
+; Description : Copy data octets from one buffer to another buffer.
+;
+; Argument(s) : pdest       Pointer to destination memory buffer.
+;
+;               psrc        Pointer to source      memory buffer.
+;
+;               size        Number of data buffer octets to copy.
+;
+; Return(s)   : none.
+;
+; Caller(s)   : Application.
+;
+; Note(s)     : (1) Null copies allowed (i.e. 0-octet size).
+;
+;               (2) Memory buffers NOT checked for overlapping.
+;
+;               (3) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
+;                   address boundary.
+;
+;               (4) ARM Cortex-M3 processors use a subset of the ARM Thumb-2 instruction set which does
+;                   NOT support 16-bit conditional branch instructions but ONLY supports 8-bit conditional
+;                   branch instructions.
+;
+;                   Therefore, branches exceeding 8-bit, signed, relative offsets :
+;
+;                   (a) CANNOT be implemented with     conditional branches; but ...
+;                   (b) MUST   be implemented with non-conditional branches.
+;********************************************************************************************************
+
+; void  Mem_Copy (void        *pdest,       ;  ==>  R0
+;                 void        *psrc,        ;  ==>  R1
+;                 CPU_SIZE_T   size)        ;  ==>  R2
+
+Mem_Copy:
+        CMP         R0, #0
+        BNE         Mem_Copy_1
+        BX          LR                      ; return if pdest == NULL
+
+Mem_Copy_1:
+        CMP         R1, #0
+        BNE         Mem_Copy_2
+        BX          LR                      ; return if psrc  == NULL
+
+Mem_Copy_2:
+        CMP         R2, #0
+        BNE         Mem_Copy_3
+        BX          LR                      ; return if size  == 0
+
+Mem_Copy_3:
+        STMFD       SP!, {R3-R12}           ; save registers on stack
+
+
+;$PAGE
+Chk_Align_32:                               ; check if both dest & src 32-bit aligned
+        AND         R3, R0, #0x03
+        AND         R4, R1, #0x03
+        CMP         R3, R4
+        BNE         Chk_Align_16            ; not 32-bit aligned, check for 16-bit alignment
+
+        RSB         R3, R3, #0x04           ; compute 1-2-3 pre-copy bytes (to align to the next 32-bit boundary)
+        AND         R3, R3, #0x03
+
+Pre_Copy_1:
+        CMP         R3, #1                  ; copy 1-2-3 bytes (to align to the next 32-bit boundary)
+        BCC         Copy_32_1               ; start real 32-bit copy
+        CMP         R2, #1                  ; check if any more data to copy
+        BCS         Pre_Copy_1_Cont
+        B           Mem_Copy_END            ;           no more data to copy (see Note #4b)
+
+Pre_Copy_1_Cont:
+        LDRB        R4, [R1], #1
+        STRB        R4, [R0], #1
+        SUB         R3, R3, #1
+        SUB         R2, R2, #1
+        B           Pre_Copy_1
+
+
+Chk_Align_16:                               ; check if both dest & src 16-bit aligned
+        AND         R3, R0, #0x01
+        AND         R4, R1, #0x01
+        CMP         R3, R4
+        BEQ         Pre_Copy_2
+        B           Copy_08_1               ; not 16-bit aligned, start 8-bit copy (see Note #4b)
+
+Pre_Copy_2:
+        CMP         R3, #1                  ; copy 1 byte (to align to the next 16-bit boundary)
+        BCC         Copy_16_1               ; start real 16-bit copy
+
+        LDRB        R4, [R1], #1
+        STRB        R4, [R0], #1
+        SUB         R3, R3, #1
+        SUB         R2, R2, #1
+        B           Pre_Copy_2
+
+
+Copy_32_1:
+        CMP         R2, #(04*10*09)         ; Copy 9 chunks of 10 32-bit words (360 octets per loop)
+        BCC         Copy_32_2
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        SUB         R2, R2, #(04*10*09)
+        B           Copy_32_1
+
+Copy_32_2:
+        CMP         R2, #(04*10*01)         ; Copy chunks of 10 32-bit words (40 octets per loop)
+        BCC         Copy_32_3
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        SUB         R2, R2, #(04*10*01)
+        B           Copy_32_2
+
+Copy_32_3:
+        CMP         R2, #(04*01*01)         ; Copy remaining 32-bit words
+        BCC         Copy_16_1
+        LDR         R3, [R1], #4
+        STR         R3, [R0], #4
+        SUB         R2, R2, #(04*01*01)
+        B           Copy_32_3
+
+;$PAGE
+Copy_16_1:
+        CMP         R2, #(02*01*16)         ; Copy chunks of 16 16-bit words (32 bytes per loop)
+        BCC         Copy_16_2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        SUB         R2, R2, #(02*01*16)
+        B           Copy_16_1
+
+Copy_16_2:
+        CMP         R2, #(02*01*01)         ; Copy remaining 16-bit words
+        BCC         Copy_08_1
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        SUB         R2, R2, #(02*01*01)
+        B           Copy_16_2
+
+;$PAGE
+Copy_08_1:
+        CMP         R2, #(01*01*16)         ; Copy chunks of 16 8-bit words (16 bytes per loop)
+        BCC         Copy_08_2
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        SUB         R2, R2, #(01*01*16)
+        B           Copy_08_1
+
+Copy_08_2:
+        CMP         R2, #(01*01*01)         ; Copy remaining 8-bit words
+        BCC         Mem_Copy_END
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        SUB         R2, R2, #(01*01*01)
+        B           Copy_08_2
+
+
+Mem_Copy_END:
+        LDMFD       SP!, {R3-R12}           ; restore registers from stack
+        BX          LR                      ; return
+
+
+        END
+

+ 312 - 0
MiddleWare/uCOS_II/uC-LIB/Ports/ARM-Cortex-M4/RealView/lib_mem_a.asm

@@ -0,0 +1,312 @@
+;********************************************************************************************************
+;                                                uC/LIB
+;                                        CUSTOM LIBRARY MODULES
+;
+;                          (c) Copyright 2004-2011; Micrium, Inc.; Weston, FL
+;
+;               All rights reserved.  Protected by international copyright laws.
+;
+;               uC/LIB is provided in source form to registered licensees ONLY.  It is
+;               illegal to distribute this source code to any third party unless you receive
+;               written permission by an authorized Micrium representative.  Knowledge of
+;               the source code may NOT be used to develop a similar product.
+;
+;               Please help us continue to provide the Embedded community with the finest
+;               software available.  Your honesty is greatly appreciated.
+;
+;               You can contact us at www.micrium.com.
+;********************************************************************************************************
+
+
+;********************************************************************************************************
+;
+;                                     STANDARD MEMORY OPERATIONS
+;
+;                                           ARM-Cortex-M4
+;                                     RealView Development Suite
+;                            RealView Microcontroller Development Kit (MDK)
+;                                      ARM Developer Suite (ADS)
+;                                           Keil uVision
+;
+; Filename      : lib_mem_a.asm
+; Version       : V1.38.01.00
+; Programmer(s) : JDH
+;                 BAN
+;********************************************************************************************************
+; Note(s)       : (1) NO compiler-supplied standard library functions are used in library or product software.
+;
+;                     (a) ALL standard library functions are implemented in the custom library modules :
+;
+;                         (1) \<Custom Library Directory>\lib*.*
+;
+;                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+;
+;                               where
+;                                       <Custom Library Directory>      directory path for custom library software
+;                                       <cpu>                           directory name for specific processor (CPU)
+;                                       <compiler>                      directory name for specific compiler
+;
+;                     (b) Product-specific library functions are implemented in individual products.
+;
+;                 (2) Assumes ARM CPU mode configured for Little Endian.
+;********************************************************************************************************
+
+
+;********************************************************************************************************
+;                                           PUBLIC FUNCTIONS
+;********************************************************************************************************
+
+        EXPORT  Mem_Copy
+
+
+;********************************************************************************************************
+;                                      CODE GENERATION DIRECTIVES
+;********************************************************************************************************
+
+        AREA |.text|, CODE, READONLY, ALIGN=2
+        THUMB
+        REQUIRE8
+        PRESERVE8
+
+
+;$PAGE
+;********************************************************************************************************
+;                                             Mem_Copy()
+;
+; Description : Copy data octets from one buffer to another buffer.
+;
+; Argument(s) : pdest       Pointer to destination memory buffer.
+;
+;               psrc        Pointer to source      memory buffer.
+;
+;               size        Number of data buffer octets to copy.
+;
+; Return(s)   : none.
+;
+; Caller(s)   : Application.
+;
+; Note(s)     : (1) Null copies allowed (i.e. 0-octet size).
+;
+;               (2) Memory buffers NOT checked for overlapping.
+;
+;               (3) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
+;                   address boundary.
+;
+;               (4) ARM Cortex-M3 processors use a subset of the ARM Thumb-2 instruction set which does
+;                   NOT support 16-bit conditional branch instructions but ONLY supports 8-bit conditional
+;                   branch instructions.
+;
+;                   Therefore, branches exceeding 8-bit, signed, relative offsets :
+;
+;                   (a) CANNOT be implemented with     conditional branches; but ...
+;                   (b) MUST   be implemented with non-conditional branches.
+;********************************************************************************************************
+
+; void  Mem_Copy (void        *pdest,       ;  ==>  R0
+;                 void        *psrc,        ;  ==>  R1
+;                 CPU_SIZE_T   size)        ;  ==>  R2
+
+Mem_Copy
+        CMP         R0, #0
+        BNE         Mem_Copy_1
+        BX          LR                      ; return if pdest == NULL
+
+Mem_Copy_1
+        CMP         R1, #0
+        BNE         Mem_Copy_2
+        BX          LR                      ; return if psrc  == NULL
+
+Mem_Copy_2
+        CMP         R2, #0
+        BNE         Mem_Copy_3
+        BX          LR                      ; return if size  == 0
+
+Mem_Copy_3
+        STMFD       SP!, {R3-R12}           ; save registers on stack
+
+
+;$PAGE
+Chk_Align_32                                ; check if both dest & src 32-bit aligned
+        AND         R3, R0, #0x03
+        AND         R4, R1, #0x03
+        CMP         R3, R4
+        BNE         Chk_Align_16            ; not 32-bit aligned, check for 16-bit alignment
+
+        RSB         R3, R3, #0x04           ; compute 1-2-3 pre-copy bytes (to align to the next 32-bit boundary)
+        AND         R3, R3, #0x03
+
+Pre_Copy_1
+        CMP         R3, #1                  ; copy 1-2-3 bytes (to align to the next 32-bit boundary)
+        BCC         Copy_32_1               ; start real 32-bit copy
+        CMP         R2, #1                  ; check if any more data to copy
+        BCS         Pre_Copy_1_Cont
+        B           Mem_Copy_END            ;           no more data to copy (see Note #4b)
+
+Pre_Copy_1_Cont
+        LDRB        R4, [R1], #1
+        STRB        R4, [R0], #1
+        SUB         R3, R3, #1
+        SUB         R2, R2, #1
+        B           Pre_Copy_1
+
+
+Chk_Align_16                                ; check if both dest & src 16-bit aligned
+        AND         R3, R0, #0x01
+        AND         R4, R1, #0x01
+        CMP         R3, R4
+        BEQ         Pre_Copy_2
+        B           Copy_08_1               ; not 16-bit aligned, start 8-bit copy (see Note #4b)
+
+Pre_Copy_2
+        CMP         R3, #1                  ; copy 1 byte (to align to the next 16-bit boundary)
+        BCC         Copy_16_1               ; start real 16-bit copy
+
+        LDRB        R4, [R1], #1
+        STRB        R4, [R0], #1
+        SUB         R3, R3, #1
+        SUB         R2, R2, #1
+        B           Pre_Copy_2
+
+
+Copy_32_1
+        CMP         R2, #(04*10*09)         ; Copy 9 chunks of 10 32-bit words (360 octets per loop)
+        BCC         Copy_32_2
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        SUB         R2, R2, #(04*10*09)
+        B           Copy_32_1
+
+Copy_32_2
+        CMP         R2, #(04*10*01)         ; Copy chunks of 10 32-bit words (40 octets per loop)
+        BCC         Copy_32_3
+        LDMIA       R1!, {R3-R12}
+        STMIA       R0!, {R3-R12}
+        SUB         R2, R2, #(04*10*01)
+        B           Copy_32_2
+
+Copy_32_3
+        CMP         R2, #(04*01*01)         ; Copy remaining 32-bit words
+        BCC         Copy_16_1
+        LDR         R3, [R1], #4
+        STR         R3, [R0], #4
+        SUB         R2, R2, #(04*01*01)
+        B           Copy_32_3
+
+;$PAGE
+Copy_16_1
+        CMP         R2, #(02*01*16)         ; Copy chunks of 16 16-bit words (32 bytes per loop)
+        BCC         Copy_16_2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        SUB         R2, R2, #(02*01*16)
+        B           Copy_16_1
+
+Copy_16_2
+        CMP         R2, #(02*01*01)         ; Copy remaining 16-bit words
+        BCC         Copy_08_1
+        LDRH        R3, [R1], #2
+        STRH        R3, [R0], #2
+        SUB         R2, R2, #(02*01*01)
+        B           Copy_16_2
+
+;$PAGE
+Copy_08_1
+        CMP         R2, #(01*01*16)         ; Copy chunks of 16 8-bit words (16 bytes per loop)
+        BCC         Copy_08_2
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        SUB         R2, R2, #(01*01*16)
+        B           Copy_08_1
+
+Copy_08_2
+        CMP         R2, #(01*01*01)         ; Copy remaining 8-bit words
+        BCC         Mem_Copy_END
+        LDRB        R3, [R1], #1
+        STRB        R3, [R0], #1
+        SUB         R2, R2, #(01*01*01)
+        B           Copy_08_2
+
+
+Mem_Copy_END
+        LDMFD       SP!, {R3-R12}           ; restore registers from stack
+        BX          LR                      ; return
+
+
+        END
+

+ 655 - 0
MiddleWare/uCOS_II/uC-LIB/lib_ascii.c

@@ -0,0 +1,655 @@
+/*
+*********************************************************************************************************
+*                                                uC/LIB
+*                                        CUSTOM LIBRARY MODULES
+*
+*                         (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL
+*
+*                  All rights reserved.  Protected by international copyright laws.
+*
+*                  uC/LIB is provided in source form to registered licensees ONLY.  It is
+*                  illegal to distribute this source code to any third party unless you receive
+*                  written permission by an authorized Micrium representative.  Knowledge of
+*                  the source code may NOT be used to develop a similar product.
+*
+*                  Please help us continue to provide the Embedded community with the finest
+*                  software available.  Your honesty is greatly appreciated.
+*
+*                  You can find our product's user manual, API reference, release notes and
+*                  more information at: https://doc.micrium.com
+*
+*                  You can contact us at: http://www.micrium.com
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                     ASCII CHARACTER OPERATIONS
+*
+* Filename      : lib_ascii.c
+* Version       : V1.38.01
+* Programmer(s) : BAN
+*                 ITJ
+*********************************************************************************************************
+* Note(s)       : (1) NO compiler-supplied standard library functions are used in library or product software.
+*
+*                     (a) ALL standard library functions are implemented in the custom library modules :
+*
+*                         (1) \<Custom Library Directory>\lib_*.*
+*
+*                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+*
+*                               where
+*                                       <Custom Library Directory>      directory path for custom library software
+*                                       <cpu>                           directory name for specific processor (CPU)
+*                                       <compiler>                      directory name for specific compiler
+*
+*                     (b) Product-specific library functions are implemented in individual products.
+*
+*
+*                 (2) (a) ECMA-6 '7-Bit coded Character Set' (6th edition), which corresponds to the
+*                         3rd edition of ISO 646, specifies several versions of a 7-bit character set :
+*
+*                         (1) THE GENERAL VERSION, which allows characters at 0x23 and 0x24 to be given a
+*                             set alternate form and allows the characters 0x40, 0x5B, 0x5D, 0x60, 0x7B &
+*                             0x7D to be assigned a "unique graphic character" or to be declared as unused.
+*                             All other characters are explicitly specified.
+*
+*                         (2) THE INTERNATIONAL REFERENCE VERSION, which explicitly specifies all characters
+*                             in the 7-bit character set.
+*
+*                         (3) NATIONAL & APPLICATION-ORIENTED VERSIONS, which may be derived from the
+*                             standard in specified ways.
+*
+*                     (b) The character set represented in this file reproduces the Internation Reference
+*                         Version.  This is identical to the 7-bit character set which occupies Unicode
+*                         characters 0x0000 through 0x007F.  The character names are taken from v5.0 of the
+*                         Unicode specification, with certain abbreviations so that the resulting #define
+*                         names will not violate ANSI C naming restriction :
+*
+*                         (1) For the Latin capital & lowercase letters, the name components 'LETTER_CAPITAL'
+*                             & 'LETTER_SMALL' are replaced by 'UPPER' & 'LOWER', respectively.
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#define    MICRIUM_SOURCE
+#define    LIB_ASCII_MODULE
+#include  <lib_ascii.h>
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL DEFINES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                           LOCAL CONSTANTS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          LOCAL DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL TABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                       LOCAL GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                      LOCAL FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                     LOCAL CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_IsAlpha()
+*
+* Description : Determine whether a character is an alphabetic character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     an alphabetic character.
+*
+*               DEF_NO,     if character is NOT an alphabetic character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.2.(2) states that "isalpha() returns true only for the
+*                   characters for which isupper() or islower() is true".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsAlpha (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  alpha;
+
+
+    alpha = ASCII_IS_ALPHA(c);
+
+    return (alpha);
+}
+
+
+/*
+*********************************************************************************************************
+*                                         ASCII_IsAlphaNum()
+*
+* Description : Determine whether a character is an alphanumeric character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     an alphanumeric character.
+*
+*               DEF_NO,     if character is NOT an alphanumeric character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.1.(2) states that "isalnum() ... tests for any character
+*                   for which isalpha() or isdigit() is true".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsAlphaNum (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  alpha_num;
+
+
+    alpha_num = ASCII_IS_ALPHA_NUM(c);
+
+    return (alpha_num);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_IsLower()
+*
+* Description : Determine whether a character is a lowercase alphabetic character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a lowercase alphabetic character.
+*
+*               DEF_NO,     if character is NOT a lowercase alphabetic character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.7.(2)  states that "islower() returns true only for
+*                   the lowercase letters".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsLower (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  lower;
+
+
+    lower = ASCII_IS_LOWER(c);
+
+    return (lower);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_IsUpper()
+*
+* Description : Determine whether a character is an uppercase alphabetic character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     an uppercase alphabetic character.
+*
+*               DEF_NO,     if character is NOT an uppercase alphabetic character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.11.(2) states that "isupper() returns true only for
+*                   the uppercase letters".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsUpper (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  upper;
+
+
+    upper = ASCII_IS_UPPER(c);
+
+    return (upper);
+}
+
+
+/*
+*********************************************************************************************************
+*                                            ASCII_IsDig()
+*
+* Description : Determine whether a character is a decimal-digit character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a decimal-digit character.
+*
+*               DEF_NO,     if character is NOT a decimal-digit character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.5.(2)  states that "isdigit()  ... tests for any
+*                   decimal-digit character".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsDig (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  dig;
+
+
+    dig = ASCII_IS_DIG(c);
+
+    return (dig);
+}
+
+
+/*
+*********************************************************************************************************
+*                                          ASCII_IsDigOct()
+*
+* Description : Determine whether a character is an octal-digit character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     an octal-digit character.
+*
+*               DEF_NO,     if character is NOT an octal-digit character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsDigOct (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  dig_oct;
+
+
+    dig_oct = ASCII_IS_DIG_OCT(c);
+
+    return (dig_oct);
+}
+
+
+/*
+*********************************************************************************************************
+*                                          ASCII_IsDigHex()
+*
+* Description : Determine whether a character is a hexadecimal-digit character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a hexadecimal-digit character.
+*
+*               DEF_NO,     if character is NOT a hexadecimal-digit character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.12.(2) states that "isxdigit() ... tests for any
+*                   hexadecimal-digit character".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsDigHex (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  dig_hex;
+
+
+    dig_hex = ASCII_IS_DIG_HEX(c);
+
+    return (dig_hex);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_IsBlank()
+*
+* Description : Determine whether a character is a standard blank character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a standard blank character.
+*
+*               DEF_NO,     if character is NOT a standard blank character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.3.(2) states that "isblank() returns true only for
+*                       the standard blank characters".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.1.3.(2) defines "the standard blank characters" as
+*                       the "space (' '), and horizontal tab ('\t')".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsBlank (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  blank;
+
+
+    blank = ASCII_IS_BLANK(c);
+
+    return (blank);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_IsSpace()
+*
+* Description : Determine whether a character is a white-space character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a white-space character.
+*
+*               DEF_NO,     if character is NOT a white-space character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.10.(2) states that "isspace() returns true only
+*                       for the standard white-space characters".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.1.10.(2) defines "the standard white-space characters"
+*                       as the "space (' '), form feed ('\f'), new-line ('\n'), carriage return ('\r'),
+*                       horizontal tab ('\t'), and vertical tab ('\v')".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsSpace (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  space;
+
+
+    space = ASCII_IS_SPACE(c);
+
+    return (space);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_IsPrint()
+*
+* Description : Determine whether a character is a printing character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a printing character.
+*
+*               DEF_NO,     if character is NOT a printing character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.8.(2) states that "isprint() ... tests for any
+*                       printing character including space (' ')".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US
+*                       ASCII character set, the printing characters are those whose values lie from
+*                       0x20 (space) through 0x7E (tilde)".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsPrint (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  print;
+
+
+    print = ASCII_IS_PRINT(c);
+
+    return (print);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_IsGraph()
+*
+* Description : Determine whether a character is any printing character except a space character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a graphic character.
+*
+*               DEF_NO,     if character is NOT a graphic character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.6.(2) states that "isgraph() ... tests for any
+*                       printing character except space (' ')".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US
+*                       ASCII character set, the printing characters are those whose values lie from
+*                       0x20 (space) through 0x7E (tilde)".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsGraph (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  graph;
+
+
+    graph = ASCII_IS_GRAPH(c);
+
+    return (graph);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_IsPunct()
+*
+* Description : Determine whether a character is a punctuation character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a punctuation character.
+*
+*               DEF_NO,     if character is NOT a punctuation character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.9.(2) states that "ispunct() returns true for every
+*                   printing character for which neither isspace() nor isalnum() is true".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsPunct (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  punct;
+
+
+    punct = ASCII_IS_PUNCT(c);
+
+    return (punct);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_IsCtrl()
+*
+* Description : Determine whether a character is a control character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a control character.
+*
+*               DEF_NO,     if character is NOT a control character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.4.(2) states that "iscntrl() ... tests for any
+*                       control character".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US
+*                       ASCII character set, ... the control characters are those whose values lie from
+*                       0 (NUL) through 0x1F (US), and the character 0x7F (DEL)".
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsCtrl (CPU_CHAR  c)
+{
+    CPU_BOOLEAN  ctrl;
+
+
+    ctrl = ASCII_IS_CTRL(c);
+
+    return (ctrl);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_ToLower()
+*
+* Description : Convert uppercase alphabetic character to its corresponding lowercase alphabetic character.
+*
+* Argument(s) : c           Character to convert.
+*
+* Return(s)   : Lowercase equivalent of 'c', if character 'c' is an uppercase character (see Note #1b1).
+*
+*               Character 'c',               otherwise                                  (see Note #1b2).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.2.1.(2) states that "tolower() ... converts an
+*                       uppercase letter to a corresponding lowercase letter".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.2.1.(3) states that :
+*
+*                       (1) (A) "if the argument is a character for which isupper() is true and there are
+*                                one or more corresponding characters ... for which islower() is true," ...
+*                           (B) "tolower() ... returns one of the corresponding characters;" ...
+*
+*                       (2) "otherwise, the argument is returned unchanged."
+*********************************************************************************************************
+*/
+
+CPU_CHAR  ASCII_ToLower (CPU_CHAR  c)
+{
+    CPU_CHAR  lower;
+
+
+    lower = ASCII_TO_LOWER(c);
+
+    return (lower);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_ToUpper()
+*
+* Description : Convert lowercase alphabetic character to its corresponding uppercase alphabetic character.
+*
+* Argument(s) : c           Character to convert.
+*
+* Return(s)   : Uppercase equivalent of 'c', if character 'c' is a lowercase character (see Note #1b1).
+*
+*               Character 'c',               otherwise                                 (see Note #1b2).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.2.2.(2) states that "toupper() ... converts a
+*                       lowercase letter to a corresponding uppercase letter".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.2.2.(3) states that :
+*
+*                       (1) (A) "if the argument is a character for which islower() is true and there are
+*                                one or more corresponding characters ... for which isupper() is true," ...
+*                           (B) "toupper() ... returns one of the corresponding characters;" ...
+*
+*                       (2) "otherwise, the argument is returned unchanged."
+*********************************************************************************************************
+*/
+
+CPU_CHAR  ASCII_ToUpper (CPU_CHAR  c)
+{
+    CPU_CHAR  upper;
+
+
+    upper = ASCII_TO_UPPER(c);
+
+    return (upper);
+}
+
+
+/*
+*********************************************************************************************************
+*                                             ASCII_Cmp()
+*
+* Description : Determine if two characters are identical (case-insensitive).
+*
+* Argument(s) : c1          First  character.
+*
+*               c2          Second character.
+*
+* Return(s)   : DEF_YES, if the characters are     identical.
+*
+*               DEF_NO,  if the characters are NOT identical.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_Cmp (CPU_CHAR  c1,
+                        CPU_CHAR  c2)
+{
+    CPU_CHAR     c1_upper;
+    CPU_CHAR     c2_upper;
+    CPU_BOOLEAN  cmp;
+
+
+    c1_upper =  ASCII_ToUpper(c1);
+    c2_upper =  ASCII_ToUpper(c2);
+    cmp      = (c1_upper == c2_upper) ? (DEF_YES) : (DEF_NO);
+
+    return (cmp);
+}
+

+ 842 - 0
MiddleWare/uCOS_II/uC-LIB/lib_ascii.h

@@ -0,0 +1,842 @@
+/*
+*********************************************************************************************************
+*                                                uC/LIB
+*                                        CUSTOM LIBRARY MODULES
+*
+*                         (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL
+*
+*                  All rights reserved.  Protected by international copyright laws.
+*
+*                  uC/LIB is provided in source form to registered licensees ONLY.  It is
+*                  illegal to distribute this source code to any third party unless you receive
+*                  written permission by an authorized Micrium representative.  Knowledge of
+*                  the source code may NOT be used to develop a similar product.
+*
+*                  Please help us continue to provide the Embedded community with the finest
+*                  software available.  Your honesty is greatly appreciated.
+*
+*                  You can find our product's user manual, API reference, release notes and
+*                  more information at: https://doc.micrium.com
+*
+*                  You can contact us at: http://www.micrium.com
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                     ASCII CHARACTER OPERATIONS
+*
+* Filename      : lib_ascii.h
+* Version       : V1.38.01
+* Programmer(s) : BAN
+*********************************************************************************************************
+* Note(s)       : (1) NO compiler-supplied standard library functions are used in library or product software.
+*
+*                     (a) ALL standard library functions are implemented in the custom library modules :
+*
+*                         (1) \<Custom Library Directory>\lib_*.*
+*
+*                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+*
+*                               where
+*                                       <Custom Library Directory>      directory path for custom library software
+*                                       <cpu>                           directory name for specific processor (CPU)
+*                                       <compiler>                      directory name for specific compiler
+*
+*                     (b) Product-specific library functions are implemented in individual products.
+*
+*
+*                 (2) (a) ECMA-6 '7-Bit coded Character Set' (6th edition), which corresponds to the
+*                         3rd edition of ISO 646, specifies several versions of a 7-bit character set :
+*
+*                         (1) THE GENERAL VERSION, which allows characters at 0x23 and 0x24 to be given a
+*                             set alternate form and allows the characters 0x40, 0x5B, 0x5D, 0x60, 0x7B &
+*                             0x7D to be assigned a "unique graphic character" or to be declared as unused.
+*                             All other characters are explicitly specified.
+*
+*                         (2) THE INTERNATIONAL REFERENCE VERSION, which explicitly specifies all characters
+*                             in the 7-bit character set.
+*
+*                         (3) NATIONAL & APPLICATION-ORIENTED VERSIONS, which may be derived from the
+*                             standard in specified ways.
+*
+*                     (b) The character set represented in this file reproduces the Internation Reference
+*                         Version.  This is identical to the 7-bit character set which occupies Unicode
+*                         characters 0x0000 through 0x007F.  The character names are taken from v5.0 of the
+*                         Unicode specification, with certain abbreviations so that the resulting #define
+*                         names will not violate ANSI C naming restriction :
+*
+*                         (1) For the Latin capital & lowercase letters, the name components 'LETTER_CAPITAL'
+*                             & 'LETTER_SMALL' are replaced by 'UPPER' & 'LOWER', respectively.
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*
+* Note(s) : (1) This ASCII library header file is protected from multiple pre-processor inclusion through
+*               use of the ASCII library module present pre-processor macro definition.
+*********************************************************************************************************
+*/
+
+#ifndef  LIB_ASCII_MODULE_PRESENT                               /* See Note #1.                                         */
+#define  LIB_ASCII_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*
+* Note(s) : (1) The custom library software files are located in the following directories :
+*
+*               (a) \<Custom Library Directory>\lib_*.*
+*
+*                       where
+*                               <Custom Library Directory>      directory path for custom library software
+*
+*           (2) CPU-configuration  software files are located in the following directories :
+*
+*               (a) \<CPU-Compiler Directory>\cpu_*.*
+*               (b) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.*
+*
+*                       where
+*                               <CPU-Compiler Directory>        directory path for common CPU-compiler software
+*                               <cpu>                           directory name for specific processor (CPU)
+*                               <compiler>                      directory name for specific compiler
+*
+*           (3) Compiler MUST be configured to include as additional include path directories :
+*
+*               (a) '\<Custom Library Directory>\' directory                            See Note #1a
+*
+*               (b) (1) '\<CPU-Compiler Directory>\'                  directory         See Note #2a
+*                   (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory         See Note #2b
+*
+*           (4) NO compiler-supplied standard library functions SHOULD be used.
+*********************************************************************************************************
+*/
+
+#include  <cpu.h>
+#include  <lib_def.h>
+
+
+/*
+*********************************************************************************************************
+*                                               EXTERNS
+*********************************************************************************************************
+*/
+
+#ifdef   LIB_ASCII_MODULE
+#define  LIB_ASCII_EXT
+#else
+#define  LIB_ASCII_EXT  extern
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                               DEFINES
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                         ASCII CHARACTER DEFINES
+*********************************************************************************************************
+*/
+
+                                                                /* -------------------- C0 CONTROLS ------------------- */
+#define  ASCII_CHAR_NULL                                0x00    /* '\0'                                                 */
+#define  ASCII_CHAR_START_OF_HEADING                    0x01
+#define  ASCII_CHAR_START_OF_TEXT                       0x02
+#define  ASCII_CHAR_END_OF_TEXT                         0x03
+#define  ASCII_CHAR_END_OF_TRANSMISSION                 0x04
+#define  ASCII_CHAR_ENQUIRY                             0x05
+#define  ASCII_CHAR_ACKNOWLEDGE                         0x06
+#define  ASCII_CHAR_BELL                                0x07    /* '\a'                                                 */
+#define  ASCII_CHAR_BACKSPACE                           0x08    /* '\b'                                                 */
+#define  ASCII_CHAR_CHARACTER_TABULATION                0x09    /* '\t'                                                 */
+#define  ASCII_CHAR_LINE_FEED                           0x0A    /* '\n'                                                 */
+#define  ASCII_CHAR_LINE_TABULATION                     0x0B    /* '\v'                                                 */
+#define  ASCII_CHAR_FORM_FEED                           0x0C    /* '\f'                                                 */
+#define  ASCII_CHAR_CARRIAGE_RETURN                     0x0D    /* '\r'                                                 */
+#define  ASCII_CHAR_SHIFT_OUT                           0x0E
+#define  ASCII_CHAR_SHIFT_IN                            0x0F
+#define  ASCII_CHAR_DATA_LINK_ESCAPE                    0x10
+#define  ASCII_CHAR_DEVICE_CONTROL_ONE                  0x11
+#define  ASCII_CHAR_DEVICE_CONTROL_TWO                  0x12
+#define  ASCII_CHAR_DEVICE_CONTROL_THREE                0x13
+#define  ASCII_CHAR_DEVICE_CONTROL_FOUR                 0x14
+#define  ASCII_CHAR_NEGATIVE_ACKNOWLEDGE                0x15
+#define  ASCII_CHAR_SYNCHRONOUS_IDLE                    0x16
+#define  ASCII_CHAR_END_OF_TRANSMISSION_BLOCK           0x17
+#define  ASCII_CHAR_CANCEL                              0x18
+#define  ASCII_CHAR_END_OF_MEDIUM                       0x19
+#define  ASCII_CHAR_SUBSITUTE                           0x1A
+#define  ASCII_CHAR_ESCAPE                              0x1B
+#define  ASCII_CHAR_INFO_SEPARATOR_FOUR                 0x1C
+#define  ASCII_CHAR_INFO_SEPARATOR_THREE                0x1D
+#define  ASCII_CHAR_INFO_SEPARATOR_TWO                  0x1E
+#define  ASCII_CHAR_INFO_SEPARATOR_ONE                  0x1F
+
+#define  ASCII_CHAR_NUL                                 ASCII_CHAR_NULL
+#define  ASCII_CHAR_SOH                                 ASCII_CHAR_START_OF_HEADING
+#define  ASCII_CHAR_START_HEADING                       ASCII_CHAR_START_OF_HEADING
+#define  ASCII_CHAR_STX                                 ASCII_CHAR_START_OF_TEXT
+#define  ASCII_CHAR_START_TEXT                          ASCII_CHAR_START_OF_TEXT
+#define  ASCII_CHAR_ETX                                 ASCII_CHAR_END_OF_TEXT
+#define  ASCII_CHAR_END_TEXT                            ASCII_CHAR_END_OF_TEXT
+#define  ASCII_CHAR_EOT                                 ASCII_CHAR_END_OF_TRANSMISSION
+#define  ASCII_CHAR_END_TRANSMISSION                    ASCII_CHAR_END_OF_TRANSMISSION
+#define  ASCII_CHAR_ENQ                                 ASCII_CHAR_ENQUIRY
+#define  ASCII_CHAR_ACK                                 ASCII_CHAR_ACKNOWLEDGE
+#define  ASCII_CHAR_BEL                                 ASCII_CHAR_BELL
+#define  ASCII_CHAR_BS                                  ASCII_CHAR_BACKSPACE
+#define  ASCII_CHAR_HT                                  ASCII_CHAR_CHARACTER_TABULATION
+#define  ASCII_CHAR_TAB                                 ASCII_CHAR_CHARACTER_TABULATION
+#define  ASCII_CHAR_LF                                  ASCII_CHAR_LINE_FEED
+#define  ASCII_CHAR_VT                                  ASCII_CHAR_LINE_TABULATION
+#define  ASCII_CHAR_FF                                  ASCII_CHAR_FORM_FEED
+#define  ASCII_CHAR_CR                                  ASCII_CHAR_CARRIAGE_RETURN
+#define  ASCII_CHAR_SO                                  ASCII_CHAR_SHIFT_OUT
+#define  ASCII_CHAR_SI                                  ASCII_CHAR_SHIFT_IN
+#define  ASCII_CHAR_DLE                                 ASCII_CHAR_DATA_LINK_ESCAPE
+#define  ASCII_CHAR_DC1                                 ASCII_CHAR_DEVICE_CONTROL_ONE
+#define  ASCII_CHAR_DC2                                 ASCII_CHAR_DEVICE_CONTROL_TWO
+#define  ASCII_CHAR_DC3                                 ASCII_CHAR_DEVICE_CONTROL_THREE
+#define  ASCII_CHAR_DC4                                 ASCII_CHAR_DEVICE_CONTROL_FOUR
+#define  ASCII_CHAR_DEV_CTRL_ONE                        ASCII_CHAR_DEVICE_CONTROL_ONE
+#define  ASCII_CHAR_DEV_CTRL_TWO                        ASCII_CHAR_DEVICE_CONTROL_TWO
+#define  ASCII_CHAR_DEV_CTRL_THREE                      ASCII_CHAR_DEVICE_CONTROL_THREE
+#define  ASCII_CHAR_DEV_CTRL_FOUR                       ASCII_CHAR_DEVICE_CONTROL_FOUR
+#define  ASCII_CHAR_NAK                                 ASCII_CHAR_NEGATIVE_ACKNOWLEDGE
+#define  ASCII_CHAR_NEG_ACK                             ASCII_CHAR_NEGATIVE_ACKNOWLEDGE
+#define  ASCII_CHAR_SYN                                 ASCII_CHAR_SYNCHRONOUS_IDLE
+#define  ASCII_CHAR_SYNC_IDLE                           ASCII_CHAR_SYNCHRONOUS_IDLE
+#define  ASCII_CHAR_ETB                                 ASCII_CHAR_END_OF_TRANSMISSION_BLOCK
+#define  ASCII_CHAR_END_TRANSMISSION_BLK                ASCII_CHAR_END_OF_TRANSMISSION_BLOCK
+#define  ASCII_CHAR_CAN                                 ASCII_CHAR_CANCEL
+#define  ASCII_CHAR_EM                                  ASCII_CHAR_END_OF_MEDIUM
+#define  ASCII_CHAR_END_MEDIUM                          ASCII_CHAR_END_OF_MEDIUM
+#define  ASCII_CHAR_SUB                                 ASCII_CHAR_SUBSITUTE
+#define  ASCII_CHAR_ESC                                 ASCII_CHAR_ESCAPE
+#define  ASCII_CHAR_IS1                                 ASCII_CHAR_INFO_SEPARATOR_ONE
+#define  ASCII_CHAR_IS2                                 ASCII_CHAR_INFO_SEPARATOR_TWO
+#define  ASCII_CHAR_IS3                                 ASCII_CHAR_INFO_SEPARATOR_THREE
+#define  ASCII_CHAR_IS4                                 ASCII_CHAR_INFO_SEPARATOR_FOUR
+
+
+                                                                /* ------------ ASCII PUNCTUATION & SYMBOLS ----------- */
+#define  ASCII_CHAR_SPACE                               0x20    /* ' '                                                  */
+#define  ASCII_CHAR_EXCLAMATION_MARK                    0x21    /* '!'                                                  */
+#define  ASCII_CHAR_QUOTATION_MARK                      0x22    /* '\"'                                                 */
+#define  ASCII_CHAR_NUMBER_SIGN                         0x23    /* '#'                                                  */
+#define  ASCII_CHAR_DOLLAR_SIGN                         0x24    /* '$'                                                  */
+#define  ASCII_CHAR_PERCENTAGE_SIGN                     0x25    /* '%'                                                  */
+#define  ASCII_CHAR_AMPERSAND                           0x26    /* '&'                                                  */
+#define  ASCII_CHAR_APOSTROPHE                          0x27    /* '\''                                                 */
+#define  ASCII_CHAR_LEFT_PARENTHESIS                    0x28    /* '('                                                  */
+#define  ASCII_CHAR_RIGHT_PARENTHESIS                   0x29    /* ')'                                                  */
+#define  ASCII_CHAR_ASTERISK                            0x2A    /* '*'                                                  */
+#define  ASCII_CHAR_PLUS_SIGN                           0x2B    /* '+'                                                  */
+#define  ASCII_CHAR_COMMA                               0x2C    /* ','                                                  */
+#define  ASCII_CHAR_HYPHEN_MINUS                        0x2D    /* '-'                                                  */
+#define  ASCII_CHAR_FULL_STOP                           0x2E    /* '.'                                                  */
+#define  ASCII_CHAR_SOLIDUS                             0x2F    /* '/'                                                  */
+
+#define  ASCII_CHAR_PAREN_LEFT                          ASCII_CHAR_LEFT_PARENTHESIS
+#define  ASCII_CHAR_PAREN_RIGHT                         ASCII_CHAR_RIGHT_PARENTHESIS
+
+
+                                                                /* ------------------- ASCII DIGITS ------------------- */
+#define  ASCII_CHAR_DIGIT_ZERO                          0x30    /* '0'                                                  */
+#define  ASCII_CHAR_DIGIT_ONE                           0x31    /* '1'                                                  */
+#define  ASCII_CHAR_DIGIT_TWO                           0x32    /* '2'                                                  */
+#define  ASCII_CHAR_DIGIT_THREE                         0x33    /* '3'                                                  */
+#define  ASCII_CHAR_DIGIT_FOUR                          0x34    /* '4'                                                  */
+#define  ASCII_CHAR_DIGIT_FIVE                          0x35    /* '5'                                                  */
+#define  ASCII_CHAR_DIGIT_SIX                           0x36    /* '6'                                                  */
+#define  ASCII_CHAR_DIGIT_SEVEN                         0x37    /* '7'                                                  */
+#define  ASCII_CHAR_DIGIT_EIGHT                         0x38    /* '8'                                                  */
+#define  ASCII_CHAR_DIGIT_NINE                          0x39    /* '9'                                                  */
+
+#define  ASCII_CHAR_DIG_ZERO                            ASCII_CHAR_DIGIT_ZERO
+#define  ASCII_CHAR_DIG_ONE                             ASCII_CHAR_DIGIT_ONE
+#define  ASCII_CHAR_DIG_TWO                             ASCII_CHAR_DIGIT_TWO
+#define  ASCII_CHAR_DIG_THREE                           ASCII_CHAR_DIGIT_THREE
+#define  ASCII_CHAR_DIG_FOUR                            ASCII_CHAR_DIGIT_FOUR
+#define  ASCII_CHAR_DIG_FIVE                            ASCII_CHAR_DIGIT_FIVE
+#define  ASCII_CHAR_DIG_SIX                             ASCII_CHAR_DIGIT_SIX
+#define  ASCII_CHAR_DIG_SEVEN                           ASCII_CHAR_DIGIT_SEVEN
+#define  ASCII_CHAR_DIG_EIGHT                           ASCII_CHAR_DIGIT_EIGHT
+#define  ASCII_CHAR_DIG_NINE                            ASCII_CHAR_DIGIT_NINE
+
+
+                                                                /* ------------ ASCII PUNCTUATION & SYMBOLS ----------- */
+#define  ASCII_CHAR_COLON                               0x3A    /* ':'                                                  */
+#define  ASCII_CHAR_SEMICOLON                           0x3B    /* ';'                                                  */
+#define  ASCII_CHAR_LESS_THAN_SIGN                      0x3C    /* '<'                                                  */
+#define  ASCII_CHAR_EQUALS_SIGN                         0x3D    /* '='                                                  */
+#define  ASCII_CHAR_GREATER_THAN_SIGN                   0x3E    /* '>'                                                  */
+#define  ASCII_CHAR_QUESTION_MARK                       0x3F    /* '\?'                                                 */
+#define  ASCII_CHAR_COMMERCIAL_AT                       0x40    /* '@'                                                  */
+
+#define  ASCII_CHAR_AT_SIGN                             ASCII_CHAR_COMMERCIAL_AT
+
+
+                                                                /* ------------- UPPERCASE LATIN ALPHABET ------------- */
+#define  ASCII_CHAR_LATIN_UPPER_A                       0x41    /* 'A'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_B                       0x42    /* 'B'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_C                       0x43    /* 'C'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_D                       0x44    /* 'D'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_E                       0x45    /* 'E'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_F                       0x46    /* 'F'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_G                       0x47    /* 'G'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_H                       0x48    /* 'H'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_I                       0x49    /* 'I'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_J                       0x4A    /* 'J'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_K                       0x4B    /* 'K'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_L                       0x4C    /* 'L'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_M                       0x4D    /* 'M'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_N                       0x4E    /* 'N'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_O                       0x4F    /* 'O'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_P                       0x50    /* 'P'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_Q                       0x51    /* 'Q'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_R                       0x52    /* 'R'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_S                       0x53    /* 'S'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_T                       0x54    /* 'T'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_U                       0x55    /* 'U'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_V                       0x56    /* 'V'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_W                       0x57    /* 'W'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_X                       0x58    /* 'X'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_Y                       0x59    /* 'Y'                                                  */
+#define  ASCII_CHAR_LATIN_UPPER_Z                       0x5A    /* 'Z'                                                  */
+
+
+                                                                /* ------------ ASCII PUNCTUATION & SYMBOLS ----------- */
+#define  ASCII_CHAR_LEFT_SQUARE_BRACKET                 0x5B    /* '['                                                  */
+#define  ASCII_CHAR_REVERSE_SOLIDUS                     0x5C    /* '\\'                                                 */
+#define  ASCII_CHAR_RIGHT_SQUARE_BRACKET                0x5D    /* ']'                                                  */
+#define  ASCII_CHAR_CIRCUMFLEX_ACCENT                   0x5E    /* '^'                                                  */
+#define  ASCII_CHAR_LOW_LINE                            0x5F    /* '_'                                                  */
+#define  ASCII_CHAR_GRAVE_ACCENT                        0x60    /* '`'                                                  */
+
+#define  ASCII_CHAR_BRACKET_SQUARE_LEFT                 ASCII_CHAR_LEFT_SQUARE_BRACKET
+#define  ASCII_CHAR_BRACKET_SQUARE_RIGHT                ASCII_CHAR_RIGHT_SQUARE_BRACKET
+
+
+                                                                /* ------------- LOWERCASE LATIN ALPHABET ------------- */
+#define  ASCII_CHAR_LATIN_LOWER_A                       0x61    /* 'a'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_B                       0x62    /* 'b'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_C                       0x63    /* 'c'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_D                       0x64    /* 'd'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_E                       0x65    /* 'e'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_F                       0x66    /* 'f'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_G                       0x67    /* 'g'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_H                       0x68    /* 'h'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_I                       0x69    /* 'i'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_J                       0x6A    /* 'j'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_K                       0x6B    /* 'k'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_L                       0x6C    /* 'l'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_M                       0x6D    /* 'm'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_N                       0x6E    /* 'n'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_O                       0x6F    /* 'o'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_P                       0x70    /* 'p'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_Q                       0x71    /* 'q'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_R                       0x72    /* 'r'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_S                       0x73    /* 's'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_T                       0x74    /* 't'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_U                       0x75    /* 'u'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_V                       0x76    /* 'v'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_W                       0x77    /* 'w'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_X                       0x78    /* 'x'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_Y                       0x79    /* 'y'                                                  */
+#define  ASCII_CHAR_LATIN_LOWER_Z                       0x7A    /* 'z'                                                  */
+
+
+                                                                /* ------------ ASCII PUNCTUATION & SYMBOLS ----------- */
+#define  ASCII_CHAR_LEFT_CURLY_BRACKET                  0x7B    /* '{'                                                  */
+#define  ASCII_CHAR_VERTICAL_LINE                       0x7C    /* '|'                                                  */
+#define  ASCII_CHAR_RIGHT_CURLY_BRACKET                 0x7D    /* '}'                                                  */
+#define  ASCII_CHAR_TILDE                               0x7E    /* '~'                                                  */
+
+#define  ASCII_CHAR_BRACKET_CURLY_LEFT                  ASCII_CHAR_LEFT_CURLY_BRACKET
+#define  ASCII_CHAR_BRACKET_CURLY_RIGHT                 ASCII_CHAR_RIGHT_CURLY_BRACKET
+
+
+                                                                /* ---------------- CONTROL CHARACTERS ---------------- */
+#define  ASCII_CHAR_DELETE                              0x7F
+
+#define  ASCII_CHAR_DEL                                 ASCII_CHAR_DELETE
+
+
+/*
+*********************************************************************************************************
+*                                             DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                              MACRO'S
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                               ASCII CHARACTER CLASSIFICATION MACRO's
+*
+* Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.(1) states that "character classification functions ...
+*               return nonzero (true) if and only if the value of the argument 'c' conforms to ... the
+*               description of the function."
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                           ASCII_IS_DIG()
+*
+* Description : Determine whether a character is a decimal-digit character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a decimal-digit character.
+*
+*               DEF_NO,     if character is NOT a decimal-digit character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.5.(2)  states that "isdigit()  ... tests for any
+*                   decimal-digit character".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_DIG(c)               ((((c) >= ASCII_CHAR_DIG_ZERO) && ((c) <= ASCII_CHAR_DIG_NINE)) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                         ASCII_IS_DIG_OCT()
+*
+* Description : Determine whether a character is an octal-digit character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     an octal-digit character.
+*
+*               DEF_NO,     if character is NOT an octal-digit character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_DIG_OCT(c)          ((((c) >= ASCII_CHAR_DIG_ZERO) && ((c) <= ASCII_CHAR_DIG_SEVEN)) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                         ASCII_IS_DIG_HEX()
+*
+* Description : Determine whether a character is a hexadecimal-digit character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a hexadecimal-digit character.
+*
+*               DEF_NO,     if character is NOT a hexadecimal-digit character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.12.(2) states that "isxdigit() ... tests for any
+*                   hexadecimal-digit character".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_DIG_HEX(c)          (((((c) >= ASCII_CHAR_DIG_ZERO     ) && ((c) <= ASCII_CHAR_DIG_NINE     )) || \
+                                        (((c) >= ASCII_CHAR_LATIN_UPPER_A) && ((c) <= ASCII_CHAR_LATIN_UPPER_F)) || \
+                                        (((c) >= ASCII_CHAR_LATIN_LOWER_A) && ((c) <= ASCII_CHAR_LATIN_LOWER_F))) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                          ASCII_IS_LOWER()
+*
+* Description : Determine whether a character is a lowercase alphabetic character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a lowercase alphabetic character.
+*
+*               DEF_NO,     if character is NOT a lowercase alphabetic character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.7.(2)  states that "islower() returns true only for
+*                   the lowercase letters".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_LOWER(c)             ((((c) >= ASCII_CHAR_LATIN_LOWER_A) && ((c) <= ASCII_CHAR_LATIN_LOWER_Z)) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                          ASCII_IS_UPPER()
+*
+* Description : Determine whether a character is an uppercase alphabetic character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     an uppercase alphabetic character.
+*
+*               DEF_NO,     if character is NOT an uppercase alphabetic character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.11.(2) states that "isupper() returns true only for
+*                   the uppercase letters".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_UPPER(c)             ((((c) >= ASCII_CHAR_LATIN_UPPER_A) && ((c) <= ASCII_CHAR_LATIN_UPPER_Z)) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                          ASCII_IS_ALPHA()
+*
+* Description : Determine whether a character is an alphabetic character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     an alphabetic character.
+*
+*               DEF_NO,     if character is NOT an alphabetic character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.2.(2) states that "isalpha() returns true only for the
+*                   characters for which isupper() or islower() is true".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_ALPHA(c)             ((((ASCII_IS_UPPER(c)) == DEF_YES) || \
+                                         ((ASCII_IS_LOWER(c)) == DEF_YES)) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                        ASCII_IS_ALPHA_NUM()
+*
+* Description : Determine whether a character is an alphanumeric character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     an alphanumeric character.
+*
+*               DEF_NO,     if character is NOT an alphanumeric character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.1.(2) states that "isalnum() ... tests for any character
+*                   for which isalpha() or isdigit() is true".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_ALPHA_NUM(c)         ((((ASCII_IS_ALPHA(c)) == DEF_YES) || \
+                                         ((ASCII_IS_DIG  (c)) == DEF_YES)) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                          ASCII_IS_BLANK()
+*
+* Description : Determine whether a character is a standard blank character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a standard blank character.
+*
+*               DEF_NO,     if character is NOT a standard blank character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.3.(2) states that "isblank() returns true only for
+*                       the standard blank characters".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.1.3.(2) defines "the standard blank characters" as
+*                       the "space (' '), and horizontal tab ('\t')".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_BLANK(c)             ((((c) == ASCII_CHAR_SPACE) || ((c) == ASCII_CHAR_HT)) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                          ASCII_IS_SPACE()
+*
+* Description : Determine whether a character is a white-space character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a white-space character.
+*
+*               DEF_NO,     if character is NOT a white-space character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.10.(2) states that "isspace() returns true only
+*                       for the standard white-space characters".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.1.10.(2) defines "the standard white-space characters"
+*                       as the "space (' '), form feed ('\f'), new-line ('\n'), carriage return ('\r'),
+*                       horizontal tab ('\t'), and vertical tab ('\v')".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_SPACE(c)             ((((c) == ASCII_CHAR_SPACE) || ((c) == ASCII_CHAR_CR) || \
+                                         ((c) == ASCII_CHAR_LF   ) || ((c) == ASCII_CHAR_FF) || \
+                                         ((c) == ASCII_CHAR_HT   ) || ((c) == ASCII_CHAR_VT)) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                          ASCII_IS_PRINT()
+*
+* Description : Determine whether a character is a printing character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a printing character.
+*
+*               DEF_NO,     if character is NOT a printing character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.8.(2) states that "isprint() ... tests for any
+*                       printing character including space (' ')".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US
+*                       ASCII character set, the printing characters are those whose values lie from
+*                       0x20 (space) through 0x7E (tilde)".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_PRINT(c)             ((((c) >= ASCII_CHAR_SPACE) && ((c) <= ASCII_CHAR_TILDE)) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                          ASCII_IS_GRAPH()
+*
+* Description : Determine whether a character is any printing character except a space character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a graphic character.
+*
+*               DEF_NO,     if character is NOT a graphic character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.6.(2) states that "isgraph() ... tests for any
+*                       printing character except space (' ')".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US
+*                       ASCII character set, the printing characters are those whose values lie from
+*                       0x20 (space) through 0x7E (tilde)".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_GRAPH(c)             ((((c) >= ASCII_CHAR_EXCLAMATION_MARK) && ((c) <= ASCII_CHAR_TILDE)) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                          ASCII_IS_PUNCT()
+*
+* Description : Determine whether a character is a punctuation character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a punctuation character.
+*
+*               DEF_NO,     if character is NOT a punctuation character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) ISO/IEC 9899:TC2, Section 7.4.1.9.(2) states that "ispunct() returns true for every
+*                   printing character for which neither isspace() nor isalnum() is true".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_PUNCT(c)             ((((ASCII_IS_PRINT(c)) == DEF_YES) && \
+                                         ((ASCII_IS_SPACE(c)) == DEF_NO ) && \
+                                         ((ASCII_IS_ALPHA_NUM(c)) == DEF_NO )) ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                           ASCII_IS_CTRL()
+*
+* Description : Determine whether a character is a control character.
+*
+* Argument(s) : c           Character to examine.
+*
+* Return(s)   : DEF_YES, if character is     a control character.
+*
+*               DEF_NO,     if character is NOT a control character.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.4.(2) states that "iscntrl() ... tests for any
+*                       control character".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US
+*                       ASCII character set, ... the control characters are those whose values lie from
+*                       0 (NUL) through 0x1F (US), and the character 0x7F (DEL)".
+*********************************************************************************************************
+*/
+
+#define  ASCII_IS_CTRL(c)             (((((CPU_INT08S)(c) >= ASCII_CHAR_NULL  ) && ((c) <= ASCII_CHAR_IS1)) || \
+                                                                                   ((c) == ASCII_CHAR_DEL))  ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                ASCII CHARACTER CASE MAPPING MACRO's
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                          ASCII_TO_LOWER()
+*
+* Description : Convert uppercase alphabetic character to its corresponding lowercase alphabetic character.
+*
+* Argument(s) : c           Character to convert.
+*
+* Return(s)   : Lowercase equivalent of 'c', if character 'c' is an uppercase character (see Note #1b1).
+*
+*               Character 'c',               otherwise                                  (see Note #1b2).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.2.1.(2) states that "tolower() ... converts an
+*                       uppercase letter to a corresponding lowercase letter".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.2.1.(3) states that :
+*
+*                       (1) (A) "if the argument is a character for which isupper() is true and there are
+*                                one or more corresponding characters ... for which islower() is true," ...
+*                           (B) "tolower() ... returns one of the corresponding characters;" ...
+*
+*                       (2) "otherwise, the argument is returned unchanged."
+*********************************************************************************************************
+*/
+
+#define  ASCII_TO_LOWER(c)              (((ASCII_IS_UPPER(c)) == DEF_YES) ? ((c) + (ASCII_CHAR_LATIN_LOWER_A - ASCII_CHAR_LATIN_UPPER_A)) : (c))
+
+
+/*
+*********************************************************************************************************
+*                                          ASCII_TO_UPPER()
+*
+* Description : Convert lowercase alphabetic character to its corresponding uppercase alphabetic character.
+*
+* Argument(s) : c           Character to convert.
+*
+* Return(s)   : Uppercase equivalent of 'c', if character 'c' is a lowercase character (see Note #1b1).
+*
+*               Character 'c',               otherwise                                 (see Note #1b2).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) ISO/IEC 9899:TC2, Section 7.4.2.2.(2) states that "toupper() ... converts a
+*                       lowercase letter to a corresponding uppercase letter".
+*
+*                   (b) ISO/IEC 9899:TC2, Section 7.4.2.2.(3) states that :
+*
+*                       (1) (A) "if the argument is a character for which islower() is true and there are
+*                                one or more corresponding characters ... for which isupper() is true," ...
+*                           (B) "toupper() ... returns one of the corresponding characters;" ...
+*
+*                       (2) "otherwise, the argument is returned unchanged."
+*********************************************************************************************************
+*/
+
+#define  ASCII_TO_UPPER(c)              (((ASCII_IS_LOWER(c)) == DEF_YES) ? ((c) - (ASCII_CHAR_LATIN_LOWER_A - ASCII_CHAR_LATIN_UPPER_A)) : (c))
+
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  ASCII_IsAlpha   (CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsAlphaNum(CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsLower   (CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsUpper   (CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsDig     (CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsDigOct  (CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsDigHex  (CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsBlank   (CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsSpace   (CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsPrint   (CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsGraph   (CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsPunct   (CPU_CHAR  c);
+
+CPU_BOOLEAN  ASCII_IsCtrl    (CPU_CHAR  c);
+
+
+CPU_CHAR     ASCII_ToLower   (CPU_CHAR  c);
+
+CPU_CHAR     ASCII_ToUpper   (CPU_CHAR  c);
+
+
+CPU_BOOLEAN  ASCII_Cmp       (CPU_CHAR  c1,
+                              CPU_CHAR  c2);
+
+
+/*
+*********************************************************************************************************
+*                                        CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*
+* Note(s) : (1) See 'lib_ascii.h  MODULE'.
+*********************************************************************************************************
+*/
+
+#endif                                                          /* End of lib ascii module include.                     */
+

+ 1344 - 0
MiddleWare/uCOS_II/uC-LIB/lib_def.h

@@ -0,0 +1,1344 @@
+/*
+*********************************************************************************************************
+*                                                uC/LIB
+*                                        CUSTOM LIBRARY MODULES
+*
+*                         (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL
+*
+*                  All rights reserved.  Protected by international copyright laws.
+*
+*                  uC/LIB is provided in source form to registered licensees ONLY.  It is
+*                  illegal to distribute this source code to any third party unless you receive
+*                  written permission by an authorized Micrium representative.  Knowledge of
+*                  the source code may NOT be used to develop a similar product.
+*
+*                  Please help us continue to provide the Embedded community with the finest
+*                  software available.  Your honesty is greatly appreciated.
+*
+*                  You can find our product's user manual, API reference, release notes and
+*                  more information at: https://doc.micrium.com
+*
+*                  You can contact us at: http://www.micrium.com
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                     CORE CUSTOM LIBRARY MODULE
+*
+* Filename      : lib_def.h
+* Version       : V1.38.01
+* Programmer(s) : ITJ
+*                 FBJ
+*                 JFD
+*********************************************************************************************************
+* Note(s)       : (1) Assumes the following versions (or more recent) of software modules are included in
+*                     the project build :
+*
+*                     (a) uC/CPU V1.29.00
+*
+*
+*                 (2) NO compiler-supplied standard library functions are used in library or product software.
+*
+*                     (a) ALL standard library functions are implemented in the custom library modules :
+*
+*                         (1) \<Custom Library Directory>\lib_*.*
+*
+*                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+*
+*                               where
+*                                       <Custom Library Directory>      directory path for custom library software
+*                                       <cpu>                           directory name for specific processor (CPU)
+*                                       <compiler>                      directory name for specific compiler
+*
+*                     (b) Product-specific library functions are implemented in individual products.
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*
+* Note(s) : (1) This library definition header file is protected from multiple pre-processor inclusion
+*               through use of the library definition module present pre-processor macro definition.
+*********************************************************************************************************
+*/
+
+#ifndef  LIB_DEF_MODULE_PRESENT
+#define  LIB_DEF_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*                                CUSTOM LIBRARY MODULE VERSION NUMBER
+*
+* Note(s) : (1) (a) The custom library module software version is denoted as follows :
+*
+*                       Vx.yy.zz
+*
+*                           where
+*                                   V               denotes 'Version' label
+*                                   x               denotes     major software version revision number
+*                                   yy              denotes     minor software version revision number
+*                                   zz              denotes sub-minor software version revision number
+*
+*               (b) The software version label #define is formatted as follows :
+*
+*                       ver = x.yyzz * 100 * 100
+*
+*                           where
+*                                   ver             denotes software version number scaled as an integer value
+*                                   x.yyzz          denotes software version number, where the unscaled integer
+*                                                       portion denotes the major version number & the unscaled
+*                                                       fractional portion denotes the (concatenated) minor
+*                                                       version numbers
+*********************************************************************************************************
+*/
+
+#define  LIB_VERSION                                   13801u   /* See Note #1.                                         */
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*
+* Note(s) : (1) The custom library software files are located in the following directories :
+*
+*               (a) \<Custom Library Directory>\lib_*.*
+*
+*                       where
+*                               <Custom Library Directory>      directory path for custom library software
+*
+*           (2) CPU-configuration  software files are located in the following directories :
+*
+*               (a) \<CPU-Compiler Directory>\cpu_*.*
+*               (b) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.*
+*
+*                       where
+*                               <CPU-Compiler Directory>        directory path for common CPU-compiler software
+*                               <cpu>                           directory name for specific processor (CPU)
+*                               <compiler>                      directory name for specific compiler
+*
+*           (3) Compiler MUST be configured to include as additional include path directories :
+*
+*               (a) '\<Custom Library Directory>\' directory                            See Note #1a
+*
+*               (b) (1) '\<CPU-Compiler Directory>\'                  directory         See Note #2a
+*                   (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory         See Note #2b
+*********************************************************************************************************
+*/
+
+#include  <cpu_def.h>
+#include  <cpu.h>
+
+
+/*
+*********************************************************************************************************
+*                                          STANDARD DEFINES
+*********************************************************************************************************
+*/
+
+#define  DEF_NULL                                          0
+
+
+                                                                /* ----------------- BOOLEAN DEFINES ------------------ */
+#define  DEF_FALSE                                         0u
+#define  DEF_TRUE                                          1u
+
+#define  DEF_NO                                            0u
+#define  DEF_YES                                           1u
+
+#define  DEF_DISABLED                                      0u
+#define  DEF_ENABLED                                       1u
+
+#define  DEF_INACTIVE                                      0u
+#define  DEF_ACTIVE                                        1u
+
+#define  DEF_INVALID                                       0u
+#define  DEF_VALID                                         1u
+
+#define  DEF_OFF                                           0u
+#define  DEF_ON                                            1u
+
+#define  DEF_CLR                                           0u
+#define  DEF_SET                                           1u
+
+#define  DEF_FAIL                                          0u
+#define  DEF_OK                                            1u
+
+
+                                                                /* ------------------- BIT DEFINES -------------------- */
+#define  DEF_BIT_NONE                                   0x00u
+
+#define  DEF_BIT_00                                     0x01u
+#define  DEF_BIT_01                                     0x02u
+#define  DEF_BIT_02                                     0x04u
+#define  DEF_BIT_03                                     0x08u
+#define  DEF_BIT_04                                     0x10u
+#define  DEF_BIT_05                                     0x20u
+#define  DEF_BIT_06                                     0x40u
+#define  DEF_BIT_07                                     0x80u
+
+#define  DEF_BIT_08                                   0x0100u
+#define  DEF_BIT_09                                   0x0200u
+#define  DEF_BIT_10                                   0x0400u
+#define  DEF_BIT_11                                   0x0800u
+#define  DEF_BIT_12                                   0x1000u
+#define  DEF_BIT_13                                   0x2000u
+#define  DEF_BIT_14                                   0x4000u
+#define  DEF_BIT_15                                   0x8000u
+
+#define  DEF_BIT_16                               0x00010000u
+#define  DEF_BIT_17                               0x00020000u
+#define  DEF_BIT_18                               0x00040000u
+#define  DEF_BIT_19                               0x00080000u
+#define  DEF_BIT_20                               0x00100000u
+#define  DEF_BIT_21                               0x00200000u
+#define  DEF_BIT_22                               0x00400000u
+#define  DEF_BIT_23                               0x00800000u
+
+#define  DEF_BIT_24                               0x01000000u
+#define  DEF_BIT_25                               0x02000000u
+#define  DEF_BIT_26                               0x04000000u
+#define  DEF_BIT_27                               0x08000000u
+#define  DEF_BIT_28                               0x10000000u
+#define  DEF_BIT_29                               0x20000000u
+#define  DEF_BIT_30                               0x40000000u
+#define  DEF_BIT_31                               0x80000000u
+#define  DEF_BIT_32                       0x0000000100000000u
+#define  DEF_BIT_33                       0x0000000200000000u
+#define  DEF_BIT_34                       0x0000000400000000u
+#define  DEF_BIT_35                       0x0000000800000000u
+#define  DEF_BIT_36                       0x0000001000000000u
+#define  DEF_BIT_37                       0x0000002000000000u
+#define  DEF_BIT_38                       0x0000004000000000u
+#define  DEF_BIT_39                       0x0000008000000000u
+
+#define  DEF_BIT_40                       0x0000010000000000u
+#define  DEF_BIT_41                       0x0000020000000000u
+#define  DEF_BIT_42                       0x0000040000000000u
+#define  DEF_BIT_43                       0x0000080000000000u
+#define  DEF_BIT_44                       0x0000100000000000u
+#define  DEF_BIT_45                       0x0000200000000000u
+#define  DEF_BIT_46                       0x0000400000000000u
+#define  DEF_BIT_47                       0x0000800000000000u
+
+#define  DEF_BIT_48                       0x0001000000000000u
+#define  DEF_BIT_49                       0x0002000000000000u
+#define  DEF_BIT_50                       0x0004000000000000u
+#define  DEF_BIT_51                       0x0008000000000000u
+#define  DEF_BIT_52                       0x0010000000000000u
+#define  DEF_BIT_53                       0x0020000000000000u
+#define  DEF_BIT_54                       0x0040000000000000u
+#define  DEF_BIT_55                       0x0080000000000000u
+
+#define  DEF_BIT_56                       0x0100000000000000u
+#define  DEF_BIT_57                       0x0200000000000000u
+#define  DEF_BIT_58                       0x0400000000000000u
+#define  DEF_BIT_59                       0x0800000000000000u
+#define  DEF_BIT_60                       0x1000000000000000u
+#define  DEF_BIT_61                       0x2000000000000000u
+#define  DEF_BIT_62                       0x4000000000000000u
+#define  DEF_BIT_63                       0x8000000000000000u
+
+
+                                                                /* ------------------ ALIGN DEFINES ------------------- */
+#define  DEF_ALIGN_MAX_NBR_OCTETS                       4096u
+
+
+                                                                /* ------------------ OCTET DEFINES ------------------- */
+#define  DEF_OCTET_NBR_BITS                                8u
+#define  DEF_OCTET_MASK                                 0xFFu
+
+#define  DEF_OCTET_TO_BIT_NBR_BITS                         3u
+#define  DEF_OCTET_TO_BIT_SHIFT                          DEF_OCTET_TO_BIT_NBR_BITS
+#define  DEF_OCTET_TO_BIT_MASK                          0x07u
+
+
+#define  DEF_NIBBLE_NBR_BITS                               4u
+#define  DEF_NIBBLE_MASK                                0x0Fu
+
+
+                                                                /* --------------- NUMBER BASE DEFINES ---------------- */
+#define  DEF_NBR_BASE_BIN                                  2u
+#define  DEF_NBR_BASE_OCT                                  8u
+#define  DEF_NBR_BASE_DEC                                 10u
+#define  DEF_NBR_BASE_HEX                                 16u
+
+
+                                                                /* ----------------- INTEGER DEFINES ------------------ */
+#define  DEF_INT_08_NBR_BITS                               8u
+#define  DEF_INT_08_MASK                                0xFFu
+
+#define  DEF_INT_08U_MIN_VAL                               0u
+#define  DEF_INT_08U_MAX_VAL                             255u
+
+#define  DEF_INT_08S_MIN_VAL_ONES_CPL                  (-127)
+#define  DEF_INT_08S_MAX_VAL_ONES_CPL                    127
+
+#define  DEF_INT_08S_MIN_VAL                            (DEF_INT_08S_MIN_VAL_ONES_CPL - 1)
+#define  DEF_INT_08S_MAX_VAL                             DEF_INT_08S_MAX_VAL_ONES_CPL
+
+#define  DEF_INT_08U_NBR_DIG_MIN                           1u
+#define  DEF_INT_08U_NBR_DIG_MAX                           3u
+
+#define  DEF_INT_08S_NBR_DIG_MIN                           3u
+#define  DEF_INT_08S_NBR_DIG_MAX                           3u
+
+
+
+#define  DEF_INT_16_NBR_BITS                              16u
+#define  DEF_INT_16_MASK                              0xFFFFu
+
+#define  DEF_INT_16U_MIN_VAL                               0u
+#define  DEF_INT_16U_MAX_VAL                           65535u
+
+#define  DEF_INT_16S_MIN_VAL_ONES_CPL                (-32767)
+#define  DEF_INT_16S_MAX_VAL_ONES_CPL                  32767
+
+#define  DEF_INT_16S_MIN_VAL                            (DEF_INT_16S_MIN_VAL_ONES_CPL - 1)
+#define  DEF_INT_16S_MAX_VAL                             DEF_INT_16S_MAX_VAL_ONES_CPL
+
+#define  DEF_INT_16U_NBR_DIG_MIN                           1u
+#define  DEF_INT_16U_NBR_DIG_MAX                           5u
+
+#define  DEF_INT_16S_NBR_DIG_MIN                           5u
+#define  DEF_INT_16S_NBR_DIG_MAX                           5u
+
+
+
+#define  DEF_INT_32_NBR_BITS                              32u
+#define  DEF_INT_32_MASK                          0xFFFFFFFFu
+
+#define  DEF_INT_32U_MIN_VAL                               0u
+#define  DEF_INT_32U_MAX_VAL                      4294967295u
+
+#define  DEF_INT_32S_MIN_VAL_ONES_CPL           (-2147483647)
+#define  DEF_INT_32S_MAX_VAL_ONES_CPL             2147483647
+
+#define  DEF_INT_32S_MIN_VAL                            (DEF_INT_32S_MIN_VAL_ONES_CPL - 1)
+#define  DEF_INT_32S_MAX_VAL                             DEF_INT_32S_MAX_VAL_ONES_CPL
+
+#define  DEF_INT_32U_NBR_DIG_MIN                           1u
+#define  DEF_INT_32U_NBR_DIG_MAX                          10u
+
+#define  DEF_INT_32S_NBR_DIG_MIN                          10u
+#define  DEF_INT_32S_NBR_DIG_MAX                          10u
+
+
+
+#define  DEF_INT_64_NBR_BITS                              64u
+#define  DEF_INT_64_MASK                  0xFFFFFFFFFFFFFFFFu
+
+#define  DEF_INT_64U_MIN_VAL                               0u
+#define  DEF_INT_64U_MAX_VAL            18446744073709551615u
+
+#define  DEF_INT_64S_MIN_VAL_ONES_CPL  (-9223372036854775807)
+#define  DEF_INT_64S_MAX_VAL_ONES_CPL    9223372036854775807
+
+#define  DEF_INT_64S_MIN_VAL                            (DEF_INT_64S_MIN_VAL_ONES_CPL - 1)
+#define  DEF_INT_64S_MAX_VAL                             DEF_INT_64S_MAX_VAL_ONES_CPL
+
+#define  DEF_INT_64U_NBR_DIG_MIN                           1u
+#define  DEF_INT_64U_NBR_DIG_MAX                          20u
+
+#define  DEF_INT_64S_NBR_DIG_MIN                          19u
+#define  DEF_INT_64S_NBR_DIG_MAX                          19u
+
+
+                                                                /* --------------- CPU INTEGER DEFINES ---------------- */
+#define  DEF_INT_CPU_NBR_BITS                           (CPU_CFG_DATA_SIZE     * DEF_OCTET_NBR_BITS)
+#define  DEF_INT_CPU_NBR_BITS_MAX                       (CPU_CFG_DATA_SIZE_MAX * DEF_OCTET_NBR_BITS)
+
+
+
+#if     (DEF_INT_CPU_NBR_BITS == DEF_INT_08_NBR_BITS)
+
+
+#define  DEF_INT_CPU_MASK                                DEF_INT_08_MASK
+
+#define  DEF_INT_CPU_U_MIN_VAL                           DEF_INT_08U_MIN_VAL
+#define  DEF_INT_CPU_U_MAX_VAL                           DEF_INT_08U_MAX_VAL
+
+#define  DEF_INT_CPU_S_MIN_VAL                           DEF_INT_08S_MIN_VAL
+#define  DEF_INT_CPU_S_MAX_VAL                           DEF_INT_08S_MAX_VAL
+
+#define  DEF_INT_CPU_S_MIN_VAL_ONES_CPL                  DEF_INT_08S_MIN_VAL_ONES_CPL
+#define  DEF_INT_CPU_S_MAX_VAL_ONES_CPL                  DEF_INT_08S_MAX_VAL_ONES_CPL
+
+
+
+#elif   (DEF_INT_CPU_NBR_BITS == DEF_INT_16_NBR_BITS)
+
+
+#define  DEF_INT_CPU_MASK                                DEF_INT_16_MASK
+
+#define  DEF_INT_CPU_U_MIN_VAL                           DEF_INT_16U_MIN_VAL
+#define  DEF_INT_CPU_U_MAX_VAL                           DEF_INT_16U_MAX_VAL
+
+#define  DEF_INT_CPU_S_MIN_VAL                           DEF_INT_16S_MIN_VAL
+#define  DEF_INT_CPU_S_MAX_VAL                           DEF_INT_16S_MAX_VAL
+
+#define  DEF_INT_CPU_S_MIN_VAL_ONES_CPL                  DEF_INT_16S_MIN_VAL_ONES_CPL
+#define  DEF_INT_CPU_S_MAX_VAL_ONES_CPL                  DEF_INT_16S_MAX_VAL_ONES_CPL
+
+
+
+#elif   (DEF_INT_CPU_NBR_BITS == DEF_INT_32_NBR_BITS)
+
+
+#define  DEF_INT_CPU_MASK                                DEF_INT_32_MASK
+
+#define  DEF_INT_CPU_U_MIN_VAL                           DEF_INT_32U_MIN_VAL
+#define  DEF_INT_CPU_U_MAX_VAL                           DEF_INT_32U_MAX_VAL
+
+#define  DEF_INT_CPU_S_MIN_VAL                           DEF_INT_32S_MIN_VAL
+#define  DEF_INT_CPU_S_MAX_VAL                           DEF_INT_32S_MAX_VAL
+
+#define  DEF_INT_CPU_S_MIN_VAL_ONES_CPL                  DEF_INT_32S_MIN_VAL_ONES_CPL
+#define  DEF_INT_CPU_S_MAX_VAL_ONES_CPL                  DEF_INT_32S_MAX_VAL_ONES_CPL
+
+
+
+#elif   (DEF_INT_CPU_NBR_BITS == DEF_INT_64_NBR_BITS)
+
+
+#define  DEF_INT_CPU_MASK                                DEF_INT_64_MASK
+
+#define  DEF_INT_CPU_U_MIN_VAL                           DEF_INT_64U_MIN_VAL
+#define  DEF_INT_CPU_U_MAX_VAL                           DEF_INT_64U_MAX_VAL
+
+#define  DEF_INT_CPU_S_MIN_VAL                           DEF_INT_64S_MIN_VAL
+#define  DEF_INT_CPU_S_MAX_VAL                           DEF_INT_64S_MAX_VAL
+
+#define  DEF_INT_CPU_S_MIN_VAL_ONES_CPL                  DEF_INT_64S_MIN_VAL_ONES_CPL
+#define  DEF_INT_CPU_S_MAX_VAL_ONES_CPL                  DEF_INT_64S_MAX_VAL_ONES_CPL
+
+
+
+#else
+
+#error  "CPU_CFG_DATA_SIZE  illegally #defined in 'cpu.h'      "
+#error  "                   [See 'cpu.h  CONFIGURATION ERRORS']"
+
+#endif
+
+
+                                                                /* ------------------- TIME DEFINES ------------------- */
+#define  DEF_TIME_NBR_DAY_PER_WK                           7u
+#define  DEF_TIME_NBR_DAY_PER_YR                         365u
+#define  DEF_TIME_NBR_DAY_PER_YR_LEAP                    366u
+
+#define  DEF_TIME_NBR_HR_PER_DAY                          24u
+#define  DEF_TIME_NBR_HR_PER_WK                         (DEF_TIME_NBR_HR_PER_DAY  * DEF_TIME_NBR_DAY_PER_WK     )
+#define  DEF_TIME_NBR_HR_PER_YR                         (DEF_TIME_NBR_HR_PER_DAY  * DEF_TIME_NBR_DAY_PER_YR     )
+#define  DEF_TIME_NBR_HR_PER_YR_LEAP                    (DEF_TIME_NBR_HR_PER_DAY  * DEF_TIME_NBR_DAY_PER_YR_LEAP)
+
+#define  DEF_TIME_NBR_MIN_PER_HR                          60u
+#define  DEF_TIME_NBR_MIN_PER_DAY                       (DEF_TIME_NBR_MIN_PER_HR  * DEF_TIME_NBR_HR_PER_DAY     )
+#define  DEF_TIME_NBR_MIN_PER_WK                        (DEF_TIME_NBR_MIN_PER_DAY * DEF_TIME_NBR_DAY_PER_WK     )
+#define  DEF_TIME_NBR_MIN_PER_YR                        (DEF_TIME_NBR_MIN_PER_DAY * DEF_TIME_NBR_DAY_PER_YR     )
+#define  DEF_TIME_NBR_MIN_PER_YR_LEAP                   (DEF_TIME_NBR_MIN_PER_DAY * DEF_TIME_NBR_DAY_PER_YR_LEAP)
+
+#define  DEF_TIME_NBR_SEC_PER_MIN                         60u
+#define  DEF_TIME_NBR_SEC_PER_HR                        (DEF_TIME_NBR_SEC_PER_MIN * DEF_TIME_NBR_MIN_PER_HR     )
+#define  DEF_TIME_NBR_SEC_PER_DAY                       (DEF_TIME_NBR_SEC_PER_HR  * DEF_TIME_NBR_HR_PER_DAY     )
+#define  DEF_TIME_NBR_SEC_PER_WK                        (DEF_TIME_NBR_SEC_PER_DAY * DEF_TIME_NBR_DAY_PER_WK     )
+#define  DEF_TIME_NBR_SEC_PER_YR                        (DEF_TIME_NBR_SEC_PER_DAY * DEF_TIME_NBR_DAY_PER_YR     )
+#define  DEF_TIME_NBR_SEC_PER_YR_LEAP                   (DEF_TIME_NBR_SEC_PER_DAY * DEF_TIME_NBR_DAY_PER_YR_LEAP)
+
+#define  DEF_TIME_NBR_mS_PER_SEC                        1000u
+#define  DEF_TIME_NBR_uS_PER_SEC                     1000000u
+#define  DEF_TIME_NBR_nS_PER_SEC                  1000000000u
+
+
+/*
+*********************************************************************************************************
+*                                             ERROR CODES
+*
+* Note(s) : (1) All library error codes are #define'd in 'lib_def.h';
+*********************************************************************************************************
+*/
+
+typedef enum lib_err {
+
+    LIB_ERR_NONE                            =         0u,
+
+    LIB_MEM_ERR_NONE                        =     10000u,
+    LIB_MEM_ERR_NULL_PTR                    =     10001u,       /* Ptr arg(s) passed NULL ptr(s).                       */
+
+    LIB_MEM_ERR_INVALID_MEM_SIZE            =     10100u,       /* Invalid mem     size.                                */
+    LIB_MEM_ERR_INVALID_MEM_ALIGN           =     10101u,       /* Invalid mem     align.                               */
+    LIB_MEM_ERR_INVALID_SEG_SIZE            =     10110u,       /* Invalid mem seg size.                                */
+    LIB_MEM_ERR_INVALID_SEG_OVERLAP         =     10111u,       /* Invalid mem seg overlaps other mem seg(s).           */
+    LIB_MEM_ERR_INVALID_SEG_EXISTS          =     10112u,       /* Invalid mem seg already exists.                      */
+    LIB_MEM_ERR_INVALID_POOL                =     10120u,       /* Invalid mem pool.                                    */
+    LIB_MEM_ERR_INVALID_BLK_NBR             =     10130u,       /* Invalid mem pool blk nbr.                            */
+    LIB_MEM_ERR_INVALID_BLK_SIZE            =     10131u,       /* Invalid mem pool blk size.                           */
+    LIB_MEM_ERR_INVALID_BLK_ALIGN           =     10132u,       /* Invalid mem pool blk align.                          */
+    LIB_MEM_ERR_INVALID_BLK_IX              =     10133u,       /* Invalid mem pool ix.                                 */
+    LIB_MEM_ERR_INVALID_BLK_ADDR            =     10135u,       /* Invalid mem pool blk addr.                           */
+    LIB_MEM_ERR_INVALID_BLK_ADDR_IN_POOL    =     10136u,       /* Mem pool blk addr already in mem pool.               */
+
+    LIB_MEM_ERR_SEG_EMPTY                   =     10200u,       /* Mem seg  empty; i.e. NO avail mem in seg.            */
+    LIB_MEM_ERR_SEG_OVF                     =     10201u,       /* Mem seg  ovf;   i.e. req'd mem ovfs rem mem in seg.  */
+    LIB_MEM_ERR_POOL_FULL                   =     10205u,       /* Mem pool full;  i.e. all mem blks avail in mem pool. */
+    LIB_MEM_ERR_POOL_EMPTY                  =     10206u,       /* Mem pool empty; i.e. NO  mem blks avail in mem pool. */
+    LIB_MEM_ERR_POOL_UNLIMITED              =     10207u,       /* Mem pool is unlimited.                               */
+
+    LIB_MEM_ERR_HEAP_EMPTY                  =     10210u,       /* Heap seg empty; i.e. NO avail mem in heap.           */
+    LIB_MEM_ERR_HEAP_OVF                    =     10211u,       /* Heap seg ovf;   i.e. req'd mem ovfs rem mem in heap. */
+    LIB_MEM_ERR_HEAP_NOT_FOUND              =     10215u        /* Heap seg NOT found.                                  */
+
+} LIB_ERR;
+
+
+/*
+*********************************************************************************************************
+*                                             DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               TRACING
+*********************************************************************************************************
+*/
+
+                                                                /* Trace level, default to TRACE_LEVEL_OFF.             */
+#ifndef  TRACE_LEVEL_OFF
+#define  TRACE_LEVEL_OFF                                   0u
+#endif
+
+#ifndef  TRACE_LEVEL_INFO
+#define  TRACE_LEVEL_INFO                                  1u
+#endif
+
+#ifndef  TRACE_LEVEL_DBG
+#define  TRACE_LEVEL_DBG                                   2u
+#endif
+
+#ifndef  TRACE_LEVEL_LOG
+#define  TRACE_LEVEL_LOG                                   3u
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             BIT MACRO'S
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                              DEF_BIT()
+*
+* Description : Create bit mask with single, specified bit set.
+*
+* Argument(s) : bit         Bit number of bit to set.
+*
+* Return(s)   : Bit mask with single, specified bit set.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'bit' SHOULD be a non-negative integer.
+*
+*               (2) (a) 'bit' values that overflow the target CPU &/or compiler environment (e.g. negative
+*                       or greater-than-CPU-data-size values) MAY generate compiler warnings &/or errors.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT(bit)                                                   (1u << (bit))
+
+
+/*
+*********************************************************************************************************
+*                                             DEF_BITxx()
+*
+* Description : Create bit mask of specified bit size with single, specified bit set.
+*
+* Argument(s) : bit         Bit number of bit to set.
+*
+* Return(s)   : Bit mask with single, specified bit set.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'bit' SHOULD be a non-negative integer.
+*
+*               (2) (a) 'bit' values that overflow the target CPU &/or compiler environment (e.g. negative
+*                       or greater-than-CPU-data-size values) MAY generate compiler warnings &/or errors.
+*
+*                   (b) To avoid overflowing any target CPU &/or compiler's integer data type, unsigned
+*                       bit constant '1' is cast to specified integer data type size.
+*
+*               (3) Ideally, DEF_BITxx() macro's should be named DEF_BIT_xx(); however, these names already
+*                   previously-released for bit constant #define's (see 'STANDARD DEFINES  BIT DEFINES').
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT08(bit)                        ((CPU_INT08U)((CPU_INT08U)1u  << (bit)))
+
+#define  DEF_BIT16(bit)                        ((CPU_INT16U)((CPU_INT16U)1u  << (bit)))
+
+#define  DEF_BIT32(bit)                        ((CPU_INT32U)((CPU_INT32U)1u  << (bit)))
+
+#define  DEF_BIT64(bit)                        ((CPU_INT64U)((CPU_INT64U)1u  << (bit)))
+
+
+/*
+*********************************************************************************************************
+*                                           DEF_BIT_MASK()
+*
+* Description : Shift a bit mask.
+*
+* Argument(s) : bit_mask    Bit mask to shift.
+*
+*               bit_shift   Number of bit positions to left-shift bit mask.
+*
+* Return(s)   : Shifted bit mask.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) 'bit_mask'  SHOULD be an unsigned    integer.
+*
+*                   (b) 'bit_shift' SHOULD be a non-negative integer.
+*
+*               (2) 'bit_shift' values that overflow the target CPU &/or compiler environment (e.g. negative
+*                   or greater-than-CPU-data-size values) MAY generate compiler warnings &/or errors.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_MASK(bit_mask, bit_shift)                                     ((bit_mask) << (bit_shift))
+
+
+/*
+*********************************************************************************************************
+*                                          DEF_BIT_MASK_xx()
+*
+* Description : Shift a bit mask of specified bit size.
+*
+* Argument(s) : bit_mask    Bit mask to shift.
+*
+*               bit_shift   Number of bit positions to left-shift bit mask.
+*
+* Return(s)   : Shifted bit mask.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) 'bit_mask'  SHOULD be an unsigned    integer.
+*
+*                   (b) 'bit_shift' SHOULD be a non-negative integer.
+*
+*               (2) 'bit_shift' values that overflow the target CPU &/or compiler environment (e.g. negative
+*                   or greater-than-CPU-data-size values) MAY generate compiler warnings &/or errors.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_MASK_08(bit_mask, bit_shift)         ((CPU_INT08U)((CPU_INT08U)(bit_mask) << (bit_shift)))
+
+#define  DEF_BIT_MASK_16(bit_mask, bit_shift)         ((CPU_INT16U)((CPU_INT16U)(bit_mask) << (bit_shift)))
+
+#define  DEF_BIT_MASK_32(bit_mask, bit_shift)         ((CPU_INT32U)((CPU_INT32U)(bit_mask) << (bit_shift)))
+
+#define  DEF_BIT_MASK_64(bit_mask, bit_shift)         ((CPU_INT64U)((CPU_INT64U)(bit_mask) << (bit_shift)))
+
+
+/*
+*********************************************************************************************************
+*                                           DEF_BIT_FIELD()
+*
+* Description : Create & shift a contiguous bit field.
+*
+* Argument(s) : bit_field   Number of contiguous bits to set in the bit field.
+*
+*               bit_shift   Number of bit positions   to left-shift bit field.
+*
+* Return(s)   : Shifted bit field.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'bit_field' & 'bit_shift' SHOULD be non-negative integers.
+*
+*               (2) (a) 'bit_field'/'bit_shift' values that overflow the target CPU &/or compiler
+*                       environment (e.g. negative or greater-than-CPU-data-size values) MAY generate
+*                       compiler warnings &/or errors.
+*
+*                   (b) To avoid overflowing any target CPU &/or compiler's integer data type, unsigned
+*                       bit constant '1' is suffixed with 'L'ong integer modifier.
+*
+*                       This may still be insufficient for CPUs &/or compilers that support 'long long'
+*                       integer data types, in which case 'LL' integer modifier should be suffixed.
+*                       However, since almost all 16- & 32-bit CPUs & compilers support 'long' integer
+*                       data types but many may NOT support 'long long' integer data types, only 'long'
+*                       integer data types & modifiers are supported.
+*
+*                       See also 'DEF_BIT_FIELD_xx()  Note #1b'.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_FIELD(bit_field, bit_shift)                                 ((((bit_field) >= DEF_INT_CPU_NBR_BITS) ? (DEF_INT_CPU_U_MAX_VAL)     \
+                                                                                                                     : (DEF_BIT(bit_field) - 1uL)) \
+                                                                                                                            << (bit_shift))
+
+/*
+*********************************************************************************************************
+*                                         DEF_BIT_FIELD_xx()
+*
+* Description : Create & shift a contiguous bit field of specified bit size.
+*
+* Argument(s) : bit_field   Number of contiguous bits to set in the bit field.
+*
+*               bit_shift   Number of bit positions   to left-shift bit field.
+*
+* Return(s)   : Shifted bit field.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'bit_field' & 'bit_shift' SHOULD be non-negative integers.
+*
+*               (2) (a) 'bit_field'/'bit_shift' values that overflow the target CPU &/or compiler
+*                       environment (e.g. negative or greater-than-CPU-data-size values) MAY generate
+*                       compiler warnings &/or errors.
+*
+*                   (b) To avoid overflowing any target CPU &/or compiler's integer data type, unsigned
+*                       bit constant '1' is cast to specified integer data type size.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_FIELD_08(bit_field, bit_shift)     ((CPU_INT08U)((((CPU_INT08U)(bit_field) >= (CPU_INT08U)DEF_INT_08_NBR_BITS) ? (CPU_INT08U)(DEF_INT_08U_MAX_VAL)                    \
+                                                                                                                                : (CPU_INT08U)(DEF_BIT08(bit_field) - (CPU_INT08U)1u)) \
+                                                                                                                                                     << (bit_shift)))
+
+#define  DEF_BIT_FIELD_16(bit_field, bit_shift)     ((CPU_INT16U)((((CPU_INT16U)(bit_field) >= (CPU_INT16U)DEF_INT_16_NBR_BITS) ? (CPU_INT16U)(DEF_INT_16U_MAX_VAL)                    \
+                                                                                                                                : (CPU_INT16U)(DEF_BIT16(bit_field) - (CPU_INT16U)1u)) \
+                                                                                                                                                     << (bit_shift)))
+
+#define  DEF_BIT_FIELD_32(bit_field, bit_shift)     ((CPU_INT32U)((((CPU_INT32U)(bit_field) >= (CPU_INT32U)DEF_INT_32_NBR_BITS) ? (CPU_INT32U)(DEF_INT_32U_MAX_VAL)                    \
+                                                                                                                                : (CPU_INT32U)(DEF_BIT32(bit_field) - (CPU_INT32U)1u)) \
+                                                                                                                                                     << (bit_shift)))
+
+#define  DEF_BIT_FIELD_64(bit_field, bit_shift)     ((CPU_INT64U)((((CPU_INT64U)(bit_field) >= (CPU_INT64U)DEF_INT_64_NBR_BITS) ? (CPU_INT64U)(DEF_INT_64U_MAX_VAL)                    \
+                                                                                                                                : (CPU_INT64U)(DEF_BIT64(bit_field) - (CPU_INT64U)1u)) \
+                                                                                                                                                     << (bit_shift)))
+
+
+/*
+*********************************************************************************************************
+*                                            DEF_BIT_SET()
+*
+* Description : Set specified bit(s) in a value.
+*
+* Argument(s) : val         Value to modify by setting specified bit(s).
+*
+*               mask        Mask of bits to set.
+*
+* Return(s)   : Modified value with specified bit(s) set.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'val' & 'mask' SHOULD be unsigned integers.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_SET(val, mask)                        ((val) = ((val) | (mask)))
+
+
+/*
+*********************************************************************************************************
+*                                          DEF_BIT_SET_xx()
+*
+* Description : Set specified bit(s) in a value of specified bit size.
+*
+* Argument(s) : val         Value to modify by setting specified bit(s).
+*
+*               mask        Mask of bits to set.
+*
+* Return(s)   : Modified value with specified bit(s) set.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'val' & 'mask' SHOULD be unsigned integers.
+*
+*               (2) These macros are deprecated and should be replaced by the DEF_BIT_SET macro.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_SET_08(val, mask)                     DEF_BIT_SET((val), (mask))
+
+#define  DEF_BIT_SET_16(val, mask)                     DEF_BIT_SET((val), (mask))
+
+#define  DEF_BIT_SET_32(val, mask)                     DEF_BIT_SET((val), (mask))
+
+#define  DEF_BIT_SET_64(val, mask)                     DEF_BIT_SET((val), (mask))
+
+
+/*
+*********************************************************************************************************
+*                                            DEF_BIT_CLR()
+*
+* Description : Clear specified bit(s) in a value.
+*
+* Argument(s) : val         Value to modify by clearing specified bit(s).
+*
+*               mask        Mask of bits to clear.
+*
+* Return(s)   : Modified value with specified bit(s) clear.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'val' & 'mask' SHOULD be unsigned integers.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_CLR(val, mask)                        ((val) = ((val) & ~(mask)))
+
+
+/*
+*********************************************************************************************************
+*                                          DEF_BIT_CLR_xx()
+*
+* Description : Clear specified bit(s) in a value of specified bit size.
+*
+* Argument(s) : val         Value to modify by clearing specified bit(s).
+*
+*               mask        Mask of bits to clear.
+*
+* Return(s)   : Modified value with specified bit(s) clear.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'val' & 'mask' SHOULD be unsigned integers.
+*
+*               (2) These macros are deprecated and should be replaced by the DEF_BIT_CLR macro.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_CLR_08(val, mask)                     DEF_BIT_CLR((val), (mask))
+
+#define  DEF_BIT_CLR_16(val, mask)                     DEF_BIT_CLR((val), (mask))
+
+#define  DEF_BIT_CLR_32(val, mask)                     DEF_BIT_CLR((val), (mask))
+
+#define  DEF_BIT_CLR_64(val, mask)                     DEF_BIT_CLR((val), (mask))
+
+
+/*
+*********************************************************************************************************
+*                                            DEF_BIT_TOGGLE()
+*
+* Description : Toggles specified bit(s) in a value.
+*
+* Argument(s) : val         Value to modify by toggling specified bit(s).
+*
+*               mask        Mask of bits to toggle.
+*
+* Return(s)   : Modified value with specified bit(s) toggled.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'val' & 'mask' SHOULD be unsigned integers.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_TOGGLE(val, mask)                      ((val) ^= (mask))
+
+
+/*
+*********************************************************************************************************
+*                                           DEF_BIT_FIELD_RD()
+*
+* Description : Reads a 'val' field, masked and shifted, given by mask 'field_mask'.
+*
+* Argument(s) : val         Value to read from.
+*
+*               field_mask  Mask of field to read. See note #1, #2 and #3.
+*
+* Return(s)   : Field value, masked and right-shifted to bit position 0.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'field_mask' argument must NOT be 0.
+*
+*               (2) 'field_mask' argument must contain a mask with contiguous set bits.
+*
+*               (3) 'val' & 'field_mask' SHOULD be unsigned integers.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_FIELD_RD(val, field_mask)              (((val) & (field_mask)) / ((field_mask) & ~((field_mask) << 1u)))
+
+
+/*
+*********************************************************************************************************
+*                                          DEF_BIT_FIELD_ENC()
+*
+* Description : Encodes given 'field_val' at position given by mask 'field_mask'.
+*
+* Argument(s) : field_val   Value to encode.
+*
+*               field_mask  Mask of field to read. See note #1 and #2.
+*
+* Return(s)   : Field value, masked and left-shifted to field position.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'field_mask' argument must contain a mask with contiguous set bits.
+*
+*               (2) 'field_val' & 'field_mask' SHOULD be unsigned integers.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_FIELD_ENC(field_val, field_mask)       (((field_val) * ((field_mask) & ~((field_mask) << 1u))) & (field_mask))
+
+
+/*
+*********************************************************************************************************
+*                                           DEF_BIT_FIELD_WR()
+*
+* Description : Writes 'field_val' field at position given by mask 'field_mask' in variable 'var'.
+*
+* Argument(s) : var         Variable to write field to. See note #2.
+*
+*               field_val   Desired value for field. See note #2.
+*
+*               field_mask  Mask of field to write to. See note #1 and #2.
+*
+* Return(s)   : None.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'field_mask' argument must contain a mask with contiguous set bits.
+*
+*               (2) 'var', 'field_val' & 'field_mask' SHOULD be unsigned integers.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_FIELD_WR(var, field_val, field_mask)   (var) = (((var) & ~(field_mask)) | DEF_BIT_FIELD_ENC((field_val), (field_mask)))
+
+
+/*
+*********************************************************************************************************
+*                                          DEF_BIT_IS_SET()
+*
+* Description : Determine if specified bit(s) in a value are set.
+*
+* Argument(s) : val         Value to check for specified bit(s) set.
+*
+*               mask        Mask of bits to check if set (see Note #2).
+*
+* Return(s)   : DEF_YES, if ALL specified bit(s) are     set in value.
+*
+*               DEF_NO,  if ALL specified bit(s) are NOT set in value.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'val' & 'mask' SHOULD be unsigned integers.
+*
+*               (2) NULL 'mask' allowed; returns 'DEF_NO' since NO mask bits specified.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_IS_SET(val, mask)                    (((((val) & (mask)) == (mask)) && \
+                                                         ((mask)          !=  0u))    ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                          DEF_BIT_IS_CLR()
+*
+* Description : Determine if specified bit(s) in a value are clear.
+*
+* Argument(s) : val         Value to check for specified bit(s) clear.
+*
+*               mask        Mask of bits to check if clear (see Note #2).
+*
+* Return(s)   : DEF_YES, if ALL specified bit(s) are     clear in value.
+*
+*               DEF_NO,  if ALL specified bit(s) are NOT clear in value.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'val' & 'mask' SHOULD be unsigned integers.
+*
+*               (2) NULL 'mask' allowed; returns 'DEF_NO' since NO mask bits specified.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_IS_CLR(val, mask)                    (((((val) & (mask)) ==  0u)  && \
+                                                         ((mask)          !=  0u))  ? (DEF_YES) : (DEF_NO))
+
+
+/*
+*********************************************************************************************************
+*                                        DEF_BIT_IS_SET_ANY()
+*
+* Description : Determine if any specified bit(s) in a value are set.
+*
+* Argument(s) : val         Value to check for specified bit(s) set.
+*
+*               mask        Mask of bits to check if set (see Note #2).
+*
+* Return(s)   : DEF_YES, if ANY specified bit(s) are     set in value.
+*
+*               DEF_NO,  if ALL specified bit(s) are NOT set in value.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'val' & 'mask' SHOULD be unsigned integers.
+*
+*               (2) NULL 'mask' allowed; returns 'DEF_NO' since NO mask bits specified.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_IS_SET_ANY(val, mask)               ((((val) & (mask)) ==  0u)     ? (DEF_NO ) : (DEF_YES))
+
+
+/*
+*********************************************************************************************************
+*                                        DEF_BIT_IS_CLR_ANY()
+*
+* Description : Determine if any specified bit(s) in a value are clear.
+*
+* Argument(s) : val         Value to check for specified bit(s) clear.
+*
+*               mask        Mask of bits to check if clear (see Note #2).
+*
+* Return(s)   : DEF_YES, if ANY specified bit(s) are     clear in value.
+*
+*               DEF_NO,  if ALL specified bit(s) are NOT clear in value.
+*
+* Note(s)     : (1) 'val' & 'mask' SHOULD be unsigned integers.
+*
+*               (2) NULL 'mask' allowed; returns 'DEF_NO' since NO mask bits specified.
+*********************************************************************************************************
+*/
+
+#define  DEF_BIT_IS_CLR_ANY(val, mask)               ((((val) & (mask)) == (mask))  ? (DEF_NO ) : (DEF_YES))
+
+
+/*
+*********************************************************************************************************
+*                                            VALUE MACRO'S
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                          DEF_CHK_VAL_MIN()
+*
+* Description : Validate a value as greater than or equal to a specified minimum value.
+*
+* Argument(s) : val        Value to validate.
+*
+*               val_min    Minimum value to test.
+*
+* Return(s)   : DEF_OK,    Value is greater than or equal to minimum value.
+*
+*               DEF_FAIL,  otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) DEF_CHK_VAL_MIN() avoids directly comparing any two values if only one of the values
+*                   is negative since the negative value might be incorrectly promoted to an arbitrary
+*                   unsigned value if the other value to compare is unsigned.
+*
+*               (2) Validation of values is limited to the range supported by the compiler &/or target
+*                   environment.  All other values that underflow/overflow the supported range will
+*                   modulo/wrap into the supported range as arbitrary signed or unsigned values.
+*
+*                   Therefore, any values that underflow the most negative signed value or overflow
+*                   the most positive unsigned value supported by the compiler &/or target environment
+*                   cannot be validated :
+*
+*                           (    N-1       N     ]
+*                           ( -(2   )  ,  2  - 1 ]
+*                           (                    ]
+*
+*                               where
+*                                       N       Number of data word bits supported by the compiler
+*                                                   &/or target environment
+*
+*                   (a) Note that the most negative value, -2^(N-1), is NOT included in the supported
+*                       range since many compilers do NOT always correctly handle this value.
+*
+*               (3) 'val' and 'val_min' are compared to 1 instead of 0 to avoid warning generated for
+*                   unsigned numbers.
+*********************************************************************************************************
+*/
+
+#define  DEF_CHK_VAL_MIN(val, val_min)            (((!(((val)     >= 1) && ((val_min) < 1))) && \
+                                                     ((((val_min) >= 1) && ((val)     < 1))  || \
+                                                       ((val) < (val_min)))) ? DEF_FAIL : DEF_OK)
+
+
+/*
+*********************************************************************************************************
+*                                          DEF_CHK_VAL_MAX()
+*
+* Description : Validate a value as less than or equal to a specified maximum value.
+*
+* Argument(s) : val        Value to validate.
+*
+*               val_max    Maximum value to test.
+*
+* Return(s)   : DEF_OK,    Value is less than or equal to maximum value.
+*
+*               DEF_FAIL,  otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) DEF_CHK_VAL_MAX() avoids directly comparing any two values if only one of the values
+*                   is negative since the negative value might be incorrectly promoted to an arbitrary
+*                   unsigned value if the other value to compare is unsigned.
+*
+*               (2) Validation of values is limited to the range supported by the compiler &/or target
+*                   environment.  All other values that underflow/overflow the supported range will
+*                   modulo/wrap into the supported range as arbitrary signed or unsigned values.
+*
+*                   Therefore, any values that underflow the most negative signed value or overflow
+*                   the most positive unsigned value supported by the compiler &/or target environment
+*                   cannot be validated :
+*
+*                           (    N-1       N     ]
+*                           ( -(2   )  ,  2  - 1 ]
+*                           (                    ]
+*
+*                               where
+*                                       N       Number of data word bits supported by the compiler
+*                                                   &/or target environment
+*
+*                   (a) Note that the most negative value, -2^(N-1), is NOT included in the supported
+*                       range since many compilers do NOT always correctly handle this value.
+*
+*               (3) 'val' and 'val_max' are compared to 1 instead of 0 to avoid warning generated for
+*                   unsigned numbers.
+*********************************************************************************************************
+*/
+
+#define  DEF_CHK_VAL_MAX(val, val_max)            (((!(((val_max) >= 1) && ((val)     < 1))) && \
+                                                     ((((val)     >= 1) && ((val_max) < 1))  || \
+                                                       ((val) > (val_max)))) ? DEF_FAIL : DEF_OK)
+
+
+/*
+*********************************************************************************************************
+*                                            DEF_CHK_VAL()
+*
+* Description : Validate a value as greater than or equal to a specified minimum value & less than or
+*                   equal to a specified maximum value.
+*
+* Argument(s) : val        Value to validate.
+*
+*               val_min    Minimum value to test.
+*
+*               val_max    Maximum value to test.
+*
+* Return(s)   : DEF_OK,    Value is greater than or equal to minimum value AND
+*                                   less    than or equal to maximum value.
+*
+*               DEF_FAIL,  otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) DEF_CHK_VAL() avoids directly comparing any two values if only one of the values
+*                   is negative since the negative value might be incorrectly promoted to an arbitrary
+*                   unsigned value if the other value to compare is unsigned.
+*
+*               (2) Validation of values is limited to the range supported by the compiler &/or target
+*                   environment.  All other values that underflow/overflow the supported range will
+*                   modulo/wrap into the supported range as arbitrary signed or unsigned values.
+*
+*                   Therefore, any values that underflow the most negative signed value or overflow
+*                   the most positive unsigned value supported by the compiler &/or target environment
+*                   cannot be validated :
+*
+*                           (    N-1       N     ]
+*                           ( -(2   )  ,  2  - 1 ]
+*                           (                    ]
+*
+*                               where
+*                                       N       Number of data word bits supported by the compiler
+*                                                   &/or target environment
+*
+*                   (a) Note that the most negative value, -2^(N-1), is NOT included in the supported
+*                       range since many compilers do NOT always correctly handle this value.
+*
+*               (3) DEF_CHK_VAL() does NOT validate that the maximum value ('val_max') is greater than
+*                   or equal to the minimum value ('val_min').
+*********************************************************************************************************
+*/
+
+#define  DEF_CHK_VAL(val, val_min, val_max)          (((DEF_CHK_VAL_MIN((val), (val_min)) == DEF_FAIL) ||                  \
+                                                       (DEF_CHK_VAL_MAX((val), (val_max)) == DEF_FAIL)) ? DEF_FAIL : DEF_OK)
+
+
+/*
+*********************************************************************************************************
+*                                         DEF_GET_U_MAX_VAL()
+*
+* Description : Get the maximum unsigned value that can be represented in an unsigned integer variable
+*                   of the same data type size as an object.
+*
+* Argument(s) : obj         Object or data type to return maximum unsigned value (see Note #1).
+*
+* Return(s)   : Maximum unsigned integer value that can be represented by the object, if NO error(s).
+*
+*               0,                                                                    otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'obj' SHOULD be an integer object or data type but COULD also be a character or
+*                   pointer object or data type.
+*********************************************************************************************************
+*/
+
+#if     (CPU_CFG_DATA_SIZE_MAX == CPU_WORD_SIZE_08)
+
+#define  DEF_GET_U_MAX_VAL(obj)                 ((sizeof(obj) == CPU_WORD_SIZE_08) ? DEF_INT_08U_MAX_VAL : 0)
+
+
+#elif   (CPU_CFG_DATA_SIZE_MAX == CPU_WORD_SIZE_16)
+
+#define  DEF_GET_U_MAX_VAL(obj)                 ((sizeof(obj) == CPU_WORD_SIZE_08) ? DEF_INT_08U_MAX_VAL :   \
+                                                ((sizeof(obj) == CPU_WORD_SIZE_16) ? DEF_INT_16U_MAX_VAL : 0))
+
+
+#elif   (CPU_CFG_DATA_SIZE_MAX == CPU_WORD_SIZE_32)
+
+#define  DEF_GET_U_MAX_VAL(obj)                 ((sizeof(obj) == CPU_WORD_SIZE_08) ? DEF_INT_08U_MAX_VAL :    \
+                                                ((sizeof(obj) == CPU_WORD_SIZE_16) ? DEF_INT_16U_MAX_VAL :    \
+                                                ((sizeof(obj) == CPU_WORD_SIZE_32) ? DEF_INT_32U_MAX_VAL : 0)))
+
+
+#elif   (CPU_CFG_DATA_SIZE_MAX == CPU_WORD_SIZE_64)
+
+#define  DEF_GET_U_MAX_VAL(obj)                 ((sizeof(obj) == CPU_WORD_SIZE_08) ? DEF_INT_08U_MAX_VAL :     \
+                                                ((sizeof(obj) == CPU_WORD_SIZE_16) ? DEF_INT_16U_MAX_VAL :     \
+                                                ((sizeof(obj) == CPU_WORD_SIZE_32) ? DEF_INT_32U_MAX_VAL :     \
+                                                ((sizeof(obj) == CPU_WORD_SIZE_64) ? DEF_INT_64U_MAX_VAL : 0))))
+
+#else
+
+#error  "CPU_CFG_DATA_SIZE_MAX  illegally #defined in 'cpu.h'      "
+#error  "                       [See 'cpu.h  CONFIGURATION ERRORS']"
+
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                            MATH MACRO'S
+*
+* Note(s) : (1) Ideally, ALL mathematical macro's & functions SHOULD be defined in the custom mathematics
+*               library ('lib_math.*').  #### However, to maintain backwards compatibility with previously-
+*               released modules, mathematical macro & function definitions should only be moved to the
+*               custom mathematics library once all previously-released modules are updated to include the
+*               custom mathematics library.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                              DEF_MIN()
+*
+* Description : Determine the minimum of two values.
+*
+* Argument(s) : a           First  value.
+*
+*               b           Second value.
+*
+* Return(s)   : Minimum of the two values.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+#define  DEF_MIN(a, b)                                  (((a) < (b)) ? (a) : (b))
+
+
+/*
+*********************************************************************************************************
+*                                              DEF_MAX()
+*
+* Description : Determine the maximum of two values.
+*
+* Argument(s) : a           First  value.
+*
+*               b           Second value.
+*
+* Return(s)   : Maximum of the two values.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+#define  DEF_MAX(a, b)                                  (((a) > (b)) ? (a) : (b))
+
+
+/*
+*********************************************************************************************************
+*                                              DEF_ABS()
+*
+* Description : Determine the absolute value of a value.
+*
+* Argument(s) : a           Value to calculate absolute value.
+*
+* Return(s)   : Absolute value of the value.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+#define  DEF_ABS(a)                                     (((a) < 0) ? (-(a)) : (a))
+
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                        CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                    LIBRARY CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+                                                                /* See 'lib_def.h  Note #1a'.                           */
+#if     (CPU_CORE_VERSION < 12900u)
+#error  "CPU_CORE_VERSION  [SHOULD be >= V1.29.00]"
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*
+* Note(s) : (1) See 'lib_def.h  MODULE'.
+*********************************************************************************************************
+*/
+
+#endif                                                          /* End of lib def module include.                       */
+

+ 281 - 0
MiddleWare/uCOS_II/uC-LIB/lib_math.c

@@ -0,0 +1,281 @@
+/*
+*********************************************************************************************************
+*                                                uC/LIB
+*                                        CUSTOM LIBRARY MODULES
+*
+*                         (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL
+*
+*                  All rights reserved.  Protected by international copyright laws.
+*
+*                  uC/LIB is provided in source form to registered licensees ONLY.  It is
+*                  illegal to distribute this source code to any third party unless you receive
+*                  written permission by an authorized Micrium representative.  Knowledge of
+*                  the source code may NOT be used to develop a similar product.
+*
+*                  Please help us continue to provide the Embedded community with the finest
+*                  software available.  Your honesty is greatly appreciated.
+*
+*                  You can find our product's user manual, API reference, release notes and
+*                  more information at: https://doc.micrium.com
+*
+*                  You can contact us at: http://www.micrium.com
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                        MATHEMATIC OPERATIONS
+*
+* Filename      : lib_math.c
+* Version       : V1.38.01
+* Programmer(s) : SR
+*                 ITJ
+*********************************************************************************************************
+* Note(s)       : (1) NO compiler-supplied standard library functions are used in library or product software.
+*
+*                     (a) ALL standard library functions are implemented in the custom library modules :
+*
+*                         (1) \<Custom Library Directory>\lib_*.*
+*
+*                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+*
+*                               where
+*                                       <Custom Library Directory>      directory path for custom library software
+*                                       <cpu>                           directory name for specific processor (CPU)
+*                                       <compiler>                      directory name for specific compiler
+*
+*                     (b) Product-specific library functions are implemented in individual products.
+*
+*********************************************************************************************************
+* Notice(s)     : (1) The Institute of Electrical and Electronics Engineers and The Open Group, have given
+*                     us permission to reprint portions of their documentation.  Portions of this text are
+*                     reprinted and reproduced in electronic form from the IEEE Std 1003.1, 2004 Edition,
+*                     Standard for Information Technology -- Portable Operating System Interface (POSIX),
+*                     The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute
+*                     of Electrical and Electronics Engineers, Inc and The Open Group.  In the event of any
+*                     discrepancy between these versions and the original IEEE and The Open Group Standard,
+*                     the original IEEE and The Open Group Standard is the referee document.  The original
+*                     Standard can be obtained online at http://www.opengroup.org/unix/online.html.
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#define    MICRIUM_SOURCE
+#define    LIB_MATH_MODULE
+#include  <lib_math.h>
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL DEFINES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                           LOCAL CONSTANTS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          LOCAL DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL TABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                       LOCAL GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+RAND_NBR  Math_RandSeedCur;                                     /* Cur rand nbr seed.                                   */
+
+
+/*
+*********************************************************************************************************
+*                                      LOCAL FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                     LOCAL CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                             Math_Init()
+*
+* Description : (1) Initialize Mathematic Module :
+*
+*                   (a) Initialize random number seed value
+*
+*
+* Argument(s) : none.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (2) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that "if rand()
+*                   is called before any calls to srand() are made, the same sequence shall be generated
+*                   as when srand() is first called with a seed value of 1".
+*********************************************************************************************************
+*/
+
+void  Math_Init (void)
+{
+    Math_RandSetSeed((RAND_NBR)RAND_SEED_INIT_VAL);             /* See Note #2.                                         */
+}
+
+
+/*
+*********************************************************************************************************
+*                                         Math_RandSetSeed()
+*
+* Description : Set the current pseudo-random number generator seed.
+*
+* Argument(s) : seed        Initial (or current) value to set for the pseudo-random number sequence.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that "srand()
+*                   ... uses the argument as a seed for a new sequence of pseudo-random numbers to be
+*                   returned by subsequent calls to rand()".
+*
+*               (2) 'Math_RandSeedCur' MUST always be accessed exclusively in critical sections.
+*
+*                   See also 'Math_Rand()  Note #1b'.
+*********************************************************************************************************
+*/
+
+void  Math_RandSetSeed (RAND_NBR  seed)
+{
+    CPU_SR_ALLOC();
+
+
+    CPU_CRITICAL_ENTER();
+    Math_RandSeedCur = seed;
+    CPU_CRITICAL_EXIT();
+}
+
+
+/*
+*********************************************************************************************************
+*                                             Math_Rand()
+*
+* Description : Calculate the next pseudo-random number.
+*
+* Argument(s) : none.
+*
+* Return(s)   : Next pseudo-random number in the sequence after 'Math_RandSeedCur'.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) The pseudo-random number generator is implemented as a Linear Congruential
+*                       Generator (LCG).
+*
+*                   (b) The pseudo-random number generated is in the range [0, RAND_LCG_PARAM_M].
+*
+*                   See also 'Math_RandSeed()  Note #1'.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that "rand()
+*                       ... need not be reentrant ... [and] is not required to be thread-safe".
+*
+*                   (b) However, in order to implement Math_Rand() as re-entrant; 'Math_RandSeedCur' MUST
+*                       always be accessed & updated exclusively in critical sections.
+*
+*                   See also 'Math_RandSeed()  Note #2'.
+*********************************************************************************************************
+*/
+
+RAND_NBR  Math_Rand (void)
+{
+    RAND_NBR  seed;
+    RAND_NBR  rand_nbr;
+    CPU_SR_ALLOC();
+
+
+    CPU_CRITICAL_ENTER();
+    seed             = Math_RandSeedCur;
+    rand_nbr         = Math_RandSeed(seed);
+    Math_RandSeedCur = rand_nbr;
+    CPU_CRITICAL_EXIT();
+
+    return (rand_nbr);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           Math_RandSeed()
+*
+* Description : Calculate the next pseudo-random number.
+*
+* Argument(s) : seed        Initial (or current) value for the pseudo-random number sequence.
+*
+* Return(s)   : Next pseudo-random number in the sequence after 'seed'.
+*
+* Caller(s)   : Math_Rand(),
+*               Application.
+*
+* Note(s)     : (1) (a) BSD/ANSI-C implements rand() as a Linear Congruential Generator (LCG) :
+*
+*                       (A) random_number       =  [(a * random_number ) + b]  modulo m
+*                                        n + 1                        n
+*
+*                               where
+*                                       (1) (a) random_number           Next     random number to generate
+*                                                            n+1
+*                                           (b) random_number           Previous random number    generated
+*                                                            n
+*
+*                                       (2) a = RAND_LCG_PARAM_A        LCG multiplier
+*                                       (3) b = RAND_LCG_PARAM_B        LCG incrementor
+*                                       (4) m = RAND_LCG_PARAM_M + 1    LCG modulus
+*
+*                   (b) The pseudo-random number generated is in the range [0, RAND_LCG_PARAM_M].
+*
+                    See also 'lib_math.h  RANDOM NUMBER DEFINES  Note #1b'.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that "rand()
+*                       ... need not be reentrant ... [and] is not required to be thread-safe".
+*
+*                   (b) However, Math_RandSeed() is re-entrant since it calculates the next random number
+*                       using ONLY local variables.
+*********************************************************************************************************
+*/
+
+RAND_NBR  Math_RandSeed (RAND_NBR  seed)
+{
+    RAND_NBR  rand_nbr;
+
+
+    rand_nbr = (((RAND_NBR)RAND_LCG_PARAM_A * seed) + (RAND_NBR)RAND_LCG_PARAM_B)  %  ((RAND_NBR)RAND_LCG_PARAM_M + 1u);
+
+    return (rand_nbr);
+}
+

+ 298 - 0
MiddleWare/uCOS_II/uC-LIB/lib_math.h

@@ -0,0 +1,298 @@
+/*
+*********************************************************************************************************
+*                                                uC/LIB
+*                                        CUSTOM LIBRARY MODULES
+*
+*                         (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL
+*
+*                  All rights reserved.  Protected by international copyright laws.
+*
+*                  uC/LIB is provided in source form to registered licensees ONLY.  It is
+*                  illegal to distribute this source code to any third party unless you receive
+*                  written permission by an authorized Micrium representative.  Knowledge of
+*                  the source code may NOT be used to develop a similar product.
+*
+*                  Please help us continue to provide the Embedded community with the finest
+*                  software available.  Your honesty is greatly appreciated.
+*
+*                  You can find our product's user manual, API reference, release notes and
+*                  more information at: https://doc.micrium.com
+*
+*                  You can contact us at: http://www.micrium.com
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                        MATHEMATIC OPERATIONS
+*
+* Filename      : lib_math.h
+* Version       : V1.38.01
+* Programmer(s) : SR
+*                 ITJ
+*********************************************************************************************************
+* Note(s)       : (1) NO compiler-supplied standard library functions are used in library or product software.
+*
+*                     (a) ALL standard library functions are implemented in the custom library modules :
+*
+*                         (1) \<Custom Library Directory>\lib_*.*
+*
+*                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+*
+*                               where
+*                                       <Custom Library Directory>      directory path for custom library software
+*                                       <cpu>                           directory name for specific processor (CPU)
+*                                       <compiler>                      directory name for specific compiler
+*
+*                     (b) Product-specific library functions are implemented in individual products.
+*
+*********************************************************************************************************
+* Notice(s)     : (1) The Institute of Electrical and Electronics Engineers and The Open Group, have given
+*                     us permission to reprint portions of their documentation.  Portions of this text are
+*                     reprinted and reproduced in electronic form from the IEEE Std 1003.1, 2004 Edition,
+*                     Standard for Information Technology -- Portable Operating System Interface (POSIX),
+*                     The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute
+*                     of Electrical and Electronics Engineers, Inc and The Open Group.  In the event of any
+*                     discrepancy between these versions and the original IEEE and The Open Group Standard,
+*                     the original IEEE and The Open Group Standard is the referee document.  The original
+*                     Standard can be obtained online at http://www.opengroup.org/unix/online.html.
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*
+* Note(s) : (1) This mathematics library header file is protected from multiple pre-processor inclusion
+*               through use of the mathematics library module present pre-processor macro definition.
+*********************************************************************************************************
+*/
+
+#ifndef  LIB_MATH_MODULE_PRESENT                                /* See Note #1.                                         */
+#define  LIB_MATH_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*
+* Note(s) : (1) The custom library software files are located in the following directories :
+*
+*               (a) \<Custom Library Directory>\lib_*.*
+*
+*                       where
+*                               <Custom Library Directory>      directory path for custom library software
+*
+*           (2) CPU-configuration  software files are located in the following directories :
+*
+*               (a) \<CPU-Compiler Directory>\cpu_*.*
+*               (b) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.*
+*
+*                       where
+*                               <CPU-Compiler Directory>        directory path for common CPU-compiler software
+*                               <cpu>                           directory name for specific processor (CPU)
+*                               <compiler>                      directory name for specific compiler
+*
+*           (3) Compiler MUST be configured to include as additional include path directories :
+*
+*               (a) '\<Custom Library Directory>\' directory                            See Note #1a
+*
+*               (b) (1) '\<CPU-Compiler Directory>\'                  directory         See Note #2a
+*                   (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory         See Note #2b
+*
+*           (4) NO compiler-supplied standard library functions SHOULD be used.
+*********************************************************************************************************
+*/
+
+#include  <cpu.h>
+#include  <cpu_core.h>
+
+#include  <lib_def.h>
+
+
+/*
+*********************************************************************************************************
+*                                               EXTERNS
+*********************************************************************************************************
+*/
+
+#ifdef   LIB_MATH_MODULE
+#define  LIB_MATH_EXT
+#else
+#define  LIB_MATH_EXT  extern
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                               DEFINES
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                        RANDOM NUMBER DEFINES
+*
+* Note(s) : (1) (a) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that "if rand()
+*                   is called before any calls to srand() are made, the same sequence shall be generated
+*                   as when srand() is first called with a seed value of 1".
+*
+*               (b) (1) BSD/ANSI-C implements rand() as a Linear Congruential Generator (LCG) :
+*
+*                       (A) random_number       =  [(a * random_number ) + b]  modulo m
+*                                        n + 1                        n
+*
+*                               where
+*                                       (1) (a) random_number       Next     random number to generate
+*                                                            n+1
+*                                           (b) random_number       Previous random number    generated
+*                                                            n
+*                                           (c) random_number       Initial  random number seed
+*                                                            0                      See also Note #1a
+*
+*                                       (2) a =   1103515245        LCG multiplier
+*                                       (3) b =        12345        LCG incrementor
+*                                       (4) m = RAND_MAX + 1        LCG modulus     See also Note #1b2
+*
+*                   (2) (A) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that
+*                           "rand() ... shall compute a sequence of pseudo-random integers in the range
+*                           [0, {RAND_MAX}] with a period of at least 2^32".
+*
+*                       (B) However, BSD/ANSI-C 'stdlib.h' defines "RAND_MAX" as "0x7fffffff", or 2^31;
+*                           which therefore limits the range AND period to no more than 2^31.
+*********************************************************************************************************
+*/
+
+#define  RAND_SEED_INIT_VAL                                1u   /* See Note #1a.                                        */
+
+#define  RAND_LCG_PARAM_M                         0x7FFFFFFFu   /* See Note #1b2B.                                      */
+#define  RAND_LCG_PARAM_A                         1103515245u   /* See Note #1b1A2.                                     */
+#define  RAND_LCG_PARAM_B                              12345u   /* See Note #1b1A3.                                     */
+
+
+/*
+*********************************************************************************************************
+*                                             DATA TYPES
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                       RANDOM NUMBER DATA TYPE
+*********************************************************************************************************
+*/
+
+typedef  CPU_INT32U  RAND_NBR;
+
+
+/*
+*********************************************************************************************************
+*                                          GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MACROS
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                            MATH_IS_PWR2()
+*
+* Description : Determine if a value is a power of 2.
+*
+* Argument(s) : nbr           Value.
+*
+* Return(s)   : DEF_YES, 'nbr' is a power of 2.
+*
+*               DEF_NO,  'nbr' is not a power of 2.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+#define  MATH_IS_PWR2(nbr)                                 ((((nbr) != 0u) && (((nbr) & ((nbr) - 1u)) == 0u)) ? DEF_YES : DEF_NO)
+
+
+/*
+*********************************************************************************************************
+*                                        MATH_ROUND_INC_UP_PWR2()
+*
+* Description : Round value up to the next (power of 2) increment.
+*
+* Argument(s) : nbr           Value to round.
+*
+*               inc           Increment to use. MUST be a power of 2.
+*
+* Return(s)   : Rounded up value.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+#define  MATH_ROUND_INC_UP_PWR2(nbr, inc)                  (((nbr) & ~((inc) - 1)) + (((nbr) & ((inc) - 1)) == 0 ? 0 : (inc)))
+
+
+/*
+*********************************************************************************************************
+*                                          MATH_ROUND_INC_UP()
+*
+* Description : Round value up to the next increment.
+*
+* Argument(s) : nbr           Value to round.
+*
+*               inc           Increment to use.
+*
+* Return(s)   : Rounded up value.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+#define  MATH_ROUND_INC_UP(nbr, inc)                       (((nbr) + ((inc) - 1)) / (inc) * (inc))
+
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+void      Math_Init       (void);
+
+                                                                /* ------------------ RAND NBR FNCTS ------------------ */
+void      Math_RandSetSeed(RAND_NBR  seed);
+
+RAND_NBR  Math_Rand       (void);
+
+RAND_NBR  Math_RandSeed   (RAND_NBR  seed);
+
+
+/*
+*********************************************************************************************************
+*                                        CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*
+* Note(s) : (1) See 'lib_math.h  MODULE'.
+*********************************************************************************************************
+*/
+
+#endif                                                          /* End of lib math module include.                      */
+

+ 2842 - 0
MiddleWare/uCOS_II/uC-LIB/lib_mem.c

@@ -0,0 +1,2842 @@
+/*
+*********************************************************************************************************
+*                                                uC/LIB
+*                                        CUSTOM LIBRARY MODULES
+*
+*                         (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL
+*
+*                  All rights reserved.  Protected by international copyright laws.
+*
+*                  uC/LIB is provided in source form to registered licensees ONLY.  It is
+*                  illegal to distribute this source code to any third party unless you receive
+*                  written permission by an authorized Micrium representative.  Knowledge of
+*                  the source code may NOT be used to develop a similar product.
+*
+*                  Please help us continue to provide the Embedded community with the finest
+*                  software available.  Your honesty is greatly appreciated.
+*
+*                  You can find our product's user manual, API reference, release notes and
+*                  more information at: https://doc.micrium.com
+*
+*                  You can contact us at: http://www.micrium.com
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                     STANDARD MEMORY OPERATIONS
+*
+* Filename      : lib_mem.c
+* Version       : V1.38.01
+* Programmer(s) : ITJ
+*                 FGK
+*                 JFD
+*                 FBJ
+*                 EJ
+*********************************************************************************************************
+* Note(s)       : (1) NO compiler-supplied standard library functions are used in library or product software.
+*
+*                     (a) ALL standard library functions are implemented in the custom library modules :
+*
+*                         (1) \<Custom Library Directory>\lib_*.*
+*
+*                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+*
+*                               where
+*                                       <Custom Library Directory>      directory path for custom library software
+*                                       <cpu>                           directory name for specific processor (CPU)
+*                                       <compiler>                      directory name for specific compiler
+*
+*                     (b) Product-specific library functions are implemented in individual products.
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#define    MICRIUM_SOURCE
+#define    LIB_MEM_MODULE
+#include  "lib_mem.h"
+#include  "lib_math.h"
+#include  "lib_str.h"
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL DEFINES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                           LOCAL CONSTANTS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          LOCAL DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL TABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                       LOCAL GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+#ifndef  LIB_MEM_CFG_HEAP_BASE_ADDR
+CPU_INT08U   Mem_Heap[LIB_MEM_CFG_HEAP_SIZE];                   /* Mem heap.                                            */
+#endif
+
+MEM_SEG      Mem_SegHeap;                                       /* Heap mem seg.                                        */
+#endif
+
+MEM_SEG     *Mem_SegHeadPtr;                                    /* Ptr to head of seg list.                             */
+
+
+/*
+*********************************************************************************************************
+*                                      LOCAL FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+static  void          Mem_SegCreateCritical    (const  CPU_CHAR      *p_name,
+                                                       MEM_SEG       *p_seg,
+                                                       CPU_ADDR       seg_base_addr,
+                                                       CPU_SIZE_T     padding_align,
+                                                       CPU_SIZE_T     size);
+
+static  MEM_SEG      *Mem_SegOverlapChkCritical(       CPU_ADDR       seg_base_addr,
+                                                       CPU_SIZE_T     size,
+                                                       LIB_ERR       *p_err);
+
+static  void         *Mem_SegAllocInternal     (const  CPU_CHAR      *p_name,
+                                                       MEM_SEG       *p_seg,
+                                                       CPU_SIZE_T     size,
+                                                       CPU_SIZE_T     align,
+                                                       CPU_SIZE_T     padding_align,
+                                                       CPU_SIZE_T    *p_bytes_reqd,
+                                                       LIB_ERR       *p_err);
+
+static  void         *Mem_SegAllocExtCritical  (       MEM_SEG       *p_seg,
+                                                       CPU_SIZE_T     size,
+                                                       CPU_SIZE_T     align,
+                                                       CPU_SIZE_T     padding_align,
+                                                       CPU_SIZE_T    *p_bytes_reqd,
+                                                       LIB_ERR       *p_err);
+
+static  void          Mem_DynPoolCreateInternal(const  CPU_CHAR      *p_name,
+                                                       MEM_DYN_POOL  *p_pool,
+                                                       MEM_SEG       *p_seg,
+                                                       CPU_SIZE_T     blk_size,
+                                                       CPU_SIZE_T     blk_align,
+                                                       CPU_SIZE_T     blk_padding_align,
+                                                       CPU_SIZE_T     blk_qty_init,
+                                                       CPU_SIZE_T     blk_qty_max,
+                                                       LIB_ERR       *p_err);
+
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
+static  void          Mem_SegAllocTrackCritical(const  CPU_CHAR      *p_name,
+                                                       MEM_SEG       *p_seg,
+                                                       CPU_SIZE_T     size,
+                                                       LIB_ERR       *p_err);
+#endif
+
+#if ((LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) && \
+     (LIB_MEM_CFG_HEAP_SIZE      >  0u))
+static  CPU_BOOLEAN   Mem_PoolBlkIsValidAddr   (       MEM_POOL      *p_pool,
+                                                       void          *p_mem);
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                     LOCAL CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*********************************************************************************************************
+*                                            GLOBAL FUNCTIONS
+*********************************************************************************************************
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                             Mem_Init()
+*
+* Description : (1) Initializes Memory Management Module :
+*
+*                   (a) Initialize heap memory pool
+*                   (b) Initialize      memory pool table
+*
+*
+* Argument(s) : none.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (2) Mem_Init() MUST be called ... :
+*
+*                   (a) ONLY ONCE from a product's application; ...
+*                   (b) BEFORE product's application calls any memory library module function(s)
+*********************************************************************************************************
+*/
+
+void  Mem_Init (void)
+{
+
+                                                                /* ------------------ INIT SEG LIST ------------------- */
+    Mem_SegHeadPtr = DEF_NULL;
+
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+    {
+        LIB_ERR   err;
+        CPU_ADDR  heap_base_addr;
+
+
+                                                                /* ------------------ INIT HEAP SEG ------------------- */
+#ifdef  LIB_MEM_CFG_HEAP_BASE_ADDR
+        heap_base_addr = LIB_MEM_CFG_HEAP_BASE_ADDR;
+#else
+        heap_base_addr = (CPU_ADDR)&Mem_Heap[0u];
+#endif
+
+        Mem_SegCreate("Heap",
+                      &Mem_SegHeap,                             /* Create heap seg.                                     */
+                       heap_base_addr,
+                       LIB_MEM_CFG_HEAP_SIZE,
+                       LIB_MEM_PADDING_ALIGN_NONE,
+                      &err);
+        if (err != LIB_MEM_ERR_NONE) {
+            CPU_SW_EXCEPTION(;);
+        }
+    }
+#endif
+}
+
+
+/*
+*********************************************************************************************************
+*                                              Mem_Clr()
+*
+* Description : Clears data buffer (see Note #2).
+*
+* Argument(s) : pmem        Pointer to memory buffer to clear.
+*
+*               size        Number of data buffer octets to clear (see Note #1).
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Null clears allowed (i.e. zero-length clears).
+*
+*                   See also 'Mem_Set()  Note #1'.
+*
+*               (2) Clear data by setting each data octet to 0.
+*********************************************************************************************************
+*/
+
+void  Mem_Clr (void        *pmem,
+               CPU_SIZE_T   size)
+{
+    Mem_Set(pmem,
+            0u,                                                 /* See Note #2.                                         */
+            size);
+}
+
+
+/*
+*********************************************************************************************************
+*                                              Mem_Set()
+*
+* Description : Fills data buffer with specified data octet.
+*
+* Argument(s) : pmem        Pointer to memory buffer to fill with specified data octet.
+*
+*               data_val    Data fill octet value.
+*
+*               size        Number of data buffer octets to fill (see Note #1).
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Null sets allowed (i.e. zero-length sets).
+*
+*               (2) For best CPU performance, optimized to fill data buffer using 'CPU_ALIGN'-sized data
+*                   words. Since many word-aligned processors REQUIRE that multi-octet words be accessed on
+*                   word-aligned addresses, 'CPU_ALIGN'-sized words MUST be accessed on 'CPU_ALIGN'd
+*                   addresses.
+*
+*               (3) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
+*                   address boundary.
+*
+*                   Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values.  Thus
+*                   address values MUST be cast to an appropriately-sized integer value PRIOR to any
+*                  'mem_align_mod' arithmetic operation.
+*********************************************************************************************************
+*/
+
+void  Mem_Set (void        *pmem,
+               CPU_INT08U   data_val,
+               CPU_SIZE_T   size)
+{
+    CPU_SIZE_T   size_rem;
+    CPU_ALIGN    data_align;
+    CPU_ALIGN   *pmem_align;
+    CPU_INT08U  *pmem_08;
+    CPU_DATA     mem_align_mod;
+    CPU_DATA     i;
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (size < 1) {                                             /* See Note #1.                                         */
+        return;
+    }
+    if (pmem == (void *)0) {
+        return;
+    }
+#endif
+
+
+    data_align = 0u;
+    for (i = 0u; i < sizeof(CPU_ALIGN); i++) {                  /* Fill each data_align octet with data val.            */
+        data_align <<=  DEF_OCTET_NBR_BITS;
+        data_align  |= (CPU_ALIGN)data_val;
+    }
+
+    size_rem      =  size;
+    mem_align_mod = (CPU_INT08U)((CPU_ADDR)pmem % sizeof(CPU_ALIGN));   /* See Note #3.                                 */
+
+    pmem_08 = (CPU_INT08U *)pmem;
+    if (mem_align_mod != 0u) {                                  /* If leading octets avail,                   ...       */
+        i = mem_align_mod;
+        while ((size_rem > 0) &&                                /* ... start mem buf fill with leading octets ...       */
+               (i        < sizeof(CPU_ALIGN ))) {               /* ... until next CPU_ALIGN word boundary.              */
+           *pmem_08++ = data_val;
+            size_rem -= sizeof(CPU_INT08U);
+            i++;
+        }
+    }
+
+    pmem_align = (CPU_ALIGN *)pmem_08;                          /* See Note #2.                                         */
+    while (size_rem >= sizeof(CPU_ALIGN)) {                     /* While mem buf aligned on CPU_ALIGN word boundaries,  */
+       *pmem_align++ = data_align;                              /* ... fill mem buf with    CPU_ALIGN-sized data.       */
+        size_rem    -= sizeof(CPU_ALIGN);
+    }
+
+    pmem_08 = (CPU_INT08U *)pmem_align;
+    while (size_rem > 0) {                                      /* Finish mem buf fill with trailing octets.            */
+       *pmem_08++   = data_val;
+        size_rem   -= sizeof(CPU_INT08U);
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                             Mem_Copy()
+*
+* Description : Copies data octets from one memory buffer to another memory buffer.
+*
+* Argument(s) : pdest       Pointer to destination memory buffer.
+*
+*               psrc        Pointer to source      memory buffer.
+*
+*               size        Number of octets to copy (see Note #1).
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Null copies allowed (i.e. zero-length copies).
+*
+*               (2) Memory buffers NOT checked for overlapping.
+*
+*                   (a) IEEE Std 1003.1, 2004 Edition, Section 'memcpy() : DESCRIPTION' states that "if
+*                       copying takes place between objects that overlap, the behavior is undefined".
+*
+*                   (b) However, data octets from a source memory buffer at a higher address value SHOULD
+*                       successfully copy to a destination memory buffer at a lower  address value even
+*                       if any octets of the memory buffers overlap as long as no individual, atomic CPU
+*                       word copy overlaps.
+*
+*                       Since Mem_Copy() performs the data octet copy via 'CPU_ALIGN'-sized words &/or
+*                       octets; & since 'CPU_ALIGN'-sized words MUST be accessed on word-aligned addresses
+*                       (see Note #3b), neither 'CPU_ALIGN'-sized words nor octets at unique addresses can
+*                       ever overlap.
+*
+*                       Therefore, Mem_Copy() SHOULD be able to successfully copy overlapping memory
+*                       buffers as long as the source memory buffer is at a higher address value than the
+*                       destination memory buffer.
+*
+*               (3) For best CPU performance, optimized to copy data buffer using 'CPU_ALIGN'-sized data
+*                   words. Since many word-aligned processors REQUIRE that multi-octet words be accessed on
+*                   word-aligned addresses, 'CPU_ALIGN'-sized words MUST be accessed on 'CPU_ALIGN'd
+*                   addresses.
+*
+*               (4) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
+*                   address boundary.
+*
+*                   Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values.  Thus
+*                   address values MUST be cast to an appropriately-sized integer value PRIOR to any
+*                  'mem_align_mod' arithmetic operation.
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_OPTIMIZE_ASM_EN != DEF_ENABLED)
+void  Mem_Copy (       void        *pdest,
+                const  void        *psrc,
+                       CPU_SIZE_T   size)
+{
+           CPU_SIZE_T    size_rem;
+           CPU_SIZE_T    mem_gap_octets;
+           CPU_ALIGN    *pmem_align_dest;
+    const  CPU_ALIGN    *pmem_align_src;
+           CPU_INT08U   *pmem_08_dest;
+    const  CPU_INT08U   *pmem_08_src;
+           CPU_DATA      i;
+           CPU_DATA      mem_align_mod_dest;
+           CPU_DATA      mem_align_mod_src;
+           CPU_BOOLEAN   mem_aligned;
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (size < 1) {                                             /* See Note #1.                                         */
+        return;
+    }
+    if (pdest == (void *)0) {
+        return;
+    }
+    if (psrc  == (void *)0) {
+        return;
+    }
+#endif
+
+
+    size_rem           =  size;
+
+    pmem_08_dest       = (      CPU_INT08U *)pdest;
+    pmem_08_src        = (const CPU_INT08U *)psrc;
+
+    mem_gap_octets     = pmem_08_src - pmem_08_dest;
+
+
+    if (mem_gap_octets >= sizeof(CPU_ALIGN)) {                  /* Avoid bufs overlap.                                  */
+                                                                /* See Note #4.                                         */
+        mem_align_mod_dest = (CPU_INT08U)((CPU_ADDR)pmem_08_dest % sizeof(CPU_ALIGN));
+        mem_align_mod_src  = (CPU_INT08U)((CPU_ADDR)pmem_08_src  % sizeof(CPU_ALIGN));
+
+        mem_aligned        = (mem_align_mod_dest == mem_align_mod_src) ? DEF_YES : DEF_NO;
+
+        if (mem_aligned == DEF_YES) {                           /* If mem bufs' alignment offset equal, ...             */
+                                                                /* ... optimize copy for mem buf alignment.             */
+            if (mem_align_mod_dest != 0u) {                     /* If leading octets avail,                   ...       */
+                i = mem_align_mod_dest;
+                while ((size_rem   >  0) &&                     /* ... start mem buf copy with leading octets ...       */
+                       (i          <  sizeof(CPU_ALIGN ))) {    /* ... until next CPU_ALIGN word boundary.              */
+                   *pmem_08_dest++ = *pmem_08_src++;
+                    size_rem      -=  sizeof(CPU_INT08U);
+                    i++;
+                }
+            }
+
+            pmem_align_dest = (      CPU_ALIGN *)pmem_08_dest;  /* See Note #3.                                         */
+            pmem_align_src  = (const CPU_ALIGN *)pmem_08_src;
+            while (size_rem      >=  sizeof(CPU_ALIGN)) {       /* While mem bufs aligned on CPU_ALIGN word boundaries, */
+               *pmem_align_dest++ = *pmem_align_src++;          /* ... copy psrc to pdest with CPU_ALIGN-sized words.   */
+                size_rem         -=  sizeof(CPU_ALIGN);
+            }
+
+            pmem_08_dest = (      CPU_INT08U *)pmem_align_dest;
+            pmem_08_src  = (const CPU_INT08U *)pmem_align_src;
+        }
+    }
+
+    while (size_rem > 0) {                                      /* For unaligned mem bufs or trailing octets, ...       */
+       *pmem_08_dest++ = *pmem_08_src++;                        /* ... copy psrc to pdest by octets.                    */
+        size_rem      -=  sizeof(CPU_INT08U);
+    }
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             Mem_Move()
+*
+* Description : Moves data octets from one memory buffer to another memory buffer, or within the same
+*               memory buffer. Overlapping is correctly handled for all move operations.
+*
+* Argument(s) : pdest       Pointer to destination memory buffer.
+*
+*               psrc        Pointer to source      memory buffer.
+*
+*               size        Number of octets to move (see Note #1).
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Null move operations allowed (i.e. zero-length).
+*
+*               (2) Memory buffers checked for overlapping.
+*
+*               (3) For best CPU performance, optimized to copy data buffer using 'CPU_ALIGN'-sized data
+*                   words. Since many word-aligned processors REQUIRE that multi-octet words be accessed on
+*                   word-aligned addresses, 'CPU_ALIGN'-sized words MUST be accessed on 'CPU_ALIGN'd
+*                   addresses.
+*
+*               (4) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
+*                   address boundary.
+*
+*                   Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values.  Thus
+*                   address values MUST be cast to an appropriately-sized integer value PRIOR to any
+*                  'mem_align_mod' arithmetic operation.
+*********************************************************************************************************
+*/
+
+void  Mem_Move (       void        *pdest,
+                const  void        *psrc,
+                       CPU_SIZE_T   size)
+{
+           CPU_SIZE_T    size_rem;
+           CPU_SIZE_T    mem_gap_octets;
+           CPU_ALIGN    *pmem_align_dest;
+    const  CPU_ALIGN    *pmem_align_src;
+           CPU_INT08U   *pmem_08_dest;
+    const  CPU_INT08U   *pmem_08_src;
+           CPU_INT08S    i;
+           CPU_DATA      mem_align_mod_dest;
+           CPU_DATA      mem_align_mod_src;
+           CPU_BOOLEAN   mem_aligned;
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (size < 1) {
+        return;
+    }
+    if (pdest == (void *)0) {
+        return;
+    }
+    if (psrc  == (void *)0) {
+        return;
+    }
+#endif
+
+    pmem_08_src  = (const CPU_INT08U *)psrc;
+    pmem_08_dest = (      CPU_INT08U *)pdest;
+    if (pmem_08_src > pmem_08_dest) {
+        Mem_Copy(pdest, psrc, size);
+        return;
+    }
+
+    size_rem           =  size;
+
+    pmem_08_dest       = (      CPU_INT08U *)pdest + size - 1;
+    pmem_08_src        = (const CPU_INT08U *)psrc  + size - 1;
+
+    mem_gap_octets     = pmem_08_dest - pmem_08_src;
+
+
+    if (mem_gap_octets >= sizeof(CPU_ALIGN)) {                  /* Avoid bufs overlap.                                  */
+
+                                                                /* See Note #4.                                         */
+        mem_align_mod_dest = (CPU_INT08U)((CPU_ADDR)pmem_08_dest % sizeof(CPU_ALIGN));
+        mem_align_mod_src  = (CPU_INT08U)((CPU_ADDR)pmem_08_src  % sizeof(CPU_ALIGN));
+
+        mem_aligned        = (mem_align_mod_dest == mem_align_mod_src) ? DEF_YES : DEF_NO;
+
+        if (mem_aligned == DEF_YES) {                           /* If mem bufs' alignment offset equal, ...             */
+                                                                /* ... optimize copy for mem buf alignment.             */
+            if (mem_align_mod_dest != (sizeof(CPU_ALIGN) - 1)) {/* If leading octets avail,                   ...       */
+                i = mem_align_mod_dest;
+                while ((size_rem   >  0) &&                     /* ... start mem buf copy with leading octets ...       */
+                       (i          >= 0)) {                     /* ... until next CPU_ALIGN word boundary.              */
+                   *pmem_08_dest-- = *pmem_08_src--;
+                    size_rem      -=  sizeof(CPU_INT08U);
+                    i--;
+                }
+            }
+
+                                                                /* See Note #3.                                         */
+            pmem_align_dest = (      CPU_ALIGN *)((CPU_INT08U *)pmem_08_dest - sizeof(CPU_ALIGN) + 1);
+            pmem_align_src  = (const CPU_ALIGN *)((CPU_INT08U *)pmem_08_src  - sizeof(CPU_ALIGN) + 1);
+            while (size_rem      >=  sizeof(CPU_ALIGN)) {       /* While mem bufs aligned on CPU_ALIGN word boundaries, */
+               *pmem_align_dest-- = *pmem_align_src--;          /* ... copy psrc to pdest with CPU_ALIGN-sized words.   */
+                size_rem         -=  sizeof(CPU_ALIGN);
+            }
+
+            pmem_08_dest = (      CPU_INT08U *)pmem_align_dest + sizeof(CPU_ALIGN) - 1;
+            pmem_08_src  = (const CPU_INT08U *)pmem_align_src  + sizeof(CPU_ALIGN) - 1;
+
+        }
+    }
+
+    while (size_rem > 0) {                                      /* For unaligned mem bufs or trailing octets, ...       */
+       *pmem_08_dest-- = *pmem_08_src--;                        /* ... copy psrc to pdest by octets.                    */
+        size_rem      -=  sizeof(CPU_INT08U);
+    }
+}
+
+
+/*
+*********************************************************************************************************
+*                                              Mem_Cmp()
+*
+* Description : Verifies that ALL data octets in two memory buffers are identical in sequence.
+*
+* Argument(s) : p1_mem      Pointer to first  memory buffer.
+*
+*               p2_mem      Pointer to second memory buffer.
+*
+*               size        Number of data buffer octets to compare (see Note #1).
+*
+* Return(s)   : DEF_YES, if 'size' number of data octets are identical in both memory buffers.
+*
+*               DEF_NO,  otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Null compares allowed (i.e. zero-length compares); 'DEF_YES' returned to indicate
+*                   identical null compare.
+*
+*               (2) Many memory buffer comparisons vary ONLY in the least significant octets -- e.g.
+*                   network address buffers.  Consequently, memory buffer comparison is more efficient
+*                   if the comparison starts from the end of the memory buffers which will abort sooner
+*                   on dissimilar memory buffers that vary only in the least significant octets.
+*
+*               (3) For best CPU performance, optimized to compare data buffers using 'CPU_ALIGN'-sized
+*                   data words. Since many word-aligned processors REQUIRE that multi-octet words be accessed on
+*                   word-aligned addresses, 'CPU_ALIGN'-sized words MUST be accessed on 'CPU_ALIGN'd
+*                   addresses.
+*
+*               (4) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
+*                   address boundary.
+*
+*                   Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values.  Thus
+*                   address values MUST be cast to an appropriately-sized integer value PRIOR to any
+*                  'mem_align_mod' arithmetic operation.
+*********************************************************************************************************
+*/
+
+CPU_BOOLEAN  Mem_Cmp (const  void        *p1_mem,
+                      const  void        *p2_mem,
+                             CPU_SIZE_T   size)
+{
+           CPU_SIZE_T    size_rem;
+           CPU_ALIGN    *p1_mem_align;
+           CPU_ALIGN    *p2_mem_align;
+    const  CPU_INT08U   *p1_mem_08;
+    const  CPU_INT08U   *p2_mem_08;
+           CPU_DATA      i;
+           CPU_DATA      mem_align_mod_1;
+           CPU_DATA      mem_align_mod_2;
+           CPU_BOOLEAN   mem_aligned;
+           CPU_BOOLEAN   mem_cmp;
+
+
+    if (size < 1) {                                             /* See Note #1.                                         */
+        return (DEF_YES);
+    }
+    if (p1_mem == (void *)0) {
+        return (DEF_NO);
+    }
+    if (p2_mem == (void *)0) {
+        return (DEF_NO);
+    }
+
+
+    mem_cmp         =  DEF_YES;                                 /* Assume mem bufs are identical until cmp fails.       */
+    size_rem        =  size;
+                                                                /* Start @ end of mem bufs (see Note #2).               */
+    p1_mem_08       = (const CPU_INT08U *)p1_mem + size;
+    p2_mem_08       = (const CPU_INT08U *)p2_mem + size;
+                                                                /* See Note #4.                                         */
+    mem_align_mod_1 = (CPU_INT08U)((CPU_ADDR)p1_mem_08 % sizeof(CPU_ALIGN));
+    mem_align_mod_2 = (CPU_INT08U)((CPU_ADDR)p2_mem_08 % sizeof(CPU_ALIGN));
+
+    mem_aligned     = (mem_align_mod_1 == mem_align_mod_2) ? DEF_YES : DEF_NO;
+
+    if (mem_aligned == DEF_YES) {                               /* If mem bufs' alignment offset equal, ...             */
+                                                                /* ... optimize cmp for mem buf alignment.              */
+        if (mem_align_mod_1 != 0u) {                            /* If trailing octets avail,                  ...       */
+            i = mem_align_mod_1;
+            while ((mem_cmp == DEF_YES) &&                      /* ... cmp mem bufs while identical &         ...       */
+                   (size_rem > 0)       &&                      /* ... start mem buf cmp with trailing octets ...       */
+                   (i        > 0)) {                            /* ... until next CPU_ALIGN word boundary.              */
+                p1_mem_08--;
+                p2_mem_08--;
+                if (*p1_mem_08 != *p2_mem_08) {                 /* If ANY data octet(s) NOT identical, cmp fails.       */
+                     mem_cmp = DEF_NO;
+                }
+                size_rem -= sizeof(CPU_INT08U);
+                i--;
+            }
+        }
+
+        if (mem_cmp == DEF_YES) {                               /* If cmp still identical, cmp aligned mem bufs.        */
+            p1_mem_align = (CPU_ALIGN *)p1_mem_08;              /* See Note #3.                                         */
+            p2_mem_align = (CPU_ALIGN *)p2_mem_08;
+
+            while ((mem_cmp  == DEF_YES) &&                     /* Cmp mem bufs while identical & ...                   */
+                   (size_rem >= sizeof(CPU_ALIGN))) {           /* ... mem bufs aligned on CPU_ALIGN word boundaries.   */
+                p1_mem_align--;
+                p2_mem_align--;
+                if (*p1_mem_align != *p2_mem_align) {           /* If ANY data octet(s) NOT identical, cmp fails.       */
+                     mem_cmp = DEF_NO;
+                }
+                size_rem -= sizeof(CPU_ALIGN);
+            }
+
+            p1_mem_08 = (CPU_INT08U *)p1_mem_align;
+            p2_mem_08 = (CPU_INT08U *)p2_mem_align;
+        }
+    }
+
+    while ((mem_cmp == DEF_YES) &&                              /* Cmp mem bufs while identical ...                     */
+           (size_rem > 0)) {                                    /* ... for unaligned mem bufs or trailing octets.       */
+        p1_mem_08--;
+        p2_mem_08--;
+        if (*p1_mem_08 != *p2_mem_08) {                         /* If ANY data octet(s) NOT identical, cmp fails.       */
+             mem_cmp = DEF_NO;
+        }
+        size_rem -= sizeof(CPU_INT08U);
+    }
+
+    return (mem_cmp);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           Mem_HeapAlloc()
+*
+* Description : Allocates a memory block from the heap memory segment.
+*
+* Argument(s) : size            Size      of memory block to allocate (in bytes).
+*
+*               align           Alignment of memory block to specific word boundary (in bytes).
+*
+*               p_bytes_reqd    Optional pointer to a variable to ... :
+*
+*                                   (a) Return the number of bytes required to successfully
+*                                           allocate the memory block, if any error(s);
+*                                   (b) Return 0, otherwise.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                                   LIB_MEM_ERR_NONE                Operation was successful.
+*                                   LIB_MEM_ERR_HEAP_EMPTY          No more memory available on heap.
+*
+*                                   ---------------------RETURNED BY Mem_SegAllocInternal()---------------------
+*                                   LIB_MEM_ERR_INVALID_MEM_ALIGN   Invalid memory block alignment requested.
+*                                   LIB_MEM_ERR_INVALID_MEM_SIZE    Invalid memory block size specified.
+*                                   LIB_MEM_ERR_NULL_PTR            Error or segment data pointer NULL.
+*
+* Return(s)   : Pointer to memory block, if NO error(s).
+*
+*               Pointer to NULL,         otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Pointers to variables that return values MUST be initialized PRIOR to all other
+*                   validation or function handling in case of any error(s).
+*
+*               (2) This function is DEPRECATED and will be removed in a future version of this product.
+*                   Mem_SegAlloc(), Mem_SegAllocExt() or Mem_SegAllocHW() should be used instead.
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+void  *Mem_HeapAlloc (CPU_SIZE_T   size,
+                      CPU_SIZE_T   align,
+                      CPU_SIZE_T  *p_bytes_reqd,
+                      LIB_ERR     *p_err)
+{
+    void  *p_mem;
+
+
+    p_mem = Mem_SegAllocInternal(DEF_NULL,
+                                &Mem_SegHeap,
+                                 size,
+                                 align,
+                                 LIB_MEM_CFG_HEAP_PADDING_ALIGN,
+                                 p_bytes_reqd,
+                                 p_err);
+    if (*p_err == LIB_MEM_ERR_SEG_OVF) {
+       *p_err = LIB_MEM_ERR_HEAP_OVF;
+    }
+
+    return (p_mem);
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                        Mem_HeapGetSizeRem()
+*
+* Description : Gets remaining heap memory size available to allocate.
+*
+* Argument(s) : align       Desired word boundary alignment (in bytes) to return remaining memory size from.
+*
+*               p_err       Pointer to variable that will receive the return error code from this function
+*
+*                               LIB_MEM_ERR_NONE                Operation was successful.
+*
+*                               --------------------RETURNED BY Mem_SegRemSizeGet()--------------------
+*                               LIB_MEM_ERR_NULL_PTR            Segment data pointer NULL.
+*                               LIB_MEM_ERR_INVALID_MEM_ALIGN   Invalid memory alignment.
+*
+* Return(s)   : Remaining heap memory size (in bytes), if NO error(s).
+*
+*               0,                                     otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) This function is DEPRECATED and will be removed in a future version of this product.
+*                   Mem_SegRemSizeGet() should be used instead.
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+CPU_SIZE_T  Mem_HeapGetSizeRem (CPU_SIZE_T   align,
+                                LIB_ERR     *p_err)
+{
+    CPU_SIZE_T  rem_size;
+
+
+    rem_size = Mem_SegRemSizeGet(&Mem_SegHeap,
+                                  align,
+                                  DEF_NULL,
+                                  p_err);
+    if (*p_err != LIB_MEM_ERR_NONE) {
+        return (0u);
+    }
+
+    return (rem_size);
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                            Mem_SegCreate()
+*
+* Description : Creates a new memory segment to be used for runtime memory allocation.
+*
+* Argument(s) : p_name          Pointer to segment name.
+*
+*               p_seg           Pointer to segment data. Must be allocated by caller.
+*
+*               seg_base_addr   Address of segment's first byte.
+*
+*               size            Total size of segment, in bytes.
+*
+*               padding_align   Padding alignment, in bytes, that will be added to any allocated buffer from
+*                               this memory segment. MUST be a power of 2. LIB_MEM_PADDING_ALIGN_NONE
+*                               means no padding.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                                   LIB_MEM_ERR_NONE                    Operation was successful.
+*                                   LIB_MEM_ERR_INVALID_SEG_SIZE        Invalid segment size specified.
+*                                   LIB_MEM_ERR_INVALID_MEM_ALIGN       Invalid padding alignment.
+*                                   LIB_MEM_ERR_NULL_PTR                Error or segment data pointer NULL.
+*
+*                                   -------------------RETURNED BY Mem_SegOverlapChkCritical()-------------------
+*                                   LIB_MEM_ERR_INVALID_SEG_OVERLAP     Segment overlaps another existing segment.
+*                                   LIB_MEM_ERR_INVALID_SEG_EXISTS      Segment already exists.
+*
+* Return(s)   : None.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) New segments are checked for overlap with existing segments. A critical section needs
+*                   to be maintained during the whole list search and add procedure to prevent a reentrant
+*                   call from creating another segment overlapping with the one being added.
+*********************************************************************************************************
+*/
+
+void  Mem_SegCreate (const  CPU_CHAR    *p_name,
+                            MEM_SEG     *p_seg,
+                            CPU_ADDR     seg_base_addr,
+                            CPU_SIZE_T   size,
+                            CPU_SIZE_T   padding_align,
+                            LIB_ERR     *p_err)
+{
+    CPU_SR_ALLOC();
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (p_err == DEF_NULL) {                                    /* Chk for null err ptr.                                */
+        CPU_SW_EXCEPTION(;);
+    }
+
+    if (p_seg == DEF_NULL) {                                    /* Chk for null seg ptr.                                */
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return;
+    }
+
+    if (size < 1u) {                                            /* Chk for invalid sized seg.                           */
+       *p_err = LIB_MEM_ERR_INVALID_SEG_SIZE;
+        return;
+    }
+                                                                /* Chk for addr space ovf.                              */
+    if (seg_base_addr + (size - 1u) < seg_base_addr) {
+       *p_err = LIB_MEM_ERR_INVALID_SEG_SIZE;
+        return;
+    }
+
+    if ((padding_align               != LIB_MEM_PADDING_ALIGN_NONE) &&
+        (MATH_IS_PWR2(padding_align) != DEF_YES)) {
+       *p_err = LIB_MEM_ERR_INVALID_MEM_ALIGN;
+        return;
+    }
+#endif
+
+    CPU_CRITICAL_ENTER();
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    (void)Mem_SegOverlapChkCritical(seg_base_addr,              /* Chk for overlap.                                     */
+                                    size,
+                                    p_err);
+    if (*p_err != LIB_MEM_ERR_NONE) {
+        CPU_CRITICAL_EXIT();
+        return;
+    }
+#endif
+
+    Mem_SegCreateCritical(p_name,                               /* Create seg.                                          */
+                          p_seg,
+                          seg_base_addr,
+                          padding_align,
+                          size);
+    CPU_CRITICAL_EXIT();
+
+   *p_err = LIB_MEM_ERR_NONE;
+}
+
+
+/*
+*********************************************************************************************************
+*                                            Mem_SegClr()
+*
+* Description : Clears a memory segment.
+*
+* Argument(s) : p_seg           Pointer to segment data. Must be allocated by caller.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                               LIB_MEM_ERR_NONE                Operation was successful.
+*                               LIB_MEM_ERR_NULL_PTR            Segment data pointer NULL.
+*
+* Return(s)   : None.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) This function must be used with extreme caution. It must only be called on memory
+*                   segments that are no longer used.
+*
+*               (2) This function is disabled when debug mode is enabled to avoid heap memory leaks.
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_DISABLED)
+void  Mem_SegClr (MEM_SEG  *p_seg,
+                  LIB_ERR  *p_err)
+{
+    CPU_SR_ALLOC();
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (p_err == DEF_NULL) {                                    /* Chk for null err ptr.                                */
+        CPU_SW_EXCEPTION(;);
+    }
+
+    if (p_seg == DEF_NULL) {                                    /* Chk for null seg ptr.                                */
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return;
+    }
+#endif
+
+    CPU_CRITICAL_ENTER();
+    p_seg->AddrNext = p_seg->AddrBase;
+    CPU_CRITICAL_EXIT();
+
+   *p_err = LIB_MEM_ERR_NONE;
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                         Mem_SegRemSizeGet()
+*
+* Description : Gets free space of memory segment.
+*
+* Argument(s) : p_seg       Pointer to segment data.
+*
+*               align       Alignment in bytes to assume for calculation of free space.
+*
+*               p_seg_info  Pointer to structure that will receive further segment info data (used size,
+*                           total size, base address and next allocation address).
+*
+*               p_err       Pointer to variable that will receive the return error code from this function :
+*
+*                           LIB_MEM_ERR_NONE                Operation was successful.
+*                           LIB_MEM_ERR_NULL_PTR            Segment data pointer NULL.
+*                           LIB_MEM_ERR_INVALID_MEM_ALIGN   Invalid memory alignment.
+*
+* Return(s)   : Memory segment remaining size in bytes,     if successful.
+*               0,                                          otherwise or if memory segment empty.
+*
+* Caller(s)   : Application,
+*               Mem_HeapGetSizeRem(),
+*               Mem_OutputUsage().
+*
+* Note(s)     : None.
+*********************************************************************************************************
+*/
+
+CPU_SIZE_T  Mem_SegRemSizeGet (MEM_SEG       *p_seg,
+                               CPU_SIZE_T     align,
+                               MEM_SEG_INFO  *p_seg_info,
+                               LIB_ERR       *p_err)
+{
+    CPU_SIZE_T  rem_size;
+    CPU_SIZE_T  total_size;
+    CPU_SIZE_T  used_size;
+    CPU_ADDR    next_addr_align;
+    CPU_SR_ALLOC();
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (p_err == DEF_NULL) {                                    /* Chk for null err ptr.                                */
+        CPU_SW_EXCEPTION(seg_info);
+    }
+
+    if (MATH_IS_PWR2(align) != DEF_YES) {                       /* Chk for invalid align val.                           */
+       *p_err = LIB_MEM_ERR_INVALID_MEM_ALIGN;
+        return (0u);
+    }
+#endif
+
+    if (p_seg == DEF_NULL) {                                    /* Dflt to heap in case p_seg is null.                  */
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+        p_seg = &Mem_SegHeap;
+#else
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return (0u);
+#endif
+    }
+
+    CPU_CRITICAL_ENTER();                                       /* Calc seg stats.                                      */
+    next_addr_align = MATH_ROUND_INC_UP_PWR2(p_seg->AddrNext, align);
+    CPU_CRITICAL_EXIT();
+
+    total_size = p_seg->AddrEnd  - p_seg->AddrBase + 1u;
+    used_size  = next_addr_align - p_seg->AddrBase;
+    rem_size   = total_size      - used_size;
+
+    if (p_seg_info != DEF_NULL) {
+        p_seg_info->TotalSize     = total_size;
+        p_seg_info->UsedSize      = used_size;
+        p_seg_info->AddrBase      = p_seg->AddrBase;
+        p_seg_info->AddrNextAlloc = next_addr_align;
+    }
+
+   *p_err = LIB_MEM_ERR_NONE;
+
+    return (rem_size);
+}
+
+
+/*
+*********************************************************************************************************
+*                                            Mem_SegAlloc()
+*
+* Description : Allocates memory from specified segment. Returned memory block will be aligned on a CPU
+*               word boundary.
+*
+* Argument(s) : p_name  Pointer to allocated object name. Used for allocations tracking. May be DEF_NULL.
+*
+*               p_seg   Pointer to segment from which to allocate memory. Will be allocated from
+*                       general-purpose heap if null.
+*
+*               size    Size of memory block to allocate, in bytes.
+*
+*               p_err   Pointer to variable that will receive the return error code from this function :
+*
+*                           LIB_MEM_ERR_NONE                Operation was successful.
+*
+*                           ------------------RETURNED BY Mem_SegAllocInternal()-------------------
+*                           LIB_MEM_ERR_INVALID_MEM_ALIGN   Invalid memory block alignment requested.
+*                           LIB_MEM_ERR_INVALID_MEM_SIZE    Invalid memory block size specified.
+*                           LIB_MEM_ERR_NULL_PTR            Error or segment data pointer NULL.
+*                           LIB_MEM_ERR_SEG_OVF             Allocation would overflow memory segment.
+*
+* Return(s)   : Pointer to allocated memory block, if successful.
+*
+*               DEF_NULL, otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) The memory block returned  by this function will be aligned on a word boundary. In
+*                   order to specify a specific alignment value, use either Mem_SegAllocExt() or
+*                   Mem_SegAllocHW().
+*********************************************************************************************************
+*/
+
+void  *Mem_SegAlloc (const  CPU_CHAR    *p_name,
+                            MEM_SEG     *p_seg,
+                            CPU_SIZE_T   size,
+                            LIB_ERR     *p_err)
+{
+    void  *p_blk;
+
+
+    if (p_seg == DEF_NULL) {                                    /* Alloc from heap if p_seg is null.                    */
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+        p_seg = &Mem_SegHeap;
+#else
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return (DEF_NULL);
+#endif
+    }
+
+    p_blk = Mem_SegAllocInternal(p_name,
+                                 p_seg,
+                                 size,
+                                 sizeof(CPU_ALIGN),
+                                 LIB_MEM_PADDING_ALIGN_NONE,
+                                 DEF_NULL,
+                                 p_err);
+
+    return (p_blk);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           Mem_SegAllocExt()
+*
+* Description : Allocates memory from specified memory segment.
+*
+* Argument(s) : p_name          Pointer to allocated object name. Used for allocations tracking. May be DEF_NULL.
+*
+*               p_seg           Pointer to segment from which to allocate memory. Will be allocated from
+*                               general-purpose heap if null.
+*
+*               size            Size of memory block to allocate, in bytes.
+*
+*               align           Required alignment of memory block, in bytes. MUST be a power of 2.
+*
+*               p_bytes_reqd    Pointer to variable that will receive the number of free bytes missing for
+*                               the allocation to succeed. Set to DEF_NULL to skip calculation.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                                   LIB_MEM_ERR_NONE                Operation was successful.
+*
+*                                   ------------------RETURNED BY Mem_SegAllocInternal()-------------------
+*                                   LIB_MEM_ERR_INVALID_MEM_ALIGN   Invalid memory block alignment requested.
+*                                   LIB_MEM_ERR_INVALID_MEM_SIZE    Invalid memory block size specified.
+*                                   LIB_MEM_ERR_NULL_PTR            Error or segment data pointer NULL.
+*                                   LIB_MEM_ERR_SEG_OVF             Allocation would overflow memory segment.
+*
+* Return(s)   : Pointer to allocated memory block, if successful.
+*
+*               DEF_NULL, otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+void  *Mem_SegAllocExt (const  CPU_CHAR    *p_name,
+                               MEM_SEG     *p_seg,
+                               CPU_SIZE_T   size,
+                               CPU_SIZE_T   align,
+                               CPU_SIZE_T  *p_bytes_reqd,
+                               LIB_ERR     *p_err)
+{
+    void  *p_blk;
+
+
+    if (p_seg == DEF_NULL) {                                    /* Alloc from heap if p_seg is null.                    */
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+        p_seg = &Mem_SegHeap;
+#else
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return (DEF_NULL);
+#endif
+    }
+
+    p_blk = Mem_SegAllocInternal(p_name,
+                                 p_seg,
+                                 size,
+                                 align,
+                                 LIB_MEM_PADDING_ALIGN_NONE,
+                                 p_bytes_reqd,
+                                 p_err);
+
+    return (p_blk);
+}
+
+
+/*
+*********************************************************************************************************
+*                                          Mem_SegAllocHW()
+*
+* Description : Allocates memory from specified segment. The returned buffer will be padded in function
+*               of memory segment's properties.
+*
+* Argument(s) : p_name          Pointer to allocated object name. Used for allocations tracking. May be DEF_NULL.
+*
+*               p_seg           Pointer to segment from which to allocate memory. Will be allocated from
+*                               general-purpose heap if null.
+*
+*               size            Size of memory block to allocate, in bytes.
+*
+*               align           Required alignment of memory block, in bytes. MUST be a power of 2.
+*
+*               p_bytes_reqd    Pointer to variable that will receive the number of free bytes missing for
+*                               the allocation to succeed. Set to DEF_NULL to skip calculation.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                                   LIB_MEM_ERR_NONE                Operation was successful.
+*
+*                                   ------------------RETURNED BY Mem_SegAllocInternal()-------------------
+*                                   LIB_MEM_ERR_INVALID_MEM_ALIGN   Invalid memory block alignment requested.
+*                                   LIB_MEM_ERR_INVALID_MEM_SIZE    Invalid memory block size specified.
+*                                   LIB_MEM_ERR_NULL_PTR            Error or segment data pointer NULL.
+*                                   LIB_MEM_ERR_SEG_OVF             Allocation would overflow memory segment.
+*
+* Return(s)   : Pointer to allocated memory block, if successful.
+*
+*               DEF_NULL, otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+void  *Mem_SegAllocHW (const  CPU_CHAR    *p_name,
+                              MEM_SEG     *p_seg,
+                              CPU_SIZE_T   size,
+                              CPU_SIZE_T   align,
+                              CPU_SIZE_T  *p_bytes_reqd,
+                              LIB_ERR     *p_err)
+{
+    void  *p_blk;
+
+
+    if (p_seg == DEF_NULL) {                                    /* Alloc from heap if p_seg is null.                    */
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+        p_seg = &Mem_SegHeap;
+#else
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return (DEF_NULL);
+#endif
+    }
+
+    p_blk = Mem_SegAllocInternal(p_name,
+                                 p_seg,
+                                 size,
+                                 align,
+                                 p_seg->PaddingAlign,
+                                 p_bytes_reqd,
+                                 p_err);
+
+    return (p_blk);
+}
+
+
+/*
+*********************************************************************************************************
+*                                          Mem_PoolCreate()
+*
+* Description : (1) Creates a memory pool :
+*
+*                   (a) Create    memory pool from heap or dedicated memory
+*                   (b) Allocate  memory pool memory blocks
+*                   (c) Configure memory pool
+*
+*
+* Argument(s) : p_pool          Pointer to a memory pool structure to create (see Note #1).
+*
+*               p_mem_base      Memory pool segment base address :
+*
+*                                       (a)     Null address    Memory pool allocated from general-purpose heap.
+*                                       (b) Non-null address    Memory pool allocated from dedicated memory
+*                                                                   specified by its base address.
+*
+*               mem_size        Size      of memory pool segment          (in bytes).
+*
+*               blk_nbr         Number    of memory pool blocks to create.
+*
+*               blk_size        Size      of memory pool blocks to create (in bytes).
+*
+*               blk_align       Alignment of memory pool blocks to specific word boundary (in bytes).
+*
+*               p_bytes_reqd    Optional pointer to a variable to ... :
+*
+*                                   (a) Return the number of bytes required to successfully
+*                                               allocate the memory pool, if any error(s);
+*                                       (b) Return 0, otherwise.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                                   LIB_MEM_ERR_NONE                    Operation was successful.
+*                                   LIB_MEM_ERR_NULL_PTR                Pointer to memory pool is null.
+*                                   LIB_MEM_ERR_INVALID_BLK_ALIGN       Invalid block alignment requested.
+*                                   LIB_MEM_ERR_INVALID_BLK_NBR         Invalid number of blocks specified.
+*                                   LIB_MEM_ERR_INVALID_BLK_SIZE        Invalid block size specified.
+*                                   LIB_MEM_ERR_INVALID_SEG_SIZE        Invalid segment size.
+*                                   LIB_MEM_ERR_HEAP_EMPTY              No more memory available on heap.
+*
+*                                   ---------------RETURNED BY Mem_SegOverlapChkCritical()----------------
+*                                   LIB_MEM_ERR_INVALID_SEG_EXISTS      Segment already exists.
+*                                   LIB_MEM_ERR_INVALID_SEG_OVERLAP     Segment overlaps another existing segment.
+*
+*                                   -----------------RETURNED BY Mem_SegAllocExtCritical()-----------------
+*                                   LIB_MEM_ERR_SEG_OVF                 Allocation would overflow memory segment.
+*
+*                                   ------------------RETURNED BY Mem_SegAllocInternal()-------------------
+*                                   LIB_MEM_ERR_INVALID_MEM_ALIGN       Invalid memory block alignment requested.
+*                                   LIB_MEM_ERR_INVALID_MEM_SIZE        Invalid memory block size specified.
+*                                   LIB_MEM_ERR_NULL_PTR                Error or segment data pointer NULL.
+*                                   LIB_MEM_ERR_SEG_OVF                 Allocation would overflow memory segment.
+*
+*                                   -----------------------RETURNED BY Mem_PoolClr()-----------------------
+*                                   LIB_MEM_ERR_NULL_PTR                Argument 'p_pool' passed a NULL pointer.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) This function is DEPRECATED and will be removed in a future version of this product.
+*                   Mem_DynPoolCreate() or Mem_DynPoolCreateHW() should be used instead.
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+void  Mem_PoolCreate (MEM_POOL          *p_pool,
+                      void              *p_mem_base,
+                      CPU_SIZE_T         mem_size,
+                      MEM_POOL_BLK_QTY   blk_nbr,
+                      CPU_SIZE_T         blk_size,
+                      CPU_SIZE_T         blk_align,
+                      CPU_SIZE_T        *p_bytes_reqd,
+                      LIB_ERR           *p_err)
+{
+    MEM_SEG           *p_seg;
+    void              *p_pool_mem;
+    CPU_SIZE_T         pool_size;
+    CPU_SIZE_T         blk_size_align;
+    CPU_ADDR           pool_addr_end;
+    MEM_POOL_BLK_QTY   blk_ix;
+    CPU_INT08U        *p_blk;
+    CPU_SR_ALLOC();
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)                 /* --------------- VALIDATE RTN ERR PTR --------------- */
+    if (p_err == DEF_NULL) {
+        CPU_SW_EXCEPTION(;);
+    }
+
+                                                                /* ------------- VALIDATE MEM POOL CREATE ------------- */
+    if (p_pool == DEF_NULL) {
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return;
+    }
+
+    if (p_mem_base != DEF_NULL) {
+        if (mem_size < 1u) {
+           *p_err = LIB_MEM_ERR_INVALID_SEG_SIZE;
+            return;
+        }
+    }
+
+    if (blk_nbr < 1u) {
+       *p_err = LIB_MEM_ERR_INVALID_BLK_NBR;
+        return;
+    }
+
+    if (blk_size < 1u) {
+       *p_err = LIB_MEM_ERR_INVALID_BLK_SIZE;
+        return;
+    }
+
+    if (MATH_IS_PWR2(blk_align) != DEF_YES) {                   /* Chk that req alignment is a pwr of 2.                */
+       *p_err = LIB_MEM_ERR_INVALID_BLK_ALIGN;
+        return;
+    }
+#endif
+
+    Mem_PoolClr(p_pool, p_err);                                 /* Init mem pool.                                       */
+    if (*p_err != LIB_MEM_ERR_NONE) {
+         return;
+    }
+
+                                                                /* -------- DETERMINE AND/OR ALLOC SEG TO USE --------- */
+    if (p_mem_base == DEF_NULL) {                               /* Use heap seg.                                        */
+        p_seg = &Mem_SegHeap;
+    } else {                                                    /* Use other seg.                                       */
+        CPU_CRITICAL_ENTER();
+        p_seg = Mem_SegOverlapChkCritical((CPU_ADDR)p_mem_base,
+                                                    mem_size,
+                                                    p_err);
+        switch (*p_err) {
+            case LIB_MEM_ERR_INVALID_SEG_EXISTS:                /* Seg already exists.                                  */
+                 break;
+
+            case LIB_MEM_ERR_NONE:                              /* Seg must be created.                                 */
+                 p_seg = (MEM_SEG *)Mem_SegAllocExtCritical(&Mem_SegHeap,
+                                                             sizeof(MEM_SEG),
+                                                             sizeof(CPU_ALIGN),
+                                                             LIB_MEM_PADDING_ALIGN_NONE,
+                                                             p_bytes_reqd,
+                                                             p_err);
+                 if (*p_err != LIB_MEM_ERR_NONE) {
+                     CPU_CRITICAL_EXIT();
+                     return;
+                 }
+
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)                    /* Track alloc if req'd.                                */
+                 Mem_SegAllocTrackCritical("Unknown segment data",
+                                           &Mem_SegHeap,
+                                            sizeof(MEM_SEG),
+                                            p_err);
+                 if (*p_err != LIB_MEM_ERR_NONE) {
+                     CPU_CRITICAL_EXIT();
+                     return;
+                 }
+#endif
+
+                 Mem_SegCreateCritical(          DEF_NULL,
+                                                 p_seg,
+                                       (CPU_ADDR)p_mem_base,
+                                                 LIB_MEM_PADDING_ALIGN_NONE,
+                                                 mem_size);
+                 break;
+
+
+            case LIB_MEM_ERR_INVALID_SEG_OVERLAP:
+            default:
+                 CPU_CRITICAL_EXIT();
+                 return;                                        /* Prevent 'break NOT reachable' compiler warning.      */
+        }
+
+        CPU_CRITICAL_EXIT();
+    }
+
+
+                                                                /* ---------------- ALLOC MEM FOR POOL ---------------- */
+                                                                /* Calc blk size with align.                            */
+    blk_size_align =  MATH_ROUND_INC_UP_PWR2(blk_size, blk_align);
+    pool_size      =  blk_size_align * blk_nbr;                 /* Calc required size for pool.                         */
+
+                                                                /* Alloc mem for pool.                                  */
+    p_pool_mem = (void *)Mem_SegAllocInternal("Unnamed static pool",
+                                               p_seg,
+                                               pool_size,
+                                               blk_align,
+                                               LIB_MEM_PADDING_ALIGN_NONE,
+                                               p_bytes_reqd,
+                                               p_err);
+    if (*p_err != LIB_MEM_ERR_NONE) {
+        return;
+    }
+
+                                                                /* ------------ ALLOC MEM FOR FREE BLK TBL ------------ */
+    p_pool->BlkFreeTbl = (void *)Mem_SegAllocInternal("Unnamed static pool free blk tbl",
+                                                      &Mem_SegHeap,
+                                                       blk_nbr * sizeof(void *),
+                                                       sizeof(CPU_ALIGN),
+                                                       LIB_MEM_PADDING_ALIGN_NONE,
+                                                       p_bytes_reqd,
+                                                       p_err);
+    if (*p_err != LIB_MEM_ERR_NONE) {
+        return;
+    }
+
+                                                                /* ------------------ INIT BLK LIST ------------------- */
+    p_blk = (CPU_INT08U *)p_pool_mem;
+    for (blk_ix = 0; blk_ix < blk_nbr; blk_ix++) {
+        p_pool->BlkFreeTbl[blk_ix]  = p_blk;
+        p_blk                      += blk_size_align;
+    }
+
+
+                                                                /* ------------------ INIT POOL DATA ------------------ */
+    pool_addr_end         = (CPU_ADDR)p_pool_mem + (pool_size - 1u);
+    p_pool->PoolAddrStart =  p_pool_mem;
+    p_pool->PoolAddrEnd   = (void *)pool_addr_end;
+    p_pool->BlkNbr        =  blk_nbr;
+    p_pool->BlkSize       =  blk_size_align;
+    p_pool->BlkFreeTblIx  =  blk_nbr;
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                            Mem_PoolClr()
+*
+* Description : Clears a memory pool (see Note #1).
+*
+* Argument(s) : p_pool   Pointer to a memory pool structure to clear (see Note #2).
+*
+*               p_err        Pointer to variable that will receive the return error code from this function :
+*
+*                               LIB_MEM_ERR_NONE                Operation was successful.
+*                               LIB_MEM_ERR_NULL_PTR            Argument 'p_pool' passed a NULL pointer.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application,
+*               Mem_PoolCreate().
+*
+* Note(s)     : (1) (a) Mem_PoolClr() ONLY clears a memory pool structure's variables & should ONLY be
+*                       called to initialize a memory pool structure prior to calling Mem_PoolCreate().
+*
+*                   (b) Mem_PoolClr() does NOT deallocate memory from the memory pool or deallocate the
+*                       memory pool itself & MUST NOT be called after calling Mem_PoolCreate() since
+*                       this will likely corrupt the memory pool management.
+*
+*               (2) Assumes 'p_pool' points to a valid memory pool (if non-NULL).
+*
+*               (3) This function is DEPRECATED and will be removed in a future version of this product.
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+void  Mem_PoolClr (MEM_POOL  *p_pool,
+                   LIB_ERR   *p_err)
+{
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)                 /* -------------- VALIDATE RTN ERR  PTR --------------- */
+    if (p_err == DEF_NULL) {
+        CPU_SW_EXCEPTION(;);
+    }
+
+                                                                /* -------------- VALIDATE MEM POOL PTR --------------- */
+    if (p_pool == DEF_NULL) {
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return;
+    }
+#endif
+
+    p_pool->PoolAddrStart = DEF_NULL;
+    p_pool->PoolAddrEnd   = DEF_NULL;
+    p_pool->BlkSize       = 0u;
+    p_pool->BlkNbr        = 0u;
+    p_pool->BlkFreeTbl    = DEF_NULL;
+    p_pool->BlkFreeTblIx  = 0u;
+
+   *p_err = LIB_MEM_ERR_NONE;
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          Mem_PoolBlkGet()
+*
+* Description : Gets a memory block from memory pool.
+*
+* Argument(s) : p_pool  Pointer to  memory pool to get memory block from.
+*
+*               size    Size of requested memory (in bytes).
+*
+*               p_err   Pointer to variable that will receive the return error code from this function :
+*
+*                           LIB_MEM_ERR_NONE                Operation was successful.
+*                           LIB_MEM_ERR_INVALID_BLK_SIZE    Invalid memory pool block size requested.
+*                           LIB_MEM_ERR_NULL_PTR            Argument 'p_pool' passed a NULL pointer.
+*                           LIB_MEM_ERR_POOL_EMPTY          NO memory blocks available in memory pool.
+*
+* Return(s)   : Pointer to memory block, if NO error(s).
+*
+*               Pointer to NULL,         otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) This function is DEPRECATED and will be removed in a future version of this product.
+*                   Mem_DynPoolBlkGet() should be used instead.
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+void  *Mem_PoolBlkGet (MEM_POOL    *p_pool,
+                       CPU_SIZE_T   size,
+                       LIB_ERR     *p_err)
+{
+    CPU_INT08U  *p_blk;
+    CPU_SR_ALLOC();
+
+
+   (void)&size;                                                 /* Prevent possible 'variable unused' warning.          */
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)                 /* -------------- VALIDATE MEM POOL GET --------------- */
+    if (p_err == DEF_NULL) {                                    /* Validate err ptr.                                    */
+        CPU_SW_EXCEPTION(DEF_NULL);
+    }
+
+    if (p_pool == DEF_NULL) {                                   /* Validate pool ptr.                                   */
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return (DEF_NULL);
+    }
+
+    if (size < 1u) {                                            /* Validate req'd size as non-NULL.                     */
+       *p_err = LIB_MEM_ERR_INVALID_BLK_SIZE;
+        return (DEF_NULL);
+    }
+
+    if (size > p_pool->BlkSize) {                               /* Validate req'd size <= mem pool blk size.            */
+       *p_err = LIB_MEM_ERR_INVALID_BLK_SIZE;
+        return (DEF_NULL);
+    }
+#endif
+
+
+                                                                /* -------------- GET MEM BLK FROM POOL --------------- */
+    p_blk = DEF_NULL;
+    CPU_CRITICAL_ENTER();
+    if (p_pool->BlkFreeTblIx > 0u) {
+        p_pool->BlkFreeTblIx                     -= 1u;
+        p_blk                                     = p_pool->BlkFreeTbl[p_pool->BlkFreeTblIx];
+        p_pool->BlkFreeTbl[p_pool->BlkFreeTblIx]  = DEF_NULL;
+    }
+    CPU_CRITICAL_EXIT();
+
+    if (p_blk == DEF_NULL) {
+       *p_err = LIB_MEM_ERR_POOL_EMPTY;
+    } else {
+       *p_err = LIB_MEM_ERR_NONE;
+    }
+
+    return (p_blk);
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          Mem_PoolBlkFree()
+*
+* Description : Free a memory block to memory pool.
+*
+* Argument(s) : p_pool  Pointer to memory pool to free memory block.
+*
+*               p_blk   Pointer to memory block address to free.
+*
+*               p_err   Pointer to variable that will receive the return error code from this function :
+*
+*                           LIB_MEM_ERR_NONE                        Operation was successful.
+*                           LIB_MEM_ERR_NULL_PTR                    Argument 'p_pool'/'p_blk' passed
+*                                                                       a NULL pointer.
+*                           LIB_MEM_ERR_INVALID_BLK_ADDR            Invalid memory block address.
+*                           LIB_MEM_ERR_INVALID_BLK_ADDR_IN_POOL            Memory block address already
+*                                                                        in memory pool.
+*                           LIB_MEM_ERR_POOL_FULL                   Pool is full.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) This function is DEPRECATED and will be removed in a future version of this product.
+*                   Mem_DynPoolBlkFree() should be used instead.
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+void  Mem_PoolBlkFree (MEM_POOL  *p_pool,
+                       void      *p_blk,
+                       LIB_ERR   *p_err)
+{
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    CPU_SIZE_T   tbl_ix;
+    CPU_BOOLEAN  addr_valid;
+#endif
+    CPU_SR_ALLOC();
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)                 /* -------------- VALIDATE MEM POOL FREE -------------- */
+    if (p_err == DEF_NULL) {
+        CPU_SW_EXCEPTION(;);
+    }
+
+    if (p_pool == DEF_NULL) {                                   /* Validate mem ptrs.                                   */
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return;
+    }
+
+    if (p_blk == DEF_NULL) {
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return;
+    }
+
+    addr_valid = Mem_PoolBlkIsValidAddr(p_pool, p_blk);         /* Validate mem blk as valid pool blk addr.             */
+    if (addr_valid != DEF_OK) {
+       *p_err = LIB_MEM_ERR_INVALID_BLK_ADDR;
+        return;
+    }
+
+    CPU_CRITICAL_ENTER();                                       /* Make sure blk isn't already in free list.            */
+    for (tbl_ix = 0u; tbl_ix < p_pool->BlkNbr; tbl_ix++) {
+        if (p_pool->BlkFreeTbl[tbl_ix] == p_blk) {
+            CPU_CRITICAL_EXIT();
+           *p_err = LIB_MEM_ERR_INVALID_BLK_ADDR_IN_POOL;
+            return;
+        }
+    }
+#else                                                           /* Double-free possibility if not in critical section.  */
+    CPU_CRITICAL_ENTER();
+#endif
+                                                                /* --------------- FREE MEM BLK TO POOL --------------- */
+    if (p_pool->BlkFreeTblIx >= p_pool->BlkNbr) {
+        CPU_CRITICAL_EXIT();
+       *p_err = LIB_MEM_ERR_POOL_FULL;
+        return;
+    }
+
+    p_pool->BlkFreeTbl[p_pool->BlkFreeTblIx]  = p_blk;
+    p_pool->BlkFreeTblIx                     += 1u;
+    CPU_CRITICAL_EXIT();
+
+   *p_err = LIB_MEM_ERR_NONE;
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                      Mem_PoolBlkGetNbrAvail()
+*
+* Description : Get memory pool's remaining number of blocks available to allocate.
+*
+* Argument(s) : p_pool   Pointer to a memory pool structure.
+*
+*               p_err    Pointer to variable that will receive the return error code from this function :
+*
+*                               LIB_MEM_ERR_NONE                Operation was successful.
+*                               LIB_MEM_ERR_NULL_PTR            Argument 'p_pool' passed a NULL pointer.
+*
+* Return(s)   : Remaining memory pool blocks,   if NO error(s).
+*
+*               0,                              otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) This function is DEPRECATED and will be removed in a future version of this product.
+*                   Mem_DynPoolBlkNbrAvailGet() should be used instead.
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+MEM_POOL_BLK_QTY  Mem_PoolBlkGetNbrAvail (MEM_POOL  *p_pool,
+                                          LIB_ERR   *p_err)
+{
+    CPU_SIZE_T  nbr_avail;
+    CPU_SR_ALLOC();
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+                                                                /* --------------- VALIDATE RTN ERR PTR --------------- */
+    if (p_err == DEF_NULL) {
+        CPU_SW_EXCEPTION(0u);
+    }
+                                                                /* ---------------- VALIDATE MEM POOL ----------------- */
+    if (p_pool == DEF_NULL) {                                   /* Validate mem ptr.                                    */
+       *p_err =  LIB_MEM_ERR_NULL_PTR;
+        return (0u);
+    }
+#endif
+
+    CPU_CRITICAL_ENTER();
+    nbr_avail = p_pool->BlkFreeTblIx;
+    CPU_CRITICAL_EXIT();
+
+   *p_err = LIB_MEM_ERR_NONE;
+
+    return (nbr_avail);
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          Mem_DynPoolCreate()
+*
+* Description : Creates a dynamic memory pool.
+*
+* Argument(s) : p_name          Pointer to pool name.
+*
+*               p_pool          Pointer to pool data.
+*
+*               p_seg           Pointer to segment from which to allocate memory. Will be allocated from
+*                               general-purpose heap if null.
+*
+*               blk_size        Size of memory block to allocate from pool, in bytes. See Note #1.
+*
+*               blk_align       Required alignment of memory block, in bytes. MUST be a power of 2.
+*
+*               blk_qty_init    Initial number of elements to be allocated in pool.
+*
+*               blk_qty_max     Maximum number of elements that can be allocated from this pool. Set to
+*                               LIB_MEM_BLK_QTY_UNLIMITED if no limit.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                                   LIB_MEM_ERR_NONE                Operation was successful.
+*
+*                                   --------------------RETURNED BY Mem_DynPoolCreateInternal()-------------------
+*                                   LIB_MEM_ERR_INVALID_BLK_ALIGN   Invalid requested block alignment.
+*                                   LIB_MEM_ERR_INVALID_BLK_SIZE    Invalid requested block size.
+*                                   LIB_MEM_ERR_INVALID_BLK_NBR     Invalid requested block quantity max.
+*                                   LIB_MEM_ERR_NULL_PTR            Pool data pointer NULL.
+*                                   LIB_MEM_ERR_INVALID_MEM_ALIGN   Invalid memory block alignment requested.
+*                                   LIB_MEM_ERR_INVALID_MEM_SIZE    Invalid memory block size specified.
+*                                   LIB_MEM_ERR_NULL_PTR            Error or segment data pointer NULL.
+*                                   LIB_MEM_ERR_SEG_OVF             Allocation would overflow memory segment.
+*
+* Return(s)   : None.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'blk_size' must be big enough to fit a pointer since the pointer to the next free
+*                   block is stored in the block itself (only when free/unused).
+*********************************************************************************************************
+*/
+
+void  Mem_DynPoolCreate (const  CPU_CHAR      *p_name,
+                                MEM_DYN_POOL  *p_pool,
+                                MEM_SEG       *p_seg,
+                                CPU_SIZE_T     blk_size,
+                                CPU_SIZE_T     blk_align,
+                                CPU_SIZE_T     blk_qty_init,
+                                CPU_SIZE_T     blk_qty_max,
+                                LIB_ERR       *p_err)
+{
+    if (p_seg == DEF_NULL) {                                    /* Alloc from heap if p_seg is null.                    */
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+        p_seg = &Mem_SegHeap;
+#else
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return (DEF_NULL);
+#endif
+    }
+
+    Mem_DynPoolCreateInternal(p_name,
+                              p_pool,
+                              p_seg,
+                              blk_size,
+                              blk_align,
+                              LIB_MEM_PADDING_ALIGN_NONE,
+                              blk_qty_init,
+                              blk_qty_max,
+                              p_err);
+}
+
+
+/*
+*********************************************************************************************************
+*                                        Mem_DynPoolCreateHW()
+*
+* Description : Creates a dynamic memory pool. Memory blocks will be padded according to memory segment's
+*               properties.
+*
+* Argument(s) : p_name          Pointer to pool name.
+*
+*               p_pool          Pointer to pool data.
+*
+*               p_seg           Pointer to segment from which to allocate memory. Will allocate from
+*                               general-purpose heap if null.
+*
+*               blk_size        Size of memory block to allocate from pool, in bytes. See Note #1.
+*
+*               blk_align       Required alignment of memory block, in bytes. MUST be a power of 2.
+*
+*               blk_qty_init    Initial number of elements to be allocated in pool.
+*
+*               blk_qty_max     Maximum number of elements that can be allocated from this pool. Set to
+*                               LIB_MEM_BLK_QTY_UNLIMITED if no limit.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                                   LIB_MEM_ERR_NONE                Operation was successful.
+*
+*                                   -------------------RETURNED BY Mem_DynPoolCreateInternal()-------------------
+*                                   LIB_MEM_ERR_INVALID_MEM_ALIGN   Invalid memory block alignment requested.
+*                                   LIB_MEM_ERR_INVALID_MEM_SIZE    Invalid memory block size specified.
+*                                   LIB_MEM_ERR_NULL_PTR            Error or segment data pointer NULL.
+*                                   LIB_MEM_ERR_SEG_OVF             Allocation would overflow memory segment.
+*
+* Return(s)   : None.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) 'blk_size' must be big enough to fit a pointer since the pointer to the next free
+*                   block is stored in the block itself (only when free/unused).
+*********************************************************************************************************
+*/
+
+void  Mem_DynPoolCreateHW (const  CPU_CHAR      *p_name,
+                                  MEM_DYN_POOL  *p_pool,
+                                  MEM_SEG       *p_seg,
+                                  CPU_SIZE_T     blk_size,
+                                  CPU_SIZE_T     blk_align,
+                                  CPU_SIZE_T     blk_qty_init,
+                                  CPU_SIZE_T     blk_qty_max,
+                                  LIB_ERR       *p_err)
+{
+    if (p_seg == DEF_NULL) {                                    /* Alloc from heap if p_seg is null.                    */
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+        p_seg = &Mem_SegHeap;
+#else
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return (DEF_NULL);
+#endif
+    }
+
+    Mem_DynPoolCreateInternal(p_name,
+                              p_pool,
+                              p_seg,
+                              blk_size,
+                              blk_align,
+                              p_seg->PaddingAlign,
+                              blk_qty_init,
+                              blk_qty_max,
+                              p_err);
+}
+
+
+/*
+*********************************************************************************************************
+*                                          Mem_DynPoolBlkGet()
+*
+* Description : Gets a memory block from specified pool, growing it if needed.
+*
+* Argument(s) : p_pool  Pointer to pool data.
+*
+*               p_err   Pointer to variable that will receive the return error code from this function :
+*
+*                           LIB_MEM_ERR_NONE                    Operation was successful.
+*                           LIB_MEM_ERR_NULL_PTR                Pool data pointer NULL.
+*                           LIB_MEM_ERR_POOL_EMPTY              Pools is empty.
+*
+*                           ----------------------RETURNED BY Mem_SegAllocInternal()-----------------------
+*                           LIB_MEM_ERR_INVALID_MEM_ALIGN       Invalid memory block alignment requested.
+*                           LIB_MEM_ERR_INVALID_MEM_SIZE        Invalid memory block size specified.
+*                           LIB_MEM_ERR_NULL_PTR                Error or segment data pointer NULL.
+*                           LIB_MEM_ERR_SEG_OVF                 Allocation would overflow memory segment.
+*
+* Return(s)   : Pointer to memory block, if successful.
+*
+*               DEF_NULL, otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+void  *Mem_DynPoolBlkGet (MEM_DYN_POOL  *p_pool,
+                          LIB_ERR       *p_err)
+{
+           void      *p_blk;
+    const  CPU_CHAR  *p_pool_name;
+    CPU_SR_ALLOC();
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (p_err == DEF_NULL) {                                    /* Chk for NULL err ptr.                                */
+        CPU_SW_EXCEPTION(DEF_NULL);
+    }
+
+    if (p_pool == DEF_NULL) {                                   /* Chk for NULL pool data ptr.                          */
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return (DEF_NULL);
+    }
+#endif
+
+                                                                /* Ensure pool is not empty if qty is limited.          */
+    if (p_pool->BlkQtyMax != LIB_MEM_BLK_QTY_UNLIMITED) {
+        CPU_CRITICAL_ENTER();
+        if (p_pool->BlkAllocCnt >= p_pool->BlkQtyMax) {
+            CPU_CRITICAL_EXIT();
+
+           *p_err = LIB_MEM_ERR_POOL_EMPTY;
+            return (DEF_NULL);
+        }
+
+        p_pool->BlkAllocCnt++;
+        CPU_CRITICAL_EXIT();
+    }
+
+                                                                /* --------------- ALLOC FROM FREE LIST --------------- */
+    CPU_CRITICAL_ENTER();
+    if (p_pool->BlkFreePtr != DEF_NULL) {
+        p_blk              = p_pool->BlkFreePtr;
+        p_pool->BlkFreePtr = *((void **)p_blk);
+        CPU_CRITICAL_EXIT();
+
+       *p_err = LIB_MEM_ERR_NONE;
+
+        return (p_blk);
+    }
+    CPU_CRITICAL_EXIT();
+
+                                                                /* ------------------ ALLOC NEW BLK ------------------- */
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
+    p_pool_name = p_pool->NamePtr;
+#else
+    p_pool_name = DEF_NULL;
+#endif
+    p_blk = Mem_SegAllocInternal(p_pool_name,
+                                 p_pool->PoolSegPtr,
+                                 p_pool->BlkSize,
+                                 p_pool->BlkAlign,
+                                 p_pool->BlkPaddingAlign,
+                                 DEF_NULL,
+                                 p_err);
+    if (*p_err != LIB_MEM_ERR_NONE) {
+        return (DEF_NULL);
+    }
+
+    return (p_blk);
+}
+
+
+/*
+*********************************************************************************************************
+*                                         Mem_DynPoolBlkFree()
+*
+* Description : Frees memory block, making it available for future use.
+*
+* Argument(s) : p_pool  Pointer to pool data.
+*
+*               p_blk   Pointer to first byte of memory block.
+*
+*               p_err   Pointer to variable that will receive the return error code from this function :
+*
+*                           LIB_MEM_ERR_NONE        Operation was successful.
+*                           LIB_MEM_ERR_NULL_PTR    'p_pool' or 'p_blk' pointer passed is NULL.
+*                           LIB_MEM_ERR_POOL_FULL   Pool is full.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+void  Mem_DynPoolBlkFree (MEM_DYN_POOL  *p_pool,
+                          void          *p_blk,
+                          LIB_ERR       *p_err)
+{
+    CPU_SR_ALLOC();
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (p_err == DEF_NULL) {                                    /* Chk for NULL err ptr.                                */
+        CPU_SW_EXCEPTION(;);
+    }
+
+    if (p_pool == DEF_NULL) {                                   /* Chk for NULL pool data ptr.                          */
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return;
+    }
+
+    if (p_blk == DEF_NULL) {
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return;
+    }
+#endif
+
+    if (p_pool->BlkQtyMax != LIB_MEM_BLK_QTY_UNLIMITED) {       /* Ensure pool is not full.                             */
+        CPU_CRITICAL_ENTER();
+        if (p_pool->BlkAllocCnt == 0u) {
+            CPU_CRITICAL_EXIT();
+
+           *p_err = LIB_MEM_ERR_POOL_FULL;
+            return;
+        }
+
+        p_pool->BlkAllocCnt--;
+        CPU_CRITICAL_EXIT();
+    }
+
+    CPU_CRITICAL_ENTER();
+   *((void **)p_blk)   = p_pool->BlkFreePtr;
+    p_pool->BlkFreePtr = p_blk;
+    CPU_CRITICAL_EXIT();
+
+   *p_err = LIB_MEM_ERR_NONE;
+}
+
+
+/*
+*********************************************************************************************************
+*                                     Mem_DynPoolBlkNbrAvailGet()
+*
+* Description : Gets number of available blocks in dynamic memory pool. This call will fail with a
+*               dynamic memory pool for which no limit was set at creation.
+*
+* Argument(s) : p_pool  Pointer to pool data.
+*
+*               p_err   Pointer to variable that will receive the return error code from this function :
+*
+*                           LIB_MEM_ERR_NONE                Operation was successful.
+*                           LIB_MEM_ERR_NULL_PTR            'p_pool' pointer passed is NULL.
+*                           LIB_MEM_ERR_POOL_UNLIMITED      Pool has no specified limit.
+*
+* Return(s)   : Number of blocks available in dynamic memory pool, if successful.
+*
+*               0, if pool is empty or if an error occurred.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : None.
+*********************************************************************************************************
+*/
+
+CPU_SIZE_T  Mem_DynPoolBlkNbrAvailGet (MEM_DYN_POOL  *p_pool,
+                                       LIB_ERR       *p_err)
+{
+    CPU_SIZE_T  blk_nbr_avail;
+    CPU_SR_ALLOC();
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (p_err == DEF_NULL) {                                    /* Chk for NULL err ptr.                                */
+        CPU_SW_EXCEPTION(;);
+    }
+
+    if (p_pool == DEF_NULL) {                                   /* Chk for NULL pool data ptr.                          */
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return (0u);
+    }
+#endif
+
+    if (p_pool->BlkQtyMax != LIB_MEM_BLK_QTY_UNLIMITED) {
+        CPU_CRITICAL_ENTER();
+        blk_nbr_avail = p_pool->BlkQtyMax - p_pool->BlkAllocCnt;
+        CPU_CRITICAL_EXIT();
+
+       *p_err = LIB_MEM_ERR_NONE;
+    } else {
+        blk_nbr_avail = 0u;
+       *p_err         = LIB_MEM_ERR_POOL_UNLIMITED;
+    }
+
+    return (blk_nbr_avail);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           Mem_OutputUsage()
+*
+* Description : Outputs memory usage report through 'out_fnct'.
+*
+* Argument(s) : out_fnct        Pointer to output function.
+*
+*               print_details   DEF_YES, if the size of each allocation should be printed.
+*                               DEF_NO,  otherwise.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                                   LIB_MEM_ERR_NONE                Operation was successful.
+*                                   LIB_MEM_ERR_NULL_PTR            'out_fnct' pointer passed is NULL.
+*
+*                                   ---------------------RETURNED BY Mem_SegRemSizeGet()--------------------
+*                                   LIB_MEM_ERR_NULL_PTR            Segment data pointer NULL.
+*                                   LIB_MEM_ERR_INVALID_MEM_ALIGN   Invalid memory alignment.
+*
+* Return(s)   : None.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
+void  Mem_OutputUsage(void     (*out_fnct) (CPU_CHAR *),
+                      LIB_ERR   *p_err)
+{
+    CPU_CHAR   str[DEF_INT_32U_NBR_DIG_MAX];
+    MEM_SEG   *p_seg;
+    CPU_SR_ALLOC();
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (p_err == DEF_NULL) {                                    /* Chk for NULL err ptr.                                */
+        CPU_SW_EXCEPTION(;);
+    }
+
+    if (out_fnct == DEF_NULL) {                                 /* Chk for NULL out fnct ptr.                           */
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return;
+    }
+#endif
+
+    out_fnct("---------------- Memory allocation info ----------------\r\n");
+    out_fnct("| Type    | Size       | Free size  | Name\r\n");
+    out_fnct("|---------|------------|------------|-------------------\r\n");
+
+    CPU_CRITICAL_ENTER();
+    p_seg = Mem_SegHeadPtr;
+    while (p_seg != DEF_NULL) {
+        CPU_SIZE_T       rem_size;
+        MEM_SEG_INFO     seg_info;
+        MEM_ALLOC_INFO  *p_alloc;
+
+
+        rem_size = Mem_SegRemSizeGet(p_seg, 1u, &seg_info, p_err);
+        if (*p_err != LIB_MEM_ERR_NONE) {
+            return;
+        }
+
+        out_fnct("| Section | ");
+
+        (void)Str_FmtNbr_Int32U(seg_info.TotalSize,
+                                10u,
+                                DEF_NBR_BASE_DEC,
+                                ' ',
+                                DEF_NO,
+                                DEF_YES,
+                               &str[0u]);
+
+        out_fnct(str);
+        out_fnct(" | ");
+
+        (void)Str_FmtNbr_Int32U(rem_size,
+                                10u,
+                                DEF_NBR_BASE_DEC,
+                                ' ',
+                                DEF_NO,
+                                DEF_YES,
+                               &str[0u]);
+
+        out_fnct(str);
+        out_fnct(" | ");
+        out_fnct((p_seg->NamePtr != DEF_NULL) ? (CPU_CHAR *)p_seg->NamePtr : (CPU_CHAR *)"Unknown");
+        out_fnct("\r\n");
+
+        p_alloc = p_seg->AllocInfoHeadPtr;
+        while (p_alloc != DEF_NULL) {
+            out_fnct("| -> Obj  | ");
+
+            (void)Str_FmtNbr_Int32U(p_alloc->Size,
+                                    10u,
+                                    DEF_NBR_BASE_DEC,
+                                    ' ',
+                                    DEF_NO,
+                                    DEF_YES,
+                                   &str[0u]);
+
+            out_fnct(str);
+            out_fnct(" |            | ");
+
+            out_fnct((p_alloc->NamePtr != DEF_NULL) ? (CPU_CHAR *)p_alloc->NamePtr : (CPU_CHAR *)"Unknown");
+            out_fnct("\r\n");
+
+            p_alloc = p_alloc->NextPtr;
+        }
+
+        p_seg = p_seg->NextPtr;
+    }
+    CPU_CRITICAL_EXIT();
+
+   *p_err = LIB_MEM_ERR_NONE;
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*********************************************************************************************************
+*                                           LOCAL FUNCTIONS
+*********************************************************************************************************
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                       Mem_SegCreateCritical()
+*
+* Description : Creates a new memory segment to be used for runtime memory allocation or dynamic pools.
+*
+* Argument(s) : p_name          Pointer to segment name.
+*
+*               p_seg           Pointer to segment data. Must be allocated by caller.
+*               -----           Argument validated by caller.
+*
+*               seg_base_addr   Segment's first byte address.
+*
+*               padding_align   Padding alignment, in bytes, that will be added to any allocated buffer
+*                               from this memory segment. MUST be a power of 2.
+*                               LIB_MEM_PADDING_ALIGN_NONE means no padding.
+*               -------------   Argument validated by caller.
+*
+*               size            Total size of segment, in bytes.
+*               ----            Argument validated by caller.
+*
+* Return(s)   : Pointer to segment data, if successful.
+*
+*               DEF_NULL, otherwise.
+*
+* Caller(s)   : Mem_PoolCreate(),
+*               Mem_SegCreate().
+*
+* Note(s)     : (1) This function MUST be called within a CRITICAL_SECTION.
+*********************************************************************************************************
+*/
+
+static  void  Mem_SegCreateCritical(const  CPU_CHAR    *p_name,
+                                           MEM_SEG     *p_seg,
+                                           CPU_ADDR     seg_base_addr,
+                                           CPU_SIZE_T   padding_align,
+                                           CPU_SIZE_T   size)
+{
+    p_seg->AddrBase         =  seg_base_addr;
+    p_seg->AddrEnd          = (seg_base_addr + (size - 1u));
+    p_seg->AddrNext         =  seg_base_addr;
+    p_seg->NextPtr          =  Mem_SegHeadPtr;
+    p_seg->PaddingAlign     =  padding_align;
+
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
+    p_seg->NamePtr          = p_name;
+    p_seg->AllocInfoHeadPtr = DEF_NULL;
+#else
+    (void)&p_name;
+#endif
+
+    Mem_SegHeadPtr = p_seg;
+}
+
+
+/*
+*********************************************************************************************************
+*                                      Mem_SegOverlapChkCritical()
+*
+* Description : Checks if existing memory segment exists or overlaps with specified memory area.
+*
+* Argument(s) : seg_base_addr   Address of first byte of memory area.
+*
+*               size            Size of memory area, in bytes.
+*
+*               p_err       Pointer to variable that will receive the return error code from this function :
+*
+*                               LIB_MEM_ERR_INVALID_SEG_OVERLAP     Segment overlaps another existing segment.
+*                               LIB_MEM_ERR_INVALID_SEG_EXISTS      Segment already exists.
+*
+* Return(s)   : Pointer to memory segment that overlaps.
+*
+*               DEF_NULL, otherwise.
+*
+* Caller(s)   : Mem_PoolCreate(),
+*               Mem_SegCreate().
+*
+* Note(s)     : (1) This function MUST be called within a CRITICAL_SECTION.
+*********************************************************************************************************
+*/
+
+static  MEM_SEG  *Mem_SegOverlapChkCritical (CPU_ADDR     seg_base_addr,
+                                             CPU_SIZE_T   size,
+                                             LIB_ERR     *p_err)
+{
+    MEM_SEG   *p_seg_chk;
+    CPU_ADDR   seg_new_end;
+    CPU_ADDR   seg_chk_start;
+    CPU_ADDR   seg_chk_end;
+
+
+    seg_new_end = seg_base_addr + (size - 1u);
+    p_seg_chk   = Mem_SegHeadPtr;
+
+    while (p_seg_chk != DEF_NULL) {
+        seg_chk_start = (CPU_ADDR)p_seg_chk->AddrBase;
+        seg_chk_end   = (CPU_ADDR)p_seg_chk->AddrEnd;
+
+        if ((seg_base_addr == seg_chk_start) && (seg_new_end == seg_chk_end)) {
+           *p_err = LIB_MEM_ERR_INVALID_SEG_EXISTS;
+            return (p_seg_chk);
+        } else if (((seg_base_addr >= seg_chk_start) && (seg_base_addr <= seg_chk_end)) ||
+                   ((seg_base_addr <= seg_chk_start) && (seg_new_end   >= seg_chk_start))) {
+           *p_err = LIB_MEM_ERR_INVALID_SEG_OVERLAP;
+            return (p_seg_chk);
+        }
+
+        p_seg_chk = p_seg_chk->NextPtr;
+    }
+
+   *p_err = LIB_MEM_ERR_NONE;
+
+    return (DEF_NULL);
+}
+
+
+/*
+*********************************************************************************************************
+*                                       Mem_SegAllocInternal()
+*
+* Description : Allocates memory from specified segment.
+*
+* Argument(s) : p_name  Pointer to allocated object name. Used for allocations tracking. May be DEF_NULL.
+*
+*               p_seg           Pointer to segment from which to allocate memory.
+*               -----           Argument validated by caller.
+*
+*               size            Size of memory block to allocate, in bytes.
+*
+*               align           Required alignment of memory block, in bytes. MUST be a power of 2.
+*
+*               padding_align   Padding alignment, in bytes, that will be added to any allocated buffer from
+*                               this memory segment. MUST be a power of 2. LIB_MEM_PADDING_ALIGN_NONE
+*                               means no padding.
+*
+*               p_bytes_reqd    Pointer to variable that will receive the number of free bytes missing for
+*                                the allocation to succeed. Set to DEF_NULL to skip calculation.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                                   LIB_MEM_ERR_INVALID_MEM_ALIGN   Invalid memory block alignment requested.
+*                                   LIB_MEM_ERR_INVALID_MEM_SIZE    Invalid memory block size specified.
+*                                   LIB_MEM_ERR_NULL_PTR            Error or segment data pointer NULL.
+*
+*                                   ------------------RETURNED BY Mem_SegAllocExtCritical()------------------
+*                                   LIB_MEM_ERR_SEG_OVF             Allocation would overflow memory segment.
+*
+* Return(s)   : Pointer to allocated memory block, if successful.
+*
+*               DEF_NULL, otherwise.
+*
+* Caller(s)   : Mem_DynPoolBlkGet(),
+*               Mem_DynPoolCreateInternal(),
+*               Mem_HeapAlloc(),
+*               Mem_PoolCreate(),
+*               Mem_SegAlloc(),
+*               Mem_SegAllocExt(),
+*               Mem_SegAllocHW().
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+static  void  *Mem_SegAllocInternal (const  CPU_CHAR    *p_name,
+                                            MEM_SEG     *p_seg,
+                                            CPU_SIZE_T   size,
+                                            CPU_SIZE_T   align,
+                                            CPU_SIZE_T   padding_align,
+                                            CPU_SIZE_T  *p_bytes_reqd,
+                                            LIB_ERR     *p_err)
+{
+    void  *p_blk;
+    CPU_SR_ALLOC();
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (p_err == DEF_NULL) {                                    /* Chk for null err ptr.                                */
+        CPU_SW_EXCEPTION(DEF_NULL);
+    }
+
+    if (size < 1u) {                                            /* Chk for invalid sized mem req.                       */
+       *p_err = LIB_MEM_ERR_INVALID_MEM_SIZE;
+        return (DEF_NULL);
+    }
+
+    if (MATH_IS_PWR2(align) != DEF_YES) {                       /* Chk that align is a pwr of 2.                        */
+       *p_err = LIB_MEM_ERR_INVALID_MEM_ALIGN;
+        return (DEF_NULL);
+    }
+#endif
+
+    CPU_CRITICAL_ENTER();
+    p_blk = Mem_SegAllocExtCritical(p_seg,
+                                    size,
+                                    align,
+                                    padding_align,
+                                    p_bytes_reqd,
+                                    p_err);
+    if (*p_err != LIB_MEM_ERR_NONE) {
+        CPU_CRITICAL_EXIT();
+        return (DEF_NULL);
+    }
+
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)                    /* Track alloc if req'd.                                */
+    Mem_SegAllocTrackCritical(p_name,
+                              p_seg,
+                              size,
+                              p_err);
+    if (*p_err != LIB_MEM_ERR_NONE) {
+        CPU_CRITICAL_EXIT();
+        return (DEF_NULL);
+    }
+#else
+    (void)&p_name;
+#endif
+    CPU_CRITICAL_EXIT();
+
+    return (p_blk);
+}
+
+
+/*
+*********************************************************************************************************
+*                                      Mem_SegAllocExtCritical()
+*
+* Description : Allocates memory from specified segment.
+*
+* Argument(s) : p_seg           Pointer to segment from which to allocate memory.
+*
+*               size            Size of memory block to allocate, in bytes.
+*
+*               align           Required alignment of memory block, in bytes. MUST be a power of 2.
+*
+*               padding_align   Padding alignment, in bytes, that will be added to any allocated buffer from
+*                               this memory segment. MUST be a power of 2. LIB_MEM_PADDING_ALIGN_NONE
+*                               means no padding.
+*
+*               p_bytes_reqd    Pointer to variable that will receive the number of free bytes missing for
+*                               the allocation to succeed. Set to DEF_NULL to skip calculation.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                                   LIB_MEM_ERR_SEG_OVF     Allocation would overflow memory segment.
+*
+* Return(s)   : Pointer to allocated memory block, if successful.
+*
+*               DEF_NULL, otherwise.
+*
+* Caller(s)   : Mem_PoolCreate(),
+*               Mem_SegAllocInternal(),
+*               Mem_SegAllocTrackCritical().
+*
+* Note(s)     : (1) This function MUST be called within a CRITICAL_SECTION.
+*********************************************************************************************************
+*/
+
+static  void  *Mem_SegAllocExtCritical (MEM_SEG     *p_seg,
+                                        CPU_SIZE_T   size,
+                                        CPU_SIZE_T   align,
+                                        CPU_SIZE_T   padding_align,
+                                        CPU_SIZE_T  *p_bytes_reqd,
+                                        LIB_ERR     *p_err)
+{
+    CPU_ADDR    blk_addr;
+    CPU_ADDR    addr_next;
+    CPU_SIZE_T  size_rem_seg;
+    CPU_SIZE_T  size_tot_blk;
+    CPU_SIZE_T  blk_align = DEF_MAX(align, padding_align);
+
+
+    blk_addr     = MATH_ROUND_INC_UP_PWR2(p_seg->AddrNext,      /* Compute align'ed blk addr.                           */
+                                          blk_align);
+    addr_next    = MATH_ROUND_INC_UP_PWR2(blk_addr + size,      /* Compute addr of next alloc.                          */
+                                          padding_align);
+    size_rem_seg = p_seg->AddrEnd - p_seg->AddrNext + 1u;
+    size_tot_blk = addr_next - p_seg->AddrNext;                 /* Compute tot blk size including align and padding.    */
+    if (size_rem_seg < size_tot_blk) {                          /* If seg doesn't have enough space ...                 */
+        if (p_bytes_reqd != DEF_NULL) {                         /* ... calc nbr of req'd bytes.                         */
+           *p_bytes_reqd = size_tot_blk - size_rem_seg;
+        }
+
+       *p_err = LIB_MEM_ERR_SEG_OVF;
+        return (DEF_NULL);
+    }
+
+    p_seg->AddrNext = addr_next;
+
+   *p_err = LIB_MEM_ERR_NONE;
+
+    return ((void *)blk_addr);
+}
+
+
+/*
+*********************************************************************************************************
+*                                     Mem_SegAllocTrackCritical()
+*
+* Description : Tracks segment allocation, adding the 'size' of the allocation under the 'p_name' entry.
+*
+* Argument(s) : p_name  Pointer to the name of the object. This string is not copied and its memory should
+*                       remain accessible at all times.
+*
+*               p_seg   Pointer to segment data.
+*
+*               size    Allocation size, in bytes.
+*
+*               p_err   Pointer to variable that will receive the return error code from this function :
+*
+*                           LIB_MEM_ERR_HEAP_EMPTY      No more memory available on heap
+*
+*                           --------------RETURNED BY Mem_SegAllocExtCritical()---------------
+*                           LIB_MEM_ERR_SEG_OVF         Allocation would overflow memory segment.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Mem_PoolCreate(),
+*               Mem_SegAllocInternal().
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
+static  void  Mem_SegAllocTrackCritical (const  CPU_CHAR    *p_name,
+                                                MEM_SEG     *p_seg,
+                                                CPU_SIZE_T   size,
+                                                LIB_ERR     *p_err)
+{
+    MEM_ALLOC_INFO  *p_alloc;
+
+
+                                                                /* ------- UPDATE ALLOC INFO LIST, IF POSSIBLE -------- */
+    p_alloc = p_seg->AllocInfoHeadPtr;
+    while (p_alloc != DEF_NULL) {
+        if (p_alloc->NamePtr == p_name) {
+            p_alloc->Size += size;
+           *p_err = LIB_MEM_ERR_NONE;
+            return;
+        }
+
+        p_alloc = p_alloc->NextPtr;
+    }
+
+                                                                /* --------- ADD NEW ALLOC INFO ENTRY IN LIST --------- */
+    p_alloc = Mem_SegAllocExtCritical(&Mem_SegHeap,             /* Alloc new alloc info struct on heap.                 */
+                                       sizeof(MEM_ALLOC_INFO),
+                                       sizeof(CPU_ALIGN),
+                                       LIB_MEM_PADDING_ALIGN_NONE,
+                                       DEF_NULL,
+                                       p_err);
+    if (*p_err != LIB_MEM_ERR_NONE) {
+        return;
+    }
+
+    p_alloc->NamePtr = p_name;                                  /* Populate alloc info.                                 */
+    p_alloc->Size    = size;
+
+    p_alloc->NextPtr        = p_seg->AllocInfoHeadPtr;          /* Prepend new item in list.                            */
+    p_seg->AllocInfoHeadPtr = p_alloc;
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                     Mem_DynPoolCreateInternal()
+*
+* Description : Creates a dynamic memory pool.
+*
+* Argument(s) : p_name              Pointer to pool name.
+*
+*               p_pool              Pointer to pool data.
+*
+*               p_seg               Pointer to segment from which to allocate memory.
+*
+*               blk_size            Size of memory block to allocate from pool, in bytes. See Note #1.
+*
+*               blk_align           Required alignment of memory block, in bytes. MUST be a power of 2.
+*
+*               blk_padding_align   Block's padding alignment, in bytes, that will be added at the end
+*                                   of block's buffer. MUST be a power of 2. LIB_MEM_PADDING_ALIGN_NONE
+*                                   means no padding.
+*
+*               blk_qty_init        Initial number of elements to be allocated in pool.
+*
+*               blk_qty_max         Maximum number of elements that can be allocated from this pool. Set to
+*                                   LIB_MEM_BLK_QTY_UNLIMITED if no limit.
+*
+*               p_err           Pointer to variable that will receive the return error code from this function :
+*
+*                                   LIB_MEM_ERR_INVALID_BLK_ALIGN   Invalid requested block alignment.
+*                                   LIB_MEM_ERR_INVALID_BLK_SIZE    Invalid requested block size.
+*                                   LIB_MEM_ERR_INVALID_BLK_NBR     Invalid requested block quantity max.
+*                                   LIB_MEM_ERR_NULL_PTR            Pool data pointer NULL.
+*
+*                                   ------------------RETURNED BY Mem_SegAllocInternal()-------------------
+*                                   LIB_MEM_ERR_INVALID_MEM_ALIGN   Invalid memory block alignment requested.
+*                                   LIB_MEM_ERR_INVALID_MEM_SIZE    Invalid memory block size specified.
+*                                   LIB_MEM_ERR_NULL_PTR            Error or segment data pointer NULL.
+*                                   LIB_MEM_ERR_SEG_OVF             Allocation would overflow memory segment.
+*
+* Return(s)   : None.
+*
+* Caller(s)   : Mem_DynPoolCreate(),
+*               Mem_DynPoolCreateHW().
+*
+* Note(s)     : (1) 'blk_size' must be big enough to fit a pointer since the pointer to the next free
+*                   block is stored in the block itself (only when free/unused).
+*********************************************************************************************************
+*/
+
+static  void  Mem_DynPoolCreateInternal (const  CPU_CHAR      *p_name,
+                                                MEM_DYN_POOL  *p_pool,
+                                                MEM_SEG       *p_seg,
+                                                CPU_SIZE_T     blk_size,
+                                                CPU_SIZE_T     blk_align,
+                                                CPU_SIZE_T     blk_padding_align,
+                                                CPU_SIZE_T     blk_qty_init,
+                                                CPU_SIZE_T     blk_qty_max,
+                                                LIB_ERR       *p_err)
+{
+    CPU_INT08U  *p_blks;
+    CPU_SIZE_T   blk_size_align;
+    CPU_SIZE_T   blk_align_worst = DEF_MAX(blk_align, blk_padding_align);
+
+
+#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
+    if (p_err == DEF_NULL) {                                    /* Chk for NULL err ptr.                                */
+        CPU_SW_EXCEPTION(DEF_NULL);
+    }
+
+    if (p_pool == DEF_NULL) {                                   /* Chk for NULL pool data ptr.                          */
+       *p_err = LIB_MEM_ERR_NULL_PTR;
+        return;
+    }
+
+    if (blk_size < 1u) {                                        /* Chk for inv blk size.                                */
+       *p_err = LIB_MEM_ERR_INVALID_BLK_SIZE;
+        return;
+    }
+
+    if ((blk_qty_max  != LIB_MEM_BLK_QTY_UNLIMITED) &&          /* Chk for invalid blk qty.                             */
+        (blk_qty_init >  blk_qty_max)) {
+       *p_err = LIB_MEM_ERR_INVALID_BLK_NBR;
+        return;
+    }
+
+    if (MATH_IS_PWR2(blk_align) != DEF_YES) {                   /* Chk for illegal align spec.                          */
+       *p_err = LIB_MEM_ERR_INVALID_BLK_ALIGN;
+        return;
+    }
+#endif
+
+                                                                /* Calc blk size with align.                            */
+    if (blk_size < sizeof(void *)) {                            /* If size if smaller than ptr ...                      */
+                                                                /* ... inc size to ptr size.                            */
+        blk_size_align = MATH_ROUND_INC_UP_PWR2(sizeof(void *), blk_align_worst);
+    } else {
+        blk_size_align = MATH_ROUND_INC_UP_PWR2(blk_size, blk_align_worst);
+    }
+
+    if (blk_qty_init != 0u) {                                   /* Alloc init blks.                                     */
+        p_blks = (CPU_INT08U *)Mem_SegAllocInternal(p_name,
+                                                    p_seg,
+                                                    blk_size_align * blk_qty_init,
+                                                    blk_align_worst,
+                                                    LIB_MEM_PADDING_ALIGN_NONE,
+                                                    DEF_NULL,
+                                                    p_err);
+        if (*p_err != LIB_MEM_ERR_NONE) {
+            return;
+        }
+    }
+
+
+                                                                /* ----------------- CREATE POOL DATA ----------------- */
+    p_pool->PoolSegPtr      = p_seg;
+    p_pool->BlkSize         = blk_size;
+    p_pool->BlkAlign        = blk_align_worst;
+    p_pool->BlkPaddingAlign = blk_padding_align;
+    p_pool->BlkQtyMax       = blk_qty_max;
+    p_pool->BlkAllocCnt     = 0u;
+
+    if (blk_qty_init != 0u) {                                   /* Init free list.                                      */
+        CPU_SIZE_T  i;
+
+
+        p_pool->BlkFreePtr = (void *)p_blks;
+        for (i = 0u; i < blk_qty_init - 1u; i++) {
+           *((void **)p_blks)  = p_blks + blk_size_align;
+            p_blks            += blk_size_align;
+        }
+       *((void **)p_blks) = DEF_NULL;
+    } else {
+        p_pool->BlkFreePtr = DEF_NULL;
+    }
+
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
+    p_pool->NamePtr = p_name;
+#endif
+
+   *p_err = LIB_MEM_ERR_NONE;
+}
+
+
+/*
+*********************************************************************************************************
+*                                      Mem_PoolBlkIsValidAddr()
+*
+* Description : Calculates if a given memory block address is valid for the memory pool.
+*
+* Argument(s) : p_pool   Pointer to memory pool structure to validate memory block address.
+*               ------   Argument validated by caller.
+*
+*               p_mem    Pointer to memory block address to validate.
+*               -----    Argument validated by caller.
+*
+* Return(s)   : DEF_YES, if valid memory pool block address.
+*
+*               DEF_NO,  otherwise.
+*
+* Caller(s)   : Mem_PoolBlkFree().
+*
+* Note(s)     : none.
+*********************************************************************************************************
+*/
+
+#if ((LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) && \
+     (LIB_MEM_CFG_HEAP_SIZE      >  0u))
+static  CPU_BOOLEAN  Mem_PoolBlkIsValidAddr (MEM_POOL  *p_pool,
+                                             void      *p_mem)
+{
+    CPU_ADDR  pool_offset;
+
+
+    if ((p_mem < p_pool->PoolAddrStart) ||
+        (p_mem > p_pool->PoolAddrEnd)) {
+        return (DEF_FALSE);
+    }
+
+    pool_offset = (CPU_ADDR)p_mem - (CPU_ADDR)p_pool->PoolAddrStart;
+    if (pool_offset % p_pool->BlkSize != 0u) {
+        return (DEF_FALSE);
+    } else {
+        return (DEF_TRUE);
+    }
+}
+#endif

+ 1412 - 0
MiddleWare/uCOS_II/uC-LIB/lib_mem.h

@@ -0,0 +1,1412 @@
+/*
+*********************************************************************************************************
+*                                                uC/LIB
+*                                        CUSTOM LIBRARY MODULES
+*
+*                         (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL
+*
+*                  All rights reserved.  Protected by international copyright laws.
+*
+*                  uC/LIB is provided in source form to registered licensees ONLY.  It is
+*                  illegal to distribute this source code to any third party unless you receive
+*                  written permission by an authorized Micrium representative.  Knowledge of
+*                  the source code may NOT be used to develop a similar product.
+*
+*                  Please help us continue to provide the Embedded community with the finest
+*                  software available.  Your honesty is greatly appreciated.
+*
+*                  You can find our product's user manual, API reference, release notes and
+*                  more information at: https://doc.micrium.com
+*
+*                  You can contact us at: http://www.micrium.com
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                     STANDARD MEMORY OPERATIONS
+*
+* Filename      : lib_mem.h
+* Version       : V1.38.01
+* Programmer(s) : ITJ
+*                 FBJ
+*                 EJ
+*                 JFD
+*********************************************************************************************************
+* Note(s)       : (1) NO compiler-supplied standard library functions are used in library or product software.
+*
+*                     (a) ALL standard library functions are implemented in the custom library modules :
+*
+*                         (1) \<Custom Library Directory>\lib_*.*
+*
+*                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+*
+*                               where
+*                                       <Custom Library Directory>      directory path for custom library software
+*                                       <cpu>                           directory name for specific processor (CPU)
+*                                       <compiler>                      directory name for specific compiler
+*
+*                     (b) Product-specific library functions are implemented in individual products.
+*
+*                 (2) Assumes the following versions (or more recent) of software modules are included in
+*                     the project build :
+*
+*                     (a) uC/CPU V1.27
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*
+* Note(s) : (1) This memory library header file is protected from multiple pre-processor inclusion through
+*               use of the memory library module present pre-processor macro definition.
+*********************************************************************************************************
+*/
+
+#ifndef  LIB_MEM_MODULE_PRESENT                                 /* See Note #1.                                         */
+#define  LIB_MEM_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*
+* Note(s) : (1) The custom library software files are located in the following directories :
+*
+*               (a) \<Your Product Application>\lib_cfg.h
+*
+*               (b) \<Custom Library Directory>\lib_*.*
+*
+*                       where
+*                               <Your Product Application>      directory path for Your Product's Application
+*                               <Custom Library Directory>      directory path for custom library software
+*
+*           (2) CPU-configuration  software files are located in the following directories :
+*
+*               (a) \<CPU-Compiler Directory>\cpu_*.*
+*               (b) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.*
+*
+*                       where
+*                               <CPU-Compiler Directory>        directory path for common CPU-compiler software
+*                               <cpu>                           directory name for specific processor (CPU)
+*                               <compiler>                      directory name for specific compiler
+*
+*           (3) Compiler MUST be configured to include as additional include path directories :
+*
+*               (a) '\<Your Product Application>\' directory                            See Note #1a
+*
+*               (b) '\<Custom Library Directory>\' directory                            See Note #1b
+*
+*               (c) (1) '\<CPU-Compiler Directory>\'                  directory         See Note #2a
+*                   (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory         See Note #2b
+*
+*           (4) NO compiler-supplied standard library functions SHOULD be used.
+*********************************************************************************************************
+*/
+
+#include  <cpu.h>
+#include  <cpu_core.h>
+
+#include  <lib_def.h>
+#include  <lib_cfg.h>
+
+
+/*
+*********************************************************************************************************
+*                                               EXTERNS
+*********************************************************************************************************
+*/
+
+#ifdef   LIB_MEM_MODULE
+#define  LIB_MEM_EXT
+#else
+#define  LIB_MEM_EXT  extern
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                               DEFINES
+*********************************************************************************************************
+*/
+
+#define  LIB_MEM_PADDING_ALIGN_NONE                       1u
+
+#define  LIB_MEM_BLK_QTY_UNLIMITED                        0u
+
+
+/*
+*********************************************************************************************************
+*                                        DEFAULT CONFIGURATION
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                             MEMORY LIBRARY ARGUMENT CHECK CONFIGURATION
+*
+* Note(s) : (1) Configure LIB_MEM_CFG_ARG_CHK_EXT_EN to enable/disable the memory library suite external
+*               argument check feature :
+*
+*               (a) When ENABLED,      arguments received from any port interface provided by the developer
+*                   or application are checked/validated.
+*
+*               (b) When DISABLED, NO  arguments received from any port interface provided by the developer
+*                   or application are checked/validated.
+*********************************************************************************************************
+*/
+
+                                                                /* Cfg external argument check feature (see Note #1) :  */
+#ifndef  LIB_MEM_CFG_ARG_CHK_EXT_EN
+#define  LIB_MEM_CFG_ARG_CHK_EXT_EN     DEF_DISABLED
+                                                                /* DEF_DISABLED     Argument check DISABLED             */
+                                                                /* DEF_ENABLED      Argument check ENABLED              */
+#endif
+
+
+/*
+*********************************************************************************************************
+*                         MEMORY LIBRARY ASSEMBLY OPTIMIZATION CONFIGURATION
+*
+* Note(s) : (1) Configure LIB_MEM_CFG_OPTIMIZE_ASM_EN to enable/disable assembly-optimized memory
+*               functions.
+*********************************************************************************************************
+*/
+
+                                                                /* Cfg assembly-optimized function(s) [see Note #1] :   */
+#ifndef  LIB_MEM_CFG_OPTIMIZE_ASM_EN
+#define  LIB_MEM_CFG_OPTIMIZE_ASM_EN    DEF_DISABLED
+                                                                /* DEF_DISABLED     Assembly-optimized fnct(s) DISABLED */
+                                                                /* DEF_ENABLED      Assembly-optimized fnct(s) ENABLED  */
+#endif
+
+
+/*
+*********************************************************************************************************
+*                          MEMORY ALLOCATION DEBUG INFORMATION CONFIGURATION
+*
+* Note(s) : (1) Configure LIB_MEM_CFG_DBG_INFO_EN to enable/disable debug information associated to each
+*               segment allocation.
+*********************************************************************************************************
+*/
+
+#ifndef  LIB_MEM_CFG_DBG_INFO_EN
+#define  LIB_MEM_CFG_DBG_INFO_EN         DEF_DISABLED
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                  HEAP PADDING ALIGN CONFIGURATION
+*
+* Note(s) : (1) Configure LIB_MEM_CFG_HEAP_PADDING_ALIGN to set the padding alignment of any buffer
+*               allocated from the heap.
+*********************************************************************************************************
+*/
+
+#ifndef  LIB_MEM_CFG_HEAP_PADDING_ALIGN
+#define  LIB_MEM_CFG_HEAP_PADDING_ALIGN  LIB_MEM_PADDING_ALIGN_NONE
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             DATA TYPES
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                            LIB MEM TYPE
+*
+* Note(s) : (1) 'LIB_MEM_TYPE' declared as 'CPU_INT32U' & all 'LIB_MEM_TYPE's #define'd with large, non-trivial
+*               values to trap & discard invalid/corrupted library memory objects based on 'LIB_MEM_TYPE'.
+*********************************************************************************************************
+*/
+
+typedef  CPU_INT32U  LIB_MEM_TYPE;
+
+
+/*
+*********************************************************************************************************
+*                                MEMORY POOL BLOCK QUANTITY DATA TYPE
+*********************************************************************************************************
+*/
+
+typedef  CPU_SIZE_T  MEM_POOL_BLK_QTY;
+
+
+/*
+*********************************************************************************************************
+*                                      MEMORY POOL TABLE IX TYPE
+*********************************************************************************************************
+*/
+
+typedef  MEM_POOL_BLK_QTY  MEM_POOL_IX;
+
+
+/*
+*********************************************************************************************************
+*                              MEMORY ALLOCATION TRACKING INFO DATA TYPE
+*********************************************************************************************************
+*/
+
+#if (LIB_MEM_CFG_DBG_INFO_EN  == DEF_ENABLED)
+typedef  struct  mem_alloc_info  MEM_ALLOC_INFO;
+
+struct  mem_alloc_info  {                                       /* ------------------ MEM ALLOC INFO ------------------ */
+    const  CPU_CHAR        *NamePtr;                            /* Ptr to name.                                         */
+           CPU_SIZE_T       Size;                               /* Total alloc'd size, in bytes.                        */
+           MEM_ALLOC_INFO  *NextPtr;                            /* Ptr to next alloc info in list.                      */
+};
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                     MEMORY SEGMENTS DATA TYPES
+*********************************************************************************************************
+*/
+
+typedef  struct  mem_seg  MEM_SEG;                              /* --------------------- SEG DATA --------------------- */
+
+struct mem_seg {
+           CPU_ADDR         AddrBase;                           /* Seg start addr.                                      */
+           CPU_ADDR         AddrEnd;                            /* Seg end addr (last addr).                            */
+           CPU_ADDR         AddrNext;                           /* Next free addr.                                      */
+
+           MEM_SEG         *NextPtr;                            /* Ptr to next seg.                                     */
+
+           CPU_SIZE_T       PaddingAlign;                       /* Padding alignment in byte.                           */
+
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
+    const  CPU_CHAR        *NamePtr;                            /* Ptr to seg name.                                     */
+           MEM_ALLOC_INFO  *AllocInfoHeadPtr;                   /* Ptr to head of alloc info struct list.               */
+#endif
+};
+
+typedef  struct  mem_seg_info {                                 /* --------------------- SEG INFO --------------------- */
+    CPU_SIZE_T  UsedSize;                                       /* Allocated seg octets.                                */
+    CPU_SIZE_T  TotalSize;                                      /* Total seg capacity, in octets.                       */
+
+    CPU_ADDR    AddrBase;
+    CPU_ADDR    AddrNextAlloc;
+} MEM_SEG_INFO;
+
+
+/*
+*********************************************************************************************************
+*                                    (STATIC) MEMORY POOL DATA TYPES
+*
+* Note(s) : (1) Free static memory pool blocks are indexed in the 'BlkFreeTbl' table. Newly freed blocks
+*               are added at the first available position in the table and blocks are retrieved from the
+*               last occupied position, in a LIFO fashion.
+*
+*                                 /-------------------------------\
+*                                 |/------------\                 |
+*                    BlkFreeTbl   ||  Start     v                 v              End
+*                    /--------\   ||  /--------------------------------------------\
+*                    |p_free_1|---/|  |        |        |        |        |        |
+*                    |--------|    |  \--------------------------------------------/
+*                    |p_free_2|----/   ^                                  |        |
+*                    |--------|        |                                  |__Blk___|
+*                    |p_free_3|--------/ (Next block to be retrieved.)       Size
+*                    |--------|
+*                    |        |<-------- (Next block to be freed.)
+*                    \--------/
+*
+*********************************************************************************************************
+*/
+
+                                                                /* --------------------- MEM POOL --------------------- */
+typedef  struct  mem_pool {
+    void               *PoolAddrStart;                          /* Ptr   to start of mem seg for mem pool blks.         */
+    void               *PoolAddrEnd;                            /* Ptr   to end   of mem seg for mem pool blks.         */
+    MEM_POOL_BLK_QTY    BlkNbr;                                 /* Nbr   of mem pool   blks.                            */
+    CPU_SIZE_T          BlkSize;                                /* Size  of mem pool   blks (in octets).                */
+    void              **BlkFreeTbl;                             /* Tbl of free mem pool blks.                           */
+    CPU_SIZE_T          BlkFreeTblIx;                           /* Ix of next free blk free tbl entry.                  */
+} MEM_POOL;
+
+
+/*
+*********************************************************************************************************
+*                                     DYNAMIC MEMORY POOL DATA TYPE
+*
+* Note(s) : (1) Dynamic memory pool blocks are not indexed in a table. Only freed blocks are linked using
+*               a singly linked list, in a LIFO fashion; newly freed blocks are inserted at the head of the
+*               list and blocks are also retrieved from the head of the list.
+*
+*           (2) Pointers to the next block are only present when a block is free, using the first location
+*               in the allocated memory block. The user of dynamic memory pool must not assume his data
+*               will not be overwritten when a block is freed.
+*
+*                                   /----------------\
+*                    /----------\   |  /----------\  |    /----------\   /----------\
+*       BlkFreePtr-->|(NextPtr) |---/  |          |  \--->|(NextPtr) |-->|(NextPtr) |--> DEF_NULL
+*                    |----------|      |  Blk in  |       |----------|   |----------|
+*                    |          |      |   use    |       |          |   |          |
+*                    |          |      |          |       |          |   |          |
+*                    \----------/      \----------/       \----------/   \----------/
+*
+*********************************************************************************************************
+*/
+
+typedef  struct  mem_dyn_pool {                                 /* ---------------- DYN MEM POOL DATA ----------------- */
+           MEM_SEG     *PoolSegPtr;                             /* Mem pool from which blks are alloc'd.                */
+           CPU_SIZE_T   BlkSize;                                /* Size of pool blks, in octets.                        */
+           CPU_SIZE_T   BlkAlign;                               /* Align req'd for blks, in octets.                     */
+           CPU_SIZE_T   BlkPaddingAlign;                        /* Padding alignment in bytes for this mem seg.         */
+           void        *BlkFreePtr;                             /* Ptr to first free blk.                               */
+
+           CPU_SIZE_T   BlkQtyMax;                              /* Max qty of blk in dyn mem pool. 0 = unlimited.       */
+           CPU_SIZE_T   BlkAllocCnt;                            /* Cnt of alloc blk.                                    */
+
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
+    const  CPU_CHAR    *NamePtr;                                /* Ptr to mem pool name.                                */
+#endif
+} MEM_DYN_POOL;
+
+
+/*
+*********************************************************************************************************
+*                                          GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                              MACRO'S
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                      MEMORY DATA VALUE MACRO'S
+*
+* Note(s) : (1) (a) Some variables & variable buffers to pass & receive data values MUST start on appropriate
+*                   CPU word-aligned addresses.  This is required because most word-aligned processors are more
+*                   efficient & may even REQUIRE that multi-octet words start on CPU word-aligned addresses.
+*
+*                   (1) For 16-bit word-aligned processors, this means that
+*
+*                           all 16- & 32-bit words MUST start on addresses that are multiples of 2 octets
+*
+*                   (2) For 32-bit word-aligned processors, this means that
+*
+*                           all 16-bit       words MUST start on addresses that are multiples of 2 octets
+*                           all 32-bit       words MUST start on addresses that are multiples of 4 octets
+*
+*               (b) However, some data values macro's appropriately access data values from any CPU addresses,
+*                   word-aligned or not.  Thus for processors that require data word alignment, data words can
+*                   be accessed to/from any CPU address, word-aligned or not, without generating data-word-
+*                   alignment exceptions/faults.
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                      ENDIAN WORD ORDER MACRO'S
+*
+* Description : Convert data values to & from big-, little, or host-endian CPU word order.
+*
+* Argument(s) : val       Data value to convert (see Notes #1 & #2).
+*
+* Return(s)   : Converted data value (see Notes #1 & #2).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Convert data values to the desired data-word order :
+*
+*                       MEM_VAL_BIG_TO_LITTLE_xx()      Convert big-        endian data values
+*                                                            to little-     endian data values
+*                       MEM_VAL_LITTLE_TO_BIG_xx()      Convert little-     endian data values
+*                                                            to big-        endian data values
+*                       MEM_VAL_xxx_TO_HOST_xx()        Convert big-/little-endian data values
+*                                                            to host-       endian data values
+*                       MEM_VAL_HOST_TO_xxx_xx()        Convert host-       endian data values
+*                                                            to big-/little-endian data values
+*
+*                   See also 'cpu.h  CPU WORD CONFIGURATION  Note #2'.
+*
+*               (2) 'val' data value to convert & any variable to receive the returned conversion MUST
+*                   start on appropriate CPU word-aligned addresses.
+*
+*                   See also 'MEMORY DATA VALUE MACRO'S  Note #1a'.
+*
+*               (3) MEM_VAL_COPY_xxx() macro's are more efficient than generic endian word order macro's &
+*                   are also independent of CPU data-word-alignment & SHOULD be used whenever possible.
+*
+*                   See also 'MEM_VAL_COPY_GET_xxx()  Note #4'
+*                          & 'MEM_VAL_COPY_SET_xxx()  Note #4'.
+*
+*               (4) Generic endian word order macro's are NOT atomic operations & MUST NOT be used on any
+*                   non-static (i.e. volatile) variables, registers, hardware, etc.; without the caller of
+*                   the macro's providing some form of additional protection (e.g. mutual exclusion).
+*
+*               (5) The 'CPU_CFG_ENDIAN_TYPE' pre-processor 'else'-conditional code SHOULD never be compiled/
+*                   linked since each 'cpu.h' SHOULD ensure that the CPU data-word-memory order configuration
+*                   constant (CPU_CFG_ENDIAN_TYPE) is configured with an appropriate data-word-memory order
+*                   value (see 'cpu.h  CPU WORD CONFIGURATION  Note #2').  The 'else'-conditional code is
+*                   included as an extra precaution in case 'cpu.h' is incorrectly configured.
+*********************************************************************************************************
+*/
+
+#if    ((CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_64) || \
+        (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_32))
+
+#define  MEM_VAL_BIG_TO_LITTLE_16(val)        ((CPU_INT16U)(((CPU_INT16U)((((CPU_INT16U)(val)) & (CPU_INT16U)    0xFF00u) >> (1u * DEF_OCTET_NBR_BITS))) | \
+                                                            ((CPU_INT16U)((((CPU_INT16U)(val)) & (CPU_INT16U)    0x00FFu) << (1u * DEF_OCTET_NBR_BITS)))))
+
+#define  MEM_VAL_BIG_TO_LITTLE_32(val)        ((CPU_INT32U)(((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0xFF000000u) >> (3u * DEF_OCTET_NBR_BITS))) | \
+                                                            ((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x00FF0000u) >> (1u * DEF_OCTET_NBR_BITS))) | \
+                                                            ((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x0000FF00u) << (1u * DEF_OCTET_NBR_BITS))) | \
+                                                            ((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x000000FFu) << (3u * DEF_OCTET_NBR_BITS)))))
+
+#elif   (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_16)
+
+#define  MEM_VAL_BIG_TO_LITTLE_16(val)        ((CPU_INT16U)(((CPU_INT16U)((((CPU_INT16U)(val)) & (CPU_INT16U)    0xFF00u) >> (1u * DEF_OCTET_NBR_BITS))) | \
+                                                            ((CPU_INT16U)((((CPU_INT16U)(val)) & (CPU_INT16U)    0x00FFu) << (1u * DEF_OCTET_NBR_BITS)))))
+
+#define  MEM_VAL_BIG_TO_LITTLE_32(val)        ((CPU_INT32U)(((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0xFF000000u) >> (1u * DEF_OCTET_NBR_BITS))) | \
+                                                            ((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x00FF0000u) << (1u * DEF_OCTET_NBR_BITS))) | \
+                                                            ((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x0000FF00u) >> (1u * DEF_OCTET_NBR_BITS))) | \
+                                                            ((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x000000FFu) << (1u * DEF_OCTET_NBR_BITS)))))
+
+#else
+
+#define  MEM_VAL_BIG_TO_LITTLE_16(val)                                                  (val)
+#define  MEM_VAL_BIG_TO_LITTLE_32(val)                                                  (val)
+
+#endif
+
+
+#define  MEM_VAL_LITTLE_TO_BIG_16(val)                          MEM_VAL_BIG_TO_LITTLE_16(val)
+#define  MEM_VAL_LITTLE_TO_BIG_32(val)                          MEM_VAL_BIG_TO_LITTLE_32(val)
+
+
+
+#if     (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
+
+#define  MEM_VAL_BIG_TO_HOST_16(val)                                                    (val)
+#define  MEM_VAL_BIG_TO_HOST_32(val)                                                    (val)
+#define  MEM_VAL_LITTLE_TO_HOST_16(val)                         MEM_VAL_LITTLE_TO_BIG_16(val)
+#define  MEM_VAL_LITTLE_TO_HOST_32(val)                         MEM_VAL_LITTLE_TO_BIG_32(val)
+
+#elif   (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_LITTLE)
+
+#define  MEM_VAL_BIG_TO_HOST_16(val)                            MEM_VAL_BIG_TO_LITTLE_16(val)
+#define  MEM_VAL_BIG_TO_HOST_32(val)                            MEM_VAL_BIG_TO_LITTLE_32(val)
+#define  MEM_VAL_LITTLE_TO_HOST_16(val)                                                 (val)
+#define  MEM_VAL_LITTLE_TO_HOST_32(val)                                                 (val)
+
+#else                                                           /* See Note #5.                                         */
+
+#error  "CPU_CFG_ENDIAN_TYPE  illegally #defined in 'cpu.h'      "
+#error  "                     [See 'cpu.h  CONFIGURATION ERRORS']"
+
+#endif
+
+
+#define  MEM_VAL_HOST_TO_BIG_16(val)                            MEM_VAL_BIG_TO_HOST_16(val)
+#define  MEM_VAL_HOST_TO_BIG_32(val)                            MEM_VAL_BIG_TO_HOST_32(val)
+#define  MEM_VAL_HOST_TO_LITTLE_16(val)                         MEM_VAL_LITTLE_TO_HOST_16(val)
+#define  MEM_VAL_HOST_TO_LITTLE_32(val)                         MEM_VAL_LITTLE_TO_HOST_32(val)
+
+
+/*
+*********************************************************************************************************
+*                                          MEM_VAL_GET_xxx()
+*
+* Description : Decode data values from any CPU memory address.
+*
+* Argument(s) : addr        Lowest CPU memory address of data value to decode (see Notes #2 & #3a).
+*
+* Return(s)   : Decoded data value from CPU memory address (see Notes #1 & #3b).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Decode data values based on the values' data-word order in CPU memory :
+*
+*                       MEM_VAL_GET_xxx_BIG()           Decode big-   endian data values -- data words' most
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_GET_xxx_LITTLE()        Decode little-endian data values -- data words' least
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_GET_xxx()               Decode data values using CPU's native or configured
+*                                                           data-word order
+*
+*                   See also 'cpu.h  CPU WORD CONFIGURATION  Note #2'.
+*
+*               (2) CPU memory addresses/pointers NOT checked for NULL.
+*
+*               (3) (a) MEM_VAL_GET_xxx() macro's decode data values without regard to CPU word-aligned addresses.
+*                       Thus for processors that require data word alignment, data words can be decoded from any
+*                       CPU address, word-aligned or not, without generating data-word-alignment exceptions/faults.
+*
+*                   (b) However, any variable to receive the returned data value MUST start on an appropriate CPU
+*                       word-aligned address.
+*
+*                   See also 'MEMORY DATA VALUE MACRO'S  Note #1'.
+*
+*               (4) MEM_VAL_COPY_GET_xxx() macro's are more efficient than MEM_VAL_GET_xxx() macro's & are
+*                   also independent of CPU data-word-alignment & SHOULD be used whenever possible.
+*
+*                   See also 'MEM_VAL_COPY_GET_xxx()  Note #4'.
+*
+*               (5) MEM_VAL_GET_xxx() macro's are NOT atomic operations & MUST NOT be used on any non-static
+*                   (i.e. volatile) variables, registers, hardware, etc.; without the caller of the macro's
+*                   providing some form of additional protection (e.g. mutual exclusion).
+*
+*               (6) The 'CPU_CFG_ENDIAN_TYPE' pre-processor 'else'-conditional code SHOULD never be compiled/
+*                   linked since each 'cpu.h' SHOULD ensure that the CPU data-word-memory order configuration
+*                   constant (CPU_CFG_ENDIAN_TYPE) is configured with an appropriate data-word-memory order
+*                   value (see 'cpu.h  CPU WORD CONFIGURATION  Note #2').  The 'else'-conditional code is
+*                   included as an extra precaution in case 'cpu.h' is incorrectly configured.
+*********************************************************************************************************
+*/
+
+#define  MEM_VAL_GET_INT08U_BIG(addr)           ((CPU_INT08U) ((CPU_INT08U)(((CPU_INT08U)(*(((CPU_INT08U *)(addr)) + 0))) << (0u * DEF_OCTET_NBR_BITS))))
+
+#define  MEM_VAL_GET_INT16U_BIG(addr)           ((CPU_INT16U)(((CPU_INT16U)(((CPU_INT16U)(*(((CPU_INT08U *)(addr)) + 0))) << (1u * DEF_OCTET_NBR_BITS))) + \
+                                                              ((CPU_INT16U)(((CPU_INT16U)(*(((CPU_INT08U *)(addr)) + 1))) << (0u * DEF_OCTET_NBR_BITS)))))
+
+#define  MEM_VAL_GET_INT32U_BIG(addr)           ((CPU_INT32U)(((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 0))) << (3u * DEF_OCTET_NBR_BITS))) + \
+                                                              ((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 1))) << (2u * DEF_OCTET_NBR_BITS))) + \
+                                                              ((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 2))) << (1u * DEF_OCTET_NBR_BITS))) + \
+                                                              ((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 3))) << (0u * DEF_OCTET_NBR_BITS)))))
+
+
+
+#define  MEM_VAL_GET_INT08U_LITTLE(addr)        ((CPU_INT08U) ((CPU_INT08U)(((CPU_INT08U)(*(((CPU_INT08U *)(addr)) + 0))) << (0u * DEF_OCTET_NBR_BITS))))
+
+#define  MEM_VAL_GET_INT16U_LITTLE(addr)        ((CPU_INT16U)(((CPU_INT16U)(((CPU_INT16U)(*(((CPU_INT08U *)(addr)) + 0))) << (0u * DEF_OCTET_NBR_BITS))) + \
+                                                              ((CPU_INT16U)(((CPU_INT16U)(*(((CPU_INT08U *)(addr)) + 1))) << (1u * DEF_OCTET_NBR_BITS)))))
+
+#define  MEM_VAL_GET_INT32U_LITTLE(addr)        ((CPU_INT32U)(((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 0))) << (0u * DEF_OCTET_NBR_BITS))) + \
+                                                              ((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 1))) << (1u * DEF_OCTET_NBR_BITS))) + \
+                                                              ((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 2))) << (2u * DEF_OCTET_NBR_BITS))) + \
+                                                              ((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 3))) << (3u * DEF_OCTET_NBR_BITS)))))
+
+
+
+#if     (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
+
+#define  MEM_VAL_GET_INT08U(addr)                               MEM_VAL_GET_INT08U_BIG(addr)
+#define  MEM_VAL_GET_INT16U(addr)                               MEM_VAL_GET_INT16U_BIG(addr)
+#define  MEM_VAL_GET_INT32U(addr)                               MEM_VAL_GET_INT32U_BIG(addr)
+
+#elif   (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_LITTLE)
+
+#define  MEM_VAL_GET_INT08U(addr)                               MEM_VAL_GET_INT08U_LITTLE(addr)
+#define  MEM_VAL_GET_INT16U(addr)                               MEM_VAL_GET_INT16U_LITTLE(addr)
+#define  MEM_VAL_GET_INT32U(addr)                               MEM_VAL_GET_INT32U_LITTLE(addr)
+
+#else                                                           /* See Note #6.                                         */
+
+#error  "CPU_CFG_ENDIAN_TYPE  illegally #defined in 'cpu.h'      "
+#error  "                     [See 'cpu.h  CONFIGURATION ERRORS']"
+
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          MEM_VAL_SET_xxx()
+*
+* Description : Encode data values to any CPU memory address.
+*
+* Argument(s) : addr        Lowest CPU memory address to encode data value (see Notes #2 & #3a).
+*
+*               val         Data value to encode (see Notes #1 & #3b).
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Encode data values into CPU memory based on the values' data-word order :
+*
+*                       MEM_VAL_SET_xxx_BIG()           Encode big-   endian data values -- data words' most
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_SET_xxx_LITTLE()        Encode little-endian data values -- data words' least
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_SET_xxx()               Encode data values using CPU's native or configured
+*                                                           data-word order
+*
+*                   See also 'cpu.h  CPU WORD CONFIGURATION  Note #2'.
+*
+*               (2) CPU memory addresses/pointers NOT checked for NULL.
+*
+*               (3) (a) MEM_VAL_SET_xxx() macro's encode data values without regard to CPU word-aligned addresses.
+*                       Thus for processors that require data word alignment, data words can be encoded to any
+*                       CPU address, word-aligned or not, without generating data-word-alignment exceptions/faults.
+*
+*                   (b) However, 'val' data value to encode MUST start on an appropriate CPU word-aligned address.
+*
+*                   See also 'MEMORY DATA VALUE MACRO'S  Note #1'.
+*
+*               (4) MEM_VAL_COPY_SET_xxx() macro's are more efficient than MEM_VAL_SET_xxx() macro's & are
+*                   also independent of CPU data-word-alignment & SHOULD be used whenever possible.
+*
+*                   See also 'MEM_VAL_COPY_SET_xxx()  Note #4'.
+*
+*               (5) MEM_VAL_SET_xxx() macro's are NOT atomic operations & MUST NOT be used on any non-static
+*                   (i.e. volatile) variables, registers, hardware, etc.; without the caller of the macro's
+*                   providing some form of additional protection (e.g. mutual exclusion).
+*
+*               (6) The 'CPU_CFG_ENDIAN_TYPE' pre-processor 'else'-conditional code SHOULD never be compiled/
+*                   linked since each 'cpu.h' SHOULD ensure that the CPU data-word-memory order configuration
+*                   constant (CPU_CFG_ENDIAN_TYPE) is configured with an appropriate data-word-memory order
+*                   value (see 'cpu.h  CPU WORD CONFIGURATION  Note #2').  The 'else'-conditional code is
+*                   included as an extra precaution in case 'cpu.h' is incorrectly configured.
+*********************************************************************************************************
+*/
+
+#define  MEM_VAL_SET_INT08U_BIG(addr, val)                     do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT08U)(val)) & (CPU_INT08U)      0xFFu) >> (0u * DEF_OCTET_NBR_BITS))); } while (0)
+
+#define  MEM_VAL_SET_INT16U_BIG(addr, val)                     do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT16U)(val)) & (CPU_INT16U)    0xFF00u) >> (1u * DEF_OCTET_NBR_BITS))); \
+                                                                    (*(((CPU_INT08U *)(addr)) + 1)) = ((CPU_INT08U)((((CPU_INT16U)(val)) & (CPU_INT16U)    0x00FFu) >> (0u * DEF_OCTET_NBR_BITS))); } while (0)
+
+#define  MEM_VAL_SET_INT32U_BIG(addr, val)                     do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0xFF000000u) >> (3u * DEF_OCTET_NBR_BITS))); \
+                                                                    (*(((CPU_INT08U *)(addr)) + 1)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x00FF0000u) >> (2u * DEF_OCTET_NBR_BITS))); \
+                                                                    (*(((CPU_INT08U *)(addr)) + 2)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x0000FF00u) >> (1u * DEF_OCTET_NBR_BITS))); \
+                                                                    (*(((CPU_INT08U *)(addr)) + 3)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x000000FFu) >> (0u * DEF_OCTET_NBR_BITS))); } while (0)
+
+
+
+#define  MEM_VAL_SET_INT08U_LITTLE(addr, val)                  do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT08U)(val)) & (CPU_INT08U)      0xFFu) >> (0u * DEF_OCTET_NBR_BITS))); } while (0)
+
+#define  MEM_VAL_SET_INT16U_LITTLE(addr, val)                  do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT16U)(val)) & (CPU_INT16U)    0x00FFu) >> (0u * DEF_OCTET_NBR_BITS))); \
+                                                                    (*(((CPU_INT08U *)(addr)) + 1)) = ((CPU_INT08U)((((CPU_INT16U)(val)) & (CPU_INT16U)    0xFF00u) >> (1u * DEF_OCTET_NBR_BITS))); } while (0)
+
+#define  MEM_VAL_SET_INT32U_LITTLE(addr, val)                  do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x000000FFu) >> (0u * DEF_OCTET_NBR_BITS))); \
+                                                                    (*(((CPU_INT08U *)(addr)) + 1)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x0000FF00u) >> (1u * DEF_OCTET_NBR_BITS))); \
+                                                                    (*(((CPU_INT08U *)(addr)) + 2)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x00FF0000u) >> (2u * DEF_OCTET_NBR_BITS))); \
+                                                                    (*(((CPU_INT08U *)(addr)) + 3)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0xFF000000u) >> (3u * DEF_OCTET_NBR_BITS))); } while (0)
+
+
+
+#if     (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
+
+#define  MEM_VAL_SET_INT08U(addr, val)                          MEM_VAL_SET_INT08U_BIG(addr, val)
+#define  MEM_VAL_SET_INT16U(addr, val)                          MEM_VAL_SET_INT16U_BIG(addr, val)
+#define  MEM_VAL_SET_INT32U(addr, val)                          MEM_VAL_SET_INT32U_BIG(addr, val)
+
+#elif   (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_LITTLE)
+
+#define  MEM_VAL_SET_INT08U(addr, val)                          MEM_VAL_SET_INT08U_LITTLE(addr, val)
+#define  MEM_VAL_SET_INT16U(addr, val)                          MEM_VAL_SET_INT16U_LITTLE(addr, val)
+#define  MEM_VAL_SET_INT32U(addr, val)                          MEM_VAL_SET_INT32U_LITTLE(addr, val)
+
+#else                                                           /* See Note #6.                                         */
+
+#error  "CPU_CFG_ENDIAN_TYPE  illegally #defined in 'cpu.h'      "
+#error  "                     [See 'cpu.h  CONFIGURATION ERRORS']"
+
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                       MEM_VAL_COPY_GET_xxx()
+*
+* Description : Copy & decode data values from any CPU memory address to any CPU memory address.
+*
+* Argument(s) : addr_dest       Lowest CPU memory address to copy/decode source address's data value
+*                                   (see Notes #2 & #3).
+*
+*               addr_src        Lowest CPU memory address of data value to copy/decode
+*                                   (see Notes #2 & #3).
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Copy/decode data values based on the values' data-word order :
+*
+*                       MEM_VAL_COPY_GET_xxx_BIG()      Decode big-   endian data values -- data words' most
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_COPY_GET_xxx_LITTLE()   Decode little-endian data values -- data words' least
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_COPY_GET_xxx()          Decode data values using CPU's native or configured
+*                                                           data-word order
+*
+*                   See also 'cpu.h  CPU WORD CONFIGURATION  Note #2'.
+*
+*               (2) (a) CPU memory addresses/pointers NOT checked for NULL.
+*
+*                   (b) CPU memory addresses/buffers  NOT checked for overlapping.
+*
+*                       (1) IEEE Std 1003.1, 2004 Edition, Section 'memcpy() : DESCRIPTION' states that
+*                           "copying ... between objects that overlap ... is undefined".
+*
+*               (3) MEM_VAL_COPY_GET_xxx() macro's copy/decode data values without regard to CPU word-aligned
+*                   addresses.  Thus for processors that require data word alignment, data words can be copied/
+*                   decoded to/from any CPU address, word-aligned or not, without generating data-word-alignment
+*                   exceptions/faults.
+*
+*               (4) MEM_VAL_COPY_GET_xxx() macro's are more efficient than MEM_VAL_GET_xxx() macro's & are
+*                   also independent of CPU data-word-alignment & SHOULD be used whenever possible.
+*
+*                   See also 'MEM_VAL_GET_xxx()  Note #4'.
+*
+*               (5) Since octet-order copy/conversion are inverse operations, MEM_VAL_COPY_GET_xxx() &
+*                   MEM_VAL_COPY_SET_xxx() macros are inverse, but identical, operations & are provided
+*                   in both forms for semantics & consistency.
+*
+*                   See also 'MEM_VAL_COPY_SET_xxx()  Note #5'.
+*
+*               (6) MEM_VAL_COPY_GET_xxx() macro's are NOT atomic operations & MUST NOT be used on any non-
+*                   static (i.e. volatile) variables, registers, hardware, etc.; without the caller of the
+*                   macro's providing some form of additional protection (e.g. mutual exclusion).
+*
+*               (7) The 'CPU_CFG_ENDIAN_TYPE' pre-processor 'else'-conditional code SHOULD never be compiled/
+*                   linked since each 'cpu.h' SHOULD ensure that the CPU data-word-memory order configuration
+*                   constant (CPU_CFG_ENDIAN_TYPE) is configured with an appropriate data-word-memory order
+*                   value (see 'cpu.h  CPU WORD CONFIGURATION  Note #2').  The 'else'-conditional code is
+*                   included as an extra precaution in case 'cpu.h' is incorrectly configured.
+*********************************************************************************************************
+*/
+
+#if     (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
+
+
+#define  MEM_VAL_COPY_GET_INT08U_BIG(addr_dest, addr_src)      do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 0)); } while (0)
+
+#define  MEM_VAL_COPY_GET_INT16U_BIG(addr_dest, addr_src)      do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 0)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 1)) = (*(((CPU_INT08U *)(addr_src)) + 1)); } while (0)
+
+#define  MEM_VAL_COPY_GET_INT32U_BIG(addr_dest, addr_src)      do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 0)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 1)) = (*(((CPU_INT08U *)(addr_src)) + 1)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 2)) = (*(((CPU_INT08U *)(addr_src)) + 2)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 3)) = (*(((CPU_INT08U *)(addr_src)) + 3)); } while (0)
+
+
+
+#define  MEM_VAL_COPY_GET_INT08U_LITTLE(addr_dest, addr_src)   do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 0)); } while (0)
+
+#define  MEM_VAL_COPY_GET_INT16U_LITTLE(addr_dest, addr_src)   do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 1)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 1)) = (*(((CPU_INT08U *)(addr_src)) + 0)); } while (0)
+
+#define  MEM_VAL_COPY_GET_INT32U_LITTLE(addr_dest, addr_src)   do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 3)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 1)) = (*(((CPU_INT08U *)(addr_src)) + 2)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 2)) = (*(((CPU_INT08U *)(addr_src)) + 1)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 3)) = (*(((CPU_INT08U *)(addr_src)) + 0)); } while (0)
+
+
+
+#define  MEM_VAL_COPY_GET_INT08U(addr_dest, addr_src)               MEM_VAL_COPY_GET_INT08U_BIG(addr_dest, addr_src)
+#define  MEM_VAL_COPY_GET_INT16U(addr_dest, addr_src)               MEM_VAL_COPY_GET_INT16U_BIG(addr_dest, addr_src)
+#define  MEM_VAL_COPY_GET_INT32U(addr_dest, addr_src)               MEM_VAL_COPY_GET_INT32U_BIG(addr_dest, addr_src)
+
+
+
+
+#elif   (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_LITTLE)
+
+
+#define  MEM_VAL_COPY_GET_INT08U_BIG(addr_dest, addr_src)      do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 0)); } while (0)
+
+#define  MEM_VAL_COPY_GET_INT16U_BIG(addr_dest, addr_src)      do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 1)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 1)) = (*(((CPU_INT08U *)(addr_src)) + 0)); } while (0)
+
+#define  MEM_VAL_COPY_GET_INT32U_BIG(addr_dest, addr_src)      do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 3)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 1)) = (*(((CPU_INT08U *)(addr_src)) + 2)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 2)) = (*(((CPU_INT08U *)(addr_src)) + 1)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 3)) = (*(((CPU_INT08U *)(addr_src)) + 0)); } while (0)
+
+
+
+#define  MEM_VAL_COPY_GET_INT08U_LITTLE(addr_dest, addr_src)   do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 0)); } while (0)
+
+#define  MEM_VAL_COPY_GET_INT16U_LITTLE(addr_dest, addr_src)   do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 0)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 1)) = (*(((CPU_INT08U *)(addr_src)) + 1)); } while (0)
+
+#define  MEM_VAL_COPY_GET_INT32U_LITTLE(addr_dest, addr_src)   do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 0)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 1)) = (*(((CPU_INT08U *)(addr_src)) + 1)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 2)) = (*(((CPU_INT08U *)(addr_src)) + 2)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 3)) = (*(((CPU_INT08U *)(addr_src)) + 3)); } while (0)
+
+
+
+#define  MEM_VAL_COPY_GET_INT08U(addr_dest, addr_src)               MEM_VAL_COPY_GET_INT08U_LITTLE(addr_dest, addr_src)
+#define  MEM_VAL_COPY_GET_INT16U(addr_dest, addr_src)               MEM_VAL_COPY_GET_INT16U_LITTLE(addr_dest, addr_src)
+#define  MEM_VAL_COPY_GET_INT32U(addr_dest, addr_src)               MEM_VAL_COPY_GET_INT32U_LITTLE(addr_dest, addr_src)
+
+
+
+
+#else                                                           /* See Note #7.                                         */
+
+#error  "CPU_CFG_ENDIAN_TYPE  illegally #defined in 'cpu.h'      "
+#error  "                     [See 'cpu.h  CONFIGURATION ERRORS']"
+
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                     MEM_VAL_COPY_GET_INTU_xxx()
+*
+* Description : Copy & decode data values from any CPU memory address to any CPU memory address for
+*                   any sized data values.
+*
+* Argument(s) : addr_dest       Lowest CPU memory address to copy/decode source address's data value
+*                                   (see Notes #2 & #3).
+*
+*               addr_src        Lowest CPU memory address of data value to copy/decode
+*                                   (see Notes #2 & #3).
+*
+*               val_size        Number of data value octets to copy/decode.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Copy/decode data values based on the values' data-word order :
+*
+*                       MEM_VAL_COPY_GET_INTU_BIG()     Decode big-   endian data values -- data words' most
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_COPY_GET_INTU_LITTLE()  Decode little-endian data values -- data words' least
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_COPY_GET_INTU()         Decode data values using CPU's native or configured
+*                                                           data-word order
+*
+*                   See also 'cpu.h  CPU WORD CONFIGURATION  Note #2'.
+*
+*               (2) (a) CPU memory addresses/pointers NOT checked for NULL.
+*
+*                   (b) CPU memory addresses/buffers  NOT checked for overlapping.
+*
+*                       (1) IEEE Std 1003.1, 2004 Edition, Section 'memcpy() : DESCRIPTION' states that
+*                           "copying ... between objects that overlap ... is undefined".
+*
+*               (3) MEM_VAL_COPY_GET_INTU_xxx() macro's copy/decode data values without regard to CPU word-
+*                   aligned addresses.  Thus for processors that require data word alignment, data words
+*                   can be copied/decoded to/from any CPU address, word-aligned or not, without generating
+*                   data-word-alignment exceptions/faults.
+*
+*               (4) MEM_VAL_COPY_GET_xxx() macro's are more efficient than MEM_VAL_COPY_GET_INTU_xxx()
+*                   macro's & SHOULD be used whenever possible.
+*
+*                   See also 'MEM_VAL_COPY_GET_xxx()  Note #4'.
+*
+*               (5) Since octet-order copy/conversion are inverse operations, MEM_VAL_COPY_GET_INTU_xxx() &
+*                   MEM_VAL_COPY_SET_INTU_xxx() macros are inverse, but identical, operations & are provided
+*                   in both forms for semantics & consistency.
+*
+*                   See also 'MEM_VAL_COPY_SET_INTU_xxx()  Note #5'.
+*
+*               (6) MEM_VAL_COPY_GET_INTU_xxx() macro's are NOT atomic operations & MUST NOT be used on any
+*                   non-static (i.e. volatile) variables, registers, hardware, etc.; without the caller of
+*                   the macro's providing some form of additional protection (e.g. mutual exclusion).
+*
+*               (7) MISRA-C 2004 Rule 5.2 states that "identifiers in an inner scope shall not use the same
+*                   name as an indentifier in an outer scope, and therefore hide that identifier".
+*
+*                   Therefore, to avoid possible redeclaration of commonly-used loop counter identifier names,
+*                   'i' & 'j', MEM_VAL_COPY_GET_INTU_xxx() loop counter identifier names are prefixed with a
+*                   single underscore.
+*
+*               (8) The 'CPU_CFG_ENDIAN_TYPE' pre-processor 'else'-conditional code SHOULD never be compiled/
+*                   linked since each 'cpu.h' SHOULD ensure that the CPU data-word-memory order configuration
+*                   constant (CPU_CFG_ENDIAN_TYPE) is configured with an appropriate data-word-memory order
+*                   value (see 'cpu.h  CPU WORD CONFIGURATION  Note #2').  The 'else'-conditional code is
+*                   included as an extra precaution in case 'cpu.h' is incorrectly configured.
+*********************************************************************************************************
+*/
+
+#if     (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
+
+
+#define  MEM_VAL_COPY_GET_INTU_BIG(addr_dest, addr_src, val_size)       do {                                                                                  \
+                                                                            CPU_SIZE_T  _i;                                                                   \
+                                                                                                                                                              \
+                                                                            for (_i = 0; _i < (val_size); _i++) {                                             \
+                                                                                (*(((CPU_INT08U *)(addr_dest)) + _i)) = (*(((CPU_INT08U *)(addr_src)) + _i)); \
+                                                                            }                                                                                 \
+                                                                        } while (0)
+
+
+#define  MEM_VAL_COPY_GET_INTU_LITTLE(addr_dest, addr_src, val_size)    do {                                                                                  \
+                                                                            CPU_SIZE_T  _i;                                                                   \
+                                                                            CPU_SIZE_T  _j;                                                                   \
+                                                                                                                                                              \
+                                                                                                                                                              \
+                                                                            _j = (val_size) - 1;                                                              \
+                                                                                                                                                              \
+                                                                            for (_i = 0; _i < (val_size); _i++) {                                             \
+                                                                                (*(((CPU_INT08U *)(addr_dest)) + _i)) = (*(((CPU_INT08U *)(addr_src)) + _j)); \
+                                                                                _j--;                                                                         \
+                                                                            }                                                                                 \
+                                                                        } while (0)
+
+
+#define  MEM_VAL_COPY_GET_INTU(addr_dest, addr_src, val_size)           MEM_VAL_COPY_GET_INTU_BIG(addr_dest, addr_src, val_size)
+
+
+
+
+#elif   (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_LITTLE)
+
+
+#define  MEM_VAL_COPY_GET_INTU_BIG(addr_dest, addr_src, val_size)       do {                                                                                  \
+                                                                            CPU_SIZE_T  _i;                                                                   \
+                                                                            CPU_SIZE_T  _j;                                                                   \
+                                                                                                                                                              \
+                                                                                                                                                              \
+                                                                            _j = (val_size) - 1;                                                              \
+                                                                                                                                                              \
+                                                                            for (_i = 0; _i < (val_size); _i++) {                                             \
+                                                                                (*(((CPU_INT08U *)(addr_dest)) + _i)) = (*(((CPU_INT08U *)(addr_src)) + _j)); \
+                                                                                _j--;                                                                         \
+                                                                            }                                                                                 \
+                                                                        } while (0)
+
+
+#define  MEM_VAL_COPY_GET_INTU_LITTLE(addr_dest, addr_src, val_size)    do {                                                                                  \
+                                                                            CPU_SIZE_T  _i;                                                                   \
+                                                                                                                                                              \
+                                                                            for (_i = 0; _i < (val_size); _i++) {                                             \
+                                                                                (*(((CPU_INT08U *)(addr_dest)) + _i)) = (*(((CPU_INT08U *)(addr_src)) + _i)); \
+                                                                            }                                                                                 \
+                                                                        } while (0)
+
+
+#define  MEM_VAL_COPY_GET_INTU(addr_dest, addr_src, val_size)           MEM_VAL_COPY_GET_INTU_LITTLE(addr_dest, addr_src, val_size)
+
+
+
+
+#else                                                           /* See Note #8.                                         */
+
+#error  "CPU_CFG_ENDIAN_TYPE  illegally #defined in 'cpu.h'      "
+#error  "                     [See 'cpu.h  CONFIGURATION ERRORS']"
+
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                       MEM_VAL_COPY_SET_xxx()
+*
+* Description : Copy & encode data values from any CPU memory address to any CPU memory address.
+*
+* Argument(s) : addr_dest       Lowest CPU memory address to copy/encode source address's data value
+*                                   (see Notes #2 & #3).
+*
+*               addr_src        Lowest CPU memory address of data value to copy/encode
+*                                   (see Notes #2 & #3).
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Copy/encode data values based on the values' data-word order :
+*
+*                       MEM_VAL_COPY_SET_xxx_BIG()      Encode big-   endian data values -- data words' most
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_COPY_SET_xxx_LITTLE()   Encode little-endian data values -- data words' least
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_COPY_SET_xxx()          Encode data values using CPU's native or configured
+*                                                           data-word order
+*
+*                   See also 'cpu.h  CPU WORD CONFIGURATION  Note #2'.
+*
+*               (2) (a) CPU memory addresses/pointers NOT checked for NULL.
+*
+*                   (b) CPU memory addresses/buffers  NOT checked for overlapping.
+*
+*                       (1) IEEE Std 1003.1, 2004 Edition, Section 'memcpy() : DESCRIPTION' states that
+*                           "copying ... between objects that overlap ... is undefined".
+*
+*               (3) MEM_VAL_COPY_SET_xxx() macro's copy/encode data values without regard to CPU word-aligned
+*                   addresses.  Thus for processors that require data word alignment, data words can be copied/
+*                   encoded to/from any CPU address, word-aligned or not, without generating data-word-alignment
+*                   exceptions/faults.
+*
+*               (4) MEM_VAL_COPY_SET_xxx() macro's are more efficient than MEM_VAL_SET_xxx() macro's & are
+*                   also independent of CPU data-word-alignment & SHOULD be used whenever possible.
+*
+*                   See also 'MEM_VAL_SET_xxx()  Note #4'.
+*
+*               (5) Since octet-order copy/conversion are inverse operations, MEM_VAL_COPY_GET_xxx() &
+*                   MEM_VAL_COPY_SET_xxx() macros are inverse, but identical, operations & are provided
+*                   in both forms for semantics & consistency.
+*
+*                   See also 'MEM_VAL_COPY_GET_xxx()  Note #5'.
+*
+*               (6) MEM_VAL_COPY_SET_xxx() macro's are NOT atomic operations & MUST NOT be used on any
+*                   non-static (i.e. volatile) variables, registers, hardware, etc.; without the caller
+*                   of the  macro's providing some form of additional protection (e.g. mutual exclusion).
+*********************************************************************************************************
+*/
+
+                                                                /* See Note #5.                                         */
+#define  MEM_VAL_COPY_SET_INT08U_BIG(addr_dest, addr_src)               MEM_VAL_COPY_GET_INT08U_BIG(addr_dest, addr_src)
+#define  MEM_VAL_COPY_SET_INT16U_BIG(addr_dest, addr_src)               MEM_VAL_COPY_GET_INT16U_BIG(addr_dest, addr_src)
+#define  MEM_VAL_COPY_SET_INT32U_BIG(addr_dest, addr_src)               MEM_VAL_COPY_GET_INT32U_BIG(addr_dest, addr_src)
+
+#define  MEM_VAL_COPY_SET_INT08U_LITTLE(addr_dest, addr_src)            MEM_VAL_COPY_GET_INT08U_LITTLE(addr_dest, addr_src)
+#define  MEM_VAL_COPY_SET_INT16U_LITTLE(addr_dest, addr_src)            MEM_VAL_COPY_GET_INT16U_LITTLE(addr_dest, addr_src)
+#define  MEM_VAL_COPY_SET_INT32U_LITTLE(addr_dest, addr_src)            MEM_VAL_COPY_GET_INT32U_LITTLE(addr_dest, addr_src)
+
+
+#define  MEM_VAL_COPY_SET_INT08U(addr_dest, addr_src)                   MEM_VAL_COPY_GET_INT08U(addr_dest, addr_src)
+#define  MEM_VAL_COPY_SET_INT16U(addr_dest, addr_src)                   MEM_VAL_COPY_GET_INT16U(addr_dest, addr_src)
+#define  MEM_VAL_COPY_SET_INT32U(addr_dest, addr_src)                   MEM_VAL_COPY_GET_INT32U(addr_dest, addr_src)
+
+
+/*
+*********************************************************************************************************
+*                                     MEM_VAL_COPY_SET_INTU_xxx()
+*
+* Description : Copy & encode data values from any CPU memory address to any CPU memory address for
+*                   any sized data values.
+*
+* Argument(s) : addr_dest       Lowest CPU memory address to copy/encode source address's data value
+*                                   (see Notes #2 & #3).
+*
+*               addr_src        Lowest CPU memory address of data value to copy/encode
+*                                   (see Notes #2 & #3).
+*
+*               val_size        Number of data value octets to copy/encode.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) Copy/encode data values based on the values' data-word order :
+*
+*                       MEM_VAL_COPY_SET_INTU_BIG()     Encode big-   endian data values -- data words' most
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_COPY_SET_INTU_LITTLE()  Encode little-endian data values -- data words' least
+*                                                           significant octet @ lowest memory address
+*                       MEM_VAL_COPY_SET_INTU()         Encode data values using CPU's native or configured
+*                                                           data-word order
+*
+*                   See also 'cpu.h  CPU WORD CONFIGURATION  Note #2'.
+*
+*               (2) (a) CPU memory addresses/pointers NOT checked for NULL.
+*
+*                   (b) CPU memory addresses/buffers  NOT checked for overlapping.
+*
+*                       (1) IEEE Std 1003.1, 2004 Edition, Section 'memcpy() : DESCRIPTION' states that
+*                           "copying ... between objects that overlap ... is undefined".
+*
+*               (3) MEM_VAL_COPY_SET_INTU_xxx() macro's copy/encode data values without regard to CPU word-
+*                   aligned addresses.  Thus for processors that require data word alignment, data words
+*                   can be copied/encoded to/from any CPU address, word-aligned or not, without generating
+*                   data-word-alignment exceptions/faults.
+*
+*               (4) MEM_VAL_COPY_SET_xxx() macro's are more efficient than MEM_VAL_COPY_SET_INTU_xxx()
+*                   macro's & SHOULD be used whenever possible.
+*
+*                   See also 'MEM_VAL_COPY_SET_xxx()  Note #4'.
+*
+*               (5) Since octet-order copy/conversion are inverse operations, MEM_VAL_COPY_GET_INTU_xxx() &
+*                   MEM_VAL_COPY_SET_INTU_xxx() macros are inverse, but identical, operations & are provided
+*                   in both forms for semantics & consistency.
+*
+*                   See also 'MEM_VAL_COPY_GET_INTU_xxx()  Note #5'.
+*
+*               (6) MEM_VAL_COPY_SET_INTU_xxx() macro's are NOT atomic operations & MUST NOT be used on any
+*                   non-static (i.e. volatile) variables, registers, hardware, etc.; without the caller of
+*                   the macro's providing some form of additional protection (e.g. mutual exclusion).
+*********************************************************************************************************
+*/
+
+                                                                /* See Note #5.                                         */
+#define  MEM_VAL_COPY_SET_INTU_BIG(addr_dest, addr_src, val_size)       MEM_VAL_COPY_GET_INTU_BIG(addr_dest, addr_src, val_size)
+#define  MEM_VAL_COPY_SET_INTU_LITTLE(addr_dest, addr_src, val_size)    MEM_VAL_COPY_GET_INTU_LITTLE(addr_dest, addr_src, val_size)
+#define  MEM_VAL_COPY_SET_INTU(addr_dest, addr_src, val_size)           MEM_VAL_COPY_GET_INTU(addr_dest, addr_src, val_size)
+
+
+/*
+*********************************************************************************************************
+*                                         MEM_VAL_COPY_xxx()
+*
+* Description : Copy data values from any CPU memory address to any CPU memory address.
+*
+* Argument(s) : addr_dest       Lowest CPU memory address to copy source address's data value
+*                                   (see Notes #2 & #3).
+*
+*               addr_src        Lowest CPU memory address of data value to copy
+*                                   (see Notes #2 & #3).
+*
+*               val_size        Number of data value octets to copy.
+*
+* Return(s)   : none.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) MEM_VAL_COPY_xxx() macro's copy data values based on CPU's native data-word order.
+*
+*                   See also 'cpu.h  CPU WORD CONFIGURATION  Note #2'.
+*
+*               (2) (a) CPU memory addresses/pointers NOT checked for NULL.
+*
+*                   (b) CPU memory addresses/buffers  NOT checked for overlapping.
+*
+*                       (1) IEEE Std 1003.1, 2004 Edition, Section 'memcpy() : DESCRIPTION' states that
+*                           "copying ... between objects that overlap ... is undefined".
+*
+*               (3) MEM_VAL_COPY_xxx() macro's copy data values without regard to CPU word-aligned addresses.
+*                   Thus for processors that require data word alignment, data words can be copied to/from any
+*                   CPU address, word-aligned or not, without generating data-word-alignment exceptions/faults.
+*
+*               (4) MEM_VAL_COPY_xxx() macro's are more efficient than MEM_VAL_COPY() macro & SHOULD be
+*                   used whenever possible.
+*
+*               (5) MEM_VAL_COPY_xxx() macro's are NOT atomic operations & MUST NOT be used on any non-static
+*                   (i.e. volatile) variables, registers, hardware, etc.; without the caller of the macro's
+*                   providing some form of additional protection (e.g. mutual exclusion).
+*
+*               (6) MISRA-C 2004 Rule 5.2 states that "identifiers in an inner scope shall not use the same
+*                   name as an indentifier in an outer scope, and therefore hide that identifier".
+*
+*                   Therefore, to avoid possible redeclaration of commonly-used loop counter identifier name,
+*                   'i', MEM_VAL_COPY() loop counter identifier name is prefixed with a single underscore.
+*********************************************************************************************************
+*/
+
+#define  MEM_VAL_COPY_08(addr_dest, addr_src)                  do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 0)); } while (0)
+
+#define  MEM_VAL_COPY_16(addr_dest, addr_src)                  do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 0)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 1)) = (*(((CPU_INT08U *)(addr_src)) + 1)); } while (0)
+
+#define  MEM_VAL_COPY_32(addr_dest, addr_src)                  do { (*(((CPU_INT08U *)(addr_dest)) + 0)) = (*(((CPU_INT08U *)(addr_src)) + 0)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 1)) = (*(((CPU_INT08U *)(addr_src)) + 1)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 2)) = (*(((CPU_INT08U *)(addr_src)) + 2)); \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) + 3)) = (*(((CPU_INT08U *)(addr_src)) + 3)); } while (0)
+
+
+#define  MEM_VAL_COPY(addr_dest, addr_src, val_size)        do {                                                                                \
+                                                                CPU_SIZE_T  _i;                                                                 \
+                                                                                                                                                \
+                                                                for (_i = 0; _i < (val_size); _i++) {                                           \
+                                                                    (*(((CPU_INT08U *)(addr_dest)) +_i)) = (*(((CPU_INT08U *)(addr_src)) +_i)); \
+                                                                }                                                                               \
+                                                            } while (0)
+
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+void               Mem_Init                 (       void);
+
+                                                                /* ------------------ MEM API  FNCTS ------------------ */
+void               Mem_Clr                  (       void              *pmem,
+                                                    CPU_SIZE_T         size);
+
+void               Mem_Set                  (       void              *pmem,
+                                                    CPU_INT08U         data_val,
+                                                    CPU_SIZE_T         size);
+
+void               Mem_Copy                 (       void              *pdest,
+                                             const  void              *psrc,
+                                                    CPU_SIZE_T         size);
+
+void               Mem_Move                 (       void              *pdest,
+                                             const  void              *psrc,
+                                                    CPU_SIZE_T         size);
+
+CPU_BOOLEAN        Mem_Cmp                  (const  void              *p1_mem,
+                                             const  void              *p2_mem,
+                                                    CPU_SIZE_T         size);
+
+
+                                                                /* ----------- MEM HEAP FNCTS (DEPRECATED) ------------ */
+#if (LIB_MEM_CFG_HEAP_SIZE > 0u)
+void              *Mem_HeapAlloc            (       CPU_SIZE_T         size,
+                                                    CPU_SIZE_T         align,
+                                                    CPU_SIZE_T        *p_bytes_reqd,
+                                                    LIB_ERR           *p_err);
+
+CPU_SIZE_T         Mem_HeapGetSizeRem       (       CPU_SIZE_T         align,
+                                                    LIB_ERR           *p_err);
+#endif
+
+                                                                /* ------------------ MEM SEG FNCTS ------------------- */
+void               Mem_SegCreate            (const  CPU_CHAR          *p_name,
+                                                    MEM_SEG           *p_seg,
+                                                    CPU_ADDR           seg_base_addr,
+                                                    CPU_SIZE_T         size,
+                                                    CPU_SIZE_T         padding_align,
+                                                    LIB_ERR           *p_err);
+
+void               Mem_SegClr               (       MEM_SEG           *p_seg,
+                                                    LIB_ERR           *p_err);
+
+void              *Mem_SegAlloc             (const  CPU_CHAR          *p_name,
+                                                    MEM_SEG           *p_seg,
+                                                    CPU_SIZE_T         size,
+                                                    LIB_ERR           *p_err);
+
+void              *Mem_SegAllocExt          (const  CPU_CHAR          *p_name,
+                                                    MEM_SEG           *p_seg,
+                                                    CPU_SIZE_T         size,
+                                                    CPU_SIZE_T         align,
+                                                    CPU_SIZE_T        *p_bytes_reqd,
+                                                    LIB_ERR           *p_err);
+
+void              *Mem_SegAllocHW           (const  CPU_CHAR          *p_name,
+                                                    MEM_SEG           *p_seg,
+                                                    CPU_SIZE_T         size,
+                                                    CPU_SIZE_T         align,
+                                                    CPU_SIZE_T        *p_bytes_reqd,
+                                                    LIB_ERR           *p_err);
+
+CPU_SIZE_T         Mem_SegRemSizeGet        (       MEM_SEG           *p_seg,
+                                                    CPU_SIZE_T         align,
+                                                    MEM_SEG_INFO      *p_seg_info,
+                                                    LIB_ERR           *p_err);
+
+#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
+void               Mem_OutputUsage          (       void             (*out_fnct) (CPU_CHAR *),
+                                                    LIB_ERR           *p_err);
+#endif
+
+                                                                /* -------- STATIC MEM POOL FNCTS (DEPRECATED) -------- */
+void               Mem_PoolCreate           (       MEM_POOL          *p_pool,
+                                                    void              *p_mem_base,
+                                                    CPU_SIZE_T         mem_size,
+                                                    MEM_POOL_BLK_QTY   blk_nbr,
+                                                    CPU_SIZE_T         blk_size,
+                                                    CPU_SIZE_T         blk_align,
+                                                    CPU_SIZE_T        *p_bytes_reqd,
+                                                    LIB_ERR           *p_err);
+
+void               Mem_PoolClr              (       MEM_POOL          *p_pool,
+                                                    LIB_ERR           *p_err);
+
+void              *Mem_PoolBlkGet           (       MEM_POOL          *p_pool,
+                                                    CPU_SIZE_T         size,
+                                                    LIB_ERR           *p_err);
+
+void               Mem_PoolBlkFree          (       MEM_POOL          *p_pool,
+                                                    void              *p_blk,
+                                                    LIB_ERR           *p_err);
+
+MEM_POOL_BLK_QTY   Mem_PoolBlkGetNbrAvail   (       MEM_POOL          *p_pool,
+                                                    LIB_ERR           *p_err);
+
+                                                                /* -------------- DYNAMIC MEM POOL FNCTS -------------- */
+void               Mem_DynPoolCreate        (const  CPU_CHAR          *p_name,
+                                                    MEM_DYN_POOL      *p_pool,
+                                                    MEM_SEG           *p_seg,
+                                                    CPU_SIZE_T         blk_size,
+                                                    CPU_SIZE_T         blk_align,
+                                                    CPU_SIZE_T         blk_qty_init,
+                                                    CPU_SIZE_T         blk_qty_max,
+                                                    LIB_ERR           *p_err);
+
+void               Mem_DynPoolCreateHW      (const  CPU_CHAR          *p_name,
+                                                    MEM_DYN_POOL      *p_pool,
+                                                    MEM_SEG           *p_seg,
+                                                    CPU_SIZE_T         blk_size,
+                                                    CPU_SIZE_T         blk_align,
+                                                    CPU_SIZE_T         blk_qty_init,
+                                                    CPU_SIZE_T         blk_qty_max,
+                                                    LIB_ERR           *p_err);
+
+void              *Mem_DynPoolBlkGet        (       MEM_DYN_POOL      *p_pool,
+                                                    LIB_ERR           *p_err);
+
+void               Mem_DynPoolBlkFree       (       MEM_DYN_POOL      *p_pool,
+                                                    void              *p_blk,
+                                                    LIB_ERR           *p_err);
+
+CPU_SIZE_T         Mem_DynPoolBlkNbrAvailGet(       MEM_DYN_POOL      *p_pool,
+                                                    LIB_ERR           *p_err);
+
+
+/*
+*********************************************************************************************************
+*                                        CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+#ifndef  LIB_MEM_CFG_ARG_CHK_EXT_EN
+#error  "LIB_MEM_CFG_ARG_CHK_EXT_EN         not #define'd in 'lib_cfg.h'"
+#error  "                             [MUST be  DEF_DISABLED]           "
+#error  "                             [     ||  DEF_ENABLED ]           "
+
+#elif  ((LIB_MEM_CFG_ARG_CHK_EXT_EN != DEF_DISABLED) && \
+        (LIB_MEM_CFG_ARG_CHK_EXT_EN != DEF_ENABLED ))
+#error  "LIB_MEM_CFG_ARG_CHK_EXT_EN   illegally #define'd in 'lib_cfg.h'"
+#error  "                             [MUST be  DEF_DISABLED]           "
+#error  "                             [     ||  DEF_ENABLED ]           "
+#endif
+
+
+
+#ifndef  LIB_MEM_CFG_OPTIMIZE_ASM_EN
+#error  "LIB_MEM_CFG_OPTIMIZE_ASM_EN        not #define'd in 'lib_cfg.h'"
+#error  "                             [MUST be  DEF_DISABLED]           "
+#error  "                             [     ||  DEF_ENABLED ]           "
+
+#elif  ((LIB_MEM_CFG_OPTIMIZE_ASM_EN != DEF_DISABLED) && \
+        (LIB_MEM_CFG_OPTIMIZE_ASM_EN != DEF_ENABLED ))
+#error  "LIB_MEM_CFG_OPTIMIZE_ASM_EN  illegally #define'd in 'lib_cfg.h'"
+#error  "                             [MUST be  DEF_DISABLED]           "
+#error  "                             [     ||  DEF_ENABLED ]           "
+#endif
+
+
+#ifndef  LIB_MEM_CFG_HEAP_SIZE
+#error  "LIB_MEM_CFG_HEAP_SIZE              not #define'd in 'lib_cfg.h'"
+#error  "                                   [MUST be  >= 0]             "
+#endif
+
+
+#ifdef   LIB_MEM_CFG_HEAP_BASE_ADDR
+#if     (LIB_MEM_CFG_HEAP_BASE_ADDR == 0x0)
+#error  "LIB_MEM_CFG_HEAP_BASE_ADDR   illegally #define'd in 'lib_cfg.h'"
+#error  "                             [MUST be  > 0x0]                  "
+#endif
+#endif
+
+
+#if    ((LIB_MEM_CFG_DBG_INFO_EN != DEF_DISABLED) && \
+        (LIB_MEM_CFG_DBG_INFO_EN != DEF_ENABLED ))
+#error  "LIB_MEM_CFG_DBG_INFO_EN illegally defined in 'lib_cfg.h'"
+#error  "                        [MUST be  DEF_DISABLED]         "
+#error  "                        [     ||  DEF_ENABLED ]         "
+
+#elif  ((LIB_MEM_CFG_HEAP_SIZE   == 0u) &&           \
+        (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED))
+#error  "LIB_MEM_CFG_HEAP_SIZE illegally defined in 'lib_cfg.h'                         "
+#error  "                      [MUST be > 0 when LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED]"
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                    LIBRARY CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+                                                                /* See 'lib_mem.h  Note #2a'.                           */
+#if     (CPU_CORE_VERSION < 127u)
+#error  "CPU_CORE_VERSION  [SHOULD be >= V1.27]"
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*
+* Note(s) : (1) See 'lib_mem.h  MODULE'.
+*********************************************************************************************************
+*/
+
+#endif                                                          /* End of lib mem module include.                       */
+

+ 4041 - 0
MiddleWare/uCOS_II/uC-LIB/lib_str.c

@@ -0,0 +1,4041 @@
+/*
+*********************************************************************************************************
+*                                                uC/LIB
+*                                        CUSTOM LIBRARY MODULES
+*
+*                         (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL
+*
+*                  All rights reserved.  Protected by international copyright laws.
+*
+*                  uC/LIB is provided in source form to registered licensees ONLY.  It is
+*                  illegal to distribute this source code to any third party unless you receive
+*                  written permission by an authorized Micrium representative.  Knowledge of
+*                  the source code may NOT be used to develop a similar product.
+*
+*                  Please help us continue to provide the Embedded community with the finest
+*                  software available.  Your honesty is greatly appreciated.
+*
+*                  You can find our product's user manual, API reference, release notes and
+*                  more information at: https://doc.micrium.com
+*
+*                  You can contact us at: http://www.micrium.com
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                       ASCII STRING MANAGEMENT
+*
+* Filename      : lib_str.c
+* Version       : V1.38.01
+* Programmer(s) : ITJ
+*                 BAN
+*                 JDH
+*********************************************************************************************************
+* Note(s)       : (1) NO compiler-supplied standard library functions are used in library or product software.
+*
+*                     (a) ALL standard library functions are implemented in the custom library modules :
+*
+*                         (1) \<Custom Library Directory>\lib_*.*
+*
+*                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+*
+*                               where
+*                                       <Custom Library Directory>      directory path for custom library software
+*                                       <cpu>                           directory name for specific processor (CPU)
+*                                       <compiler>                      directory name for specific compiler
+*
+*                     (b) Product-specific library functions are implemented in individual products.
+*
+*********************************************************************************************************
+* Notice(s)     : (1) The Institute of Electrical and Electronics Engineers and The Open Group, have given
+*                     us permission to reprint portions of their documentation.  Portions of this text are
+*                     reprinted and reproduced in electronic form from the IEEE Std 1003.1, 2004 Edition,
+*                     Standard for Information Technology -- Portable Operating System Interface (POSIX),
+*                     The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute
+*                     of Electrical and Electronics Engineers, Inc and The Open Group.  In the event of any
+*                     discrepancy between these versions and the original IEEE and The Open Group Standard,
+*                     the original IEEE and The Open Group Standard is the referee document.  The original
+*                     Standard can be obtained online at http://www.opengroup.org/unix/online.html.
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#define    MICRIUM_SOURCE
+#define    LIB_STR_MODULE
+#include  <lib_str.h>
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL DEFINES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                           LOCAL CONSTANTS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          LOCAL DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                            LOCAL TABLES
+*********************************************************************************************************
+*/
+
+static  const  CPU_INT32U  Str_MultOvfThTbl_Int32U[] = {
+   (CPU_INT32U) DEF_INT_32U_MAX_VAL,                /*                Invalid base  0.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL /  1u),         /*                Invalid base  1.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL /  2u),         /* 32-bit mult ovf th for base  2.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL /  3u),         /* 32-bit mult ovf th for base  3.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL /  4u),         /* 32-bit mult ovf th for base  4.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL /  5u),         /* 32-bit mult ovf th for base  5.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL /  6u),         /* 32-bit mult ovf th for base  6.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL /  7u),         /* 32-bit mult ovf th for base  7.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL /  8u),         /* 32-bit mult ovf th for base  8.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL /  9u),         /* 32-bit mult ovf th for base  9.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 10u),         /* 32-bit mult ovf th for base 10.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 11u),         /* 32-bit mult ovf th for base 11.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 12u),         /* 32-bit mult ovf th for base 12.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 13u),         /* 32-bit mult ovf th for base 13.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 14u),         /* 32-bit mult ovf th for base 14.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 15u),         /* 32-bit mult ovf th for base 15.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 16u),         /* 32-bit mult ovf th for base 16.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 17u),         /* 32-bit mult ovf th for base 17.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 18u),         /* 32-bit mult ovf th for base 18.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 19u),         /* 32-bit mult ovf th for base 19.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 20u),         /* 32-bit mult ovf th for base 20.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 21u),         /* 32-bit mult ovf th for base 21.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 22u),         /* 32-bit mult ovf th for base 22.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 23u),         /* 32-bit mult ovf th for base 23.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 24u),         /* 32-bit mult ovf th for base 24.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 25u),         /* 32-bit mult ovf th for base 25.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 26u),         /* 32-bit mult ovf th for base 26.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 27u),         /* 32-bit mult ovf th for base 27.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 28u),         /* 32-bit mult ovf th for base 28.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 29u),         /* 32-bit mult ovf th for base 29.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 30u),         /* 32-bit mult ovf th for base 30.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 31u),         /* 32-bit mult ovf th for base 31.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 32u),         /* 32-bit mult ovf th for base 32.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 33u),         /* 32-bit mult ovf th for base 33.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 34u),         /* 32-bit mult ovf th for base 34.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 35u),         /* 32-bit mult ovf th for base 35.  */
+   (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 36u)          /* 32-bit mult ovf th for base 36.  */
+};
+
+
+/*
+*********************************************************************************************************
+*                                       LOCAL GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                      LOCAL FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+static  CPU_CHAR    *Str_FmtNbr_Int32  (       CPU_INT32U     nbr,
+                                               CPU_INT08U     nbr_dig,
+                                               CPU_INT08U     nbr_base,
+                                               CPU_BOOLEAN    nbr_neg,
+                                               CPU_CHAR       lead_char,
+                                               CPU_BOOLEAN    lower_case,
+                                               CPU_BOOLEAN    nul,
+                                               CPU_CHAR      *pstr);
+
+static  CPU_INT32U   Str_ParseNbr_Int32(const  CPU_CHAR      *pstr,
+                                               CPU_CHAR     **pstr_next,
+                                               CPU_INT08U     nbr_base,
+                                               CPU_BOOLEAN    nbr_signed,
+                                               CPU_BOOLEAN   *pnbr_neg);
+
+
+/*
+*********************************************************************************************************
+*                                     LOCAL CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                              Str_Len()
+*
+* Description : Calculate length of a string.
+*
+* Argument(s) : pstr        Pointer to string (see Note #1).
+*
+* Return(s)   : Length of string; number of characters in string before terminating NULL character
+*                   (see Note #2b1).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : DESCRIPTION' states that :
+*
+*                       (1) "The strlen() function shall compute the number of bytes in the string to
+*                            which 's' ('pstr') points," ...
+*                       (2) "not including the terminating null byte."
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : RETURN VALUE' states that :
+*
+*                       (1) "The strlen() function shall return the length of 's' ('pstr');" ...
+*                       (2) "no return value shall be reserved to indicate an error."
+*
+*               (3) String length calculation terminates when :
+*
+*                   (a) String pointer points to NULL.
+*                       (1) String buffer overlaps with NULL address.
+*                       (2) String length calculated for string up to but NOT beyond or including
+*                           the NULL address.
+*
+*                   (b) Terminating NULL character found.
+*                       (1) String length calculated for string up to but NOT           including
+*                           the NULL character (see Note #2a2).
+*********************************************************************************************************
+*/
+
+CPU_SIZE_T  Str_Len (const  CPU_CHAR  *pstr)
+{
+    CPU_SIZE_T  len;
+
+
+    len = Str_Len_N(pstr,
+                    DEF_INT_CPU_U_MAX_VAL);
+
+    return (len);
+}
+
+
+/*
+*********************************************************************************************************
+*                                             Str_Len_N()
+*
+* Description : Calculate length of a string, up to a maximum number of characters.
+*
+* Argument(s) : pstr        Pointer to string (see Note #1).
+*
+*               len_max     Maximum number of characters to search (see Note #3c).
+*
+* Return(s)   : Length of string; number of characters in string before terminating NULL character,
+*                   if terminating NULL character     found (see Note #2b1).
+*
+*               Requested maximum number of characters to search,
+*                   if terminating NULL character NOT found (see Note #3c).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : DESCRIPTION' states that :
+*
+*                       (1) "The strlen() function shall compute the number of bytes in the string to
+*                            which 's' ('pstr') points," ...
+*                       (2) "not including the terminating null byte."
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : RETURN VALUE' states that :
+*
+*                       (1) "The strlen() function shall return the length of 's' ('pstr');" ...
+*                       (2) "no return value shall be reserved to indicate an error."
+*
+*               (3) String length calculation terminates when :
+*
+*                   (a) String pointer points to NULL.
+*                       (1) String buffer overlaps with NULL address.
+*                       (2) String length calculated for string up to but NOT beyond or including
+*                           the NULL address.
+*
+*                   (b) Terminating NULL character found.
+*                       (1) String length calculated for string up to but NOT           including
+*                           the NULL character (see Note #2a2).
+*
+*                   (c) 'len_max' number of characters searched.
+*                       (1) 'len_max' number of characters does NOT include the terminating NULL character.
+*********************************************************************************************************
+*/
+
+CPU_SIZE_T  Str_Len_N (const  CPU_CHAR    *pstr,
+                              CPU_SIZE_T   len_max)
+{
+    const  CPU_CHAR    *pstr_len;
+           CPU_SIZE_T   len;
+
+
+    pstr_len = pstr;
+    len      = 0u;
+    while (( pstr_len != (const CPU_CHAR *)  0 ) &&             /* Calc str len until NULL ptr (see Note #3a) ...       */
+           (*pstr_len != (      CPU_CHAR  )'\0') &&             /* ... or NULL char found      (see Note #3b) ...       */
+           ( len      <  (      CPU_SIZE_T)len_max)) {          /* ... or max nbr chars srch'd (see Note #3c).          */
+        pstr_len++;
+        len++;
+    }
+
+    return (len);                                               /* Rtn str len (see Note #3b1).                         */
+}
+
+
+/*
+*********************************************************************************************************
+*                                             Str_Copy()
+*
+* Description : Copy source string to destination string buffer.
+*
+* Argument(s) : pstr_dest   Pointer to destination string buffer to receive source string copy   (see Note #1a).
+*
+*               pstr_src    Pointer to source      string to copy into destination string buffer (see Note #1b).
+*
+* Return(s)   : Pointer to destination string, if NO error(s) [see Note #2b1].
+*
+*               Pointer to NULL,               otherwise      (see Note #2b2A).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
+*
+*                       (1) Destination buffer size MUST be large enough to accommodate the entire source
+*                           string size including the terminating NULL character.
+*
+*                   (b) Source buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcpy() : DESCRIPTION' states that :
+*
+*                       (1) "The strcpy() function shall copy the string pointed to by 's2' ('pstr_src')
+*                            ... into the array pointed to by 's1' ('pstr_dest')" ...
+*                       (2) "(including the terminating null byte)."
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strcpy() : RETURN VALUE' states that :
+*
+*                       (1) "The strcpy() function shall return 's1' ('pstr_dest');" ...
+*                       (2) "no return value is reserved to indicate an error."
+*                           (A) #### This requirement is intentionally NOT implemented in order to return
+*                               NULL for any error(s).
+*
+*                   (c) IEEE Std 1003.1, 2004 Edition, Section 'strcpy() : DESCRIPTION' states that "if
+*                       copying takes place between objects that overlap, the behavior is undefined".
+*
+*               (3) String copy terminates when :
+*
+*                   (a) Destination/Source string pointer(s) are passed NULL pointers.
+*                       (1) No string copy performed; NULL pointer returned.
+*
+*                   (b) Destination/Source string pointer(s) point to NULL.
+*                       (1) String buffer(s) overlap with NULL address; NULL pointer returned.
+*
+*                   (c) Source string's terminating NULL character found.
+*                       (1) Entire source string copied into destination string buffer (see Note #2a).
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Copy (       CPU_CHAR  *pstr_dest,
+                     const  CPU_CHAR  *pstr_src)
+{
+    CPU_CHAR  *pstr_rtn;
+
+
+    pstr_rtn = Str_Copy_N(pstr_dest,
+                          pstr_src,
+                          DEF_INT_CPU_U_MAX_VAL);
+
+    return (pstr_rtn);
+}
+
+
+/*
+*********************************************************************************************************
+*                                            Str_Copy_N()
+*
+* Description : Copy source string to destination string buffer, up to a maximum number of characters.
+*
+* Argument(s) : pstr_dest   Pointer to destination string buffer to receive source string copy   (see Note #1a).
+*
+*               pstr_src    Pointer to source      string to copy into destination string buffer (see Note #1b).
+*
+*               len_max     Maximum number of characters  to copy (see Notes #2a2 & #3d).
+*
+* Return(s)   : Pointer to destination string, if NO error(s) [see Note #2b1].
+*
+*               Pointer to NULL,               otherwise      (see Note #2b2A).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
+*
+*                       (1) Destination buffer size MUST be large enough to accommodate the entire source
+*                           string size including the terminating NULL character.
+*
+*                   (b) Source string buffer NOT modified.
+*
+*               (2) (a) (1) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : DESCRIPTION' states that :
+*
+*                           (A) "The strncpy() function shall copy ... the array pointed to by 's2'
+*                               ('pstr_src') to the array pointed to by 's1' ('pstr_dest')"; ...
+*                           (B)  but "not more than 'n' ('len_max') bytes"                   ...
+*                           (C)  &   "(bytes that follow a null byte are not copied)".
+*
+*                       (2) (A) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : DESCRIPTION' adds that
+*                              "if the array pointed to by 's2' ('pstr_src') is a string that is shorter
+*                               than 'n' ('len_max') bytes, null bytes shall be appended to the copy in
+*                               the array pointed to by 's1' ('pstr_dest'), until 'n' ('len_max') bytes
+*                               in all are written."
+*
+*                               (1) #### Since Str_Copy() limits the maximum number of characters to copy
+*                                   via Str_Copy_N() by the CPU's maximum number of addressable characters,
+*                                   this requirement is intentionally NOT implemented to avoid appending
+*                                   a potentially large number of unnecessary terminating NULL characters.
+*
+*                           (B) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : APPLICATION USAGE' also
+*                               states that "if there is no null byte in the first 'n' ('len_max') bytes of
+*                               the array pointed to by 's2' ('pstr_src'), the result is not null-terminated".
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : RETURN VALUE' states that :
+*
+*                       (1) "The strncpy() function shall return 's1' ('pstr_dest');" ...
+*                       (2) "no return value is reserved to indicate an error."
+*                           (A) #### This requirement is intentionally ignored in order to return NULL
+*                               for any error(s).
+*
+*                   (c) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : DESCRIPTION' states that "if
+*                       copying takes place between objects that overlap, the behavior is undefined".
+*
+*               (3) String copy terminates when :
+*
+*                   (a) Destination/Source string pointer(s) are passed NULL pointers.
+*                       (1) No string copy performed; NULL pointer returned.
+*
+*                   (b) Destination/Source string pointer(s) point to NULL.
+*                       (1) String buffer(s) overlap with NULL address; NULL pointer returned.
+*
+*                   (c) Source string's terminating NULL character found.
+*                       (1) Entire source string copied into destination string buffer (see Note #2a1A).
+*
+*                   (d) 'len_max' number of characters copied.
+*                       (1) 'len_max' number of characters MAY include the terminating NULL character
+*                           (see Note #2a1C).
+*                       (2) Null copies allowed (i.e. zero-length copies).
+*                           (A) No string copy performed; destination string returned  (see Note #2b1).
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Copy_N (       CPU_CHAR    *pstr_dest,
+                       const  CPU_CHAR    *pstr_src,
+                              CPU_SIZE_T   len_max)
+{
+           CPU_CHAR    *pstr_copy_dest;
+    const  CPU_CHAR    *pstr_copy_src;
+           CPU_SIZE_T   len_copy;
+
+                                                                /* Rtn NULL if str ptr(s) NULL (see Note #3a1).         */
+    if (pstr_dest == (CPU_CHAR *)0) {
+        return ((CPU_CHAR *)0);
+    }
+    if (pstr_src  == (const CPU_CHAR *)0) {
+        return ((CPU_CHAR *)0);
+    }
+
+
+    pstr_copy_dest = pstr_dest;
+    pstr_copy_src  = pstr_src;
+    len_copy       = 0u;
+
+    while (( pstr_copy_dest != (      CPU_CHAR *)  0 ) &&       /* Copy str until NULL ptr(s)  [see Note #3b]  ...      */
+           ( pstr_copy_src  != (const CPU_CHAR *)  0 ) &&
+           (*pstr_copy_src  != (      CPU_CHAR  )'\0') &&       /* ... or NULL char found      (see Note #3c); ...      */
+           ( len_copy       <  (      CPU_SIZE_T)len_max)) {    /* ... or max nbr chars copied (see Note #3d).          */
+       *pstr_copy_dest = *pstr_copy_src;
+        pstr_copy_dest++;
+        pstr_copy_src++;
+        len_copy++;
+    }
+                                                                /* Rtn NULL if NULL ptr(s) found  (see Note #3b1).      */
+    if ((pstr_copy_dest == (      CPU_CHAR *)0) ||
+        (pstr_copy_src  == (const CPU_CHAR *)0)) {
+         return ((CPU_CHAR *)0);
+    }
+
+    if (len_copy < len_max) {                                   /* If  copy str len < max buf len (see Note #2a2A), ... */
+       *pstr_copy_dest = (CPU_CHAR)'\0';                        /* ... copy NULL char  (see Note #3c1).                 */
+    }
+
+
+    return (pstr_dest);                                         /* Rtn ptr to dest str (see Note #2b1).                 */
+}
+
+
+/*
+*********************************************************************************************************
+*                                              Str_Cat()
+*
+* Description : Append concatenation string to destination string.
+*
+* Argument(s) : pstr_dest   Pointer to destination   string to append concatenation  string (see Note #1a).
+*
+*               pstr_cat    Pointer to concatenation string to append to destination string (see Note #1b).
+*
+* Return(s)   : Pointer to destination string, if NO error(s) [see Note #2b1].
+*
+*               Pointer to NULL,               otherwise      (see Note #2b2A).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
+*
+*                       (1) Destination buffer size MUST be large enough to accommodate the entire
+*                           concatenated string size including the terminating NULL character.
+*
+*                   (b) Concatenation string buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcat() : DESCRIPTION' states that :
+*
+*                       (1) "The strcat() function shall append a copy of the string pointed to by 's2'
+*                           ('pstr_cat') ... to the end of the string pointed to by 's1' ('pstr_dest')."
+*
+*                       (2) (A) "The initial byte of 's2' ('pstr_cat') overwrites the null byte at the
+*                                end of 's1' ('pstr_dest')."
+*                           (B)  A "terminating null byte" is appended at the end of the concatenated
+*                                destination strings.
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strcat() : RETURN VALUE' states that :
+*
+*                       (1) "The strcat() function shall return 's1' ('pstr_dest');" ...
+*                       (2) "no return value shall be reserved to indicate an error."
+*                           (A) #### This requirement is intentionally NOT implemented in order to return
+*                               NULL for any error(s).
+*
+*                   (c) IEEE Std 1003.1, 2004 Edition, Section 'strcat() : DESCRIPTION' states that "if
+*                       copying takes place between objects that overlap, the behavior is undefined."
+*
+*               (3) String concatenation terminates when :
+*
+*                   (a) Destination/Concatenation string pointer(s) are passed NULL pointers.
+*                       (1) No string concatenation performed; NULL pointer returned.
+*
+*                   (b) Destination/Concatenation string pointer(s) point to NULL.
+*                       (1) String buffer(s) overlap with NULL address; NULL pointer returned.
+*
+*                   (c) Concatenation string's terminating NULL character found.
+*                       (1) Entire concatenation string appended to destination string (see Note #2a1).
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Cat (       CPU_CHAR  *pstr_dest,
+                    const  CPU_CHAR  *pstr_cat)
+{
+    CPU_CHAR  *pstr_rtn;
+
+
+    pstr_rtn = Str_Cat_N(pstr_dest,
+                         pstr_cat,
+                         DEF_INT_CPU_U_MAX_VAL);
+
+    return (pstr_rtn);
+}
+
+
+/*
+*********************************************************************************************************
+*                                             Str_Cat_N()
+*
+* Description : Append concatenation string to destination string, up to a maximum number of characters.
+*
+* Argument(s) : pstr_dest   Pointer to destination   string to append concatenation  string (see Note #1a).
+*
+*               pstr_cat    Pointer to concatenation string to append to destination string (see Note #1b).
+*
+*               len_max     Maximum number of characters to concatenate (see Notes #2a1B & #3d).
+*
+* Return(s)   : Pointer to destination string, if NO error(s) [see Note #2b1].
+*
+*               Pointer to NULL,               otherwise      (see Note #2b2A).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
+*
+*                       (1) Destination buffer size MUST be large enough to accommodate the entire
+*                           concatenated string size including the terminating NULL character.
+*
+*                   (b) Concatenation string buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strncat() : DESCRIPTION' states that :
+*
+*                       (1) (A) "The strncat() function shall append ... the array pointed to by 's2'
+*                               ('pstr_cat') to the end of the string pointed to by 's1' ('pstr_dest')" ...
+*                           (B)  but "not more than 'n' ('len_max') bytes".
+*
+*                       (2) (A) "The initial byte of 's2' ('pstr_cat') overwrites the null byte at the
+*                                end of 's1' ('pstr_dest')."
+*                           (B) "(a null byte and bytes that follow it are not appended)."
+*                           (C) "A terminating null byte is always appended to the result."
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strncat() : RETURN VALUE' states that :
+*
+*                       (1) "The strncat() function shall return 's1' ('pstr_dest');" ...
+*                       (2) "no return value shall be reserved to indicate an error."
+*                           (A) #### This requirement is intentionally NOT implemented in order to return
+*                               NULL for any error(s).
+*
+*                   (c) IEEE Std 1003.1, 2004 Edition, Section 'strncat() : DESCRIPTION' states that "if
+*                       copying takes place between objects that overlap, the behavior is undefined."
+*
+*               (3) String concatenation terminates when :
+*
+*                   (a) Destination/Concatenation string pointer(s) are passed NULL pointers.
+*                       (1) No string concatenation performed; NULL pointer returned.
+*
+*                   (b) Destination/Concatenation string pointer(s) point to NULL.
+*                       (1) String buffer(s) overlap with NULL address; NULL pointer returned.
+*
+*                   (c) Concatenation string's terminating NULL character found.
+*                       (1) Entire concatenation string appended to destination string (see Note #2a1A).
+*
+*                   (d) 'len_max' number of characters concatenated.
+*
+*                       (1) 'len_max' number of characters does NOT include the terminating NULL character
+*                           (see Note #2a2).
+*
+*                       (2) Null concatenations allowed (i.e. zero-length concatenations).
+*                           (A) No string concatenation performed; destination string returned
+*                               (see Note #2b1).
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Cat_N (       CPU_CHAR    *pstr_dest,
+                      const  CPU_CHAR    *pstr_cat,
+                             CPU_SIZE_T   len_max)
+{
+           CPU_CHAR    *pstr_cat_dest;
+    const  CPU_CHAR    *pstr_cat_src;
+           CPU_SIZE_T   len_cat;
+
+                                                                /* Rtn NULL if str ptr(s) NULL (see Note #3a1).         */
+    if (pstr_dest == (CPU_CHAR *)0) {
+        return ((CPU_CHAR *)0);
+    }
+    if (pstr_cat  == (const CPU_CHAR *)0) {
+        return ((CPU_CHAR *)0);
+    }
+
+    if (len_max < 1) {                                          /* Rtn dest str if cat len = 0 (see Note #3d2A).        */
+        return ((CPU_CHAR *)pstr_dest);
+    }
+
+
+    pstr_cat_dest = pstr_dest;
+    while (( pstr_cat_dest != (CPU_CHAR *)  0 ) &&              /* Adv to end of cur dest str until NULL ptr ...        */
+           (*pstr_cat_dest != (CPU_CHAR  )'\0')) {              /* ... or NULL char found..                             */
+        pstr_cat_dest++;
+    }
+    if (pstr_cat_dest == (CPU_CHAR *)0) {                       /* Rtn NULL if NULL ptr found (see Note #3b1).          */
+        return ((CPU_CHAR *)0);
+    }
+
+    pstr_cat_src = pstr_cat;
+    len_cat      = 0u;
+
+    while (( pstr_cat_dest != (      CPU_CHAR *)  0 ) &&        /* Cat str until NULL ptr(s)  [see Note #3b]  ...       */
+           ( pstr_cat_src  != (const CPU_CHAR *)  0 ) &&
+           (*pstr_cat_src  != (      CPU_CHAR  )'\0') &&        /* ... or NULL char found     (see Note #3c); ...       */
+           ( len_cat       <  (      CPU_SIZE_T)len_max)) {     /* ... or max nbr chars cat'd (see Note #3d).           */
+       *pstr_cat_dest = *pstr_cat_src;
+        pstr_cat_dest++;
+        pstr_cat_src++;
+        len_cat++;
+    }
+                                                                /* Rtn NULL if NULL ptr(s) found (see Note #3b1).       */
+    if ((pstr_cat_dest == (      CPU_CHAR *)0) ||
+        (pstr_cat_src  == (const CPU_CHAR *)0)) {
+         return ((CPU_CHAR *)0);
+    }
+
+   *pstr_cat_dest = (CPU_CHAR)'\0';                             /* Append NULL char    (see Note #2a2C).                */
+
+
+    return (pstr_dest);                                         /* Rtn ptr to dest str (see Note #2b1).                 */
+}
+
+
+/*
+*********************************************************************************************************
+*                                              Str_Cmp()
+*
+* Description : Determine if two strings are identical.
+*
+* Argument(s) : p1_str      Pointer to first  string (see Note #1).
+*
+*               p2_str      Pointer to second string (see Note #1).
+*
+* Return(s)   : 0,              if strings are identical             (see Notes #3a1A, #3a2A, & #3b).
+*
+*               Negative value, if 'p1_str' is less    than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
+*
+*               Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
+*
+*               See also Note #2b.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffers NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' states that "the
+*                       strcmp() function shall compare the string pointed to by 's1' ('p1_str') to the
+*                       string pointed to by 's2' ('p2_str)".
+*
+*                   (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : RETURN VALUE' states that
+*                          "upon successful completion, strcmp() shall return an integer greater than,
+*                           equal to, or less than 0".
+*
+*                       (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
+*                           sign of a non-zero return value shall be determined by the sign of the difference
+*                           between the values of the first pair of bytes ... that differ in the strings
+*                           being compared".
+*
+*               (3) String comparison terminates when :
+*
+*                   (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
+*                               (1) NULL strings identical; 0 returned.
+*
+*                           (B) (1) 'p1_str' passed a NULL pointer.
+*                                   (a) Return negative value of character pointed to by 'p2_str'.
+*
+*                               (2) 'p2_str' passed a NULL pointer.
+*                                   (a) Return positive value of character pointed to by 'p1_str'.
+*
+*                       (2) (A) BOTH strings point to NULL.
+*                               (1) Strings overlap with NULL address.
+*                               (2) Strings identical up to but NOT beyond or including the NULL address;
+*                                   0 returned.
+*
+*                           (B) (1) 'p1_str_cmp_next' points to NULL.
+*                                   (a) 'p1_str' overlaps with NULL address.
+*                                   (b) Strings compared up to but NOT beyond or including the NULL address.
+*                                   (c) Return negative value of character pointed to by 'p2_str_cmp_next'.
+*
+*                               (2) 'p2_str_cmp_next' points to NULL.
+*                                   (a) 'p2_str' overlaps with NULL address.
+*                                   (b) Strings compared up to but NOT beyond or including the NULL address.
+*                                   (c) Return positive value of character pointed to by 'p1_str_cmp_next'.
+*
+*                   (b) Terminating NULL character found in both strings.
+*                       (1) Strings identical; 0 returned.
+*                       (2) Only one NULL character test required in conditional since previous condition
+*                           tested character equality.
+*
+*                   (c) Non-matching characters found.
+*                       (1) Return signed-integer difference of the character pointed to by 'p2_str'
+*                           from the character pointed to by 'p1_str'.
+*
+*               (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
+*                   return value, 'CPU_CHAR' native data type size MUST be 8-bit.
+*********************************************************************************************************
+*/
+
+CPU_INT16S  Str_Cmp (const  CPU_CHAR  *p1_str,
+                     const  CPU_CHAR  *p2_str)
+{
+    CPU_INT16S  cmp_val;
+
+
+    cmp_val = Str_Cmp_N(p1_str,
+                        p2_str,
+                        DEF_INT_CPU_U_MAX_VAL);
+
+    return (cmp_val);
+}
+
+
+/*
+*********************************************************************************************************
+*                                             Str_Cmp_N()
+*
+* Description : Determine if two strings are identical for up to a maximum number of characters.
+*
+* Argument(s) : p1_str      Pointer to first  string (see Note #1).
+*
+*               p2_str      Pointer to second string (see Note #1).
+*
+*               len_max     Maximum number of characters to compare  (see Note  #3d).
+*
+* Return(s)   : 0,              if strings are identical             (see Notes #3a1A, #3a2A, #3b, & #3d).
+*
+*               Negative value, if 'p1_str' is less    than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
+*
+*               Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
+*
+*               See also Note #2b.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffers NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : DESCRIPTION' states that :
+*
+*                       (1) "The strncmp() function shall compare ... the array pointed to by 's1' ('p1_str')
+*                            to the array pointed to by 's2' ('p2_str)" ...
+*                       (2)  but "not more than 'n' ('len_max') bytes" of either array.
+*
+*                   (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : RETURN VALUE' states that
+*                          "upon successful completion, strncmp() shall return an integer greater than,
+*                           equal to, or less than 0".
+*
+*                       (2) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : DESCRIPTION' adds that
+*                          "the sign of a non-zero return value is determined by the sign of the difference
+*                           between the values of the first pair of bytes ... that differ in the strings
+*                           being compared".
+*
+*               (3) String comparison terminates when :
+*
+*                   (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
+*                               (1) NULL strings identical; 0 returned.
+*
+*                           (B) (1) 'p1_str' passed a NULL pointer.
+*                                   (a) Return negative value of character pointed to by 'p2_str'.
+*
+*                               (2) 'p2_str' passed a NULL pointer.
+*                                   (a) Return positive value of character pointed to by 'p1_str'.
+*
+*                       (2) (A) BOTH strings point to NULL.
+*                               (1) Strings overlap with NULL address.
+*                               (2) Strings identical up to but NOT beyond or including the NULL address;
+*                                   0 returned.
+*
+*                           (B) (1) 'p1_str_cmp_next' points to NULL.
+*                                   (a) 'p1_str' overlaps with NULL address.
+*                                   (b) Strings compared up to but NOT beyond or including the NULL address.
+*                                   (c) Return negative value of character pointed to by 'p2_str_cmp_next'.
+*
+*                               (2) 'p2_str_cmp_next' points to NULL.
+*                                   (a) 'p2_str' overlaps with NULL address.
+*                                   (b) Strings compared up to but NOT beyond or including the NULL address.
+*                                   (c) Return positive value of character pointed to by 'p1_str_cmp_next'.
+*
+*                   (b) Terminating NULL character found in both strings.
+*                       (1) Strings identical; 0 returned.
+*                       (2) Only one NULL character test required in conditional since previous condition
+*                           tested character equality.
+*
+*                   (c) Non-matching characters found.
+*                       (1) Return signed-integer difference of the character pointed to by 'p2_str'
+*                           from the character pointed to by 'p1_str'.
+*
+*                   (d) (1) 'len_max' passed a zero length.
+*                           (A) Zero-length strings identical; 0 returned.
+*
+*                       (2) First 'len_max' number of characters identical.
+*                           (A) Strings identical; 0 returned.
+*
+*                       See also Note #2a2.
+*
+*               (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
+*                   return value, 'CPU_CHAR' native data type size MUST be 8-bit.
+*********************************************************************************************************
+*/
+
+CPU_INT16S  Str_Cmp_N (const  CPU_CHAR    *p1_str,
+                       const  CPU_CHAR    *p2_str,
+                              CPU_SIZE_T   len_max)
+{
+    const  CPU_CHAR    *p1_str_cmp;
+    const  CPU_CHAR    *p2_str_cmp;
+    const  CPU_CHAR    *p1_str_cmp_next;
+    const  CPU_CHAR    *p2_str_cmp_next;
+           CPU_INT16S   cmp_val;
+           CPU_SIZE_T   cmp_len;
+
+
+    if (len_max < 1) {                                          /* If cmp len = 0,        rtn 0       (see Note #3d1A). */
+        return (0);
+    }
+
+    if (p1_str == (const CPU_CHAR *)0) {
+        if (p2_str == (const CPU_CHAR *)0) {
+            return (0);                                         /* If BOTH str ptrs NULL, rtn 0       (see Note #3a1A). */
+        }
+        cmp_val = (CPU_INT16S)((CPU_INT16S)0 - (CPU_INT16S)(*p2_str));
+        return (cmp_val);                                       /* If p1_str NULL, rtn neg p2_str val (see Note #3a1B1).*/
+    }
+    if (p2_str == (const CPU_CHAR *)0) {
+        cmp_val = (CPU_INT16S)(*p1_str);
+        return (cmp_val);                                       /* If p2_str NULL, rtn pos p1_str val (see Note #3a1B2).*/
+    }
+
+
+    p1_str_cmp      = p1_str;
+    p2_str_cmp      = p2_str;
+    p1_str_cmp_next = p1_str_cmp;
+    p2_str_cmp_next = p2_str_cmp;
+    p1_str_cmp_next++;
+    p2_str_cmp_next++;
+    cmp_len         = 0u;
+
+    while ((*p1_str_cmp      == *p2_str_cmp)            &&      /* Cmp strs until non-matching chars (see Note #3c) ... */
+           (*p1_str_cmp      != (      CPU_CHAR  )'\0') &&      /* ... or NULL chars                 (see Note #3b) ... */
+           ( p1_str_cmp_next != (const CPU_CHAR *)  0 ) &&      /* ... or NULL ptr(s) found          (see Note #3a2).   */
+           ( p2_str_cmp_next != (const CPU_CHAR *)  0 ) &&
+           ( cmp_len         <  (      CPU_SIZE_T)len_max)) {   /* ... or max nbr chars cmp'd        (see Note #3d2).   */
+        p1_str_cmp++;
+        p2_str_cmp++;
+        p1_str_cmp_next++;
+        p2_str_cmp_next++;
+        cmp_len++;
+    }
+
+
+    if (cmp_len == len_max) {                                   /* If strs     identical for max len nbr of chars, ...  */
+        return (0);                                             /* ... rtn 0                 (see Note #3d2A).          */
+    }
+
+    if (*p1_str_cmp != *p2_str_cmp) {                           /* If strs NOT identical, ...                           */
+                                                                /* ... calc & rtn char diff  (see Note #3c1).           */
+         cmp_val = (CPU_INT16S)((CPU_INT16S)(*p1_str_cmp) - (CPU_INT16S)(*p2_str_cmp));
+
+    } else if (*p1_str_cmp  == (CPU_CHAR)'\0') {                /* If NULL char(s) found, ...                           */
+         cmp_val = (CPU_INT16S)0;                               /* ... strs identical; rtn 0 (see Note #3b).            */
+
+    } else {
+        if (p1_str_cmp_next == (const CPU_CHAR *)0) {
+            if (p2_str_cmp_next == (const CPU_CHAR *)0) {       /* If BOTH next str ptrs NULL, ...                      */
+                cmp_val = (CPU_INT16S)0;                        /* ... rtn 0                       (see Note #3a2A).    */
+            } else {                                            /* If p1_str_cmp_next NULL, ...                         */
+                                                                /* ... rtn neg p2_str_cmp_next val (see Note #3a2B1).   */
+                cmp_val = (CPU_INT16S)((CPU_INT16S)0 - (CPU_INT16S)(*p2_str_cmp_next));
+            }
+        } else {                                                /* If p2_str_cmp_next NULL, ...                         */
+            cmp_val = (CPU_INT16S)(*p1_str_cmp_next);           /* ... rtn pos p1_str_cmp_next val (see Note #3a2B2).   */
+        }
+    }
+
+
+    return (cmp_val);
+}
+
+
+/*
+*********************************************************************************************************
+*                                         Str_CmpIgnoreCase()
+*
+* Description : Determine if two strings are identical, ignoring case.
+*
+* Argument(s) : p1_str      Pointer to first  string (see Note #1).
+*
+*               p2_str      Pointer to second string (see Note #1).
+*
+* Return(s)   : 0,              if strings are identical             (see Notes #3a1A, #3a2A, & #3b).
+*
+*               Negative value, if 'p1_str' is less    than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
+*
+*               Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
+*
+*               See also Note #2b.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffers NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcasecmp() : DESCRIPTION' states that :
+*
+*                       (1) (A) "The strcasecmp() function shall compare ... the string pointed to by 's1'
+*                                ('p1_str') to the string pointed to by 's2' ('p2_str')" ...
+*                           (B) "ignoring differences in case".
+*
+*                       (2) "strcasecmp() ... shall behave as if the strings had been converted to lowercase
+*                            and then a byte comparison performed."
+*
+*                   (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strcasecmp() : RETURN VALUE' states that
+*                          "upon successful completion, strcasecmp() shall return an integer greater than,
+*                           equal to, or less than 0".
+*
+*                       (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
+*                           sign of a non-zero return value shall be determined by the sign of the difference
+*                           between the values of the first pair of bytes ... that differ in the strings
+*                           being compared".
+*
+*               (3) String comparison terminates when :
+*
+*                   (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
+*                               (1) NULL strings identical; 0 returned.
+*
+*                           (B) (1) 'p1_str' passed a NULL pointer.
+*                                   (a) Return negative value of character pointed to by 'p2_str', converted
+*                                       to lower case (see Note #2a2).
+*
+*                               (2) 'p2_str' passed a NULL pointer.
+*                                   (a) Return positive value of character pointed to by 'p1_str', converted
+*                                       to lower case (see Note #2a2).
+*
+*                       (2) (A) BOTH strings point to NULL.
+*                               (1) Strings overlap with NULL address.
+*                               (2) Strings identical up to but NOT beyond or including the NULL address;
+*                                   0 returned.
+*
+*                           (B) (1) 'p1_str_cmp_next' points to NULL.
+*                                   (a) 'p1_str' overlaps with NULL address.
+*                                   (b) Strings compared up to but NOT beyond or including the NULL address.
+*                                   (c) Return negative value of character pointed to by 'p2_str_cmp_next',
+*                                       converted to lower case (see Note #2a2).
+*
+*                               (2) 'p2_str_cmp_next' points to NULL.
+*                                   (a) 'p2_str' overlaps with NULL address.
+*                                   (b) Strings compared up to but NOT beyond or including the NULL address.
+*                                   (c) Return positive value of character pointed to by 'p1_str_cmp_next',
+*                                       converted to lower case (see Note #2a2).
+*
+*                   (b) Terminating NULL character found in both strings.
+*                       (1) Strings identical; 0 returned.
+*                       (2) Only one NULL character test required in conditional since previous condition
+*                           tested character equality.
+*
+*                   (c) Non-matching characters found.
+*                       (1) Return signed-integer difference of the character pointed to by 'p2_str',
+*                           converted to lower case, from the character pointed to by 'p1_str', converted
+*                           to lower case.
+*
+*               (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
+*                   return value, 'CPU_CHAR' native data type size MUST be 8-bit.
+*********************************************************************************************************
+*/
+
+CPU_INT16S  Str_CmpIgnoreCase (const  CPU_CHAR  *p1_str,
+                               const  CPU_CHAR  *p2_str)
+{
+    CPU_INT16S  cmp_val;
+
+
+    cmp_val = Str_CmpIgnoreCase_N(p1_str,
+                                  p2_str,
+                                  DEF_INT_CPU_U_MAX_VAL);
+
+    return (cmp_val);
+}
+
+
+/*
+*********************************************************************************************************
+*                                        Str_CmpIgnoreCase_N()
+*
+* Description : Determine if two strings are identical for up to a maximum number of characters,
+*                   ignoring case.
+*
+* Argument(s) : p1_str      Pointer to first  string (see Note #1).
+*
+*               p2_str      Pointer to second string (see Note #1).
+*
+*               len_max     Maximum number of characters to compare  (see Note  #3d).
+*
+* Return(s)   : 0,              if strings are identical             (see Notes #3a1A, #3a2A, #3b, & #3d).
+*
+*               Negative value, if 'p1_str' is less    than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
+*
+*               Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
+*
+*               See also Note #2b.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffers NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strncasecmp() : DESCRIPTION' states that :
+*
+*                       (1) (A) "The strncasecmp() function shall compare ... the string pointed to by 's1'
+*                                ('p1_str') to the string pointed to by 's2' ('p2_str')" ...
+*                           (B) "ignoring differences in case"                           ...
+*                           (C)  but "not more than 'n' ('len_max') bytes" of either string.
+*
+*                       (2) "strncasecmp() shall behave as if the strings had been converted to lowercase
+*                            and then a byte comparison performed."
+*
+*                   (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strncasecmp() : RETURN VALUE' states that
+*                          "upon successful completion, strncasecmp() shall return an integer greater than,
+*                           equal to, or less than 0".
+*
+*                       (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
+*                           sign of a non-zero return value shall be determined by the sign of the difference
+*                           between the values of the first pair of bytes ... that differ in the strings
+*                           being compared".
+*
+*               (3) String comparison terminates when :
+*
+*                   (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
+*                               (1) NULL strings identical; 0 returned.
+*
+*                           (B) (1) 'p1_str' passed a NULL pointer.
+*                                   (a) Return negative value of character pointed to by 'p2_str', converted
+*                                       to lower case (see Note #2a2).
+*
+*                               (2) 'p2_str' passed a NULL pointer.
+*                                   (a) Return positive value of character pointed to by 'p1_str', converted
+*                                       to lower case (see Note #2a2).
+*
+*                       (2) (A) BOTH strings point to NULL.
+*                               (1) Strings overlap with NULL address.
+*                               (2) Strings identical up to but NOT beyond or including the NULL address;
+*                                   0 returned.
+*
+*                           (B) (1) 'p1_str_cmp_next' points to NULL.
+*                                   (a) 'p1_str' overlaps with NULL address.
+*                                   (b) Strings compared up to but NOT beyond or including the NULL address.
+*                                   (c) Return negative value of character pointed to by 'p2_str_cmp_next',
+*                                       converted to lower case (see Note #2a2).
+*
+*                               (2) 'p2_str_cmp_next' points to NULL.
+*                                   (a) 'p2_str' overlaps with NULL address.
+*                                   (b) Strings compared up to but NOT beyond or including the NULL address.
+*                                   (c) Return positive value of character pointed to by 'p1_str_cmp_next',
+*                                       converted to lower case (see Note #2a2).
+*
+*                   (b) Terminating NULL character found in both strings.
+*                       (1) Strings identical; 0 returned.
+*                       (2) Only one NULL character test required in conditional since previous condition
+*                           tested character equality.
+*
+*                   (c) Non-matching characters found.
+*                       (1) Return signed-integer difference of the character pointed to by 'p2_str',
+*                           converted to lower case, from the character pointed to by 'p1_str', converted
+*                           to lower case.
+*
+*                   (d) (1) 'len_max' passed a zero length.
+*                           (A) Zero-length strings identical; 0 returned.
+*
+*                       (2) First 'len_max' number of characters identical.
+*                           (A) Strings identical; 0 returned.
+*
+*                       See also Note #2a1C.
+*$PAGE*
+*               (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
+*                   return value, 'CPU_CHAR' native data type size MUST be 8-bit.
+*********************************************************************************************************
+*/
+
+CPU_INT16S  Str_CmpIgnoreCase_N (const  CPU_CHAR    *p1_str,
+                                 const  CPU_CHAR    *p2_str,
+                                        CPU_SIZE_T   len_max)
+{
+    const  CPU_CHAR    *p1_str_cmp;
+    const  CPU_CHAR    *p2_str_cmp;
+    const  CPU_CHAR    *p1_str_cmp_next;
+    const  CPU_CHAR    *p2_str_cmp_next;
+           CPU_CHAR     char_1;
+           CPU_CHAR     char_2;
+           CPU_INT16S   cmp_val;
+           CPU_SIZE_T   cmp_len;
+
+
+    if (len_max < 1) {                                          /* If cmp len = 0,        rtn 0       (see Note #3d1A). */
+        return (0);
+    }
+
+    if (p1_str == (const CPU_CHAR *)0) {
+        if (p2_str == (const CPU_CHAR *)0) {
+            return (0);                                         /* If BOTH str ptrs NULL, rtn 0       (see Note #3a1A). */
+        }
+        char_2  =  ASCII_ToLower(*p2_str);
+        cmp_val = (CPU_INT16S)((CPU_INT16S)0 - (CPU_INT16S)char_2);
+        return (cmp_val);                                       /* If p1_str NULL, rtn neg p2_str val (see Note #3a1B1).*/
+    }
+    if (p2_str == (const CPU_CHAR *)0) {
+        char_1  =  ASCII_ToLower(*p1_str);
+        cmp_val = (CPU_INT16S)char_1;
+        return (cmp_val);                                       /* If p2_str NULL, rtn pos p1_str val (see Note #3a1B2).*/
+    }
+
+
+    p1_str_cmp      = p1_str;
+    p2_str_cmp      = p2_str;
+    p1_str_cmp_next = p1_str_cmp;
+    p2_str_cmp_next = p2_str_cmp;
+    p1_str_cmp_next++;
+    p2_str_cmp_next++;
+    char_1          = ASCII_ToLower(*p1_str_cmp);
+    char_2          = ASCII_ToLower(*p2_str_cmp);
+    cmp_len         = 0u;
+
+    while (( char_1          ==  char_2)                &&      /* Cmp strs until non-matching chars (see Note #3c) ... */
+           (*p1_str_cmp      != (      CPU_CHAR  )'\0') &&      /* ... or NULL chars                 (see Note #3b) ... */
+           ( p1_str_cmp_next != (const CPU_CHAR *)  0 ) &&      /* ... or NULL ptr(s) found          (see Note #3a2).   */
+           ( p2_str_cmp_next != (const CPU_CHAR *)  0 ) &&
+           ( cmp_len         <  (      CPU_SIZE_T)len_max)) {   /* ... or max nbr chars cmp'd        (see Note #3d2).   */
+        p1_str_cmp++;
+        p2_str_cmp++;
+        p1_str_cmp_next++;
+        p2_str_cmp_next++;
+        cmp_len++;
+        char_1 = ASCII_ToLower(*p1_str_cmp);
+        char_2 = ASCII_ToLower(*p2_str_cmp);
+    }
+
+
+    if (cmp_len == len_max) {                                   /* If strs     identical for max len nbr of chars, ...  */
+        return (0);                                             /* ... rtn 0                 (see Note #3d2A).          */
+    }
+
+    if (char_1 != char_2) {                                     /* If strs NOT identical, ...                           */
+                                                                /* ... calc & rtn char diff  (see Note #3c1).           */
+         cmp_val = (CPU_INT16S)((CPU_INT16S)char_1 - (CPU_INT16S)char_2);
+
+    } else if (char_1 == (CPU_CHAR)'\0') {                      /* If NULL char(s) found, ...                           */
+         cmp_val = (CPU_INT16S)0;                               /* ... strs identical; rtn 0 (see Note #3b).            */
+
+    } else {
+        if (p1_str_cmp_next == (const CPU_CHAR *)0) {
+            if (p2_str_cmp_next == (const CPU_CHAR *)0) {       /* If BOTH next str ptrs NULL, ...                      */
+                cmp_val = (CPU_INT16S)0;                        /* ... rtn 0                       (see Note #3a2A).    */
+            } else {                                            /* If p1_str_cmp_next NULL, ...                         */
+                char_2  =  ASCII_ToLower(*p2_str_cmp_next);
+                                                                /* ... rtn neg p2_str_cmp_next val (see Note #3a2B1).   */
+                cmp_val = (CPU_INT16S)((CPU_INT16S)0 - (CPU_INT16S)char_2);
+            }
+        } else {                                                /* If p2_str_cmp_next NULL, ...                         */
+            char_1  =  ASCII_ToLower(*p1_str_cmp_next);
+            cmp_val = (CPU_INT16S)char_1;                       /* ... rtn pos p1_str_cmp_next val (see Note #3a2B2).   */
+        }
+    }
+
+
+    return (cmp_val);
+}
+
+
+/*
+*********************************************************************************************************
+*                                             Str_Char()
+*
+* Description : Search string for first occurrence of specific character.
+*
+* Argument(s) : pstr            Pointer to string (see Note #1).
+*
+*               srch_char       Search character.
+*
+* Return(s)   : Pointer to first occurrence of search character in string, if any    (see Note #2b1).
+*
+*               Pointer to NULL,                                           otherwise (see Note #2b2).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : DESCRIPTION' states that :
+*
+*                       (1) "The strchr() function shall locate the first occurrence of 'c' ('srch_char')
+*                            ... in the string pointed to by 's' ('pstr')."
+*                       (2) "The terminating null byte is considered to be part of the string."
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : RETURN VALUE' states that
+*                       "upon completion, strchr() shall return" :
+*
+*                       (1) "a pointer to the byte," ...
+*                       (2) "or a null pointer if the byte was not found."
+*                           (A) #### Although NO strchr() specification states to return NULL for
+*                               any other reason(s), NULL is also returned for any error(s).
+*
+*               (3) String search terminates when :
+*
+*                   (a) String pointer passed a NULL pointer.
+*                       (1) No string search performed; NULL pointer returned.
+*
+*                   (b) String pointer points to NULL.
+*                       (1) String overlaps with NULL address; NULL pointer returned.
+*
+*                   (c) String's terminating NULL character found.
+*                       (1) Search character NOT found in search string; NULL pointer returned
+*                           (see Note #2b2).
+*                       (2) Applicable even if search character is the terminating NULL character
+*                           (see Note #2a2).
+*
+*                   (d) Search character found.
+*                       (1) Return pointer to first occurrence of search character in search string
+*                           (see Note #2a1).
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Char (const  CPU_CHAR  *pstr,
+                            CPU_CHAR   srch_char)
+{
+    CPU_CHAR  *pstr_rtn;
+
+
+    pstr_rtn = Str_Char_N(pstr,
+                          DEF_INT_CPU_U_MAX_VAL,
+                          srch_char);
+
+    return (pstr_rtn);
+}
+
+
+/*
+*********************************************************************************************************
+*                                            Str_Char_N()
+*
+* Description : Search string for first occurrence of specific character, up to a maximum number
+*                   of characters.
+*
+* Argument(s) : pstr            Pointer to string (see Note #1).
+*
+*               len_max         Maximum number of characters to search (see Notes #2c & #3e).
+*
+*               srch_char       Search character.
+*
+* Return(s)   : Pointer to first occurrence of search character in string, if any    (see Note #2b1).
+*
+*               Pointer to NULL,                                           otherwise (see Note #2b2).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : DESCRIPTION' states that :
+*
+*                       (1) "The strchr() function shall locate the first occurrence of 'c' ('srch_char')
+*                            ... in the string pointed to by 's' ('pstr')."
+*                       (2) "The terminating null byte is considered to be part of the string."
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : RETURN VALUE' states that
+*                       "upon completion, strchr() shall return" :
+*
+*                       (1) "a pointer to the byte," ...
+*                       (2) "or a null pointer if the byte was not found."
+*                           (A) #### Although NO strchr() specification states to return NULL for
+*                               any other reason(s), NULL is also returned for any error(s).
+*
+*                   (c) Ideally, the 'len_max' argument would be the last argument in this function's
+*                       argument list for consistency with all other custom string library functions.
+*                       However, the 'len_max' argument is sequentially ordered as the second argument
+*                       to comply with most standard library's strnchr() argument list.
+*
+*               (3) String search terminates when :
+*
+*                   (a) String pointer passed a NULL pointer.
+*                       (1) No string search performed; NULL pointer returned.
+*
+*                   (b) String pointer points to NULL.
+*                       (1) String overlaps with NULL address; NULL pointer returned.
+*
+*                   (c) String's terminating NULL character found.
+*                       (1) Search character NOT found in search string; NULL pointer returned
+*                           (see Note #2b2).
+*                       (2) Applicable even if search character is the terminating NULL character
+*                           (see Note #2a2).
+*
+*                   (d) Search character found.
+*                       (1) Return pointer to first occurrence of search character in search string
+*                           (see Note #2a1).
+*
+*                   (e) 'len_max' number of characters searched.
+*                       (1) Search character NOT found in search string within first 'len_max' number
+*                           of characters; NULL pointer returned.
+*                       (2) 'len_max' number of characters MAY include terminating NULL character
+*                           (see Note #2a2).
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Char_N (const  CPU_CHAR    *pstr,
+                              CPU_SIZE_T   len_max,
+                              CPU_CHAR     srch_char)
+{
+    const  CPU_CHAR    *pstr_char;
+           CPU_SIZE_T   len_srch;
+
+
+    if (pstr == (const CPU_CHAR *)0) {                          /* Rtn NULL if srch str ptr NULL (see Note #3a1).       */
+        return ((CPU_CHAR *)0);
+    }
+
+    if (len_max < 1) {                                          /* Rtn NULL if srch len = 0      (see Note #3e1).       */
+        return ((CPU_CHAR *)0);
+    }
+
+
+    pstr_char = pstr;
+    len_srch  = 0u;
+
+    while (( pstr_char != (const CPU_CHAR *)  0 )      &&       /* Srch str until NULL ptr     [see Note #3b]  ...      */
+           (*pstr_char != (      CPU_CHAR  )'\0')      &&       /* ... or NULL char            (see Note #3c)  ...      */
+           (*pstr_char != (      CPU_CHAR  )srch_char) &&       /* ... or srch char found      (see Note #3d); ...      */
+           ( len_srch  <  (      CPU_SIZE_T)len_max)) {         /* ... or max nbr chars srch'd (see Note #3e).          */
+        pstr_char++;
+        len_srch++;
+    }
+
+
+    if (pstr_char == (const CPU_CHAR *)0) {                     /* Rtn NULL if NULL ptr found      (see Note #3b1).     */
+        return ((CPU_CHAR *)0);
+    }
+
+    if (len_srch >= len_max) {                                  /* Rtn NULL if srch char NOT found ...                  */
+        return ((CPU_CHAR *)0);                                 /* ... within max nbr of chars     (see Note #3e1).     */
+    }
+
+    if (*pstr_char != srch_char) {                              /* Rtn NULL if srch char NOT found (see Note #3c1).     */
+         return ((CPU_CHAR *)0);
+    }
+
+
+    return ((CPU_CHAR *)pstr_char);                             /* Else rtn ptr to found srch char (see Note #3d1).     */
+}
+
+
+/*
+*********************************************************************************************************
+*                                           Str_Char_Last()
+*
+* Description : Search string for last occurrence of specific character.
+*
+* Argument(s) : pstr            Pointer to string (see Note #1).
+*
+*               srch_char       Search character.
+*
+* Return(s)   : Pointer to last occurrence of search character in string, if any    (see Note #2b1).
+*
+*               Pointer to NULL,                                          otherwise (see Note #2b2).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : DESCRIPTION' states that :
+*
+*                       (1) "The strrchr() function shall locate the last occurrence of 'c' ('srch_char')
+*                            ... in the string pointed to by 's' ('pstr')."
+*                       (2) "The terminating null byte is considered to be part of the string."
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : RETURN VALUE' states that
+*                       "upon successful completion, strrchr() shall return" :
+*
+*                       (1) "a pointer to the byte" ...
+*                       (2) "or a null pointer if 'c' ('srch_char') does not occur in the string."
+*                           (A) #### Although NO strrchr() specification states to return NULL for
+*                               any other reason(s), NULL is also returned for any error(s).
+*
+*               (3) String search terminates when :
+*
+*                   (a) String pointer passed a NULL pointer.
+*                       (1) No string search performed; NULL pointer returned.
+*
+*                   (b) String pointer points to NULL.
+*                       (1) String overlaps with NULL address; NULL pointer returned.
+*
+*                   (c) String searched from end to beginning.
+*                       (1) Search character NOT found in search string; NULL pointer returned.
+*                       (2) Applicable even if search character is the terminating NULL character
+*                           (see Note #2a2).
+*
+*                   (d) Search character found.
+*                       (1) Return pointer to last occurrence of search character in search string
+*                           (see Note #2a1).
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Char_Last (const  CPU_CHAR  *pstr,
+                                 CPU_CHAR   srch_char)
+{
+    CPU_CHAR  *pstr_rtn;
+
+
+    pstr_rtn = Str_Char_Last_N(pstr,
+                               DEF_INT_CPU_U_MAX_VAL,
+                               srch_char);
+
+    return (pstr_rtn);
+}
+
+
+/*
+*********************************************************************************************************
+*                                          Str_Char_Last_N()
+*
+* Description : Search string for last occurrence of specific character, up to a maximum number
+*                   of characters.
+*
+* Argument(s) : pstr            Pointer to string (see Note #1).
+*
+*               len_max         Maximum number of characters to search (see Notes #2c & #3e).
+*
+*               srch_char       Search character.
+*
+* Return(s)   : Pointer to last occurrence of search character in string, if any    (see Note #2b1).
+*
+*               Pointer to NULL,                                          otherwise (see Note #2b2).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : DESCRIPTION' states that :
+*
+*                       (1) "The strrchr() function shall locate the last occurrence of 'c' ('srch_char')
+*                            ... in the string pointed to by 's' ('pstr')."
+*                       (2) "The terminating null byte is considered to be part of the string."
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : RETURN VALUE' states that
+*                       "upon successful completion, strrchr() shall return" :
+*
+*                       (1) "a pointer to the byte" ...
+*                       (2) "or a null pointer if 'c' ('srch_char') does not occur in the string."
+*                           (A) #### Although NO strrchr() specification states to return NULL for
+*                               any other reason(s), NULL is also returned for any error(s).
+*
+*                   (c) Ideally, the 'len_max' argument would be the last argument in this function's
+*                       argument list for consistency with all other custom string library functions.
+*                       However, the 'len_max' argument is sequentially ordered as the second argument
+*                       to comply with most standard library's strnrchr() argument list.
+*
+*                       See also 'Str_Char_N()  Note #2c'.
+*
+*               (3) String search terminates when :
+*
+*                   (a) String pointer passed a NULL pointer.
+*                       (1) No string search performed; NULL pointer returned.
+*
+*                   (b) String pointer points to NULL.
+*                       (1) String overlaps with NULL address; NULL pointer returned.
+*
+*                   (c) String searched from end to beginning.
+*                       (1) Search character NOT found in search string; NULL pointer returned
+*                           (see Note #2b2).
+*                       (2) Applicable even if search character is the terminating NULL character
+*                           (see Note #2a2).
+*
+*                   (d) Search character found.
+*                       (1) Return pointer to last occurrence of search character in search string
+*                           (see Note #2a1).
+*
+*                   (e) 'len_max' number of characters searched.
+*                       (1) Search character NOT found in search string within last 'len_max' number
+*                           of characters; NULL pointer returned.
+*                       (2) 'len_max' number of characters MAY include terminating NULL character
+*                           (see Note #2a2).
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Char_Last_N (const  CPU_CHAR    *pstr,
+                                   CPU_SIZE_T   len_max,
+                                   CPU_CHAR     srch_char)
+{
+    const  CPU_CHAR    *pstr_char;
+           CPU_SIZE_T   str_len_max;
+           CPU_SIZE_T   str_len;
+
+
+    if (pstr == (const CPU_CHAR *)0) {                          /* Rtn NULL if srch str ptr NULL (see Note #3a1).       */
+        return ((CPU_CHAR *)0);
+    }
+
+    if (len_max < 1) {                                          /* Rtn NULL if srch len = 0      (see Note #3e1).       */
+        return ((CPU_CHAR *)0);
+    }
+
+
+    pstr_char    = pstr;
+     str_len_max = len_max - sizeof((CPU_CHAR)'\0');            /* Str len adj'd for NULL char len.                     */
+     str_len     = Str_Len_N(pstr_char, str_len_max);
+    pstr_char   += str_len;
+
+    if (pstr_char == (const CPU_CHAR *)0) {                     /* Rtn NULL if NULL ptr found        (see Note #3b1).   */
+        return ((CPU_CHAR *)0);
+    }
+
+    while (( pstr_char != pstr) &&                              /* Srch str from end until beginning (see Note #3c) ... */
+           (*pstr_char != srch_char)) {                         /* ... until srch char found         (see Note #3d).    */
+        pstr_char--;
+    }
+
+
+    if (*pstr_char != srch_char) {                              /* Rtn NULL if srch char NOT found   (see Note #3c1).   */
+         return ((CPU_CHAR *)0);
+    }
+
+
+    return ((CPU_CHAR *)pstr_char);                             /* Else rtn ptr to found srch char   (see Note #3d1).   */
+}
+
+
+/*
+*********************************************************************************************************
+*                                         Str_Char_Replace()
+*
+* Description : Search string for specific character and replace it by another specific character.
+*
+* Argument(s) : pstr            Pointer to string (see Note #1).
+*
+*               char_srch       Search character.
+*
+*               char_replace    Replace character.
+*
+* Return(s)   : Pointer to string, if NO error(s).
+*
+*               Pointer to NULL,   otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffer modified.
+*
+*               (2) String search terminates when :
+*
+*                   (a) String pointer passed a NULL pointer.
+*                       (1) No string search performed; NULL pointer returned.
+*
+*                   (b) String pointer points to NULL.
+*                       (1) String overlaps with NULL address; NULL pointer returned.
+*
+*                   (c) String's terminating NULL character found.
+*                       (1) Search character NOT found in search string; NULL pointer returned
+*                       (2) Applicable even if search character is the terminating NULL character
+*
+*                   (d) Search character found.
+*                       (1) Replace character found by the specified character.
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Char_Replace (CPU_CHAR  *pstr,
+                             CPU_CHAR   char_srch,
+                             CPU_CHAR   char_replace)
+{
+    CPU_CHAR  *pstr_rtn;
+
+
+    pstr_rtn = Str_Char_Replace_N(pstr,
+                                  char_srch,
+                                  char_replace,
+                                  DEF_INT_CPU_U_MAX_VAL);
+
+    return (pstr_rtn);
+}
+
+
+/*
+*********************************************************************************************************
+*                                        Str_Char_Replace_N()
+*
+* Description : Search string for specific character and replace it by another specific character, up to
+*               a maximum number of characters.
+*
+* Argument(s) : pstr            Pointer to string (see Note #1).
+*
+*               char_srch       Search character.
+*
+*               char_replace    Replace character.
+*
+*               len_max         Maximum number of characters to search (see Notes #2c & #3e).
+*
+* Return(s)   : Pointer to string, if NO error(s).
+*
+*               Pointer to NULL,   otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffer modified.
+*
+*               (2) String search terminates when :
+*
+*                   (a) String pointer passed a NULL pointer.
+*                       (1) No string search performed; NULL pointer returned.
+*
+*                   (b) String pointer points to NULL.
+*                       (1) String overlaps with NULL address; NULL pointer returned.
+*
+*                   (c) String's terminating NULL character found.
+*                       (1) Search character NOT found in search string; NULL pointer returned
+*                       (2) Applicable even if search character is the terminating NULL character
+*
+*                   (d) Search character found.
+*                       (1) Replace character found by the specified character.
+*
+*                   (e) 'len_max' number of characters searched.
+*                       (1) Search character NOT found in search string within first 'len_max' number
+*                           of characters; NULL pointer returned.
+*                       (2) 'len_max' number of characters MAY include terminating NULL character
+*                           (see Note #2a2).
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Char_Replace_N (CPU_CHAR    *pstr,
+                               CPU_CHAR     char_srch,
+                               CPU_CHAR     char_replace,
+                               CPU_SIZE_T   len_max)
+{
+    CPU_CHAR    *pstr_char;
+    CPU_SIZE_T   len;
+
+
+    if (pstr == (const CPU_CHAR *)0) {                          /* Rtn NULL if srch str ptr NULL (see Note #2a1).       */
+        return ((CPU_CHAR *)0);
+    }
+
+    if (len_max < 1) {                                          /* Rtn NULL if srch len = 0      (see Note #2e1).       */
+        return ((CPU_CHAR *)0);
+    }
+
+    pstr_char = pstr;
+    len       = len_max;
+
+    while (( pstr_char != (const CPU_CHAR *)0) &&               /* Srch str until NULL ptr     [see Note #2b]  ...      */
+           (*pstr_char !=  ASCII_CHAR_NULL   ) &&               /* ... or NULL char            (see Note #2c)  ...      */
+           ( len        >                   0)) {               /* ... or max nbr chars srch'd (see Note #2e).          */
+
+        if (*pstr_char == char_srch) {
+            *pstr_char  = char_replace;                         /* Replace char if srch char is found.                  */
+        }
+
+        pstr_char++;
+        len--;
+    }
+
+    return (pstr);
+}
+
+
+/*
+*********************************************************************************************************
+*                                              Str_Str()
+*
+* Description : Search string for first occurence of a specific search string.
+*
+* Argument(s) : pstr            Pointer to        string (see Note #1).
+*
+*               pstr_srch       Pointer to search string (see Note #1).
+*
+* Return(s)   : Pointer to first occurrence of search string in string, if any                (see Note #2b1A).
+*
+*               Pointer to string,                                      if NULL search string (see Note #2b2).
+*
+*               Pointer to NULL,                                        otherwise             (see Note #2b1B).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffers NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : DESCRIPTION' states that :
+*
+*                       (1) "The strstr() function shall locate the first occurrence  in the string
+*                            pointed to by 's1' ('pstr') of the sequence of bytes ... in the string
+*                            pointed to by 's2' ('pstr_srch')" ...
+*                       (2) "(excluding the terminating null byte)."
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : RETURN VALUE' states that :
+*
+*                       (1) "Upon successful completion, strstr() shall return" :
+*                           (A) "a pointer to the located string" ...
+*                           (B) "or a null pointer if the string is not found."
+*                               (1) #### Although NO strstr() specification states to return NULL for
+*                                   any other reason(s), NULL is also returned for any error(s).
+*
+*                       (2) "If 's2' ('pstr_srch') points to a string with zero length, the function
+*                            shall return 's1' ('pstr')."
+*
+*               (3) String search terminates when :
+*
+*                   (a) String pointer(s) are passed NULL pointers.
+*                       (1) No string search performed; NULL pointer returned.
+*
+*                   (b) String pointer(s) point to NULL.
+*                       (1) String buffer(s) overlap with NULL address; NULL pointer returned.
+*
+*                   (c) Search string length equal to zero.
+*                       (1) No string search performed; string pointer returned (see Note #2b2).
+*
+*                   (d) Search string length greater than string length.
+*                       (1) No string search performed; NULL   pointer returned (see Note #2b1B).
+*
+*                   (e) Entire string has been searched.
+*                       (1) Search string not found; NULL pointer returned (see Note #2b1B).
+*
+*                   (f) Search string found.
+*                       (1) Return pointer to first occurrence of search string in string (see Note #2b1A).
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Str (const  CPU_CHAR  *pstr,
+                    const  CPU_CHAR  *pstr_srch)
+{
+    CPU_CHAR  *pstr_rtn;
+
+
+    pstr_rtn = Str_Str_N(pstr,
+                         pstr_srch,
+                         DEF_INT_CPU_U_MAX_VAL);
+
+    return (pstr_rtn);
+}
+
+
+/*
+*********************************************************************************************************
+*                                             Str_Str_N()
+*
+* Description : Search string for first occurence of a specific search string, up to a maximum number
+*                   of characters.
+*
+* Argument(s) : pstr            Pointer to        string (see Note #1).
+*
+*               pstr_srch       Pointer to search string (see Note #1).
+*
+*               len_max         Maximum number of characters to search (see Note #3g).
+*
+* Return(s)   : Pointer to first occurrence of search string in string, if any                (see Note #2b1A).
+*
+*               Pointer to string,                                      if NULL search string (see Note #2b2).
+*
+*               Pointer to NULL,                                        otherwise             (see Note #2b1B).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffers NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : DESCRIPTION' states that :
+*
+*                       (1) "The strstr() function shall locate the first occurrence  in the string
+*                            pointed to by 's1' ('pstr') of the sequence of bytes ... in the string
+*                            pointed to by 's2' ('pstr_srch')" ...
+*                       (2) "(excluding the terminating null byte)."
+*
+*                   (b) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : RETURN VALUE' states that :
+*
+*                       (1) "Upon successful completion, strstr() shall return" :
+*                           (A) "a pointer to the located string" ...
+*                           (B) "or a null pointer if the string is not found."
+*                               (1) #### Although NO strstr() specification states to return NULL for
+*                                   any other reason(s), NULL is also returned for any error(s).
+*
+*                       (2) "If 's2' ('pstr_srch') points to a string with zero length, the function
+*                            shall return 's1' ('pstr')."
+*
+*               (3) String search terminates when :
+*
+*                   (a) String pointer(s) are passed NULL pointers.
+*                       (1) No string search performed; NULL pointer returned.
+*
+*                   (b) String pointer(s) point to NULL.
+*                       (1) String buffer(s) overlap with NULL address; NULL pointer returned.
+*
+*                   (c) Search string length equal to zero.
+*                       (1) No string search performed; string pointer returned (see Note #2b2).
+*
+*                   (d) Search string length greater than string length.
+*                       (1) No string search performed; NULL   pointer returned (see Note #2b1B).
+*
+*                   (e) Entire string has been searched.
+*                       (1) Search string not found; NULL pointer returned (see Note #2b1B).
+*                       (2) Maximum size of the search is defined as the subtraction of the
+*                           search string length from the string length.
+*
+*                   (f) Search string found.
+*                       (1) Return pointer to first occurrence of search string in string (see Note #2b1A).
+*                       (2) Search string found via Str_Cmp_N().
+*
+*                   (g) 'len_max' number of characters searched.
+*                       (1) 'len_max' number of characters does NOT include terminating NULL character
+*                           (see Note #2a2).
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_Str_N (const  CPU_CHAR    *pstr,
+                      const  CPU_CHAR    *pstr_srch,
+                             CPU_SIZE_T   len_max)
+{
+           CPU_SIZE_T    str_len;
+           CPU_SIZE_T    str_len_srch;
+           CPU_SIZE_T    len_max_srch;
+           CPU_SIZE_T    srch_len;
+           CPU_SIZE_T    srch_ix;
+           CPU_BOOLEAN   srch_done;
+           CPU_INT16S    srch_cmp;
+    const  CPU_CHAR     *pstr_str;
+    const  CPU_CHAR     *pstr_srch_ix;
+
+                                                                /* Rtn NULL if str ptr(s) NULL (see Note #3a).          */
+    if (pstr == (const CPU_CHAR *)0) {
+        return ((CPU_CHAR *)0);
+    }
+    if (pstr_srch == (const CPU_CHAR *)0) {
+        return ((CPU_CHAR *)0);
+    }
+
+    if (len_max < 1) {                                          /* Rtn NULL if srch len = 0    (see Note #3g).          */
+        return ((CPU_CHAR *)0);
+    }
+
+                                                                /* Lim max srch str len (to chk > str len).             */
+    len_max_srch = (len_max <       DEF_INT_CPU_U_MAX_VAL)
+                 ? (len_max + 1u) : DEF_INT_CPU_U_MAX_VAL;
+
+    str_len      = Str_Len_N(pstr,      len_max);
+    str_len_srch = Str_Len_N(pstr_srch, len_max_srch);
+    if (str_len_srch < 1) {                                     /* Rtn ptr to str if srch str len = 0 (see Note #2b2).  */
+        return ((CPU_CHAR *)pstr);
+    }
+    if (str_len_srch > str_len) {                               /* Rtn NULL if srch str len > str len (see Note #3d).   */
+        return ((CPU_CHAR *)0);
+    }
+                                                                /* Rtn NULL if NULL ptr found         (see Note #3b1).  */
+    pstr_str = pstr      + str_len;
+    if (pstr_str == (const CPU_CHAR *)0) {
+        return ((CPU_CHAR *)0);
+    }
+    pstr_str = pstr_srch + str_len_srch;
+    if (pstr_str == (const CPU_CHAR *)0) {
+        return ((CPU_CHAR *)0);
+    }
+
+
+    srch_len  = str_len - str_len_srch;                         /* Calc srch len (see Note #3e2).                       */
+    srch_ix   = 0u;
+    srch_done = DEF_NO;
+
+    do {
+        pstr_srch_ix = (const CPU_CHAR *)(pstr + srch_ix);
+        srch_cmp     =  Str_Cmp_N(pstr_srch_ix, pstr_srch, str_len_srch);
+        srch_done    = (srch_cmp == 0) ? DEF_YES : DEF_NO;
+        srch_ix++;
+    } while ((srch_done == DEF_NO) && (srch_ix <= srch_len));
+
+
+    if (srch_cmp != 0) {                                        /* Rtn NULL if srch str NOT found (see Note #3e2).      */
+        return ((CPU_CHAR *)0);
+    }
+
+    return ((CPU_CHAR *)pstr_srch_ix);                          /* Else rtn ptr to found srch str (see Note #3f1).      */
+}
+
+
+/*
+*********************************************************************************************************
+*                                         Str_FmtNbr_Int32U()
+*
+* Description : Format 32-bit unsigned integer into a multi-digit character string.
+*
+* Argument(s) : nbr             Number           to format.
+*
+*               nbr_dig         Number of digits to format (see Note #1).
+*
+*                               The following may be used to specify the number of digits to format :
+*
+*                                   DEF_INT_32U_NBR_DIG_MIN     Minimum number of 32-bit unsigned digits
+*                                   DEF_INT_32U_NBR_DIG_MAX     Maximum number of 32-bit unsigned digits
+*
+*               nbr_base        Base   of number to format (see Note #2).
+*
+*                               The following may be used to specify the number base :
+*
+*                                   DEF_NBR_BASE_BIN            Base  2
+*                                   DEF_NBR_BASE_OCT            Base  8
+*                                   DEF_NBR_BASE_DEC            Base 10
+*                                   DEF_NBR_BASE_HEX            Base 16
+*
+*               lead_char       Prepend leading character  (see Note #3) :
+*
+*                                   '\0'                    Do NOT prepend leading character to string.
+*                                     Printable character          Prepend leading character to string.
+*                                   Unprintable character   Format invalid string (see Note #6).
+*
+*               lower_case      Format alphabetic characters (if any) in lower case :
+*
+*                                   DEF_NO          Format alphabetic characters in upper case.
+*                                   DEF_YES         Format alphabetic characters in lower case.
+*
+*               nul             Append terminating NULL-character (see Note #4) :
+*
+*                                   DEF_NO          Do NOT append terminating NULL-character to string.
+*                                   DEF_YES                Append terminating NULL-character to string.
+*
+*               pstr            Pointer to character array to return formatted number string (see Note #5).
+*
+* Return(s)   : Pointer to formatted string, if NO error(s).
+*
+*               Pointer to NULL,             otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) If the number of digits to format ('nbr_dig') is zero; then NO formatting
+*                       is performed except possible NULL-termination of the string (see Note #4).
+*
+*                           Example :
+*
+*                               nbr      = 23456
+*                               nbr_dig  = 0
+*                               nbr_base = 10
+*
+*                               pstr     = ""                   See Note #6a
+*
+*                   (b) If the number of digits to format ('nbr_dig') is less than the number of
+*                       significant integer digits of the number to format ('nbr'); then an invalid
+*                       string is formatted instead of truncating any significant integer digits.
+*
+*                           Example :
+*
+*                               nbr      = 23456
+*                               nbr_dig  = 3
+*                               nbr_base = 10
+*
+*                               pstr     = "???"                See Note #6b
+*
+*               (2) The number's base MUST be between 2 & 36, inclusive.
+*$PAGE*
+*               (3) Leading character option prepends leading characters prior to the first non-zero digit.
+*
+*                   (a) (1) Leading character MUST be a printable ASCII character.
+*
+*                       (2) (A) Leading character MUST NOT be a number base digit, ...
+*                           (B) with the exception of '0'.
+*
+*                   (b) The number of leading characters is such that the total number of significant
+*                       integer digits plus the number of leading characters is equal to the requested
+*                       number of integer digits to format ('nbr_dig').
+*
+*                           Example :
+*
+*                               nbr       = 23456
+*                               nbr_dig   = 7
+*                               nbr_base  = 10
+*                               lead_char = ' '
+*
+*                               pstr      = "  23456"
+*
+*                   (c) (1) If the value of the number to format is     zero  ...
+*                       (2) ... & the number of digits to format is non-zero, ...
+*                       (3) ... but NO leading character available;           ...
+*                       (4) ... then one digit of '0' value is formatted.
+*
+*                           This is NOT a leading character; but a single integer digit of '0' value.
+*
+*               (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
+*                       array formatting.
+*
+*                   (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
+*                       terminate option DISABLED will cause character string run-on.
+*
+*               (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
+*
+*                   (b) To prevent character buffer overrun :
+*
+*                           Character array size MUST be  >=  ('nbr_dig'          +
+*                                                               1 'NUL' terminator)  characters
+*
+*               (6) For any unsuccessful string format or error(s), an invalid string of question marks
+*                   ('?') will be formatted, where the number of question marks is determined by the
+*                   number of digits to format ('nbr_dig') :
+*
+*                      Invalid string's     {  (a)   0 (NULL string)  ,  if 'nbr_dig' = 0
+*                          number of     =  {
+*                       question marks      {  (b)  'nbr_dig'         ,  if 'nbr_dig' > 0
+*
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_FmtNbr_Int32U (CPU_INT32U    nbr,
+                              CPU_INT08U    nbr_dig,
+                              CPU_INT08U    nbr_base,
+                              CPU_CHAR      lead_char,
+                              CPU_BOOLEAN   lower_case,
+                              CPU_BOOLEAN   nul,
+                              CPU_CHAR     *pstr)
+{
+    CPU_CHAR  *pstr_fmt;
+
+
+    pstr_fmt = Str_FmtNbr_Int32(nbr,                            /* Fmt unsigned int into str.                           */
+                                nbr_dig,
+                                nbr_base,
+                                DEF_NO,
+                                lead_char,
+                                lower_case,
+                                nul,
+                                pstr);
+
+    return (pstr_fmt);
+}
+
+
+/*
+*********************************************************************************************************
+*                                         Str_FmtNbr_Int32S()
+*
+* Description : Format 32-bit signed integer into a multi-digit character string.
+*
+* Argument(s) : nbr             Number           to format.
+*
+*               nbr_dig         Number of digits to format (see Note #1).
+*
+*                               The following may be used to specify the number of digits to format :
+*
+*                                   DEF_INT_32S_NBR_DIG_MIN + 1     Minimum number of 32-bit signed digits
+*                                   DEF_INT_32S_NBR_DIG_MAX + 1     Maximum number of 32-bit signed digits
+*                                                                   (plus 1 digit for possible negative sign)
+*
+*               nbr_base        Base   of number to format (see Note #2).
+*
+*                               The following may be used to specify the number base :
+*
+*                                   DEF_NBR_BASE_BIN            Base  2
+*                                   DEF_NBR_BASE_OCT            Base  8
+*                                   DEF_NBR_BASE_DEC            Base 10
+*                                   DEF_NBR_BASE_HEX            Base 16
+*
+*               lead_char       Prepend leading character  (see Note #3) :
+*
+*                                   '\0'                    Do NOT prepend leading character to string.
+*                                     Printable character          Prepend leading character to string.
+*                                   Unprintable character   Format invalid string (see Note #6).
+*
+*               lower_case      Format alphabetic characters (if any) in lower case :
+*
+*                                   DEF_NO          Format alphabetic characters in upper case.
+*                                   DEF_YES         Format alphabetic characters in lower case.
+*
+*               nul             Append terminating NULL-character (see Note #4) :
+*
+*                                   DEF_NO          Do NOT append terminating NULL-character to string.
+*                                   DEF_YES                Append terminating NULL-character to string.
+*
+*               pstr            Pointer to character array to return formatted number string (see Note #5).
+*
+* Return(s)   : Pointer to formatted string, if NO error(s).
+*
+*               Pointer to NULL,             otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) If the number of digits to format ('nbr_dig') is zero; then NO formatting
+*                       is performed except possible NULL-termination of the string (see Note #4).
+*
+*                           Example :
+*
+*                               nbr      = -23456
+*                               nbr_dig  =  0
+*                               nbr_base = 10
+*
+*                               pstr     = ""                   See Note #6a
+*
+*                   (b) If the number of digits to format ('nbr_dig') is less than the number of
+*                       significant integer digits of the number to format ('nbr'); then an invalid
+*                       string is formatted instead of truncating any significant integer digits.
+*
+*                           Example :
+*
+*                               nbr      = 23456
+*                               nbr_dig  = 3
+*                               nbr_base = 10
+*
+*                               pstr     = "???"                See Note #6b
+*
+*                   (c) If the number to format ('nbr') is negative but the number of digits to format
+*                       ('nbr_dig') is equal to the number of significant integer digits of the number
+*                       to format ('nbr'); then an invalid string is formatted instead of truncating
+*                       the negative sign.
+*
+*                           Example :
+*
+*                               nbr      = -23456
+*                               nbr_dig  =  5
+*                               nbr_base = 10
+*
+*                               pstr     = "?????"              See Note #6b
+*
+*               (2) The number's base MUST be between 2 & 36, inclusive.
+*$PAGE*
+*               (3) Leading character option prepends leading characters prior to the first non-zero digit.
+*
+*                   (a) (1) Leading character MUST be a printable ASCII character.
+*
+*                       (2) (A) Leading character MUST NOT be a number base digit, ...
+*                           (B) with the exception of '0'.
+*
+*                   (b) (1) The number of leading characters is such that the total number of significant
+*                           integer digits plus the number of leading characters plus possible negative
+*                           sign character is equal to the requested number of integer digits to format
+*                           ('nbr_dig').
+*
+*                               Examples :
+*
+*                                   nbr       = 23456
+*                                   nbr_dig   = 7
+*                                   nbr_base  = 10
+*                                   lead_char = ' '
+*
+*                                   pstr      = "  23456"
+*
+*
+*                                   nbr       = -23456
+*                                   nbr_dig   =  7
+*                                   nbr_base  = 10
+*                                   lead_char = ' '
+*
+*                                   pstr      = " -23456"
+*
+*                       (2) (A) If the number to format ('nbr') is negative AND the leading character
+*                               ('lead_char') is     a '0' digit; then the negative sign character
+*                               prefixes all leading characters prior to the formatted number.
+*
+*                                   Examples :
+*
+*                                       nbr        = -23456
+*                                       nbr_dig    =  8
+*                                       nbr_base   = 10
+*                                       lead_char  = '0'
+*
+*                                       pstr       = "-0023456"
+*
+*
+*                                       nbr        = -43981
+*                                       nbr_dig    =  8
+*                                       nbr_base   = 16
+*                                       lead_char  = '0'
+*                                       lower_case = DEF_NO
+*
+*                                       pstr       = "-000ABCD"
+*
+*                           (B) If the number to format ('nbr') is negative AND the leading character
+*                               ('lead_char') is NOT a '0' digit; then the negative sign character
+*                               immediately prefixes the most significant digit of the formatted number.
+*
+*                                   Examples :
+*
+*                                       nbr        = -23456
+*                                       nbr_dig    =  8
+*                                       nbr_base   = 10
+*                                       lead_char  = '#'
+*
+*                                       pstr       = "##-23456"
+*
+*
+*                                       nbr        = -43981
+*                                       nbr_dig    =  8
+*                                       nbr_base   = 16
+*                                       lead_char  = '#'
+*                                       lower_case = DEF_YES
+*
+*                                       pstr       = "###-abcd"
+*
+*                   (c) (1) If the value of the number to format is     zero  ...
+*                       (2) ... & the number of digits to format is non-zero, ...
+*                       (3) ... but NO leading character available;           ...
+*                       (4) ... then one digit of '0' value is formatted.
+*
+*                           This is NOT a leading character; but a single integer digit of '0' value.
+*$PAGE*
+*               (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
+*                       array formatting.
+*
+*                   (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
+*                       terminate option DISABLED will cause character string run-on.
+*
+*               (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
+*
+*                   (b) To prevent character buffer overrun :
+*
+*                           Character array size MUST be  >=  ('nbr_dig'          +
+*                                                               1 negative sign   +
+*                                                               1 'NUL' terminator)  characters
+*
+*               (6) For any unsuccessful string format or error(s), an invalid string of question marks
+*                   ('?') will be formatted, where the number of question marks is determined by the
+*                   number of digits to format ('nbr_dig') :
+*
+*                      Invalid string's     {  (a)   0 (NULL string)  ,  if 'nbr_dig' = 0
+*                          number of     =  {
+*                       question marks      {  (b)  'nbr_dig'         ,  if 'nbr_dig' > 0
+*
+*********************************************************************************************************
+*/
+
+CPU_CHAR  *Str_FmtNbr_Int32S (CPU_INT32S    nbr,
+                              CPU_INT08U    nbr_dig,
+                              CPU_INT08U    nbr_base,
+                              CPU_CHAR      lead_char,
+                              CPU_BOOLEAN   lower_case,
+                              CPU_BOOLEAN   nul,
+                              CPU_CHAR     *pstr)
+{
+    CPU_CHAR     *pstr_fmt;
+    CPU_INT32S    nbr_fmt;
+    CPU_BOOLEAN   nbr_neg;
+
+
+    if (nbr < 0) {                                              /* If nbr neg, ...                                      */
+        nbr_fmt = -nbr;                                         /* ... negate nbr.                                      */
+        nbr_neg =  DEF_YES;
+    } else {
+        nbr_fmt =  nbr;
+        nbr_neg =  DEF_NO;
+    }
+
+    pstr_fmt = Str_FmtNbr_Int32((CPU_INT32U)nbr_fmt,            /* Fmt signed int into str.                             */
+                                            nbr_dig,
+                                            nbr_base,
+                                            nbr_neg,
+                                            lead_char,
+                                            lower_case,
+                                            nul,
+                                            pstr);
+
+    return (pstr_fmt);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           Str_FmtNbr_32()
+*
+* Description : Format number into a multi-digit character string.
+*
+* Argument(s) : nbr             Number                         to format (see Note #1).
+*
+*               nbr_dig         Number of decimal       digits to format (see Note #2).
+*
+*               nbr_dp          Number of decimal point digits to format.
+*
+*               lead_char       Prepend leading character (see Note #3) :
+*
+*                                   '\0'                    Do NOT prepend leading character to string.
+*                                     Printable character          Prepend leading character to string.
+*                                   Unprintable character   Format invalid string (see Note #6d).
+*
+*               nul             Append terminating NULL-character (see Note #4) :
+*
+*                                   DEF_NO          Do NOT append terminating NULL-character to string.
+*                                   DEF_YES                Append terminating NULL-character to string.
+*
+*               pstr            Pointer to character array to return formatted number string (see Note #5).
+*
+* Return(s)   : Pointer to formatted string, if NO error(s) [see Note #6c].
+*
+*               Pointer to NULL,             otherwise.
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) (a) The maximum accuracy for 32-bit floating-point numbers :
+*
+*
+*                                 Maximum Accuracy            log [Internal-Base ^ (Number-Internal-Base-Digits)]
+*                           32-bit Floating-point Number  =  -----------------------------------------------------
+*                                                                             log [External-Base]
+*
+*                                                             log [2 ^ 24]
+*                                                         =  --------------
+*                                                               log [10]
+*
+*                                                         <  7.225  Base-10 Digits
+*
+*                               where
+*                                       Internal-Base                   Internal number base of floating-
+*                                                                           point numbers (i.e.  2)
+*                                       External-Base                   External number base of floating-
+*                                                                           point numbers (i.e. 10)
+*                                       Number-Internal-Base-Digits     Number of internal number base
+*                                                                           significant digits (i.e. 24)
+*
+*                   (b) Some CPUs' &/or compilers' floating-point implementations MAY further reduce the
+*                       maximum accuracy.
+*$PAGE*
+*               (2) (a) If the total number of digits to format ('nbr_dig + nbr_dp') is zero; then NO
+*                       formatting is performed except possible NULL-termination of the string (see Note #4).
+*
+*                           Example :
+*
+*                               nbr     = -23456.789
+*                               nbr_dig =  0
+*                               nbr_dp  =  0
+*
+*                               pstr    = ""                        See Note #7a
+*
+*                   (b) (1) If the number of digits to format ('nbr_dig') is less than the number of
+*                           significant integer digits of the number to format ('nbr'); then an invalid
+*                           string is formatted instead of truncating any significant integer digits.
+*
+*                               Example :
+*
+*                                   nbr     = 23456.789
+*                                   nbr_dig = 3
+*                                   nbr_dp  = 2
+*
+*                                   pstr    = "??????"              See Note #7d
+*
+*                       (2) If the number to format ('nbr') is negative but the number of digits to format
+*                           ('nbr_dig') is equal to the number of significant integer digits of the number
+*                           to format ('nbr'); then an invalid string is formatted instead of truncating
+*                           the negative sign.
+*
+*                               Example :
+*
+*                                   nbr     = -23456.789
+*                                   nbr_dig =  5
+*                                   nbr_dp  =  2
+*
+*                                   pstr    = "????????"            See Note #7d
+*
+*                       (3) If the number to format ('nbr') is negative but the number of significant
+*                           integer digits is zero, & the number of digits to format ('nbr_dig') is one
+*                           but the number of decimal point digits to format ('nbr_dp') is zero; then
+*                           an invalid string is formatted instead of truncating the negative sign.
+*
+*                               Example :
+*
+*                                   nbr     = -0.7895
+*                                   nbr_dig =  1
+*                                   nbr_dp  =  0
+*
+*                                   pstr    = "?"                   See Note #7d
+*
+*                       (4) (A) If the number to format ('nbr') is negative but the number of significant
+*                               integer digits is zero, & the number of digits to format ('nbr_dig') is
+*                               zero but the number of decimal point digits to format ('nbr_dp') is non-
+*                               zero; then the negative sign immediately prefixes the decimal point --
+*                               with NO decimal digits formatted, NOT even a single decimal digit of '0'.
+*
+*                                   Example :
+*
+*                                       nbr     = -0.7895
+*                                       nbr_dig =  0
+*                                       nbr_dp  =  2
+*
+*                                       pstr    = "-.78"
+*
+*                           (B) If the number to format ('nbr') is positive but the number of significant
+*                               integer digits is zero, & the number of digits to format ('nbr_dig') is
+*                               zero but the number of decimal point digits to format ('nbr_dp') is non-
+*                               zero; then a single decimal digit of '0' prefixes the decimal point.
+*
+*                               This '0' digit is used whenever a negative sign is not formatted (see
+*                               Note #2b4A) so that the formatted string's decimal point is not floating,
+*                               but fixed in the string as the 2nd character.
+*
+*                                   Example :
+*
+*                                       nbr     =  0.7895
+*                                       nbr_dig =  0
+*                                       nbr_dp  =  2
+*
+*                                       pstr    = "0.78"
+*$PAGE*
+*                   (c) (1) If the total number of digits to format ('nbr_dig + nbr_dp') is greater than ... :
+*
+*                           (A) ... the maximum accuracy of the CPU's &/or compiler's 32-bit floating-point
+*                               numbers, digits following all significantly-accurate digits of the number to
+*                               format ('nbr') will be inaccurate; ...
+*                           (B) ... the configured maximum accuracy ('LIB_STR_CFG_FP_MAX_NBR_DIG_SIG'), all
+*                               digits or decimal places following all significantly-accurate digits of the
+*                               number to format ('nbr') will be replaced & formatted with zeros ('0').
+*
+*                                   Example :
+*
+*                                       nbr                            = 123456789.012345
+*                                       nbr_dig                        = 9
+*                                       nbr_dp                         = 6
+*                                       LIB_STR_CFG_FP_MAX_NBR_DIG_SIG = 7
+*
+*                                       pstr                           = "123456700.000000"
+*
+*                       (2) Therefore, one or more least-significant digit(s) of the number to format ('nbr')
+*                           MAY be rounded & not necessarily truncated due to the inaccuracy of the CPU's
+*                           &/or compiler's floating-point implementation.
+*
+*                       See also Note #1.
+*
+*               (3) Leading character option prepends leading characters prior to the first non-zero digit.
+*
+*                   (a) (1) Leading character MUST be a printable ASCII character.
+*
+*                       (2) (A) Leading character MUST NOT be a base-10 digit, ...
+*                           (B) with the exception of '0'.
+*
+*                   (b) (1) The number of leading characters is such that the total number of significant
+*                           integer digits plus the number of leading characters plus possible negative
+*                           sign character is equal to the requested number of integer digits to format
+*                           ('nbr_dig').
+*
+*                               Examples :
+*
+*                                   nbr       = 23456.789
+*                                   nbr_dig   = 7
+*                                   nbr_dp    = 2
+*                                   lead_char = ' '
+*
+*                                   pstr      = "  23456.78"
+*
+*
+*                                   nbr       = -23456.789
+*                                   nbr_dig   =  7
+*                                   nbr_dp    =  2
+*                                   lead_char = ' '
+*
+*                                   pstr      = " -23456.78"
+*
+*                       (2) (A) If the number to format ('nbr') is negative AND the leading character
+*                               ('lead_char') is     a '0' digit; then the negative sign character
+*                               prefixes all leading characters prior to the formatted number.
+*
+*                                   Example :
+*
+*                                       nbr       = -23456.789
+*                                       nbr_dig   =  8
+*                                       nbr_dp    =  2
+*                                       lead_char = '0'
+*
+*                                       pstr      = "-0023456.78"
+*
+*                           (B) If the number to format ('nbr') is negative AND the leading character
+*                               ('lead_char') is NOT a '0' digit; then the negative sign character
+*                               immediately prefixes the most significant digit of the formatted number.
+*
+*                                   Examples :
+*
+*                                       nbr       = -23456.789
+*                                       nbr_dig   =  8
+*                                       nbr_dp    =  2
+*                                       lead_char = '#'
+*
+*                                       pstr      = "##-23456.78"
+*
+*                   (c) (1) If the integer value of the number to format is zero & ...
+*                       (2) ... the number of digits to format is greater than one ...
+*                       (3) ... OR  the number is NOT negative,                    ...
+*                       (4) ... but NO leading character available;                ...
+*                       (5) ... then one digit of '0' value is formatted.
+*
+*                           This is NOT a leading character; but a single integer digit of '0' value.
+*
+*                       See also Note #2b4B.
+*$PAGE*
+*               (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
+*                       array formatting.
+*
+*                   (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
+*                       terminate option DISABLED will cause character string run-on.
+*
+*               (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
+*
+*                   (b) To prevent character buffer overrun :
+*
+*                           Character array size MUST be  >=  ('nbr_dig'          +
+*                                                              'nbr_dp'           +
+*                                                               1 negative sign   +
+*                                                               1 decimal point   +
+*                                                               1 'NUL' terminator)  characters
+*
+*               (6) String format terminates when :
+*
+*                   (a) Format string pointer is passed a NULL pointer.
+*                       (1) No      string formatted;                NULL pointer returned.
+*
+*                   (b) Total number of digits to format ('nbr_dig + nbr_dp') is zero.
+*                       (1) NULL    string formatted (see Note #7a); NULL pointer returned.
+*
+*                   (c) Number of digits to format ('nbr_dig') is less than number of significant
+*                           integer digits of the number to format ('nbr'), including possible
+*                           negative sign.
+*                       (1) Invalid string formatted (see Note #7);  NULL pointer returned.
+*
+*                   (d) Lead character is NOT a valid, printable character (see Note #3a).
+*                       (1) Invalid string formatted (see Note #7);  NULL pointer returned.
+*
+*                   (e) Number successfully formatted into character string array.
+*
+*               (7) For any unsuccessful string format or error(s), an invalid string of question marks
+*                   ('?') will be formatted, where the number of question marks is determined by the
+*                   number of digits ('nbr_dig') & number of decimal point digits ('nbr_dp') to format :
+*
+*                                           {  (a)    0 (NULL string)          ,  if 'nbr_dig' = 0  AND
+*                                           {                                        'nbr_dp'  = 0
+*                                           {
+*                                           {  (b)   'nbr_dig'                 ,  if 'nbr_dig' > 0  AND
+*                                           {                                        'nbr_dp'  = 0
+*                      Invalid string's     {
+*                          number of     =  {  (c)  ['nbr_dp'               +  ,  if 'nbr_dig' = 0  AND
+*                       question marks      {         1 (for decimal point) +        'nbr_dp'  > 0
+*                                           {         1 (for negative sign) ]
+*                                           {
+*                                           {  (d)  ['nbr_dig'              +  ,  if 'nbr_dig' > 0  AND
+*                                           {        'nbr_dp'               +        'nbr_dp'  > 0
+*                                           {         1 (for decimal point) ]
+*
+*********************************************************************************************************
+*/
+
+#if (LIB_STR_CFG_FP_EN == DEF_ENABLED)
+CPU_CHAR  *Str_FmtNbr_32 (CPU_FP32      nbr,
+                          CPU_INT08U    nbr_dig,
+                          CPU_INT08U    nbr_dp,
+                          CPU_CHAR      lead_char,
+                          CPU_BOOLEAN   nul,
+                          CPU_CHAR     *pstr)
+{
+    CPU_CHAR     *pstr_fmt;
+    CPU_DATA      i;
+    CPU_FP32      nbr_fmt;
+    CPU_FP32      nbr_log;
+    CPU_INT32U    nbr_shiftd;
+    CPU_INT16U    nbr_dig_max;
+    CPU_INT16U    nbr_dig_sig;
+    CPU_INT08U    nbr_neg_sign;
+    CPU_INT08U    dig_val;
+    CPU_FP32      dig_exp;
+    CPU_FP32      dp_exp;
+    CPU_BOOLEAN   lead_char_dig;
+    CPU_BOOLEAN   lead_char_fmtd;
+    CPU_BOOLEAN   lead_char_0;
+    CPU_BOOLEAN   fmt_invalid;
+    CPU_BOOLEAN   print_char;
+    CPU_BOOLEAN   nbr_neg;
+    CPU_BOOLEAN   nbr_neg_fmtd;
+
+
+                                                                /* ---------------- VALIDATE FMT ARGS ----------------- */
+    if (pstr == (CPU_CHAR *)0) {                                /* Rtn NULL if str ptr NULL (see Note #6a).             */
+        return ((CPU_CHAR *)0);
+    }
+
+    dig_exp     =  1.0f;
+    fmt_invalid =  DEF_NO;
+    lead_char_0 = (lead_char == '0') ? DEF_YES : DEF_NO;        /* Chk if lead char a '0' dig (see Note #3b2).          */
+    nbr_fmt     =  0.0f;
+    nbr_neg     =  DEF_NO;
+
+    if ((nbr_dig < 1) && (nbr_dp < 1)) {                        /* If nbr digs/dps = 0, ...                             */
+        fmt_invalid = DEF_YES;                                  /* ... fmt invalid str (see Note #6b).                  */
+    }
+
+    if (lead_char != (CPU_CHAR)'\0') {
+        print_char =  ASCII_IsPrint(lead_char);
+        if (print_char != DEF_YES) {                            /* If lead char non-printable  (see Note #3a1), ...     */
+            fmt_invalid = DEF_YES;                              /* ... fmt invalid str         (see Note #6d).          */
+
+        } else if (lead_char != '0') {                          /* Chk lead char for non-0 dig.                         */
+            lead_char_dig = ASCII_IsDig(lead_char);
+            if (lead_char_dig == DEF_YES) {                     /* If  lead char     non-0 dig (see Note #3a2A), ...    */
+                fmt_invalid = DEF_YES;                          /* ... fmt invalid str         (see Note #6d).          */
+            }
+        }
+    }
+
+
+                                                                /* ----------------- PREPARE NBR FMT ------------------ */
+    pstr_fmt = pstr;
+
+    if (fmt_invalid == DEF_NO) {
+        if (nbr < 0.0f) {                                       /* If nbr neg, ...                                      */
+            nbr_fmt      = -nbr;                                /* ... negate nbr.                                      */
+            nbr_neg_sign =  1u;
+            nbr_neg      =  DEF_YES;
+        } else {
+            nbr_fmt      =  nbr;
+            nbr_neg_sign =  0u;
+            nbr_neg      =  DEF_NO;
+        }
+
+        nbr_log     = nbr_fmt;
+        nbr_dig_max = 0u;
+        while (nbr_log >= 1.0f) {                               /* While base-10 digs avail, ...                        */
+            nbr_dig_max++;                                      /* ... calc max nbr digs.                               */
+            nbr_log /= 10.0f;
+        }
+
+        if (((nbr_dig >= (nbr_dig_max + nbr_neg_sign)) ||       /* If req'd nbr digs >= (max nbr digs + neg sign)    .. */
+             (nbr_dig_max < 1))                        &&       /* .. or NO nbr digs,                                .. */
+            ((nbr_dig     > 1) ||                               /* .. but NOT [(req'd nbr dig = 1) AND               .. */
+             (nbr_dp      > 0) ||                               /* ..          (req'd nbr dp  = 0) AND               .. */
+             (nbr_neg == DEF_NO))) {                            /* ..          (      nbr neg    )]   (see Note #2b3).  */
+                                                                /* .. prepare nbr digs to fmt.                          */
+            for (i = 1u; i < nbr_dig; i++) {
+                dig_exp *= 10.0f;
+            }
+
+            nbr_neg_fmtd   =  DEF_NO;
+            nbr_dig_sig    =  0u;
+            lead_char_fmtd =  DEF_NO;
+        } else {                                                /* Else if nbr trunc'd, ...                             */
+            fmt_invalid = DEF_YES;                              /* ... fmt invalid str (see Note #6c).                  */
+        }
+    }
+
+
+                                                                /* ------------------- FMT NBR STR -------------------- */
+    for (i = nbr_dig; i > 0; i--) {                             /* Fmt str for desired nbr digs :                       */
+        if (fmt_invalid == DEF_NO) {
+            if (nbr_dig_sig < LIB_STR_CFG_FP_MAX_NBR_DIG_SIG) { /* If nbr sig digs < max, fmt str digs;           ...   */
+                nbr_shiftd = (CPU_INT32U)(nbr_fmt / dig_exp);
+                if ((nbr_shiftd > 0) ||                         /* If shifted nbr > 0                          ...      */
+                    (i == 1u)) {                                /* ... OR on one's dig to fmt (see Note #3c1), ...      */
+                                                                /* ... calc & fmt dig val;                     ...      */
+                    if ((nbr_neg      == DEF_YES) &&            /* If  nbr neg                     ...                  */
+                        (nbr_neg_fmtd == DEF_NO )) {            /* ... but neg sign NOT yet fmt'd; ...                  */
+
+                        if (lead_char_fmtd == DEF_YES) {        /* ... & if lead char(s) fmt'd,    ...                  */
+                            pstr_fmt--;                         /* ... replace last lead char w/   ...                  */
+                        }
+                       *pstr_fmt++   = '-';                     /* ... prepend neg sign (see Notes #2b & #3b).          */
+                        nbr_neg_fmtd = DEF_YES;
+                    }
+
+                    if (nbr_shiftd > 0) {                       /* If shifted nbr > 0,        ...                       */
+                        dig_val    = (CPU_INT08U)(nbr_shiftd % 10u);
+                       *pstr_fmt++ = (CPU_CHAR  )(dig_val    + '0');
+
+                        nbr_dig_sig++;                          /* ... inc nbr sig digs;      ...                       */
+
+                    } else if ((nbr_dig > 1) ||                 /* ... else if req'd digs > 1 ...                       */
+                               (nbr_neg == DEF_NO)) {           /* ... or non-neg nbr,        ...                       */
+                       *pstr_fmt++ = '0';                       /* ... fmt one '0' char (see Note #3c5).                */
+                    }
+
+                } else if ((nbr_neg      == DEF_YES) &&         /* ... else if nbr neg                         ...      */
+                           (lead_char_0  == DEF_YES) &&         /* ... & lead char a '0' dig                   ...      */
+                           (nbr_neg_fmtd == DEF_NO )) {         /* ... but neg sign NOT yet fmt'd,             ...      */
+
+                   *pstr_fmt++   = '-';                         /* ... prepend neg sign (see Note #3b);        ...      */
+                    nbr_neg_fmtd = DEF_YES;
+
+                } else if (lead_char != (CPU_CHAR)'\0') {       /* ... else if avail,                          ...      */
+                   *pstr_fmt++     = lead_char;                 /* ... fmt lead char.                                   */
+                    lead_char_fmtd = DEF_YES;
+                }
+
+                dig_exp /= 10.0f;                               /* Shift to next least-sig dig.                         */
+
+            } else {                                            /* ... else append non-sig 0's (see Note #2c2).         */
+               *pstr_fmt++ = '0';
+            }
+
+        } else {                                                /* Else fmt '?' for invalid str (see Note #7).          */
+           *pstr_fmt++ = '?';
+        }
+    }
+
+
+    if (nbr_dp > 0) {                                           /* Fmt str for desired nbr dp :                         */
+        if (nbr_dig < 1) {                                      /* If NO digs fmt'd;                             ...    */
+            if (fmt_invalid == DEF_NO) {                        /* ... nbr fmt valid,                            ...    */
+                if ((nbr_neg      == DEF_YES) &&                /* ... nbr neg                                   ...    */
+                    (nbr_neg_fmtd == DEF_NO )) {                /* ... but neg sign NOT yet fmt'd,               ...    */
+                    *pstr_fmt++ = '-';                          /* ... prepend neg sign (see Notes #2b & #3b);   ...    */
+                } else {                                        /* ... else prepend 1 dig of '0' (see Note #3c5) ...    */
+                    *pstr_fmt++ = '0';
+                }
+            } else {                                            /* ... else fmt '?' for invalid str (see Note #7).      */
+                *pstr_fmt++ = '?';
+            }
+        }
+
+        if (fmt_invalid == DEF_NO) {                            /* If nbr fmt valid, ...                                */
+           *pstr_fmt++ = '.';                                   /* ... append dp prior to dp conversion.                */
+        } else {                                                /* Else fmt '?' for invalid str (see Note #7).          */
+           *pstr_fmt++ = '?';
+        }
+
+        dp_exp = 10.0f;
+        for (i = 0u; i < nbr_dp; i++) {
+            if (fmt_invalid == DEF_NO) {
+                                                                /* If nbr sig digs < max, fmt str dps;    ...           */
+                if (nbr_dig_sig <  LIB_STR_CFG_FP_MAX_NBR_DIG_SIG) {
+                    nbr_shiftd  = (CPU_INT32U)(nbr_fmt * dp_exp);
+                    dig_val     = (CPU_INT08U)(nbr_shiftd % 10u);
+                   *pstr_fmt++  = (CPU_CHAR  )(dig_val    + '0');
+                    dp_exp     *=  10.0f;                       /* Shift to next least-sig dp.                          */
+
+                    if ((nbr_shiftd  > 0) ||                    /* If shifted nbr > 0                  ...              */
+                        (nbr_dig_sig > 0)) {                    /* ... OR  > 0 sig digs already fmt'd, ...              */
+                         nbr_dig_sig++;                         /* ... inc nbr sig digs.                                */
+                    }
+
+                } else {                                        /* ... else append non-sig 0's (see Note #2c2).         */
+                   *pstr_fmt++ = '0';
+                }
+
+            } else {                                            /* Else fmt '?' for invalid str (see Note #7).          */
+               *pstr_fmt++ = '?';
+            }
+        }
+    }
+
+
+    if (nul != DEF_NO) {                                        /* If NOT DISABLED, append NULL char (see Note #4).     */
+       *pstr_fmt = (CPU_CHAR)'\0';
+    }
+
+
+    if (fmt_invalid != DEF_NO) {                                /* Rtn NULL for invalid str fmt (see Notes #6a - #6d).  */
+        return ((CPU_CHAR *)0);
+    }
+
+
+    return (pstr);                                              /* Rtn ptr to fmt'd str (see Note #6e).                 */
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                        Str_ParseNbr_Int32U()
+*
+* Description : Parse 32-bit unsigned integer from string.
+*
+* Argument(s) : pstr        Pointer to string (see Notes #1 & #2a).
+*
+*               pstr_next   Optional pointer to a variable to ... :
+*
+*                               (a) Return a pointer to first character following the integer string,
+*                                       if NO error(s) [see Note #2a2B2];
+*                               (b) Return a pointer to 'pstr',
+*                                       otherwise      (see Note #2a2A2).
+*
+*               nbr_base    Base of number to parse (see Notes #2a1B1 & #2a2B1).
+*
+* Return(s)   : Parsed integer,      if integer parsed with NO overflow   (see Note #2a3A).
+*
+*               DEF_INT_32U_MAX_VAL, if integer parsed but     overflowed (see Note #2a3A1).
+*
+*               0,                   otherwise                            (see Note #2a3B).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : DESCRIPTION' states that "these
+*                       functions shall convert the initial portion of the string pointed to by 'str' ('pstr')
+*                       to a type unsigned long ... representation" :
+*
+*                       (1) "First, they decompose the input string into three parts" :
+*
+*                           (A) "An initial, possibly empty, sequence of white-space characters [as specified
+*                                by isspace()]."
+*
+*                               (1) "The subject sequence is defined as the longest initial subsequence of the
+*                                    input string, starting with the first non-white-space character that is of
+*                                    the expected form.  The subject sequence shall contain no characters if the
+*                                    input string is empty or consists entirely of white-space characters."
+*
+*                           (B) (1) "A subject sequence interpreted as an integer represented in some radix
+*                                    determined by the value of 'base' ('nbr_base')" :
+*
+*                                   (a) "If the value of 'base' ('nbr_base') is 0, the expected form of the
+*                                        subject sequence is that of a decimal constant, octal constant, or
+*                                        hexadecimal constant" :
+*
+*                                       (1) "A decimal constant begins with a non-zero digit, and consists of a
+*                                            sequence of decimal digits."
+*
+*                                       (2) "An octal constant consists of the prefix '0' optionally followed by
+*                                            a sequence of the digits '0' to '7' only."
+*
+*                                       (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
+*                                            by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
+*                                            (or 'F') with values 10 to 15 respectively."
+*
+*                                   (b) "If the value of 'base' ('nbr_base') is between 2 and 36, the expected form
+*                                        of the subject sequence is a sequence of letters and digits representing
+*                                        an integer with the radix specified by 'base' ('nbr_base')" :
+*
+*                                       (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
+*                                                ascribed the values 10 to 35"; ...
+*                                           (B) "only letters whose ascribed values are less than that of base
+*                                                are permitted."
+*
+*                                       (2) (A) "If the value of 'base' ('nbr_base') is 16, the characters '0x' or
+*                                                '0X' may optionally precede the sequence of letters and digits."
+*
+*                                           (B) Although NO specification states that "if the value of 'base'
+*                                               ('nbr_base') is" 8, the '0' character "may optionally precede
+*                                               the sequence of letters and digits"; it seems reasonable to
+*                                               allow the '0' character to be optionally parsed.
+*
+*                               (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
+*
+*                                   (a) However, it does NOT seem reasonable to parse & convert a negative number
+*                                       integer string into an unsigned integer.
+*
+*                           (C) (1) (a) "A final string of one or more unrecognized characters,"  ...
+*                                   (b) "including the terminating null byte of the input string" ...
+*                               (2) "other than a sign or a permissible letter or digit."
+*$PAGE*
+*                       (2) Second, "they shall attempt to convert the subject sequence to an unsigned integer" :
+*
+*                           (A) "If the subject sequence is empty or does not have the expected form" :
+*
+*                               (1) "no conversion [is] performed"; ...
+*                               (2) "the value of 'str' ('pstr') [is] stored in the object pointed to by 'endptr'
+*                                    ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null pointer."
+*
+*                           (B) "If the subject sequence has the expected form" :
+*
+*                               (1) (a) "and the value of 'base' ('nbr_base') is 0, the sequence of characters
+*                                        starting with the first digit shall be interpreted as an integer constant."
+*
+*                                   (b) "and the value of 'base' ('nbr_base') is between 2 and 36, it shall be
+*                                        used as the base for conversion, ascribing to each letter its value as
+*                                        given above" (see Note #2a1B1b1A).
+*
+*                               (2) "A pointer to the final string shall be stored in the object pointed to by
+*                                   'endptr' ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null
+*                                   pointer."
+*
+*                       (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : RETURN VALUE' states that :
+*
+*                           (A) "Upon successful completion, these functions shall return the converted value."
+*                               (1) "If the correct value is outside the range of representable values, {ULONG_MAX}
+*                                    ... shall be returned."
+*
+*                           (B) "If no conversion could be performed, 0 shall be returned."
+*
+*                   (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
+*                           shall fail if" :
+*
+*                           (A) "[EINVAL] - The value of 'base' ('nbr_base') is not supported."
+*
+*                           (B) "[ERANGE] - The value to be returned is not representable."
+*
+*                       (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
+*                           may fail if" :
+*
+*                           (A) "[EINVAL] - No conversion could be performed."
+*
+*               (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
+*
+*                   (a) Valid parse string integer :
+*
+*                           pstr      = "     ABCDE xyz"
+*                           nbr_base  = 16
+*
+*                           nbr       = 703710
+*                           pstr_next = " xyz"
+*
+*
+*                   (b) Invalid parse string integer :
+*
+*                           pstr      = "     ABCDE"
+*                           nbr_base  = 10
+*
+*                           nbr       =  0
+*                           pstr_next = pstr = "     ABCDE"
+*
+*
+*                   (c) Valid hexadecimal parse string integer :
+*
+*                           pstr      = "     0xGABCDE"
+*                           nbr_base  = 16
+*
+*                           nbr       =  0
+*                           pstr_next = "xGABCDE"
+*
+*
+*                   (d) Valid decimal parse string integer ('0x' prefix ignored
+*                               following invalid hexadecimal characters) :
+*
+*                           pstr      = "     0xGABCDE"
+*                           nbr_base  =  0
+*
+*                           nbr       =  0
+*                           pstr_next = "xGABCDE"
+*
+*
+*                   (e) Valid decimal parse string integer ('0'  prefix ignored
+*                               following invalid octal       characters) :
+*
+*                           pstr      = "     0GABCDE"
+*                           nbr_base  =  0
+*
+*                           nbr       =  0
+*                           pstr_next = "GABCDE"
+*
+*$PAGE*
+*                   (f) Parse string integer overflow :
+*
+*                           pstr      = "   12345678901234567890*123456"
+*                           nbr_base  = 10
+*
+*                           nbr       = DEF_INT_32U_MAX_VAL
+*                           pstr_next = "*123456"
+*
+*
+*                   (g) Invalid negative unsigned parse string :
+*
+*                           pstr      = "  -12345678901234567890*123456"
+*                           nbr_base  = 10
+*
+*                           nbr       = 0
+*                           pstr_next = pstr = "  -12345678901234567890*123456"
+*
+*********************************************************************************************************
+*/
+
+CPU_INT32U  Str_ParseNbr_Int32U (const  CPU_CHAR     *pstr,
+                                        CPU_CHAR    **pstr_next,
+                                        CPU_INT08U    nbr_base)
+{
+    CPU_INT32U  nbr;
+
+
+    nbr = Str_ParseNbr_Int32(               pstr,               /* Parse/convert str ...                                */
+                                            pstr_next,
+                                            nbr_base,
+                                            DEF_NO,             /* ... as unsigned int (see Note #2a2).                 */
+                             (CPU_BOOLEAN *)0);
+
+    return (nbr);
+}
+
+
+/*
+*********************************************************************************************************
+*                                        Str_ParseNbr_Int32S()
+*
+* Description : Parse 32-bit signed integer from string.
+*
+* Argument(s) : pstr        Pointer to string (see Notes #1 & #2a).
+*
+*               pstr_next   Optional pointer to a variable to ... :
+*
+*                               (a) Return a pointer to first character following the integer string,
+*                                       if NO error(s) [see Note #2a2B2];
+*                               (b) Return a pointer to 'pstr',
+*                                       otherwise      (see Note #2a2A2).
+*
+*               nbr_base    Base of number to parse (see Notes #2a1B1 & #2a2B1).
+*
+* Return(s)   : Parsed integer,      if integer parsed with NO over- or underflow (see Note #2a3A).
+*
+*               DEF_INT_32S_MIN_VAL, if integer parsed but negatively underflowed (see Note #2a3A1a).
+*
+*               DEF_INT_32U_MAX_VAL, if integer parsed but positively overflowed  (see Note #2a3A1b).
+*
+*               0,                   otherwise                                    (see Note #2a3B).
+*
+* Caller(s)   : Application.
+*
+* Note(s)     : (1) String buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtol() : DESCRIPTION' states that "these
+*                       functions shall convert the initial portion of the string pointed to by 'str' ('pstr')
+*                       to a type long ... representation" :
+*
+*                       (1) "First, they decompose the input string into three parts" :
+*
+*                           (A) "An initial, possibly empty, sequence of white-space characters [as specified
+*                                by isspace()]."
+*
+*                               (1) "The subject sequence is defined as the longest initial subsequence of the
+*                                    input string, starting with the first non-white-space character that is of
+*                                    the expected form.  The subject sequence shall contain no characters if the
+*                                    input string is empty or consists entirely of white-space characters."
+*
+*                           (B) (1) "A subject sequence interpreted as an integer represented in some radix
+*                                    determined by the value of 'base' ('nbr_base')" :
+*
+*                                   (a) "If the value of 'base' ('nbr_base') is 0, the expected form of the
+*                                        subject sequence is that of a decimal constant, octal constant, or
+*                                        hexadecimal constant" :
+*
+*                                       (1) "A decimal constant begins with a non-zero digit, and consists of a
+*                                            sequence of decimal digits."
+*
+*                                       (2) "An octal constant consists of the prefix '0' optionally followed by
+*                                            a sequence of the digits '0' to '7' only."
+*
+*                                       (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
+*                                            by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
+*                                            (or 'F') with values 10 to 15 respectively."
+*
+*                                   (b) "If the value of 'base' ('nbr_base') is between 2 and 36, the expected form
+*                                        of the subject sequence is a sequence of letters and digits representing
+*                                        an integer with the radix specified by 'base' ('nbr_base')" :
+*
+*                                       (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
+*                                                ascribed the values 10 to 35"; ...
+*                                           (B) "only letters whose ascribed values are less than that of base
+*                                                are permitted."
+*
+*                                       (2) (A) "If the value of 'base' ('nbr_base') is 16, the characters '0x' or
+*                                                '0X' may optionally precede the sequence of letters and digits."
+*
+*                                           (B) Although NO specification states that "if the value of 'base'
+*                                               ('nbr_base') is" 8, the '0' character "may optionally precede
+*                                               the sequence of letters and digits"; it seems reasonable to
+*                                               allow the '0' character to be optionally parsed.
+*
+*                               (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
+*
+*                                   (a) However, it does NOT seem reasonable to parse & convert a negative number
+*                                       integer string into an unsigned integer.
+*
+*                           (C) (1) (a) "A final string of one or more unrecognized characters,"  ...
+*                                   (b) "including the terminating null byte of the input string" ...
+*                               (2) "other than a sign or a permissible letter or digit."
+*$PAGE*
+*                       (2) Second, "they shall attempt to convert the subject sequence to an integer" :
+*
+*                           (A) "If the subject sequence is empty or does not have the expected form" :
+*
+*                               (1) "no conversion is performed"; ...
+*                               (2) "the value of 'str' ('pstr') is stored in the object pointed to by 'endptr'
+*                                    ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null pointer."
+*
+*                           (B) "If the subject sequence has the expected form" :
+*
+*                               (1) (a) "and the value of 'base' ('nbr_base') is 0, the sequence of characters
+*                                        starting with the first digit shall be interpreted as an integer constant."
+*
+*                                   (b) "and the value of 'base' ('nbr_base') is between 2 and 36, it shall be
+*                                        used as the base for conversion, ascribing to each letter its value as
+*                                        given above" (see Note #2a1B1b1A).
+*
+*                               (2) "A pointer to the final string shall be stored in the object pointed to by
+*                                   'endptr' ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null
+*                                   pointer."
+*
+*                       (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtol() : RETURN VALUE' states that :
+*
+*                           (A) "Upon successful completion, these functions shall return the converted value."
+*
+*                               (1) "If the correct value is outside the range of representable values", either
+*                                    of the following "shall be returned" :
+*                                   (a) "{LONG_MIN}" or ...
+*                                   (b) "{LONG_MAX}"
+*
+*                           (B) "If no conversion could be performed, 0 shall be returned."
+*
+*                   (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
+*                           shall fail if" :
+*
+*                           (A) "[EINVAL] - The value of 'base' ('nbr_base') is not supported."
+*
+*                           (B) "[ERANGE] - The value to be returned is not representable."
+*
+*                       (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
+*                           may fail if" :
+*
+*                           (A) "[EINVAL] - No conversion could be performed."
+*
+*               (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
+*
+*                   (a) Valid parse string integer :
+*
+*                           pstr      = "     ABCDE xyz"
+*                           nbr_base  = 16
+*
+*                           nbr       = 703710
+*                           pstr_next = " xyz"
+*
+*
+*                   (b) Invalid parse string integer :
+*
+*                           pstr      = "     ABCDE"
+*                           nbr_base  = 10
+*
+*                           nbr       =  0
+*                           pstr_next = pstr = "     ABCDE"
+*
+*
+*                   (c) Valid hexadecimal parse string integer :
+*
+*                           pstr      = "     0xGABCDE"
+*                           nbr_base  = 16
+*
+*                           nbr       =  0
+*                           pstr_next = "xGABCDE"
+*
+*
+*                   (d) Valid decimal parse string integer ('0x' prefix ignored
+*                               following invalid hexadecimal characters) :
+*
+*                           pstr      = "     0xGABCDE"
+*                           nbr_base  =  0
+*
+*                           nbr       =  0
+*                           pstr_next = "xGABCDE"
+*
+*
+*                   (e) Valid decimal parse string integer ('0'  prefix ignored
+*                               following invalid octal       characters) :
+*
+*                           pstr      = "     0GABCDE"
+*                           nbr_base  =  0
+*
+*                           nbr       =  0
+*                           pstr_next = "GABCDE"
+*
+*$PAGE*
+*                   (f) Parse string integer overflow :
+*
+*                           pstr      = "   12345678901234567890*123456"
+*                           nbr_base  = 10
+*
+*                           nbr       = DEF_INT_32S_MAX_VAL
+*                           pstr_next = "*123456"
+*
+*
+*                   (g) Parse string integer underflow :
+*
+*                           pstr      = "  -12345678901234567890*123456"
+*                           nbr_base  = 10
+*
+*                           nbr       = DEF_INT_32S_MIN_VAL
+*                           pstr_next = "*123456"
+*
+*********************************************************************************************************
+*/
+
+CPU_INT32S  Str_ParseNbr_Int32S (const  CPU_CHAR     *pstr,
+                                        CPU_CHAR    **pstr_next,
+                                        CPU_INT08U    nbr_base)
+{
+    CPU_INT32S   nbr;
+    CPU_INT32U   nbr_abs;
+    CPU_BOOLEAN  nbr_neg;
+
+
+    nbr_abs = Str_ParseNbr_Int32(pstr,                          /* Parse/convert str ...                                */
+                                 pstr_next,
+                                 nbr_base,
+                                 DEF_YES,                       /* ... as signed int (see Note #2a2).                   */
+                                &nbr_neg);
+
+    if (nbr_neg == DEF_NO) {                                    /* Chk for neg nbr & ovf/undf (see Note #2a3A1).        */
+        nbr = (nbr_abs > (CPU_INT32U) DEF_INT_32S_MAX_VAL)          ?  (CPU_INT32S)DEF_INT_32S_MAX_VAL
+                                                                    :  (CPU_INT32S)nbr_abs;
+    } else {
+        nbr = (nbr_abs > (CPU_INT32U)-DEF_INT_32S_MIN_VAL_ONES_CPL) ?  (CPU_INT32S)DEF_INT_32S_MIN_VAL
+                                                                    : -(CPU_INT32S)nbr_abs;
+    }
+
+    return (nbr);
+}
+
+
+/*
+*********************************************************************************************************
+*********************************************************************************************************
+*                                           LOCAL FUNCTIONS
+*********************************************************************************************************
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                         Str_FmtNbr_Int32()
+*
+* Description : Format 32-bit integer into a multi-digit character string.
+*
+* Argument(s) : nbr             Number           to format.
+*
+*               nbr_dig         Number of digits to format (see Note #1).
+*
+*               nbr_base        Base   of number to format (see Note #2).
+*
+*               nbr_neg         Indicates whether number to format is negative :
+*               -------
+*                                   DEF_NO          Number is non-negative.
+*                                   DEF_YES         Number is     negative.
+*
+*                               Argument validated in Str_FmtNbr_Int32U(),
+*                                                     Str_FmtNbr_Int32S().
+*
+*               lead_char       Prepend leading character  (see Note #3) :
+*
+*                                   '\0'                    Do NOT prepend leading character to string.
+*                                     Printable character          Prepend leading character to string.
+*                                   Unprintable character   Format invalid string (see Note #6e).
+*
+*               lower_case      Format alphabetic characters (if any) in lower case :
+*
+*                                   DEF_NO          Format alphabetic characters in upper case.
+*                                   DEF_YES         Format alphabetic characters in lower case.
+*
+*               nul             Append terminating NULL-character (see Note #4) :
+*
+*                                   DEF_NO          Do NOT append terminating NULL-character to string.
+*                                   DEF_YES                Append terminating NULL-character to string.
+*
+*               pstr            Pointer to character array to return formatted number string (see Note #5).
+*
+* Return(s)   : Pointer to formatted string, if NO error(s) [see Note #6f].
+*
+*               Pointer to NULL,             otherwise.
+*
+* Caller(s)   : Str_FmtNbr_Int32U(),
+*               Str_FmtNbr_Int32S().
+*$PAGE*
+* Note(s)     : (1) (a) The maximum number of digits to format for 32-bit integer numbers :
+*
+*
+*                               Maximum Number of             [  log (Number)      ]
+*                             32-bit Integer Digits  =  floor [ -------------- + 1 ]
+*                                   to Format                 [   log (Base)       ]
+*
+*                               where
+*                                       Number                  Number to format
+*                                       Base            Base of number to format
+*
+*                   (b) (1) If the number of digits to format ('nbr_dig') is zero; then NO formatting
+*                           is performed except possible NULL-termination of the string (see Note #4).
+*
+*                               Example :
+*
+*                                   nbr      = -23456
+*                                   nbr_dig  =  0
+*                                   nbr_base = 10
+*
+*                                   pstr     = ""                   See Note #7a
+*
+*                       (2) If the number of digits to format ('nbr_dig') is less than the number of
+*                           significant integer digits of the number to format ('nbr'); then an invalid
+*                           string is formatted instead of truncating any significant integer digits.
+*
+*                               Example :
+*
+*                                   nbr      = 23456
+*                                   nbr_dig  = 3
+*                                   nbr_base = 10
+*
+*                                   pstr     = "???"                See Note #7b
+*
+*                       (3) If the number to format ('nbr') is negative but the number of digits to format
+*                           ('nbr_dig') is equal to the number of significant integer digits of the number
+*                           to format ('nbr'); then an invalid string is formatted instead of truncating
+*                           the negative sign.
+*
+*                               Example :
+*
+*                                   nbr      = -23456
+*                                   nbr_dig  =  5
+*                                   nbr_base = 10
+*
+*                                   pstr     = "?????"              See Note #7b
+*
+*               (2) The number's base MUST be between 2 & 36, inclusive.
+*$PAGE*
+*               (3) Leading character option prepends leading characters prior to the first non-zero digit.
+*
+*                   (a) (1) Leading character MUST be a printable ASCII character.
+*
+*                       (2) (A) Leading character MUST NOT be a number base digit, ...
+*                           (B) with the exception of '0'.
+*
+*                   (b) (1) The number of leading characters is such that the total number of significant
+*                           integer digits plus the number of leading characters plus possible negative
+*                           sign character is equal to the requested number of integer digits to format
+*                           ('nbr_dig').
+*
+*                               Examples :
+*
+*                                   nbr       = 23456
+*                                   nbr_dig   = 7
+*                                   nbr_base  = 10
+*                                   lead_char = ' '
+*
+*                                   pstr      = "  23456"
+*
+*
+*                                   nbr       = -23456
+*                                   nbr_dig   = 7
+*                                   nbr_base  = 10
+*                                   lead_char = ' '
+*
+*                                   pstr      = " -23456"
+*
+*                       (2) (A) If the number to format ('nbr') is negative AND the leading character
+*                               ('lead_char') is     a '0' digit; then the negative sign character
+*                               prefixes all leading characters prior to the formatted number.
+*
+*                                   Examples :
+*
+*                                       nbr        = -23456
+*                                       nbr_dig    =  8
+*                                       nbr_base   = 10
+*                                       lead_char  = '0'
+*
+*                                       pstr       = "-0023456"
+*
+*
+*                                       nbr        = -43981
+*                                       nbr_dig    =  8
+*                                       nbr_base   = 16
+*                                       lead_char  = '0'
+*                                       lower_case = DEF_NO
+*
+*                                       pstr       = "-000ABCD"
+*
+*                           (B) If the number to format ('nbr') is negative AND the leading character
+*                               ('lead_char') is NOT a '0' digit; then the negative sign character
+*                               immediately prefixes the most significant digit of the formatted number.
+*
+*                                   Examples :
+*
+*                                       nbr        = -23456
+*                                       nbr_dig    =  8
+*                                       nbr_base   = 10
+*                                       lead_char  = '#'
+*
+*                                       pstr       = "##-23456"
+*
+*
+*                                       nbr        = -43981
+*                                       nbr_dig    =  8
+*                                       nbr_base   = 16
+*                                       lead_char  = '#'
+*                                       lower_case = DEF_YES
+*
+*                                       pstr       = "###-abcd"
+*
+*                   (c) (1) If the value of the number to format is     zero  ...
+*                       (2) ... & the number of digits to format is non-zero, ...
+*                       (3) ... but NO leading character available;           ...
+*                       (4) ... then one digit of '0' value is formatted.
+*
+*                           This is NOT a leading character; but a single integer digit of '0' value.
+*$PAGE*
+*               (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
+*                       array formatting.
+*
+*                   (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
+*                       terminate option DISABLED will cause character string run-on.
+*
+*               (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
+*
+*                   (b) To prevent character buffer overrun :
+*
+*                           Character array size MUST be  >=  ('nbr_dig'          +
+*                                                               1 negative sign   +
+*                                                               1 'NUL' terminator)  characters
+*
+*               (6) String format terminates when :
+*
+*                   (a) Format string pointer is passed a NULL pointer.
+*                       (1) No      string formatted;                NULL pointer returned.
+*
+*                   (b) Number of digits to format ('nbr_dig') is zero.
+*                       (1) NULL    string formatted (see Note #7a); NULL pointer returned.
+*
+*                   (c) Number of digits to format ('nbr_dig') is less than number of significant
+*                           integer digits of the number to format ('nbr'), including possible
+*                           negative sign.
+*                       (1) Invalid string formatted (see Note #7);  NULL pointer returned.
+*
+*                   (d) Base is passed an invalid base (see Note #2).
+*                       (1) Invalid string format performed; NULL pointer returned.
+*
+*                   (e) Lead character is NOT a valid, printable character (see Note #3a).
+*                       (1) Invalid string formatted (see Note #7);  NULL pointer returned.
+*
+*                   (f) Number successfully formatted into character string array.
+*
+*               (7) For any unsuccessful string format or error(s), an invalid string of question marks
+*                   ('?') will be formatted, where the number of question marks is determined by the
+*                   number of digits to format ('nbr_dig') :
+*
+*                      Invalid string's     {  (a)   0 (NULL string)  ,  if 'nbr_dig' = 0
+*                          number of     =  {
+*                       question marks      {  (b)  'nbr_dig'         ,  if 'nbr_dig' > 0
+*
+*********************************************************************************************************
+*/
+
+static  CPU_CHAR  *Str_FmtNbr_Int32 (CPU_INT32U    nbr,
+                                     CPU_INT08U    nbr_dig,
+                                     CPU_INT08U    nbr_base,
+                                     CPU_BOOLEAN   nbr_neg,
+                                     CPU_CHAR      lead_char,
+                                     CPU_BOOLEAN   lower_case,
+                                     CPU_BOOLEAN   nul,
+                                     CPU_CHAR     *pstr)
+{
+    CPU_CHAR     *pstr_fmt;
+    CPU_DATA      i;
+    CPU_INT32U    nbr_fmt;
+    CPU_INT32U    nbr_log;
+    CPU_INT08U    nbr_dig_max;
+    CPU_INT08U    nbr_dig_min;
+    CPU_INT08U    nbr_dig_fmtd;
+    CPU_INT08U    nbr_neg_sign;
+    CPU_INT08U    nbr_lead_char;
+    CPU_INT08U    dig_val;
+    CPU_INT08U    lead_char_delta_0;
+    CPU_INT08U    lead_char_delta_a;
+    CPU_BOOLEAN   lead_char_dig;
+    CPU_BOOLEAN   lead_char_0;
+    CPU_BOOLEAN   fmt_invalid;
+    CPU_BOOLEAN   print_char;
+    CPU_BOOLEAN   nbr_neg_fmtd;
+
+
+                                                                /* ---------------- VALIDATE FMT ARGS ----------------- */
+    if (pstr == (CPU_CHAR *)0) {                                /* Rtn NULL if str ptr NULL (see Note #6a).             */
+        return ((CPU_CHAR *)0);
+    }
+
+    fmt_invalid = DEF_NO;
+    lead_char_0 = DEF_NO;
+
+    if (nbr_dig < 1) {                                          /* If nbr digs = 0, ...                                 */
+        fmt_invalid = DEF_YES;                                  /* ... fmt invalid str (see Note #6b).                  */
+    }
+                                                                /* If invalid base, ...                                 */
+    if ((nbr_base <  2u) ||
+        (nbr_base > 36u)) {
+        fmt_invalid = DEF_YES;                                  /* ... fmt invalid str (see Note #6d).                  */
+    }
+
+    if (lead_char != (CPU_CHAR)'\0') {
+        print_char =  ASCII_IsPrint(lead_char);
+        if (print_char != DEF_YES) {                            /* If lead char non-printable (see Note #3a1), ...      */
+            fmt_invalid = DEF_YES;                              /* ... fmt invalid str        (see Note #6e).           */
+
+        } else if (lead_char != '0') {                          /* Chk lead char for non-0 nbr base dig.                */
+            lead_char_delta_0 = (CPU_INT08U)(lead_char - '0');
+            if (lower_case != DEF_YES) {
+                lead_char_delta_a = (CPU_INT08U)(lead_char - 'A');
+            } else {
+                lead_char_delta_a = (CPU_INT08U)(lead_char - 'a');
+            }
+
+            lead_char_dig = (((nbr_base <= 10u) &&  (lead_char_delta_0 <  nbr_base))      ||
+                             ((nbr_base >  10u) && ((lead_char_delta_0 <             10u) ||
+                                                    (lead_char_delta_a < (nbr_base - 10u))))) ? DEF_YES : DEF_NO;
+
+            if (lead_char_dig == DEF_YES) {                     /* If lead char non-0 nbr base dig (see Note #3a2A), ...*/
+                fmt_invalid = DEF_YES;                          /* ... fmt invalid str             (see Note #6e).      */
+            }
+        }
+    }
+
+
+                                                                /* ----------------- PREPARE NBR FMT ------------------ */
+    pstr_fmt    = pstr;
+    lead_char_0 = DEF_NO;
+
+    if (fmt_invalid == DEF_NO) {
+        nbr_fmt     = nbr;
+        nbr_log     = nbr;
+        nbr_dig_max = 1u;
+        while (nbr_log >= nbr_base) {                           /* While nbr base digs avail, ...                       */
+            nbr_dig_max++;                                      /* ... calc max nbr digs.                               */
+            nbr_log /= nbr_base;
+        }
+
+        nbr_neg_sign = (nbr_neg == DEF_YES) ? 1u : 0u;
+        if (nbr_dig >= (nbr_dig_max + nbr_neg_sign)) {          /* If req'd nbr digs >= (max nbr digs + neg sign), ...  */
+            nbr_neg_fmtd = DEF_NO;
+            nbr_dig_min  = DEF_MIN(nbr_dig_max, nbr_dig);
+                                                                /* ... calc nbr digs to fmt & nbr lead chars.           */
+            if (lead_char != (CPU_CHAR)'\0') {
+                nbr_dig_fmtd  = nbr_dig;
+                nbr_lead_char = nbr_dig     -
+                                nbr_dig_min - nbr_neg_sign;
+            } else {
+                nbr_dig_fmtd  = nbr_dig_min + nbr_neg_sign;
+                nbr_lead_char = 0u;
+            }
+
+            if (nbr_lead_char > 0) {                            /* If lead chars to fmt, ...                            */
+                lead_char_0 = (lead_char == '0')                /* ... chk if lead char a '0' dig (see Note #3a2B).     */
+                            ?  DEF_YES : DEF_NO;
+            }
+
+        } else {                                                /* Else if nbr trunc'd, ...                             */
+            fmt_invalid = DEF_YES;                              /* ... fmt invalid str (see Note #6c).                  */
+        }
+    }
+
+    if (fmt_invalid != DEF_NO) {
+        nbr_dig_fmtd = nbr_dig;
+    }
+
+
+                                                                /* ------------------- FMT NBR STR -------------------- */
+    pstr_fmt += nbr_dig_fmtd;                                   /* Start fmt @ least-sig dig.                           */
+
+    if (nul != DEF_NO) {                                        /* If NOT DISABLED, append NULL char (see Note #4).     */
+       *pstr_fmt = (CPU_CHAR)'\0';
+    }
+    pstr_fmt--;
+
+
+    for (i = 0u; i < nbr_dig_fmtd; i++) {                       /* Fmt str for desired nbr digs :                       */
+        if (fmt_invalid == DEF_NO) {
+            if ((nbr_fmt > 0) ||                                /* If fmt nbr > 0                               ...     */
+                (i == 0u)) {                                    /* ... OR on one's  dig to fmt (see Note #3c1), ...     */
+                                                                /* ... calc & fmt dig val;                      ...     */
+                dig_val = (CPU_INT08U)(nbr_fmt % nbr_base);
+                if (dig_val < 10u) {
+                   *pstr_fmt-- = (CPU_CHAR)(dig_val + '0');
+                } else {
+                    if (lower_case !=  DEF_YES) {
+                       *pstr_fmt--  = (CPU_CHAR)((dig_val - 10u) + 'A');
+                    } else {
+                       *pstr_fmt--  = (CPU_CHAR)((dig_val - 10u) + 'a');
+                    }
+                }
+
+                nbr_fmt /= nbr_base;                            /* Shift to next more-sig dig.                          */
+
+            } else if ((nbr_neg      == DEF_YES)  &&            /* ... else if nbr neg             AND          ...     */
+                     (((lead_char_0  == DEF_NO )  &&            /* ... lead char NOT a '0' dig                  ...     */
+                       (nbr_neg_fmtd == DEF_NO )) ||            /* ... but neg sign NOT yet fmt'd  OR           ...     */
+                      ((lead_char_0  != DEF_NO )  &&            /* ... lead char is  a '0' dig                  ...     */
+                       (i == (nbr_dig_fmtd - 1u))))) {          /* ... & on most-sig dig to fmt,                ...     */
+
+               *pstr_fmt--   = '-';                             /* ... prepend neg sign (see Note #3b);         ...     */
+                nbr_neg_fmtd = DEF_YES;
+
+            } else if (lead_char != (CPU_CHAR)'\0') {           /* ... else if avail,                           ...     */
+               *pstr_fmt-- = lead_char;                         /* ... fmt lead char.                                   */
+            }
+
+        } else {                                                /* Else fmt '?' for invalid str (see Note #7).          */
+           *pstr_fmt-- = '?';
+        }
+    }
+
+
+    if (fmt_invalid != DEF_NO) {                                /* Rtn NULL for invalid str fmt (see Notes #6a - #6e).  */
+        return ((CPU_CHAR *)0);
+    }
+
+
+    return (pstr);                                              /* Rtn ptr to fmt'd str (see Note #6f).                 */
+}
+
+
+/*
+*********************************************************************************************************
+*                                        Str_ParseNbr_Int32()
+*
+* Description : Parse 32-bit integer from string.
+*
+* Argument(s) : pstr            Pointer to string (see Notes #1 & #2a).
+*
+*               pstr_next       Optional pointer to a variable to ... :
+*
+*                                   (a) Return a pointer to first character following the integer string,
+*                                           if NO error(s) [see Note #2a2B2];
+*                                   (b) Return a pointer to 'pstr',
+*                                           otherwise      (see Note #2a2A2).
+*
+*               nbr_base        Base of number to parse (see Notes #2a1B1 & #2a2B1).
+*
+*               nbr_signed      Indicates whether number to parse is signed :
+*
+*                                   DEF_NO                  Number is unsigned.
+*                                   DEF_YES                 Number is   signed.
+*
+*               pnbr_neg        Pointer to a variable to return if the parsed (signed) number is negative :
+*
+*                                   DEF_NO                  Number is non-negative.
+*                                   DEF_YES                 Number is     negative.
+*
+* Return(s)   : Parsed integer,      if integer parsed with NO overflow   (see Note #2a3A).
+*
+*               DEF_INT_32U_MAX_VAL, if integer parsed but     overflowed (see Note #2a3A1).
+*
+*               0,                   otherwise                            (see Note #2a3B).
+*
+* Caller(s)   : Str_ParseNbr_Int32U(),
+*               Str_ParseNbr_Int32S().
+*
+* Note(s)     : (1) String buffer NOT modified.
+*
+*               (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtol() : DESCRIPTION' states that "these
+*                       functions shall convert the initial portion of the string pointed to by 'str' ('pstr')
+*                       to a type long ... representation" :
+*
+*                       (1) "First, they decompose the input string into three parts" :
+*
+*                           (A) "An initial, possibly empty, sequence of white-space characters [as specified
+*                                by isspace()]."
+*
+*                               (1) "The subject sequence is defined as the longest initial subsequence of the
+*                                    input string, starting with the first non-white-space character that is of
+*                                    the expected form.  The subject sequence shall contain no characters if the
+*                                    input string is empty or consists entirely of white-space characters."
+*
+*                           (B) (1) "A subject sequence interpreted as an integer represented in some radix
+*                                    determined by the value of 'base' ('nbr_base')" :
+*
+*                                   (a) "If the value of 'base' ('nbr_base') is 0, the expected form of the
+*                                        subject sequence is that of a decimal constant, octal constant, or
+*                                        hexadecimal constant" :
+*
+*                                       (1) "A decimal constant begins with a non-zero digit, and consists of a
+*                                            sequence of decimal digits."
+*
+*                                       (2) "An octal constant consists of the prefix '0' optionally followed by
+*                                            a sequence of the digits '0' to '7' only."
+*
+*                                       (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
+*                                            by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
+*                                            (or 'F') with values 10 to 15 respectively."
+*
+*                                   (b) "If the value of 'base' ('nbr_base') is between 2 and 36, the expected form
+*                                        of the subject sequence is a sequence of letters and digits representing
+*                                        an integer with the radix specified by 'base' ('nbr_base')" :
+*
+*                                       (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
+*                                                ascribed the values 10 to 35"; ...
+*                                           (B) "only letters whose ascribed values are less than that of base
+*                                                are permitted."
+*
+*                                       (2) (A) "If the value of 'base' ('nbr_base') is 16, the characters '0x' or
+*                                               '0X' may optionally precede the sequence of letters and digits."
+*
+*                                           (B) Although NO specification states that "if the value of 'base'
+*                                               ('nbr_base') is" 8, the '0' character "may optionally precede
+*                                               the sequence of letters and digits"; it seems reasonable to
+*                                               allow the '0' character to be optionally parsed.
+*$PAGE*
+*                               (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
+*
+*                                   (a) It does NOT seem reasonable to parse & convert a negative number
+*                                       integer string into an unsigned integer.  However, a negative sign
+*                                       for an unsigned integer will automatically be parsed as an invalid
+*                                       character (see Note #2aC1).
+*
+*                           (C) (1) (a) "A final string of one or more unrecognized characters,"  ...
+*                                   (b) "including the terminating null byte of the input string" ...
+*                               (2) "other than a sign or a permissible letter or digit."
+*
+*                       (2) Second, "they shall attempt to convert the subject sequence to an integer" :
+*
+*                           (A) "If the subject sequence is empty or does not have the expected form" :
+*
+*                               (1) "no conversion is performed"; ...
+*                               (2) "the value of 'str' ('pstr') is stored in the object pointed to by 'endptr'
+*                                    ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null pointer."
+*
+*                           (B) "If the subject sequence has the expected form" :
+*
+*                               (1) (a) "and the value of 'base' ('nbr_base') is 0, the sequence of characters
+*                                        starting with the first digit shall be interpreted as an integer constant."
+*
+*                                   (b) "and the value of 'base' ('nbr_base') is between 2 and 36, it shall be
+*                                        used as the base for conversion, ascribing to each letter its value as
+*                                        given above" (see Note #2a1B1b1A).
+*
+*                               (2) "A pointer to the final string shall be stored in the object pointed to by
+*                                   'endptr' ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null
+*                                   pointer."
+*
+*                       (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtol() : RETURN VALUE' states that :
+*
+*                           (A) "Upon successful completion, these functions shall return the converted value."
+*                               (1) "If the correct value is outside the range of representable values, {LONG_MIN}
+*                                    [or] {LONG_MAX} ... shall be returned."
+*
+*                           (B) "If no conversion could be performed, 0 shall be returned."
+*
+*                   (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
+*                           shall fail if" :
+*
+*                           (A) "[EINVAL] - The value of 'base' ('nbr_base') is not supported."
+*
+*                           (B) "[ERANGE] - The value to be returned is not representable."
+*
+*                       (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
+*                           may fail if" :
+*
+*                           (A) "[EINVAL] - No conversion could be performed."
+*$PAGE*
+*               (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
+*
+*                   (a) Valid parse string integer :
+*
+*                           pstr      = "     ABCDE xyz"
+*                           nbr_base  = 16
+*
+*                           nbr       = 703710
+*                           pstr_next = " xyz"
+*
+*
+*                   (b) Invalid parse string integer :
+*
+*                           pstr      = "     ABCDE"
+*                           nbr_base  = 10
+*
+*                           nbr       =  0
+*                           pstr_next = pstr = "     ABCDE"
+*
+*
+*                   (c) Valid hexadecimal parse string integer :
+*
+*                           pstr      = "     0xGABCDE"
+*                           nbr_base  = 16
+*
+*                           nbr       =  0
+*                           pstr_next = "xGABCDE"
+*
+*
+*                   (d) Valid decimal parse string integer ('0x' prefix ignored
+*                               following invalid hexadecimal characters) :
+*
+*                           pstr      = "     0xGABCDE"
+*                           nbr_base  =  0
+*
+*                           nbr       =  0
+*                           pstr_next = "xGABCDE"
+*
+*
+*                   (e) Valid decimal parse string integer ('0'  prefix ignored
+*                               following invalid octal       characters) :
+*
+*                           pstr      = "     0GABCDE"
+*                           nbr_base  =  0
+*
+*                           nbr       =  0
+*                           pstr_next = "GABCDE"
+*
+*
+*                   (f) Parse string integer overflow :
+*
+*                           pstr      = "   12345678901234567890*123456"
+*                           nbr_base  = 10
+*
+*                           nbr       = DEF_INT_32U_MAX_VAL
+*                           pstr_next = "*123456"
+*
+*
+*                   (g) Parse string integer underflow :
+*
+*                           pstr      = "  -12345678901234567890*123456"
+*                           nbr_base  = 10
+*
+*                           nbr       = DEF_INT_32S_MIN_VAL
+*                           pstr_next = "*123456"
+*
+*
+*               (4) String parse terminates when :
+*
+*                   (a) Base passed an invalid base (see Note #2a1B1b).
+*                       (1) No conversion performed; 0 returned.
+*
+*                   (b) (1) Parse string passed a NULL pointer OR empty integer sequence (see Note #2a2A).
+*                           (A) No conversion performed; 0 returned.
+*
+*                       (2) Invalid parse string character found (see Note #2a1C).
+*                           (A) Parsed integer returned.
+*                           (B) 'pstr_next' points to invalid character.
+*
+*                       (3) Entire  parse string converted (see Note #2a2B).
+*                           (A) Parsed integer returned.
+*                           (B) 'pstr_next' points to terminating NULL character.
+*
+*               (5) Pointers to variables that return values MUST be initialized PRIOR to all other
+*                   validation or function handling in case of any error(s).
+*********************************************************************************************************
+*/
+
+static  CPU_INT32U  Str_ParseNbr_Int32 (const  CPU_CHAR      *pstr,
+                                               CPU_CHAR     **pstr_next,
+                                               CPU_INT08U     nbr_base,
+                                               CPU_BOOLEAN    nbr_signed,
+                                               CPU_BOOLEAN   *pnbr_neg)
+{
+    const  CPU_CHAR     *pstr_parse;
+    const  CPU_CHAR     *pstr_parse_nbr;
+           CPU_CHAR     *pstr_parse_unused;
+           CPU_CHAR      parse_char;
+           CPU_INT08U    parse_dig;
+           CPU_INT32U    nbr;
+           CPU_BOOLEAN   nbr_neg_unused;
+           CPU_BOOLEAN   nbr_dig;
+           CPU_BOOLEAN   nbr_alpha;
+           CPU_BOOLEAN   nbr_hex;
+           CPU_BOOLEAN   nbr_hex_lower;
+           CPU_BOOLEAN   whitespace;
+           CPU_BOOLEAN   neg;
+           CPU_BOOLEAN   ovf;
+           CPU_BOOLEAN   done;
+
+                                                                /* --------------- VALIDATE PARSE ARGS ---------------- */
+    if (pstr_next == (CPU_CHAR **) 0) {                         /* If NOT avail, ...                                    */
+        pstr_next  = (CPU_CHAR **)&pstr_parse_unused;           /* ... re-cfg NULL rtn ptr to unused local var.         */
+       (void)&pstr_parse_unused;                                /* Prevent possible 'variable unused' warning.          */
+    }
+   *pstr_next = (CPU_CHAR *)pstr;                               /* Init rtn str for err (see Note #5).                  */
+
+    if (pnbr_neg == (CPU_BOOLEAN *) 0) {                        /* If NOT avail, ...                                    */
+        pnbr_neg  = (CPU_BOOLEAN *)&nbr_neg_unused;             /* ... re-cfg NULL rtn ptr to unused local var.         */
+       (void)&nbr_neg_unused;                                   /* Prevent possible 'variable unused' warning.          */
+    }
+   *pnbr_neg = DEF_NO;                                          /* Init nbr neg for err (see Note #5).                  */
+
+
+    if (pstr == (CPU_CHAR *)0) {                                /* Rtn zero if str ptr NULL (see Note #4b1).            */
+        return (0u);
+    }
+                                                                /* Rtn zero if invalid base (see Note #4a).             */
+    if ((nbr_base == 1u) ||
+        (nbr_base > 36u)) {
+        return (0u);
+    }
+
+
+                                                                /* ------------- IGNORE PRECEDING CHAR(S) ------------- */
+    pstr_parse = pstr;                                          /* Save ptr to init'l str for err (see Note #2a2A2).    */
+
+    whitespace = ASCII_IsSpace(*pstr_parse);
+    while (whitespace == DEF_YES) {                             /* Ignore initial white-space char(s) [see Note #2a1A]. */
+        pstr_parse++;
+        whitespace = ASCII_IsSpace(*pstr_parse);
+    }
+
+    switch (*pstr_parse) {
+        case '+':                                               /* Ignore   pos sign (see Note #2a1B2).                 */
+             pstr_parse++;
+             neg = DEF_NO;
+             break;
+
+
+        case '-':                                               /* Validate neg sign (see Note #2a1B2a).                */
+             if (nbr_signed == DEF_YES) {
+                 pstr_parse++;
+             }
+             neg = DEF_YES;
+             break;
+
+
+        default:
+             neg = DEF_NO;
+             break;
+    }
+
+
+                                                                /* --------- IGNORE NBR BASE PRECEDING CHAR(S) -------- */
+    pstr_parse_nbr = pstr_parse;                                /* Save ptr to str's nbr (see Note #2a1A1).             */
+
+    switch (nbr_base) {
+        case  0u:                                               /* Determine unspecified nbr base (see Notes #2a1B1a).  */
+             if (*pstr_parse == '0') {                          /* If avail, ...                                        */
+                  pstr_parse++;                                 /* ... adv past '0'  prefix (see Note #2a1B1b2).        */
+                  switch (*pstr_parse) {
+                      case 'x':                                 /* For '0x' prefix, ...                                 */
+                      case 'X':
+                           nbr_base   = 16u;                    /* ... set nbr base = 16    (see Note #2a1B1a3).        */
+                           parse_char = (CPU_CHAR)(*(pstr_parse + 1));
+                           nbr_hex    =  ASCII_IsDigHex(parse_char);
+                           if (nbr_hex == DEF_YES) {            /* If next char is valid hex dig, ...                   */
+                               pstr_parse++;                    /* ... adv past '0x' prefix (see Note #2a1B1b2A).       */
+                           }
+                           break;
+
+
+                      default:                                  /* For '0'  prefix, ...                                 */
+                           nbr_base =  8u;                      /* ... set nbr base =  8    (see Note #2a1B1a2).        */
+                           break;
+                  }
+
+             } else {                                           /* For non-'0' prefix, ...                              */
+                 nbr_base = 10u;                                /* ... set nbr base = 10    (see Note #2a1B1a1).        */
+             }
+             break;
+
+
+        case  8u:                                               /* See Note #2a1B1a2.                                   */
+             if (*pstr_parse == '0') {                          /* If avail, ...                                        */
+                  pstr_parse++;                                 /* ... adv past '0'  prefix (see Note #2a1B1b2B).       */
+             }
+             break;
+
+
+        case 16u:                                               /* See Note #2a1B1a3.                                   */
+             if (*pstr_parse == '0') {                          /* If avail, ...                                        */
+                  pstr_parse++;                                 /* ... adv past '0'  prefix (see Note #2a1B1b2).        */
+                  switch (*pstr_parse) {
+                      case 'x':
+                      case 'X':
+                           parse_char = (CPU_CHAR)(*(pstr_parse + 1));
+                           nbr_hex    =  ASCII_IsDigHex(parse_char);
+                           if (nbr_hex == DEF_YES) {            /* If next char is valid hex dig, ...                   */
+                               pstr_parse++;                    /* ... adv past '0x' prefix (see Note #2a1B1b2A).       */
+                           }
+                           break;
+
+
+                      default:
+                           break;
+                  }
+             }
+             break;
+
+
+        default:                                                /* See Note #2a1B1b.                                    */
+             break;
+    }
+
+
+                                                                /* ------------------ PARSE INT STR ------------------- */
+    nbr  = 0u;
+    ovf  = DEF_NO;
+    done = DEF_NO;
+
+    while (done == DEF_NO) {                                    /* Parse str for desired nbr base digs (see Note #2a2). */
+        parse_char = (CPU_CHAR)*pstr_parse;
+        nbr_alpha  =  ASCII_IsAlphaNum(parse_char);
+        if (nbr_alpha == DEF_YES) {                             /* If valid alpha num nbr dig avail, ...                */
+                                                                /* ... convert parse char into nbr dig.                 */
+            nbr_dig = ASCII_IsDig(parse_char);
+            if (nbr_dig == DEF_YES) {
+                parse_dig = (CPU_INT08U)(parse_char - '0');
+            } else {
+                nbr_hex_lower = ASCII_IsLower(parse_char);
+                if (nbr_hex_lower == DEF_YES) {
+                    parse_dig = (CPU_INT08U)((parse_char - 'a') + 10u);
+                } else {
+                    parse_dig = (CPU_INT08U)((parse_char - 'A') + 10u);
+                }
+            }
+
+            if (parse_dig < nbr_base) {                         /* If parse char valid for nbr base ...                 */
+                if (ovf == DEF_NO) {                            /* ... & nbr NOT yet ovf'd,         ...                 */
+                    if (nbr <= Str_MultOvfThTbl_Int32U[nbr_base]) {
+                                                                /* ... merge parse char dig into nbr.                   */
+                        nbr *= nbr_base;
+                        nbr += parse_dig;
+                        if (nbr < parse_dig) {
+                            ovf = DEF_YES;
+                        }
+                    } else {
+                        ovf = DEF_YES;
+                    }
+                }
+                pstr_parse++;
+
+            } else {                                            /* Invalid         char parsed (see Note #2a1C1a).      */
+                done = DEF_YES;
+            }
+
+        } else {                                                /* Invalid OR NULL char parsed (see Note #2a1C1).       */
+            done = DEF_YES;
+        }
+    }
+
+    if (ovf == DEF_YES) {                                       /* If nbr ovf'd, ...                                    */
+        nbr  = DEF_INT_32U_MAX_VAL;                             /* ... rtn max int val (see Note #2a3A1).               */
+    }
+
+
+    if (pstr_parse !=             pstr_parse_nbr) {             /* If final parse str != init'l parse nbr str,       .. */
+       *pstr_next   = (CPU_CHAR *)pstr_parse;                   /* .. rtn   parse str's next char (see Note #2a2B2); .. */
+    } else {
+       *pstr_next   = (CPU_CHAR *)pstr;                         /* .. else rtn initial parse str  (see Note #2a2A2).    */
+    }
+
+   *pnbr_neg = neg;                                             /* Rtn neg nbr status.                                  */
+
+
+    return (nbr);
+}
+

+ 429 - 0
MiddleWare/uCOS_II/uC-LIB/lib_str.h

@@ -0,0 +1,429 @@
+/*
+*********************************************************************************************************
+*                                                uC/LIB
+*                                        CUSTOM LIBRARY MODULES
+*
+*                         (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL
+*
+*                  All rights reserved.  Protected by international copyright laws.
+*
+*                  uC/LIB is provided in source form to registered licensees ONLY.  It is
+*                  illegal to distribute this source code to any third party unless you receive
+*                  written permission by an authorized Micrium representative.  Knowledge of
+*                  the source code may NOT be used to develop a similar product.
+*
+*                  Please help us continue to provide the Embedded community with the finest
+*                  software available.  Your honesty is greatly appreciated.
+*
+*                  You can find our product's user manual, API reference, release notes and
+*                  more information at: https://doc.micrium.com
+*
+*                  You can contact us at: http://www.micrium.com
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                       ASCII STRING MANAGEMENT
+*
+* Filename      : lib_str.h
+* Version       : V1.38.01
+* Programmer(s) : ITJ
+*                 JDH
+*********************************************************************************************************
+* Note(s)       : (1) NO compiler-supplied standard library functions are used in library or product software.
+*
+*                     (a) ALL standard library functions are implemented in the custom library modules :
+*
+*                         (1) \<Custom Library Directory>\lib_*.*
+*
+*                         (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
+*
+*                               where
+*                                       <Custom Library Directory>      directory path for custom library software
+*                                       <cpu>                           directory name for specific processor (CPU)
+*                                       <compiler>                      directory name for specific compiler
+*
+*                     (b) Product-specific library functions are implemented in individual products.
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*
+* Note(s) : (1) This string library header file is protected from multiple pre-processor inclusion through
+*               use of the string library module present pre-processor macro definition.
+*********************************************************************************************************
+*/
+
+#ifndef  LIB_STR_MODULE_PRESENT                                 /* See Note #1.                                         */
+#define  LIB_STR_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*                                 ASCII STRING CONFIGURATION DEFINES
+*
+* Note(s) : (1) Some ASCII string configuration #define's MUST be available PRIOR to including any
+*               application configuration (see 'INCLUDE FILES  Note #1a').
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                    STRING FLOATING POINT DEFINES
+*
+* Note(s) : (1) (a) (1) The maximum accuracy for 32-bit floating-point numbers :
+*
+*
+*                             Maximum Accuracy            log [Internal-Base ^ (Number-Internal-Base-Digits)]
+*                       32-bit Floating-point Number  =  -----------------------------------------------------
+*                                                                         log [External-Base]
+*
+*                                                         log [2 ^ 24]
+*                                                     =  --------------
+*                                                           log [10]
+*
+*                                                     <  7.225  Base-10 Digits
+*
+*                           where
+*                                   Internal-Base                   Internal number base of floating-
+*                                                                       point numbers (i.e.  2)
+*                                   External-Base                   External number base of floating-
+*                                                                       point numbers (i.e. 10)
+*                                   Number-Internal-Base-Digits     Number of internal number base
+*                                                                       significant digits (i.e. 24)
+*
+*                   (2) Also, since some 32-bit floating-point calculations are converted to 32-bit
+*                       unsigned numbers, the maximum accuracy is limited to the maximum accuracy
+*                       for 32-bit unsigned numbers of 9 digits.
+*
+*               (b) Some CPUs' &/or compilers' floating-point implementations MAY further reduce the
+*                   maximum accuracy.
+*********************************************************************************************************
+*/
+
+#define  LIB_STR_FP_MAX_NBR_DIG_SIG_MIN                    1u
+#define  LIB_STR_FP_MAX_NBR_DIG_SIG_MAX                    9u   /* See Note #1a2.                                       */
+#define  LIB_STR_FP_MAX_NBR_DIG_SIG_DFLT                   7u   /* See Note #1a1.                                       */
+
+
+/*
+*********************************************************************************************************
+*                                            INCLUDE FILES
+*
+* Note(s) : (1) The custom library software files are located in the following directories :
+*
+*               (a) \<Your Product Application>\lib_cfg.h
+*
+*               (b) \<Custom Library Directory>\lib_*.*
+*
+*                       where
+*                               <Your Product Application>      directory path for Your Product's Application
+*                               <Custom Library Directory>      directory path for custom library software
+*
+*           (2) CPU-configuration  software files are located in the following directories :
+*
+*               (a) \<CPU-Compiler Directory>\cpu_*.*
+*               (b) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.*
+*
+*                       where
+*                               <CPU-Compiler Directory>        directory path for common CPU-compiler software
+*                               <cpu>                           directory name for specific processor (CPU)
+*                               <compiler>                      directory name for specific compiler
+*
+*           (3) Compiler MUST be configured to include as additional include path directories :
+*
+*               (a) '\<Your Product Application>\' directory                            See Note #1a
+*
+*               (b) '\<Custom Library Directory>\' directory                            See Note #1b
+*
+*               (c) (1) '\<CPU-Compiler Directory>\'                  directory         See Note #2a
+*                   (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory         See Note #2b
+*
+*           (4) NO compiler-supplied standard library functions SHOULD be used.
+*
+*               #### The reference to standard library header files SHOULD be removed once all custom
+*               library functions are implemented WITHOUT reference to ANY standard library function(s).
+*
+*               See also 'STANDARD LIBRARY MACRO'S  Note #1'.
+*********************************************************************************************************
+*/
+
+#include  <cpu.h>
+
+#include  <lib_def.h>
+#include  <lib_ascii.h>
+
+#include  <lib_cfg.h>
+
+#if 0                                                           /* See Note #4.                                         */
+#include  <stdio.h>
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                               EXTERNS
+*********************************************************************************************************
+*/
+
+#ifdef   LIB_STR_MODULE
+#define  LIB_STR_EXT
+#else
+#define  LIB_STR_EXT  extern
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                        DEFAULT CONFIGURATION
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                 STRING FLOATING POINT CONFIGURATION
+*
+* Note(s) : (1) Configure LIB_STR_CFG_FP_EN to enable/disable floating point string function(s).
+*
+*           (2) Configure LIB_STR_CFG_FP_MAX_NBR_DIG_SIG to configure the maximum number of significant
+*               digits to calculate &/or display for floating point string function(s).
+*
+*               See also 'STRING FLOATING POINT DEFINES  Note #1'.
+*********************************************************************************************************
+*/
+
+                                                                /* Configure floating point feature(s) [see Note #1] :  */
+#ifndef  LIB_STR_CFG_FP_EN
+#define  LIB_STR_CFG_FP_EN                      DEF_DISABLED
+                                                                /*   DEF_DISABLED     Floating point functions DISABLED */
+                                                                /*   DEF_ENABLED      Floating point functions ENABLED  */
+#endif
+
+                                                                /* Configure floating point feature(s)' number of ...   */
+                                                                /* ... significant digits (see Note #2).                */
+#ifndef  LIB_STR_CFG_FP_MAX_NBR_DIG_SIG
+#define  LIB_STR_CFG_FP_MAX_NBR_DIG_SIG         LIB_STR_FP_MAX_NBR_DIG_SIG_DFLT
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                               DEFINES
+*********************************************************************************************************
+*/
+
+#define  STR_CR_LF                     "\r\n"
+#define  STR_LF_CR                     "\n\r"
+#define  STR_NEW_LINE                   STR_CR_LF
+#define  STR_PARENT_PATH               ".."
+
+#define  STR_CR_LF_LEN                 (sizeof(STR_CR_LF)       - 1)
+#define  STR_LF_CR_LEN                 (sizeof(STR_LF_CR)       - 1)
+#define  STR_NEW_LINE_LEN              (sizeof(STR_NEW_LINE)    - 1)
+#define  STR_PARENT_PATH_LEN           (sizeof(STR_PARENT_PATH) - 1)
+
+
+/*
+*********************************************************************************************************
+*                                             DATA TYPES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                          GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                              MACRO'S
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                      STANDARD LIBRARY MACRO'S
+*
+* Note(s) : (1) NO compiler-supplied standard library functions SHOULD be used.
+*
+*               #### The reference to standard memory functions SHOULD be removed once all custom library
+*               functions are implemented WITHOUT reference to ANY standard library function(s).
+*
+*               See also 'INCLUDE FILES  Note #3'.
+*********************************************************************************************************
+*/
+
+                                                                /* See Note #1.                                         */
+#define  Str_FmtPrint                   snprintf
+#define  Str_FmtScan                    sscanf
+
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+                                                                /* ------------------ STR LEN  FNCTS ------------------ */
+CPU_SIZE_T   Str_Len            (const  CPU_CHAR      *pstr);
+
+CPU_SIZE_T   Str_Len_N          (const  CPU_CHAR      *pstr,
+                                        CPU_SIZE_T     len_max);
+
+
+                                                                       /* ------------------ STR COPY FNCTS ------------------ */
+CPU_CHAR    *Str_Copy           (       CPU_CHAR      *pstr_dest,
+                                 const  CPU_CHAR      *pstr_src);
+
+CPU_CHAR    *Str_Copy_N         (       CPU_CHAR      *pstr_dest,
+                                 const  CPU_CHAR      *pstr_src,
+                                        CPU_SIZE_T     len_max);
+
+
+CPU_CHAR    *Str_Cat            (       CPU_CHAR      *pstr_dest,
+                                 const  CPU_CHAR      *pstr_cat);
+
+CPU_CHAR    *Str_Cat_N          (       CPU_CHAR      *pstr_dest,
+                                 const  CPU_CHAR      *pstr_cat,
+                                        CPU_SIZE_T     len_max);
+
+
+                                                                       /* ------------------ STR CMP  FNCTS ------------------ */
+CPU_INT16S   Str_Cmp            (const  CPU_CHAR      *p1_str,
+                                 const  CPU_CHAR      *p2_str);
+
+CPU_INT16S   Str_Cmp_N          (const  CPU_CHAR      *p1_str,
+                                 const  CPU_CHAR      *p2_str,
+                                        CPU_SIZE_T     len_max);
+
+CPU_INT16S   Str_CmpIgnoreCase  (const  CPU_CHAR      *p1_str,
+                                 const  CPU_CHAR      *p2_str);
+
+CPU_INT16S   Str_CmpIgnoreCase_N(const  CPU_CHAR      *p1_str,
+                                 const  CPU_CHAR      *p2_str,
+                                        CPU_SIZE_T     len_max);
+
+
+                                                                       /* ------------------ STR SRCH FNCTS ------------------ */
+CPU_CHAR    *Str_Char           (const  CPU_CHAR      *pstr,
+                                        CPU_CHAR       srch_char);
+
+CPU_CHAR    *Str_Char_N         (const  CPU_CHAR      *pstr,
+                                        CPU_SIZE_T     len_max,
+                                        CPU_CHAR       srch_char);
+
+CPU_CHAR    *Str_Char_Last      (const  CPU_CHAR      *pstr,
+                                        CPU_CHAR       srch_char);
+
+CPU_CHAR    *Str_Char_Last_N    (const  CPU_CHAR      *pstr,
+                                        CPU_SIZE_T     len_max,
+                                        CPU_CHAR       srch_char);
+
+CPU_CHAR    *Str_Char_Replace   (       CPU_CHAR      *pstr,
+                                        CPU_CHAR       char_srch,
+                                        CPU_CHAR       char_replace);
+
+CPU_CHAR    *Str_Char_Replace_N (       CPU_CHAR      *pstr,
+                                        CPU_CHAR       char_srch,
+                                        CPU_CHAR       char_replace,
+                                        CPU_SIZE_T     len_max);
+
+CPU_CHAR    *Str_Str            (const  CPU_CHAR      *pstr,
+                                 const  CPU_CHAR      *pstr_srch);
+
+CPU_CHAR    *Str_Str_N          (const  CPU_CHAR      *pstr,
+                                 const  CPU_CHAR      *pstr_srch,
+                                        CPU_SIZE_T     len_max);
+
+
+                                                                       /* ------------------ STR FMT  FNCTS ------------------ */
+CPU_CHAR    *Str_FmtNbr_Int32U  (       CPU_INT32U     nbr,
+                                        CPU_INT08U     nbr_dig,
+                                        CPU_INT08U     nbr_base,
+                                        CPU_CHAR       lead_char,
+                                        CPU_BOOLEAN    lower_case,
+                                        CPU_BOOLEAN    nul,
+                                        CPU_CHAR      *pstr);
+
+CPU_CHAR    *Str_FmtNbr_Int32S  (       CPU_INT32S     nbr,
+                                        CPU_INT08U     nbr_dig,
+                                        CPU_INT08U     nbr_base,
+                                        CPU_CHAR       lead_char,
+                                        CPU_BOOLEAN    lower_case,
+                                        CPU_BOOLEAN    nul,
+                                        CPU_CHAR      *pstr);
+
+#if (LIB_STR_CFG_FP_EN == DEF_ENABLED)
+CPU_CHAR    *Str_FmtNbr_32      (       CPU_FP32       nbr,
+                                        CPU_INT08U     nbr_dig,
+                                        CPU_INT08U     nbr_dp,
+                                        CPU_CHAR       lead_char,
+                                        CPU_BOOLEAN    nul,
+                                        CPU_CHAR      *pstr);
+#endif
+
+
+                                                                       /* ----------------- STR PARSE FNCTS ------------------ */
+CPU_INT32U   Str_ParseNbr_Int32U(const  CPU_CHAR      *pstr,
+                                        CPU_CHAR     **pstr_next,
+                                        CPU_INT08U     nbr_base);
+
+CPU_INT32S   Str_ParseNbr_Int32S(const  CPU_CHAR      *pstr,
+                                        CPU_CHAR     **pstr_next,
+                                        CPU_INT08U     nbr_base);
+
+
+/*
+*********************************************************************************************************
+*                                        CONFIGURATION ERRORS
+*********************************************************************************************************
+*/
+
+#ifndef  LIB_STR_CFG_FP_EN
+#error  "LIB_STR_CFG_FP_EN                     not #define'd in 'lib_cfg.h'"
+#error  "                                [MUST be  DEF_DISABLED]           "
+#error  "                                [     ||  DEF_ENABLED ]           "
+
+#elif  ((LIB_STR_CFG_FP_EN != DEF_DISABLED) && \
+        (LIB_STR_CFG_FP_EN != DEF_ENABLED ))
+#error  "LIB_STR_CFG_FP_EN               illegally #define'd in 'lib_cfg.h'"
+#error  "                                [MUST be  DEF_DISABLED]           "
+#error  "                                [     ||  DEF_ENABLED ]           "
+
+
+#elif   (LIB_STR_CFG_FP_EN == DEF_ENABLED)
+
+#ifndef  LIB_STR_CFG_FP_MAX_NBR_DIG_SIG
+#error  "LIB_STR_CFG_FP_MAX_NBR_DIG_SIG        not #define'd in 'lib_cfg.h'          "
+#error  "                                [MUST be  >= LIB_STR_FP_MAX_NBR_DIG_SIG_MIN]"
+#error  "                                [     &&  <= LIB_STR_FP_MAX_NBR_DIG_SIG_MAX]"
+
+#elif   (DEF_CHK_VAL(LIB_STR_CFG_FP_MAX_NBR_DIG_SIG,          \
+                     LIB_STR_FP_MAX_NBR_DIG_SIG_MIN,          \
+                     LIB_STR_FP_MAX_NBR_DIG_SIG_MAX) != DEF_OK)
+#error  "LIB_STR_CFG_FP_MAX_NBR_DIG_SIG  illegally #define'd in 'lib_cfg.h'          "
+#error  "                                [MUST be  >= LIB_STR_FP_MAX_NBR_DIG_SIG_MIN]"
+#error  "                                [     &&  <= LIB_STR_FP_MAX_NBR_DIG_SIG_MAX]"
+#endif
+
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*
+* Note(s) : (1) See 'lib_str.h  MODULE'.
+*********************************************************************************************************
+*/
+
+#endif                                                          /* End of lib str module include.                       */
+

+ 189 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/GNU/os_cpu.h

@@ -0,0 +1,189 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*
+*
+*                         (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
+*                    All rights reserved.  Protected by international copyright laws.
+*
+*                                           ARM Cortex-M4 Port
+*
+* File      : OS_CPU.H
+* Version   : V2.92.09
+* By        : JJL
+*             JBL
+*
+* LICENSING TERMS:
+* ---------------
+*           uC/OS-II is provided in source form for FREE short-term evaluation, for educational use or
+*           for peaceful research.  If you plan or intend to use uC/OS-II in a commercial application/
+*           product then, you need to contact Micrium to properly license uC/OS-II for its use in your
+*           application/product.   We provide ALL the source code for your convenience and to help you
+*           experience uC/OS-II.  The fact that the source is provided does NOT mean that you can use
+*           it commercially without paying a licensing fee.
+*
+*           Knowledge of the source code may NOT be used to develop a similar product.
+*
+*           Please help us continue to provide the embedded community with the finest software available.
+*           Your honesty is greatly appreciated.
+*
+*           You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
+*
+* For       : ARMv7 Cortex-M4
+* Mode      : Thumb-2 ISA
+* Toolchain : GNU C Compiler
+*********************************************************************************************************
+*/
+
+#ifndef OS_CPU_H
+#define OS_CPU_H
+
+#ifdef OS_CPU_GLOBALS
+#define OS_CPU_EXT
+#else
+#define OS_CPU_EXT extern
+#endif
+
+#ifndef OS_CPU_EXCEPT_STK_SIZE
+#define OS_CPU_EXCEPT_STK_SIZE 128u /* Default exception stack size is 128 OS_STK entries */
+#endif
+
+/*
+*********************************************************************************************************
+*                                               DEFINES
+*********************************************************************************************************
+*/
+
+#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
+#define OS_CPU_ARM_FP_EN 1u
+#else
+#define OS_CPU_ARM_FP_EN 0u
+#endif
+
+/*
+*********************************************************************************************************
+*                              OS TICK INTERRUPT PRIORITY CONFIGURATION
+*
+* Note(s) : (1) For systems that don't need any high, real-time priority interrupts; the tick interrupt
+*               should be configured as the highest priority interrupt but won't adversely affect system
+*               operations.
+*
+*           (2) For systems that need one or more high, real-time interrupts; these should be configured
+*               higher than the tick interrupt which MAY delay execution of the tick interrupt.
+*
+*               (a) If the higher priority interrupts do NOT continually consume CPU cycles but only
+*                   occasionally delay tick interrupts, then the real-time interrupts can successfully
+*                   handle their intermittent/periodic events with the system not losing tick interrupts
+*                   but only increasing the jitter.
+*
+*               (b) If the higher priority interrupts consume enough CPU cycles to continually delay the
+*                   tick interrupt, then the CPU/system is most likely over-burdened & can't be expected
+*                   to handle all its interrupts/tasks. The system time reference gets compromised as a
+*                   result of losing tick interrupts.
+*********************************************************************************************************
+*/
+
+#define OS_CPU_CFG_SYSTICK_PRIO 0u
+
+/*
+*********************************************************************************************************
+*                                              DATA TYPES
+*                                         (Compiler Specific)
+*********************************************************************************************************
+*/
+
+typedef unsigned char BOOLEAN;
+typedef unsigned char INT8U;   /* Unsigned  8 bit quantity                           */
+typedef signed char INT8S;     /* Signed    8 bit quantity                           */
+typedef unsigned short INT16U; /* Unsigned 16 bit quantity                           */
+typedef signed short INT16S;   /* Signed   16 bit quantity                           */
+typedef unsigned int INT32U;   /* Unsigned 32 bit quantity                           */
+typedef signed int INT32S;     /* Signed   32 bit quantity                           */
+typedef float FP32;            /* Single precision floating point                    */
+typedef double FP64;           /* Double precision floating point                    */
+
+typedef unsigned int OS_STK;    /* Each stack entry is 32-bit wide                    */
+typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */
+
+/*
+*********************************************************************************************************
+*                                              Cortex-M4
+*                                      Critical Section Management
+*
+* Method #1:  Disable/Enable interrupts using simple instructions.  After critical section, interrupts
+*             will be enabled even if they were disabled before entering the critical section.
+*             NOT IMPLEMENTED
+*
+* Method #2:  Disable/Enable interrupts by preserving the state of interrupts.  In other words, if
+*             interrupts were disabled before entering the critical section, they will be disabled when
+*             leaving the critical section.
+*             NOT IMPLEMENTED
+*
+* Method #3:  Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
+*             would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
+*             disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
+*             disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
+*             into the CPU's status register.
+*********************************************************************************************************
+*/
+
+#define OS_CRITICAL_METHOD 3u
+
+#if OS_CRITICAL_METHOD == 3u
+#define OS_ENTER_CRITICAL()        \
+    {                              \
+        cpu_sr = OS_CPU_SR_Save(); \
+    }
+#define OS_EXIT_CRITICAL()         \
+    {                              \
+        OS_CPU_SR_Restore(cpu_sr); \
+    }
+#endif
+
+/*
+*********************************************************************************************************
+*                                        Cortex-M4 Miscellaneous
+*********************************************************************************************************
+*/
+
+#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM        */
+
+#define OS_TASK_SW() OSCtxSw()
+
+/*
+*********************************************************************************************************
+*                                          GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE];
+OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase;
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM                                  */
+OS_CPU_SR OS_CPU_SR_Save(void);
+void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
+#endif
+
+void OSCtxSw(void);
+void OSIntCtxSw(void);
+void OSStartHighRdy(void);
+
+void PendSV_Handler(void);
+
+/* See OS_CPU_C.C                                    */
+void SysTick_Handler(void);
+void OS_CPU_SysTickInit(INT32U cnts);
+
+#if (OS_CPU_ARM_FP_EN > 0u)
+void OS_CPU_FP_Reg_Push(OS_STK *stkPtr);
+void OS_CPU_FP_Reg_Pop(OS_STK *stkPtr);
+#endif
+
+#endif

+ 315 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/GNU/os_cpu_a.S

@@ -0,0 +1,315 @@
+@
+@********************************************************************************************************
+@                                                uC/OS-II
+@                                          The Real-Time Kernel
+@
+@
+@                         (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
+@                    All rights reserved.  Protected by international copyright laws.
+@
+@                                           ARM Cortex-M4 Port
+@
+@ File      : OS_CPU_A.ASM
+@ Version   : V2.92.09
+@ By        : JJL
+@             BAN
+@             JBL
+@
+@ For       : ARMv7 Cortex-M4
+@@Mode      : Thumb-2 ISA
+@ Toolchain : GNU C Compiler
+@
+@********************************************************************************************************
+@
+
+@********************************************************************************************************
+@                                          PUBLIC FUNCTIONS
+@********************************************************************************************************
+
+    .extern  OSRunning                                           @ External references
+    .extern  OSPrioCur
+    .extern  OSPrioHighRdy
+    .extern  OSTCBCur
+    .extern  OSTCBHighRdy
+    .extern  OSIntExit
+    .extern  OSTaskSwHook
+    .extern  OS_CPU_ExceptStkBase
+
+    .global  OS_CPU_SR_Save                                      @ Functions declared in this file
+    .global  OS_CPU_SR_Restore
+    .global  OSStartHighRdy
+    .global  OSCtxSw
+    .global  OSIntCtxSw
+    .global  PendSV_Handler
+    
+#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
+    .global  OS_CPU_FP_Reg_Push
+    .global  OS_CPU_FP_Reg_Pop
+#endif
+
+
+@********************************************************************************************************
+@                                               EQUATES
+@********************************************************************************************************
+
+.equ NVIC_INT_CTRL,   0xE000ED04                              @ Interrupt control state register.
+.equ NVIC_SYSPRI14,   0xE000ED22                              @ System priority register (priority 14).
+.equ NVIC_PENDSV_PRI, 0xFF                                    @ PendSV priority value (lowest).
+.equ NVIC_PENDSVSET,  0x10000000                              @ Value to trigger PendSV exception.
+
+
+@********************************************************************************************************
+@                                     CODE GENERATION DIRECTIVES
+@********************************************************************************************************
+
+.text
+.align 2
+.thumb
+.syntax unified
+
+
+@********************************************************************************************************
+@                                   FLOATING POINT REGISTERS PUSH
+@                             void  OS_CPU_FP_Reg_Push (CPU_STK  *stkPtr)
+@
+@ Note(s) : 1) This function saves S0-S31, and FPSCR registers of the Floating Point Unit.
+@
+@           2) Pseudo-code is:
+@              a) Get FPSCR register value;
+@              b) Push value on process stack;
+@              c) Push remaining regs S0-S31 on process stack;
+@              d) Update OSTCBCurPtr->StkPtr;
+@********************************************************************************************************
+
+#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
+OS_CPU_FP_Reg_Push:
+    MRS     R1, PSP                                             @ PSP is process stack pointer
+    CBZ     R1, OS_CPU_FP_nosave                                @ Skip FP register save the first time
+
+    VMRS    R1, FPSCR
+    STR R1, [R0, #-4]!
+    VSTMDB  R0!, {S0-S31}
+    LDR     R1, =OSTCBCur
+    LDR     R2, [R1]
+    STR     R0, [R2]
+OS_CPU_FP_nosave:
+    BX      LR
+#endif
+
+
+@********************************************************************************************************
+@                                   FLOATING POINT REGISTERS POP
+@                             void  OS_CPU_FP_Reg_Pop (CPU_STK  *stkPtr)
+@
+@ Note(s) : 1) This function restores S0-S31, and FPSCR registers of the Floating Point Unit.
+@
+@           2) Pseudo-code is:
+@              a) Restore regs S0-S31 of new process stack;
+@              b) Restore FPSCR reg value
+@              c) Update OSTCBHighRdyPtr->StkPtr pointer of new proces stack;
+@********************************************************************************************************
+
+#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
+OS_CPU_FP_Reg_Pop:
+    VLDMIA  R0!, {S0-S31}
+    LDMIA   R0!, {R1}
+    VMSR    FPSCR, R1
+    LDR     R1, =OSTCBHighRdy
+    LDR     R2, [R1]
+    STR     R0, [R2]
+    BX      LR
+#endif
+
+
+@********************************************************************************************************
+@                                   CRITICAL SECTION METHOD 3 FUNCTIONS
+@
+@ Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
+@              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
+@              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
+@              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
+@              into the CPU's status register.
+@
+@ Prototypes :     OS_CPU_SR  OS_CPU_SR_Save(void)@
+@                  void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr)@
+@
+@
+@ Note(s)    : 1) These functions are used in general like this:
+@
+@                 void Task (void *p_arg)
+@                 {
+@                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
+@                     OS_CPU_SR  cpu_sr;
+@                 #endif
+@
+@                          :
+@                          :
+@                     OS_ENTER_CRITICAL();             /* cpu_sr = OS_CPU_SaveSR();                */
+@                          :
+@                          :
+@                     OS_EXIT_CRITICAL();              /* OS_CPU_RestoreSR(cpu_sr);                */
+@                          :
+@                          :
+@                 }
+@********************************************************************************************************
+
+.thumb_func
+OS_CPU_SR_Save:
+    MRS     R0, PRIMASK                                         @ Set prio int mask to mask all (except faults)
+    CPSID   I
+    BX      LR
+
+.thumb_func
+OS_CPU_SR_Restore:
+    MSR     PRIMASK, R0
+    BX      LR
+
+
+@********************************************************************************************************
+@                                         START MULTITASKING
+@                                      void OSStartHighRdy(void)
+@
+@ Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause
+@              the first task to start.
+@
+@           2) OSStartHighRdy() MUST:
+@              a) Setup PendSV exception priority to lowest;
+@              b) Set initial PSP to 0, to tell context switcher this is first run;
+@              c) Set the main stack to OS_CPU_ExceptStkBase
+@              d) Set OSRunning to TRUE;
+@              e) Trigger PendSV exception;
+@              f) Enable interrupts (tasks will run with interrupts enabled).
+@********************************************************************************************************
+
+.thumb_func
+OSStartHighRdy:
+    LDR     R0, =NVIC_SYSPRI14                                  @ Set the PendSV exception priority
+    LDR     R1, =NVIC_PENDSV_PRI
+    STRB    R1, [R0]
+
+    MOVS    R0, #0                                              @ Set the PSP to 0 for initial context switch call
+    MSR     PSP, R0
+
+    LDR     R0, =OS_CPU_ExceptStkBase                           @ Initialize the MSP to the OS_CPU_ExceptStkBase
+    LDR     R1, [R0]
+    MSR     MSP, R1    
+
+    LDR     R0, =OSRunning                                      @ OSRunning = TRUE
+    MOVS    R1, #1
+    STRB    R1, [R0]
+
+    LDR     R0, =NVIC_INT_CTRL                                  @ Trigger the PendSV exception (causes context switch)
+    LDR     R1, =NVIC_PENDSVSET
+    STR     R1, [R0]
+
+    CPSIE   I                                                   @ Enable interrupts at processor level
+
+OSStartHang:
+    B       OSStartHang                                         @ Should never get here
+
+
+@********************************************************************************************************
+@                       PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
+@
+@ Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch.  This function
+@              triggers the PendSV exception which is where the real work is done.
+@********************************************************************************************************
+
+.thumb_func
+OSCtxSw:
+    LDR     R0, =NVIC_INT_CTRL                                  @ Trigger the PendSV exception (causes context switch)
+    LDR     R1, =NVIC_PENDSVSET
+    STR     R1, [R0]
+    BX      LR
+
+
+@********************************************************************************************************
+@                   PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
+@
+@ Note(s) : 1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as
+@              the result of an interrupt.  This function simply triggers a PendSV exception which will
+@              be handled when there are no more interrupts active and interrupts are enabled.
+@********************************************************************************************************
+
+.thumb_func
+OSIntCtxSw:
+    LDR     R0, =NVIC_INT_CTRL                                  @ Trigger the PendSV exception (causes context switch)
+    LDR     R1, =NVIC_PENDSVSET
+    STR     R1, [R0]
+    BX      LR
+
+
+@********************************************************************************************************
+@                                       HANDLE PendSV EXCEPTION
+@                                   void OS_CPU_PendSVHandler(void)
+@
+@ Note(s) : 1) PendSV is used to cause a context switch.  This is a recommended method for performing
+@              context switches with Cortex-M4.  This is because the Cortex-M4 auto-saves half of the
+@              processor context on any exception, and restores same on return from exception.  So only
+@              saving of R4-R11 is required and fixing up the stack pointers.  Using the PendSV exception
+@              this way means that context saving and restoring is identical whether it is initiated from
+@              a thread or occurs due to an interrupt or exception.
+@
+@           2) Pseudo-code is:
+@              a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch);
+@              b) Save remaining regs r4-r11 on process stack;
+@              c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP;
+@              d) Call OSTaskSwHook();
+@              e) Get current high priority, OSPrioCur = OSPrioHighRdy;
+@              f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
+@              g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
+@              h) Restore R4-R11 from new process stack;
+@              i) Perform exception return which will restore remaining context.
+@
+@           3) On entry into PendSV handler:
+@              a) The following have been saved on the process stack (by processor):
+@                 xPSR, PC, LR, R12, R0-R3
+@              b) Processor mode is switched to Handler mode (from Thread mode)
+@              c) Stack is Main stack (switched from Process stack)
+@              d) OSTCBCur      points to the OS_TCB of the task to suspend
+@                 OSTCBHighRdy  points to the OS_TCB of the task to resume
+@
+@           4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
+@              know that it will only be run when no other exception or interrupt is active, and
+@              therefore safe to assume that context being switched out was using the process stack (PSP).
+@********************************************************************************************************
+
+.thumb_func
+PendSV_Handler:
+    CPSID   I                                                   @ Prevent interruption during context switch
+    MRS     R0, PSP                                             @ PSP is process stack pointer
+    CBZ     R0, OS_CPU_PendSVHandler_nosave                     @ Skip register save the first time
+
+    SUBS    R0, R0, #0x20                                       @ Save remaining regs r4-11 on process stack
+    STM     R0, {R4-R11}
+
+    LDR     R1, =OSTCBCur                                       @ OSTCBCur->OSTCBStkPtr = SP;
+    LDR     R1, [R1]
+    STR     R0, [R1]                                            @ R0 is SP of process being switched out
+
+                                                                @ At this point, entire context of process has been saved
+OS_CPU_PendSVHandler_nosave:
+    PUSH    {R14}                                               @ Save LR exc_return value
+    LDR     R0, =OSTaskSwHook                                   @ OSTaskSwHook();
+    BLX     R0
+    POP     {R14}
+
+    LDR     R0, =OSPrioCur                                      @ OSPrioCur = OSPrioHighRdy;
+    LDR     R1, =OSPrioHighRdy
+    LDRB    R2, [R1]
+    STRB    R2, [R0]
+
+    LDR     R0, =OSTCBCur                                       @ OSTCBCur  = OSTCBHighRdy;
+    LDR     R1, =OSTCBHighRdy
+    LDR     R2, [R1]
+    STR     R2, [R0]
+
+    LDR     R0, [R2]                                            @ R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
+    LDM     R0, {R4-R11}                                        @ Restore r4-11 from new process stack
+    ADDS    R0, R0, #0x20
+    MSR     PSP, R0                                             @ Load PSP with new process SP
+    ORR     LR, LR, #0xF4                                       @ Ensure exception return uses process stack
+    CPSIE   I
+    BX      LR                                                  @ Exception return will restore remaining context
+
+.end

+ 488 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/GNU/os_cpu_c.c

@@ -0,0 +1,488 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*
+*
+*                           (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
+*                    All rights reserved.  Protected by international copyright laws.
+*
+*                                           ARM Cortex-M4 Port
+*
+* File      : OS_CPU_C.C
+* Version   : V2.92.09
+* By        : JJL
+*             BAN
+*             JBL
+*
+* LICENSING TERMS:
+* ---------------
+*           uC/OS-II is provided in source form for FREE short-term evaluation, for educational use or
+*           for peaceful research.  If you plan or intend to use uC/OS-II in a commercial application/
+*           product then, you need to contact Micrium to properly license uC/OS-II for its use in your
+*           application/product.   We provide ALL the source code for your convenience and to help you
+*           experience uC/OS-II.  The fact that the source is provided does NOT mean that you can use
+*           it commercially without paying a licensing fee.
+*
+*           Knowledge of the source code may NOT be used to develop a similar product.
+*
+*           Please help us continue to provide the embedded community with the finest software available.
+*           Your honesty is greatly appreciated.
+*
+*           You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
+*
+* For       : ARMv7 Cortex-M4
+* Mode      : Thumb-2 ISA
+* Toolchain : GNU C Compiler
+*********************************************************************************************************
+*/
+
+#define OS_CPU_GLOBALS
+
+/*
+*********************************************************************************************************
+*                                             INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#include <ucos_ii.h>
+#include <lib_def.h>
+
+/*
+*********************************************************************************************************
+*                                          LOCAL VARIABLES
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+static INT16U OSTmrCtr;
+#endif
+
+/*
+*********************************************************************************************************
+*                                          SYS TICK DEFINES
+*********************************************************************************************************
+*/
+
+#define OS_CPU_CM4_NVIC_ST_CTRL (*((volatile INT32U *)0xE000E010uL))    /* SysTick Ctrl & Status Reg. */
+#define OS_CPU_CM4_NVIC_ST_RELOAD (*((volatile INT32U *)0xE000E014uL))  /* SysTick Reload  Value Reg. */
+#define OS_CPU_CM4_NVIC_ST_CURRENT (*((volatile INT32U *)0xE000E018uL)) /* SysTick Current Value Reg. */
+#define OS_CPU_CM4_NVIC_ST_CAL (*((volatile INT32U *)0xE000E01CuL))     /* SysTick Cal     Value Reg. */
+#define OS_CPU_CM4_NVIC_SHPRI1 (*((volatile INT32U *)0xE000ED18uL))     /* System Handlers  4 to  7 Prio.       */
+#define OS_CPU_CM4_NVIC_SHPRI2 (*((volatile INT32U *)0xE000ED1CuL))     /* System Handlers  8 to 11 Prio.       */
+#define OS_CPU_CM4_NVIC_SHPRI3 (*((volatile INT32U *)0xE000ED20uL))     /* System Handlers 12 to 15 Prio.       */
+
+#define OS_CPU_CM4_NVIC_ST_CTRL_COUNT 0x00010000uL   /* Count flag.                */
+#define OS_CPU_CM4_NVIC_ST_CTRL_CLK_SRC 0x00000004uL /* Clock Source.              */
+#define OS_CPU_CM4_NVIC_ST_CTRL_INTEN 0x00000002uL   /* Interrupt enable.          */
+#define OS_CPU_CM4_NVIC_ST_CTRL_ENABLE 0x00000001uL  /* Counter mode.              */
+#define OS_CPU_CM4_NVIC_PRIO_MIN 0xFFu               /* Min handler prio.          */
+
+/*
+*********************************************************************************************************
+*                                       OS INITIALIZATION HOOK
+*                                            (BEGINNING)
+*
+* Description: This function is called by OSInit() at the beginning of OSInit().
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts should be disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void OSInitHookBegin(void)
+{
+    INT32U size;
+    OS_STK *pstk;
+
+    /* Clear exception stack for stack checking.            */
+    pstk = &OS_CPU_ExceptStk[0];
+    size = OS_CPU_EXCEPT_STK_SIZE;
+    while (size > 0u)
+    {
+        size--;
+        *pstk++ = (OS_STK)0;
+    }
+
+    /* Align the ISR stack to 8-bytes                       */
+    OS_CPU_ExceptStkBase = (OS_STK *)&OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE];
+    OS_CPU_ExceptStkBase = (OS_STK *)((OS_STK)(OS_CPU_ExceptStkBase)&0xFFFFFFF8);
+
+#if OS_TMR_EN > 0u
+    OSTmrCtr = 0u;
+#endif
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                       OS INITIALIZATION HOOK
+*                                               (END)
+*
+* Description: This function is called by OSInit() at the end of OSInit().
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts should be disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void OSInitHookEnd(void)
+{
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                          TASK CREATION HOOK
+*
+* Description: This function is called when a task is created.
+*
+* Arguments  : ptcb   is a pointer to the task control block of the task being created.
+*
+* Note(s)    : 1) Interrupts are disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void OSTaskCreateHook(OS_TCB *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskCreateHook(ptcb);
+#else
+    (void)ptcb; /* Prevent compiler warning                           */
+#endif
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                           TASK DELETION HOOK
+*
+* Description: This function is called when a task is deleted.
+*
+* Arguments  : ptcb   is a pointer to the task control block of the task being deleted.
+*
+* Note(s)    : 1) Interrupts are disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void OSTaskDelHook(OS_TCB *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskDelHook(ptcb);
+#else
+    (void)ptcb; /* Prevent compiler warning                           */
+#endif
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                             IDLE TASK HOOK
+*
+* Description: This function is called by the idle task.  This hook has been added to allow you to do
+*              such things as STOP the CPU to conserve power.
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts are enabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void OSTaskIdleHook(void)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskIdleHook();
+#endif
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                            TASK RETURN HOOK
+*
+* Description: This function is called if a task accidentally returns.  In other words, a task should
+*              either be an infinite loop or delete itself when done.
+*
+* Arguments  : ptcb      is a pointer to the task control block of the task that is returning.
+*
+* Note(s)    : none
+*********************************************************************************************************
+*/
+
+#if OS_CPU_HOOKS_EN > 0u
+void OSTaskReturnHook(OS_TCB *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskReturnHook(ptcb);
+#else
+    (void)ptcb;
+#endif
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                           STATISTIC TASK HOOK
+*
+* Description: This function is called every second by uC/OS-II's statistics task.  This allows your
+*              application to add functionality to the statistics task.
+*
+* Arguments  : none
+*********************************************************************************************************
+*/
+
+#if OS_CPU_HOOKS_EN > 0u
+void OSTaskStatHook(void)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskStatHook();
+#endif
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                        INITIALIZE A TASK'S STACK
+*
+* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
+*              stack frame of the task being created.  This function is highly processor specific.
+*
+* Arguments  : task          is a pointer to the task code
+*
+*              p_arg         is a pointer to a user supplied data area that will be passed to the task
+*                            when the task first executes.
+*
+*              ptos          is a pointer to the top of stack.  It is assumed that 'ptos' points to
+*                            a 'free' entry on the task stack.  If OS_STK_GROWTH is set to 1 then
+*                            'ptos' will contain the HIGHEST valid address of the stack.  Similarly, if
+*                            OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
+*                            of the stack.
+*
+*              opt           specifies options that can be used to alter the behavior of OSTaskStkInit().
+*                            (see uCOS_II.H for OS_TASK_OPT_xxx).
+*
+* Returns    : Always returns the location of the new top-of-stack once the processor registers have
+*              been placed on the stack in the proper order.
+*
+* Note(s)    : 1) Interrupts are enabled when your task starts executing.
+*              2) All tasks run in Thread mode, using process stack.
+*********************************************************************************************************
+*/
+
+OS_STK *OSTaskStkInit(void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
+{
+    OS_STK *p_stk;
+
+    p_stk = ptos + 1u; /* Load stack pointer                                   */
+                       /* Align the stack to 8-bytes.                          */
+    p_stk = (OS_STK *)((OS_STK)(p_stk)&0xFFFFFFF8u);
+    /* Registers stacked as if auto-saved on exception      */
+    *(--p_stk) = (OS_STK)0x01000000uL;  /* xPSR                                                 */
+    *(--p_stk) = (OS_STK)task;          /* Entry Point                                          */
+    *(--p_stk) = (OS_STK)OS_TaskReturn; /* R14 (LR)                                             */
+    *(--p_stk) = (OS_STK)0x12121212uL;  /* R12                                                  */
+    *(--p_stk) = (OS_STK)0x03030303uL;  /* R3                                                   */
+    *(--p_stk) = (OS_STK)0x02020202uL;  /* R2                                                   */
+    *(--p_stk) = (OS_STK)0x01010101uL;  /* R1                                                   */
+    *(--p_stk) = (OS_STK)p_arg;         /* R0 : argument                                        */
+
+    /* Remaining registers saved on process stack           */
+    *(--p_stk) = (OS_STK)0x11111111uL; /* R11                                                  */
+    *(--p_stk) = (OS_STK)0x10101010uL; /* R10                                                  */
+    *(--p_stk) = (OS_STK)0x09090909uL; /* R9                                                   */
+    *(--p_stk) = (OS_STK)0x08080808uL; /* R8                                                   */
+    *(--p_stk) = (OS_STK)0x07070707uL; /* R7                                                   */
+    *(--p_stk) = (OS_STK)0x06060606uL; /* R6                                                   */
+    *(--p_stk) = (OS_STK)0x05050505uL; /* R5                                                   */
+    *(--p_stk) = (OS_STK)0x04040404uL; /* R4                                                   */
+
+#if (OS_CPU_ARM_FP_EN > 0u)
+    if ((opt & OS_TASK_OPT_SAVE_FP) != (INT16U)0)
+    {
+        *--p_stk = (OS_STK)0x02000000u; /* FPSCR                                                */
+                                        /* Initialize S0-S31 floating point registers           */
+        *--p_stk = (OS_STK)0x41F80000u; /* S31                                                  */
+        *--p_stk = (OS_STK)0x41F00000u; /* S30                                                  */
+        *--p_stk = (OS_STK)0x41E80000u; /* S29                                                  */
+        *--p_stk = (OS_STK)0x41E00000u; /* S28                                                  */
+        *--p_stk = (OS_STK)0x41D80000u; /* S27                                                  */
+        *--p_stk = (OS_STK)0x41D00000u; /* S26                                                  */
+        *--p_stk = (OS_STK)0x41C80000u; /* S25                                                  */
+        *--p_stk = (OS_STK)0x41C00000u; /* S24                                                  */
+        *--p_stk = (OS_STK)0x41B80000u; /* S23                                                  */
+        *--p_stk = (OS_STK)0x41B00000u; /* S22                                                  */
+        *--p_stk = (OS_STK)0x41A80000u; /* S21                                                  */
+        *--p_stk = (OS_STK)0x41A00000u; /* S20                                                  */
+        *--p_stk = (OS_STK)0x41980000u; /* S19                                                  */
+        *--p_stk = (OS_STK)0x41900000u; /* S18                                                  */
+        *--p_stk = (OS_STK)0x41880000u; /* S17                                                  */
+        *--p_stk = (OS_STK)0x41800000u; /* S16                                                  */
+        *--p_stk = (OS_STK)0x41700000u; /* S15                                                  */
+        *--p_stk = (OS_STK)0x41600000u; /* S14                                                  */
+        *--p_stk = (OS_STK)0x41500000u; /* S13                                                  */
+        *--p_stk = (OS_STK)0x41400000u; /* S12                                                  */
+        *--p_stk = (OS_STK)0x41300000u; /* S11                                                  */
+        *--p_stk = (OS_STK)0x41200000u; /* S10                                                  */
+        *--p_stk = (OS_STK)0x41100000u; /* S9                                                   */
+        *--p_stk = (OS_STK)0x41000000u; /* S8                                                   */
+        *--p_stk = (OS_STK)0x40E00000u; /* S7                                                   */
+        *--p_stk = (OS_STK)0x40C00000u; /* S6                                                   */
+        *--p_stk = (OS_STK)0x40A00000u; /* S5                                                   */
+        *--p_stk = (OS_STK)0x40800000u; /* S4                                                   */
+        *--p_stk = (OS_STK)0x40400000u; /* S3                                                   */
+        *--p_stk = (OS_STK)0x40000000u; /* S2                                                   */
+        *--p_stk = (OS_STK)0x3F800000u; /* S1                                                   */
+        *--p_stk = (OS_STK)0x00000000u; /* S0                                                   */
+    }
+#endif
+
+    return (p_stk);
+}
+
+/*
+*********************************************************************************************************
+*                                           TASK SWITCH HOOK
+*
+* Description: This function is called when a task switch is performed.  This allows you to perform other
+*              operations during a context switch.
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts are disabled during this call.
+*              2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that
+*                 will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the
+*                 task being switched out (i.e. the preempted task).
+*********************************************************************************************************
+*/
+#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u)
+void OSTaskSwHook(void)
+{
+
+#if (OS_CPU_ARM_FP_EN > 0u)
+    if ((OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0)
+    {
+        OS_CPU_FP_Reg_Push(OSTCBCur->OSTCBStkPtr);
+    }
+
+    if ((OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0)
+    {
+        OS_CPU_FP_Reg_Pop(OSTCBHighRdy->OSTCBStkPtr);
+    }
+#endif
+
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskSwHook();
+#endif
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                           OS_TCBInit() HOOK
+*
+* Description: This function is called by OS_TCBInit() after setting up most of the TCB.
+*
+* Arguments  : ptcb    is a pointer to the TCB of the task being created.
+*
+* Note(s)    : 1) Interrupts may or may not be ENABLED during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void OSTCBInitHook(OS_TCB *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TCBInitHook(ptcb);
+#else
+    (void)ptcb; /* Prevent compiler warning                           */
+#endif
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                               TICK HOOK
+*
+* Description: This function is called every tick.
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts may or may not be ENABLED during this call.
+*********************************************************************************************************
+*/
+#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u)
+void OSTimeTickHook(void)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TimeTickHook();
+#endif
+
+#if OS_TMR_EN > 0u
+    OSTmrCtr++;
+    if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC))
+    {
+        OSTmrCtr = 0;
+        OSTmrSignal();
+    }
+#endif
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                          SYS TICK HANDLER
+*
+* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-II tick
+*              interrupt.
+*
+* Arguments  : None.
+*
+* Note(s)    : 1) This function MUST be placed on entry 15 of the Cortex-M4 vector table.
+*********************************************************************************************************
+*/
+
+void SysTick_Handler(void)
+{
+    OS_CPU_SR cpu_sr;
+
+    OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR          */
+    OSIntNesting++;
+    OS_EXIT_CRITICAL();
+
+    OSTimeTick(); /* Call uC/OS-II's OSTimeTick()                       */
+
+    OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR          */
+}
+
+/*
+*********************************************************************************************************
+*                                         INITIALIZE SYS TICK
+*
+* Description: Initialize the SysTick.
+*
+* Arguments  : cnts         Number of SysTick counts between two OS tick interrupts.
+*
+* Note(s)    : 1) This function MUST be called after OSStart() & after processor initialization.
+*********************************************************************************************************
+*/
+
+void OS_CPU_SysTickInit(INT32U cnts)
+{
+    INT32U prio;
+
+    OS_CPU_CM4_NVIC_ST_RELOAD = cnts - 1u;
+
+    /* Set SysTick handler prio.                              */
+    prio = OS_CPU_CM4_NVIC_SHPRI3;
+    prio &= DEF_BIT_FIELD(24, 0);
+    prio |= DEF_BIT_MASK(OS_CPU_CFG_SYSTICK_PRIO, 24);
+
+    OS_CPU_CM4_NVIC_SHPRI3 = prio;
+
+    /* Enable timer.                                          */
+    OS_CPU_CM4_NVIC_ST_CTRL |= OS_CPU_CM4_NVIC_ST_CTRL_CLK_SRC |
+                               OS_CPU_CM4_NVIC_ST_CTRL_ENABLE;
+    /* Enable timer interrupt.                                */
+    OS_CPU_CM4_NVIC_ST_CTRL |= OS_CPU_CM4_NVIC_ST_CTRL_INTEN;
+}

+ 327 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/GNU/os_dbg.c

@@ -0,0 +1,327 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                           DEBUGGER CONSTANTS
+*
+*                              (c) Copyright 1992-2009, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_DBG.C
+* By      : Jean J. Labrosse
+* Version : V2.92.09
+*
+* LICENSING TERMS:
+* ---------------
+*           uC/OS-II is provided in source form for FREE short-term evaluation, for educational use or 
+*           for peaceful research.  If you plan or intend to use uC/OS-II in a commercial application/
+*           product then, you need to contact Micrium to properly license uC/OS-II for its use in your 
+*           application/product.   We provide ALL the source code for your convenience and to help you 
+*           experience uC/OS-II.  The fact that the source is provided does NOT mean that you can use 
+*           it commercially without paying a licensing fee.
+*
+*           Knowledge of the source code may NOT be used to develop a similar product.
+*
+*           Please help us continue to provide the embedded community with the finest software available.
+*           Your honesty is greatly appreciated.
+*
+*           You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
+*
+* For       : ARMv7 Cortex-M4
+* Mode      : Thumb-2 ISA
+* Toolchain : GNU C Compiler
+*********************************************************************************************************
+*/
+
+#include <ucos_ii.h>
+
+#define  OS_COMPILER_OPT
+
+/*
+*********************************************************************************************************
+*                                             DEBUG DATA
+*********************************************************************************************************
+*/
+
+OS_COMPILER_OPT  INT16U  const  OSDebugEn           = OS_DEBUG_EN;               /* Debug constants are defined below   */
+
+#if OS_DEBUG_EN > 0u
+
+OS_COMPILER_OPT  INT32U  const  OSEndiannessTest    = 0x12345678L;               /* Variable to test CPU endianness     */
+
+OS_COMPILER_OPT  INT16U  const  OSEventEn           = OS_EVENT_EN;
+OS_COMPILER_OPT  INT16U  const  OSEventMax          = OS_MAX_EVENTS;             /* Number of event control blocks      */
+OS_COMPILER_OPT  INT16U  const  OSEventNameEn       = OS_EVENT_NAME_EN;
+#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u)
+OS_COMPILER_OPT  INT16U  const  OSEventSize         = sizeof(OS_EVENT);          /* Size in Bytes of OS_EVENT           */
+OS_COMPILER_OPT  INT16U  const  OSEventTblSize      = sizeof(OSEventTbl);        /* Size of OSEventTbl[] in bytes       */
+#else
+OS_COMPILER_OPT  INT16U  const  OSEventSize         = 0u;
+OS_COMPILER_OPT  INT16U  const  OSEventTblSize      = 0u;
+#endif
+OS_COMPILER_OPT  INT16U  const  OSEventMultiEn      = OS_EVENT_MULTI_EN;
+
+
+OS_COMPILER_OPT  INT16U  const  OSFlagEn            = OS_FLAG_EN;
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+OS_COMPILER_OPT  INT16U  const  OSFlagGrpSize       = sizeof(OS_FLAG_GRP);       /* Size in Bytes of OS_FLAG_GRP        */
+OS_COMPILER_OPT  INT16U  const  OSFlagNodeSize      = sizeof(OS_FLAG_NODE);      /* Size in Bytes of OS_FLAG_NODE       */
+OS_COMPILER_OPT  INT16U  const  OSFlagWidth         = sizeof(OS_FLAGS);          /* Width (in bytes) of OS_FLAGS        */
+#else
+OS_COMPILER_OPT  INT16U  const  OSFlagGrpSize       = 0u;
+OS_COMPILER_OPT  INT16U  const  OSFlagNodeSize      = 0u;
+OS_COMPILER_OPT  INT16U  const  OSFlagWidth         = 0u;
+#endif
+OS_COMPILER_OPT  INT16U  const  OSFlagMax           = OS_MAX_FLAGS;
+OS_COMPILER_OPT  INT16U  const  OSFlagNameEn        = OS_FLAG_NAME_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSLowestPrio        = OS_LOWEST_PRIO;
+
+OS_COMPILER_OPT  INT16U  const  OSMboxEn            = OS_MBOX_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSMemEn             = OS_MEM_EN;
+OS_COMPILER_OPT  INT16U  const  OSMemMax            = OS_MAX_MEM_PART;           /* Number of memory partitions         */
+OS_COMPILER_OPT  INT16U  const  OSMemNameEn         = OS_MEM_NAME_EN;
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+OS_COMPILER_OPT  INT16U  const  OSMemSize           = sizeof(OS_MEM);            /* Mem. Partition header sine (bytes)  */
+OS_COMPILER_OPT  INT16U  const  OSMemTblSize        = sizeof(OSMemTbl);
+#else
+OS_COMPILER_OPT  INT16U  const  OSMemSize           = 0u;
+OS_COMPILER_OPT  INT16U  const  OSMemTblSize        = 0u;
+#endif
+OS_COMPILER_OPT  INT16U  const  OSMutexEn           = OS_MUTEX_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSPtrSize           = sizeof(void *);            /* Size in Bytes of a pointer          */
+
+OS_COMPILER_OPT  INT16U  const  OSQEn               = OS_Q_EN;
+OS_COMPILER_OPT  INT16U  const  OSQMax              = OS_MAX_QS;                 /* Number of queues                    */
+#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+OS_COMPILER_OPT  INT16U  const  OSQSize             = sizeof(OS_Q);              /* Size in bytes of OS_Q structure     */
+#else
+OS_COMPILER_OPT  INT16U  const  OSQSize             = 0u;
+#endif
+
+OS_COMPILER_OPT  INT16U  const  OSRdyTblSize        = OS_RDY_TBL_SIZE;           /* Number of bytes in the ready table  */
+
+OS_COMPILER_OPT  INT16U  const  OSSemEn             = OS_SEM_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSStkWidth          = sizeof(OS_STK);            /* Size in Bytes of a stack entry      */
+
+OS_COMPILER_OPT  INT16U  const  OSTaskCreateEn      = OS_TASK_CREATE_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskCreateExtEn   = OS_TASK_CREATE_EXT_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskDelEn         = OS_TASK_DEL_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskIdleStkSize   = OS_TASK_IDLE_STK_SIZE;
+OS_COMPILER_OPT  INT16U  const  OSTaskProfileEn     = OS_TASK_PROFILE_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskMax           = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks      */
+OS_COMPILER_OPT  INT16U  const  OSTaskNameEn        = OS_TASK_NAME_EN;  
+OS_COMPILER_OPT  INT16U  const  OSTaskStatEn        = OS_TASK_STAT_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskStatStkSize   = OS_TASK_STAT_STK_SIZE;
+OS_COMPILER_OPT  INT16U  const  OSTaskStatStkChkEn  = OS_TASK_STAT_STK_CHK_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskSwHookEn      = OS_TASK_SW_HOOK_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskRegTblSize    = OS_TASK_REG_TBL_SIZE;
+
+OS_COMPILER_OPT  INT16U  const  OSTCBPrioTblMax     = OS_LOWEST_PRIO + 1u;       /* Number of entries in OSTCBPrioTbl[] */
+OS_COMPILER_OPT  INT16U  const  OSTCBSize           = sizeof(OS_TCB);            /* Size in Bytes of OS_TCB             */
+OS_COMPILER_OPT  INT16U  const  OSTicksPerSec       = OS_TICKS_PER_SEC;
+OS_COMPILER_OPT  INT16U  const  OSTimeTickHookEn    = OS_TIME_TICK_HOOK_EN;
+OS_COMPILER_OPT  INT16U  const  OSVersionNbr        = OS_VERSION;
+
+OS_COMPILER_OPT  INT16U  const  OSTmrEn             = OS_TMR_EN;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgMax         = OS_TMR_CFG_MAX;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgNameEn      = OS_TMR_CFG_NAME_EN;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgWheelSize   = OS_TMR_CFG_WHEEL_SIZE;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC;
+
+#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u)
+OS_COMPILER_OPT  INT16U  const  OSTmrSize           = sizeof(OS_TMR);
+OS_COMPILER_OPT  INT16U  const  OSTmrTblSize        = sizeof(OSTmrTbl);
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelSize      = sizeof(OS_TMR_WHEEL);
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelTblSize   = sizeof(OSTmrWheelTbl);
+#else
+OS_COMPILER_OPT  INT16U  const  OSTmrSize           = 0u;
+OS_COMPILER_OPT  INT16U  const  OSTmrTblSize        = 0u;
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelSize      = 0u;
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelTblSize   = 0u;
+#endif
+
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                             DEBUG DATA
+*                            TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II
+*********************************************************************************************************
+*/
+#if OS_DEBUG_EN > 0u
+
+OS_COMPILER_OPT  INT16U  const  OSDataSize = sizeof(OSCtxSwCtr)
+#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u)
+                          + sizeof(OSEventFreeList)
+                          + sizeof(OSEventTbl)
+#endif
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+                          + sizeof(OSFlagTbl)
+                          + sizeof(OSFlagFreeList)
+#endif
+#if OS_TASK_STAT_EN > 0u
+                          + sizeof(OSCPUUsage)
+                          + sizeof(OSIdleCtrMax)
+                          + sizeof(OSIdleCtrRun)
+                          + sizeof(OSStatRdy)
+                          + sizeof(OSTaskStatStk)
+#endif
+#if OS_TICK_STEP_EN > 0u
+                          + sizeof(OSTickStepState)
+#endif
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+                          + sizeof(OSMemFreeList)
+                          + sizeof(OSMemTbl)
+#endif
+#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+                          + sizeof(OSQFreeList)
+                          + sizeof(OSQTbl)
+#endif
+#if OS_TIME_GET_SET_EN > 0u   
+                          + sizeof(OSTime)
+#endif
+#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u)
+                          + sizeof(OSTmrFree)
+                          + sizeof(OSTmrUsed)
+                          + sizeof(OSTmrTime)
+                          + sizeof(OSTmrSem)
+                          + sizeof(OSTmrSemSignal)
+                          + sizeof(OSTmrTbl)
+                          + sizeof(OSTmrFreeList)
+                          + sizeof(OSTmrTaskStk)
+                          + sizeof(OSTmrWheelTbl)
+#endif
+                          + sizeof(OSIntNesting)
+                          + sizeof(OSLockNesting)
+                          + sizeof(OSPrioCur)
+                          + sizeof(OSPrioHighRdy)
+                          + sizeof(OSRdyGrp)
+                          + sizeof(OSRdyTbl)
+                          + sizeof(OSRunning)
+                          + sizeof(OSTaskCtr)
+                          + sizeof(OSIdleCtr)
+                          + sizeof(OSTaskIdleStk)
+                          + sizeof(OSTCBCur)
+                          + sizeof(OSTCBFreeList)
+                          + sizeof(OSTCBHighRdy)
+                          + sizeof(OSTCBList)
+                          + sizeof(OSTCBPrioTbl)
+                          + sizeof(OSTCBTbl);
+
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                        OS DEBUG INITIALIZATION
+*
+* Description: This function is used to make sure that debug variables that are unused in the application
+*              are not optimized away.  This function might not be necessary for all compilers.  In this
+*              case, you should simply DELETE the code in this function while still leaving the declaration
+*              of the function itself.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Note(s)    : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out
+*                  the 'const' variables which are declared in this file.
+*              (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function 
+*                  if your compiler DOES NOT optimize out the 'const' variables above.
+*********************************************************************************************************
+*/
+
+#if OS_DEBUG_EN > 0u
+void  OSDebugInit (void)
+{
+    void  *ptemp;
+
+    
+    ptemp = (void *)&OSDebugEn;
+
+    ptemp = (void *)&OSEndiannessTest;
+
+    ptemp = (void *)&OSEventMax;
+    ptemp = (void *)&OSEventNameEn;
+    ptemp = (void *)&OSEventEn;
+    ptemp = (void *)&OSEventSize;
+    ptemp = (void *)&OSEventTblSize;
+    ptemp = (void *)&OSEventMultiEn;
+
+    ptemp = (void *)&OSFlagEn;
+    ptemp = (void *)&OSFlagGrpSize;
+    ptemp = (void *)&OSFlagNodeSize;
+    ptemp = (void *)&OSFlagWidth;
+    ptemp = (void *)&OSFlagMax;
+    ptemp = (void *)&OSFlagNameEn;
+
+    ptemp = (void *)&OSLowestPrio;
+
+    ptemp = (void *)&OSMboxEn;
+
+    ptemp = (void *)&OSMemEn;
+    ptemp = (void *)&OSMemMax;
+    ptemp = (void *)&OSMemNameEn;
+    ptemp = (void *)&OSMemSize;
+    ptemp = (void *)&OSMemTblSize;
+
+    ptemp = (void *)&OSMutexEn;
+
+    ptemp = (void *)&OSPtrSize;
+
+    ptemp = (void *)&OSQEn;
+    ptemp = (void *)&OSQMax;
+    ptemp = (void *)&OSQSize;
+
+    ptemp = (void *)&OSRdyTblSize;
+
+    ptemp = (void *)&OSSemEn;
+
+    ptemp = (void *)&OSStkWidth;
+
+    ptemp = (void *)&OSTaskCreateEn;
+    ptemp = (void *)&OSTaskCreateExtEn;
+    ptemp = (void *)&OSTaskDelEn;
+    ptemp = (void *)&OSTaskIdleStkSize;
+    ptemp = (void *)&OSTaskProfileEn;
+    ptemp = (void *)&OSTaskMax;
+    ptemp = (void *)&OSTaskNameEn;
+    ptemp = (void *)&OSTaskStatEn;
+    ptemp = (void *)&OSTaskStatStkSize;
+    ptemp = (void *)&OSTaskStatStkChkEn;
+    ptemp = (void *)&OSTaskSwHookEn;
+
+    ptemp = (void *)&OSTCBPrioTblMax;
+    ptemp = (void *)&OSTCBSize;
+
+    ptemp = (void *)&OSTicksPerSec;
+    ptemp = (void *)&OSTimeTickHookEn;
+
+#if OS_TMR_EN > 0u
+    ptemp = (void *)&OSTmrTbl[0];
+    ptemp = (void *)&OSTmrWheelTbl[0];
+    
+    ptemp = (void *)&OSTmrEn;
+    ptemp = (void *)&OSTmrCfgMax;
+    ptemp = (void *)&OSTmrCfgNameEn;
+    ptemp = (void *)&OSTmrCfgWheelSize;
+    ptemp = (void *)&OSTmrCfgTicksPerSec;
+    ptemp = (void *)&OSTmrSize;
+    ptemp = (void *)&OSTmrTblSize;
+
+    ptemp = (void *)&OSTmrWheelSize;
+    ptemp = (void *)&OSTmrWheelTblSize;
+#endif
+
+    ptemp = (void *)&OSVersionNbr;
+
+    ptemp = (void *)&OSDataSize;
+
+    ptemp = ptemp;                             /* Prevent compiler warning for 'ptemp' not being used! */
+}
+#endif

+ 189 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/IAR/os_cpu.h

@@ -0,0 +1,189 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*
+*
+*                         (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
+*                    All rights reserved.  Protected by international copyright laws.
+*
+*                                           ARM Cortex-M4 Port
+*
+* File      : OS_CPU.H
+* Version   : V2.92.09
+* By        : JJL
+*             JBL
+*
+* LICENSING TERMS:
+* ---------------
+*           uC/OS-II is provided in source form for FREE short-term evaluation, for educational use or 
+*           for peaceful research.  If you plan or intend to use uC/OS-II in a commercial application/
+*           product then, you need to contact Micrium to properly license uC/OS-II for its use in your 
+*           application/product.   We provide ALL the source code for your convenience and to help you 
+*           experience uC/OS-II.  The fact that the source is provided does NOT mean that you can use 
+*           it commercially without paying a licensing fee.
+*
+*           Knowledge of the source code may NOT be used to develop a similar product.
+*
+*           Please help us continue to provide the embedded community with the finest software available.
+*           Your honesty is greatly appreciated.
+*
+*           You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
+*
+* For       : ARMv7 Cortex-M4
+* Mode      : Thumb-2 ISA
+* Toolchain : IAR EWARM
+*********************************************************************************************************
+*/
+
+#ifndef  OS_CPU_H
+#define  OS_CPU_H
+
+#ifdef   OS_CPU_GLOBALS
+#define  OS_CPU_EXT
+#else
+#define  OS_CPU_EXT  extern
+#endif
+
+#ifndef  OS_CPU_EXCEPT_STK_SIZE
+#define  OS_CPU_EXCEPT_STK_SIZE    128u          /* Default exception stack size is 128 OS_STK entries */
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                               DEFINES
+*********************************************************************************************************
+*/
+
+#ifdef __ARMVFP__
+#define  OS_CPU_ARM_FP_EN                                 1u
+#else
+#define  OS_CPU_ARM_FP_EN                                 0u
+#endif
+
+
+/*
+*********************************************************************************************************
+*                              OS TICK INTERRUPT PRIORITY CONFIGURATION
+*
+* Note(s) : (1) For systems that don't need any high, real-time priority interrupts; the tick interrupt
+*               should be configured as the highest priority interrupt but won't adversely affect system
+*               operations.
+*
+*           (2) For systems that need one or more high, real-time interrupts; these should be configured
+*               higher than the tick interrupt which MAY delay execution of the tick interrupt.
+*
+*               (a) If the higher priority interrupts do NOT continually consume CPU cycles but only
+*                   occasionally delay tick interrupts, then the real-time interrupts can successfully
+*                   handle their intermittent/periodic events with the system not losing tick interrupts
+*                   but only increasing the jitter.
+*
+*               (b) If the higher priority interrupts consume enough CPU cycles to continually delay the
+*                   tick interrupt, then the CPU/system is most likely over-burdened & can't be expected
+*                   to handle all its interrupts/tasks. The system time reference gets compromised as a
+*                   result of losing tick interrupts.
+*********************************************************************************************************
+*/
+
+#define  OS_CPU_CFG_SYSTICK_PRIO           0u
+
+/*
+*********************************************************************************************************
+*                                              DATA TYPES
+*                                         (Compiler Specific)
+*********************************************************************************************************
+*/
+
+typedef unsigned char  BOOLEAN;
+typedef unsigned char  INT8U;                    /* Unsigned  8 bit quantity                           */
+typedef signed   char  INT8S;                    /* Signed    8 bit quantity                           */
+typedef unsigned short INT16U;                   /* Unsigned 16 bit quantity                           */
+typedef signed   short INT16S;                   /* Signed   16 bit quantity                           */
+typedef unsigned int   INT32U;                   /* Unsigned 32 bit quantity                           */
+typedef signed   int   INT32S;                   /* Signed   32 bit quantity                           */
+typedef float          FP32;                     /* Single precision floating point                    */
+typedef double         FP64;                     /* Double precision floating point                    */
+
+typedef unsigned int   OS_STK;                   /* Each stack entry is 32-bit wide                    */
+typedef unsigned int   OS_CPU_SR;                /* Define size of CPU status register (PSR = 32 bits) */
+
+
+/*
+*********************************************************************************************************
+*                                              Cortex-M4
+*                                      Critical Section Management
+*
+* Method #1:  Disable/Enable interrupts using simple instructions.  After critical section, interrupts
+*             will be enabled even if they were disabled before entering the critical section.
+*             NOT IMPLEMENTED
+*
+* Method #2:  Disable/Enable interrupts by preserving the state of interrupts.  In other words, if
+*             interrupts were disabled before entering the critical section, they will be disabled when
+*             leaving the critical section.
+*             NOT IMPLEMENTED
+*
+* Method #3:  Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
+*             would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
+*             disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
+*             disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
+*             into the CPU's status register.
+*********************************************************************************************************
+*/
+
+#define  OS_CRITICAL_METHOD   3u
+
+#if OS_CRITICAL_METHOD == 3u
+#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}
+#define  OS_EXIT_CRITICAL()   {OS_CPU_SR_Restore(cpu_sr);}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                        Cortex-M4 Miscellaneous
+*********************************************************************************************************
+*/
+
+#define  OS_STK_GROWTH        1u                  /* Stack grows from HIGH to LOW memory on ARM        */
+
+#define  OS_TASK_SW()         OSCtxSw()
+
+
+/*
+*********************************************************************************************************
+*                                          GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+OS_CPU_EXT  OS_STK   OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE];
+OS_CPU_EXT  OS_STK  *OS_CPU_ExceptStkBase;
+
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+#if OS_CRITICAL_METHOD == 3u                      /* See OS_CPU_A.ASM                                  */
+OS_CPU_SR  OS_CPU_SR_Save    (void);
+void       OS_CPU_SR_Restore (OS_CPU_SR cpu_sr);
+#endif
+
+void  OSCtxSw                (void);
+void  OSIntCtxSw             (void);
+void  OSStartHighRdy         (void);
+
+void  OS_CPU_PendSVHandler   (void);
+
+                                                  /* See OS_CPU_C.C                                    */
+void  OS_CPU_SysTickHandler  (void);
+void  OS_CPU_SysTickInit     (INT32U    cnts);
+
+#if (OS_CPU_ARM_FP_EN > 0u)
+void  OS_CPU_FP_Reg_Push     (OS_STK   *stkPtr);
+void  OS_CPU_FP_Reg_Pop      (OS_STK   *stkPtr);
+#endif
+
+#endif

+ 306 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/IAR/os_cpu_a.asm

@@ -0,0 +1,306 @@
+;
+;********************************************************************************************************
+;                                                uC/OS-II
+;                                          The Real-Time Kernel
+;
+;
+;                         (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
+;                    All rights reserved.  Protected by international copyright laws.
+;
+;                                           ARM Cortex-M4 Port
+;
+; File      : OS_CPU_A.ASM
+; Version   : V2.92.09
+; By        : JJL
+;             BAN
+;             JBL
+;
+; For       : ARMv7 Cortex-M4
+; Mode      : Thumb-2 ISA
+; Toolchain : IAR EWARM
+;********************************************************************************************************
+;
+
+;********************************************************************************************************
+;                                          PUBLIC FUNCTIONS
+;********************************************************************************************************
+
+    EXTERN  OSRunning                                           ; External references
+    EXTERN  OSPrioCur
+    EXTERN  OSPrioHighRdy
+    EXTERN  OSTCBCur
+    EXTERN  OSTCBHighRdy
+    EXTERN  OSIntExit
+    EXTERN  OSTaskSwHook
+    EXTERN  OS_CPU_ExceptStkBase
+
+    PUBLIC  OS_CPU_SR_Save                                      ; Functions declared in this file
+    PUBLIC  OS_CPU_SR_Restore
+    PUBLIC  OSStartHighRdy
+    PUBLIC  OSCtxSw
+    PUBLIC  OSIntCtxSw
+    PUBLIC  OS_CPU_PendSVHandler
+    
+#ifdef __ARMVFP__  
+    PUBLIC  OS_CPU_FP_Reg_Push
+    PUBLIC  OS_CPU_FP_Reg_Pop
+#endif    
+
+
+;********************************************************************************************************
+;                                               EQUATES
+;********************************************************************************************************
+
+NVIC_INT_CTRL   EQU     0xE000ED04                              ; Interrupt control state register.
+NVIC_SYSPRI14   EQU     0xE000ED22                              ; System priority register (priority 14).
+NVIC_PENDSV_PRI EQU           0xFF                              ; PendSV priority value (lowest).
+NVIC_PENDSVSET  EQU     0x10000000                              ; Value to trigger PendSV exception.
+
+
+;********************************************************************************************************
+;                                     CODE GENERATION DIRECTIVES
+;********************************************************************************************************
+
+    RSEG CODE:CODE:NOROOT(2)
+    THUMB
+
+
+;********************************************************************************************************
+;                                   FLOATING POINT REGISTERS PUSH
+;                             void  OS_CPU_FP_Reg_Push (OS_STK  *stkPtr)
+;
+; Note(s) : 1) This function saves S0-S31, and FPSCR registers of the Floating Point Unit.
+;
+;           2) Pseudo-code is:
+;              a) Get FPSCR register value;
+;              b) Push value on process stack;
+;              c) Push remaining regs S0-S31 on process stack;
+;              d) Update OSTCBCur->OSTCBStkPtr;
+;********************************************************************************************************
+
+#ifdef __ARMVFP__
+OS_CPU_FP_Reg_Push
+    MRS     R1, PSP                                             ; PSP is process stack pointer
+    CBZ     R1, OS_CPU_FP_nosave                                ; Skip FP register save the first time
+    
+    VMRS    R1, FPSCR
+    STR R1, [R0, #-4]!
+    VSTMDB  R0!, {S0-S31}
+    LDR     R1, =OSTCBCur
+    LDR     R2, [R1]
+    STR     R0, [R2]
+OS_CPU_FP_nosave    
+    BX      LR
+#endif
+
+
+;********************************************************************************************************
+;                                   FLOATING POINT REGISTERS POP
+;                             void  OS_CPU_FP_Reg_Pop (OS_STK  *stkPtr)
+;
+; Note(s) : 1) This function restores S0-S31, and FPSCR registers of the Floating Point Unit.
+;
+;           2) Pseudo-code is:
+;              a) Restore regs S0-S31 of new process stack;
+;              b) Restore FPSCR reg value
+;              c) Update OSTCBHighRdy->OSTCBStkPtr pointer of new proces stack;
+;********************************************************************************************************
+
+#ifdef __ARMVFP__
+OS_CPU_FP_Reg_Pop
+    VLDMIA  R0!, {S0-S31}
+    LDMIA   R0!, {R1}
+    VMSR    FPSCR, R1    
+    LDR     R1, =OSTCBHighRdy
+    LDR     R2, [R1]
+    STR     R0, [R2]
+    BX      LR
+#endif
+
+
+;********************************************************************************************************
+;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
+;
+; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
+;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
+;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
+;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
+;              into the CPU's status register.
+;
+; Prototypes :     OS_CPU_SR  OS_CPU_SR_Save(void);
+;                  void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
+;
+;
+; Note(s)    : 1) These functions are used in general like this:
+;
+;                 void Task (void *p_arg)
+;                 {
+;                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
+;                     OS_CPU_SR  cpu_sr;
+;                 #endif
+;
+;                          :
+;                          :
+;                     OS_ENTER_CRITICAL();             /* cpu_sr = OS_CPU_SaveSR();                */
+;                          :
+;                          :
+;                     OS_EXIT_CRITICAL();              /* OS_CPU_RestoreSR(cpu_sr);                */
+;                          :
+;                          :
+;                 }
+;********************************************************************************************************
+
+OS_CPU_SR_Save
+    MRS     R0, PRIMASK                                         ; Set prio int mask to mask all (except faults)
+    CPSID   I
+    BX      LR
+
+OS_CPU_SR_Restore
+    MSR     PRIMASK, R0
+    BX      LR
+
+
+;********************************************************************************************************
+;                                         START MULTITASKING
+;                                      void OSStartHighRdy(void)
+;
+; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause
+;              the first task to start.
+;
+;           2) OSStartHighRdy() MUST:
+;              a) Setup PendSV exception priority to lowest;
+;              b) Set initial PSP to 0, to tell context switcher this is first run;
+;              c) Set the main stack to OS_CPU_ExceptStkBase
+;              d) Set OSRunning to TRUE;
+;              e) Trigger PendSV exception;
+;              f) Enable interrupts (tasks will run with interrupts enabled).
+;********************************************************************************************************
+
+OSStartHighRdy
+    LDR     R0, =NVIC_SYSPRI14                                  ; Set the PendSV exception priority
+    LDR     R1, =NVIC_PENDSV_PRI
+    STRB    R1, [R0]
+
+    MOVS    R0, #0                                              ; Set the PSP to 0 for initial context switch call
+    MSR     PSP, R0
+
+    LDR     R0, =OS_CPU_ExceptStkBase                           ; Initialize the MSP to the OS_CPU_ExceptStkBase
+    LDR     R1, [R0]
+    MSR     MSP, R1    
+
+    LDR     R0, =OSRunning                                      ; OSRunning = TRUE
+    MOVS    R1, #1
+    STRB    R1, [R0]
+
+    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
+    LDR     R1, =NVIC_PENDSVSET
+    STR     R1, [R0]
+
+    CPSIE   I                                                   ; Enable interrupts at processor level
+
+OSStartHang
+    B       OSStartHang                                         ; Should never get here
+
+
+;********************************************************************************************************
+;                       PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
+;
+; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch.  This function
+;              triggers the PendSV exception which is where the real work is done.
+;********************************************************************************************************
+
+OSCtxSw
+    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
+    LDR     R1, =NVIC_PENDSVSET
+    STR     R1, [R0]
+    BX      LR
+
+
+;********************************************************************************************************
+;                   PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
+;
+; Note(s) : 1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as
+;              the result of an interrupt.  This function simply triggers a PendSV exception which will
+;              be handled when there are no more interrupts active and interrupts are enabled.
+;********************************************************************************************************
+
+OSIntCtxSw
+    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
+    LDR     R1, =NVIC_PENDSVSET
+    STR     R1, [R0]
+    BX      LR
+
+
+;********************************************************************************************************
+;                                       HANDLE PendSV EXCEPTION
+;                                   void OS_CPU_PendSVHandler(void)
+;
+; Note(s) : 1) PendSV is used to cause a context switch.  This is a recommended method for performing
+;              context switches with Cortex-M3.  This is because the Cortex-M3 auto-saves half of the
+;              processor context on any exception, and restores same on return from exception.  So only
+;              saving of R4-R11 is required and fixing up the stack pointers.  Using the PendSV exception
+;              this way means that context saving and restoring is identical whether it is initiated from
+;              a thread or occurs due to an interrupt or exception.
+;
+;           2) Pseudo-code is:
+;              a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch);
+;              b) Save remaining regs r4-r11 on process stack;
+;              c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP;
+;              d) Call OSTaskSwHook();
+;              e) Get current high priority, OSPrioCur = OSPrioHighRdy;
+;              f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
+;              g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
+;              h) Restore R4-R11 from new process stack;
+;              i) Perform exception return which will restore remaining context.
+;
+;           3) On entry into PendSV handler:
+;              a) The following have been saved on the process stack (by processor):
+;                 xPSR, PC, LR, R12, R0-R3
+;              b) Processor mode is switched to Handler mode (from Thread mode)
+;              c) Stack is Main stack (switched from Process stack)
+;              d) OSTCBCur      points to the OS_TCB of the task to suspend
+;                 OSTCBHighRdy  points to the OS_TCB of the task to resume
+;
+;           4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
+;              know that it will only be run when no other exception or interrupt is active, and
+;              therefore safe to assume that context being switched out was using the process stack (PSP).
+;********************************************************************************************************
+
+OS_CPU_PendSVHandler
+    CPSID   I                                                   ; Prevent interruption during context switch
+    MRS     R0, PSP                                             ; PSP is process stack pointer
+    CBZ     R0, OS_CPU_PendSVHandler_nosave                     ; Skip register save the first time
+
+    SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
+    STM     R0, {R4-R11}
+
+    LDR     R1, =OSTCBCur                                       ; OSTCBCur->OSTCBStkPtr = SP;
+    LDR     R1, [R1]
+    STR     R0, [R1]                                            ; R0 is SP of process being switched out
+
+                                                                ; At this point, entire context of process has been saved
+OS_CPU_PendSVHandler_nosave
+    PUSH    {R14}                                               ; Save LR exc_return value
+    LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
+    BLX     R0
+    POP     {R14}
+
+    LDR     R0, =OSPrioCur                                      ; OSPrioCur = OSPrioHighRdy;
+    LDR     R1, =OSPrioHighRdy
+    LDRB    R2, [R1]
+    STRB    R2, [R0]
+
+    LDR     R0, =OSTCBCur                                       ; OSTCBCur  = OSTCBHighRdy;
+    LDR     R1, =OSTCBHighRdy
+    LDR     R2, [R1]
+    STR     R2, [R0]
+
+    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
+    LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
+    ADDS    R0, R0, #0x20
+    MSR     PSP, R0                                             ; Load PSP with new process SP
+    ORR     LR, LR, #0xF4                                       ; Ensure exception return uses process stack
+    CPSIE   I
+    BX      LR                                                  ; Exception return will restore remaining context
+
+    END

+ 624 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/IAR/os_cpu_c.c

@@ -0,0 +1,624 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*
+*
+*                           (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
+*                    All rights reserved.  Protected by international copyright laws.
+*
+*                                           ARM Cortex-M4 Port
+*
+* File      : OS_CPU_C.C
+* Version   : V2.92.09
+* By        : JJL
+*             BAN
+*
+* LICENSING TERMS:
+* ---------------
+*           uC/OS-II is provided in source form for FREE short-term evaluation, for educational use or 
+*           for peaceful research.  If you plan or intend to use uC/OS-II in a commercial application/
+*           product then, you need to contact Micrium to properly license uC/OS-II for its use in your 
+*           experience uC/OS-II.  The fact that the source is provided does NOT mean that you can use 
+*           it commercially without paying a licensing fee.
+*
+*           Knowledge of the source code may NOT be used to develop a similar product.
+*
+*           Please help us continue to provide the embedded community with the finest software available.
+*           Your honesty is greatly appreciated.
+*
+*           You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
+*
+* For       : ARMv7 Cortex-M4
+* Mode      : Thumb-2 ISA
+* Toolchain : IAR EWARM
+*********************************************************************************************************
+*/
+
+#define   OS_CPU_GLOBALS
+
+
+/*
+*********************************************************************************************************
+*                                             INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#include  <ucos_ii.h>
+#include  <lib_def.h>
+
+
+/*
+*********************************************************************************************************
+*                                          LOCAL VARIABLES
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+static  INT16U  OSTmrCtr;
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          SYS TICK DEFINES
+*********************************************************************************************************
+*/
+
+#define  OS_CPU_CM4_NVIC_ST_CTRL    (*((volatile INT32U *)0xE000E010uL)) /* SysTick Ctrl & Status Reg.                  */
+#define  OS_CPU_CM4_NVIC_ST_RELOAD  (*((volatile INT32U *)0xE000E014uL)) /* SysTick Reload  Value Reg.                  */
+#define  OS_CPU_CM4_NVIC_ST_CURRENT (*((volatile INT32U *)0xE000E018uL)) /* SysTick Current Value Reg.                  */
+#define  OS_CPU_CM4_NVIC_ST_CAL     (*((volatile INT32U *)0xE000E01CuL)) /* SysTick Cal     Value Reg.                  */
+#define  OS_CPU_CM4_NVIC_SHPRI1     (*((volatile INT32U *)0xE000ED18uL)) /* System Handlers  4 to  7 Prio.              */
+#define  OS_CPU_CM4_NVIC_SHPRI2     (*((volatile INT32U *)0xE000ED1CuL)) /* System Handlers  8 to 11 Prio.              */
+#define  OS_CPU_CM4_NVIC_SHPRI3     (*((volatile INT32U *)0xE000ED20uL)) /* System Handlers 12 to 15 Prio.              */
+
+
+#define  OS_CPU_CM4_NVIC_ST_CTRL_COUNT                    0x00010000uL   /* Count flag.                                 */
+#define  OS_CPU_CM4_NVIC_ST_CTRL_CLK_SRC                  0x00000004uL   /* Clock Source.                               */
+#define  OS_CPU_CM4_NVIC_ST_CTRL_INTEN                    0x00000002uL   /* Interrupt enable.                           */
+#define  OS_CPU_CM4_NVIC_ST_CTRL_ENABLE                   0x00000001uL   /* Counter mode.                               */
+#define  OS_CPU_CM4_NVIC_PRIO_MIN                               0xFFu    /* Min handler prio.                           */
+
+
+/*
+*********************************************************************************************************
+*                                       OS INITIALIZATION HOOK
+*                                            (BEGINNING)
+*
+* Description: This function is called by OSInit() at the beginning of OSInit().
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts should be disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSInitHookBegin (void)
+{
+    INT32U   size;
+    OS_STK  *pstk;
+
+                                                                /* Clear exception stack for stack checking.            */
+    pstk = &OS_CPU_ExceptStk[0];
+    size = OS_CPU_EXCEPT_STK_SIZE;
+    while (size > 0u) {
+        size--;
+       *pstk++ = (OS_STK)0;
+    }
+
+                                                                /* Align the ISR stack to 8-bytes                       */
+    OS_CPU_ExceptStkBase = (OS_STK *)&OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE];
+    OS_CPU_ExceptStkBase = (OS_STK *)((OS_STK)(OS_CPU_ExceptStkBase) & 0xFFFFFFF8);
+
+#if OS_TMR_EN > 0u
+    OSTmrCtr = 0u;
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                       OS INITIALIZATION HOOK
+*                                               (END)
+*
+* Description: This function is called by OSInit() at the end of OSInit().
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts should be disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSInitHookEnd (void)
+{
+
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          TASK CREATION HOOK
+*
+* Description: This function is called when a task is created.
+*
+* Arguments  : ptcb   is a pointer to the task control block of the task being created.
+*
+* Note(s)    : 1) Interrupts are disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTaskCreateHook (OS_TCB *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskCreateHook(ptcb);
+#else
+    (void)ptcb;                                                 /* Prevent compiler warning                             */
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                           TASK DELETION HOOK
+*
+* Description: This function is called when a task is deleted.
+*
+* Arguments  : ptcb   is a pointer to the task control block of the task being deleted.
+*
+* Note(s)    : 1) Interrupts are disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTaskDelHook (OS_TCB *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskDelHook(ptcb);
+#else
+    (void)ptcb;                                                 /* Prevent compiler warning                             */
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             IDLE TASK HOOK
+*
+* Description: This function is called by the idle task.  This hook has been added to allow you to do
+*              such things as STOP the CPU to conserve power.
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts are enabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTaskIdleHook (void)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskIdleHook();
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                            TASK RETURN HOOK
+*
+* Description: This function is called if a task accidentally returns.  In other words, a task should
+*              either be an infinite loop or delete itself when done.
+*
+* Arguments  : ptcb      is a pointer to the task control block of the task that is returning.
+*
+* Note(s)    : none
+*********************************************************************************************************
+*/
+
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTaskReturnHook (OS_TCB  *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskReturnHook(ptcb);
+#else
+    (void)ptcb;
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                           STATISTIC TASK HOOK
+*
+* Description: This function is called every second by uC/OS-II's statistics task.  This allows your
+*              application to add functionality to the statistics task.
+*
+* Arguments  : none
+*********************************************************************************************************
+*/
+
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTaskStatHook (void)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskStatHook();
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                        INITIALIZE A TASK'S STACK
+*
+* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
+*              stack frame of the task being created.  This function is highly processor specific.
+*
+* Arguments  : task          is a pointer to the task code
+*
+*              p_arg         is a pointer to a user supplied data area that will be passed to the task
+*                            when the task first executes.
+*
+*              ptos          is a pointer to the top of stack.  It is assumed that 'ptos' points to
+*                            a 'free' entry on the task stack.  If OS_STK_GROWTH is set to 1 then
+*                            'ptos' will contain the HIGHEST valid address of the stack.  Similarly, if
+*                            OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
+*                            of the stack.
+*
+*              opt           specifies options that can be used to alter the behavior of OSTaskStkInit().
+*                            (see uCOS_II.H for OS_TASK_OPT_xxx).
+*
+* Returns    : Always returns the location of the new top-of-stack once the processor registers have
+*              been placed on the stack in the proper order.
+*
+* Note(s)    : (1) Interrupts are enabled when task starts executing.
+*
+*              (2) All tasks run in Thread mode, using process stack.
+*
+*              (3) There are two different stack frames depending on whether the Floating-Point(FP)
+*                  co-processor is enabled or not.
+*
+*                  (a) The stack frame shown in the diagram is used when the FP co-processor is not present and
+*                      OS_TASK_OPT_SAVE_FP is disabled. In this case, the FP registers and FP Status Control 
+*                      register are not saved in the stack frame.
+*
+*                  (b) If the FP co-processor is present but the OS_TASK_OPT_SAVE_FP is not set, then the stack
+*                      frame is saved as shown in diagram (a). Moreover, if OS_TASK_OPT_SAVE_FP is set, then the
+*                      FP registers and FP Status Control register are saved in the stack frame.
+*
+*                      (1) When enabling the FP co-processor, make sure to clear bits ASPEN and LSPEN in the
+*                          Floating-Point Context Control Register (FPCCR).
+*
+*                    +------------+       +------------+
+*                    |            |       |            |
+*                    +------------+       +------------+
+*                    |    xPSR    |       |    xPSR    | 
+*                    +------------+       +------------+       
+*                    |Return Addr |       |Return Addr |
+*                    +------------+       +------------+
+*                    |  LR(R14)   |       |   LR(R14)  |
+*                    +------------+       +------------+ 
+*                    |    R12     |       |     R12    | 
+*                    +------------+       +------------+
+*                    |    R3      |       |     R3     |
+*                    +------------+       +------------+
+*                    |    R2      |       |     R0     |
+*                    +------------+       +------------+
+*                    |    R1      |       |     R1     |
+*                    +------------+       +------------+
+*                    |    R0      |       |     R0     |
+*                    +------------+       +------------+
+*                    |    R11     |       |     R11    |
+*                    +------------+       +------------+
+*                    |    R10     |       |     R10    |
+*                    +------------+       +------------+
+*                    |    R9      |       |     R9     |
+*                    +------------+       +------------+
+*                    |    R8      |       |     R8     |
+*                    +------------+       +------------+
+*                    |    R7      |       |     R7     |
+*                    +------------+       +------------+
+*                    |    R6      |       |     R6     |
+*                    +------------+       +------------+
+*                    |    R5      |       |     R5     |
+*                    +------------+       +------------+
+*                    |    R4      |       |     R4     |
+*                    +------------+       +------------+
+*                         (a)             |   FPSCR    |
+*                                         +------------+
+*                                         |     S31    |
+*                                         +------------+
+*                                                .
+*                                                .
+*                                                .
+*                                         +------------+
+*                                         |     S1     |
+                                          +------------+
+*                                         |     S0     |
+*                                         +------------+
+*                                              (b)
+*
+*             (4) The SP must be 8-byte aligned in conforming to the Procedure Call Standard for the ARM architecture 
+*
+*                    (a) Section 2.1 of the  ABI for the ARM Architecture Advisory Note. SP must be 8-byte aligned 
+*                        on entry to AAPCS-Conforming functions states : 
+*                    
+*                        The Procedure Call Standard for the ARM Architecture [AAPCS] requires primitive 
+*                        data types to be naturally aligned according to their sizes (for size = 1, 2, 4, 8 bytes). 
+*                        Doing otherwise creates more problems than it solves. 
+*
+*                        In return for preserving the natural alignment of data, conforming code is permitted 
+*                        to rely on that alignment. To support aligning data allocated on the stack, the stack 
+*                        pointer (SP) is required to be 8-byte aligned on entry to a conforming function. In 
+*                        practice this requirement is met if:
+*
+*                           (1) At each call site, the current size of the calling function’s stack frame is a multiple of 8 bytes.
+*                               This places an obligation on compilers and assembly language programmers.
+*
+*                           (2) SP is a multiple of 8 when control first enters a program.
+*                               This places an obligation on authors of low level OS, RTOS, and runtime library 
+*                               code to align SP at all points at which control first enters 
+*                               a body of (AAPCS-conforming) code. 
+*              
+*                       In turn, this requires the value of SP to be aligned to 0 modulo 8:
+*
+*                           (3) By exception handlers, before calling AAPCS-conforming code.
+*
+*                           (4) By OS/RTOS/run-time system code, before giving control to an application.
+*
+*                 (b) Section 2.3.1 corrective steps from the the SP must be 8-byte aligned on entry 
+*                     to AAPCS-conforming functions advisory note also states.
+* 
+*                     " This requirement extends to operating systems and run-time code for all architecture versions 
+*                       prior to ARMV7 and to the A, R and M architecture profiles thereafter. Special considerations 
+*                       associated with ARMV7M are discussed in §2.3.3"
+* 
+*                     (1) Even if the SP 8-byte aligment is not a requirement for the ARMv7M profile, the stack is aligned
+*                         to 8-byte boundaries to support legacy execution enviroments.
+*
+*                 (c) Section 5.2.1.2 from the Procedure Call Standard for the ARM 
+*                     architecture states :  "The stack must also conform to the following 
+*                     constraint at a public interface:
+*
+*                     (1) SP mod 8 = 0. The stack must be double-word aligned"
+*
+*                 (d) From the ARM Technical Support Knowledge Base. 8 Byte stack aligment.
+*
+*                     "8 byte stack alignment is a requirement of the ARM Architecture Procedure 
+*                      Call Standard [AAPCS]. This specifies that functions must maintain an 8 byte 
+*                      aligned stack address (e.g. 0x00, 0x08, 0x10, 0x18, 0x20) on all external 
+*                      interfaces. In practice this requirement is met if:
+*
+*                      (1) At each external interface, the current stack pointer 
+*                          is a multiple of 8 bytes.
+* 
+*                      (2) Your OS maintains 8 byte stack alignment on its external interfaces 
+*                          e.g. on task switches"
+*
+**********************************************************************************************************
+*/
+
+OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
+{
+    OS_STK  *p_stk;
+
+
+    p_stk      = ptos + 1u;                                     /* Load stack pointer                                   */
+                                                                /* Align the stack to 8-bytes.                          */
+    p_stk      = (OS_STK *)((OS_STK)(p_stk) & 0xFFFFFFF8u);
+                                                                /* Registers stacked as if auto-saved on exception      */
+    *(--p_stk) = (OS_STK)0x01000000uL;                          /* xPSR                                                 */
+    *(--p_stk) = (OS_STK)task;                                  /* Entry Point                                          */
+    *(--p_stk) = (OS_STK)OS_TaskReturn;                         /* R14 (LR)                                             */
+    *(--p_stk) = (OS_STK)0x12121212uL;                          /* R12                                                  */
+    *(--p_stk) = (OS_STK)0x03030303uL;                          /* R3                                                   */
+    *(--p_stk) = (OS_STK)0x02020202uL;                          /* R2                                                   */
+    *(--p_stk) = (OS_STK)0x01010101uL;                          /* R1                                                   */
+    *(--p_stk) = (OS_STK)p_arg;                                 /* R0 : argument                                        */
+
+                                                                /* Remaining registers saved on process stack           */
+    *(--p_stk) = (OS_STK)0x11111111uL;                          /* R11                                                  */
+    *(--p_stk) = (OS_STK)0x10101010uL;                          /* R10                                                  */
+    *(--p_stk) = (OS_STK)0x09090909uL;                          /* R9                                                   */
+    *(--p_stk) = (OS_STK)0x08080808uL;                          /* R8                                                   */
+    *(--p_stk) = (OS_STK)0x07070707uL;                          /* R7                                                   */
+    *(--p_stk) = (OS_STK)0x06060606uL;                          /* R6                                                   */
+    *(--p_stk) = (OS_STK)0x05050505uL;                          /* R5                                                   */
+    *(--p_stk) = (OS_STK)0x04040404uL;                          /* R4                                                   */
+    
+#if (OS_CPU_ARM_FP_EN > 0u)
+    if ((opt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
+        *--p_stk = (OS_STK)0x02000000u;                         /* FPSCR                                                */
+                                                                /* Initialize S0-S31 floating point registers           */
+        *--p_stk = (OS_STK)0x41F80000u;                         /* S31                                                  */
+        *--p_stk = (OS_STK)0x41F00000u;                         /* S30                                                  */
+        *--p_stk = (OS_STK)0x41E80000u;                         /* S29                                                  */
+        *--p_stk = (OS_STK)0x41E00000u;                         /* S28                                                  */
+        *--p_stk = (OS_STK)0x41D80000u;                         /* S27                                                  */
+        *--p_stk = (OS_STK)0x41D00000u;                         /* S26                                                  */
+        *--p_stk = (OS_STK)0x41C80000u;                         /* S25                                                  */
+        *--p_stk = (OS_STK)0x41C00000u;                         /* S24                                                  */
+        *--p_stk = (OS_STK)0x41B80000u;                         /* S23                                                  */
+        *--p_stk = (OS_STK)0x41B00000u;                         /* S22                                                  */
+        *--p_stk = (OS_STK)0x41A80000u;                         /* S21                                                  */
+        *--p_stk = (OS_STK)0x41A00000u;                         /* S20                                                  */
+        *--p_stk = (OS_STK)0x41980000u;                         /* S19                                                  */
+        *--p_stk = (OS_STK)0x41900000u;                         /* S18                                                  */
+        *--p_stk = (OS_STK)0x41880000u;                         /* S17                                                  */
+        *--p_stk = (OS_STK)0x41800000u;                         /* S16                                                  */
+        *--p_stk = (OS_STK)0x41700000u;                         /* S15                                                  */
+        *--p_stk = (OS_STK)0x41600000u;                         /* S14                                                  */
+        *--p_stk = (OS_STK)0x41500000u;                         /* S13                                                  */
+        *--p_stk = (OS_STK)0x41400000u;                         /* S12                                                  */
+        *--p_stk = (OS_STK)0x41300000u;                         /* S11                                                  */
+        *--p_stk = (OS_STK)0x41200000u;                         /* S10                                                  */
+        *--p_stk = (OS_STK)0x41100000u;                         /* S9                                                   */
+        *--p_stk = (OS_STK)0x41000000u;                         /* S8                                                   */
+        *--p_stk = (OS_STK)0x40E00000u;                         /* S7                                                   */
+        *--p_stk = (OS_STK)0x40C00000u;                         /* S6                                                   */
+        *--p_stk = (OS_STK)0x40A00000u;                         /* S5                                                   */
+        *--p_stk = (OS_STK)0x40800000u;                         /* S4                                                   */
+        *--p_stk = (OS_STK)0x40400000u;                         /* S3                                                   */
+        *--p_stk = (OS_STK)0x40000000u;                         /* S2                                                   */
+        *--p_stk = (OS_STK)0x3F800000u;                         /* S1                                                   */
+        *--p_stk = (OS_STK)0x00000000u;                         /* S0                                                   */
+    }
+#endif    
+
+    return (p_stk);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           TASK SWITCH HOOK
+*
+* Description: This function is called when a task switch is performed.  This allows you to perform other
+*              operations during a context switch.
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts are disabled during this call.
+*              2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that
+*                 will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the
+*                 task being switched out (i.e. the preempted task).
+*********************************************************************************************************
+*/
+#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u)
+void  OSTaskSwHook (void)
+{
+    
+#if (OS_CPU_ARM_FP_EN > 0u)
+    if ((OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
+        OS_CPU_FP_Reg_Push(OSTCBCur->OSTCBStkPtr);
+    }
+
+    if ((OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
+        OS_CPU_FP_Reg_Pop(OSTCBHighRdy->OSTCBStkPtr);
+    }
+#endif
+    
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskSwHook();
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                           OS_TCBInit() HOOK
+*
+* Description: This function is called by OS_TCBInit() after setting up most of the TCB.
+*
+* Arguments  : ptcb    is a pointer to the TCB of the task being created.
+*
+* Note(s)    : 1) Interrupts may or may not be ENABLED during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTCBInitHook (OS_TCB *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TCBInitHook(ptcb);
+#else
+    (void)ptcb;                                                 /* Prevent compiler warning                             */
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                               TICK HOOK
+*
+* Description: This function is called every tick.
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts may or may not be ENABLED during this call.
+*********************************************************************************************************
+*/
+#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u)
+void  OSTimeTickHook (void)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TimeTickHook();
+#endif
+
+#if OS_TMR_EN > 0u
+    OSTmrCtr++;
+    if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) {
+        OSTmrCtr = 0;
+        OSTmrSignal();
+    }
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          SYS TICK HANDLER
+*
+* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-II tick
+*              interrupt.
+*
+* Arguments  : None.
+*
+* Note(s)    : 1) This function MUST be placed on entry 15 of the Cortex-M3 vector table.
+*********************************************************************************************************
+*/
+
+void  OS_CPU_SysTickHandler (void)
+{
+    OS_CPU_SR  cpu_sr;
+
+
+    OS_ENTER_CRITICAL();                                        /* Tell uC/OS-II that we are starting an ISR            */
+    OSIntNesting++;
+    OS_EXIT_CRITICAL();
+
+    OSTimeTick();                                               /* Call uC/OS-II's OSTimeTick()                         */
+
+    OSIntExit();                                                /* Tell uC/OS-II that we are leaving the ISR            */
+}
+
+
+/*
+*********************************************************************************************************
+*                                         INITIALIZE SYS TICK
+*
+* Description: Initialize the SysTick.
+*
+* Arguments  : cnts         Number of SysTick counts between two OS tick interrupts.
+*
+* Note(s)    : 1) This function MUST be called after OSStart() & after processor initialization.
+*********************************************************************************************************
+*/
+
+void  OS_CPU_SysTickInit (INT32U  cnts)
+{
+    INT32U  prio;
+
+
+    OS_CPU_CM4_NVIC_ST_RELOAD = cnts - 1u;
+
+                                                                /* Set SysTick handler prio.                            */
+    prio  = OS_CPU_CM4_NVIC_SHPRI3;
+    prio &= DEF_BIT_FIELD(24, 0);
+    prio |= DEF_BIT_MASK(OS_CPU_CFG_SYSTICK_PRIO, 24);
+
+    OS_CPU_CM4_NVIC_SHPRI3 = prio;
+
+                                                                /* Enable timer.                                        */
+    OS_CPU_CM4_NVIC_ST_CTRL |= OS_CPU_CM4_NVIC_ST_CTRL_CLK_SRC |
+                               OS_CPU_CM4_NVIC_ST_CTRL_ENABLE;
+                                                                /* Enable timer interrupt.                              */
+    OS_CPU_CM4_NVIC_ST_CTRL |= OS_CPU_CM4_NVIC_ST_CTRL_INTEN;
+}

+ 315 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/IAR/os_dbg.c

@@ -0,0 +1,315 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                           DEBUGGER CONSTANTS
+*
+*                              (c) Copyright 1992-2009, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_DBG.C
+* By      : Jean J. Labrosse
+* Version : V2.92.09
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.  
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micriµm to properly license 
+* its use in your product. We provide ALL the source code for your convenience and to help you experience 
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a 
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#include <ucos_ii.h>
+
+#define  OS_COMPILER_OPT  __root
+
+/*
+*********************************************************************************************************
+*                                             DEBUG DATA
+*********************************************************************************************************
+*/
+
+OS_COMPILER_OPT  INT16U  const  OSDebugEn           = OS_DEBUG_EN;               /* Debug constants are defined below   */
+
+#if OS_DEBUG_EN > 0u
+
+OS_COMPILER_OPT  INT32U  const  OSEndiannessTest    = 0x12345678L;               /* Variable to test CPU endianness     */
+
+OS_COMPILER_OPT  INT16U  const  OSEventEn           = OS_EVENT_EN;
+OS_COMPILER_OPT  INT16U  const  OSEventMax          = OS_MAX_EVENTS;             /* Number of event control blocks      */
+OS_COMPILER_OPT  INT16U  const  OSEventNameEn       = OS_EVENT_NAME_EN;
+#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u)
+OS_COMPILER_OPT  INT16U  const  OSEventSize         = sizeof(OS_EVENT);          /* Size in Bytes of OS_EVENT           */
+OS_COMPILER_OPT  INT16U  const  OSEventTblSize      = sizeof(OSEventTbl);        /* Size of OSEventTbl[] in bytes       */
+#else
+OS_COMPILER_OPT  INT16U  const  OSEventSize         = 0u;
+OS_COMPILER_OPT  INT16U  const  OSEventTblSize      = 0u;
+#endif
+OS_COMPILER_OPT  INT16U  const  OSEventMultiEn      = OS_EVENT_MULTI_EN;
+
+
+OS_COMPILER_OPT  INT16U  const  OSFlagEn            = OS_FLAG_EN;
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+OS_COMPILER_OPT  INT16U  const  OSFlagGrpSize       = sizeof(OS_FLAG_GRP);       /* Size in Bytes of OS_FLAG_GRP        */
+OS_COMPILER_OPT  INT16U  const  OSFlagNodeSize      = sizeof(OS_FLAG_NODE);      /* Size in Bytes of OS_FLAG_NODE       */
+OS_COMPILER_OPT  INT16U  const  OSFlagWidth         = sizeof(OS_FLAGS);          /* Width (in bytes) of OS_FLAGS        */
+#else
+OS_COMPILER_OPT  INT16U  const  OSFlagGrpSize       = 0u;
+OS_COMPILER_OPT  INT16U  const  OSFlagNodeSize      = 0u;
+OS_COMPILER_OPT  INT16U  const  OSFlagWidth         = 0u;
+#endif
+OS_COMPILER_OPT  INT16U  const  OSFlagMax           = OS_MAX_FLAGS;
+OS_COMPILER_OPT  INT16U  const  OSFlagNameEn        = OS_FLAG_NAME_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSLowestPrio        = OS_LOWEST_PRIO;
+
+OS_COMPILER_OPT  INT16U  const  OSMboxEn            = OS_MBOX_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSMemEn             = OS_MEM_EN;
+OS_COMPILER_OPT  INT16U  const  OSMemMax            = OS_MAX_MEM_PART;           /* Number of memory partitions         */
+OS_COMPILER_OPT  INT16U  const  OSMemNameEn         = OS_MEM_NAME_EN;
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+OS_COMPILER_OPT  INT16U  const  OSMemSize           = sizeof(OS_MEM);            /* Mem. Partition header sine (bytes)  */
+OS_COMPILER_OPT  INT16U  const  OSMemTblSize        = sizeof(OSMemTbl);
+#else
+OS_COMPILER_OPT  INT16U  const  OSMemSize           = 0u;
+OS_COMPILER_OPT  INT16U  const  OSMemTblSize        = 0u;
+#endif
+OS_COMPILER_OPT  INT16U  const  OSMutexEn           = OS_MUTEX_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSPtrSize           = sizeof(void *);            /* Size in Bytes of a pointer          */
+
+OS_COMPILER_OPT  INT16U  const  OSQEn               = OS_Q_EN;
+OS_COMPILER_OPT  INT16U  const  OSQMax              = OS_MAX_QS;                 /* Number of queues                    */
+#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+OS_COMPILER_OPT  INT16U  const  OSQSize             = sizeof(OS_Q);              /* Size in bytes of OS_Q structure     */
+#else
+OS_COMPILER_OPT  INT16U  const  OSQSize             = 0u;
+#endif
+
+OS_COMPILER_OPT  INT16U  const  OSRdyTblSize        = OS_RDY_TBL_SIZE;           /* Number of bytes in the ready table  */
+
+OS_COMPILER_OPT  INT16U  const  OSSemEn             = OS_SEM_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSStkWidth          = sizeof(OS_STK);            /* Size in Bytes of a stack entry      */
+
+OS_COMPILER_OPT  INT16U  const  OSTaskCreateEn      = OS_TASK_CREATE_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskCreateExtEn   = OS_TASK_CREATE_EXT_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskDelEn         = OS_TASK_DEL_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskIdleStkSize   = OS_TASK_IDLE_STK_SIZE;
+OS_COMPILER_OPT  INT16U  const  OSTaskProfileEn     = OS_TASK_PROFILE_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskMax           = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks      */
+OS_COMPILER_OPT  INT16U  const  OSTaskNameEn        = OS_TASK_NAME_EN;  
+OS_COMPILER_OPT  INT16U  const  OSTaskStatEn        = OS_TASK_STAT_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskStatStkSize   = OS_TASK_STAT_STK_SIZE;
+OS_COMPILER_OPT  INT16U  const  OSTaskStatStkChkEn  = OS_TASK_STAT_STK_CHK_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskSwHookEn      = OS_TASK_SW_HOOK_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskRegTblSize    = OS_TASK_REG_TBL_SIZE;
+
+OS_COMPILER_OPT  INT16U  const  OSTCBPrioTblMax     = OS_LOWEST_PRIO + 1u;       /* Number of entries in OSTCBPrioTbl[] */
+OS_COMPILER_OPT  INT16U  const  OSTCBSize           = sizeof(OS_TCB);            /* Size in Bytes of OS_TCB             */
+OS_COMPILER_OPT  INT16U  const  OSTicksPerSec       = OS_TICKS_PER_SEC;
+OS_COMPILER_OPT  INT16U  const  OSTimeTickHookEn    = OS_TIME_TICK_HOOK_EN;
+OS_COMPILER_OPT  INT16U  const  OSVersionNbr        = OS_VERSION;
+
+OS_COMPILER_OPT  INT16U  const  OSTmrEn             = OS_TMR_EN;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgMax         = OS_TMR_CFG_MAX;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgNameEn      = OS_TMR_CFG_NAME_EN;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgWheelSize   = OS_TMR_CFG_WHEEL_SIZE;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC;
+
+#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u)
+OS_COMPILER_OPT  INT16U  const  OSTmrSize           = sizeof(OS_TMR);
+OS_COMPILER_OPT  INT16U  const  OSTmrTblSize        = sizeof(OSTmrTbl);
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelSize      = sizeof(OS_TMR_WHEEL);
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelTblSize   = sizeof(OSTmrWheelTbl);
+#else
+OS_COMPILER_OPT  INT16U  const  OSTmrSize           = 0u;
+OS_COMPILER_OPT  INT16U  const  OSTmrTblSize        = 0u;
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelSize      = 0u;
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelTblSize   = 0u;
+#endif
+
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                             DEBUG DATA
+*                            TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II
+*********************************************************************************************************
+*/
+#if OS_DEBUG_EN > 0u
+
+OS_COMPILER_OPT  INT16U  const  OSDataSize = sizeof(OSCtxSwCtr)
+#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u)
+                          + sizeof(OSEventFreeList)
+                          + sizeof(OSEventTbl)
+#endif
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+                          + sizeof(OSFlagTbl)
+                          + sizeof(OSFlagFreeList)
+#endif
+#if OS_TASK_STAT_EN > 0u
+                          + sizeof(OSCPUUsage)
+                          + sizeof(OSIdleCtrMax)
+                          + sizeof(OSIdleCtrRun)
+                          + sizeof(OSStatRdy)
+                          + sizeof(OSTaskStatStk)
+#endif
+#if OS_TICK_STEP_EN > 0u
+                          + sizeof(OSTickStepState)
+#endif
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+                          + sizeof(OSMemFreeList)
+                          + sizeof(OSMemTbl)
+#endif
+#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+                          + sizeof(OSQFreeList)
+                          + sizeof(OSQTbl)
+#endif
+#if OS_TIME_GET_SET_EN > 0u   
+                          + sizeof(OSTime)
+#endif
+#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u)
+                          + sizeof(OSTmrFree)
+                          + sizeof(OSTmrUsed)
+                          + sizeof(OSTmrTime)
+                          + sizeof(OSTmrSem)
+                          + sizeof(OSTmrSemSignal)
+                          + sizeof(OSTmrTbl)
+                          + sizeof(OSTmrFreeList)
+                          + sizeof(OSTmrTaskStk)
+                          + sizeof(OSTmrWheelTbl)
+#endif
+                          + sizeof(OSIntNesting)
+                          + sizeof(OSLockNesting)
+                          + sizeof(OSPrioCur)
+                          + sizeof(OSPrioHighRdy)
+                          + sizeof(OSRdyGrp)
+                          + sizeof(OSRdyTbl)
+                          + sizeof(OSRunning)
+                          + sizeof(OSTaskCtr)
+                          + sizeof(OSIdleCtr)
+                          + sizeof(OSTaskIdleStk)
+                          + sizeof(OSTCBCur)
+                          + sizeof(OSTCBFreeList)
+                          + sizeof(OSTCBHighRdy)
+                          + sizeof(OSTCBList)
+                          + sizeof(OSTCBPrioTbl)
+                          + sizeof(OSTCBTbl);
+
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                        OS DEBUG INITIALIZATION
+*
+* Description: This function is used to make sure that debug variables that are unused in the application
+*              are not optimized away.  This function might not be necessary for all compilers.  In this
+*              case, you should simply DELETE the code in this function while still leaving the declaration
+*              of the function itself.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Note(s)    : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out
+*                  the 'const' variables which are declared in this file.
+*              (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function 
+*                  if your compiler DOES NOT optimize out the 'const' variables above.
+*********************************************************************************************************
+*/
+
+#if OS_DEBUG_EN > 0u
+void  OSDebugInit (void)
+{
+    void  *ptemp;
+
+    
+    ptemp = (void *)&OSDebugEn;
+
+    ptemp = (void *)&OSEndiannessTest;
+
+    ptemp = (void *)&OSEventMax;
+    ptemp = (void *)&OSEventNameEn;
+    ptemp = (void *)&OSEventEn;
+    ptemp = (void *)&OSEventSize;
+    ptemp = (void *)&OSEventTblSize;
+    ptemp = (void *)&OSEventMultiEn;
+
+    ptemp = (void *)&OSFlagEn;
+    ptemp = (void *)&OSFlagGrpSize;
+    ptemp = (void *)&OSFlagNodeSize;
+    ptemp = (void *)&OSFlagWidth;
+    ptemp = (void *)&OSFlagMax;
+    ptemp = (void *)&OSFlagNameEn;
+
+    ptemp = (void *)&OSLowestPrio;
+
+    ptemp = (void *)&OSMboxEn;
+
+    ptemp = (void *)&OSMemEn;
+    ptemp = (void *)&OSMemMax;
+    ptemp = (void *)&OSMemNameEn;
+    ptemp = (void *)&OSMemSize;
+    ptemp = (void *)&OSMemTblSize;
+
+    ptemp = (void *)&OSMutexEn;
+
+    ptemp = (void *)&OSPtrSize;
+
+    ptemp = (void *)&OSQEn;
+    ptemp = (void *)&OSQMax;
+    ptemp = (void *)&OSQSize;
+
+    ptemp = (void *)&OSRdyTblSize;
+
+    ptemp = (void *)&OSSemEn;
+
+    ptemp = (void *)&OSStkWidth;
+
+    ptemp = (void *)&OSTaskCreateEn;
+    ptemp = (void *)&OSTaskCreateExtEn;
+    ptemp = (void *)&OSTaskDelEn;
+    ptemp = (void *)&OSTaskIdleStkSize;
+    ptemp = (void *)&OSTaskProfileEn;
+    ptemp = (void *)&OSTaskMax;
+    ptemp = (void *)&OSTaskNameEn;
+    ptemp = (void *)&OSTaskStatEn;
+    ptemp = (void *)&OSTaskStatStkSize;
+    ptemp = (void *)&OSTaskStatStkChkEn;
+    ptemp = (void *)&OSTaskSwHookEn;
+
+    ptemp = (void *)&OSTCBPrioTblMax;
+    ptemp = (void *)&OSTCBSize;
+
+    ptemp = (void *)&OSTicksPerSec;
+    ptemp = (void *)&OSTimeTickHookEn;
+
+#if OS_TMR_EN > 0u
+    ptemp = (void *)&OSTmrTbl[0];
+    ptemp = (void *)&OSTmrWheelTbl[0];
+    
+    ptemp = (void *)&OSTmrEn;
+    ptemp = (void *)&OSTmrCfgMax;
+    ptemp = (void *)&OSTmrCfgNameEn;
+    ptemp = (void *)&OSTmrCfgWheelSize;
+    ptemp = (void *)&OSTmrCfgTicksPerSec;
+    ptemp = (void *)&OSTmrSize;
+    ptemp = (void *)&OSTmrTblSize;
+
+    ptemp = (void *)&OSTmrWheelSize;
+    ptemp = (void *)&OSTmrWheelTblSize;
+#endif
+
+    ptemp = (void *)&OSVersionNbr;
+
+    ptemp = (void *)&OSDataSize;
+
+    ptemp = ptemp;                             /* Prevent compiler warning for 'ptemp' not being used! */
+}
+#endif

+ 193 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/RealView/os_cpu.h

@@ -0,0 +1,193 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*
+*
+*                         (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
+*                    All rights reserved.  Protected by international copyright laws.
+*
+*                                           ARM Cortex-M4 Port
+*
+* File      : OS_CPU.H
+* Version   : V2.92.09
+* By        : JJL
+*             JBL
+*
+* LICENSING TERMS:
+* ---------------
+*           uC/OS-II is provided in source form for FREE short-term evaluation, for educational use or 
+*           for peaceful research.  If you plan or intend to use uC/OS-II in a commercial application/
+*           product then, you need to contact Micrium to properly license uC/OS-II for its use in your 
+*           application/product.   We provide ALL the source code for your convenience and to help you 
+*           experience uC/OS-II.  The fact that the source is provided does NOT mean that you can use 
+*           it commercially without paying a licensing fee.
+*
+*           Knowledge of the source code may NOT be used to develop a similar product.
+*
+*           Please help us continue to provide the embedded community with the finest software available.
+*           Your honesty is greatly appreciated.
+*
+*           You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
+*
+* For       : ARMv7 Cortex-M4
+* Mode      : Thumb-2 ISA
+* Toolchain : RealView Development Suite
+*             RealView Microcontroller Development Kit (MDK)
+*             ARM Developer Suite (ADS)
+*             Keil uVision
+*********************************************************************************************************
+*/
+
+#ifndef  OS_CPU_H
+#define  OS_CPU_H
+
+#ifdef   OS_CPU_GLOBALS
+#define  OS_CPU_EXT
+#else
+#define  OS_CPU_EXT  extern
+#endif
+
+#ifndef  OS_CPU_EXCEPT_STK_SIZE
+#define  OS_CPU_EXCEPT_STK_SIZE    128u          /* Default exception stack size is 128 OS_STK entries */
+#endif
+
+/*
+*********************************************************************************************************
+*                                               DEFINES
+*********************************************************************************************************
+*/
+
+#ifndef  __TARGET_FPU_SOFTVFP
+#define  OS_CPU_ARM_FP_EN                              DEF_ENABLED
+#else
+#define  OS_CPU_ARM_FP_EN                              DEF_DISABLED
+#endif
+
+#define  OS_CPU_ARM_FP_REG_NBR                           32u
+
+
+/*
+*********************************************************************************************************
+*                              OS TICK INTERRUPT PRIORITY CONFIGURATION
+*
+* Note(s) : (1) For systems that don't need any high, real-time priority interrupts; the tick interrupt
+*               should be configured as the highest priority interrupt but won't adversely affect system
+*               operations.
+*
+*           (2) For systems that need one or more high, real-time interrupts; these should be configured
+*               higher than the tick interrupt which MAY delay execution of the tick interrupt.
+*
+*               (a) If the higher priority interrupts do NOT continually consume CPU cycles but only
+*                   occasionally delay tick interrupts, then the real-time interrupts can successfully
+*                   handle their intermittent/periodic events with the system not losing tick interrupts
+*                   but only increasing the jitter.
+*
+*               (b) If the higher priority interrupts consume enough CPU cycles to continually delay the
+*                   tick interrupt, then the CPU/system is most likely over-burdened & can't be expected
+*                   to handle all its interrupts/tasks. The system time reference gets compromised as a
+*                   result of losing tick interrupts.
+*********************************************************************************************************
+*/
+
+#define  OS_CPU_CFG_SYSTICK_PRIO           0u
+
+/*
+*********************************************************************************************************
+*                                              DATA TYPES
+*                                         (Compiler Specific)
+*********************************************************************************************************
+*/
+
+typedef unsigned char  BOOLEAN;
+typedef unsigned char  INT8U;                    /* Unsigned  8 bit quantity                           */
+typedef signed   char  INT8S;                    /* Signed    8 bit quantity                           */
+typedef unsigned short INT16U;                   /* Unsigned 16 bit quantity                           */
+typedef signed   short INT16S;                   /* Signed   16 bit quantity                           */
+typedef unsigned int   INT32U;                   /* Unsigned 32 bit quantity                           */
+typedef signed   int   INT32S;                   /* Signed   32 bit quantity                           */
+typedef float          FP32;                     /* Single precision floating point                    */
+typedef double         FP64;                     /* Double precision floating point                    */
+
+typedef unsigned int   OS_STK;                   /* Each stack entry is 32-bit wide                    */
+typedef unsigned int   OS_CPU_SR;                /* Define size of CPU status register (PSR = 32 bits) */
+
+
+/*
+*********************************************************************************************************
+*                                              Cortex-M4
+*                                      Critical Section Management
+*
+* Method #1:  Disable/Enable interrupts using simple instructions.  After critical section, interrupts
+*             will be enabled even if they were disabled before entering the critical section.
+*             NOT IMPLEMENTED
+*
+* Method #2:  Disable/Enable interrupts by preserving the state of interrupts.  In other words, if
+*             interrupts were disabled before entering the critical section, they will be disabled when
+*             leaving the critical section.
+*             NOT IMPLEMENTED
+*
+* Method #3:  Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
+*             would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
+*             disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
+*             disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
+*             into the CPU's status register.
+*********************************************************************************************************
+*/
+
+#define  OS_CRITICAL_METHOD   3u
+
+#if OS_CRITICAL_METHOD == 3u
+#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}
+#define  OS_EXIT_CRITICAL()   {OS_CPU_SR_Restore(cpu_sr);}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                        Cortex-M4 Miscellaneous
+*********************************************************************************************************
+*/
+
+#define  OS_STK_GROWTH        1u                  /* Stack grows from HIGH to LOW memory on ARM        */
+
+#define  OS_TASK_SW()         OSCtxSw()
+
+
+/*
+*********************************************************************************************************
+*                                          GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+OS_CPU_EXT  OS_STK   OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE];
+OS_CPU_EXT  OS_STK  *OS_CPU_ExceptStkBase;
+
+
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+#if OS_CRITICAL_METHOD == 3u                      /* See OS_CPU_A.ASM                                  */
+OS_CPU_SR  OS_CPU_SR_Save    (void);
+void       OS_CPU_SR_Restore (OS_CPU_SR cpu_sr);
+#endif
+
+void  OSCtxSw                (void);
+void  OSIntCtxSw             (void);
+void  OSStartHighRdy         (void);
+
+void  OS_CPU_PendSVHandler   (void);
+
+                                                  /* See OS_CPU_C.C                                    */
+void  OS_CPU_SysTickHandler  (void);
+void  OS_CPU_SysTickInit     (INT32U    cnts);
+
+#if (OS_CPU_ARM_FP_EN > 0u)
+void  OS_CPU_FP_Reg_Push     (OS_STK   *stkPtr);
+void  OS_CPU_FP_Reg_Pop      (OS_STK   *stkPtr);
+#endif
+
+#endif

+ 315 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/RealView/os_cpu_a.asm

@@ -0,0 +1,315 @@
+;
+;********************************************************************************************************
+;                                                uC/OS-II
+;                                          The Real-Time Kernel
+;
+;
+;                         (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
+;                    All rights reserved.  Protected by international copyright laws.
+;
+;                                           ARM Cortex-M4 Port
+;
+; File      : OS_CPU_A.ASM
+; Version   : V2.92.09
+; By        : JJL
+;             BAN
+;             JBL
+;
+; For       : ARMv7 Cortex-M4
+; Mode      : Thumb-2 ISA
+; Toolchain : RealView Development Suite
+;             RealView Microcontroller Development Kit (MDK)
+;             ARM Developer Suite (ADS)
+;             Keil uVision
+;********************************************************************************************************
+;
+
+;********************************************************************************************************
+;                                          PUBLIC FUNCTIONS
+;********************************************************************************************************
+
+    EXTERN  OSRunning                                           ; External references
+    EXTERN  OSPrioCur
+    EXTERN  OSPrioHighRdy
+    EXTERN  OSTCBCur
+    EXTERN  OSTCBHighRdy
+    EXTERN  OSIntExit
+    EXTERN  OSTaskSwHook
+    EXTERN  OS_CPU_ExceptStkBase
+
+    EXPORT  OS_CPU_SR_Save                                      ; Functions declared in this file
+    EXPORT  OS_CPU_SR_Restore
+    EXPORT  OSStartHighRdy
+    EXPORT  OSCtxSw
+    EXPORT  OSIntCtxSw
+    EXPORT  OS_CPU_PendSVHandler
+
+    IF {FPU} != "SoftVFP"
+    EXPORT  OS_CPU_FP_Reg_Push
+    EXPORT  OS_CPU_FP_Reg_Pop
+    ENDIF
+
+
+;********************************************************************************************************
+;                                               EQUATES
+;********************************************************************************************************
+
+NVIC_INT_CTRL   EQU     0xE000ED04                              ; Interrupt control state register.
+NVIC_SYSPRI14   EQU     0xE000ED22                              ; System priority register (priority 14).
+NVIC_PENDSV_PRI EQU           0xFF                              ; PendSV priority value (lowest).
+NVIC_PENDSVSET  EQU     0x10000000                              ; Value to trigger PendSV exception.
+
+
+;********************************************************************************************************
+;                                     CODE GENERATION DIRECTIVES
+;********************************************************************************************************
+
+    AREA |.text|, CODE, READONLY, ALIGN=2
+    THUMB
+    REQUIRE8
+    PRESERVE8
+
+
+;********************************************************************************************************
+;                                   FLOATING POINT REGISTERS PUSH
+;                             void  OS_CPU_FP_Reg_Push (CPU_STK  *stkPtr)
+;
+; Note(s) : 1) This function saves S0-S31, and FPSCR registers of the Floating Point Unit.
+;
+;           2) Pseudo-code is:
+;              a) Get FPSCR register value;
+;              b) Push value on process stack;
+;              c) Push remaining regs S0-S31 on process stack;
+;              d) Update OSTCBCurPtr->StkPtr;
+;********************************************************************************************************
+
+    IF {FPU} != "SoftVFP"
+
+OS_CPU_FP_Reg_Push
+    MRS     R1, PSP                                             ; PSP is process stack pointer
+    CBZ     R1, OS_CPU_FP_nosave                                ; Skip FP register save the first time
+
+    VMRS    R1, FPSCR
+    STR R1, [R0, #-4]!
+    VSTMDB  R0!, {S0-S31}
+    LDR     R1, =OSTCBCur
+    LDR     R2, [R1]
+    STR     R0, [R2]
+OS_CPU_FP_nosave
+    BX      LR
+
+    ENDIF
+
+
+;********************************************************************************************************
+;                                   FLOATING POINT REGISTERS POP
+;                             void  OS_CPU_FP_Reg_Pop (CPU_STK  *stkPtr)
+;
+; Note(s) : 1) This function restores S0-S31, and FPSCR registers of the Floating Point Unit.
+;
+;           2) Pseudo-code is:
+;              a) Restore regs S0-S31 of new process stack;
+;              b) Restore FPSCR reg value
+;              c) Update OSTCBHighRdyPtr->StkPtr pointer of new proces stack;
+;********************************************************************************************************
+
+    IF {FPU} != "SoftVFP"
+
+OS_CPU_FP_Reg_Pop
+    VLDMIA  R0!, {S0-S31}
+    LDMIA   R0!, {R1}
+    VMSR    FPSCR, R1
+    LDR     R1, =OSTCBHighRdy
+    LDR     R2, [R1]
+    STR     R0, [R2]
+    BX      LR
+
+    ENDIF
+
+
+;********************************************************************************************************
+;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
+;
+; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
+;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
+;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
+;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
+;              into the CPU's status register.
+;
+; Prototypes :     OS_CPU_SR  OS_CPU_SR_Save(void);
+;                  void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
+;
+;
+; Note(s)    : 1) These functions are used in general like this:
+;
+;                 void Task (void *p_arg)
+;                 {
+;                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
+;                     OS_CPU_SR  cpu_sr;
+;                 #endif
+;
+;                          :
+;                          :
+;                     OS_ENTER_CRITICAL();             /* cpu_sr = OS_CPU_SaveSR();                */
+;                          :
+;                          :
+;                     OS_EXIT_CRITICAL();              /* OS_CPU_RestoreSR(cpu_sr);                */
+;                          :
+;                          :
+;                 }
+;********************************************************************************************************
+
+OS_CPU_SR_Save
+    MRS     R0, PRIMASK                                         ; Set prio int mask to mask all (except faults)
+    CPSID   I
+    BX      LR
+
+OS_CPU_SR_Restore
+    MSR     PRIMASK, R0
+    BX      LR
+
+
+;********************************************************************************************************
+;                                         START MULTITASKING
+;                                      void OSStartHighRdy(void)
+;
+; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause
+;              the first task to start.
+;
+;           2) OSStartHighRdy() MUST:
+;              a) Setup PendSV exception priority to lowest;
+;              b) Set initial PSP to 0, to tell context switcher this is first run;
+;              c) Set the main stack to OS_CPU_ExceptStkBase
+;              d) Set OSRunning to TRUE;
+;              e) Trigger PendSV exception;
+;              f) Enable interrupts (tasks will run with interrupts enabled).
+;********************************************************************************************************
+
+OSStartHighRdy
+    LDR     R0, =NVIC_SYSPRI14                                  ; Set the PendSV exception priority
+    LDR     R1, =NVIC_PENDSV_PRI
+    STRB    R1, [R0]
+
+    MOVS    R0, #0                                              ; Set the PSP to 0 for initial context switch call
+    MSR     PSP, R0
+
+    LDR     R0, =OS_CPU_ExceptStkBase                           ; Initialize the MSP to the OS_CPU_ExceptStkBase
+    LDR     R1, [R0]
+    MSR     MSP, R1    
+
+    LDR     R0, =OSRunning                                      ; OSRunning = TRUE
+    MOVS    R1, #1
+    STRB    R1, [R0]
+
+    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
+    LDR     R1, =NVIC_PENDSVSET
+    STR     R1, [R0]
+
+    CPSIE   I                                                   ; Enable interrupts at processor level
+
+OSStartHang
+    B       OSStartHang                                         ; Should never get here
+
+
+;********************************************************************************************************
+;                       PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
+;
+; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch.  This function
+;              triggers the PendSV exception which is where the real work is done.
+;********************************************************************************************************
+
+OSCtxSw
+    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
+    LDR     R1, =NVIC_PENDSVSET
+    STR     R1, [R0]
+    BX      LR
+
+
+;********************************************************************************************************
+;                   PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
+;
+; Note(s) : 1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as
+;              the result of an interrupt.  This function simply triggers a PendSV exception which will
+;              be handled when there are no more interrupts active and interrupts are enabled.
+;********************************************************************************************************
+
+OSIntCtxSw
+    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
+    LDR     R1, =NVIC_PENDSVSET
+    STR     R1, [R0]
+    BX      LR
+
+
+;********************************************************************************************************
+;                                       HANDLE PendSV EXCEPTION
+;                                   void OS_CPU_PendSVHandler(void)
+;
+; Note(s) : 1) PendSV is used to cause a context switch.  This is a recommended method for performing
+;              context switches with Cortex-M3.  This is because the Cortex-M3 auto-saves half of the
+;              processor context on any exception, and restores same on return from exception.  So only
+;              saving of R4-R11 is required and fixing up the stack pointers.  Using the PendSV exception
+;              this way means that context saving and restoring is identical whether it is initiated from
+;              a thread or occurs due to an interrupt or exception.
+;
+;           2) Pseudo-code is:
+;              a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch);
+;              b) Save remaining regs r4-r11 on process stack;
+;              c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP;
+;              d) Call OSTaskSwHook();
+;              e) Get current high priority, OSPrioCur = OSPrioHighRdy;
+;              f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
+;              g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
+;              h) Restore R4-R11 from new process stack;
+;              i) Perform exception return which will restore remaining context.
+;
+;           3) On entry into PendSV handler:
+;              a) The following have been saved on the process stack (by processor):
+;                 xPSR, PC, LR, R12, R0-R3
+;              b) Processor mode is switched to Handler mode (from Thread mode)
+;              c) Stack is Main stack (switched from Process stack)
+;              d) OSTCBCur      points to the OS_TCB of the task to suspend
+;                 OSTCBHighRdy  points to the OS_TCB of the task to resume
+;
+;           4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
+;              know that it will only be run when no other exception or interrupt is active, and
+;              therefore safe to assume that context being switched out was using the process stack (PSP).
+;********************************************************************************************************
+
+OS_CPU_PendSVHandler
+    CPSID   I                                                   ; Prevent interruption during context switch
+    MRS     R0, PSP                                             ; PSP is process stack pointer
+    CBZ     R0, OS_CPU_PendSVHandler_nosave                     ; Skip register save the first time
+
+    SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
+    STM     R0, {R4-R11}
+
+    LDR     R1, =OSTCBCur                                       ; OSTCBCur->OSTCBStkPtr = SP;
+    LDR     R1, [R1]
+    STR     R0, [R1]                                            ; R0 is SP of process being switched out
+
+                                                                ; At this point, entire context of process has been saved
+OS_CPU_PendSVHandler_nosave
+    PUSH    {R14}                                               ; Save LR exc_return value
+    LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
+    BLX     R0
+    POP     {R14}
+
+    LDR     R0, =OSPrioCur                                      ; OSPrioCur = OSPrioHighRdy;
+    LDR     R1, =OSPrioHighRdy
+    LDRB    R2, [R1]
+    STRB    R2, [R0]
+
+    LDR     R0, =OSTCBCur                                       ; OSTCBCur  = OSTCBHighRdy;
+    LDR     R1, =OSTCBHighRdy
+    LDR     R2, [R1]
+    STR     R2, [R0]
+
+    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
+    LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
+    ADDS    R0, R0, #0x20
+    MSR     PSP, R0                                             ; Load PSP with new process SP
+    ORR     LR, LR, #0xF4                                       ; Ensure exception return uses process stack
+    CPSIE   I
+    BX      LR                                                  ; Exception return will restore remaining context
+
+    END

+ 507 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/RealView/os_cpu_c.c

@@ -0,0 +1,507 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*
+*
+*                           (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
+*                    All rights reserved.  Protected by international copyright laws.
+*
+*                                           ARM Cortex-M4 Port
+*
+* File      : OS_CPU_C.C
+* Version   : V2.92.09
+* By        : JJL
+*             BAN
+*             JBL
+*
+* LICENSING TERMS:
+* ---------------
+*           uC/OS-II is provided in source form for FREE short-term evaluation, for educational use or 
+*           for peaceful research.  If you plan or intend to use uC/OS-II in a commercial application/
+*           product then, you need to contact Micrium to properly license uC/OS-II for its use in your 
+*           application/product.   We provide ALL the source code for your convenience and to help you 
+*           experience uC/OS-II.  The fact that the source is provided does NOT mean that you can use 
+*           it commercially without paying a licensing fee.
+*
+*           Knowledge of the source code may NOT be used to develop a similar product.
+*
+*           Please help us continue to provide the embedded community with the finest software available.
+*           Your honesty is greatly appreciated.
+*
+*           You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
+*
+* For       : ARMv7 Cortex-M4
+* Mode      : Thumb-2 ISA
+* Toolchain : RealView Development Suite
+*             RealView Microcontroller Development Kit (MDK)
+*             ARM Developer Suite (ADS)
+*             Keil uVision
+*********************************************************************************************************
+*/
+
+#define   OS_CPU_GLOBALS
+
+
+/*
+*********************************************************************************************************
+*                                             INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#include  <ucos_ii.h>
+#include  <lib_def.h>
+
+
+/*
+*********************************************************************************************************
+*                                          LOCAL VARIABLES
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+static  INT16U  OSTmrCtr;
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          SYS TICK DEFINES
+*********************************************************************************************************
+*/
+
+#define  OS_CPU_CM4_NVIC_ST_CTRL    (*((volatile INT32U *)0xE000E010uL)) /* SysTick Ctrl & Status Reg. */
+#define  OS_CPU_CM4_NVIC_ST_RELOAD  (*((volatile INT32U *)0xE000E014uL)) /* SysTick Reload  Value Reg. */
+#define  OS_CPU_CM4_NVIC_ST_CURRENT (*((volatile INT32U *)0xE000E018uL)) /* SysTick Current Value Reg. */
+#define  OS_CPU_CM4_NVIC_ST_CAL     (*((volatile INT32U *)0xE000E01CuL)) /* SysTick Cal     Value Reg. */
+#define  OS_CPU_CM4_NVIC_SHPRI1     (*((volatile INT32U *)0xE000ED18uL)) /* System Handlers  4 to  7 Prio.       */
+#define  OS_CPU_CM4_NVIC_SHPRI2     (*((volatile INT32U *)0xE000ED1CuL)) /* System Handlers  8 to 11 Prio.       */
+#define  OS_CPU_CM4_NVIC_SHPRI3     (*((volatile INT32U *)0xE000ED20uL)) /* System Handlers 12 to 15 Prio.       */
+
+
+#define  OS_CPU_CM4_NVIC_ST_CTRL_COUNT                    0x00010000uL   /* Count flag.                */
+#define  OS_CPU_CM4_NVIC_ST_CTRL_CLK_SRC                  0x00000004uL   /* Clock Source.              */
+#define  OS_CPU_CM4_NVIC_ST_CTRL_INTEN                    0x00000002uL   /* Interrupt enable.          */
+#define  OS_CPU_CM4_NVIC_ST_CTRL_ENABLE                   0x00000001uL   /* Counter mode.              */
+#define  OS_CPU_CM4_NVIC_PRIO_MIN                               0xFFu    /* Min handler prio.          */
+
+
+/*
+*********************************************************************************************************
+*                                       OS INITIALIZATION HOOK
+*                                            (BEGINNING)
+*
+* Description: This function is called by OSInit() at the beginning of OSInit().
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts should be disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSInitHookBegin (void)
+{
+    INT32U   size;
+    OS_STK  *pstk;
+
+                                                                /* Clear exception stack for stack checking.            */
+    pstk = &OS_CPU_ExceptStk[0];
+    size = OS_CPU_EXCEPT_STK_SIZE;
+    while (size > 0u) {
+        size--;
+       *pstk++ = (OS_STK)0;
+    }
+
+                                                                /* Align the ISR stack to 8-bytes                       */
+    OS_CPU_ExceptStkBase = (OS_STK *)&OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE];
+    OS_CPU_ExceptStkBase = (OS_STK *)((OS_STK)(OS_CPU_ExceptStkBase) & 0xFFFFFFF8);
+
+#if OS_TMR_EN > 0u
+    OSTmrCtr = 0u;
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                       OS INITIALIZATION HOOK
+*                                               (END)
+*
+* Description: This function is called by OSInit() at the end of OSInit().
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts should be disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSInitHookEnd (void)
+{
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          TASK CREATION HOOK
+*
+* Description: This function is called when a task is created.
+*
+* Arguments  : ptcb   is a pointer to the task control block of the task being created.
+*
+* Note(s)    : 1) Interrupts are disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTaskCreateHook (OS_TCB *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskCreateHook(ptcb);
+#else
+    (void)ptcb;                                  /* Prevent compiler warning                           */
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                           TASK DELETION HOOK
+*
+* Description: This function is called when a task is deleted.
+*
+* Arguments  : ptcb   is a pointer to the task control block of the task being deleted.
+*
+* Note(s)    : 1) Interrupts are disabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTaskDelHook (OS_TCB *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskDelHook(ptcb);
+#else
+    (void)ptcb;                                  /* Prevent compiler warning                           */
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                             IDLE TASK HOOK
+*
+* Description: This function is called by the idle task.  This hook has been added to allow you to do
+*              such things as STOP the CPU to conserve power.
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts are enabled during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTaskIdleHook (void)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskIdleHook();
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                            TASK RETURN HOOK
+*
+* Description: This function is called if a task accidentally returns.  In other words, a task should
+*              either be an infinite loop or delete itself when done.
+*
+* Arguments  : ptcb      is a pointer to the task control block of the task that is returning.
+*
+* Note(s)    : none
+*********************************************************************************************************
+*/
+
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTaskReturnHook (OS_TCB  *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskReturnHook(ptcb);
+#else
+    (void)ptcb;
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                           STATISTIC TASK HOOK
+*
+* Description: This function is called every second by uC/OS-II's statistics task.  This allows your
+*              application to add functionality to the statistics task.
+*
+* Arguments  : none
+*********************************************************************************************************
+*/
+
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTaskStatHook (void)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskStatHook();
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                        INITIALIZE A TASK'S STACK
+*
+* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
+*              stack frame of the task being created.  This function is highly processor specific.
+*
+* Arguments  : task          is a pointer to the task code
+*
+*              p_arg         is a pointer to a user supplied data area that will be passed to the task
+*                            when the task first executes.
+*
+*              ptos          is a pointer to the top of stack.  It is assumed that 'ptos' points to
+*                            a 'free' entry on the task stack.  If OS_STK_GROWTH is set to 1 then
+*                            'ptos' will contain the HIGHEST valid address of the stack.  Similarly, if
+*                            OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
+*                            of the stack.
+*
+*              opt           specifies options that can be used to alter the behavior of OSTaskStkInit().
+*                            (see uCOS_II.H for OS_TASK_OPT_xxx).
+*
+* Returns    : Always returns the location of the new top-of-stack once the processor registers have
+*              been placed on the stack in the proper order.
+*
+* Note(s)    : 1) Interrupts are enabled when your task starts executing.
+*              2) All tasks run in Thread mode, using process stack.
+*********************************************************************************************************
+*/
+
+OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
+{
+    OS_STK *p_stk;
+
+
+    (void)opt;                                                  /* 'opt' is not used, prevent warning                   */
+    p_stk      = ptos + 1u;                                     /* Load stack pointer                                   */
+                                                                /* Align the stack to 8-bytes.                          */
+    p_stk      = (OS_STK *)((OS_STK)(p_stk) & 0xFFFFFFF8u);
+                                                                /* Registers stacked as if auto-saved on exception      */
+    *(--p_stk) = (OS_STK)0x01000000uL;                          /* xPSR                                                 */
+    *(--p_stk) = (OS_STK)task;                                  /* Entry Point                                          */
+    *(--p_stk) = (OS_STK)OS_TaskReturn;                         /* R14 (LR)                                             */
+    *(--p_stk) = (OS_STK)0x12121212uL;                          /* R12                                                  */
+    *(--p_stk) = (OS_STK)0x03030303uL;                          /* R3                                                   */
+    *(--p_stk) = (OS_STK)0x02020202uL;                          /* R2                                                   */
+    *(--p_stk) = (OS_STK)0x01010101uL;                          /* R1                                                   */
+    *(--p_stk) = (OS_STK)p_arg;                                 /* R0 : argument                                        */
+
+                                                                /* Remaining registers saved on process stack           */
+    *(--p_stk) = (OS_STK)0x11111111uL;                          /* R11                                                  */
+    *(--p_stk) = (OS_STK)0x10101010uL;                          /* R10                                                  */
+    *(--p_stk) = (OS_STK)0x09090909uL;                          /* R9                                                   */
+    *(--p_stk) = (OS_STK)0x08080808uL;                          /* R8                                                   */
+    *(--p_stk) = (OS_STK)0x07070707uL;                          /* R7                                                   */
+    *(--p_stk) = (OS_STK)0x06060606uL;                          /* R6                                                   */
+    *(--p_stk) = (OS_STK)0x05050505uL;                          /* R5                                                   */
+    *(--p_stk) = (OS_STK)0x04040404uL;                          /* R4                                                   */
+
+#if (OS_CPU_ARM_FP_EN == DEF_ENABLED)
+    if ((opt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
+        *--p_stk = (CPU_STK)0x02000000u;                        /* FPSCR                                                  */
+                                                                /* Initialize S0-S31 floating point registers             */
+        *--p_stk = (CPU_STK)0x41F80000u;                        /* S31                                                    */
+        *--p_stk = (CPU_STK)0x41F00000u;                        /* S30                                                    */
+        *--p_stk = (CPU_STK)0x41E80000u;                        /* S29                                                    */
+        *--p_stk = (CPU_STK)0x41E00000u;                        /* S28                                                    */
+        *--p_stk = (CPU_STK)0x41D80000u;                        /* S27                                                    */
+        *--p_stk = (CPU_STK)0x41D00000u;                        /* S26                                                    */
+        *--p_stk = (CPU_STK)0x41C80000u;                        /* S25                                                    */
+        *--p_stk = (CPU_STK)0x41C00000u;                        /* S24                                                    */
+        *--p_stk = (CPU_STK)0x41B80000u;                        /* S23                                                    */
+        *--p_stk = (CPU_STK)0x41B00000u;                        /* S22                                                    */
+        *--p_stk = (CPU_STK)0x41A80000u;                        /* S21                                                    */
+        *--p_stk = (CPU_STK)0x41A00000u;                        /* S20                                                    */
+        *--p_stk = (CPU_STK)0x41980000u;                        /* S19                                                    */
+        *--p_stk = (CPU_STK)0x41900000u;                        /* S18                                                    */
+        *--p_stk = (CPU_STK)0x41880000u;                        /* S17                                                    */
+        *--p_stk = (CPU_STK)0x41800000u;                        /* S16                                                    */
+        *--p_stk = (CPU_STK)0x41700000u;                        /* S15                                                    */
+        *--p_stk = (CPU_STK)0x41600000u;                        /* S14                                                    */
+        *--p_stk = (CPU_STK)0x41500000u;                        /* S13                                                    */
+        *--p_stk = (CPU_STK)0x41400000u;                        /* S12                                                    */
+        *--p_stk = (CPU_STK)0x41300000u;                        /* S11                                                    */
+        *--p_stk = (CPU_STK)0x41200000u;                        /* S10                                                    */
+        *--p_stk = (CPU_STK)0x41100000u;                        /* S9                                                     */
+        *--p_stk = (CPU_STK)0x41000000u;                        /* S8                                                     */
+        *--p_stk = (CPU_STK)0x40E00000u;                        /* S7                                                     */
+        *--p_stk = (CPU_STK)0x40C00000u;                        /* S6                                                     */
+        *--p_stk = (CPU_STK)0x40A00000u;                        /* S5                                                     */
+        *--p_stk = (CPU_STK)0x40800000u;                        /* S4                                                     */
+        *--p_stk = (CPU_STK)0x40400000u;                        /* S3                                                     */
+        *--p_stk = (CPU_STK)0x40000000u;                        /* S2                                                     */
+        *--p_stk = (CPU_STK)0x3F800000u;                        /* S1                                                     */
+        *--p_stk = (CPU_STK)0x00000000u;                        /* S0                                                     */
+    }
+#endif
+
+    return (p_stk);
+}
+
+
+/*
+*********************************************************************************************************
+*                                           TASK SWITCH HOOK
+*
+* Description: This function is called when a task switch is performed.  This allows you to perform other
+*              operations during a context switch.
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts are disabled during this call.
+*              2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that
+*                 will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the
+*                 task being switched out (i.e. the preempted task).
+*********************************************************************************************************
+*/
+#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u)
+void  OSTaskSwHook (void)
+{
+
+#if (OS_CPU_ARM_FP_EN > 0u)
+    if ((OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
+        OS_CPU_FP_Reg_Push(OSTCBCur->OSTCBStkPtr);
+    }
+
+    if ((OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
+        OS_CPU_FP_Reg_Pop(OSTCBHighRdy->OSTCBStkPtr);
+    }
+#endif
+
+#if OS_APP_HOOKS_EN > 0u
+    App_TaskSwHook();
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                           OS_TCBInit() HOOK
+*
+* Description: This function is called by OS_TCBInit() after setting up most of the TCB.
+*
+* Arguments  : ptcb    is a pointer to the TCB of the task being created.
+*
+* Note(s)    : 1) Interrupts may or may not be ENABLED during this call.
+*********************************************************************************************************
+*/
+#if OS_CPU_HOOKS_EN > 0u
+void  OSTCBInitHook (OS_TCB *ptcb)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TCBInitHook(ptcb);
+#else
+    (void)ptcb;                                  /* Prevent compiler warning                           */
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                               TICK HOOK
+*
+* Description: This function is called every tick.
+*
+* Arguments  : none
+*
+* Note(s)    : 1) Interrupts may or may not be ENABLED during this call.
+*********************************************************************************************************
+*/
+#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u)
+void  OSTimeTickHook (void)
+{
+#if OS_APP_HOOKS_EN > 0u
+    App_TimeTickHook();
+#endif
+
+#if OS_TMR_EN > 0u
+    OSTmrCtr++;
+    if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) {
+        OSTmrCtr = 0;
+        OSTmrSignal();
+    }
+#endif
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          SYS TICK HANDLER
+*
+* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-II tick
+*              interrupt.
+*
+* Arguments  : None.
+*
+* Note(s)    : 1) This function MUST be placed on entry 15 of the Cortex-M3 vector table.
+*********************************************************************************************************
+*/
+
+void  OS_CPU_SysTickHandler (void)
+{
+    OS_CPU_SR  cpu_sr;
+
+
+    OS_ENTER_CRITICAL();                         /* Tell uC/OS-II that we are starting an ISR          */
+    OSIntNesting++;
+    OS_EXIT_CRITICAL();
+
+    OSTimeTick();                                /* Call uC/OS-II's OSTimeTick()                       */
+
+    OSIntExit();                                 /* Tell uC/OS-II that we are leaving the ISR          */
+}
+
+
+/*
+*********************************************************************************************************
+*                                         INITIALIZE SYS TICK
+*
+* Description: Initialize the SysTick.
+*
+* Arguments  : cnts         Number of SysTick counts between two OS tick interrupts.
+*
+* Note(s)    : 1) This function MUST be called after OSStart() & after processor initialization.
+*********************************************************************************************************
+*/
+
+void  OS_CPU_SysTickInit (INT32U  cnts)
+{
+    INT32U  prio;
+
+
+    OS_CPU_CM4_NVIC_ST_RELOAD = cnts - 1u;
+
+                                                            /* Set SysTick handler prio.                              */
+    prio  = OS_CPU_CM4_NVIC_SHPRI3;
+    prio &= DEF_BIT_FIELD(24, 0);
+    prio |= DEF_BIT_MASK(OS_CPU_CFG_SYSTICK_PRIO, 24);
+
+    OS_CPU_CM4_NVIC_SHPRI3 = prio;
+
+                                                            /* Enable timer.                                          */
+    OS_CPU_CM4_NVIC_ST_CTRL |= OS_CPU_CM4_NVIC_ST_CTRL_CLK_SRC |
+                               OS_CPU_CM4_NVIC_ST_CTRL_ENABLE;
+                                                            /* Enable timer interrupt.                                */
+    OS_CPU_CM4_NVIC_ST_CTRL |= OS_CPU_CM4_NVIC_ST_CTRL_INTEN;
+}

+ 330 - 0
MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/RealView/os_dbg.c

@@ -0,0 +1,330 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                           DEBUGGER CONSTANTS
+*
+*                              (c) Copyright 1992-2009, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_DBG.C
+* By      : Jean J. Labrosse
+* Version : V2.92.09
+*
+* LICENSING TERMS:
+* ---------------
+*           uC/OS-II is provided in source form for FREE short-term evaluation, for educational use or 
+*           for peaceful research.  If you plan or intend to use uC/OS-II in a commercial application/
+*           product then, you need to contact Micrium to properly license uC/OS-II for its use in your 
+*           application/product.   We provide ALL the source code for your convenience and to help you 
+*           experience uC/OS-II.  The fact that the source is provided does NOT mean that you can use 
+*           it commercially without paying a licensing fee.
+*
+*           Knowledge of the source code may NOT be used to develop a similar product.
+*
+*           Please help us continue to provide the embedded community with the finest software available.
+*           Your honesty is greatly appreciated.
+*
+*           You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
+*
+* For       : ARMv7 Cortex-M4
+* Mode      : Thumb-2 ISA
+* Toolchain : RealView Development Suite
+*             RealView Microcontroller Development Kit (MDK)
+*             ARM Developer Suite (ADS)
+*             Keil uVision
+*********************************************************************************************************
+*/
+
+#include <ucos_ii.h>
+
+#define  OS_COMPILER_OPT
+
+/*
+*********************************************************************************************************
+*                                             DEBUG DATA
+*********************************************************************************************************
+*/
+
+OS_COMPILER_OPT  INT16U  const  OSDebugEn           = OS_DEBUG_EN;               /* Debug constants are defined below   */
+
+#if OS_DEBUG_EN > 0u
+
+OS_COMPILER_OPT  INT32U  const  OSEndiannessTest    = 0x12345678L;               /* Variable to test CPU endianness     */
+
+OS_COMPILER_OPT  INT16U  const  OSEventEn           = OS_EVENT_EN;
+OS_COMPILER_OPT  INT16U  const  OSEventMax          = OS_MAX_EVENTS;             /* Number of event control blocks      */
+OS_COMPILER_OPT  INT16U  const  OSEventNameEn       = OS_EVENT_NAME_EN;
+#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u)
+OS_COMPILER_OPT  INT16U  const  OSEventSize         = sizeof(OS_EVENT);          /* Size in Bytes of OS_EVENT           */
+OS_COMPILER_OPT  INT16U  const  OSEventTblSize      = sizeof(OSEventTbl);        /* Size of OSEventTbl[] in bytes       */
+#else
+OS_COMPILER_OPT  INT16U  const  OSEventSize         = 0u;
+OS_COMPILER_OPT  INT16U  const  OSEventTblSize      = 0u;
+#endif
+OS_COMPILER_OPT  INT16U  const  OSEventMultiEn      = OS_EVENT_MULTI_EN;
+
+
+OS_COMPILER_OPT  INT16U  const  OSFlagEn            = OS_FLAG_EN;
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+OS_COMPILER_OPT  INT16U  const  OSFlagGrpSize       = sizeof(OS_FLAG_GRP);       /* Size in Bytes of OS_FLAG_GRP        */
+OS_COMPILER_OPT  INT16U  const  OSFlagNodeSize      = sizeof(OS_FLAG_NODE);      /* Size in Bytes of OS_FLAG_NODE       */
+OS_COMPILER_OPT  INT16U  const  OSFlagWidth         = sizeof(OS_FLAGS);          /* Width (in bytes) of OS_FLAGS        */
+#else
+OS_COMPILER_OPT  INT16U  const  OSFlagGrpSize       = 0u;
+OS_COMPILER_OPT  INT16U  const  OSFlagNodeSize      = 0u;
+OS_COMPILER_OPT  INT16U  const  OSFlagWidth         = 0u;
+#endif
+OS_COMPILER_OPT  INT16U  const  OSFlagMax           = OS_MAX_FLAGS;
+OS_COMPILER_OPT  INT16U  const  OSFlagNameEn        = OS_FLAG_NAME_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSLowestPrio        = OS_LOWEST_PRIO;
+
+OS_COMPILER_OPT  INT16U  const  OSMboxEn            = OS_MBOX_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSMemEn             = OS_MEM_EN;
+OS_COMPILER_OPT  INT16U  const  OSMemMax            = OS_MAX_MEM_PART;           /* Number of memory partitions         */
+OS_COMPILER_OPT  INT16U  const  OSMemNameEn         = OS_MEM_NAME_EN;
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+OS_COMPILER_OPT  INT16U  const  OSMemSize           = sizeof(OS_MEM);            /* Mem. Partition header sine (bytes)  */
+OS_COMPILER_OPT  INT16U  const  OSMemTblSize        = sizeof(OSMemTbl);
+#else
+OS_COMPILER_OPT  INT16U  const  OSMemSize           = 0u;
+OS_COMPILER_OPT  INT16U  const  OSMemTblSize        = 0u;
+#endif
+OS_COMPILER_OPT  INT16U  const  OSMutexEn           = OS_MUTEX_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSPtrSize           = sizeof(void *);            /* Size in Bytes of a pointer          */
+
+OS_COMPILER_OPT  INT16U  const  OSQEn               = OS_Q_EN;
+OS_COMPILER_OPT  INT16U  const  OSQMax              = OS_MAX_QS;                 /* Number of queues                    */
+#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+OS_COMPILER_OPT  INT16U  const  OSQSize             = sizeof(OS_Q);              /* Size in bytes of OS_Q structure     */
+#else
+OS_COMPILER_OPT  INT16U  const  OSQSize             = 0u;
+#endif
+
+OS_COMPILER_OPT  INT16U  const  OSRdyTblSize        = OS_RDY_TBL_SIZE;           /* Number of bytes in the ready table  */
+
+OS_COMPILER_OPT  INT16U  const  OSSemEn             = OS_SEM_EN;
+
+OS_COMPILER_OPT  INT16U  const  OSStkWidth          = sizeof(OS_STK);            /* Size in Bytes of a stack entry      */
+
+OS_COMPILER_OPT  INT16U  const  OSTaskCreateEn      = OS_TASK_CREATE_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskCreateExtEn   = OS_TASK_CREATE_EXT_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskDelEn         = OS_TASK_DEL_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskIdleStkSize   = OS_TASK_IDLE_STK_SIZE;
+OS_COMPILER_OPT  INT16U  const  OSTaskProfileEn     = OS_TASK_PROFILE_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskMax           = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks      */
+OS_COMPILER_OPT  INT16U  const  OSTaskNameEn        = OS_TASK_NAME_EN;  
+OS_COMPILER_OPT  INT16U  const  OSTaskStatEn        = OS_TASK_STAT_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskStatStkSize   = OS_TASK_STAT_STK_SIZE;
+OS_COMPILER_OPT  INT16U  const  OSTaskStatStkChkEn  = OS_TASK_STAT_STK_CHK_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskSwHookEn      = OS_TASK_SW_HOOK_EN;
+OS_COMPILER_OPT  INT16U  const  OSTaskRegTblSize    = OS_TASK_REG_TBL_SIZE;
+
+OS_COMPILER_OPT  INT16U  const  OSTCBPrioTblMax     = OS_LOWEST_PRIO + 1u;       /* Number of entries in OSTCBPrioTbl[] */
+OS_COMPILER_OPT  INT16U  const  OSTCBSize           = sizeof(OS_TCB);            /* Size in Bytes of OS_TCB             */
+OS_COMPILER_OPT  INT16U  const  OSTicksPerSec       = OS_TICKS_PER_SEC;
+OS_COMPILER_OPT  INT16U  const  OSTimeTickHookEn    = OS_TIME_TICK_HOOK_EN;
+OS_COMPILER_OPT  INT16U  const  OSVersionNbr        = OS_VERSION;
+
+OS_COMPILER_OPT  INT16U  const  OSTmrEn             = OS_TMR_EN;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgMax         = OS_TMR_CFG_MAX;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgNameEn      = OS_TMR_CFG_NAME_EN;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgWheelSize   = OS_TMR_CFG_WHEEL_SIZE;
+OS_COMPILER_OPT  INT16U  const  OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC;
+
+#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u)
+OS_COMPILER_OPT  INT16U  const  OSTmrSize           = sizeof(OS_TMR);
+OS_COMPILER_OPT  INT16U  const  OSTmrTblSize        = sizeof(OSTmrTbl);
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelSize      = sizeof(OS_TMR_WHEEL);
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelTblSize   = sizeof(OSTmrWheelTbl);
+#else
+OS_COMPILER_OPT  INT16U  const  OSTmrSize           = 0u;
+OS_COMPILER_OPT  INT16U  const  OSTmrTblSize        = 0u;
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelSize      = 0u;
+OS_COMPILER_OPT  INT16U  const  OSTmrWheelTblSize   = 0u;
+#endif
+
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                             DEBUG DATA
+*                            TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II
+*********************************************************************************************************
+*/
+#if OS_DEBUG_EN > 0u
+
+OS_COMPILER_OPT  INT16U  const  OSDataSize = sizeof(OSCtxSwCtr)
+#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u)
+                          + sizeof(OSEventFreeList)
+                          + sizeof(OSEventTbl)
+#endif
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+                          + sizeof(OSFlagTbl)
+                          + sizeof(OSFlagFreeList)
+#endif
+#if OS_TASK_STAT_EN > 0u
+                          + sizeof(OSCPUUsage)
+                          + sizeof(OSIdleCtrMax)
+                          + sizeof(OSIdleCtrRun)
+                          + sizeof(OSStatRdy)
+                          + sizeof(OSTaskStatStk)
+#endif
+#if OS_TICK_STEP_EN > 0u
+                          + sizeof(OSTickStepState)
+#endif
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+                          + sizeof(OSMemFreeList)
+                          + sizeof(OSMemTbl)
+#endif
+#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+                          + sizeof(OSQFreeList)
+                          + sizeof(OSQTbl)
+#endif
+#if OS_TIME_GET_SET_EN > 0u   
+                          + sizeof(OSTime)
+#endif
+#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u)
+                          + sizeof(OSTmrFree)
+                          + sizeof(OSTmrUsed)
+                          + sizeof(OSTmrTime)
+                          + sizeof(OSTmrSem)
+                          + sizeof(OSTmrSemSignal)
+                          + sizeof(OSTmrTbl)
+                          + sizeof(OSTmrFreeList)
+                          + sizeof(OSTmrTaskStk)
+                          + sizeof(OSTmrWheelTbl)
+#endif
+                          + sizeof(OSIntNesting)
+                          + sizeof(OSLockNesting)
+                          + sizeof(OSPrioCur)
+                          + sizeof(OSPrioHighRdy)
+                          + sizeof(OSRdyGrp)
+                          + sizeof(OSRdyTbl)
+                          + sizeof(OSRunning)
+                          + sizeof(OSTaskCtr)
+                          + sizeof(OSIdleCtr)
+                          + sizeof(OSTaskIdleStk)
+                          + sizeof(OSTCBCur)
+                          + sizeof(OSTCBFreeList)
+                          + sizeof(OSTCBHighRdy)
+                          + sizeof(OSTCBList)
+                          + sizeof(OSTCBPrioTbl)
+                          + sizeof(OSTCBTbl);
+
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                        OS DEBUG INITIALIZATION
+*
+* Description: This function is used to make sure that debug variables that are unused in the application
+*              are not optimized away.  This function might not be necessary for all compilers.  In this
+*              case, you should simply DELETE the code in this function while still leaving the declaration
+*              of the function itself.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Note(s)    : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out
+*                  the 'const' variables which are declared in this file.
+*              (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function 
+*                  if your compiler DOES NOT optimize out the 'const' variables above.
+*********************************************************************************************************
+*/
+
+#if OS_DEBUG_EN > 0u
+void  OSDebugInit (void)
+{
+    void  *ptemp;
+
+    
+    ptemp = (void *)&OSDebugEn;
+
+    ptemp = (void *)&OSEndiannessTest;
+
+    ptemp = (void *)&OSEventMax;
+    ptemp = (void *)&OSEventNameEn;
+    ptemp = (void *)&OSEventEn;
+    ptemp = (void *)&OSEventSize;
+    ptemp = (void *)&OSEventTblSize;
+    ptemp = (void *)&OSEventMultiEn;
+
+    ptemp = (void *)&OSFlagEn;
+    ptemp = (void *)&OSFlagGrpSize;
+    ptemp = (void *)&OSFlagNodeSize;
+    ptemp = (void *)&OSFlagWidth;
+    ptemp = (void *)&OSFlagMax;
+    ptemp = (void *)&OSFlagNameEn;
+
+    ptemp = (void *)&OSLowestPrio;
+
+    ptemp = (void *)&OSMboxEn;
+
+    ptemp = (void *)&OSMemEn;
+    ptemp = (void *)&OSMemMax;
+    ptemp = (void *)&OSMemNameEn;
+    ptemp = (void *)&OSMemSize;
+    ptemp = (void *)&OSMemTblSize;
+
+    ptemp = (void *)&OSMutexEn;
+
+    ptemp = (void *)&OSPtrSize;
+
+    ptemp = (void *)&OSQEn;
+    ptemp = (void *)&OSQMax;
+    ptemp = (void *)&OSQSize;
+
+    ptemp = (void *)&OSRdyTblSize;
+
+    ptemp = (void *)&OSSemEn;
+
+    ptemp = (void *)&OSStkWidth;
+
+    ptemp = (void *)&OSTaskCreateEn;
+    ptemp = (void *)&OSTaskCreateExtEn;
+    ptemp = (void *)&OSTaskDelEn;
+    ptemp = (void *)&OSTaskIdleStkSize;
+    ptemp = (void *)&OSTaskProfileEn;
+    ptemp = (void *)&OSTaskMax;
+    ptemp = (void *)&OSTaskNameEn;
+    ptemp = (void *)&OSTaskStatEn;
+    ptemp = (void *)&OSTaskStatStkSize;
+    ptemp = (void *)&OSTaskStatStkChkEn;
+    ptemp = (void *)&OSTaskSwHookEn;
+
+    ptemp = (void *)&OSTCBPrioTblMax;
+    ptemp = (void *)&OSTCBSize;
+
+    ptemp = (void *)&OSTicksPerSec;
+    ptemp = (void *)&OSTimeTickHookEn;
+
+#if OS_TMR_EN > 0u
+    ptemp = (void *)&OSTmrTbl[0];
+    ptemp = (void *)&OSTmrWheelTbl[0];
+    
+    ptemp = (void *)&OSTmrEn;
+    ptemp = (void *)&OSTmrCfgMax;
+    ptemp = (void *)&OSTmrCfgNameEn;
+    ptemp = (void *)&OSTmrCfgWheelSize;
+    ptemp = (void *)&OSTmrCfgTicksPerSec;
+    ptemp = (void *)&OSTmrSize;
+    ptemp = (void *)&OSTmrTblSize;
+
+    ptemp = (void *)&OSTmrWheelSize;
+    ptemp = (void *)&OSTmrWheelTblSize;
+#endif
+
+    ptemp = (void *)&OSVersionNbr;
+
+    ptemp = (void *)&OSDataSize;
+
+    ptemp = ptemp;                             /* Prevent compiler warning for 'ptemp' not being used! */
+}
+#endif

+ 29 - 0
MiddleWare/uCOS_II/uCOS-II/Source/os.h

@@ -0,0 +1,29 @@
+/*
+*********************************************************************************************************
+*                                              uC/OS-II
+*                                        The Real-Time Kernel
+*
+*                            (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : os.h
+* By      : Jean J. Labrosse
+* Version : V2.92.10
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+* 
+* Note : This file is included in the uC/OS-II for compatibility with uC/OS-III and should not be used
+*        in normal circumstances.
+*********************************************************************************************************
+*/
+
+#include  <ucos_ii.h>
+
+
+typedef  INT8U  OS_ERR;

+ 2092 - 0
MiddleWare/uCOS_II/uCOS-II/Source/os_core.c

@@ -0,0 +1,2092 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                             CORE FUNCTIONS
+*
+*                              (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_CORE.C
+* By      : Jean J. Labrosse
+* Version : V2.92.10
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#define  MICRIUM_SOURCE
+
+#ifndef  OS_MASTER_FILE
+#define  OS_GLOBALS
+#include <ucos_ii.h>
+#endif
+
+/*
+*********************************************************************************************************
+*                                      PRIORITY RESOLUTION TABLE
+*
+* Note: Index into table is bit pattern to resolve highest priority
+*       Indexed value corresponds to highest priority bit position (i.e. 0..7)
+*********************************************************************************************************
+*/
+
+INT8U  const  OSUnMapTbl[256] = {
+    0u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x00 to 0x0F                   */
+    4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x10 to 0x1F                   */
+    5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x20 to 0x2F                   */
+    4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x30 to 0x3F                   */
+    6u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x40 to 0x4F                   */
+    4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x50 to 0x5F                   */
+    5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x60 to 0x6F                   */
+    4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x70 to 0x7F                   */
+    7u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x80 to 0x8F                   */
+    4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x90 to 0x9F                   */
+    5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xA0 to 0xAF                   */
+    4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xB0 to 0xBF                   */
+    6u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xC0 to 0xCF                   */
+    4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xD0 to 0xDF                   */
+    5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xE0 to 0xEF                   */
+    4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u  /* 0xF0 to 0xFF                   */
+};
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                         FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+static  void  OS_InitEventList(void);
+
+static  void  OS_InitMisc(void);
+
+static  void  OS_InitRdyList(void);
+
+static  void  OS_InitTaskIdle(void);
+
+#if OS_TASK_STAT_EN > 0u
+static  void  OS_InitTaskStat(void);
+#endif
+
+static  void  OS_InitTCBList(void);
+
+static  void  OS_SchedNew(void);
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                        GET THE NAME OF A SEMAPHORE, MUTEX, MAILBOX or QUEUE
+*
+* Description: This function is used to obtain the name assigned to a semaphore, mutex, mailbox or queue.
+*
+* Arguments  : pevent    is a pointer to the event group.  'pevent' can point either to a semaphore,
+*                        a mutex, a mailbox or a queue.  Where this function is concerned, the actual
+*                        type is irrelevant.
+*
+*              pname     is a pointer to a pointer to an ASCII string that will receive the name of the semaphore,
+*                        mutex, mailbox or queue.
+*
+*              perr      is a pointer to an error code that can contain one of the following values:
+*
+*                        OS_ERR_NONE                if the name was copied to 'pname'
+*                        OS_ERR_EVENT_TYPE          if 'pevent' is not pointing to the proper event
+*                                                   control block type.
+*                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
+*                        OS_ERR_PEVENT_NULL         if you passed a NULL pointer for 'pevent'
+*                        OS_ERR_NAME_GET_ISR        if you are trying to call this function from an ISR
+*
+* Returns    : The length of the string or 0 if the 'pevent' is a NULL pointer.
+*********************************************************************************************************
+*/
+
+#if (OS_EVENT_EN) && (OS_EVENT_NAME_EN > 0u)
+INT8U  OSEventNameGet (OS_EVENT   *pevent,
+                       INT8U     **pname,
+                       INT8U      *perr)
+{
+    INT8U      len;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {               /* Is 'pevent' a NULL pointer?                        */
+        *perr = OS_ERR_PEVENT_NULL;
+        return (0u);
+    }
+    if (pname == (INT8U **)0) {                   /* Is 'pname' a NULL pointer?                         */
+        *perr = OS_ERR_PNAME_NULL;
+        return (0u);
+    }
+#endif
+    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
+        *perr  = OS_ERR_NAME_GET_ISR;
+        return (0u);
+    }
+    switch (pevent->OSEventType) {
+        case OS_EVENT_TYPE_SEM:
+        case OS_EVENT_TYPE_MUTEX:
+        case OS_EVENT_TYPE_MBOX:
+        case OS_EVENT_TYPE_Q:
+             break;
+
+        default:
+             *perr = OS_ERR_EVENT_TYPE;
+             return (0u);
+    }
+    OS_ENTER_CRITICAL();
+    *pname = pevent->OSEventName;
+    len    = OS_StrLen(*pname);
+    OS_EXIT_CRITICAL();
+    *perr  = OS_ERR_NONE;
+    return (len);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                        ASSIGN A NAME TO A SEMAPHORE, MUTEX, MAILBOX or QUEUE
+*
+* Description: This function assigns a name to a semaphore, mutex, mailbox or queue.
+*
+* Arguments  : pevent    is a pointer to the event group.  'pevent' can point either to a semaphore,
+*                        a mutex, a mailbox or a queue.  Where this function is concerned, it doesn't
+*                        matter the actual type.
+*
+*              pname     is a pointer to an ASCII string that will be used as the name of the semaphore,
+*                        mutex, mailbox or queue.
+*
+*              perr      is a pointer to an error code that can contain one of the following values:
+*
+*                        OS_ERR_NONE                if the requested task is resumed
+*                        OS_ERR_EVENT_TYPE          if 'pevent' is not pointing to the proper event
+*                                                   control block type.
+*                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
+*                        OS_ERR_PEVENT_NULL         if you passed a NULL pointer for 'pevent'
+*                        OS_ERR_NAME_SET_ISR        if you called this function from an ISR
+*
+* Returns    : None
+*********************************************************************************************************
+*/
+
+#if (OS_EVENT_EN) && (OS_EVENT_NAME_EN > 0u)
+void  OSEventNameSet (OS_EVENT  *pevent,
+                      INT8U     *pname,
+                      INT8U     *perr)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return;
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {               /* Is 'pevent' a NULL pointer?                        */
+        *perr = OS_ERR_PEVENT_NULL;
+        return;
+    }
+    if (pname == (INT8U *)0) {                   /* Is 'pname' a NULL pointer?                         */
+        *perr = OS_ERR_PNAME_NULL;
+        return;
+    }
+#endif
+    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
+        *perr = OS_ERR_NAME_SET_ISR;
+        return;
+    }
+    switch (pevent->OSEventType) {
+        case OS_EVENT_TYPE_SEM:
+        case OS_EVENT_TYPE_MUTEX:
+        case OS_EVENT_TYPE_MBOX:
+        case OS_EVENT_TYPE_Q:
+             break;
+
+        default:
+             *perr = OS_ERR_EVENT_TYPE;
+             return;
+    }
+    OS_ENTER_CRITICAL();
+    pevent->OSEventName = pname;
+    OS_EXIT_CRITICAL();
+    *perr = OS_ERR_NONE;
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       PEND ON MULTIPLE EVENTS
+*
+* Description: This function waits for multiple events.  If multiple events are ready at the start of the
+*              pend call, then all available events are returned as ready.  If the task must pend on the
+*              multiple events, then only the first posted or aborted event is returned as ready.
+*
+* Arguments  : pevents_pend  is a pointer to a NULL-terminated array of event control blocks to wait for.
+*
+*              pevents_rdy   is a pointer to an array to return which event control blocks are available
+*                            or ready.  The size of the array MUST be greater than or equal to the size
+*                            of the 'pevents_pend' array, including terminating NULL.
+*
+*              pmsgs_rdy     is a pointer to an array to return messages from any available message-type
+*                            events.  The size of the array MUST be greater than or equal to the size of
+*                            the 'pevents_pend' array, excluding the terminating NULL.  Since NULL
+*                            messages are valid messages, this array cannot be NULL-terminated.  Instead,
+*                            every available message-type event returns its messages in the 'pmsgs_rdy'
+*                            array at the same index as the event is returned in the 'pevents_rdy' array.
+*                            All other 'pmsgs_rdy' array indices are filled with NULL messages.
+*
+*              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
+*                            wait for the resources up to the amount of time specified by this argument.
+*                            If you specify 0, however, your task will wait forever for the specified
+*                            events or, until the resources becomes available (or the events occur).
+*
+*              perr          is a pointer to where an error message will be deposited.  Possible error
+*                            messages are:
+*
+*                            OS_ERR_NONE         The call was successful and your task owns the resources
+*                                                or, the events you are waiting for occurred; check the
+*                                                'pevents_rdy' array for which events are available.
+*                            OS_ERR_PEND_ABORT   The wait on the events was aborted; check the
+*                                                'pevents_rdy' array for which events were aborted.
+*                            OS_ERR_TIMEOUT      The events were not received within the specified
+*                                                'timeout'.
+*                            OS_ERR_PEVENT_NULL  If 'pevents_pend', 'pevents_rdy', or 'pmsgs_rdy' is a
+*                                                NULL pointer.
+*                            OS_ERR_EVENT_TYPE   If you didn't pass a pointer to an array of semaphores,
+*                                                mailboxes, and/or queues.
+*                            OS_ERR_PEND_ISR     If you called this function from an ISR and the result
+*                                                would lead to a suspension.
+*                            OS_ERR_PEND_LOCKED  If you called this function when the scheduler is locked.
+*
+* Returns    : >  0          the number of events returned as ready or aborted.
+*              == 0          if no events are returned as ready because of timeout or upon error.
+*
+* Notes      : 1) a. Validate 'pevents_pend' array as valid OS_EVENTs :
+*
+*                        semaphores, mailboxes, queues
+*
+*                 b. Return ALL available events and messages, if any
+*
+*                 c. Add    current task priority as pending to   each events's wait list
+*                      Performed in OS_EventTaskWaitMulti()
+*
+*                 d. Wait on any of multiple events
+*
+*                 e. Remove current task priority as pending from each events's wait list
+*                      Performed in OS_EventTaskRdy(), if events posted or aborted
+*
+*                 f. Return any event posted or aborted, if any
+*                      else
+*                    Return timeout
+*
+*              2) 'pevents_rdy' initialized to NULL PRIOR to all other validation or function handling in
+*                 case of any error(s).
+*********************************************************************************************************
+*/
+/*$PAGE*/
+#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u))
+INT16U  OSEventPendMulti (OS_EVENT  **pevents_pend,
+                          OS_EVENT  **pevents_rdy,
+                          void      **pmsgs_rdy,
+                          INT32U      timeout,
+                          INT8U      *perr)
+{
+    OS_EVENT  **pevents;
+    OS_EVENT   *pevent;
+#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u))
+    OS_Q       *pq;
+#endif
+    BOOLEAN     events_rdy;
+    INT16U      events_rdy_nbr;
+    INT8U       events_stat;
+#if (OS_CRITICAL_METHOD == 3u)                          /* Allocate storage for CPU status register    */
+    OS_CPU_SR   cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if (OS_ARG_CHK_EN > 0u)
+    if (pevents_pend == (OS_EVENT **)0) {               /* Validate 'pevents_pend'                     */
+       *perr =  OS_ERR_PEVENT_NULL;
+        return (0u);
+    }
+    if (*pevents_pend  == (OS_EVENT *)0) {              /* Validate 'pevents_pend'                     */
+       *perr =  OS_ERR_PEVENT_NULL;
+        return (0u);
+    }
+    if (pevents_rdy  == (OS_EVENT **)0) {               /* Validate 'pevents_rdy'                      */
+       *perr =  OS_ERR_PEVENT_NULL;
+        return (0u);
+    }
+    if (pmsgs_rdy == (void **)0) {                      /* Validate 'pmsgs_rdy'                        */
+       *perr =  OS_ERR_PEVENT_NULL;
+        return (0u);
+    }
+#endif
+
+   *pevents_rdy = (OS_EVENT *)0;                        /* Init array to NULL in case of errors        */
+
+    pevents     =  pevents_pend;
+    pevent      = *pevents;
+    while  (pevent != (OS_EVENT *)0) {
+        switch (pevent->OSEventType) {                  /* Validate event block types                  */
+#if (OS_SEM_EN  > 0u)
+            case OS_EVENT_TYPE_SEM:
+                 break;
+#endif
+#if (OS_MBOX_EN > 0u)
+            case OS_EVENT_TYPE_MBOX:
+                 break;
+#endif
+#if ((OS_Q_EN   > 0u) && (OS_MAX_QS > 0u))
+            case OS_EVENT_TYPE_Q:
+                 break;
+#endif
+
+            case OS_EVENT_TYPE_MUTEX:
+            case OS_EVENT_TYPE_FLAG:
+            default:
+                *perr = OS_ERR_EVENT_TYPE;
+                 return (0u);
+        }
+        pevents++;
+        pevent = *pevents;
+    }
+
+    if (OSIntNesting  > 0u) {                           /* See if called from ISR ...                  */
+       *perr =  OS_ERR_PEND_ISR;                        /* ... can't PEND from an ISR                  */
+        return (0u);
+    }
+    if (OSLockNesting > 0u) {                           /* See if called with scheduler locked ...     */
+       *perr =  OS_ERR_PEND_LOCKED;                     /* ... can't PEND when locked                  */
+        return (0u);
+    }
+
+/*$PAGE*/
+    events_rdy     =  OS_FALSE;
+    events_rdy_nbr =  0u;
+    events_stat    =  OS_STAT_RDY;
+    pevents        =  pevents_pend;
+    pevent         = *pevents;
+    OS_ENTER_CRITICAL();
+    while (pevent != (OS_EVENT *)0) {                   /* See if any events already available         */
+        switch (pevent->OSEventType) {
+#if (OS_SEM_EN > 0u)
+            case OS_EVENT_TYPE_SEM:
+                 if (pevent->OSEventCnt > 0u) {         /* If semaphore count > 0, resource available; */
+                     pevent->OSEventCnt--;              /* ... decrement semaphore,                ... */
+                    *pevents_rdy++ =  pevent;           /* ... and return available semaphore event    */
+                      events_rdy   =  OS_TRUE;
+                    *pmsgs_rdy++   = (void *)0;         /* NO message returned  for semaphores         */
+                      events_rdy_nbr++;
+
+                 } else {
+                      events_stat |=  OS_STAT_SEM;      /* Configure multi-pend for semaphore events   */
+                 }
+                 break;
+#endif
+
+#if (OS_MBOX_EN > 0u)
+            case OS_EVENT_TYPE_MBOX:
+                 if (pevent->OSEventPtr != (void *)0) { /* If mailbox NOT empty;                   ... */
+                                                        /* ... return available message,           ... */
+                    *pmsgs_rdy++         = (void *)pevent->OSEventPtr;
+                     pevent->OSEventPtr  = (void *)0;
+                    *pevents_rdy++       =  pevent;     /* ... and return available mailbox event      */
+                      events_rdy         =  OS_TRUE;
+                      events_rdy_nbr++;
+
+                 } else {
+                      events_stat |= OS_STAT_MBOX;      /* Configure multi-pend for mailbox events     */
+                 }
+                 break;
+#endif
+
+#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u))
+            case OS_EVENT_TYPE_Q:
+                 pq = (OS_Q *)pevent->OSEventPtr;
+                 if (pq->OSQEntries > 0u) {             /* If queue NOT empty;                     ... */
+                                                        /* ... return available message,           ... */
+                    *pmsgs_rdy++ = (void *)*pq->OSQOut++;
+                     if (pq->OSQOut == pq->OSQEnd) {    /* If OUT ptr at queue end, ...                */
+                         pq->OSQOut  = pq->OSQStart;    /* ... wrap   to queue start                   */
+                     }
+                     pq->OSQEntries--;                  /* Update number of queue entries              */
+                    *pevents_rdy++ = pevent;            /* ... and return available queue event        */
+                      events_rdy   = OS_TRUE;
+                      events_rdy_nbr++;
+
+                 } else {
+                      events_stat |= OS_STAT_Q;         /* Configure multi-pend for queue events       */
+                 }
+                 break;
+#endif
+
+            case OS_EVENT_TYPE_MUTEX:
+            case OS_EVENT_TYPE_FLAG:
+            default:
+                 OS_EXIT_CRITICAL();
+                *pevents_rdy = (OS_EVENT *)0;           /* NULL terminate return event array           */
+                *perr        =  OS_ERR_EVENT_TYPE;
+                 return (events_rdy_nbr);
+        }
+        pevents++;
+        pevent = *pevents;
+    }
+
+    if ( events_rdy == OS_TRUE) {                       /* Return any events already available         */
+       *pevents_rdy = (OS_EVENT *)0;                    /* NULL terminate return event array           */
+        OS_EXIT_CRITICAL();
+       *perr        =  OS_ERR_NONE;
+        return (events_rdy_nbr);
+    }
+/*$PAGE*/
+                                                        /* Otherwise, must wait until any event occurs */
+    OSTCBCur->OSTCBStat     |= events_stat  |           /* Resource not available, ...                 */
+                               OS_STAT_MULTI;           /* ... pend on multiple events                 */
+    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
+    OSTCBCur->OSTCBDly       = timeout;                 /* Store pend timeout in TCB                   */
+    OS_EventTaskWaitMulti(pevents_pend);                /* Suspend task until events or timeout occurs */
+
+    OS_EXIT_CRITICAL();
+    OS_Sched();                                         /* Find next highest priority task ready       */
+    OS_ENTER_CRITICAL();
+
+    switch (OSTCBCur->OSTCBStatPend) {                  /* Handle event posted, aborted, or timed-out  */
+        case OS_STAT_PEND_OK:
+        case OS_STAT_PEND_ABORT:
+             pevent = OSTCBCur->OSTCBEventPtr;
+             if (pevent != (OS_EVENT *)0) {             /* If task event ptr != NULL, ...              */
+                *pevents_rdy++   =  pevent;             /* ... return available event ...              */
+                *pevents_rdy     = (OS_EVENT *)0;       /* ... & NULL terminate return event array     */
+                  events_rdy_nbr =  1;
+
+             } else {                                   /* Else NO event available, handle as timeout  */
+                 OSTCBCur->OSTCBStatPend = OS_STAT_PEND_TO;
+                 OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend);
+             }
+             break;
+
+        case OS_STAT_PEND_TO:                           /* If events timed out, ...                    */
+        default:                                        /* ... remove task from events' wait lists     */
+             OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend);
+             break;
+    }
+
+    switch (OSTCBCur->OSTCBStatPend) {
+        case OS_STAT_PEND_OK:
+             switch (pevent->OSEventType) {             /* Return event's message                      */
+#if (OS_SEM_EN > 0u)
+                 case OS_EVENT_TYPE_SEM:
+                     *pmsgs_rdy++ = (void *)0;          /* NO message returned for semaphores          */
+                      break;
+#endif
+
+#if ((OS_MBOX_EN > 0u) ||                 \
+    ((OS_Q_EN    > 0u) && (OS_MAX_QS > 0u)))
+                 case OS_EVENT_TYPE_MBOX:
+                 case OS_EVENT_TYPE_Q:
+                     *pmsgs_rdy++ = (void *)OSTCBCur->OSTCBMsg;     /* Return received message         */
+                      break;
+#endif
+
+                 case OS_EVENT_TYPE_MUTEX:
+                 case OS_EVENT_TYPE_FLAG:
+                 default:
+                      OS_EXIT_CRITICAL();
+                     *pevents_rdy = (OS_EVENT *)0;      /* NULL terminate return event array           */
+                     *perr        =  OS_ERR_EVENT_TYPE;
+                      return (events_rdy_nbr);
+             }
+            *perr = OS_ERR_NONE;
+             break;
+
+        case OS_STAT_PEND_ABORT:
+            *pmsgs_rdy++ = (void *)0;                   /* NO message returned for abort               */
+            *perr        =  OS_ERR_PEND_ABORT;          /* Indicate that event  aborted                */
+             break;
+
+        case OS_STAT_PEND_TO:
+        default:
+            *pmsgs_rdy++ = (void *)0;                   /* NO message returned for timeout             */
+            *perr        =  OS_ERR_TIMEOUT;             /* Indicate that events timed out              */
+             break;
+    }
+
+    OSTCBCur->OSTCBStat          =  OS_STAT_RDY;        /* Set   task  status to ready                 */
+    OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;    /* Clear pend  status                          */
+    OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;      /* Clear event pointers                        */
+    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
+#if ((OS_MBOX_EN > 0u) ||                 \
+    ((OS_Q_EN    > 0u) && (OS_MAX_QS > 0u)))
+    OSTCBCur->OSTCBMsg           = (void      *)0;      /* Clear task  message                         */
+#endif
+    OS_EXIT_CRITICAL();
+
+    return (events_rdy_nbr);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                           INITIALIZATION
+*
+* Description: This function is used to initialize the internals of uC/OS-II and MUST be called prior to
+*              creating any uC/OS-II object and, prior to calling OSStart().
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+void  OSInit (void)
+{
+#if OS_TASK_CREATE_EXT_EN > 0u
+#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
+    INT8U  err;
+#endif
+#endif
+
+    OSInitHookBegin();                                           /* Call port specific initialization code   */
+
+    OS_InitMisc();                                               /* Initialize miscellaneous variables       */
+
+    OS_InitRdyList();                                            /* Initialize the Ready List                */
+
+    OS_InitTCBList();                                            /* Initialize the free list of OS_TCBs      */
+
+    OS_InitEventList();                                          /* Initialize the free list of OS_EVENTs    */
+
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+    OS_FlagInit();                                               /* Initialize the event flag structures     */
+#endif
+
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+    OS_MemInit();                                                /* Initialize the memory manager            */
+#endif
+
+#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+    OS_QInit();                                                  /* Initialize the message queue structures  */
+#endif
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
+    OS_TLS_Init(&err);                                           /* Initialize TLS, before creating tasks    */
+    if (err != OS_ERR_NONE) {
+        return;
+    }
+#endif
+#endif
+
+    OS_InitTaskIdle();                                           /* Create the Idle Task                     */
+#if OS_TASK_STAT_EN > 0u
+    OS_InitTaskStat();                                           /* Create the Statistic Task                */
+#endif
+
+#if OS_TMR_EN > 0u
+    OSTmr_Init();                                                /* Initialize the Timer Manager             */
+#endif
+
+    OSInitHookEnd();                                             /* Call port specific init. code            */
+
+#if OS_DEBUG_EN > 0u
+    OSDebugInit();
+#endif
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                              ENTER ISR
+*
+* Description: This function is used to notify uC/OS-II that you are about to service an interrupt
+*              service routine (ISR).  This allows uC/OS-II to keep track of interrupt nesting and thus
+*              only perform rescheduling at the last nested ISR.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Notes      : 1) This function should be called with interrupts already disabled
+*              2) Your ISR can directly increment OSIntNesting without calling this function because
+*                 OSIntNesting has been declared 'global'.
+*              3) You MUST still call OSIntExit() even though you increment OSIntNesting directly.
+*              4) You MUST invoke OSIntEnter() and OSIntExit() in pair.  In other words, for every call
+*                 to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
+*                 end of the ISR.
+*              5) You are allowed to nest interrupts up to 255 levels deep.
+*              6) I removed the OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL() around the increment because
+*                 OSIntEnter() is always called with interrupts disabled.
+*********************************************************************************************************
+*/
+
+void  OSIntEnter (void)
+{
+    if (OSRunning == OS_TRUE) {
+        if (OSIntNesting < 255u) {
+            OSIntNesting++;                      /* Increment ISR nesting level                        */
+        }
+    }
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                              EXIT ISR
+*
+* Description: This function is used to notify uC/OS-II that you have completed servicing an ISR.  When
+*              the last nested ISR has completed, uC/OS-II will call the scheduler to determine whether
+*              a new, high-priority task, is ready to run.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Notes      : 1) You MUST invoke OSIntEnter() and OSIntExit() in pair.  In other words, for every call
+*                 to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the
+*                 end of the ISR.
+*              2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
+*********************************************************************************************************
+*/
+
+void  OSIntExit (void)
+{
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    if (OSRunning == OS_TRUE) {
+        OS_ENTER_CRITICAL();
+        if (OSIntNesting > 0u) {                           /* Prevent OSIntNesting from wrapping       */
+            OSIntNesting--;
+        }
+        if (OSIntNesting == 0u) {                          /* Reschedule only if all ISRs complete ... */
+            if (OSLockNesting == 0u) {                     /* ... and not locked.                      */
+                OS_SchedNew();
+                OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
+                if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy */
+#if OS_TASK_PROFILE_EN > 0u
+                    OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task  */
+#endif
+                    OSCtxSwCtr++;                          /* Keep track of the number of ctx switches */
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
+                    OS_TLS_TaskSw();
+#endif
+#endif
+
+                    OSIntCtxSw();                          /* Perform interrupt level ctx switch       */
+                }
+            }
+        }
+        OS_EXIT_CRITICAL();
+    }
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                         INDICATE THAT IT'S NO LONGER SAFE TO CREATE OBJECTS
+*
+* Description: This function is called by the application code to indicate that all initialization has
+*              been completed and that kernel objects are no longer allowed to be created.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Note(s)    : 1) You should call this function when you no longer want to allow application code to
+*                 create kernel objects.
+*              2) You need to define the macro 'OS_SAFETY_CRITICAL_IEC61508'
+*********************************************************************************************************
+*/
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+void  OSSafetyCriticalStart (void)
+{
+    OSSafetyCriticalStartFlag = OS_TRUE;
+}
+
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                         PREVENT SCHEDULING
+*
+* Description: This function is used to prevent rescheduling to take place.  This allows your application
+*              to prevent context switches until you are ready to permit context switching.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Notes      : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair.  In other words, for every
+*                 call to OSSchedLock() you MUST have a call to OSSchedUnlock().
+*********************************************************************************************************
+*/
+
+#if OS_SCHED_LOCK_EN > 0u
+void  OSSchedLock (void)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    if (OSRunning == OS_TRUE) {                  /* Make sure multitasking is running                  */
+        OS_ENTER_CRITICAL();
+        if (OSIntNesting == 0u) {                /* Can't call from an ISR                             */
+            if (OSLockNesting < 255u) {          /* Prevent OSLockNesting from wrapping back to 0      */
+                OSLockNesting++;                 /* Increment lock nesting level                       */
+            }
+        }
+        OS_EXIT_CRITICAL();
+    }
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                          ENABLE SCHEDULING
+*
+* Description: This function is used to re-allow rescheduling.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Notes      : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair.  In other words, for every
+*                 call to OSSchedLock() you MUST have a call to OSSchedUnlock().
+*********************************************************************************************************
+*/
+
+#if OS_SCHED_LOCK_EN > 0u
+void  OSSchedUnlock (void)
+{
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    if (OSRunning == OS_TRUE) {                            /* Make sure multitasking is running        */
+        OS_ENTER_CRITICAL();
+        if (OSIntNesting == 0u) {                          /* Can't call from an ISR                   */
+            if (OSLockNesting > 0u) {                      /* Do not decrement if already 0            */
+                OSLockNesting--;                           /* Decrement lock nesting level             */
+                if (OSLockNesting == 0u) {                 /* See if scheduler is enabled              */
+                    OS_EXIT_CRITICAL();
+                    OS_Sched();                            /* See if a HPT is ready                    */
+                } else {
+                    OS_EXIT_CRITICAL();
+                }
+            } else {
+                OS_EXIT_CRITICAL();
+            }
+        } else {
+            OS_EXIT_CRITICAL();
+        }
+    }
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                         START MULTITASKING
+*
+* Description: This function is used to start the multitasking process which lets uC/OS-II manages the
+*              task that you have created.  Before you can call OSStart(), you MUST have called OSInit()
+*              and you MUST have created at least one task.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Note       : OSStartHighRdy() MUST:
+*                 a) Call OSTaskSwHook() then,
+*                 b) Set OSRunning to OS_TRUE.
+*                 c) Load the context of the task pointed to by OSTCBHighRdy.
+*                 d_ Execute the task.
+*********************************************************************************************************
+*/
+
+void  OSStart (void)
+{
+    if (OSRunning == OS_FALSE) {
+        OS_SchedNew();                               /* Find highest priority's task priority number   */
+        OSPrioCur     = OSPrioHighRdy;
+        OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run    */
+        OSTCBCur      = OSTCBHighRdy;
+        OSStartHighRdy();                            /* Execute target specific code to start task     */
+    }
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                      STATISTICS INITIALIZATION
+*
+* Description: This function is called by your application to establish CPU usage by first determining
+*              how high a 32-bit counter would count to in 1 second if no other tasks were to execute
+*              during that time.  CPU usage is then determined by a low priority task which keeps track
+*              of this 32-bit counter every second but this time, with other tasks running.  CPU usage is
+*              determined by:
+*
+*                                             OSIdleCtr
+*                 CPU Usage (%) = 100 * (1 - ------------)
+*                                            OSIdleCtrMax
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+#if OS_TASK_STAT_EN > 0u
+void  OSStatInit (void)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    OSTimeDly(2u);                               /* Synchronize with clock tick                        */
+    OS_ENTER_CRITICAL();
+    OSIdleCtr    = 0uL;                          /* Clear idle counter                                 */
+    OS_EXIT_CRITICAL();
+    OSTimeDly(OS_TICKS_PER_SEC / 10u);           /* Determine MAX. idle counter value for 1/10 second  */
+    OS_ENTER_CRITICAL();
+    OSIdleCtrMax = OSIdleCtr;                    /* Store maximum idle counter count in 1/10 second    */
+    OSStatRdy    = OS_TRUE;
+    OS_EXIT_CRITICAL();
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                         PROCESS SYSTEM TICK
+*
+* Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known
+*              as a 'clock tick').  This function should be called by the ticker ISR but, can also be
+*              called by a high priority task.
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+void  OSTimeTick (void)
+{
+    OS_TCB    *ptcb;
+#if OS_TICK_STEP_EN > 0u
+    BOOLEAN    step;
+#endif
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register     */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_TIME_TICK_HOOK_EN > 0u
+    OSTimeTickHook();                                      /* Call user definable hook                     */
+#endif
+#if OS_TIME_GET_SET_EN > 0u
+    OS_ENTER_CRITICAL();                                   /* Update the 32-bit tick counter               */
+    OSTime++;
+    OS_EXIT_CRITICAL();
+#endif
+    if (OSRunning == OS_TRUE) {
+#if OS_TICK_STEP_EN > 0u
+        switch (OSTickStepState) {                         /* Determine whether we need to process a tick  */
+            case OS_TICK_STEP_DIS:                         /* Yes, stepping is disabled                    */
+                 step = OS_TRUE;
+                 break;
+
+            case OS_TICK_STEP_WAIT:                        /* No,  waiting for uC/OS-View to set ...       */
+                 step = OS_FALSE;                          /*      .. OSTickStepState to OS_TICK_STEP_ONCE */
+                 break;
+
+            case OS_TICK_STEP_ONCE:                        /* Yes, process tick once and wait for next ... */
+                 step            = OS_TRUE;                /*      ... step command from uC/OS-View        */
+                 OSTickStepState = OS_TICK_STEP_WAIT;
+                 break;
+
+            default:                                       /* Invalid case, correct situation              */
+                 step            = OS_TRUE;
+                 OSTickStepState = OS_TICK_STEP_DIS;
+                 break;
+        }
+        if (step == OS_FALSE) {                            /* Return if waiting for step command           */
+            return;
+        }
+#endif
+        ptcb = OSTCBList;                                  /* Point at first TCB in TCB list               */
+        while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {     /* Go through all TCBs in TCB list              */
+            OS_ENTER_CRITICAL();
+            if (ptcb->OSTCBDly != 0u) {                    /* No, Delayed or waiting for event with TO     */
+                ptcb->OSTCBDly--;                          /* Decrement nbr of ticks to end of delay       */
+                if (ptcb->OSTCBDly == 0u) {                /* Check for timeout                            */
+
+                    if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
+                        ptcb->OSTCBStat  &= (INT8U)~(INT8U)OS_STAT_PEND_ANY;          /* Yes, Clear status flag   */
+                        ptcb->OSTCBStatPend = OS_STAT_PEND_TO;                 /* Indicate PEND timeout    */
+                    } else {
+                        ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
+                    }
+
+                    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {  /* Is task suspended?       */
+                        OSRdyGrp               |= ptcb->OSTCBBitY;             /* No,  Make ready          */
+                        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
+                    }
+                }
+            }
+            ptcb = ptcb->OSTCBNext;                        /* Point at next TCB in TCB list                */
+            OS_EXIT_CRITICAL();
+        }
+    }
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                             GET VERSION
+*
+* Description: This function is used to return the version number of uC/OS-II.  The returned value 
+*              corresponds to uC/OS-II's version number multiplied by 10000.  In other words, version 
+*              2.01.00 would be returned as 20100.
+*
+* Arguments  : none
+*
+* Returns    : The version number of uC/OS-II multiplied by 10000.
+*********************************************************************************************************
+*/
+
+INT16U  OSVersion (void)
+{
+    return (OS_VERSION);
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                           DUMMY FUNCTION
+*
+* Description: This function doesn't do anything.  It is called by OSTaskDel().
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+#if OS_TASK_DEL_EN > 0u
+void  OS_Dummy (void)
+{
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                           MAKE TASK READY TO RUN BASED ON EVENT OCCURING
+*
+* Description: This function is called by other uC/OS-II services and is used to ready a task that was
+*              waiting for an event to occur.
+*
+* Arguments  : pevent      is a pointer to the event control block corresponding to the event.
+*
+*              pmsg        is a pointer to a message.  This pointer is used by message oriented services
+*                          such as MAILBOXEs and QUEUEs.  The pointer is not used when called by other
+*                          service functions.
+*
+*              msk         is a mask that is used to clear the status byte of the TCB.  For example,
+*                          OSSemPost() will pass OS_STAT_SEM, OSMboxPost() will pass OS_STAT_MBOX etc.
+*
+*              pend_stat   is used to indicate the readied task's pending status:
+*
+*                          OS_STAT_PEND_OK      Task ready due to a post (or delete), not a timeout or
+*                                               an abort.
+*                          OS_STAT_PEND_ABORT   Task ready due to an abort.
+*
+* Returns    : none
+*
+* Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+#if (OS_EVENT_EN)
+INT8U  OS_EventTaskRdy (OS_EVENT  *pevent,
+                        void      *pmsg,
+                        INT8U      msk,
+                        INT8U      pend_stat)
+{
+    OS_TCB   *ptcb;
+    INT8U     y;
+    INT8U     x;
+    INT8U     prio;
+#if OS_LOWEST_PRIO > 63u
+    OS_PRIO  *ptbl;
+#endif
+
+
+#if OS_LOWEST_PRIO <= 63u
+    y    = OSUnMapTbl[pevent->OSEventGrp];              /* Find HPT waiting for message                */
+    x    = OSUnMapTbl[pevent->OSEventTbl[y]];
+    prio = (INT8U)((y << 3u) + x);                      /* Find priority of task getting the msg       */
+#else
+    if ((pevent->OSEventGrp & 0xFFu) != 0u) {           /* Find HPT waiting for message                */
+        y = OSUnMapTbl[ pevent->OSEventGrp & 0xFFu];
+    } else {
+        y = OSUnMapTbl[(OS_PRIO)(pevent->OSEventGrp >> 8u) & 0xFFu] + 8u;
+    }
+    ptbl = &pevent->OSEventTbl[y];
+    if ((*ptbl & 0xFFu) != 0u) {
+        x = OSUnMapTbl[*ptbl & 0xFFu];
+    } else {
+        x = OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u;
+    }
+    prio = (INT8U)((y << 4u) + x);                      /* Find priority of task getting the msg       */
+#endif
+
+    ptcb                  =  OSTCBPrioTbl[prio];        /* Point to this task's OS_TCB                 */
+    ptcb->OSTCBDly        =  0u;                        /* Prevent OSTimeTick() from readying task     */
+#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u)
+    ptcb->OSTCBMsg        =  pmsg;                      /* Send message directly to waiting task       */
+#else
+    pmsg                  =  pmsg;                      /* Prevent compiler warning if not used        */
+#endif
+    ptcb->OSTCBStat      &= (INT8U)~msk;                /* Clear bit associated with event type        */
+    ptcb->OSTCBStatPend   =  pend_stat;                 /* Set pend status of post or abort            */
+                                                        /* See if task is ready (could be susp'd)      */
+    if ((ptcb->OSTCBStat &   OS_STAT_SUSPEND) == OS_STAT_RDY) {
+        OSRdyGrp         |=  ptcb->OSTCBBitY;           /* Put task in the ready to run list           */
+        OSRdyTbl[y]      |=  ptcb->OSTCBBitX;
+    }
+
+    OS_EventTaskRemove(ptcb, pevent);                   /* Remove this task from event   wait list     */
+#if (OS_EVENT_MULTI_EN > 0u)
+    if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) {   /* Remove this task from events' wait lists    */
+        OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr);
+        ptcb->OSTCBEventPtr       = (OS_EVENT  *)pevent;/* Return event as first multi-pend event ready*/
+    }
+#endif
+
+    return (prio);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                  MAKE TASK WAIT FOR EVENT TO OCCUR
+*
+* Description: This function is called by other uC/OS-II services to suspend a task because an event has
+*              not occurred.
+*
+* Arguments  : pevent   is a pointer to the event control block for which the task will be waiting for.
+*
+* Returns    : none
+*
+* Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+#if (OS_EVENT_EN)
+void  OS_EventTaskWait (OS_EVENT *pevent)
+{
+    INT8U  y;
+
+
+    OSTCBCur->OSTCBEventPtr               = pevent;                 /* Store ptr to ECB in TCB         */
+
+    pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;    /* Put task in waiting list        */
+    pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;
+
+    y             =  OSTCBCur->OSTCBY;            /* Task no longer ready                              */
+    OSRdyTbl[y]  &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
+    if (OSRdyTbl[y] == 0u) {                      /* Clear event grp bit if this was only task pending */
+        OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
+    }
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                         MAKE TASK WAIT FOR ANY OF MULTIPLE EVENTS TO OCCUR
+*
+* Description: This function is called by other uC/OS-II services to suspend a task because any one of
+*              multiple events has not occurred.
+*
+* Arguments  : pevents_wait     is a pointer to an array of event control blocks, NULL-terminated, for
+*                               which the task will be waiting for.
+*
+* Returns    : none.
+*
+* Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u))
+void  OS_EventTaskWaitMulti (OS_EVENT **pevents_wait)
+{
+    OS_EVENT **pevents;
+    OS_EVENT  *pevent;
+    INT8U      y;
+
+
+    OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;
+    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)pevents_wait;       /* Store ptr to ECBs in TCB        */
+
+    pevents =  pevents_wait;
+    pevent  = *pevents;
+    while (pevent != (OS_EVENT *)0) {                               /* Put task in waiting lists       */
+        pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;
+        pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;
+        pevents++;
+        pevent = *pevents;
+    }
+
+    y             =  OSTCBCur->OSTCBY;            /* Task no longer ready                              */
+    OSRdyTbl[y]  &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
+    if (OSRdyTbl[y] == 0u) {                      /* Clear event grp bit if this was only task pending */
+        OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
+    }
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                  REMOVE TASK FROM EVENT WAIT LIST
+*
+* Description: Remove a task from an event's wait list.
+*
+* Arguments  : ptcb     is a pointer to the task to remove.
+*
+*              pevent   is a pointer to the event control block.
+*
+* Returns    : none
+*
+* Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+#if (OS_EVENT_EN)
+void  OS_EventTaskRemove (OS_TCB   *ptcb,
+                          OS_EVENT *pevent)
+{
+    INT8U  y;
+
+
+    y                       =  ptcb->OSTCBY;
+    pevent->OSEventTbl[y]  &= (OS_PRIO)~ptcb->OSTCBBitX;    /* Remove task from wait list              */
+    if (pevent->OSEventTbl[y] == 0u) {
+        pevent->OSEventGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
+    }
+    ptcb->OSTCBEventPtr     = (OS_EVENT  *)0;               /* Unlink OS_EVENT from OS_TCB             */
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                             REMOVE TASK FROM MULTIPLE EVENTS WAIT LISTS
+*
+* Description: Remove a task from multiple events' wait lists.
+*
+* Arguments  : ptcb             is a pointer to the task to remove.
+*
+*              pevents_multi    is a pointer to the array of event control blocks, NULL-terminated.
+*
+* Returns    : none
+*
+* Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u))
+void  OS_EventTaskRemoveMulti (OS_TCB    *ptcb,
+                               OS_EVENT **pevents_multi)
+{
+    OS_EVENT **pevents;
+    OS_EVENT  *pevent;
+    INT8U      y;
+    OS_PRIO    bity;
+    OS_PRIO    bitx;
+
+
+    y       =  ptcb->OSTCBY;
+    bity    =  ptcb->OSTCBBitY;
+    bitx    =  ptcb->OSTCBBitX;
+    pevents =  pevents_multi;
+    pevent  = *pevents;
+    while (pevent != (OS_EVENT *)0) {                   /* Remove task from all events' wait lists     */
+        pevent->OSEventTbl[y]  &= (OS_PRIO)~bitx;
+        if (pevent->OSEventTbl[y] == 0u) {
+            pevent->OSEventGrp &= (OS_PRIO)~bity;
+        }
+        pevents++;
+        pevent = *pevents;
+    }
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                             INITIALIZE EVENT CONTROL BLOCK'S WAIT LIST
+*
+* Description: This function is called by other uC/OS-II services to initialize the event wait list.
+*
+* Arguments  : pevent    is a pointer to the event control block allocated to the event.
+*
+* Returns    : none
+*
+* Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+#if (OS_EVENT_EN)
+void  OS_EventWaitListInit (OS_EVENT *pevent)
+{
+    INT8U  i;
+
+
+    pevent->OSEventGrp = 0u;                     /* No task waiting on event                           */
+    for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
+        pevent->OSEventTbl[i] = 0u;
+    }
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                             INITIALIZATION
+*                           INITIALIZE THE FREE LIST OF EVENT CONTROL BLOCKS
+*
+* Description: This function is called by OSInit() to initialize the free list of event control blocks.
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+static  void  OS_InitEventList (void)
+{
+#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u)
+#if (OS_MAX_EVENTS > 1u)
+    INT16U     ix;
+    INT16U     ix_next;
+    OS_EVENT  *pevent1;
+    OS_EVENT  *pevent2;
+
+
+    OS_MemClr((INT8U *)&OSEventTbl[0], sizeof(OSEventTbl)); /* Clear the event table                   */
+    for (ix = 0u; ix < (OS_MAX_EVENTS - 1u); ix++) {        /* Init. list of free EVENT control blocks */
+        ix_next = ix + 1u;
+        pevent1 = &OSEventTbl[ix];
+        pevent2 = &OSEventTbl[ix_next];
+        pevent1->OSEventType    = OS_EVENT_TYPE_UNUSED;
+        pevent1->OSEventPtr     = pevent2;
+#if OS_EVENT_NAME_EN > 0u
+        pevent1->OSEventName    = (INT8U *)(void *)"?";     /* Unknown name                            */
+#endif
+    }
+    pevent1                         = &OSEventTbl[ix];
+    pevent1->OSEventType            = OS_EVENT_TYPE_UNUSED;
+    pevent1->OSEventPtr             = (OS_EVENT *)0;
+#if OS_EVENT_NAME_EN > 0u
+    pevent1->OSEventName            = (INT8U *)(void *)"?"; /* Unknown name                            */
+#endif
+    OSEventFreeList                 = &OSEventTbl[0];
+#else
+    OSEventFreeList                 = &OSEventTbl[0];       /* Only have ONE event control block       */
+    OSEventFreeList->OSEventType    = OS_EVENT_TYPE_UNUSED;
+    OSEventFreeList->OSEventPtr     = (OS_EVENT *)0;
+#if OS_EVENT_NAME_EN > 0u
+    OSEventFreeList->OSEventName    = (INT8U *)"?";         /* Unknown name                            */
+#endif
+#endif
+#endif
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                             INITIALIZATION
+*                                    INITIALIZE MISCELLANEOUS VARIABLES
+*
+* Description: This function is called by OSInit() to initialize miscellaneous variables.
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+static  void  OS_InitMisc (void)
+{
+#if OS_TIME_GET_SET_EN > 0u
+    OSTime                    = 0uL;                       /* Clear the 32-bit system clock            */
+#endif
+
+    OSIntNesting              = 0u;                        /* Clear the interrupt nesting counter      */
+    OSLockNesting             = 0u;                        /* Clear the scheduling lock counter        */
+
+    OSTaskCtr                 = 0u;                        /* Clear the number of tasks                */
+
+    OSRunning                 = OS_FALSE;                  /* Indicate that multitasking not started   */
+
+    OSCtxSwCtr                = 0u;                        /* Clear the context switch counter         */
+    OSIdleCtr                 = 0uL;                       /* Clear the 32-bit idle counter            */
+
+#if OS_TASK_STAT_EN > 0u
+    OSIdleCtrRun              = 0uL;
+    OSIdleCtrMax              = 0uL;
+    OSStatRdy                 = OS_FALSE;                  /* Statistic task is not ready              */
+#endif
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    OSSafetyCriticalStartFlag = OS_FALSE;                  /* Still allow creation of objects          */
+#endif
+
+#if OS_TASK_REG_TBL_SIZE > 0u
+    OSTaskRegNextAvailID      = 0u;                        /* Initialize the task register ID          */
+#endif
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                             INITIALIZATION
+*                                       INITIALIZE THE READY LIST
+*
+* Description: This function is called by OSInit() to initialize the Ready List.
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+static  void  OS_InitRdyList (void)
+{
+    INT8U  i;
+
+
+    OSRdyGrp      = 0u;                                    /* Clear the ready list                     */
+    for (i = 0u; i < OS_RDY_TBL_SIZE; i++) {
+        OSRdyTbl[i] = 0u;
+    }
+
+    OSPrioCur     = 0u;
+    OSPrioHighRdy = 0u;
+
+    OSTCBHighRdy  = (OS_TCB *)0;
+    OSTCBCur      = (OS_TCB *)0;
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                             INITIALIZATION
+*                                         CREATING THE IDLE TASK
+*
+* Description: This function creates the Idle Task.
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+static  void  OS_InitTaskIdle (void)
+{
+#if OS_TASK_NAME_EN > 0u
+    INT8U  err;
+#endif
+
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+    #if OS_STK_GROWTH == 1u
+    (void)OSTaskCreateExt(OS_TaskIdle,
+                          (void *)0,                                 /* No arguments passed to OS_TaskIdle() */
+                          &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u],/* Set Top-Of-Stack                     */
+                          OS_TASK_IDLE_PRIO,                         /* Lowest priority level                */
+                          OS_TASK_IDLE_ID,
+                          &OSTaskIdleStk[0],                         /* Set Bottom-Of-Stack                  */
+                          OS_TASK_IDLE_STK_SIZE,
+                          (void *)0,                                 /* No TCB extension                     */
+                          OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack  */
+    #else
+    (void)OSTaskCreateExt(OS_TaskIdle,
+                          (void *)0,                                 /* No arguments passed to OS_TaskIdle() */
+                          &OSTaskIdleStk[0],                         /* Set Top-Of-Stack                     */
+                          OS_TASK_IDLE_PRIO,                         /* Lowest priority level                */
+                          OS_TASK_IDLE_ID,
+                          &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u],/* Set Bottom-Of-Stack                  */
+                          OS_TASK_IDLE_STK_SIZE,
+                          (void *)0,                                 /* No TCB extension                     */
+                          OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack  */
+    #endif
+#else
+    #if OS_STK_GROWTH == 1u
+    (void)OSTaskCreate(OS_TaskIdle,
+                       (void *)0,
+                       &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u],
+                       OS_TASK_IDLE_PRIO);
+    #else
+    (void)OSTaskCreate(OS_TaskIdle,
+                       (void *)0,
+                       &OSTaskIdleStk[0],
+                       OS_TASK_IDLE_PRIO);
+    #endif
+#endif
+
+#if OS_TASK_NAME_EN > 0u
+    OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)(void *)"uC/OS-II Idle", &err);
+#endif
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                             INITIALIZATION
+*                                      CREATING THE STATISTIC TASK
+*
+* Description: This function creates the Statistic Task.
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+#if OS_TASK_STAT_EN > 0u
+static  void  OS_InitTaskStat (void)
+{
+#if OS_TASK_NAME_EN > 0u
+    INT8U  err;
+#endif
+
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+    #if OS_STK_GROWTH == 1u
+    (void)OSTaskCreateExt(OS_TaskStat,
+                          (void *)0,                                   /* No args passed to OS_TaskStat()*/
+                          &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u],  /* Set Top-Of-Stack               */
+                          OS_TASK_STAT_PRIO,                           /* One higher than the idle task  */
+                          OS_TASK_STAT_ID,
+                          &OSTaskStatStk[0],                           /* Set Bottom-Of-Stack            */
+                          OS_TASK_STAT_STK_SIZE,
+                          (void *)0,                                   /* No TCB extension               */
+                          OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */
+    #else
+    (void)OSTaskCreateExt(OS_TaskStat,
+                          (void *)0,                                   /* No args passed to OS_TaskStat()*/
+                          &OSTaskStatStk[0],                           /* Set Top-Of-Stack               */
+                          OS_TASK_STAT_PRIO,                           /* One higher than the idle task  */
+                          OS_TASK_STAT_ID,
+                          &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u],  /* Set Bottom-Of-Stack            */
+                          OS_TASK_STAT_STK_SIZE,
+                          (void *)0,                                   /* No TCB extension               */
+                          OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */
+    #endif
+#else
+    #if OS_STK_GROWTH == 1u
+    (void)OSTaskCreate(OS_TaskStat,
+                       (void *)0,                                      /* No args passed to OS_TaskStat()*/
+                       &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u],     /* Set Top-Of-Stack               */
+                       OS_TASK_STAT_PRIO);                             /* One higher than the idle task  */
+    #else
+    (void)OSTaskCreate(OS_TaskStat,
+                       (void *)0,                                      /* No args passed to OS_TaskStat()*/
+                       &OSTaskStatStk[0],                              /* Set Top-Of-Stack               */
+                       OS_TASK_STAT_PRIO);                             /* One higher than the idle task  */
+    #endif
+#endif
+
+#if OS_TASK_NAME_EN > 0u
+    OSTaskNameSet(OS_TASK_STAT_PRIO, (INT8U *)(void *)"uC/OS-II Stat", &err);
+#endif
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                             INITIALIZATION
+*                            INITIALIZE THE FREE LIST OF TASK CONTROL BLOCKS
+*
+* Description: This function is called by OSInit() to initialize the free list of OS_TCBs.
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+static  void  OS_InitTCBList (void)
+{
+    INT8U    ix;
+    INT8U    ix_next;
+    OS_TCB  *ptcb1;
+    OS_TCB  *ptcb2;
+
+
+    OS_MemClr((INT8U *)&OSTCBTbl[0],     sizeof(OSTCBTbl));      /* Clear all the TCBs                 */
+    OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl));  /* Clear the priority table           */
+    for (ix = 0u; ix < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1u); ix++) {    /* Init. list of free TCBs     */
+        ix_next =  ix + 1u;
+        ptcb1   = &OSTCBTbl[ix];
+        ptcb2   = &OSTCBTbl[ix_next];
+        ptcb1->OSTCBNext = ptcb2;
+#if OS_TASK_NAME_EN > 0u
+        ptcb1->OSTCBTaskName = (INT8U *)(void *)"?";             /* Unknown name                       */
+#endif
+    }
+    ptcb1                   = &OSTCBTbl[ix];
+    ptcb1->OSTCBNext        = (OS_TCB *)0;                       /* Last OS_TCB                        */
+#if OS_TASK_NAME_EN > 0u
+    ptcb1->OSTCBTaskName    = (INT8U *)(void *)"?";              /* Unknown name                       */
+#endif
+    OSTCBList               = (OS_TCB *)0;                       /* TCB lists initializations          */
+    OSTCBFreeList           = &OSTCBTbl[0];
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                      CLEAR A SECTION OF MEMORY
+*
+* Description: This function is called by other uC/OS-II services to clear a contiguous block of RAM.
+*
+* Arguments  : pdest    is the start of the RAM to clear (i.e. write 0x00 to)
+*
+*              size     is the number of bytes to clear.
+*
+* Returns    : none
+*
+* Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
+*              2) Note that we can only clear up to 64K bytes of RAM.  This is not an issue because none
+*                 of the uses of this function gets close to this limit.
+*              3) The clear is done one byte at a time since this will work on any processor irrespective
+*                 of the alignment of the destination.
+*********************************************************************************************************
+*/
+
+void  OS_MemClr (INT8U  *pdest,
+                 INT16U  size)
+{
+    while (size > 0u) {
+        *pdest++ = (INT8U)0;
+        size--;
+    }
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       COPY A BLOCK OF MEMORY
+*
+* Description: This function is called by other uC/OS-II services to copy a block of memory from one
+*              location to another.
+*
+* Arguments  : pdest    is a pointer to the 'destination' memory block
+*
+*              psrc     is a pointer to the 'source'      memory block
+*
+*              size     is the number of bytes to copy.
+*
+* Returns    : none
+*
+* Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.  There is
+*                 no provision to handle overlapping memory copy.  However, that's not a problem since this
+*                 is not a situation that will happen.
+*              2) Note that we can only copy up to 64K bytes of RAM
+*              3) The copy is done one byte at a time since this will work on any processor irrespective
+*                 of the alignment of the source and destination.
+*********************************************************************************************************
+*/
+
+void  OS_MemCopy (INT8U  *pdest,
+                  INT8U  *psrc,
+                  INT16U  size)
+{
+    while (size > 0u) {
+        *pdest++ = *psrc++;
+        size--;
+    }
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                              SCHEDULER
+*
+* Description: This function is called by other uC/OS-II services to determine whether a new, high
+*              priority task has been made ready to run.  This function is invoked by TASK level code
+*              and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling).
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
+*              2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
+*********************************************************************************************************
+*/
+
+void  OS_Sched (void)
+{
+#if OS_CRITICAL_METHOD == 3u                           /* Allocate storage for CPU status register     */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    OS_ENTER_CRITICAL();
+    if (OSIntNesting == 0u) {                          /* Schedule only if all ISRs done and ...       */
+        if (OSLockNesting == 0u) {                     /* ... scheduler is not locked                  */
+            OS_SchedNew();
+            OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
+            if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy     */
+#if OS_TASK_PROFILE_EN > 0u
+                OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task      */
+#endif
+                OSCtxSwCtr++;                          /* Increment context switch counter             */
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
+                OS_TLS_TaskSw();
+#endif
+#endif
+
+                OS_TASK_SW();                          /* Perform a context switch                     */
+            }
+        }
+    }
+    OS_EXIT_CRITICAL();
+}
+
+
+/*
+*********************************************************************************************************
+*                               FIND HIGHEST PRIORITY TASK READY TO RUN
+*
+* Description: This function is called by other uC/OS-II services to determine the highest priority task
+*              that is ready to run.  The global variable 'OSPrioHighRdy' is changed accordingly.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
+*              2) Interrupts are assumed to be disabled when this function is called.
+*********************************************************************************************************
+*/
+
+static  void  OS_SchedNew (void)
+{
+#if OS_LOWEST_PRIO <= 63u                        /* See if we support up to 64 tasks                   */
+    INT8U   y;
+
+
+    y             = OSUnMapTbl[OSRdyGrp];
+    OSPrioHighRdy = (INT8U)((y << 3u) + OSUnMapTbl[OSRdyTbl[y]]);
+#else                                            /* We support up to 256 tasks                         */
+    INT8U     y;
+    OS_PRIO  *ptbl;
+
+
+    if ((OSRdyGrp & 0xFFu) != 0u) {
+        y = OSUnMapTbl[OSRdyGrp & 0xFFu];
+    } else {
+        y = OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] + 8u;
+    }
+    ptbl = &OSRdyTbl[y];
+    if ((*ptbl & 0xFFu) != 0u) {
+        OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(*ptbl & 0xFFu)]);
+    } else {
+        OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u);
+    }
+#endif
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                               DETERMINE THE LENGTH OF AN ASCII STRING
+*
+* Description: This function is called by other uC/OS-II services to determine the size of an ASCII string
+*              (excluding the NUL character).
+*
+* Arguments  : psrc     is a pointer to the string for which we need to know the size.
+*
+* Returns    : The size of the string (excluding the NUL terminating character)
+*
+* Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
+*              2) The string to check must be less than 255 characters long.
+*********************************************************************************************************
+*/
+
+#if (OS_EVENT_NAME_EN > 0u) || (OS_FLAG_NAME_EN > 0u) || (OS_MEM_NAME_EN > 0u) || (OS_TASK_NAME_EN > 0u) || (OS_TMR_CFG_NAME_EN > 0u)
+INT8U  OS_StrLen (INT8U *psrc)
+{
+    INT8U  len;
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (psrc == (INT8U *)0) {
+        return (0u);
+    }
+#endif
+
+    len = 0u;
+    while (*psrc != OS_ASCII_NUL) {
+        psrc++;
+        len++;
+    }
+    return (len);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                              IDLE TASK
+*
+* Description: This task is internal to uC/OS-II and executes whenever no other higher priority tasks
+*              executes because they are ALL waiting for event(s) to occur.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Note(s)    : 1) OSTaskIdleHook() is called after the critical section to ensure that interrupts will be
+*                 enabled for at least a few instructions.  On some processors (ex. Philips XA), enabling
+*                 and then disabling interrupts didn't allow the processor enough time to have interrupts
+*                 enabled before they were disabled again.  uC/OS-II would thus never recognize
+*                 interrupts.
+*              2) This hook has been added to allow you to do such things as STOP the CPU to conserve
+*                 power.
+*********************************************************************************************************
+*/
+
+void  OS_TaskIdle (void *p_arg)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    p_arg = p_arg;                               /* Prevent compiler warning for not using 'p_arg'     */
+    for (;;) {
+        OS_ENTER_CRITICAL();
+        OSIdleCtr++;
+        OS_EXIT_CRITICAL();
+        OSTaskIdleHook();                        /* Call user definable HOOK                           */
+    }
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                           STATISTICS TASK
+*
+* Description: This task is internal to uC/OS-II and is used to compute some statistics about the
+*              multitasking environment.  Specifically, OS_TaskStat() computes the CPU usage.
+*              CPU usage is determined by:
+*
+*                                          OSIdleCtr
+*                 OSCPUUsage = 100 * (1 - ------------)     (units are in %)
+*                                         OSIdleCtrMax
+*
+* Arguments  : parg     this pointer is not used at this time.
+*
+* Returns    : none
+*
+* Notes      : 1) This task runs at a priority level higher than the idle task.  In fact, it runs at the
+*                 next higher priority, OS_TASK_IDLE_PRIO-1.
+*              2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0.
+*              3) You MUST have at least a delay of 2/10 seconds to allow for the system to establish the
+*                 maximum value for the idle counter.
+*********************************************************************************************************
+*/
+
+#if OS_TASK_STAT_EN > 0u
+void  OS_TaskStat (void *p_arg)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    p_arg = p_arg;                               /* Prevent compiler warning for not using 'p_arg'     */
+    while (OSStatRdy == OS_FALSE) {
+        OSTimeDly(2u * OS_TICKS_PER_SEC / 10u);  /* Wait until statistic task is ready                 */
+    }
+    OSIdleCtrMax /= 100uL;
+    if (OSIdleCtrMax == 0uL) {
+        OSCPUUsage = 0u;
+#if OS_TASK_SUSPEND_EN > 0u
+        (void)OSTaskSuspend(OS_PRIO_SELF);
+#else
+        for (;;) {
+            OSTimeDly(OS_TICKS_PER_SEC);
+        }
+#endif
+    }
+    OS_ENTER_CRITICAL();
+    OSIdleCtr = OSIdleCtrMax * 100uL;            /* Set initial CPU usage as 0%                        */
+    OS_EXIT_CRITICAL();
+    for (;;) {
+        OS_ENTER_CRITICAL();
+        OSIdleCtrRun = OSIdleCtr;                /* Obtain the of the idle counter for the past second */
+        OSIdleCtr    = 0uL;                      /* Reset the idle counter for the next second         */
+        OS_EXIT_CRITICAL();
+        OSCPUUsage   = (INT8U)(100uL - OSIdleCtrRun / OSIdleCtrMax);
+        OSTaskStatHook();                        /* Invoke user definable hook                         */
+#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
+        OS_TaskStatStkChk();                     /* Check the stacks for each task                     */
+#endif
+        OSTimeDly(OS_TICKS_PER_SEC / 10u);       /* Accumulate OSIdleCtr for the next 1/10 second      */
+    }
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                        CHECK ALL TASK STACKS
+*
+* Description: This function is called by OS_TaskStat() to check the stacks of each active task.
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
+void  OS_TaskStatStkChk (void)
+{
+    OS_TCB      *ptcb;
+    OS_STK_DATA  stk_data;
+    INT8U        err;
+    INT8U        prio;
+
+
+    for (prio = 0u; prio <= OS_TASK_IDLE_PRIO; prio++) {
+        err = OSTaskStkChk(prio, &stk_data);
+        if (err == OS_ERR_NONE) {
+            ptcb = OSTCBPrioTbl[prio];
+            if (ptcb != (OS_TCB *)0) {                               /* Make sure task 'ptcb' is ...   */
+                if (ptcb != OS_TCB_RESERVED) {                       /* ... still valid.               */
+#if OS_TASK_PROFILE_EN > 0u
+                    #if OS_STK_GROWTH == 1u
+                    ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom + ptcb->OSTCBStkSize;
+                    #else
+                    ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom - ptcb->OSTCBStkSize;
+                    #endif
+                    ptcb->OSTCBStkUsed = stk_data.OSUsed;            /* Store number of entries used   */
+#endif
+                }
+            }
+        }
+    }
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                           INITIALIZE TCB
+*
+* Description: This function is internal to uC/OS-II and is used to initialize a Task Control Block when
+*              a task is created (see OSTaskCreate() and OSTaskCreateExt()).
+*
+* Arguments  : prio          is the priority of the task being created
+*
+*              ptos          is a pointer to the task's top-of-stack assuming that the CPU registers
+*                            have been placed on the stack.  Note that the top-of-stack corresponds to a
+*                            'high' memory location is OS_STK_GROWTH is set to 1 and a 'low' memory
+*                            location if OS_STK_GROWTH is set to 0.  Note that stack growth is CPU
+*                            specific.
+*
+*              pbos          is a pointer to the bottom of stack.  A NULL pointer is passed if called by
+*                            'OSTaskCreate()'.
+*
+*              id            is the task's ID (0..65535)
+*
+*              stk_size      is the size of the stack (in 'stack units').  If the stack units are INT8Us
+*                            then, 'stk_size' contains the number of bytes for the stack.  If the stack
+*                            units are INT32Us then, the stack contains '4 * stk_size' bytes.  The stack
+*                            units are established by the #define constant OS_STK which is CPU
+*                            specific.  'stk_size' is 0 if called by 'OSTaskCreate()'.
+*
+*              pext          is a pointer to a user supplied memory area that is used to extend the task
+*                            control block.  This allows you to store the contents of floating-point
+*                            registers, MMU registers or anything else you could find useful during a
+*                            context switch.  You can even assign a name to each task and store this name
+*                            in this TCB extension.  A NULL pointer is passed if called by OSTaskCreate().
+*
+*              opt           options as passed to 'OSTaskCreateExt()' or,
+*                            0 if called from 'OSTaskCreate()'.
+*
+* Returns    : OS_ERR_NONE              if the call was successful
+*              OS_ERR_TASK_NO_MORE_TCB  if there are no more free TCBs to be allocated and thus, the task
+*                                       cannot be created.
+*
+* Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+
+INT8U  OS_TCBInit (INT8U    prio,
+                   OS_STK  *ptos,
+                   OS_STK  *pbos,
+                   INT16U   id,
+                   INT32U   stk_size,
+                   void    *pext,
+                   INT16U   opt)
+{
+    OS_TCB    *ptcb;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+#if OS_TASK_REG_TBL_SIZE > 0u
+    INT8U      i;
+#endif
+#if OS_TASK_CREATE_EXT_EN > 0u
+#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
+    INT8U      j;
+#endif
+#endif
+
+
+    OS_ENTER_CRITICAL();
+    ptcb = OSTCBFreeList;                                  /* Get a free TCB from the free TCB list    */
+    if (ptcb != (OS_TCB *)0) {
+        OSTCBFreeList            = ptcb->OSTCBNext;        /* Update pointer to free TCB list          */
+        OS_EXIT_CRITICAL();
+        ptcb->OSTCBStkPtr        = ptos;                   /* Load Stack pointer in TCB                */
+        ptcb->OSTCBPrio          = prio;                   /* Load task priority into TCB              */
+        ptcb->OSTCBStat          = OS_STAT_RDY;            /* Task is ready to run                     */
+        ptcb->OSTCBStatPend      = OS_STAT_PEND_OK;        /* Clear pend status                        */
+        ptcb->OSTCBDly           = 0u;                     /* Task is not delayed                      */
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+        ptcb->OSTCBExtPtr        = pext;                   /* Store pointer to TCB extension           */
+        ptcb->OSTCBStkSize       = stk_size;               /* Store stack size                         */
+        ptcb->OSTCBStkBottom     = pbos;                   /* Store pointer to bottom of stack         */
+        ptcb->OSTCBOpt           = opt;                    /* Store task options                       */
+        ptcb->OSTCBId            = id;                     /* Store task ID                            */
+#else
+        pext                     = pext;                   /* Prevent compiler warning if not used     */
+        stk_size                 = stk_size;
+        pbos                     = pbos;
+        opt                      = opt;
+        id                       = id;
+#endif
+
+#if OS_TASK_DEL_EN > 0u
+        ptcb->OSTCBDelReq        = OS_ERR_NONE;
+#endif
+
+#if OS_LOWEST_PRIO <= 63u                                         /* Pre-compute X, Y                  */
+        ptcb->OSTCBY             = (INT8U)(prio >> 3u);
+        ptcb->OSTCBX             = (INT8U)(prio & 0x07u);
+#else                                                             /* Pre-compute X, Y                  */
+        ptcb->OSTCBY             = (INT8U)((INT8U)(prio >> 4u) & 0xFFu);
+        ptcb->OSTCBX             = (INT8U) (prio & 0x0Fu);
+#endif
+                                                                  /* Pre-compute BitX and BitY         */
+        ptcb->OSTCBBitY          = (OS_PRIO)(1uL << ptcb->OSTCBY);
+        ptcb->OSTCBBitX          = (OS_PRIO)(1uL << ptcb->OSTCBX);
+
+#if (OS_EVENT_EN)
+        ptcb->OSTCBEventPtr      = (OS_EVENT  *)0;         /* Task is not pending on an  event         */
+#if (OS_EVENT_MULTI_EN > 0u)
+        ptcb->OSTCBEventMultiPtr = (OS_EVENT **)0;         /* Task is not pending on any events        */
+#endif
+#endif
+
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) && (OS_TASK_DEL_EN > 0u)
+        ptcb->OSTCBFlagNode      = (OS_FLAG_NODE *)0;      /* Task is not pending on an event flag     */
+#endif
+
+#if (OS_MBOX_EN > 0u) || ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u))
+        ptcb->OSTCBMsg           = (void *)0;              /* No message received                      */
+#endif
+
+#if OS_TASK_PROFILE_EN > 0u
+        ptcb->OSTCBCtxSwCtr      = 0uL;                    /* Initialize profiling variables           */
+        ptcb->OSTCBCyclesStart   = 0uL;
+        ptcb->OSTCBCyclesTot     = 0uL;
+        ptcb->OSTCBStkBase       = (OS_STK *)0;
+        ptcb->OSTCBStkUsed       = 0uL;
+#endif
+
+#if OS_TASK_NAME_EN > 0u
+        ptcb->OSTCBTaskName      = (INT8U *)(void *)"?";
+#endif
+
+#if OS_TASK_REG_TBL_SIZE > 0u                              /* Initialize the task variables            */
+        for (i = 0u; i < OS_TASK_REG_TBL_SIZE; i++) {
+            ptcb->OSTCBRegTbl[i] = 0u;
+        }
+#endif
+
+        OSTCBInitHook(ptcb);
+
+        OS_ENTER_CRITICAL();
+        OSTCBPrioTbl[prio] = ptcb;
+        OS_EXIT_CRITICAL();
+
+        OSTaskCreateHook(ptcb);                            /* Call user defined hook                   */
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
+        for (j = 0u; j < OS_TLS_TBL_SIZE; j++) {
+            ptcb->OSTCBTLSTbl[j] = (OS_TLS)0;
+        }
+        OS_TLS_TaskCreate(ptcb);                           /* Call TLS hook                            */
+#endif
+#endif
+
+        OS_ENTER_CRITICAL();
+        ptcb->OSTCBNext = OSTCBList;                       /* Link into TCB chain                      */
+        ptcb->OSTCBPrev = (OS_TCB *)0;         
+        if (OSTCBList != (OS_TCB *)0) {
+            OSTCBList->OSTCBPrev = ptcb;
+        }
+        OSTCBList               = ptcb;
+        OSRdyGrp               |= ptcb->OSTCBBitY;         /* Make task ready to run                   */
+        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
+        OSTaskCtr++;                                       /* Increment the #tasks counter             */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_NONE);
+    }
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_TASK_NO_MORE_TCB);
+}

+ 1231 - 0
MiddleWare/uCOS_II/uCOS-II/Source/os_flag.c

@@ -0,0 +1,1231 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                         EVENT FLAG  MANAGEMENT
+*
+*                              (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_FLAG.C
+* By      : Jean J. Labrosse
+* Version : V2.92.11
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#define  MICRIUM_SOURCE
+
+#ifndef  OS_MASTER_FILE
+#include <ucos_ii.h>
+#endif
+
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+/*
+*********************************************************************************************************
+*                                          LOCAL PROTOTYPES
+*********************************************************************************************************
+*/
+
+static  void     OS_FlagBlock(OS_FLAG_GRP *pgrp, OS_FLAG_NODE *pnode, OS_FLAGS flags, INT8U wait_type, INT32U timeout);
+static  BOOLEAN  OS_FlagTaskRdy(OS_FLAG_NODE *pnode, OS_FLAGS flags_rdy, INT8U pend_stat);
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                          CHECK THE STATUS OF FLAGS IN AN EVENT FLAG GROUP
+*
+* Description: This function is called to check the status of a combination of bits to be set or cleared
+*              in an event flag group.  Your application can check for ANY bit to be set/cleared or ALL
+*              bits to be set/cleared.
+*
+*              This call does not block if the desired flags are not present.
+*
+* Arguments  : pgrp          is a pointer to the desired event flag group.
+*
+*              flags         Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check.
+*                            The bits you want are specified by setting the corresponding bits in
+*                            'flags'.  e.g. if your application wants to wait for bits 0 and 1 then
+*                            'flags' would contain 0x03.
+*
+*              wait_type     specifies whether you want ALL bits to be set/cleared or ANY of the bits
+*                            to be set/cleared.
+*                            You can specify the following argument:
+*
+*                            OS_FLAG_WAIT_CLR_ALL   You will check ALL bits in 'flags' to be clear (0)
+*                            OS_FLAG_WAIT_CLR_ANY   You will check ANY bit  in 'flags' to be clear (0)
+*                            OS_FLAG_WAIT_SET_ALL   You will check ALL bits in 'flags' to be set   (1)
+*                            OS_FLAG_WAIT_SET_ANY   You will check ANY bit  in 'flags' to be set   (1)
+*
+*                            NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by
+*                                  the call.  Example, to wait for any flag in a group AND then clear
+*                                  the flags that are present, set 'wait_type' to:
+*
+*                                  OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME
+*
+*              perr          is a pointer to an error code and can be:
+*                            OS_ERR_NONE               No error
+*                            OS_ERR_EVENT_TYPE         You are not pointing to an event flag group
+*                            OS_ERR_FLAG_WAIT_TYPE     You didn't specify a proper 'wait_type' argument.
+*                            OS_ERR_FLAG_INVALID_PGRP  You passed a NULL pointer instead of the event flag
+*                                                      group handle.
+*                            OS_ERR_FLAG_NOT_RDY       The desired flags you are waiting for are not
+*                                                      available.
+*
+* Returns    : The flags in the event flag group that made the task ready or, 0 if a timeout or an error
+*              occurred.
+*
+* Called from: Task or ISR
+*
+* Note(s)    : 1) IMPORTANT, the behavior of this function has changed from PREVIOUS versions.  The
+*                 function NOW returns the flags that were ready INSTEAD of the current state of the
+*                 event flags.
+*********************************************************************************************************
+*/
+
+#if OS_FLAG_ACCEPT_EN > 0u
+OS_FLAGS  OSFlagAccept (OS_FLAG_GRP  *pgrp,
+                        OS_FLAGS      flags,
+                        INT8U         wait_type,
+                        INT8U        *perr)
+{
+    OS_FLAGS      flags_rdy;
+    INT8U         result;
+    BOOLEAN       consume;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR     cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_FLAGS)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pgrp == (OS_FLAG_GRP *)0) {                        /* Validate 'pgrp'                          */
+        *perr = OS_ERR_FLAG_INVALID_PGRP;
+        return ((OS_FLAGS)0);
+    }
+#endif
+    if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) {          /* Validate event block type                */
+        *perr = OS_ERR_EVENT_TYPE;
+        return ((OS_FLAGS)0);
+    }
+    result = (INT8U)(wait_type & OS_FLAG_CONSUME);
+    if (result != (INT8U)0) {                              /* See if we need to consume the flags      */
+        wait_type &= ~OS_FLAG_CONSUME;
+        consume    = OS_TRUE;
+    } else {
+        consume    = OS_FALSE;
+    }
+/*$PAGE*/
+    *perr = OS_ERR_NONE;                                   /* Assume NO error until proven otherwise.  */
+    OS_ENTER_CRITICAL();
+    switch (wait_type) {
+        case OS_FLAG_WAIT_SET_ALL:                         /* See if all required flags are set        */
+             flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags);     /* Extract only the bits we want   */
+             if (flags_rdy == flags) {                     /* Must match ALL the bits that we want     */
+                 if (consume == OS_TRUE) {                 /* See if we need to consume the flags      */
+                     pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;     /* Clear ONLY the flags we wanted  */
+                 }
+             } else {
+                 *perr = OS_ERR_FLAG_NOT_RDY;
+             }
+             OS_EXIT_CRITICAL();
+             break;
+
+        case OS_FLAG_WAIT_SET_ANY:
+             flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags);     /* Extract only the bits we want   */
+             if (flags_rdy != (OS_FLAGS)0) {               /* See if any flag set                      */
+                 if (consume == OS_TRUE) {                 /* See if we need to consume the flags      */
+                     pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;     /* Clear ONLY the flags we got     */
+                 }
+             } else {
+                 *perr = OS_ERR_FLAG_NOT_RDY;
+             }
+             OS_EXIT_CRITICAL();
+             break;
+
+#if OS_FLAG_WAIT_CLR_EN > 0u
+        case OS_FLAG_WAIT_CLR_ALL:                         /* See if all required flags are cleared    */
+             flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags;    /* Extract only the bits we want     */
+             if (flags_rdy == flags) {                     /* Must match ALL the bits that we want     */
+                 if (consume == OS_TRUE) {                 /* See if we need to consume the flags      */
+                     pgrp->OSFlagFlags |= flags_rdy;       /* Set ONLY the flags that we wanted        */
+                 }
+             } else {
+                 *perr = OS_ERR_FLAG_NOT_RDY;
+             }
+             OS_EXIT_CRITICAL();
+             break;
+
+        case OS_FLAG_WAIT_CLR_ANY:
+             flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags;   /* Extract only the bits we want      */
+             if (flags_rdy != (OS_FLAGS)0) {               /* See if any flag cleared                  */
+                 if (consume == OS_TRUE) {                 /* See if we need to consume the flags      */
+                     pgrp->OSFlagFlags |= flags_rdy;       /* Set ONLY the flags that we got           */
+                 }
+             } else {
+                 *perr = OS_ERR_FLAG_NOT_RDY;
+             }
+             OS_EXIT_CRITICAL();
+             break;
+#endif
+
+        default:
+             OS_EXIT_CRITICAL();
+             flags_rdy = (OS_FLAGS)0;
+             *perr     = OS_ERR_FLAG_WAIT_TYPE;
+             break;
+    }
+    return (flags_rdy);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                        CREATE AN EVENT FLAG
+*
+* Description: This function is called to create an event flag group.
+*
+* Arguments  : flags         Contains the initial value to store in the event flag group.
+*
+*              perr          is a pointer to an error code which will be returned to your application:
+*                               OS_ERR_NONE               if the call was successful.
+*                               OS_ERR_CREATE_ISR         if you attempted to create an Event Flag from an
+*                                                         ISR.
+*                               OS_ERR_FLAG_GRP_DEPLETED  if there are no more event flag groups
+*
+* Returns    : A pointer to an event flag group or a NULL pointer if no more groups are available.
+*
+* Called from: Task ONLY
+*********************************************************************************************************
+*/
+
+OS_FLAG_GRP  *OSFlagCreate (OS_FLAGS  flags,
+                            INT8U    *perr)
+{
+    OS_FLAG_GRP *pgrp;
+#if OS_CRITICAL_METHOD == 3u                        /* Allocate storage for CPU status register        */
+    OS_CPU_SR    cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_FLAG_GRP *)0);
+    }
+#endif
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    if (OSSafetyCriticalStartFlag == OS_TRUE) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_FLAG_GRP *)0);
+    }
+#endif
+
+    if (OSIntNesting > 0u) {                        /* See if called from ISR ...                      */
+        *perr = OS_ERR_CREATE_ISR;                  /* ... can't CREATE from an ISR                    */
+        return ((OS_FLAG_GRP *)0);
+    }
+    OS_ENTER_CRITICAL();
+    pgrp = OSFlagFreeList;                          /* Get next free event flag                        */
+    if (pgrp != (OS_FLAG_GRP *)0) {                 /* See if we have event flag groups available      */
+                                                    /* Adjust free list                                */
+        OSFlagFreeList       = (OS_FLAG_GRP *)OSFlagFreeList->OSFlagWaitList;
+        pgrp->OSFlagType     = OS_EVENT_TYPE_FLAG;  /* Set to event flag group type                    */
+        pgrp->OSFlagFlags    = flags;               /* Set to desired initial value                    */
+        pgrp->OSFlagWaitList = (void *)0;           /* Clear list of tasks waiting on flags            */
+#if OS_FLAG_NAME_EN > 0u
+        pgrp->OSFlagName     = (INT8U *)(void *)"?";
+#endif
+        OS_EXIT_CRITICAL();
+        *perr                = OS_ERR_NONE;
+    } else {
+        OS_EXIT_CRITICAL();
+        *perr                = OS_ERR_FLAG_GRP_DEPLETED;
+    }
+    return (pgrp);                                  /* Return pointer to event flag group              */
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                     DELETE AN EVENT FLAG GROUP
+*
+* Description: This function deletes an event flag group and readies all tasks pending on the event flag
+*              group.
+*
+* Arguments  : pgrp          is a pointer to the desired event flag group.
+*
+*              opt           determines delete options as follows:
+*                            opt == OS_DEL_NO_PEND   Deletes the event flag group ONLY if no task pending
+*                            opt == OS_DEL_ALWAYS    Deletes the event flag group even if tasks are
+*                                                    waiting.  In this case, all the tasks pending will be
+*                                                    readied.
+*
+*              perr          is a pointer to an error code that can contain one of the following values:
+*                            OS_ERR_NONE               The call was successful and the event flag group was
+*                                                      deleted
+*                            OS_ERR_DEL_ISR            If you attempted to delete the event flag group from
+*                                                      an ISR
+*                            OS_ERR_FLAG_INVALID_PGRP  If 'pgrp' is a NULL pointer.
+*                            OS_ERR_EVENT_TYPE         If you didn't pass a pointer to an event flag group
+*                            OS_ERR_INVALID_OPT        An invalid option was specified
+*                            OS_ERR_TASK_WAITING       One or more tasks were waiting on the event flag
+*                                                      group.
+*
+* Returns    : pgrp          upon error
+*              (OS_EVENT *)0 if the event flag group was successfully deleted.
+*
+* Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
+*                 the event flag group MUST check the return code of OSFlagAccept() and OSFlagPend().
+*              2) This call can potentially disable interrupts for a long time.  The interrupt disable
+*                 time is directly proportional to the number of tasks waiting on the event flag group.
+*              3) All tasks that were waiting for the event flag will be readied and returned an 
+*                 OS_ERR_PEND_ABORT if OSFlagDel() was called with OS_DEL_ALWAYS
+*********************************************************************************************************
+*/
+
+#if OS_FLAG_DEL_EN > 0u
+OS_FLAG_GRP  *OSFlagDel (OS_FLAG_GRP  *pgrp,
+                         INT8U         opt,
+                         INT8U        *perr)
+{
+    BOOLEAN       tasks_waiting;
+    OS_FLAG_NODE *pnode;
+    OS_FLAG_GRP  *pgrp_return;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR     cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_FLAG_GRP *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pgrp == (OS_FLAG_GRP *)0) {                        /* Validate 'pgrp'                          */
+        *perr = OS_ERR_FLAG_INVALID_PGRP;
+        return (pgrp);
+    }
+#endif
+    if (OSIntNesting > 0u) {                               /* See if called from ISR ...               */
+        *perr = OS_ERR_DEL_ISR;                            /* ... can't DELETE from an ISR             */
+        return (pgrp);
+    }
+    if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) {          /* Validate event group type                */
+        *perr = OS_ERR_EVENT_TYPE;
+        return (pgrp);
+    }
+    OS_ENTER_CRITICAL();
+    if (pgrp->OSFlagWaitList != (void *)0) {               /* See if any tasks waiting on event flags  */
+        tasks_waiting = OS_TRUE;                           /* Yes                                      */
+    } else {
+        tasks_waiting = OS_FALSE;                          /* No                                       */
+    }
+    switch (opt) {
+        case OS_DEL_NO_PEND:                               /* Delete group if no task waiting          */
+             if (tasks_waiting == OS_FALSE) {
+#if OS_FLAG_NAME_EN > 0u
+                 pgrp->OSFlagName     = (INT8U *)(void *)"?";
+#endif
+                 pgrp->OSFlagType     = OS_EVENT_TYPE_UNUSED;
+                 pgrp->OSFlagWaitList = (void *)OSFlagFreeList; /* Return group to free list           */
+                 pgrp->OSFlagFlags    = (OS_FLAGS)0;
+                 OSFlagFreeList       = pgrp;
+                 OS_EXIT_CRITICAL();
+                 *perr                = OS_ERR_NONE;
+                 pgrp_return          = (OS_FLAG_GRP *)0;  /* Event Flag Group has been deleted        */
+             } else {
+                 OS_EXIT_CRITICAL();
+                 *perr                = OS_ERR_TASK_WAITING;
+                 pgrp_return          = pgrp;
+             }
+             break;
+
+        case OS_DEL_ALWAYS:                                /* Always delete the event flag group       */
+             pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;
+             while (pnode != (OS_FLAG_NODE *)0) {          /* Ready ALL tasks waiting for flags        */
+                 (void)OS_FlagTaskRdy(pnode, (OS_FLAGS)0, OS_STAT_PEND_ABORT);
+                 pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;
+             }
+#if OS_FLAG_NAME_EN > 0u
+             pgrp->OSFlagName     = (INT8U *)(void *)"?";
+#endif
+             pgrp->OSFlagType     = OS_EVENT_TYPE_UNUSED;
+             pgrp->OSFlagWaitList = (void *)OSFlagFreeList;/* Return group to free list                */
+             pgrp->OSFlagFlags    = (OS_FLAGS)0;
+             OSFlagFreeList       = pgrp;
+             OS_EXIT_CRITICAL();
+             if (tasks_waiting == OS_TRUE) {               /* Reschedule only if task(s) were waiting  */
+                 OS_Sched();                               /* Find highest priority task ready to run  */
+             }
+             *perr = OS_ERR_NONE;
+             pgrp_return          = (OS_FLAG_GRP *)0;      /* Event Flag Group has been deleted        */
+             break;
+
+        default:
+             OS_EXIT_CRITICAL();
+             *perr                = OS_ERR_INVALID_OPT;
+             pgrp_return          = pgrp;
+             break;
+    }
+    return (pgrp_return);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                 GET THE NAME OF AN EVENT FLAG GROUP
+*
+* Description: This function is used to obtain the name assigned to an event flag group
+*
+* Arguments  : pgrp      is a pointer to the event flag group.
+*
+*              pname     is pointer to a pointer to an ASCII string that will receive the name of the event flag
+*                        group.
+*
+*              perr      is a pointer to an error code that can contain one of the following values:
+*
+*                        OS_ERR_NONE                if the requested task is resumed
+*                        OS_ERR_EVENT_TYPE          if 'pevent' is not pointing to an event flag group
+*                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
+*                        OS_ERR_FLAG_INVALID_PGRP   if you passed a NULL pointer for 'pgrp'
+*                        OS_ERR_NAME_GET_ISR        if you called this function from an ISR
+*
+* Returns    : The length of the string or 0 if the 'pgrp' is a NULL pointer.
+*********************************************************************************************************
+*/
+
+#if OS_FLAG_NAME_EN > 0u
+INT8U  OSFlagNameGet (OS_FLAG_GRP   *pgrp,
+                      INT8U        **pname,
+                      INT8U         *perr)
+{
+    INT8U      len;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pgrp == (OS_FLAG_GRP *)0) {              /* Is 'pgrp' a NULL pointer?                          */
+        *perr = OS_ERR_FLAG_INVALID_PGRP;
+        return (0u);
+    }
+    if (pname == (INT8U **)0) {                   /* Is 'pname' a NULL pointer?                         */
+        *perr = OS_ERR_PNAME_NULL;
+        return (0u);
+    }
+#endif
+    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
+        *perr = OS_ERR_NAME_GET_ISR;
+        return (0u);
+    }
+    OS_ENTER_CRITICAL();
+    if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) {
+        OS_EXIT_CRITICAL();
+        *perr = OS_ERR_EVENT_TYPE;
+        return (0u);
+    }
+    *pname = pgrp->OSFlagName;
+    len    = OS_StrLen(*pname);
+    OS_EXIT_CRITICAL();
+    *perr  = OS_ERR_NONE;
+    return (len);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                ASSIGN A NAME TO AN EVENT FLAG GROUP
+*
+* Description: This function assigns a name to an event flag group.
+*
+* Arguments  : pgrp      is a pointer to the event flag group.
+*
+*              pname     is a pointer to an ASCII string that will be used as the name of the event flag
+*                        group.
+*
+*              perr      is a pointer to an error code that can contain one of the following values:
+*
+*                        OS_ERR_NONE                if the requested task is resumed
+*                        OS_ERR_EVENT_TYPE          if 'pevent' is not pointing to an event flag group
+*                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
+*                        OS_ERR_FLAG_INVALID_PGRP   if you passed a NULL pointer for 'pgrp'
+*                        OS_ERR_NAME_SET_ISR        if you called this function from an ISR
+*
+* Returns    : None
+*********************************************************************************************************
+*/
+
+#if OS_FLAG_NAME_EN > 0u
+void  OSFlagNameSet (OS_FLAG_GRP  *pgrp,
+                     INT8U        *pname,
+                     INT8U        *perr)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return;
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pgrp == (OS_FLAG_GRP *)0) {              /* Is 'pgrp' a NULL pointer?                          */
+        *perr = OS_ERR_FLAG_INVALID_PGRP;
+        return;
+    }
+    if (pname == (INT8U *)0) {                   /* Is 'pname' a NULL pointer?                         */
+        *perr = OS_ERR_PNAME_NULL;
+        return;
+    }
+#endif
+    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
+        *perr = OS_ERR_NAME_SET_ISR;
+        return;
+    }
+    OS_ENTER_CRITICAL();
+    if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) {
+        OS_EXIT_CRITICAL();
+        *perr = OS_ERR_EVENT_TYPE;
+        return;
+    }
+    pgrp->OSFlagName = pname;
+    OS_EXIT_CRITICAL();
+    *perr            = OS_ERR_NONE;
+    return;
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                     WAIT ON AN EVENT FLAG GROUP
+*
+* Description: This function is called to wait for a combination of bits to be set in an event flag
+*              group.  Your application can wait for ANY bit to be set or ALL bits to be set.
+*
+* Arguments  : pgrp          is a pointer to the desired event flag group.
+*
+*              flags         Is a bit pattern indicating which bit(s) (i.e. flags) you wish to wait for.
+*                            The bits you want are specified by setting the corresponding bits in
+*                            'flags'.  e.g. if your application wants to wait for bits 0 and 1 then
+*                            'flags' would contain 0x03.
+*
+*              wait_type     specifies whether you want ALL bits to be set or ANY of the bits to be set.
+*                            You can specify the following argument:
+*
+*                            OS_FLAG_WAIT_CLR_ALL   You will wait for ALL bits in 'mask' to be clear (0)
+*                            OS_FLAG_WAIT_SET_ALL   You will wait for ALL bits in 'mask' to be set   (1)
+*                            OS_FLAG_WAIT_CLR_ANY   You will wait for ANY bit  in 'mask' to be clear (0)
+*                            OS_FLAG_WAIT_SET_ANY   You will wait for ANY bit  in 'mask' to be set   (1)
+*
+*                            NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by
+*                                  the call.  Example, to wait for any flag in a group AND then clear
+*                                  the flags that are present, set 'wait_type' to:
+*
+*                                  OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME
+*
+*              timeout       is an optional timeout (in clock ticks) that your task will wait for the
+*                            desired bit combination.  If you specify 0, however, your task will wait
+*                            forever at the specified event flag group or, until a message arrives.
+*
+*              perr          is a pointer to an error code and can be:
+*                            OS_ERR_NONE               The desired bits have been set within the specified
+*                                                      'timeout'.
+*                            OS_ERR_PEND_ISR           If you tried to PEND from an ISR
+*                            OS_ERR_FLAG_INVALID_PGRP  If 'pgrp' is a NULL pointer.
+*                            OS_ERR_EVENT_TYPE         You are not pointing to an event flag group
+*                            OS_ERR_TIMEOUT            The bit(s) have not been set in the specified
+*                                                      'timeout'.
+*                            OS_ERR_PEND_ABORT         The wait on the flag was aborted.
+*                            OS_ERR_FLAG_WAIT_TYPE     You didn't specify a proper 'wait_type' argument.
+*
+* Returns    : The flags in the event flag group that made the task ready or, 0 if a timeout or an error
+*              occurred.
+*
+* Called from: Task ONLY
+*
+* Note(s)    : 1) IMPORTANT, the behavior of this function has changed from PREVIOUS versions.  The
+*                 function NOW returns the flags that were ready INSTEAD of the current state of the
+*                 event flags.
+*********************************************************************************************************
+*/
+
+OS_FLAGS  OSFlagPend (OS_FLAG_GRP  *pgrp,
+                      OS_FLAGS      flags,
+                      INT8U         wait_type,
+                      INT32U        timeout,
+                      INT8U        *perr)
+{
+    OS_FLAG_NODE  node;
+    OS_FLAGS      flags_rdy;
+    INT8U         result;
+    INT8U         pend_stat;
+    BOOLEAN       consume;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR     cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_FLAGS)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pgrp == (OS_FLAG_GRP *)0) {                        /* Validate 'pgrp'                          */
+        *perr = OS_ERR_FLAG_INVALID_PGRP;
+        return ((OS_FLAGS)0);
+    }
+#endif
+    if (OSIntNesting > 0u) {                               /* See if called from ISR ...               */
+        *perr = OS_ERR_PEND_ISR;                           /* ... can't PEND from an ISR               */
+        return ((OS_FLAGS)0);
+    }
+    if (OSLockNesting > 0u) {                              /* See if called with scheduler locked ...  */
+        *perr = OS_ERR_PEND_LOCKED;                        /* ... can't PEND when locked               */
+        return ((OS_FLAGS)0);
+    }
+    if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) {          /* Validate event block type                */
+        *perr = OS_ERR_EVENT_TYPE;
+        return ((OS_FLAGS)0);
+    }
+    result = (INT8U)(wait_type & OS_FLAG_CONSUME);
+    if (result != (INT8U)0) {                              /* See if we need to consume the flags      */
+        wait_type &= (INT8U)~(INT8U)OS_FLAG_CONSUME;
+        consume    = OS_TRUE;
+    } else {
+        consume    = OS_FALSE;
+    }
+/*$PAGE*/
+    OS_ENTER_CRITICAL();
+    switch (wait_type) {
+        case OS_FLAG_WAIT_SET_ALL:                         /* See if all required flags are set        */
+             flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags);   /* Extract only the bits we want     */
+             if (flags_rdy == flags) {                     /* Must match ALL the bits that we want     */
+                 if (consume == OS_TRUE) {                 /* See if we need to consume the flags      */
+                     pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;   /* Clear ONLY the flags we wanted    */
+                 }
+                 OSTCBCur->OSTCBFlagsRdy = flags_rdy;      /* Save flags that were ready               */
+                 OS_EXIT_CRITICAL();                       /* Yes, condition met, return to caller     */
+                 *perr                   = OS_ERR_NONE;
+                 return (flags_rdy);
+             } else {                                      /* Block task until events occur or timeout */
+                 OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
+                 OS_EXIT_CRITICAL();
+             }
+             break;
+
+        case OS_FLAG_WAIT_SET_ANY:
+             flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags);    /* Extract only the bits we want    */
+             if (flags_rdy != (OS_FLAGS)0) {               /* See if any flag set                      */
+                 if (consume == OS_TRUE) {                 /* See if we need to consume the flags      */
+                     pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;    /* Clear ONLY the flags that we got */
+                 }
+                 OSTCBCur->OSTCBFlagsRdy = flags_rdy;      /* Save flags that were ready               */
+                 OS_EXIT_CRITICAL();                       /* Yes, condition met, return to caller     */
+                 *perr                   = OS_ERR_NONE;
+                 return (flags_rdy);
+             } else {                                      /* Block task until events occur or timeout */
+                 OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
+                 OS_EXIT_CRITICAL();
+             }
+             break;
+
+#if OS_FLAG_WAIT_CLR_EN > 0u
+        case OS_FLAG_WAIT_CLR_ALL:                         /* See if all required flags are cleared    */
+             flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags;    /* Extract only the bits we want     */
+             if (flags_rdy == flags) {                     /* Must match ALL the bits that we want     */
+                 if (consume == OS_TRUE) {                 /* See if we need to consume the flags      */
+                     pgrp->OSFlagFlags |= flags_rdy;       /* Set ONLY the flags that we wanted        */
+                 }
+                 OSTCBCur->OSTCBFlagsRdy = flags_rdy;      /* Save flags that were ready               */
+                 OS_EXIT_CRITICAL();                       /* Yes, condition met, return to caller     */
+                 *perr                   = OS_ERR_NONE;
+                 return (flags_rdy);
+             } else {                                      /* Block task until events occur or timeout */
+                 OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
+                 OS_EXIT_CRITICAL();
+             }
+             break;
+
+        case OS_FLAG_WAIT_CLR_ANY:
+             flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags;   /* Extract only the bits we want      */
+             if (flags_rdy != (OS_FLAGS)0) {               /* See if any flag cleared                  */
+                 if (consume == OS_TRUE) {                 /* See if we need to consume the flags      */
+                     pgrp->OSFlagFlags |= flags_rdy;       /* Set ONLY the flags that we got           */
+                 }
+                 OSTCBCur->OSTCBFlagsRdy = flags_rdy;      /* Save flags that were ready               */
+                 OS_EXIT_CRITICAL();                       /* Yes, condition met, return to caller     */
+                 *perr                   = OS_ERR_NONE;
+                 return (flags_rdy);
+             } else {                                      /* Block task until events occur or timeout */
+                 OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
+                 OS_EXIT_CRITICAL();
+             }
+             break;
+#endif
+
+        default:
+             OS_EXIT_CRITICAL();
+             flags_rdy = (OS_FLAGS)0;
+             *perr      = OS_ERR_FLAG_WAIT_TYPE;
+             return (flags_rdy);
+    }
+/*$PAGE*/
+    OS_Sched();                                            /* Find next HPT ready to run               */
+    OS_ENTER_CRITICAL();
+    if (OSTCBCur->OSTCBStatPend != OS_STAT_PEND_OK) {      /* Have we timed-out or aborted?            */
+        pend_stat                = OSTCBCur->OSTCBStatPend;
+        OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
+        OS_FlagUnlink(&node);
+        OSTCBCur->OSTCBStat      = OS_STAT_RDY;            /* Yes, make task ready-to-run              */
+        OS_EXIT_CRITICAL();
+        flags_rdy                = (OS_FLAGS)0;
+        switch (pend_stat) {
+            case OS_STAT_PEND_ABORT:
+                 *perr = OS_ERR_PEND_ABORT;                /* Indicate that we aborted   waiting       */
+                 break;
+
+            case OS_STAT_PEND_TO:
+            default:
+                 *perr = OS_ERR_TIMEOUT;                   /* Indicate that we timed-out waiting       */
+                 break;
+        }
+        return (flags_rdy);
+    }
+    flags_rdy = OSTCBCur->OSTCBFlagsRdy;
+    if (consume == OS_TRUE) {                              /* See if we need to consume the flags      */
+        switch (wait_type) {
+            case OS_FLAG_WAIT_SET_ALL:
+            case OS_FLAG_WAIT_SET_ANY:                     /* Clear ONLY the flags we got              */
+                 pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;
+                 break;
+
+#if OS_FLAG_WAIT_CLR_EN > 0u
+            case OS_FLAG_WAIT_CLR_ALL:
+            case OS_FLAG_WAIT_CLR_ANY:                     /* Set   ONLY the flags we got              */
+                 pgrp->OSFlagFlags |=  flags_rdy;
+                 break;
+#endif
+            default:
+                 OS_EXIT_CRITICAL();
+                 *perr = OS_ERR_FLAG_WAIT_TYPE;
+                 return ((OS_FLAGS)0);
+        }
+    }
+    OS_EXIT_CRITICAL();
+    *perr = OS_ERR_NONE;                                   /* Event(s) must have occurred              */
+    return (flags_rdy);
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                              GET FLAGS WHO CAUSED TASK TO BECOME READY
+*
+* Description: This function is called to obtain the flags that caused the task to become ready to run.
+*              In other words, this function allows you to tell "Who done it!".
+*
+* Arguments  : None
+*
+* Returns    : The flags that caused the task to be ready.
+*
+* Called from: Task ONLY
+*********************************************************************************************************
+*/
+
+OS_FLAGS  OSFlagPendGetFlagsRdy (void)
+{
+    OS_FLAGS      flags;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR     cpu_sr = 0u;
+#endif
+
+
+
+    OS_ENTER_CRITICAL();
+    flags = OSTCBCur->OSTCBFlagsRdy;
+    OS_EXIT_CRITICAL();
+    return (flags);
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       POST EVENT FLAG BIT(S)
+*
+* Description: This function is called to set or clear some bits in an event flag group.  The bits to
+*              set or clear are specified by a 'bit mask'.
+*
+* Arguments  : pgrp          is a pointer to the desired event flag group.
+*
+*              flags         If 'opt' (see below) is OS_FLAG_SET, each bit that is set in 'flags' will
+*                            set the corresponding bit in the event flag group.  e.g. to set bits 0, 4
+*                            and 5 you would set 'flags' to:
+*
+*                                0x31     (note, bit 0 is least significant bit)
+*
+*                            If 'opt' (see below) is OS_FLAG_CLR, each bit that is set in 'flags' will
+*                            CLEAR the corresponding bit in the event flag group.  e.g. to clear bits 0,
+*                            4 and 5 you would specify 'flags' as:
+*
+*                                0x31     (note, bit 0 is least significant bit)
+*
+*              opt           indicates whether the flags will be:
+*                                set     (OS_FLAG_SET) or
+*                                cleared (OS_FLAG_CLR)
+*
+*              perr          is a pointer to an error code and can be:
+*                            OS_ERR_NONE                The call was successfull
+*                            OS_ERR_FLAG_INVALID_PGRP   You passed a NULL pointer
+*                            OS_ERR_EVENT_TYPE          You are not pointing to an event flag group
+*                            OS_ERR_FLAG_INVALID_OPT    You specified an invalid option
+*
+* Returns    : the new value of the event flags bits that are still set.
+*
+* Called From: Task or ISR
+*
+* WARNING(s) : 1) The execution time of this function depends on the number of tasks waiting on the event
+*                 flag group.
+*              2) The amount of time interrupts are DISABLED depends on the number of tasks waiting on
+*                 the event flag group.
+*********************************************************************************************************
+*/
+OS_FLAGS  OSFlagPost (OS_FLAG_GRP  *pgrp,
+                      OS_FLAGS      flags,
+                      INT8U         opt,
+                      INT8U        *perr)
+{
+    OS_FLAG_NODE *pnode;
+    BOOLEAN       sched;
+    OS_FLAGS      flags_cur;
+    OS_FLAGS      flags_rdy;
+    BOOLEAN       rdy;
+#if OS_CRITICAL_METHOD == 3u                         /* Allocate storage for CPU status register       */
+    OS_CPU_SR     cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_FLAGS)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pgrp == (OS_FLAG_GRP *)0) {                  /* Validate 'pgrp'                                */
+        *perr = OS_ERR_FLAG_INVALID_PGRP;
+        return ((OS_FLAGS)0);
+    }
+#endif
+    if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) {    /* Make sure we are pointing to an event flag grp */
+        *perr = OS_ERR_EVENT_TYPE;
+        return ((OS_FLAGS)0);
+    }
+/*$PAGE*/
+    OS_ENTER_CRITICAL();
+    switch (opt) {
+        case OS_FLAG_CLR:
+             pgrp->OSFlagFlags &= (OS_FLAGS)~flags;  /* Clear the flags specified in the group         */
+             break;
+
+        case OS_FLAG_SET:
+             pgrp->OSFlagFlags |=  flags;            /* Set   the flags specified in the group         */
+             break;
+
+        default:
+             OS_EXIT_CRITICAL();                     /* INVALID option                                 */
+             *perr = OS_ERR_FLAG_INVALID_OPT;
+             return ((OS_FLAGS)0);
+    }
+    sched = OS_FALSE;                                /* Indicate that we don't need rescheduling       */
+    pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;
+    while (pnode != (OS_FLAG_NODE *)0) {             /* Go through all tasks waiting on event flag(s)  */
+        switch (pnode->OSFlagNodeWaitType) {
+            case OS_FLAG_WAIT_SET_ALL:               /* See if all req. flags are set for current node */
+                 flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags);
+                 if (flags_rdy == pnode->OSFlagNodeFlags) {   /* Make task RTR, event(s) Rx'd          */
+                     rdy = OS_FlagTaskRdy(pnode, flags_rdy, OS_STAT_PEND_OK);  
+                     if (rdy == OS_TRUE) {
+                         sched = OS_TRUE;                     /* When done we will reschedule          */
+                     }
+                 }
+                 break;
+
+            case OS_FLAG_WAIT_SET_ANY:               /* See if any flag set                            */
+                 flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags);
+                 if (flags_rdy != (OS_FLAGS)0) {              /* Make task RTR, event(s) Rx'd          */
+                     rdy = OS_FlagTaskRdy(pnode, flags_rdy, OS_STAT_PEND_OK);  
+                     if (rdy == OS_TRUE) {
+                         sched = OS_TRUE;                     /* When done we will reschedule          */
+                     }
+                 }
+                 break;
+
+#if OS_FLAG_WAIT_CLR_EN > 0u
+            case OS_FLAG_WAIT_CLR_ALL:               /* See if all req. flags are set for current node */
+                 flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags;
+                 if (flags_rdy == pnode->OSFlagNodeFlags) {   /* Make task RTR, event(s) Rx'd          */
+                     rdy = OS_FlagTaskRdy(pnode, flags_rdy, OS_STAT_PEND_OK);  
+                     if (rdy == OS_TRUE) {
+                         sched = OS_TRUE;                     /* When done we will reschedule          */
+                     }
+                 }
+                 break;
+
+            case OS_FLAG_WAIT_CLR_ANY:               /* See if any flag set                            */
+                 flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags;
+                 if (flags_rdy != (OS_FLAGS)0) {              /* Make task RTR, event(s) Rx'd          */
+                     rdy = OS_FlagTaskRdy(pnode, flags_rdy, OS_STAT_PEND_OK);  
+                     if (rdy == OS_TRUE) {
+                         sched = OS_TRUE;                     /* When done we will reschedule          */
+                     }
+                 }
+                 break;
+#endif
+            default:
+                 OS_EXIT_CRITICAL();
+                 *perr = OS_ERR_FLAG_WAIT_TYPE;
+                 return ((OS_FLAGS)0);
+        }
+        pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext; /* Point to next task waiting for event flag(s) */
+    }
+    OS_EXIT_CRITICAL();
+    if (sched == OS_TRUE) {
+        OS_Sched();
+    }
+    OS_ENTER_CRITICAL();
+    flags_cur = pgrp->OSFlagFlags;
+    OS_EXIT_CRITICAL();
+    *perr     = OS_ERR_NONE;
+    return (flags_cur);
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                          QUERY EVENT FLAG
+*
+* Description: This function is used to check the value of the event flag group.
+*
+* Arguments  : pgrp         is a pointer to the desired event flag group.
+*
+*              perr          is a pointer to an error code returned to the called:
+*                            OS_ERR_NONE                The call was successfull
+*                            OS_ERR_FLAG_INVALID_PGRP   You passed a NULL pointer
+*                            OS_ERR_EVENT_TYPE          You are not pointing to an event flag group
+*
+* Returns    : The current value of the event flag group.
+*
+* Called From: Task or ISR
+*********************************************************************************************************
+*/
+
+#if OS_FLAG_QUERY_EN > 0u
+OS_FLAGS  OSFlagQuery (OS_FLAG_GRP  *pgrp,
+                       INT8U        *perr)
+{
+    OS_FLAGS   flags;
+#if OS_CRITICAL_METHOD == 3u                      /* Allocate storage for CPU status register          */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_FLAGS)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pgrp == (OS_FLAG_GRP *)0) {               /* Validate 'pgrp'                                   */
+        *perr = OS_ERR_FLAG_INVALID_PGRP;
+        return ((OS_FLAGS)0);
+    }
+#endif
+    if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type                         */
+        *perr = OS_ERR_EVENT_TYPE;
+        return ((OS_FLAGS)0);
+    }
+    OS_ENTER_CRITICAL();
+    flags = pgrp->OSFlagFlags;
+    OS_EXIT_CRITICAL();
+    *perr = OS_ERR_NONE;
+    return (flags);                               /* Return the current value of the event flags       */
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                     SUSPEND TASK UNTIL EVENT FLAG(s) RECEIVED OR TIMEOUT OCCURS
+*
+* Description: This function is internal to uC/OS-II and is used to put a task to sleep until the desired
+*              event flag bit(s) are set.
+*
+* Arguments  : pgrp          is a pointer to the desired event flag group.
+*
+*              pnode         is a pointer to a structure which contains data about the task waiting for
+*                            event flag bit(s) to be set.
+*
+*              flags         Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check.
+*                            The bits you want are specified by setting the corresponding bits in
+*                            'flags'.  e.g. if your application wants to wait for bits 0 and 1 then
+*                            'flags' would contain 0x03.
+*
+*              wait_type     specifies whether you want ALL bits to be set/cleared or ANY of the bits
+*                            to be set/cleared.
+*                            You can specify the following argument:
+*
+*                            OS_FLAG_WAIT_CLR_ALL   You will check ALL bits in 'mask' to be clear (0)
+*                            OS_FLAG_WAIT_CLR_ANY   You will check ANY bit  in 'mask' to be clear (0)
+*                            OS_FLAG_WAIT_SET_ALL   You will check ALL bits in 'mask' to be set   (1)
+*                            OS_FLAG_WAIT_SET_ANY   You will check ANY bit  in 'mask' to be set   (1)
+*
+*              timeout       is the desired amount of time that the task will wait for the event flag
+*                            bit(s) to be set.
+*
+* Returns    : none
+*
+* Called by  : OSFlagPend()  OS_FLAG.C
+*
+* Note(s)    : This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+
+static  void  OS_FlagBlock (OS_FLAG_GRP  *pgrp,
+                            OS_FLAG_NODE *pnode,
+                            OS_FLAGS      flags,
+                            INT8U         wait_type,
+                            INT32U        timeout)
+{
+    OS_FLAG_NODE  *pnode_next;
+    INT8U          y;
+
+
+    OSTCBCur->OSTCBStat      |= OS_STAT_FLAG;
+    OSTCBCur->OSTCBStatPend   = OS_STAT_PEND_OK;
+    OSTCBCur->OSTCBDly        = timeout;              /* Store timeout in task's TCB                   */
+#if OS_TASK_DEL_EN > 0u
+    OSTCBCur->OSTCBFlagNode   = pnode;                /* TCB to link to node                           */
+#endif
+    pnode->OSFlagNodeFlags    = flags;                /* Save the flags that we need to wait for       */
+    pnode->OSFlagNodeWaitType = wait_type;            /* Save the type of wait we are doing            */
+    pnode->OSFlagNodeTCB      = (void *)OSTCBCur;     /* Link to task's TCB                            */
+    pnode->OSFlagNodeNext     = pgrp->OSFlagWaitList; /* Add node at beginning of event flag wait list */
+    pnode->OSFlagNodePrev     = (void *)0;
+    pnode->OSFlagNodeFlagGrp  = (void *)pgrp;         /* Link to Event Flag Group                      */
+    pnode_next                = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;
+    if (pnode_next != (void *)0) {                    /* Is this the first NODE to insert?             */
+        pnode_next->OSFlagNodePrev = pnode;           /* No, link in doubly linked list                */
+    }
+    pgrp->OSFlagWaitList = (void *)pnode;
+
+    y            =  OSTCBCur->OSTCBY;                 /* Suspend current task until flag(s) received   */
+    OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
+    if (OSRdyTbl[y] == 0x00u) {
+        OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
+    }
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                  INITIALIZE THE EVENT FLAG MODULE
+*
+* Description: This function is called by uC/OS-II to initialize the event flag module.  Your application
+*              MUST NOT call this function.  In other words, this function is internal to uC/OS-II.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* WARNING    : You MUST NOT call this function from your code.  This is an INTERNAL function to uC/OS-II.
+*********************************************************************************************************
+*/
+
+void  OS_FlagInit (void)
+{
+#if OS_MAX_FLAGS == 1u
+    OSFlagFreeList                 = (OS_FLAG_GRP *)&OSFlagTbl[0];  /* Only ONE event flag group!      */
+    OSFlagFreeList->OSFlagType     = OS_EVENT_TYPE_UNUSED;
+    OSFlagFreeList->OSFlagWaitList = (void *)0;
+    OSFlagFreeList->OSFlagFlags    = (OS_FLAGS)0;
+#if OS_FLAG_NAME_EN > 0u
+    OSFlagFreeList->OSFlagName     = (INT8U *)"?";
+#endif
+#endif
+
+#if OS_MAX_FLAGS >= 2u
+    INT16U        ix;
+    INT16U        ix_next;
+    OS_FLAG_GRP  *pgrp1;
+    OS_FLAG_GRP  *pgrp2;
+
+
+    OS_MemClr((INT8U *)&OSFlagTbl[0], sizeof(OSFlagTbl));           /* Clear the flag group table      */
+    for (ix = 0u; ix < (OS_MAX_FLAGS - 1u); ix++) {                 /* Init. list of free EVENT FLAGS  */
+        ix_next = ix + 1u;
+        pgrp1 = &OSFlagTbl[ix];
+        pgrp2 = &OSFlagTbl[ix_next];
+        pgrp1->OSFlagType     = OS_EVENT_TYPE_UNUSED;
+        pgrp1->OSFlagWaitList = (void *)pgrp2;
+#if OS_FLAG_NAME_EN > 0u
+        pgrp1->OSFlagName     = (INT8U *)(void *)"?";               /* Unknown name                    */
+#endif
+    }
+    pgrp1                 = &OSFlagTbl[ix];
+    pgrp1->OSFlagType     = OS_EVENT_TYPE_UNUSED;
+    pgrp1->OSFlagWaitList = (void *)0;
+#if OS_FLAG_NAME_EN > 0u
+    pgrp1->OSFlagName     = (INT8U *)(void *)"?";                   /* Unknown name                    */
+#endif
+    OSFlagFreeList        = &OSFlagTbl[0];
+#endif
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                              MAKE TASK READY-TO-RUN, EVENT(s) OCCURRED
+*
+* Description: This function is internal to uC/OS-II and is used to make a task ready-to-run because the
+*              desired event flag bits have been set.
+*
+* Arguments  : pnode         is a pointer to a structure which contains data about the task waiting for
+*                            event flag bit(s) to be set.
+*
+*              flags_rdy     contains the bit pattern of the event flags that cause the task to become
+*                            ready-to-run.
+*
+*              pend_stat   is used to indicate the readied task's pending status:
+*
+*
+* Returns    : OS_TRUE       If the task has been placed in the ready list and thus needs scheduling
+*              OS_FALSE      The task is still not ready to run and thus scheduling is not necessary
+*
+* Called by  : OSFlagsPost() OS_FLAG.C
+*
+* Note(s)    : 1) This function assumes that interrupts are disabled.
+*              2) This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+
+static  BOOLEAN  OS_FlagTaskRdy (OS_FLAG_NODE *pnode,
+                                 OS_FLAGS      flags_rdy,
+                                 INT8U         pend_stat)
+{
+    OS_TCB   *ptcb;
+    BOOLEAN   sched;
+
+
+    ptcb                 = (OS_TCB *)pnode->OSFlagNodeTCB; /* Point to TCB of waiting task             */
+    ptcb->OSTCBDly       = 0u;
+    ptcb->OSTCBFlagsRdy  = flags_rdy;
+    ptcb->OSTCBStat     &= (INT8U)~(INT8U)OS_STAT_FLAG;
+    ptcb->OSTCBStatPend  = pend_stat;
+    if (ptcb->OSTCBStat == OS_STAT_RDY) {                  /* Task now ready?                          */
+        OSRdyGrp               |= ptcb->OSTCBBitY;         /* Put task into ready list                 */
+        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
+        sched                   = OS_TRUE;
+    } else {
+        sched                   = OS_FALSE;
+    }
+    OS_FlagUnlink(pnode);
+    return (sched);
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                              UNLINK EVENT FLAG NODE FROM WAITING LIST
+*
+* Description: This function is internal to uC/OS-II and is used to unlink an event flag node from a
+*              list of tasks waiting for the event flag.
+*
+* Arguments  : pnode         is a pointer to a structure which contains data about the task waiting for
+*                            event flag bit(s) to be set.
+*
+* Returns    : none
+*
+* Called by  : OS_FlagTaskRdy() OS_FLAG.C
+*              OSFlagPend()     OS_FLAG.C
+*              OSTaskDel()      OS_TASK.C
+*
+* Note(s)    : 1) This function assumes that interrupts are disabled.
+*              2) This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+
+void  OS_FlagUnlink (OS_FLAG_NODE *pnode)
+{
+#if OS_TASK_DEL_EN > 0u
+    OS_TCB       *ptcb;
+#endif
+    OS_FLAG_GRP  *pgrp;
+    OS_FLAG_NODE *pnode_prev;
+    OS_FLAG_NODE *pnode_next;
+
+
+    pnode_prev = (OS_FLAG_NODE *)pnode->OSFlagNodePrev;
+    pnode_next = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;
+    if (pnode_prev == (OS_FLAG_NODE *)0) {                      /* Is it first node in wait list?      */
+        pgrp                 = (OS_FLAG_GRP *)pnode->OSFlagNodeFlagGrp;
+        pgrp->OSFlagWaitList = (void *)pnode_next;              /*      Update list for new 1st node   */
+        if (pnode_next != (OS_FLAG_NODE *)0) {
+            pnode_next->OSFlagNodePrev = (OS_FLAG_NODE *)0;     /*      Link new 1st node PREV to NULL */
+        }
+    } else {                                                    /* No,  A node somewhere in the list   */
+        pnode_prev->OSFlagNodeNext = pnode_next;                /*      Link around the node to unlink */
+        if (pnode_next != (OS_FLAG_NODE *)0) {                  /*      Was this the LAST node?        */
+            pnode_next->OSFlagNodePrev = pnode_prev;            /*      No, Link around current node   */
+        }
+    }
+#if OS_TASK_DEL_EN > 0u
+    ptcb                = (OS_TCB *)pnode->OSFlagNodeTCB;
+    ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0;
+#endif
+}
+#endif

+ 654 - 0
MiddleWare/uCOS_II/uCOS-II/Source/os_mbox.c

@@ -0,0 +1,654 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                       MESSAGE MAILBOX MANAGEMENT
+*
+*                              (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_MBOX.C
+* By      : Jean J. Labrosse
+* Version : V2.92.11
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#define  MICRIUM_SOURCE
+
+#ifndef  OS_MASTER_FILE
+#include <ucos_ii.h>
+#endif
+
+#if OS_MBOX_EN > 0u
+/*
+*********************************************************************************************************
+*                                        ACCEPT MESSAGE FROM MAILBOX
+*
+* Description: This function checks the mailbox to see if a message is available.  Unlike OSMboxPend(),
+*              OSMboxAccept() does not suspend the calling task if a message is not available.
+*
+* Arguments  : pevent        is a pointer to the event control block
+*
+* Returns    : != (void *)0  is the message in the mailbox if one is available.  The mailbox is cleared
+*                            so the next time OSMboxAccept() is called, the mailbox will be empty.
+*              == (void *)0  if the mailbox is empty or,
+*                            if 'pevent' is a NULL pointer or,
+*                            if you didn't pass the proper event pointer.
+*********************************************************************************************************
+*/
+
+#if OS_MBOX_ACCEPT_EN > 0u
+void  *OSMboxAccept (OS_EVENT *pevent)
+{
+    void      *pmsg;
+#if OS_CRITICAL_METHOD == 3u                              /* Allocate storage for CPU status register  */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                        /* Validate 'pevent'                         */
+        return ((void *)0);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {      /* Validate event block type                 */
+        return ((void *)0);
+    }
+    OS_ENTER_CRITICAL();
+    pmsg               = pevent->OSEventPtr;
+    pevent->OSEventPtr = (void *)0;                       /* Clear the mailbox                         */
+    OS_EXIT_CRITICAL();
+    return (pmsg);                                        /* Return the message received (or NULL)     */
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                          CREATE A MESSAGE MAILBOX
+*
+* Description: This function creates a message mailbox if free event control blocks are available.
+*
+* Arguments  : pmsg          is a pointer to a message that you wish to deposit in the mailbox.  If
+*                            you set this value to the NULL pointer (i.e. (void *)0) then the mailbox
+*                            will be considered empty.
+*
+* Returns    : != (OS_EVENT *)0  is a pointer to the event control clock (OS_EVENT) associated with the
+*                                created mailbox
+*              == (OS_EVENT *)0  if no event control blocks were available
+*********************************************************************************************************
+*/
+
+OS_EVENT  *OSMboxCreate (void *pmsg)
+{
+    OS_EVENT  *pevent;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    if (OSSafetyCriticalStartFlag == OS_TRUE) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_EVENT *)0);
+    }
+#endif
+
+    if (OSIntNesting > 0u) {                     /* See if called from ISR ...                         */
+        return ((OS_EVENT *)0);                  /* ... can't CREATE from an ISR                       */
+    }
+    OS_ENTER_CRITICAL();
+    pevent = OSEventFreeList;                    /* Get next free event control block                  */
+    if (OSEventFreeList != (OS_EVENT *)0) {      /* See if pool of free ECB pool was empty             */
+        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
+    }
+    OS_EXIT_CRITICAL();
+    if (pevent != (OS_EVENT *)0) {
+        pevent->OSEventType    = OS_EVENT_TYPE_MBOX;
+        pevent->OSEventCnt     = 0u;
+        pevent->OSEventPtr     = pmsg;           /* Deposit message in event control block             */
+#if OS_EVENT_NAME_EN > 0u
+        pevent->OSEventName    = (INT8U *)(void *)"?";
+#endif
+        OS_EventWaitListInit(pevent);
+    }
+    return (pevent);                             /* Return pointer to event control block              */
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                           DELETE A MAIBOX
+*
+* Description: This function deletes a mailbox and readies all tasks pending on the mailbox.
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired
+*                            mailbox.
+*
+*              opt           determines delete options as follows:
+*                            opt == OS_DEL_NO_PEND   Delete the mailbox ONLY if no task pending
+*                            opt == OS_DEL_ALWAYS    Deletes the mailbox even if tasks are waiting.
+*                                                    In this case, all the tasks pending will be readied.
+*
+*              perr          is a pointer to an error code that can contain one of the following values:
+*                            OS_ERR_NONE             The call was successful and the mailbox was deleted
+*                            OS_ERR_DEL_ISR          If you attempted to delete the mailbox from an ISR
+*                            OS_ERR_INVALID_OPT      An invalid option was specified
+*                            OS_ERR_TASK_WAITING     One or more tasks were waiting on the mailbox
+*                            OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a mailbox
+*                            OS_ERR_PEVENT_NULL      If 'pevent' is a NULL pointer.
+*
+* Returns    : pevent        upon error
+*              (OS_EVENT *)0 if the mailbox was successfully deleted.
+*
+* Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
+*                 the mailbox MUST check the return code of OSMboxPend().
+*              2) OSMboxAccept() callers will not know that the intended mailbox has been deleted!
+*              3) This call can potentially disable interrupts for a long time.  The interrupt disable
+*                 time is directly proportional to the number of tasks waiting on the mailbox.
+*              4) Because ALL tasks pending on the mailbox will be readied, you MUST be careful in
+*                 applications where the mailbox is used for mutual exclusion because the resource(s)
+*                 will no longer be guarded by the mailbox.
+*              5) All tasks that were waiting for the mailbox will be readied and returned an 
+*                 OS_ERR_PEND_ABORT if OSMboxDel() was called with OS_DEL_ALWAYS
+*********************************************************************************************************
+*/
+
+#if OS_MBOX_DEL_EN > 0u
+OS_EVENT  *OSMboxDel (OS_EVENT  *pevent,
+                      INT8U      opt,
+                      INT8U     *perr)
+{
+    BOOLEAN    tasks_waiting;
+    OS_EVENT  *pevent_return;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_EVENT *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
+        *perr = OS_ERR_PEVENT_NULL;
+        return (pevent);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {       /* Validate event block type                */
+        *perr = OS_ERR_EVENT_TYPE;
+        return (pevent);
+    }
+    if (OSIntNesting > 0u) {                               /* See if called from ISR ...               */
+        *perr = OS_ERR_DEL_ISR;                            /* ... can't DELETE from an ISR             */
+        return (pevent);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                        /* See if any tasks waiting on mailbox      */
+        tasks_waiting = OS_TRUE;                           /* Yes                                      */
+    } else {
+        tasks_waiting = OS_FALSE;                          /* No                                       */
+    }
+    switch (opt) {
+        case OS_DEL_NO_PEND:                               /* Delete mailbox only if no task waiting   */
+             if (tasks_waiting == OS_FALSE) {
+#if OS_EVENT_NAME_EN > 0u
+                 pevent->OSEventName = (INT8U *)(void *)"?";
+#endif
+                 pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
+                 pevent->OSEventPtr  = OSEventFreeList;    /* Return Event Control Block to free list  */
+                 pevent->OSEventCnt  = 0u;
+                 OSEventFreeList     = pevent;             /* Get next free event control block        */
+                 OS_EXIT_CRITICAL();
+                 *perr               = OS_ERR_NONE;
+                 pevent_return       = (OS_EVENT *)0;      /* Mailbox has been deleted                 */
+             } else {
+                 OS_EXIT_CRITICAL();
+                 *perr               = OS_ERR_TASK_WAITING;
+                 pevent_return       = pevent;
+             }
+             break;
+
+        case OS_DEL_ALWAYS:                                /* Always delete the mailbox                */
+             while (pevent->OSEventGrp != 0u) {            /* Ready ALL tasks waiting for mailbox      */
+                 (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
+             }
+#if OS_EVENT_NAME_EN > 0u
+             pevent->OSEventName    = (INT8U *)(void *)"?";
+#endif
+             pevent->OSEventType    = OS_EVENT_TYPE_UNUSED;
+             pevent->OSEventPtr     = OSEventFreeList;     /* Return Event Control Block to free list  */
+             pevent->OSEventCnt     = 0u;
+             OSEventFreeList        = pevent;              /* Get next free event control block        */
+             OS_EXIT_CRITICAL();
+             if (tasks_waiting == OS_TRUE) {               /* Reschedule only if task(s) were waiting  */
+                 OS_Sched();                               /* Find highest priority task ready to run  */
+             }
+             *perr         = OS_ERR_NONE;
+             pevent_return = (OS_EVENT *)0;                /* Mailbox has been deleted                 */
+             break;
+
+        default:
+             OS_EXIT_CRITICAL();
+             *perr         = OS_ERR_INVALID_OPT;
+             pevent_return = pevent;
+             break;
+    }
+    return (pevent_return);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                    PEND ON MAILBOX FOR A MESSAGE
+*
+* Description: This function waits for a message to be sent to a mailbox
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired mailbox
+*
+*              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
+*                            wait for a message to arrive at the mailbox up to the amount of time
+*                            specified by this argument.  If you specify 0, however, your task will wait
+*                            forever at the specified mailbox or, until a message arrives.
+*
+*              perr          is a pointer to where an error message will be deposited.  Possible error
+*                            messages are:
+*
+*                            OS_ERR_NONE         The call was successful and your task received a
+*                                                message.
+*                            OS_ERR_TIMEOUT      A message was not received within the specified 'timeout'.
+*                            OS_ERR_PEND_ABORT   The wait on the mailbox was aborted.
+*                            OS_ERR_EVENT_TYPE   Invalid event type
+*                            OS_ERR_PEND_ISR     If you called this function from an ISR and the result
+*                                                would lead to a suspension.
+*                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer
+*                            OS_ERR_PEND_LOCKED  If you called this function when the scheduler is locked
+*
+* Returns    : != (void *)0  is a pointer to the message received
+*              == (void *)0  if no message was received or,
+*                            if 'pevent' is a NULL pointer or,
+*                            if you didn't pass the proper pointer to the event control block.
+*********************************************************************************************************
+*/
+/*$PAGE*/
+void  *OSMboxPend (OS_EVENT  *pevent,
+                   INT32U     timeout,
+                   INT8U     *perr)
+{
+    void      *pmsg;
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((void *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        *perr = OS_ERR_PEVENT_NULL;
+        return ((void *)0);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* Validate event block type                     */
+        *perr = OS_ERR_EVENT_TYPE;
+        return ((void *)0);
+    }
+    if (OSIntNesting > 0u) {                          /* See if called from ISR ...                    */
+        *perr = OS_ERR_PEND_ISR;                      /* ... can't PEND from an ISR                    */
+        return ((void *)0);
+    }
+    if (OSLockNesting > 0u) {                         /* See if called with scheduler locked ...       */
+        *perr = OS_ERR_PEND_LOCKED;                   /* ... can't PEND when locked                    */
+        return ((void *)0);
+    }
+    OS_ENTER_CRITICAL();
+    pmsg = pevent->OSEventPtr;
+    if (pmsg != (void *)0) {                          /* See if there is already a message             */
+        pevent->OSEventPtr = (void *)0;               /* Clear the mailbox                             */
+        OS_EXIT_CRITICAL();
+        *perr = OS_ERR_NONE;
+        return (pmsg);                                /* Return the message received (or NULL)         */
+    }
+    OSTCBCur->OSTCBStat     |= OS_STAT_MBOX;          /* Message not available, task will pend         */
+    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
+    OSTCBCur->OSTCBDly       = timeout;               /* Load timeout in TCB                           */
+    OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
+    OS_EXIT_CRITICAL();
+    OS_Sched();                                       /* Find next highest priority task ready to run  */
+    OS_ENTER_CRITICAL();
+    switch (OSTCBCur->OSTCBStatPend) {                /* See if we timed-out or aborted                */
+        case OS_STAT_PEND_OK:
+             pmsg =  OSTCBCur->OSTCBMsg;
+            *perr =  OS_ERR_NONE;
+             break;
+
+        case OS_STAT_PEND_ABORT:
+             pmsg = (void *)0;
+            *perr =  OS_ERR_PEND_ABORT;               /* Indicate that we aborted                      */
+             break;
+
+        case OS_STAT_PEND_TO:
+        default:
+             OS_EventTaskRemove(OSTCBCur, pevent);
+             pmsg = (void *)0;
+            *perr =  OS_ERR_TIMEOUT;                  /* Indicate that we didn't get event within TO   */
+             break;
+    }
+    OSTCBCur->OSTCBStat          =  OS_STAT_RDY;      /* Set   task  status to ready                   */
+    OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;  /* Clear pend  status                            */
+    OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;    /* Clear event pointers                          */
+#if (OS_EVENT_MULTI_EN > 0u)
+    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
+#endif
+    OSTCBCur->OSTCBMsg           = (void      *)0;    /* Clear  received message                       */
+    OS_EXIT_CRITICAL();
+    return (pmsg);                                    /* Return received message                       */
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                     ABORT WAITING ON A MESSAGE MAILBOX
+*
+* Description: This function aborts & readies any tasks currently waiting on a mailbox.  This function
+*              should be used to fault-abort the wait on the mailbox, rather than to normally signal
+*              the mailbox via OSMboxPost() or OSMboxPostOpt().
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired mailbox.
+*
+*              opt           determines the type of ABORT performed:
+*                            OS_PEND_OPT_NONE         ABORT wait for a single task (HPT) waiting on the
+*                                                     mailbox
+*                            OS_PEND_OPT_BROADCAST    ABORT wait for ALL tasks that are  waiting on the
+*                                                     mailbox
+*
+*              perr          is a pointer to where an error message will be deposited.  Possible error
+*                            messages are:
+*
+*                            OS_ERR_NONE         No tasks were     waiting on the mailbox.
+*                            OS_ERR_PEND_ABORT   At least one task waiting on the mailbox was readied
+*                                                and informed of the aborted wait; check return value
+*                                                for the number of tasks whose wait on the mailbox
+*                                                was aborted.
+*                            OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a mailbox.
+*                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
+*
+* Returns    : == 0          if no tasks were waiting on the mailbox, or upon error.
+*              >  0          if one or more tasks waiting on the mailbox are now readied and informed.
+*********************************************************************************************************
+*/
+
+#if OS_MBOX_PEND_ABORT_EN > 0u
+INT8U  OSMboxPendAbort (OS_EVENT  *pevent,
+                        INT8U      opt,
+                        INT8U     *perr)
+{
+    INT8U      nbr_tasks;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
+        *perr = OS_ERR_PEVENT_NULL;
+        return (0u);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {       /* Validate event block type                */
+        *perr = OS_ERR_EVENT_TYPE;
+        return (0u);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                        /* See if any task waiting on mailbox?      */
+        nbr_tasks = 0u;
+        switch (opt) {
+            case OS_PEND_OPT_BROADCAST:                    /* Do we need to abort ALL waiting tasks?   */
+                 while (pevent->OSEventGrp != 0u) {        /* Yes, ready ALL tasks waiting on mailbox  */
+                     (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
+                     nbr_tasks++;
+                 }
+                 break;
+
+            case OS_PEND_OPT_NONE:
+            default:                                       /* No,  ready HPT       waiting on mailbox  */
+                 (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
+                 nbr_tasks++;
+                 break;
+        }
+        OS_EXIT_CRITICAL();
+        OS_Sched();                                        /* Find HPT ready to run                    */
+        *perr = OS_ERR_PEND_ABORT;
+        return (nbr_tasks);
+    }
+    OS_EXIT_CRITICAL();
+    *perr = OS_ERR_NONE;
+    return (0u);                                           /* No tasks waiting on mailbox              */
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                      POST MESSAGE TO A MAILBOX
+*
+* Description: This function sends a message to a mailbox
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired mailbox
+*
+*              pmsg          is a pointer to the message to send.  You MUST NOT send a NULL pointer.
+*
+* Returns    : OS_ERR_NONE          The call was successful and the message was sent
+*              OS_ERR_MBOX_FULL     If the mailbox already contains a message.  You can can only send one
+*                                   message at a time and thus, the message MUST be consumed before you
+*                                   are allowed to send another one.
+*              OS_ERR_EVENT_TYPE    If you are attempting to post to a non mailbox.
+*              OS_ERR_PEVENT_NULL   If 'pevent' is a NULL pointer
+*              OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer
+*
+* Note(s)    : 1) HPT means Highest Priority Task
+*********************************************************************************************************
+*/
+
+#if OS_MBOX_POST_EN > 0u
+INT8U  OSMboxPost (OS_EVENT  *pevent,
+                   void      *pmsg)
+{
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        return (OS_ERR_PEVENT_NULL);
+    }
+    if (pmsg == (void *)0) {                          /* Make sure we are not posting a NULL pointer   */
+        return (OS_ERR_POST_NULL_PTR);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* Validate event block type                     */
+        return (OS_ERR_EVENT_TYPE);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                   /* See if any task pending on mailbox            */
+                                                      /* Ready HPT waiting on event                    */
+        (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
+        OS_EXIT_CRITICAL();
+        OS_Sched();                                   /* Find highest priority task ready to run       */
+        return (OS_ERR_NONE);
+    }
+    if (pevent->OSEventPtr != (void *)0) {            /* Make sure mailbox doesn't already have a msg  */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_MBOX_FULL);
+    }
+    pevent->OSEventPtr = pmsg;                        /* Place message in mailbox                      */
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                      POST MESSAGE TO A MAILBOX
+*
+* Description: This function sends a message to a mailbox
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired mailbox
+*
+*              pmsg          is a pointer to the message to send.  You MUST NOT send a NULL pointer.
+*
+*              opt           determines the type of POST performed:
+*                            OS_POST_OPT_NONE         POST to a single waiting task
+*                                                     (Identical to OSMboxPost())
+*                            OS_POST_OPT_BROADCAST    POST to ALL tasks that are waiting on the mailbox
+*
+*                            OS_POST_OPT_NO_SCHED     Indicates that the scheduler will NOT be invoked
+*
+* Returns    : OS_ERR_NONE          The call was successful and the message was sent
+*              OS_ERR_MBOX_FULL     If the mailbox already contains a message.  You can can only send one
+*                                   message at a time and thus, the message MUST be consumed before you
+*                                   are allowed to send another one.
+*              OS_ERR_EVENT_TYPE    If you are attempting to post to a non mailbox.
+*              OS_ERR_PEVENT_NULL   If 'pevent' is a NULL pointer
+*              OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer
+*
+* Note(s)    : 1) HPT means Highest Priority Task
+*
+* Warning    : Interrupts can be disabled for a long time if you do a 'broadcast'.  In fact, the
+*              interrupt disable time is proportional to the number of tasks waiting on the mailbox.
+*********************************************************************************************************
+*/
+
+#if OS_MBOX_POST_OPT_EN > 0u
+INT8U  OSMboxPostOpt (OS_EVENT  *pevent,
+                      void      *pmsg,
+                      INT8U      opt)
+{
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        return (OS_ERR_PEVENT_NULL);
+    }
+    if (pmsg == (void *)0) {                          /* Make sure we are not posting a NULL pointer   */
+        return (OS_ERR_POST_NULL_PTR);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* Validate event block type                     */
+        return (OS_ERR_EVENT_TYPE);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                   /* See if any task pending on mailbox            */
+        if ((opt & OS_POST_OPT_BROADCAST) != 0x00u) { /* Do we need to post msg to ALL waiting tasks ? */
+            while (pevent->OSEventGrp != 0u) {        /* Yes, Post to ALL tasks waiting on mailbox     */
+                (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
+            }
+        } else {                                      /* No,  Post to HPT waiting on mbox              */
+            (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
+        }
+        OS_EXIT_CRITICAL();
+        if ((opt & OS_POST_OPT_NO_SCHED) == 0u) {     /* See if scheduler needs to be invoked          */
+            OS_Sched();                               /* Find HPT ready to run                         */
+        }
+        return (OS_ERR_NONE);
+    }
+    if (pevent->OSEventPtr != (void *)0) {            /* Make sure mailbox doesn't already have a msg  */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_MBOX_FULL);
+    }
+    pevent->OSEventPtr = pmsg;                        /* Place message in mailbox                      */
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       QUERY A MESSAGE MAILBOX
+*
+* Description: This function obtains information about a message mailbox.
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired mailbox
+*
+*              p_mbox_data   is a pointer to a structure that will contain information about the message
+*                            mailbox.
+*
+* Returns    : OS_ERR_NONE         The call was successful and the message was sent
+*              OS_ERR_EVENT_TYPE   If you are attempting to obtain data from a non mailbox.
+*              OS_ERR_PEVENT_NULL  If 'pevent'      is a NULL pointer
+*              OS_ERR_PDATA_NULL   If 'p_mbox_data' is a NULL pointer
+*********************************************************************************************************
+*/
+
+#if OS_MBOX_QUERY_EN > 0u
+INT8U  OSMboxQuery (OS_EVENT      *pevent,
+                    OS_MBOX_DATA  *p_mbox_data)
+{
+    INT8U       i;
+    OS_PRIO    *psrc;
+    OS_PRIO    *pdest;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR   cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
+        return (OS_ERR_PEVENT_NULL);
+    }
+    if (p_mbox_data == (OS_MBOX_DATA *)0) {                /* Validate 'p_mbox_data'                   */
+        return (OS_ERR_PDATA_NULL);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {       /* Validate event block type                */
+        return (OS_ERR_EVENT_TYPE);
+    }
+    OS_ENTER_CRITICAL();
+    p_mbox_data->OSEventGrp = pevent->OSEventGrp;          /* Copy message mailbox wait list           */
+    psrc                    = &pevent->OSEventTbl[0];
+    pdest                   = &p_mbox_data->OSEventTbl[0];
+    for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
+        *pdest++ = *psrc++;
+    }
+    p_mbox_data->OSMsg = pevent->OSEventPtr;               /* Get message from mailbox                 */
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif                                                     /* OS_MBOX_QUERY_EN                         */
+#endif                                                     /* OS_MBOX_EN                               */

+ 462 - 0
MiddleWare/uCOS_II/uCOS-II/Source/os_mem.c

@@ -0,0 +1,462 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                            MEMORY MANAGEMENT
+*
+*                              (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_MEM.C
+* By      : Jean J. Labrosse
+* Version : V2.92.11
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#define  MICRIUM_SOURCE
+
+#ifndef  OS_MASTER_FILE
+#include <ucos_ii.h>
+#endif
+
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+/*
+*********************************************************************************************************
+*                                      CREATE A MEMORY PARTITION
+*
+* Description : Create a fixed-sized memory partition that will be managed by uC/OS-II.
+*
+* Arguments   : addr     is the starting address of the memory partition
+*
+*               nblks    is the number of memory blocks to create from the partition.
+*
+*               blksize  is the size (in bytes) of each block in the memory partition.
+*
+*               perr     is a pointer to a variable containing an error message which will be set by
+*                        this function to either:
+*
+*                        OS_ERR_NONE              if the memory partition has been created correctly.
+*                        OS_ERR_MEM_INVALID_ADDR  if you are specifying an invalid address for the memory
+*                                                 storage of the partition or, the block does not align
+*                                                 on a pointer boundary
+*                        OS_ERR_MEM_INVALID_PART  no free partitions available
+*                        OS_ERR_MEM_INVALID_BLKS  user specified an invalid number of blocks (must be >= 2)
+*                        OS_ERR_MEM_INVALID_SIZE  user specified an invalid block size
+*                                                   - must be greater than the size of a pointer
+*                                                   - must be able to hold an integral number of pointers
+* Returns    : != (OS_MEM *)0  is the partition was created
+*              == (OS_MEM *)0  if the partition was not created because of invalid arguments or, no
+*                              free partition is available.
+*********************************************************************************************************
+*/
+
+OS_MEM  *OSMemCreate (void   *addr,
+                      INT32U  nblks,
+                      INT32U  blksize,
+                      INT8U  *perr)
+{
+    OS_MEM    *pmem;
+    INT8U     *pblk;
+    void     **plink;
+    INT32U     loops;
+    INT32U     i;
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_MEM *)0);
+    }
+#endif
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    if (OSSafetyCriticalStartFlag == OS_TRUE) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_MEM *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (addr == (void *)0) {                          /* Must pass a valid address for the memory part.*/
+        *perr = OS_ERR_MEM_INVALID_ADDR;
+        return ((OS_MEM *)0);
+    }
+    if (((INT32U)addr & (sizeof(void *) - 1u)) != 0u){  /* Must be pointer size aligned                */
+        *perr = OS_ERR_MEM_INVALID_ADDR;
+        return ((OS_MEM *)0);
+    }
+    if (nblks < 2u) {                                 /* Must have at least 2 blocks per partition     */
+        *perr = OS_ERR_MEM_INVALID_BLKS;
+        return ((OS_MEM *)0);
+    }
+    if (blksize < sizeof(void *)) {                   /* Must contain space for at least a pointer     */
+        *perr = OS_ERR_MEM_INVALID_SIZE;
+        return ((OS_MEM *)0);
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    pmem = OSMemFreeList;                             /* Get next free memory partition                */
+    if (OSMemFreeList != (OS_MEM *)0) {               /* See if pool of free partitions was empty      */
+        OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
+    }
+    OS_EXIT_CRITICAL();
+    if (pmem == (OS_MEM *)0) {                        /* See if we have a memory partition             */
+        *perr = OS_ERR_MEM_INVALID_PART;
+        return ((OS_MEM *)0);
+    }
+    plink = (void **)addr;                            /* Create linked list of free memory blocks      */
+    pblk  = (INT8U *)addr;
+    loops  = nblks - 1u;
+    for (i = 0u; i < loops; i++) {
+        pblk +=  blksize;                             /* Point to the FOLLOWING block                  */
+       *plink = (void  *)pblk;                        /* Save pointer to NEXT block in CURRENT block   */
+        plink = (void **)pblk;                        /* Position to  NEXT      block                  */
+    }
+    *plink              = (void *)0;                  /* Last memory block points to NULL              */
+    pmem->OSMemAddr     = addr;                       /* Store start address of memory partition       */
+    pmem->OSMemFreeList = addr;                       /* Initialize pointer to pool of free blocks     */
+    pmem->OSMemNFree    = nblks;                      /* Store number of free blocks in MCB            */
+    pmem->OSMemNBlks    = nblks;
+    pmem->OSMemBlkSize  = blksize;                    /* Store block size of each memory blocks        */
+    *perr               = OS_ERR_NONE;
+    return (pmem);
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                         GET A MEMORY BLOCK
+*
+* Description : Get a memory block from a partition
+*
+* Arguments   : pmem    is a pointer to the memory partition control block
+*
+*               perr    is a pointer to a variable containing an error message which will be set by this
+*                       function to either:
+*
+*                       OS_ERR_NONE             if the memory partition has been created correctly.
+*                       OS_ERR_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to caller
+*                       OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem'
+*
+* Returns     : A pointer to a memory block if no error is detected
+*               A pointer to NULL if an error is detected
+*********************************************************************************************************
+*/
+
+void  *OSMemGet (OS_MEM  *pmem,
+                 INT8U   *perr)
+{
+    void      *pblk;
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((void *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pmem == (OS_MEM *)0) {                        /* Must point to a valid memory partition        */
+        *perr = OS_ERR_MEM_INVALID_PMEM;
+        return ((void *)0);
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    if (pmem->OSMemNFree > 0u) {                      /* See if there are any free memory blocks       */
+        pblk                = pmem->OSMemFreeList;    /* Yes, point to next free memory block          */
+        pmem->OSMemFreeList = *(void **)pblk;         /*      Adjust pointer to new free list          */
+        pmem->OSMemNFree--;                           /*      One less memory block in this partition  */
+        OS_EXIT_CRITICAL();
+        *perr = OS_ERR_NONE;                          /*      No error                                 */
+        return (pblk);                                /*      Return memory block to caller            */
+    }
+    OS_EXIT_CRITICAL();
+    *perr = OS_ERR_MEM_NO_FREE_BLKS;                  /* No,  Notify caller of empty memory partition  */
+    return ((void *)0);                               /*      Return NULL pointer to caller            */
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                 GET THE NAME OF A MEMORY PARTITION
+*
+* Description: This function is used to obtain the name assigned to a memory partition.
+*
+* Arguments  : pmem      is a pointer to the memory partition
+*
+*              pname     is a pointer to a pointer to an ASCII string that will receive the name of the memory partition.
+*
+*              perr      is a pointer to an error code that can contain one of the following values:
+*
+*                        OS_ERR_NONE                if the name was copied to 'pname'
+*                        OS_ERR_MEM_INVALID_PMEM    if you passed a NULL pointer for 'pmem'
+*                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
+*                        OS_ERR_NAME_GET_ISR        You called this function from an ISR
+*
+* Returns    : The length of the string or 0 if 'pmem' is a NULL pointer.
+*********************************************************************************************************
+*/
+
+#if OS_MEM_NAME_EN > 0u
+INT8U  OSMemNameGet (OS_MEM   *pmem,
+                     INT8U   **pname,
+                     INT8U    *perr)
+{
+    INT8U      len;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pmem == (OS_MEM *)0) {                   /* Is 'pmem' a NULL pointer?                          */
+        *perr = OS_ERR_MEM_INVALID_PMEM;
+        return (0u);
+    }
+    if (pname == (INT8U **)0) {                  /* Is 'pname' a NULL pointer?                         */
+        *perr = OS_ERR_PNAME_NULL;
+        return (0u);
+    }
+#endif
+    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
+        *perr = OS_ERR_NAME_GET_ISR;
+        return (0u);
+    }
+    OS_ENTER_CRITICAL();
+    *pname = pmem->OSMemName;
+    len    = OS_StrLen(*pname);
+    OS_EXIT_CRITICAL();
+    *perr  = OS_ERR_NONE;
+    return (len);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                 ASSIGN A NAME TO A MEMORY PARTITION
+*
+* Description: This function assigns a name to a memory partition.
+*
+* Arguments  : pmem      is a pointer to the memory partition
+*
+*              pname     is a pointer to an ASCII string that contains the name of the memory partition.
+*
+*              perr      is a pointer to an error code that can contain one of the following values:
+*
+*                        OS_ERR_NONE                if the name was copied to 'pname'
+*                        OS_ERR_MEM_INVALID_PMEM    if you passed a NULL pointer for 'pmem'
+*                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
+*                        OS_ERR_MEM_NAME_TOO_LONG   if the name doesn't fit in the storage area
+*                        OS_ERR_NAME_SET_ISR        if you called this function from an ISR
+*
+* Returns    : None
+*********************************************************************************************************
+*/
+
+#if OS_MEM_NAME_EN > 0u
+void  OSMemNameSet (OS_MEM  *pmem,
+                    INT8U   *pname,
+                    INT8U   *perr)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return;
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pmem == (OS_MEM *)0) {                   /* Is 'pmem' a NULL pointer?                          */
+        *perr = OS_ERR_MEM_INVALID_PMEM;
+        return;
+    }
+    if (pname == (INT8U *)0) {                   /* Is 'pname' a NULL pointer?                         */
+        *perr = OS_ERR_PNAME_NULL;
+        return;
+    }
+#endif
+    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
+        *perr = OS_ERR_NAME_SET_ISR;
+        return;
+    }
+    OS_ENTER_CRITICAL();
+    pmem->OSMemName = pname;
+    OS_EXIT_CRITICAL();
+    *perr           = OS_ERR_NONE;
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       RELEASE A MEMORY BLOCK
+*
+* Description : Returns a memory block to a partition
+*
+* Arguments   : pmem    is a pointer to the memory partition control block
+*
+*               pblk    is a pointer to the memory block being released.
+*
+* Returns     : OS_ERR_NONE              if the memory block was inserted into the partition
+*               OS_ERR_MEM_FULL          if you are returning a memory block to an already FULL memory
+*                                        partition (You freed more blocks than you allocated!)
+*               OS_ERR_MEM_INVALID_PMEM  if you passed a NULL pointer for 'pmem'
+*               OS_ERR_MEM_INVALID_PBLK  if you passed a NULL pointer for the block to release.
+*********************************************************************************************************
+*/
+
+INT8U  OSMemPut (OS_MEM  *pmem,
+                 void    *pblk)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pmem == (OS_MEM *)0) {                   /* Must point to a valid memory partition             */
+        return (OS_ERR_MEM_INVALID_PMEM);
+    }
+    if (pblk == (void *)0) {                     /* Must release a valid block                         */
+        return (OS_ERR_MEM_INVALID_PBLK);
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    if (pmem->OSMemNFree >= pmem->OSMemNBlks) {  /* Make sure all blocks not already returned          */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_MEM_FULL);
+    }
+    *(void **)pblk      = pmem->OSMemFreeList;   /* Insert released block into free block list         */
+    pmem->OSMemFreeList = pblk;
+    pmem->OSMemNFree++;                          /* One more memory block in this partition            */
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);                        /* Notify caller that memory block was released       */
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       QUERY MEMORY PARTITION
+*
+* Description : This function is used to determine the number of free memory blocks and the number of
+*               used memory blocks from a memory partition.
+*
+* Arguments   : pmem        is a pointer to the memory partition control block
+*
+*               p_mem_data  is a pointer to a structure that will contain information about the memory
+*                           partition.
+*
+* Returns     : OS_ERR_NONE               if no errors were found.
+*               OS_ERR_MEM_INVALID_PMEM   if you passed a NULL pointer for 'pmem'
+*               OS_ERR_MEM_INVALID_PDATA  if you passed a NULL pointer to the data recipient.
+*********************************************************************************************************
+*/
+
+#if OS_MEM_QUERY_EN > 0u
+INT8U  OSMemQuery (OS_MEM       *pmem,
+                   OS_MEM_DATA  *p_mem_data)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pmem == (OS_MEM *)0) {                   /* Must point to a valid memory partition             */
+        return (OS_ERR_MEM_INVALID_PMEM);
+    }
+    if (p_mem_data == (OS_MEM_DATA *)0) {        /* Must release a valid storage area for the data     */
+        return (OS_ERR_MEM_INVALID_PDATA);
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    p_mem_data->OSAddr     = pmem->OSMemAddr;
+    p_mem_data->OSFreeList = pmem->OSMemFreeList;
+    p_mem_data->OSBlkSize  = pmem->OSMemBlkSize;
+    p_mem_data->OSNBlks    = pmem->OSMemNBlks;
+    p_mem_data->OSNFree    = pmem->OSMemNFree;
+    OS_EXIT_CRITICAL();
+    p_mem_data->OSNUsed    = p_mem_data->OSNBlks - p_mem_data->OSNFree;
+    return (OS_ERR_NONE);
+}
+#endif                                           /* OS_MEM_QUERY_EN                                    */
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                 INITIALIZE MEMORY PARTITION MANAGER
+*
+* Description : This function is called by uC/OS-II to initialize the memory partition manager.  Your
+*               application MUST NOT call this function.
+*
+* Arguments   : none
+*
+* Returns     : none
+*
+* Note(s)    : This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+
+void  OS_MemInit (void)
+{
+#if OS_MAX_MEM_PART == 1u
+    OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl));   /* Clear the memory partition table          */
+    OSMemFreeList               = (OS_MEM *)&OSMemTbl[0]; /* Point to beginning of free list           */
+#if OS_MEM_NAME_EN > 0u
+    OSMemFreeList->OSMemName    = (INT8U *)"?";           /* Unknown name                              */
+#endif
+#endif
+
+#if OS_MAX_MEM_PART >= 2u
+    OS_MEM  *pmem;
+    INT16U   i;
+
+
+    OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl));   /* Clear the memory partition table          */
+    for (i = 0u; i < (OS_MAX_MEM_PART - 1u); i++) {       /* Init. list of free memory partitions      */
+        pmem                = &OSMemTbl[i];               /* Point to memory control block (MCB)       */
+        pmem->OSMemFreeList = (void *)&OSMemTbl[i + 1u];  /* Chain list of free partitions             */
+#if OS_MEM_NAME_EN > 0u
+        pmem->OSMemName  = (INT8U *)(void *)"?";
+#endif
+    }
+    pmem                = &OSMemTbl[i];
+    pmem->OSMemFreeList = (void *)0;                      /* Initialize last node                      */
+#if OS_MEM_NAME_EN > 0u
+    pmem->OSMemName = (INT8U *)(void *)"?";
+#endif
+
+    OSMemFreeList   = &OSMemTbl[0];                       /* Point to beginning of free list           */
+#endif
+}
+#endif                                                    /* OS_MEM_EN                                 */

+ 763 - 0
MiddleWare/uCOS_II/uCOS-II/Source/os_mutex.c

@@ -0,0 +1,763 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                  MUTUAL EXCLUSION SEMAPHORE MANAGEMENT
+*
+*                              (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_MUTEX.C
+* By      : Jean J. Labrosse
+* Version : V2.92.11
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#define  MICRIUM_SOURCE
+
+#ifndef  OS_MASTER_FILE
+#include <ucos_ii.h>
+#endif
+
+
+#if OS_MUTEX_EN > 0u
+/*
+*********************************************************************************************************
+*                                           LOCAL CONSTANTS
+*********************************************************************************************************
+*/
+
+#define  OS_MUTEX_KEEP_LOWER_8   ((INT16U)0x00FFu)
+#define  OS_MUTEX_KEEP_UPPER_8   ((INT16U)0xFF00u)
+
+#define  OS_MUTEX_AVAILABLE      ((INT16U)0x00FFu)
+
+/*
+*********************************************************************************************************
+*                                           LOCAL CONSTANTS
+*********************************************************************************************************
+*/
+
+static  void  OSMutex_RdyAtPrio(OS_TCB *ptcb, INT8U prio);
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                  ACCEPT MUTUAL EXCLUSION SEMAPHORE
+*
+* Description: This  function checks the mutual exclusion semaphore to see if a resource is available.
+*              Unlike OSMutexPend(), OSMutexAccept() does not suspend the calling task if the resource is
+*              not available or the event did not occur.
+*
+* Arguments  : pevent     is a pointer to the event control block
+*
+*              perr       is a pointer to an error code which will be returned to your application:
+*                            OS_ERR_NONE         if the call was successful.
+*                            OS_ERR_EVENT_TYPE   if 'pevent' is not a pointer to a mutex
+*                            OS_ERR_PEVENT_NULL  'pevent' is a NULL pointer
+*                            OS_ERR_PEND_ISR     if you called this function from an ISR
+*                            OS_ERR_PCP_LOWER    If the priority of the task that owns the Mutex is
+*                                                HIGHER (i.e. a lower number) than the PCP.  This error
+*                                                indicates that you did not set the PCP higher (lower
+*                                                number) than ALL the tasks that compete for the Mutex.
+*                                                Unfortunately, this is something that could not be
+*                                                detected when the Mutex is created because we don't know
+*                                                what tasks will be using the Mutex.
+*
+* Returns    : == OS_TRUE    if the resource is available, the mutual exclusion semaphore is acquired
+*              == OS_FALSE   a) if the resource is not available
+*                            b) you didn't pass a pointer to a mutual exclusion semaphore
+*                            c) you called this function from an ISR
+*
+* Warning(s) : This function CANNOT be called from an ISR because mutual exclusion semaphores are
+*              intended to be used by tasks only.
+*********************************************************************************************************
+*/
+
+#if OS_MUTEX_ACCEPT_EN > 0u
+BOOLEAN  OSMutexAccept (OS_EVENT  *pevent,
+                        INT8U     *perr)
+{
+    INT8U      pcp;                                    /* Priority Ceiling Priority (PCP)              */
+#if OS_CRITICAL_METHOD == 3u                           /* Allocate storage for CPU status register     */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (OS_FALSE);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                     /* Validate 'pevent'                            */
+        *perr = OS_ERR_PEVENT_NULL;
+        return (OS_FALSE);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) {  /* Validate event block type                    */
+        *perr = OS_ERR_EVENT_TYPE;
+        return (OS_FALSE);
+    }
+    if (OSIntNesting > 0u) {                           /* Make sure it's not called from an ISR        */
+        *perr = OS_ERR_PEND_ISR;
+        return (OS_FALSE);
+    }
+    OS_ENTER_CRITICAL();                               /* Get value (0 or 1) of Mutex                  */
+    pcp = (INT8U)(pevent->OSEventCnt >> 8u);           /* Get PCP from mutex                           */
+    if ((pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {
+        pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;   /*      Mask off LSByte (Acquire Mutex)         */
+        pevent->OSEventCnt |= OSTCBCur->OSTCBPrio;     /*      Save current task priority in LSByte    */
+        pevent->OSEventPtr  = (void *)OSTCBCur;        /*      Link TCB of task owning Mutex           */
+        if ((pcp != OS_PRIO_MUTEX_CEIL_DIS) &&
+            (OSTCBCur->OSTCBPrio <= pcp)) {            /*      PCP 'must' have a SMALLER prio ...      */
+             OS_EXIT_CRITICAL();                       /*      ... than current task!                  */
+            *perr = OS_ERR_PCP_LOWER;
+        } else {
+             OS_EXIT_CRITICAL();
+            *perr = OS_ERR_NONE;
+        }
+        return (OS_TRUE);
+    }
+    OS_EXIT_CRITICAL();
+    *perr = OS_ERR_NONE;
+    return (OS_FALSE);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                 CREATE A MUTUAL EXCLUSION SEMAPHORE
+*
+* Description: This function creates a mutual exclusion semaphore.
+*
+* Arguments  : prio          is the priority to use when accessing the mutual exclusion semaphore.  In
+*                            other words, when the semaphore is acquired and a higher priority task
+*                            attempts to obtain the semaphore then the priority of the task owning the
+*                            semaphore is raised to this priority.  It is assumed that you will specify
+*                            a priority that is LOWER in value than ANY of the tasks competing for the
+*                            mutex. If the priority is specified as OS_PRIO_MUTEX_CEIL_DIS, then the
+*                            priority ceiling promotion is disabled. This way, the tasks accessing the
+*                            semaphore do not have their priority promoted.
+*
+*              perr          is a pointer to an error code which will be returned to your application:
+*                               OS_ERR_NONE         if the call was successful.
+*                               OS_ERR_CREATE_ISR   if you attempted to create a MUTEX from an ISR
+*                               OS_ERR_PRIO_EXIST   if a task at the priority ceiling priority
+*                                                   already exist.
+*                               OS_ERR_PEVENT_NULL  No more event control blocks available.
+*                               OS_ERR_PRIO_INVALID if the priority you specify is higher that the
+*                                                   maximum allowed (i.e. > OS_LOWEST_PRIO)
+*
+* Returns    : != (void *)0  is a pointer to the event control clock (OS_EVENT) associated with the
+*                            created mutex.
+*              == (void *)0  if an error is detected.
+*
+* Note(s)    : 1) The LEAST significant 8 bits of '.OSEventCnt' hold the priority number of the task
+*                 owning the mutex or 0xFF if no task owns the mutex.
+*
+*              2) The MOST  significant 8 bits of '.OSEventCnt' hold the priority number used to
+*                 reduce priority inversion or 0xFF (OS_PRIO_MUTEX_CEIL_DIS) if priority ceiling
+*                 promotion is disabled.
+*********************************************************************************************************
+*/
+
+OS_EVENT  *OSMutexCreate (INT8U   prio,
+                          INT8U  *perr)
+{
+    OS_EVENT  *pevent;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_EVENT *)0);
+    }
+#endif
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    if (OSSafetyCriticalStartFlag == OS_TRUE) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_EVENT *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (prio != OS_PRIO_MUTEX_CEIL_DIS) {
+        if (prio >= OS_LOWEST_PRIO) {                      /* Validate PCP                             */
+           *perr = OS_ERR_PRIO_INVALID;
+            return ((OS_EVENT *)0);
+        }
+    }
+#endif
+    if (OSIntNesting > 0u) {                               /* See if called from ISR ...               */
+        *perr = OS_ERR_CREATE_ISR;                         /* ... can't CREATE mutex from an ISR       */
+        return ((OS_EVENT *)0);
+    }
+    OS_ENTER_CRITICAL();
+    if (prio != OS_PRIO_MUTEX_CEIL_DIS) {
+        if (OSTCBPrioTbl[prio] != (OS_TCB *)0) {           /* Mutex priority must not already exist    */
+            OS_EXIT_CRITICAL();                            /* Task already exist at priority ...       */
+           *perr = OS_ERR_PRIO_EXIST;                      /* ... ceiling priority                     */
+            return ((OS_EVENT *)0);
+        }
+        OSTCBPrioTbl[prio] = OS_TCB_RESERVED;              /* Reserve the table entry                  */
+    }
+
+    pevent = OSEventFreeList;                              /* Get next free event control block        */
+    if (pevent == (OS_EVENT *)0) {                         /* See if an ECB was available              */
+        if (prio != OS_PRIO_MUTEX_CEIL_DIS) {
+            OSTCBPrioTbl[prio] = (OS_TCB *)0;              /* No, Release the table entry              */
+        }
+        OS_EXIT_CRITICAL();
+       *perr = OS_ERR_PEVENT_NULL;                         /* No more event control blocks             */
+        return (pevent);
+    }
+    OSEventFreeList     = (OS_EVENT *)OSEventFreeList->OSEventPtr; /* Adjust the free list             */
+    OS_EXIT_CRITICAL();
+    pevent->OSEventType = OS_EVENT_TYPE_MUTEX;
+    pevent->OSEventCnt  = (INT16U)((INT16U)prio << 8u) | OS_MUTEX_AVAILABLE; /* Resource is avail.     */
+    pevent->OSEventPtr  = (void *)0;                       /* No task owning the mutex                 */
+#if OS_EVENT_NAME_EN > 0u
+    pevent->OSEventName = (INT8U *)(void *)"?";
+#endif
+    OS_EventWaitListInit(pevent);
+   *perr = OS_ERR_NONE;
+    return (pevent);
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                           DELETE A MUTEX
+*
+* Description: This function deletes a mutual exclusion semaphore and readies all tasks pending on the it.
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired mutex.
+*
+*              opt           determines delete options as follows:
+*                            opt == OS_DEL_NO_PEND   Delete mutex ONLY if no task pending
+*                            opt == OS_DEL_ALWAYS    Deletes the mutex even if tasks are waiting.
+*                                                    In this case, all the tasks pending will be readied.
+*
+*              perr          is a pointer to an error code that can contain one of the following values:
+*                            OS_ERR_NONE             The call was successful and the mutex was deleted
+*                            OS_ERR_DEL_ISR          If you attempted to delete the MUTEX from an ISR
+*                            OS_ERR_INVALID_OPT      An invalid option was specified
+*                            OS_ERR_TASK_WAITING     One or more tasks were waiting on the mutex
+*                            OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a mutex
+*                            OS_ERR_PEVENT_NULL      If 'pevent' is a NULL pointer.
+*
+* Returns    : pevent        upon error
+*              (OS_EVENT *)0 if the mutex was successfully deleted.
+*
+* Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
+*                 the mutex MUST check the return code of OSMutexPend().
+*
+*              2) This call can potentially disable interrupts for a long time.  The interrupt disable
+*                 time is directly proportional to the number of tasks waiting on the mutex.
+*
+*              3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the
+*                 resource(s) will no longer be guarded by the mutex.
+*
+*              4) IMPORTANT: In the 'OS_DEL_ALWAYS' case, we assume that the owner of the Mutex (if there
+*                            is one) is ready-to-run and is thus NOT pending on another kernel object or
+*                            has delayed itself.  In other words, if a task owns the mutex being deleted,
+*                            that task will be made ready-to-run at its original priority.
+*********************************************************************************************************
+*/
+
+#if OS_MUTEX_DEL_EN > 0u
+OS_EVENT  *OSMutexDel (OS_EVENT  *pevent,
+                       INT8U      opt,
+                       INT8U     *perr)
+{
+    BOOLEAN    tasks_waiting;
+    OS_EVENT  *pevent_return;
+    INT8U      pcp;                                        /* Priority ceiling priority                */
+    INT8U      prio;
+    OS_TCB    *ptcb;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_EVENT *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
+        *perr = OS_ERR_PEVENT_NULL;
+        return (pevent);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) {      /* Validate event block type                */
+        *perr = OS_ERR_EVENT_TYPE;
+        return (pevent);
+    }
+    if (OSIntNesting > 0u) {                               /* See if called from ISR ...               */
+        *perr = OS_ERR_DEL_ISR;                             /* ... can't DELETE from an ISR             */
+        return (pevent);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                        /* See if any tasks waiting on mutex        */
+        tasks_waiting = OS_TRUE;                           /* Yes                                      */
+    } else {
+        tasks_waiting = OS_FALSE;                          /* No                                       */
+    }
+    switch (opt) {
+        case OS_DEL_NO_PEND:                               /* DELETE MUTEX ONLY IF NO TASK WAITING --- */
+             if (tasks_waiting == OS_FALSE) {
+#if OS_EVENT_NAME_EN > 0u
+                 pevent->OSEventName   = (INT8U *)(void *)"?";
+#endif
+                 pcp                   = (INT8U)(pevent->OSEventCnt >> 8u);
+                 if (pcp != OS_PRIO_MUTEX_CEIL_DIS) {
+                     OSTCBPrioTbl[pcp] = (OS_TCB *)0;      /* Free up the PCP                          */
+                 }
+                 pevent->OSEventType   = OS_EVENT_TYPE_UNUSED;
+                 pevent->OSEventPtr    = OSEventFreeList;  /* Return Event Control Block to free list  */
+                 pevent->OSEventCnt    = 0u;
+                 OSEventFreeList       = pevent;
+                 OS_EXIT_CRITICAL();
+                 *perr                 = OS_ERR_NONE;
+                 pevent_return         = (OS_EVENT *)0;    /* Mutex has been deleted                   */
+             } else {
+                 OS_EXIT_CRITICAL();
+                 *perr                 = OS_ERR_TASK_WAITING;
+                 pevent_return         = pevent;
+             }
+             break;
+
+        case OS_DEL_ALWAYS:                                /* ALWAYS DELETE THE MUTEX ---------------- */
+             pcp  = (INT8U)(pevent->OSEventCnt >> 8u);                       /* Get PCP of mutex       */
+             if (pcp != OS_PRIO_MUTEX_CEIL_DIS) {
+                 prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get owner's orig prio  */
+                 ptcb = (OS_TCB *)pevent->OSEventPtr;
+                 if (ptcb != (OS_TCB *)0) {                /* See if any task owns the mutex           */
+                     if (ptcb->OSTCBPrio == pcp) {         /* See if original prio was changed         */
+                         OSMutex_RdyAtPrio(ptcb, prio);    /* Yes, Restore the task's original prio    */
+                     }
+                 }
+             }
+             while (pevent->OSEventGrp != 0u) {            /* Ready ALL tasks waiting for mutex        */
+                 (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_ABORT);
+             }
+#if OS_EVENT_NAME_EN > 0u
+             pevent->OSEventName   = (INT8U *)(void *)"?";
+#endif
+             pcp                   = (INT8U)(pevent->OSEventCnt >> 8u);
+             if (pcp != OS_PRIO_MUTEX_CEIL_DIS) {
+                 OSTCBPrioTbl[pcp] = (OS_TCB *)0;          /* Free up the PCP                          */
+             }
+             pevent->OSEventType   = OS_EVENT_TYPE_UNUSED;
+             pevent->OSEventPtr    = OSEventFreeList;      /* Return Event Control Block to free list  */
+             pevent->OSEventCnt    = 0u;
+             OSEventFreeList       = pevent;               /* Get next free event control block        */
+             OS_EXIT_CRITICAL();
+             if (tasks_waiting == OS_TRUE) {               /* Reschedule only if task(s) were waiting  */
+                 OS_Sched();                               /* Find highest priority task ready to run  */
+             }
+             *perr         = OS_ERR_NONE;
+             pevent_return = (OS_EVENT *)0;                /* Mutex has been deleted                   */
+             break;
+
+        default:
+             OS_EXIT_CRITICAL();
+             *perr         = OS_ERR_INVALID_OPT;
+             pevent_return = pevent;
+             break;
+    }
+    return (pevent_return);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                 PEND ON MUTUAL EXCLUSION SEMAPHORE
+*
+* Description: This function waits for a mutual exclusion semaphore.
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired
+*                            mutex.
+*
+*              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
+*                            wait for the resource up to the amount of time specified by this argument.
+*                            If you specify 0, however, your task will wait forever at the specified
+*                            mutex or, until the resource becomes available.
+*
+*              perr          is a pointer to where an error message will be deposited.  Possible error
+*                            messages are:
+*                               OS_ERR_NONE        The call was successful and your task owns the mutex
+*                               OS_ERR_TIMEOUT     The mutex was not available within the specified 'timeout'.
+*                               OS_ERR_PEND_ABORT  The wait on the mutex was aborted.
+*                               OS_ERR_EVENT_TYPE  If you didn't pass a pointer to a mutex
+*                               OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer
+*                               OS_ERR_PEND_ISR    If you called this function from an ISR and the result
+*                                                  would lead to a suspension.
+*                               OS_ERR_PCP_LOWER   If the priority of the task that owns the Mutex is
+*                                                  HIGHER (i.e. a lower number) than the PCP.  This error
+*                                                  indicates that you did not set the PCP higher (lower
+*                                                  number) than ALL the tasks that compete for the Mutex.
+*                                                  Unfortunately, this is something that could not be
+*                                                  detected when the Mutex is created because we don't know
+*                                                  what tasks will be using the Mutex.
+*                               OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
+*
+* Returns    : none
+*
+* Note(s)    : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex.
+*
+*              2) You MUST NOT change the priority of the task that owns the mutex
+*********************************************************************************************************
+*/
+
+void  OSMutexPend (OS_EVENT  *pevent,
+                   INT32U     timeout,
+                   INT8U     *perr)
+{
+    INT8U      pcp;                                        /* Priority Ceiling Priority (PCP)          */
+    INT8U      mprio;                                      /* Mutex owner priority                     */
+    BOOLEAN    rdy;                                        /* Flag indicating task was ready           */
+    OS_TCB    *ptcb;
+    OS_EVENT  *pevent2;
+    INT8U      y;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return;
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
+        *perr = OS_ERR_PEVENT_NULL;
+        return;
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) {      /* Validate event block type                */
+        *perr = OS_ERR_EVENT_TYPE;
+        return;
+    }
+    if (OSIntNesting > 0u) {                               /* See if called from ISR ...               */
+        *perr = OS_ERR_PEND_ISR;                           /* ... can't PEND from an ISR               */
+        return;
+    }
+    if (OSLockNesting > 0u) {                              /* See if called with scheduler locked ...  */
+        *perr = OS_ERR_PEND_LOCKED;                        /* ... can't PEND when locked               */
+        return;
+    }
+/*$PAGE*/
+    OS_ENTER_CRITICAL();
+    pcp = (INT8U)(pevent->OSEventCnt >> 8u);               /* Get PCP from mutex                       */
+                                                           /* Is Mutex available?                      */
+    if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {
+        pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;       /* Yes, Acquire the resource                */
+        pevent->OSEventCnt |= OSTCBCur->OSTCBPrio;         /*      Save priority of owning task        */
+        pevent->OSEventPtr  = (void *)OSTCBCur;            /*      Point to owning task's OS_TCB       */
+        if ((pcp != OS_PRIO_MUTEX_CEIL_DIS) &&
+            (OSTCBCur->OSTCBPrio <= pcp)) {                /*      PCP 'must' have a SMALLER prio ...  */
+             OS_EXIT_CRITICAL();                           /*      ... than current task!              */
+            *perr = OS_ERR_PCP_LOWER;
+        } else {
+             OS_EXIT_CRITICAL();
+            *perr = OS_ERR_NONE;
+        }
+        return;
+    }
+    if (pcp != OS_PRIO_MUTEX_CEIL_DIS) {
+        mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /*  Get priority of mutex owner   */
+        ptcb  = (OS_TCB *)(pevent->OSEventPtr);                   /*     Point to TCB of mutex owner   */
+        if (ptcb->OSTCBPrio > pcp) {                              /*     Need to promote prio of owner?*/
+            if (mprio > OSTCBCur->OSTCBPrio) {
+                y = ptcb->OSTCBY;
+                if ((OSRdyTbl[y] & ptcb->OSTCBBitX) != 0u) {      /*     See if mutex owner is ready   */
+                    OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX;     /*     Yes, Remove owner from Rdy ...*/
+                    if (OSRdyTbl[y] == 0u) {                      /*          ... list at current prio */
+                        OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
+                    }
+                    rdy = OS_TRUE;
+                } else {
+                    pevent2 = ptcb->OSTCBEventPtr;
+                    if (pevent2 != (OS_EVENT *)0) {               /* Remove from event wait list       */
+                        y = ptcb->OSTCBY;
+                        pevent2->OSEventTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX;
+                        if (pevent2->OSEventTbl[y] == 0u) {
+                            pevent2->OSEventGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
+                        }
+                    }
+                    rdy = OS_FALSE;                        /* No                                       */
+                }
+                ptcb->OSTCBPrio = pcp;                     /* Change owner task prio to PCP            */
+#if OS_LOWEST_PRIO <= 63u
+                ptcb->OSTCBY    = (INT8U)( ptcb->OSTCBPrio >> 3u);
+                ptcb->OSTCBX    = (INT8U)( ptcb->OSTCBPrio & 0x07u);
+#else
+                ptcb->OSTCBY    = (INT8U)((INT8U)(ptcb->OSTCBPrio >> 4u) & 0xFFu);
+                ptcb->OSTCBX    = (INT8U)( ptcb->OSTCBPrio & 0x0Fu);
+#endif
+                ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY);
+                ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX);
+
+                if (rdy == OS_TRUE) {                      /* If task was ready at owner's priority ...*/
+                    OSRdyGrp               |= ptcb->OSTCBBitY; /* ... make it ready at new priority.   */
+                    OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
+                } else {
+                    pevent2 = ptcb->OSTCBEventPtr;
+                    if (pevent2 != (OS_EVENT *)0) {        /* Add to event wait list                   */
+                        pevent2->OSEventGrp               |= ptcb->OSTCBBitY;
+                        pevent2->OSEventTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
+                    }
+                }
+                OSTCBPrioTbl[pcp] = ptcb;
+            }
+        }
+    }
+    OSTCBCur->OSTCBStat     |= OS_STAT_MUTEX;         /* Mutex not available, pend current task        */
+    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
+    OSTCBCur->OSTCBDly       = timeout;               /* Store timeout in current task's TCB           */
+    OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
+    OS_EXIT_CRITICAL();
+    OS_Sched();                                       /* Find next highest priority task ready         */
+    OS_ENTER_CRITICAL();
+    switch (OSTCBCur->OSTCBStatPend) {                /* See if we timed-out or aborted                */
+        case OS_STAT_PEND_OK:
+             *perr = OS_ERR_NONE;
+             break;
+
+        case OS_STAT_PEND_ABORT:
+             *perr = OS_ERR_PEND_ABORT;               /* Indicate that we aborted getting mutex        */
+             break;
+
+        case OS_STAT_PEND_TO:
+        default:
+             OS_EventTaskRemove(OSTCBCur, pevent);
+             *perr = OS_ERR_TIMEOUT;                  /* Indicate that we didn't get mutex within TO   */
+             break;
+    }
+    OSTCBCur->OSTCBStat          =  OS_STAT_RDY;      /* Set   task  status to ready                   */
+    OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;  /* Clear pend  status                            */
+    OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;    /* Clear event pointers                          */
+#if (OS_EVENT_MULTI_EN > 0u)
+    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
+#endif
+    OS_EXIT_CRITICAL();
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                POST TO A MUTUAL EXCLUSION SEMAPHORE
+*
+* Description: This function signals a mutual exclusion semaphore
+*
+* Arguments  : pevent              is a pointer to the event control block associated with the desired
+*                                  mutex.
+*
+* Returns    : OS_ERR_NONE             The call was successful and the mutex was signaled.
+*              OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a mutex
+*              OS_ERR_PEVENT_NULL      'pevent' is a NULL pointer
+*              OS_ERR_POST_ISR         Attempted to post from an ISR (not valid for MUTEXes)
+*              OS_ERR_NOT_MUTEX_OWNER  The task that did the post is NOT the owner of the MUTEX.
+*              OS_ERR_PCP_LOWER        If the priority of the new task that owns the Mutex is
+*                                      HIGHER (i.e. a lower number) than the PCP.  This error
+*                                      indicates that you did not set the PCP higher (lower
+*                                      number) than ALL the tasks that compete for the Mutex.
+*                                      Unfortunately, this is something that could not be
+*                                      detected when the Mutex is created because we don't know
+*                                      what tasks will be using the Mutex.
+*********************************************************************************************************
+*/
+
+INT8U  OSMutexPost (OS_EVENT *pevent)
+{
+    INT8U      pcp;                                   /* Priority ceiling priority                     */
+    INT8U      prio;
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    if (OSIntNesting > 0u) {                          /* See if called from ISR ...                    */
+        return (OS_ERR_POST_ISR);                     /* ... can't POST mutex from an ISR              */
+    }
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        return (OS_ERR_PEVENT_NULL);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type                     */
+        return (OS_ERR_EVENT_TYPE);
+    }
+    OS_ENTER_CRITICAL();
+    pcp  = (INT8U)(pevent->OSEventCnt >> 8u);         /* Get priority ceiling priority of mutex        */
+    prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);  /* Get owner's original priority      */
+    if (OSTCBCur != (OS_TCB *)pevent->OSEventPtr) {   /* See if posting task owns the MUTEX            */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_NOT_MUTEX_OWNER);
+    }
+    if (pcp != OS_PRIO_MUTEX_CEIL_DIS) {
+        if (OSTCBCur->OSTCBPrio == pcp) {             /* Did we have to raise current task's priority? */
+            OSMutex_RdyAtPrio(OSTCBCur, prio);        /* Restore the task's original priority          */
+        }
+        OSTCBPrioTbl[pcp] = OS_TCB_RESERVED;          /* Reserve table entry                           */
+    }
+    if (pevent->OSEventGrp != 0u) {                   /* Any task waiting for the mutex?               */
+                                                      /* Yes, Make HPT waiting for mutex ready         */
+        prio                = OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_OK);
+        pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;  /*      Save priority of mutex's new owner       */
+        pevent->OSEventCnt |= prio;
+        pevent->OSEventPtr  = OSTCBPrioTbl[prio];     /*      Link to new mutex owner's OS_TCB         */
+        if ((pcp  != OS_PRIO_MUTEX_CEIL_DIS) &&
+            (prio <= pcp)) {                          /*      PCP 'must' have a SMALLER prio ...       */
+            OS_EXIT_CRITICAL();                       /*      ... than current task!                   */
+            OS_Sched();                               /*      Find highest priority task ready to run  */
+            return (OS_ERR_PCP_LOWER);
+        } else {
+            OS_EXIT_CRITICAL();
+            OS_Sched();                               /*      Find highest priority task ready to run  */
+            return (OS_ERR_NONE);
+        }
+    }
+    pevent->OSEventCnt |= OS_MUTEX_AVAILABLE;         /* No,  Mutex is now available                   */
+    pevent->OSEventPtr  = (void *)0;
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                 QUERY A MUTUAL EXCLUSION SEMAPHORE
+*
+* Description: This function obtains information about a mutex
+*
+* Arguments  : pevent          is a pointer to the event control block associated with the desired mutex
+*
+*              p_mutex_data    is a pointer to a structure that will contain information about the mutex
+*
+* Returns    : OS_ERR_NONE          The call was successful and the message was sent
+*              OS_ERR_QUERY_ISR     If you called this function from an ISR
+*              OS_ERR_PEVENT_NULL   If 'pevent'       is a NULL pointer
+*              OS_ERR_PDATA_NULL    If 'p_mutex_data' is a NULL pointer
+*              OS_ERR_EVENT_TYPE    If you are attempting to obtain data from a non mutex.
+*********************************************************************************************************
+*/
+
+#if OS_MUTEX_QUERY_EN > 0u
+INT8U  OSMutexQuery (OS_EVENT       *pevent,
+                     OS_MUTEX_DATA  *p_mutex_data)
+{
+    INT8U       i;
+    OS_PRIO    *psrc;
+    OS_PRIO    *pdest;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR   cpu_sr = 0u;
+#endif
+
+
+
+    if (OSIntNesting > 0u) {                               /* See if called from ISR ...               */
+        return (OS_ERR_QUERY_ISR);                         /* ... can't QUERY mutex from an ISR        */
+    }
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
+        return (OS_ERR_PEVENT_NULL);
+    }
+    if (p_mutex_data == (OS_MUTEX_DATA *)0) {              /* Validate 'p_mutex_data'                  */
+        return (OS_ERR_PDATA_NULL);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) {      /* Validate event block type                */
+        return (OS_ERR_EVENT_TYPE);
+    }
+    OS_ENTER_CRITICAL();
+    p_mutex_data->OSMutexPCP  = (INT8U)(pevent->OSEventCnt >> 8u);
+    p_mutex_data->OSOwnerPrio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);
+    if (p_mutex_data->OSOwnerPrio == 0xFFu) {
+        p_mutex_data->OSValue = OS_TRUE;
+    } else {
+        p_mutex_data->OSValue = OS_FALSE;
+    }
+    p_mutex_data->OSEventGrp  = pevent->OSEventGrp;        /* Copy wait list                           */
+    psrc                      = &pevent->OSEventTbl[0];
+    pdest                     = &p_mutex_data->OSEventTbl[0];
+    for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
+        *pdest++ = *psrc++;
+    }
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif                                                     /* OS_MUTEX_QUERY_EN                        */
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                            RESTORE A TASK BACK TO ITS ORIGINAL PRIORITY
+*
+* Description: This function makes a task ready at the specified priority
+*
+* Arguments  : ptcb            is a pointer to OS_TCB of the task to make ready
+*
+*              prio            is the desired priority
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+static  void  OSMutex_RdyAtPrio (OS_TCB  *ptcb,
+                                 INT8U    prio)
+{
+    INT8U  y;
+
+
+    y            =  ptcb->OSTCBY;                          /* Remove owner from ready list at 'pcp'    */
+    OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX;
+    if (OSRdyTbl[y] == 0u) {
+        OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
+    }
+    ptcb->OSTCBPrio         = prio;
+    OSPrioCur               = prio;                        /* The current task is now at this priority */
+#if OS_LOWEST_PRIO <= 63u
+    ptcb->OSTCBY            = (INT8U)((INT8U)(prio >> 3u) & 0x07u);
+    ptcb->OSTCBX            = (INT8U)(prio & 0x07u);
+#else
+    ptcb->OSTCBY            = (INT8U)((INT8U)(prio >> 4u) & 0x0Fu);
+    ptcb->OSTCBX            = (INT8U) (prio & 0x0Fu);
+#endif
+    ptcb->OSTCBBitY         = (OS_PRIO)(1uL << ptcb->OSTCBY);
+    ptcb->OSTCBBitX         = (OS_PRIO)(1uL << ptcb->OSTCBX);
+    OSRdyGrp               |= ptcb->OSTCBBitY;             /* Make task ready at original priority     */
+    OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
+    OSTCBPrioTbl[prio]      = ptcb;
+}
+
+
+#endif                                                     /* OS_MUTEX_EN                              */

+ 901 - 0
MiddleWare/uCOS_II/uCOS-II/Source/os_q.c

@@ -0,0 +1,901 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                        MESSAGE QUEUE MANAGEMENT
+*
+*                              (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_Q.C
+* By      : Jean J. Labrosse
+* Version : V2.92.11
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#define  MICRIUM_SOURCE
+
+#ifndef  OS_MASTER_FILE
+#include <ucos_ii.h>
+#endif
+
+#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+/*
+*********************************************************************************************************
+*                                      ACCEPT MESSAGE FROM QUEUE
+*
+* Description: This function checks the queue to see if a message is available.  Unlike OSQPend(),
+*              OSQAccept() does not suspend the calling task if a message is not available.
+*
+* Arguments  : pevent        is a pointer to the event control block
+*
+*              perr          is a pointer to where an error message will be deposited.  Possible error
+*                            messages are:
+*
+*                            OS_ERR_NONE         The call was successful and your task received a
+*                                                message.
+*                            OS_ERR_EVENT_TYPE   You didn't pass a pointer to a queue
+*                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer
+*                            OS_ERR_Q_EMPTY      The queue did not contain any messages
+*
+* Returns    : != (void *)0  is the message in the queue if one is available.  The message is removed
+*                            from the so the next time OSQAccept() is called, the queue will contain
+*                            one less entry.
+*              == (void *)0  if you received a NULL pointer message
+*                            if the queue is empty or,
+*                            if 'pevent' is a NULL pointer or,
+*                            if you passed an invalid event type
+*
+* Note(s)    : As of V2.60, you can now pass NULL pointers through queues.  Because of this, the argument
+*              'perr' has been added to the API to tell you about the outcome of the call.
+*********************************************************************************************************
+*/
+
+#if OS_Q_ACCEPT_EN > 0u
+void  *OSQAccept (OS_EVENT  *pevent,
+                  INT8U     *perr)
+{
+    void      *pmsg;
+    OS_Q      *pq;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((void *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {               /* Validate 'pevent'                                  */
+        *perr = OS_ERR_PEVENT_NULL;
+        return ((void *)0);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type                          */
+        *perr = OS_ERR_EVENT_TYPE;
+        return ((void *)0);
+    }
+    OS_ENTER_CRITICAL();
+    pq = (OS_Q *)pevent->OSEventPtr;             /* Point at queue control block                       */
+    if (pq->OSQEntries > 0u) {                   /* See if any messages in the queue                   */
+        pmsg = *pq->OSQOut++;                    /* Yes, extract oldest message from the queue         */
+        pq->OSQEntries--;                        /* Update the number of entries in the queue          */
+        if (pq->OSQOut == pq->OSQEnd) {          /* Wrap OUT pointer if we are at the end of the queue */
+            pq->OSQOut = pq->OSQStart;
+        }
+        *perr = OS_ERR_NONE;
+    } else {
+        *perr = OS_ERR_Q_EMPTY;
+        pmsg  = (void *)0;                       /* Queue is empty                                     */
+    }
+    OS_EXIT_CRITICAL();
+    return (pmsg);                               /* Return message received (or NULL)                  */
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       CREATE A MESSAGE QUEUE
+*
+* Description: This function creates a message queue if free event control blocks are available.
+*
+* Arguments  : start         is a pointer to the base address of the message queue storage area.  The
+*                            storage area MUST be declared as an array of pointers to 'void' as follows
+*
+*                            void *MessageStorage[size]
+*
+*              size          is the number of elements in the storage area
+*
+* Returns    : != (OS_EVENT *)0  is a pointer to the event control clock (OS_EVENT) associated with the
+*                                created queue
+*              == (OS_EVENT *)0  if no event control blocks were available or an error was detected
+*********************************************************************************************************
+*/
+
+OS_EVENT  *OSQCreate (void    **start,
+                      INT16U    size)
+{
+    OS_EVENT  *pevent;
+    OS_Q      *pq;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    if (OSSafetyCriticalStartFlag == OS_TRUE) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_EVENT *)0);
+    }
+#endif
+
+    if (OSIntNesting > 0u) {                     /* See if called from ISR ...                         */
+        return ((OS_EVENT *)0);                  /* ... can't CREATE from an ISR                       */
+    }
+    OS_ENTER_CRITICAL();
+    pevent = OSEventFreeList;                    /* Get next free event control block                  */
+    if (OSEventFreeList != (OS_EVENT *)0) {      /* See if pool of free ECB pool was empty             */
+        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
+    }
+    OS_EXIT_CRITICAL();
+    if (pevent != (OS_EVENT *)0) {               /* See if we have an event control block              */
+        OS_ENTER_CRITICAL();
+        pq = OSQFreeList;                        /* Get a free queue control block                     */
+        if (pq != (OS_Q *)0) {                   /* Were we able to get a queue control block ?        */
+            OSQFreeList            = OSQFreeList->OSQPtr; /* Yes, Adjust free list pointer to next free*/
+            OS_EXIT_CRITICAL();
+            pq->OSQStart           = start;               /*      Initialize the queue                 */
+            pq->OSQEnd             = &start[size];
+            pq->OSQIn              = start;
+            pq->OSQOut             = start;
+            pq->OSQSize            = size;
+            pq->OSQEntries         = 0u;
+            pevent->OSEventType    = OS_EVENT_TYPE_Q;
+            pevent->OSEventCnt     = 0u;
+            pevent->OSEventPtr     = pq;
+#if OS_EVENT_NAME_EN > 0u
+            pevent->OSEventName    = (INT8U *)(void *)"?";
+#endif
+            OS_EventWaitListInit(pevent);                 /*      Initialize the wait list             */
+        } else {
+            pevent->OSEventPtr = (void *)OSEventFreeList; /* No,  Return event control block on error  */
+            OSEventFreeList    = pevent;
+            OS_EXIT_CRITICAL();
+            pevent = (OS_EVENT *)0;
+        }
+    }
+    return (pevent);
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       DELETE A MESSAGE QUEUE
+*
+* Description: This function deletes a message queue and readies all tasks pending on the queue.
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired
+*                            queue.
+*
+*              opt           determines delete options as follows:
+*                            opt == OS_DEL_NO_PEND   Delete the queue ONLY if no task pending
+*                            opt == OS_DEL_ALWAYS    Deletes the queue even if tasks are waiting.
+*                                                    In this case, all the tasks pending will be readied.
+*
+*              perr          is a pointer to an error code that can contain one of the following values:
+*                            OS_ERR_NONE             The call was successful and the queue was deleted
+*                            OS_ERR_DEL_ISR          If you tried to delete the queue from an ISR
+*                            OS_ERR_INVALID_OPT      An invalid option was specified
+*                            OS_ERR_TASK_WAITING     One or more tasks were waiting on the queue
+*                            OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a queue
+*                            OS_ERR_PEVENT_NULL      If 'pevent' is a NULL pointer.
+*
+* Returns    : pevent        upon error
+*              (OS_EVENT *)0 if the queue was successfully deleted.
+*
+* Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
+*                 the queue MUST check the return code of OSQPend().
+*              2) OSQAccept() callers will not know that the intended queue has been deleted unless
+*                 they check 'pevent' to see that it's a NULL pointer.
+*              3) This call can potentially disable interrupts for a long time.  The interrupt disable
+*                 time is directly proportional to the number of tasks waiting on the queue.
+*              4) Because ALL tasks pending on the queue will be readied, you MUST be careful in
+*                 applications where the queue is used for mutual exclusion because the resource(s)
+*                 will no longer be guarded by the queue.
+*              5) If the storage for the message queue was allocated dynamically (i.e. using a malloc()
+*                 type call) then your application MUST release the memory storage by call the counterpart
+*                 call of the dynamic allocation scheme used.  If the queue storage was created statically
+*                 then, the storage can be reused.
+*              6) All tasks that were waiting for the queue will be readied and returned an 
+*                 OS_ERR_PEND_ABORT if OSQDel() was called with OS_DEL_ALWAYS
+*********************************************************************************************************
+*/
+
+#if OS_Q_DEL_EN > 0u
+OS_EVENT  *OSQDel (OS_EVENT  *pevent,
+                   INT8U      opt,
+                   INT8U     *perr)
+{
+    BOOLEAN    tasks_waiting;
+    OS_EVENT  *pevent_return;
+    OS_Q      *pq;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_EVENT *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
+        *perr = OS_ERR_PEVENT_NULL;
+        return (pevent);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {          /* Validate event block type                */
+        *perr = OS_ERR_EVENT_TYPE;
+        return (pevent);
+    }
+    if (OSIntNesting > 0u) {                               /* See if called from ISR ...               */
+        *perr = OS_ERR_DEL_ISR;                            /* ... can't DELETE from an ISR             */
+        return (pevent);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                        /* See if any tasks waiting on queue        */
+        tasks_waiting = OS_TRUE;                           /* Yes                                      */
+    } else {
+        tasks_waiting = OS_FALSE;                          /* No                                       */
+    }
+    switch (opt) {
+        case OS_DEL_NO_PEND:                               /* Delete queue only if no task waiting     */
+             if (tasks_waiting == OS_FALSE) {
+#if OS_EVENT_NAME_EN > 0u
+                 pevent->OSEventName    = (INT8U *)(void *)"?";
+#endif
+                 pq                     = (OS_Q *)pevent->OSEventPtr;  /* Return OS_Q to free list     */
+                 pq->OSQPtr             = OSQFreeList;
+                 OSQFreeList            = pq;
+                 pevent->OSEventType    = OS_EVENT_TYPE_UNUSED;
+                 pevent->OSEventPtr     = OSEventFreeList; /* Return Event Control Block to free list  */
+                 pevent->OSEventCnt     = 0u;
+                 OSEventFreeList        = pevent;          /* Get next free event control block        */
+                 OS_EXIT_CRITICAL();
+                 *perr                  = OS_ERR_NONE;
+                 pevent_return          = (OS_EVENT *)0;   /* Queue has been deleted                   */
+             } else {
+                 OS_EXIT_CRITICAL();
+                 *perr                  = OS_ERR_TASK_WAITING;
+                 pevent_return          = pevent;
+             }
+             break;
+
+        case OS_DEL_ALWAYS:                                /* Always delete the queue                  */
+             while (pevent->OSEventGrp != 0u) {            /* Ready ALL tasks waiting for queue        */
+                 (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT);
+             }
+#if OS_EVENT_NAME_EN > 0u
+             pevent->OSEventName    = (INT8U *)(void *)"?";
+#endif
+             pq                     = (OS_Q *)pevent->OSEventPtr;   /* Return OS_Q to free list        */
+             pq->OSQPtr             = OSQFreeList;
+             OSQFreeList            = pq;
+             pevent->OSEventType    = OS_EVENT_TYPE_UNUSED;
+             pevent->OSEventPtr     = OSEventFreeList;     /* Return Event Control Block to free list  */
+             pevent->OSEventCnt     = 0u;
+             OSEventFreeList        = pevent;              /* Get next free event control block        */
+             OS_EXIT_CRITICAL();
+             if (tasks_waiting == OS_TRUE) {               /* Reschedule only if task(s) were waiting  */
+                 OS_Sched();                               /* Find highest priority task ready to run  */
+             }
+             *perr                  = OS_ERR_NONE;
+             pevent_return          = (OS_EVENT *)0;       /* Queue has been deleted                   */
+             break;
+
+        default:
+             OS_EXIT_CRITICAL();
+             *perr                  = OS_ERR_INVALID_OPT;
+             pevent_return          = pevent;
+             break;
+    }
+    return (pevent_return);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                             FLUSH QUEUE
+*
+* Description : This function is used to flush the contents of the message queue.
+*
+* Arguments   : none
+*
+* Returns     : OS_ERR_NONE         upon success
+*               OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a queue
+*               OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer
+*
+* WARNING     : You should use this function with great care because, when to flush the queue, you LOOSE
+*               the references to what the queue entries are pointing to and thus, you could cause
+*               'memory leaks'.  In other words, the data you are pointing to that's being referenced
+*               by the queue entries should, most likely, need to be de-allocated (i.e. freed).
+*********************************************************************************************************
+*/
+
+#if OS_Q_FLUSH_EN > 0u
+INT8U  OSQFlush (OS_EVENT *pevent)
+{
+    OS_Q      *pq;
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        return (OS_ERR_PEVENT_NULL);
+    }
+    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* Validate event block type                     */
+        return (OS_ERR_EVENT_TYPE);
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    pq             = (OS_Q *)pevent->OSEventPtr;      /* Point to queue storage structure              */
+    pq->OSQIn      = pq->OSQStart;
+    pq->OSQOut     = pq->OSQStart;
+    pq->OSQEntries = 0u;
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                    PEND ON A QUEUE FOR A MESSAGE
+*
+* Description: This function waits for a message to be sent to a queue
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired queue
+*
+*              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
+*                            wait for a message to arrive at the queue up to the amount of time
+*                            specified by this argument.  If you specify 0, however, your task will wait
+*                            forever at the specified queue or, until a message arrives.
+*
+*              perr          is a pointer to where an error message will be deposited.  Possible error
+*                            messages are:
+*
+*                            OS_ERR_NONE         The call was successful and your task received a
+*                                                message.
+*                            OS_ERR_TIMEOUT      A message was not received within the specified 'timeout'.
+*                            OS_ERR_PEND_ABORT   The wait on the queue was aborted.
+*                            OS_ERR_EVENT_TYPE   You didn't pass a pointer to a queue
+*                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer
+*                            OS_ERR_PEND_ISR     If you called this function from an ISR and the result
+*                                                would lead to a suspension.
+*                            OS_ERR_PEND_LOCKED  If you called this function with the scheduler is locked
+*
+* Returns    : != (void *)0  is a pointer to the message received
+*              == (void *)0  if you received a NULL pointer message or,
+*                            if no message was received or,
+*                            if 'pevent' is a NULL pointer or,
+*                            if you didn't pass a pointer to a queue.
+*
+* Note(s)    : As of V2.60, this function allows you to receive NULL pointer messages.
+*********************************************************************************************************
+*/
+
+void  *OSQPend (OS_EVENT  *pevent,
+                INT32U     timeout,
+                INT8U     *perr)
+{
+    void      *pmsg;
+    OS_Q      *pq;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((void *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {               /* Validate 'pevent'                                  */
+        *perr = OS_ERR_PEVENT_NULL;
+        return ((void *)0);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type                          */
+        *perr = OS_ERR_EVENT_TYPE;
+        return ((void *)0);
+    }
+    if (OSIntNesting > 0u) {                     /* See if called from ISR ...                         */
+        *perr = OS_ERR_PEND_ISR;                 /* ... can't PEND from an ISR                         */
+        return ((void *)0);
+    }
+    if (OSLockNesting > 0u) {                    /* See if called with scheduler locked ...            */
+        *perr = OS_ERR_PEND_LOCKED;              /* ... can't PEND when locked                         */
+        return ((void *)0);
+    }
+    OS_ENTER_CRITICAL();
+    pq = (OS_Q *)pevent->OSEventPtr;             /* Point at queue control block                       */
+    if (pq->OSQEntries > 0u) {                   /* See if any messages in the queue                   */
+        pmsg = *pq->OSQOut++;                    /* Yes, extract oldest message from the queue         */
+        pq->OSQEntries--;                        /* Update the number of entries in the queue          */
+        if (pq->OSQOut == pq->OSQEnd) {          /* Wrap OUT pointer if we are at the end of the queue */
+            pq->OSQOut = pq->OSQStart;
+        }
+        OS_EXIT_CRITICAL();
+        *perr = OS_ERR_NONE;
+        return (pmsg);                           /* Return message received                            */
+    }
+    OSTCBCur->OSTCBStat     |= OS_STAT_Q;        /* Task will have to pend for a message to be posted  */
+    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
+    OSTCBCur->OSTCBDly       = timeout;          /* Load timeout into TCB                              */
+    OS_EventTaskWait(pevent);                    /* Suspend task until event or timeout occurs         */
+    OS_EXIT_CRITICAL();
+    OS_Sched();                                  /* Find next highest priority task ready to run       */
+    OS_ENTER_CRITICAL();
+    switch (OSTCBCur->OSTCBStatPend) {                /* See if we timed-out or aborted                */
+        case OS_STAT_PEND_OK:                         /* Extract message from TCB (Put there by QPost) */
+             pmsg =  OSTCBCur->OSTCBMsg;
+            *perr =  OS_ERR_NONE;
+             break;
+
+        case OS_STAT_PEND_ABORT:
+             pmsg = (void *)0;
+            *perr =  OS_ERR_PEND_ABORT;               /* Indicate that we aborted                      */
+             break;
+
+        case OS_STAT_PEND_TO:
+        default:
+             OS_EventTaskRemove(OSTCBCur, pevent);
+             pmsg = (void *)0;
+            *perr =  OS_ERR_TIMEOUT;                  /* Indicate that we didn't get event within TO   */
+             break;
+    }
+    OSTCBCur->OSTCBStat          =  OS_STAT_RDY;      /* Set   task  status to ready                   */
+    OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;  /* Clear pend  status                            */
+    OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;    /* Clear event pointers                          */
+#if (OS_EVENT_MULTI_EN > 0u)
+    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
+#endif
+    OSTCBCur->OSTCBMsg           = (void      *)0;    /* Clear  received message                       */
+    OS_EXIT_CRITICAL();
+    return (pmsg);                                    /* Return received message                       */
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                  ABORT WAITING ON A MESSAGE QUEUE
+*
+* Description: This function aborts & readies any tasks currently waiting on a queue.  This function
+*              should be used to fault-abort the wait on the queue, rather than to normally signal
+*              the queue via OSQPost(), OSQPostFront() or OSQPostOpt().
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired queue.
+*
+*              opt           determines the type of ABORT performed:
+*                            OS_PEND_OPT_NONE         ABORT wait for a single task (HPT) waiting on the
+*                                                     queue
+*                            OS_PEND_OPT_BROADCAST    ABORT wait for ALL tasks that are  waiting on the
+*                                                     queue
+*
+*              perr          is a pointer to where an error message will be deposited.  Possible error
+*                            messages are:
+*
+*                            OS_ERR_NONE         No tasks were     waiting on the queue.
+*                            OS_ERR_PEND_ABORT   At least one task waiting on the queue was readied
+*                                                and informed of the aborted wait; check return value
+*                                                for the number of tasks whose wait on the queue
+*                                                was aborted.
+*                            OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a queue.
+*                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
+*
+* Returns    : == 0          if no tasks were waiting on the queue, or upon error.
+*              >  0          if one or more tasks waiting on the queue are now readied and informed.
+*********************************************************************************************************
+*/
+
+#if OS_Q_PEND_ABORT_EN > 0u
+INT8U  OSQPendAbort (OS_EVENT  *pevent,
+                     INT8U      opt,
+                     INT8U     *perr)
+{
+    INT8U      nbr_tasks;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
+        *perr = OS_ERR_PEVENT_NULL;
+        return (0u);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {          /* Validate event block type                */
+        *perr = OS_ERR_EVENT_TYPE;
+        return (0u);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                        /* See if any task waiting on queue?        */
+        nbr_tasks = 0u;
+        switch (opt) {
+            case OS_PEND_OPT_BROADCAST:                    /* Do we need to abort ALL waiting tasks?   */
+                 while (pevent->OSEventGrp != 0u) {        /* Yes, ready ALL tasks waiting on queue    */
+                     (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT);
+                     nbr_tasks++;
+                 }
+                 break;
+
+            case OS_PEND_OPT_NONE:
+            default:                                       /* No,  ready HPT       waiting on queue    */
+                 (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT);
+                 nbr_tasks++;
+                 break;
+        }
+        OS_EXIT_CRITICAL();
+        OS_Sched();                                        /* Find HPT ready to run                    */
+        *perr = OS_ERR_PEND_ABORT;
+        return (nbr_tasks);
+    }
+    OS_EXIT_CRITICAL();
+    *perr = OS_ERR_NONE;
+    return (0u);                                           /* No tasks waiting on queue                */
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       POST MESSAGE TO A QUEUE
+*
+* Description: This function sends a message to a queue
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired queue
+*
+*              pmsg          is a pointer to the message to send.
+*
+* Returns    : OS_ERR_NONE           The call was successful and the message was sent
+*              OS_ERR_Q_FULL         If the queue cannot accept any more messages because it is full.
+*              OS_ERR_EVENT_TYPE     If you didn't pass a pointer to a queue.
+*              OS_ERR_PEVENT_NULL    If 'pevent' is a NULL pointer
+*
+* Note(s)    : As of V2.60, this function allows you to send NULL pointer messages.
+*********************************************************************************************************
+*/
+
+#if OS_Q_POST_EN > 0u
+INT8U  OSQPost (OS_EVENT  *pevent,
+                void      *pmsg)
+{
+    OS_Q      *pq;
+#if OS_CRITICAL_METHOD == 3u                           /* Allocate storage for CPU status register     */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                     /* Validate 'pevent'                            */
+        return (OS_ERR_PEVENT_NULL);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {      /* Validate event block type                    */
+        return (OS_ERR_EVENT_TYPE);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                    /* See if any task pending on queue             */
+                                                       /* Ready highest priority task waiting on event */
+        (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
+        OS_EXIT_CRITICAL();
+        OS_Sched();                                    /* Find highest priority task ready to run      */
+        return (OS_ERR_NONE);
+    }
+    pq = (OS_Q *)pevent->OSEventPtr;                   /* Point to queue control block                 */
+    if (pq->OSQEntries >= pq->OSQSize) {               /* Make sure queue is not full                  */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_Q_FULL);
+    }
+    *pq->OSQIn++ = pmsg;                               /* Insert message into queue                    */
+    pq->OSQEntries++;                                  /* Update the nbr of entries in the queue       */
+    if (pq->OSQIn == pq->OSQEnd) {                     /* Wrap IN ptr if we are at end of queue        */
+        pq->OSQIn = pq->OSQStart;
+    }
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                POST MESSAGE TO THE FRONT OF A QUEUE
+*
+* Description: This function sends a message to a queue but unlike OSQPost(), the message is posted at
+*              the front instead of the end of the queue.  Using OSQPostFront() allows you to send
+*              'priority' messages.
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired queue
+*
+*              pmsg          is a pointer to the message to send.
+*
+* Returns    : OS_ERR_NONE           The call was successful and the message was sent
+*              OS_ERR_Q_FULL         If the queue cannot accept any more messages because it is full.
+*              OS_ERR_EVENT_TYPE     If you didn't pass a pointer to a queue.
+*              OS_ERR_PEVENT_NULL    If 'pevent' is a NULL pointer
+*
+* Note(s)    : As of V2.60, this function allows you to send NULL pointer messages.
+*********************************************************************************************************
+*/
+
+#if OS_Q_POST_FRONT_EN > 0u
+INT8U  OSQPostFront (OS_EVENT  *pevent,
+                     void      *pmsg)
+{
+    OS_Q      *pq;
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        return (OS_ERR_PEVENT_NULL);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* Validate event block type                     */
+        return (OS_ERR_EVENT_TYPE);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                   /* See if any task pending on queue              */
+                                                      /* Ready highest priority task waiting on event  */
+        (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
+        OS_EXIT_CRITICAL();
+        OS_Sched();                                   /* Find highest priority task ready to run       */
+        return (OS_ERR_NONE);
+    }
+    pq = (OS_Q *)pevent->OSEventPtr;                  /* Point to queue control block                  */
+    if (pq->OSQEntries >= pq->OSQSize) {              /* Make sure queue is not full                   */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_Q_FULL);
+    }
+    if (pq->OSQOut == pq->OSQStart) {                 /* Wrap OUT ptr if we are at the 1st queue entry */
+        pq->OSQOut = pq->OSQEnd;
+    }
+    pq->OSQOut--;
+    *pq->OSQOut = pmsg;                               /* Insert message into queue                     */
+    pq->OSQEntries++;                                 /* Update the nbr of entries in the queue        */
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       POST MESSAGE TO A QUEUE
+*
+* Description: This function sends a message to a queue.  This call has been added to reduce code size
+*              since it can replace both OSQPost() and OSQPostFront().  Also, this function adds the
+*              capability to broadcast a message to ALL tasks waiting on the message queue.
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired queue
+*
+*              pmsg          is a pointer to the message to send.
+*
+*              opt           determines the type of POST performed:
+*                            OS_POST_OPT_NONE         POST to a single waiting task
+*                                                     (Identical to OSQPost())
+*                            OS_POST_OPT_BROADCAST    POST to ALL tasks that are waiting on the queue
+*                            OS_POST_OPT_FRONT        POST as LIFO (Simulates OSQPostFront())
+*                            OS_POST_OPT_NO_SCHED     Indicates that the scheduler will NOT be invoked
+*
+* Returns    : OS_ERR_NONE           The call was successful and the message was sent
+*              OS_ERR_Q_FULL         If the queue cannot accept any more messages because it is full.
+*              OS_ERR_EVENT_TYPE     If you didn't pass a pointer to a queue.
+*              OS_ERR_PEVENT_NULL    If 'pevent' is a NULL pointer
+*
+* Warning    : Interrupts can be disabled for a long time if you do a 'broadcast'.  In fact, the
+*              interrupt disable time is proportional to the number of tasks waiting on the queue.
+*********************************************************************************************************
+*/
+
+#if OS_Q_POST_OPT_EN > 0u
+INT8U  OSQPostOpt (OS_EVENT  *pevent,
+                   void      *pmsg,
+                   INT8U      opt)
+{
+    OS_Q      *pq;
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        return (OS_ERR_PEVENT_NULL);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* Validate event block type                     */
+        return (OS_ERR_EVENT_TYPE);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0x00u) {                /* See if any task pending on queue              */
+        if ((opt & OS_POST_OPT_BROADCAST) != 0x00u) { /* Do we need to post msg to ALL waiting tasks ? */
+            while (pevent->OSEventGrp != 0u) {        /* Yes, Post to ALL tasks waiting on queue       */
+                (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
+            }
+        } else {                                      /* No,  Post to HPT waiting on queue             */
+            (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
+        }
+        OS_EXIT_CRITICAL();
+        if ((opt & OS_POST_OPT_NO_SCHED) == 0u) {     /* See if scheduler needs to be invoked          */
+            OS_Sched();                               /* Find highest priority task ready to run       */
+        }
+        return (OS_ERR_NONE);
+    }
+    pq = (OS_Q *)pevent->OSEventPtr;                  /* Point to queue control block                  */
+    if (pq->OSQEntries >= pq->OSQSize) {              /* Make sure queue is not full                   */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_Q_FULL);
+    }
+    if ((opt & OS_POST_OPT_FRONT) != 0x00u) {         /* Do we post to the FRONT of the queue?         */
+        if (pq->OSQOut == pq->OSQStart) {             /* Yes, Post as LIFO, Wrap OUT pointer if we ... */
+            pq->OSQOut = pq->OSQEnd;                  /*      ... are at the 1st queue entry           */
+        }
+        pq->OSQOut--;
+        *pq->OSQOut = pmsg;                           /*      Insert message into queue                */
+    } else {                                          /* No,  Post as FIFO                             */
+        *pq->OSQIn++ = pmsg;                          /*      Insert message into queue                */
+        if (pq->OSQIn == pq->OSQEnd) {                /*      Wrap IN ptr if we are at end of queue    */
+            pq->OSQIn = pq->OSQStart;
+        }
+    }
+    pq->OSQEntries++;                                 /* Update the nbr of entries in the queue        */
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                        QUERY A MESSAGE QUEUE
+*
+* Description: This function obtains information about a message queue.
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired queue
+*
+*              p_q_data      is a pointer to a structure that will contain information about the message
+*                            queue.
+*
+* Returns    : OS_ERR_NONE         The call was successful and the message was sent
+*              OS_ERR_EVENT_TYPE   If you are attempting to obtain data from a non queue.
+*              OS_ERR_PEVENT_NULL  If 'pevent'   is a NULL pointer
+*              OS_ERR_PDATA_NULL   If 'p_q_data' is a NULL pointer
+*********************************************************************************************************
+*/
+
+#if OS_Q_QUERY_EN > 0u
+INT8U  OSQQuery (OS_EVENT  *pevent,
+                 OS_Q_DATA *p_q_data)
+{
+    OS_Q       *pq;
+    INT8U       i;
+    OS_PRIO    *psrc;
+    OS_PRIO    *pdest;
+#if OS_CRITICAL_METHOD == 3u                           /* Allocate storage for CPU status register     */
+    OS_CPU_SR   cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                     /* Validate 'pevent'                            */
+        return (OS_ERR_PEVENT_NULL);
+    }
+    if (p_q_data == (OS_Q_DATA *)0) {                  /* Validate 'p_q_data'                          */
+        return (OS_ERR_PDATA_NULL);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {      /* Validate event block type                    */
+        return (OS_ERR_EVENT_TYPE);
+    }
+    OS_ENTER_CRITICAL();
+    p_q_data->OSEventGrp = pevent->OSEventGrp;         /* Copy message queue wait list                 */
+    psrc                 = &pevent->OSEventTbl[0];
+    pdest                = &p_q_data->OSEventTbl[0];
+    for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
+        *pdest++ = *psrc++;
+    }
+    pq = (OS_Q *)pevent->OSEventPtr;
+    if (pq->OSQEntries > 0u) {
+        p_q_data->OSMsg = *pq->OSQOut;                 /* Get next message to return if available      */
+    } else {
+        p_q_data->OSMsg = (void *)0;
+    }
+    p_q_data->OSNMsgs = pq->OSQEntries;
+    p_q_data->OSQSize = pq->OSQSize;
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif                                                 /* OS_Q_QUERY_EN                                */
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                     QUEUE MODULE INITIALIZATION
+*
+* Description : This function is called by uC/OS-II to initialize the message queue module.  Your
+*               application MUST NOT call this function.
+*
+* Arguments   :  none
+*
+* Returns     : none
+*
+* Note(s)    : This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+
+void  OS_QInit (void)
+{
+#if OS_MAX_QS == 1u
+    OSQFreeList         = &OSQTbl[0];                /* Only ONE queue!                                */
+    OSQFreeList->OSQPtr = (OS_Q *)0;
+#endif
+
+#if OS_MAX_QS >= 2u
+    INT16U   ix;
+    INT16U   ix_next;
+    OS_Q    *pq1;
+    OS_Q    *pq2;
+
+
+
+    OS_MemClr((INT8U *)&OSQTbl[0], sizeof(OSQTbl));  /* Clear the queue table                          */
+    for (ix = 0u; ix < (OS_MAX_QS - 1u); ix++) {     /* Init. list of free QUEUE control blocks        */
+        ix_next = ix + 1u;
+        pq1 = &OSQTbl[ix];
+        pq2 = &OSQTbl[ix_next];
+        pq1->OSQPtr = pq2;
+    }
+    pq1         = &OSQTbl[ix];
+    pq1->OSQPtr = (OS_Q *)0;
+    OSQFreeList = &OSQTbl[0];
+#endif
+}
+#endif                                               /* OS_Q_EN                                        */

+ 637 - 0
MiddleWare/uCOS_II/uCOS-II/Source/os_sem.c

@@ -0,0 +1,637 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                          SEMAPHORE MANAGEMENT
+*
+*                              (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_SEM.C
+* By      : Jean J. Labrosse
+* Version : V2.92.11
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#define  MICRIUM_SOURCE
+
+#ifndef  OS_MASTER_FILE
+#include <ucos_ii.h>
+#endif
+
+#if OS_SEM_EN > 0u
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                          ACCEPT SEMAPHORE
+*
+* Description: This function checks the semaphore to see if a resource is available or, if an event
+*              occurred.  Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
+*              resource is not available or the event did not occur.
+*
+* Arguments  : pevent     is a pointer to the event control block
+*
+* Returns    : >  0       if the resource is available or the event did not occur the semaphore is
+*                         decremented to obtain the resource.
+*              == 0       if the resource is not available or the event did not occur or,
+*                         if 'pevent' is a NULL pointer or,
+*                         if you didn't pass a pointer to a semaphore
+*********************************************************************************************************
+*/
+
+#if OS_SEM_ACCEPT_EN > 0u
+INT16U  OSSemAccept (OS_EVENT *pevent)
+{
+    INT16U     cnt;
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        return (0u);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
+        return (0u);
+    }
+    OS_ENTER_CRITICAL();
+    cnt = pevent->OSEventCnt;
+    if (cnt > 0u) {                                   /* See if resource is available                  */
+        pevent->OSEventCnt--;                         /* Yes, decrement semaphore and notify caller    */
+    }
+    OS_EXIT_CRITICAL();
+    return (cnt);                                     /* Return semaphore count                        */
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                         CREATE A SEMAPHORE
+*
+* Description: This function creates a semaphore.
+*
+* Arguments  : cnt           is the initial value for the semaphore.  If the value is 0, no resource is
+*                            available (or no event has occurred).  You initialize the semaphore to a
+*                            non-zero value to specify how many resources are available (e.g. if you have
+*                            10 resources, you would initialize the semaphore to 10).
+*
+* Returns    : != (void *)0  is a pointer to the event control block (OS_EVENT) associated with the
+*                            created semaphore
+*              == (void *)0  if no event control blocks were available
+*********************************************************************************************************
+*/
+
+OS_EVENT  *OSSemCreate (INT16U cnt)
+{
+    OS_EVENT  *pevent;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    if (OSSafetyCriticalStartFlag == OS_TRUE) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_EVENT *)0);
+    }
+#endif
+
+    if (OSIntNesting > 0u) {                               /* See if called from ISR ...               */
+        return ((OS_EVENT *)0);                            /* ... can't CREATE from an ISR             */
+    }
+    OS_ENTER_CRITICAL();
+    pevent = OSEventFreeList;                              /* Get next free event control block        */
+    if (OSEventFreeList != (OS_EVENT *)0) {                /* See if pool of free ECB pool was empty   */
+        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
+    }
+    OS_EXIT_CRITICAL();
+    if (pevent != (OS_EVENT *)0) {                         /* Get an event control block               */
+        pevent->OSEventType    = OS_EVENT_TYPE_SEM;
+        pevent->OSEventCnt     = cnt;                      /* Set semaphore value                      */
+        pevent->OSEventPtr     = (void *)0;                /* Unlink from ECB free list                */
+#if OS_EVENT_NAME_EN > 0u
+        pevent->OSEventName    = (INT8U *)(void *)"?";
+#endif
+        OS_EventWaitListInit(pevent);                      /* Initialize to 'nobody waiting' on sem.   */
+    }
+    return (pevent);
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                         DELETE A SEMAPHORE
+*
+* Description: This function deletes a semaphore and readies all tasks pending on the semaphore.
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired
+*                            semaphore.
+*
+*              opt           determines delete options as follows:
+*                            opt == OS_DEL_NO_PEND   Delete semaphore ONLY if no task pending
+*                            opt == OS_DEL_ALWAYS    Deletes the semaphore even if tasks are waiting.
+*                                                    In this case, all the tasks pending will be readied.
+*
+*              perr          is a pointer to an error code that can contain one of the following values:
+*                            OS_ERR_NONE             The call was successful and the semaphore was deleted
+*                            OS_ERR_DEL_ISR          If you attempted to delete the semaphore from an ISR
+*                            OS_ERR_INVALID_OPT      An invalid option was specified
+*                            OS_ERR_TASK_WAITING     One or more tasks were waiting on the semaphore
+*                            OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a semaphore
+*                            OS_ERR_PEVENT_NULL      If 'pevent' is a NULL pointer.
+*
+* Returns    : pevent        upon error
+*              (OS_EVENT *)0 if the semaphore was successfully deleted.
+*
+* Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
+*                 the semaphore MUST check the return code of OSSemPend().
+*              2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless
+*                 they check 'pevent' to see that it's a NULL pointer.
+*              3) This call can potentially disable interrupts for a long time.  The interrupt disable
+*                 time is directly proportional to the number of tasks waiting on the semaphore.
+*              4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in
+*                 applications where the semaphore is used for mutual exclusion because the resource(s)
+*                 will no longer be guarded by the semaphore.
+*              5) All tasks that were waiting for the semaphore will be readied and returned an 
+*                 OS_ERR_PEND_ABORT if OSSemDel() was called with OS_DEL_ALWAYS
+*********************************************************************************************************
+*/
+
+#if OS_SEM_DEL_EN > 0u
+OS_EVENT  *OSSemDel (OS_EVENT  *pevent,
+                     INT8U      opt,
+                     INT8U     *perr)
+{
+    BOOLEAN    tasks_waiting;
+    OS_EVENT  *pevent_return;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_EVENT *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
+        *perr = OS_ERR_PEVENT_NULL;
+        return (pevent);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {        /* Validate event block type                */
+        *perr = OS_ERR_EVENT_TYPE;
+        return (pevent);
+    }
+    if (OSIntNesting > 0u) {                               /* See if called from ISR ...               */
+        *perr = OS_ERR_DEL_ISR;                            /* ... can't DELETE from an ISR             */
+        return (pevent);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                        /* See if any tasks waiting on semaphore    */
+        tasks_waiting = OS_TRUE;                           /* Yes                                      */
+    } else {
+        tasks_waiting = OS_FALSE;                          /* No                                       */
+    }
+    switch (opt) {
+        case OS_DEL_NO_PEND:                               /* Delete semaphore only if no task waiting */
+             if (tasks_waiting == OS_FALSE) {
+#if OS_EVENT_NAME_EN > 0u
+                 pevent->OSEventName    = (INT8U *)(void *)"?";
+#endif
+                 pevent->OSEventType    = OS_EVENT_TYPE_UNUSED;
+                 pevent->OSEventPtr     = OSEventFreeList; /* Return Event Control Block to free list  */
+                 pevent->OSEventCnt     = 0u;
+                 OSEventFreeList        = pevent;          /* Get next free event control block        */
+                 OS_EXIT_CRITICAL();
+                 *perr                  = OS_ERR_NONE;
+                 pevent_return          = (OS_EVENT *)0;   /* Semaphore has been deleted               */
+             } else {
+                 OS_EXIT_CRITICAL();
+                 *perr                  = OS_ERR_TASK_WAITING;
+                 pevent_return          = pevent;
+             }
+             break;
+
+        case OS_DEL_ALWAYS:                                /* Always delete the semaphore              */
+             while (pevent->OSEventGrp != 0u) {            /* Ready ALL tasks waiting for semaphore    */
+                 (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
+             }
+#if OS_EVENT_NAME_EN > 0u
+             pevent->OSEventName    = (INT8U *)(void *)"?";
+#endif
+             pevent->OSEventType    = OS_EVENT_TYPE_UNUSED;
+             pevent->OSEventPtr     = OSEventFreeList;     /* Return Event Control Block to free list  */
+             pevent->OSEventCnt     = 0u;
+             OSEventFreeList        = pevent;              /* Get next free event control block        */
+             OS_EXIT_CRITICAL();
+             if (tasks_waiting == OS_TRUE) {               /* Reschedule only if task(s) were waiting  */
+                 OS_Sched();                               /* Find highest priority task ready to run  */
+             }
+             *perr                  = OS_ERR_NONE;
+             pevent_return          = (OS_EVENT *)0;       /* Semaphore has been deleted               */
+             break;
+
+        default:
+             OS_EXIT_CRITICAL();
+             *perr                  = OS_ERR_INVALID_OPT;
+             pevent_return          = pevent;
+             break;
+    }
+    return (pevent_return);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                          PEND ON SEMAPHORE
+*
+* Description: This function waits for a semaphore.
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired
+*                            semaphore.
+*
+*              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
+*                            wait for the resource up to the amount of time specified by this argument.
+*                            If you specify 0, however, your task will wait forever at the specified
+*                            semaphore or, until the resource becomes available (or the event occurs).
+*
+*              perr          is a pointer to where an error message will be deposited.  Possible error
+*                            messages are:
+*
+*                            OS_ERR_NONE         The call was successful and your task owns the resource
+*                                                or, the event you are waiting for occurred.
+*                            OS_ERR_TIMEOUT      The semaphore was not received within the specified
+*                                                'timeout'.
+*                            OS_ERR_PEND_ABORT   The wait on the semaphore was aborted.
+*                            OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a semaphore.
+*                            OS_ERR_PEND_ISR     If you called this function from an ISR and the result
+*                                                would lead to a suspension.
+*                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
+*                            OS_ERR_PEND_LOCKED  If you called this function when the scheduler is locked
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+/*$PAGE*/
+void  OSSemPend (OS_EVENT  *pevent,
+                 INT32U     timeout,
+                 INT8U     *perr)
+{
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return;
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        *perr = OS_ERR_PEVENT_NULL;
+        return;
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
+        *perr = OS_ERR_EVENT_TYPE;
+        return;
+    }
+    if (OSIntNesting > 0u) {                          /* See if called from ISR ...                    */
+        *perr = OS_ERR_PEND_ISR;                      /* ... can't PEND from an ISR                    */
+        return;
+    }
+    if (OSLockNesting > 0u) {                         /* See if called with scheduler locked ...       */
+        *perr = OS_ERR_PEND_LOCKED;                   /* ... can't PEND when locked                    */
+        return;
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventCnt > 0u) {                    /* If sem. is positive, resource available ...   */
+        pevent->OSEventCnt--;                         /* ... decrement semaphore only if positive.     */
+        OS_EXIT_CRITICAL();
+        *perr = OS_ERR_NONE;
+        return;
+    }
+                                                      /* Otherwise, must wait until event occurs       */
+    OSTCBCur->OSTCBStat     |= OS_STAT_SEM;           /* Resource not available, pend on semaphore     */
+    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
+    OSTCBCur->OSTCBDly       = timeout;               /* Store pend timeout in TCB                     */
+    OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
+    OS_EXIT_CRITICAL();
+    OS_Sched();                                       /* Find next highest priority task ready         */
+    OS_ENTER_CRITICAL();
+    switch (OSTCBCur->OSTCBStatPend) {                /* See if we timed-out or aborted                */
+        case OS_STAT_PEND_OK:
+             *perr = OS_ERR_NONE;
+             break;
+
+        case OS_STAT_PEND_ABORT:
+             *perr = OS_ERR_PEND_ABORT;               /* Indicate that we aborted                      */
+             break;
+
+        case OS_STAT_PEND_TO:
+        default:
+             OS_EventTaskRemove(OSTCBCur, pevent);
+             *perr = OS_ERR_TIMEOUT;                  /* Indicate that we didn't get event within TO   */
+             break;
+    }
+    OSTCBCur->OSTCBStat          =  OS_STAT_RDY;      /* Set   task  status to ready                   */
+    OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;  /* Clear pend  status                            */
+    OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;    /* Clear event pointers                          */
+#if (OS_EVENT_MULTI_EN > 0u)
+    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
+#endif
+    OS_EXIT_CRITICAL();
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                    ABORT WAITING ON A SEMAPHORE
+*
+* Description: This function aborts & readies any tasks currently waiting on a semaphore.  This function
+*              should be used to fault-abort the wait on the semaphore, rather than to normally signal
+*              the semaphore via OSSemPost().
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired
+*                            semaphore.
+*
+*              opt           determines the type of ABORT performed:
+*                            OS_PEND_OPT_NONE         ABORT wait for a single task (HPT) waiting on the
+*                                                     semaphore
+*                            OS_PEND_OPT_BROADCAST    ABORT wait for ALL tasks that are  waiting on the
+*                                                     semaphore
+*
+*              perr          is a pointer to where an error message will be deposited.  Possible error
+*                            messages are:
+*
+*                            OS_ERR_NONE         No tasks were     waiting on the semaphore.
+*                            OS_ERR_PEND_ABORT   At least one task waiting on the semaphore was readied
+*                                                and informed of the aborted wait; check return value
+*                                                for the number of tasks whose wait on the semaphore
+*                                                was aborted.
+*                            OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a semaphore.
+*                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
+*
+* Returns    : == 0          if no tasks were waiting on the semaphore, or upon error.
+*              >  0          if one or more tasks waiting on the semaphore are now readied and informed.
+*********************************************************************************************************
+*/
+
+#if OS_SEM_PEND_ABORT_EN > 0u
+INT8U  OSSemPendAbort (OS_EVENT  *pevent,
+                       INT8U      opt,
+                       INT8U     *perr)
+{
+    INT8U      nbr_tasks;
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        *perr = OS_ERR_PEVENT_NULL;
+        return (0u);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
+        *perr = OS_ERR_EVENT_TYPE;
+        return (0u);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                   /* See if any task waiting on semaphore?         */
+        nbr_tasks = 0u;
+        switch (opt) {
+            case OS_PEND_OPT_BROADCAST:               /* Do we need to abort ALL waiting tasks?        */
+                 while (pevent->OSEventGrp != 0u) {   /* Yes, ready ALL tasks waiting on semaphore     */
+                     (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
+                     nbr_tasks++;
+                 }
+                 break;
+
+            case OS_PEND_OPT_NONE:
+            default:                                  /* No,  ready HPT       waiting on semaphore     */
+                 (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
+                 nbr_tasks++;
+                 break;
+        }
+        OS_EXIT_CRITICAL();
+        OS_Sched();                                   /* Find HPT ready to run                         */
+        *perr = OS_ERR_PEND_ABORT;
+        return (nbr_tasks);
+    }
+    OS_EXIT_CRITICAL();
+    *perr = OS_ERR_NONE;
+    return (0u);                                      /* No tasks waiting on semaphore                 */
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                         POST TO A SEMAPHORE
+*
+* Description: This function signals a semaphore
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired
+*                            semaphore.
+*
+* Returns    : OS_ERR_NONE         The call was successful and the semaphore was signaled.
+*              OS_ERR_SEM_OVF      If the semaphore count exceeded its limit. In other words, you have
+*                                  signaled the semaphore more often than you waited on it with either
+*                                  OSSemAccept() or OSSemPend().
+*              OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a semaphore
+*              OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
+*********************************************************************************************************
+*/
+
+INT8U  OSSemPost (OS_EVENT *pevent)
+{
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        return (OS_ERR_PEVENT_NULL);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
+        return (OS_ERR_EVENT_TYPE);
+    }
+    OS_ENTER_CRITICAL();
+    if (pevent->OSEventGrp != 0u) {                   /* See if any task waiting for semaphore         */
+                                                      /* Ready HPT waiting on event                    */
+        (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
+        OS_EXIT_CRITICAL();
+        OS_Sched();                                   /* Find HPT ready to run                         */
+        return (OS_ERR_NONE);
+    }
+    if (pevent->OSEventCnt < 65535u) {                /* Make sure semaphore will not overflow         */
+        pevent->OSEventCnt++;                         /* Increment semaphore count to register event   */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_NONE);
+    }
+    OS_EXIT_CRITICAL();                               /* Semaphore value has reached its maximum       */
+    return (OS_ERR_SEM_OVF);
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                          QUERY A SEMAPHORE
+*
+* Description: This function obtains information about a semaphore
+*
+* Arguments  : pevent        is a pointer to the event control block associated with the desired
+*                            semaphore
+*
+*              p_sem_data    is a pointer to a structure that will contain information about the
+*                            semaphore.
+*
+* Returns    : OS_ERR_NONE         The call was successful and the message was sent
+*              OS_ERR_EVENT_TYPE   If you are attempting to obtain data from a non semaphore.
+*              OS_ERR_PEVENT_NULL  If 'pevent'     is a NULL pointer.
+*              OS_ERR_PDATA_NULL   If 'p_sem_data' is a NULL pointer
+*********************************************************************************************************
+*/
+
+#if OS_SEM_QUERY_EN > 0u
+INT8U  OSSemQuery (OS_EVENT     *pevent,
+                   OS_SEM_DATA  *p_sem_data)
+{
+    INT8U       i;
+    OS_PRIO    *psrc;
+    OS_PRIO    *pdest;
+#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
+    OS_CPU_SR   cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
+        return (OS_ERR_PEVENT_NULL);
+    }
+    if (p_sem_data == (OS_SEM_DATA *)0) {                  /* Validate 'p_sem_data'                    */
+        return (OS_ERR_PDATA_NULL);
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {        /* Validate event block type                */
+        return (OS_ERR_EVENT_TYPE);
+    }
+    OS_ENTER_CRITICAL();
+    p_sem_data->OSEventGrp = pevent->OSEventGrp;           /* Copy message mailbox wait list           */
+    psrc                   = &pevent->OSEventTbl[0];
+    pdest                  = &p_sem_data->OSEventTbl[0];
+    for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
+        *pdest++ = *psrc++;
+    }
+    p_sem_data->OSCnt = pevent->OSEventCnt;                /* Get semaphore count                      */
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif                                                     /* OS_SEM_QUERY_EN                          */
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                            SET SEMAPHORE
+*
+* Description: This function sets the semaphore count to the value specified as an argument.  Typically,
+*              this value would be 0.
+*
+*              You would typically use this function when a semaphore is used as a signaling mechanism
+*              and, you want to reset the count value.
+*
+* Arguments  : pevent     is a pointer to the event control block
+*
+*              cnt        is the new value for the semaphore count.  You would pass 0 to reset the
+*                         semaphore count.
+*
+*              perr       is a pointer to an error code returned by the function as follows:
+*
+*                            OS_ERR_NONE          The call was successful and the semaphore value was set.
+*                            OS_ERR_EVENT_TYPE    If you didn't pass a pointer to a semaphore.
+*                            OS_ERR_PEVENT_NULL   If 'pevent' is a NULL pointer.
+*                            OS_ERR_TASK_WAITING  If tasks are waiting on the semaphore.
+*********************************************************************************************************
+*/
+
+#if OS_SEM_SET_EN > 0u
+void  OSSemSet (OS_EVENT  *pevent,
+                INT16U     cnt,
+                INT8U     *perr)
+{
+#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return;
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
+        *perr = OS_ERR_PEVENT_NULL;
+        return;
+    }
+#endif
+    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
+        *perr = OS_ERR_EVENT_TYPE;
+        return;
+    }
+    OS_ENTER_CRITICAL();
+    *perr = OS_ERR_NONE;
+    if (pevent->OSEventCnt > 0u) {                    /* See if semaphore already has a count          */
+        pevent->OSEventCnt = cnt;                     /* Yes, set it to the new value specified.       */
+    } else {                                          /* No                                            */
+        if (pevent->OSEventGrp == 0u) {               /*      See if task(s) waiting?                  */
+            pevent->OSEventCnt = cnt;                 /*      No, OK to set the value                  */
+        } else {
+            *perr              = OS_ERR_TASK_WAITING;
+        }
+    }
+    OS_EXIT_CRITICAL();
+}
+#endif
+
+#endif                                                /* OS_SEM_EN                                     */

+ 1343 - 0
MiddleWare/uCOS_II/uCOS-II/Source/os_task.c

@@ -0,0 +1,1343 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                            TASK MANAGEMENT
+*
+*                              (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_TASK.C
+* By      : Jean J. Labrosse
+* Version : V2.92.11
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#define  MICRIUM_SOURCE
+
+#ifndef  OS_MASTER_FILE
+#include <ucos_ii.h>
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                      CHANGE PRIORITY OF A TASK
+*
+* Description: This function allows you to change the priority of a task dynamically.  Note that the new
+*              priority MUST be available.
+*
+* Arguments  : oldp     is the old priority
+*
+*              newp     is the new priority
+*
+* Returns    : OS_ERR_NONE            is the call was successful
+*              OS_ERR_PRIO_INVALID    if the priority you specify is higher that the maximum allowed
+*                                     (i.e. >= OS_LOWEST_PRIO)
+*              OS_ERR_PRIO_EXIST      if the new priority already exist.
+*              OS_ERR_PRIO            there is no task with the specified OLD priority (i.e. the OLD task does
+*                                     not exist.
+*              OS_ERR_TASK_NOT_EXIST  if the task is assigned to a Mutex PIP.
+*********************************************************************************************************
+*/
+
+#if OS_TASK_CHANGE_PRIO_EN > 0u
+INT8U  OSTaskChangePrio (INT8U  oldprio,
+                         INT8U  newprio)
+{
+#if (OS_EVENT_EN)
+    OS_EVENT  *pevent;
+#if (OS_EVENT_MULTI_EN > 0u)
+    OS_EVENT **pevents;
+#endif
+#endif
+    OS_TCB    *ptcb;
+    INT8U      y_new;
+    INT8U      x_new;
+    INT8U      y_old;
+    OS_PRIO    bity_new;
+    OS_PRIO    bitx_new;
+    OS_PRIO    bity_old;
+    OS_PRIO    bitx_old;
+#if OS_CRITICAL_METHOD == 3u
+    OS_CPU_SR  cpu_sr = 0u;                                 /* Storage for CPU status register         */
+#endif
+
+
+/*$PAGE*/
+#if OS_ARG_CHK_EN > 0u
+    if (oldprio >= OS_LOWEST_PRIO) {
+        if (oldprio != OS_PRIO_SELF) {
+            return (OS_ERR_PRIO_INVALID);
+        }
+    }
+    if (newprio >= OS_LOWEST_PRIO) {
+        return (OS_ERR_PRIO_INVALID);
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) {             /* New priority must not already exist     */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_PRIO_EXIST);
+    }
+    if (oldprio == OS_PRIO_SELF) {                          /* See if changing self                    */
+        oldprio = OSTCBCur->OSTCBPrio;                      /* Yes, get priority                       */
+    }
+    ptcb = OSTCBPrioTbl[oldprio];
+    if (ptcb == (OS_TCB *)0) {                              /* Does task to change exist?              */
+        OS_EXIT_CRITICAL();                                 /* No, can't change its priority!          */
+        return (OS_ERR_PRIO);
+    }
+    if (ptcb == OS_TCB_RESERVED) {                          /* Is task assigned to Mutex               */
+        OS_EXIT_CRITICAL();                                 /* No, can't change its priority!          */
+        return (OS_ERR_TASK_NOT_EXIST);
+    }
+#if OS_LOWEST_PRIO <= 63u
+    y_new                 = (INT8U)(newprio >> 3u);         /* Yes, compute new TCB fields             */
+    x_new                 = (INT8U)(newprio & 0x07u);
+#else
+    y_new                 = (INT8U)((INT8U)(newprio >> 4u) & 0x0Fu);
+    x_new                 = (INT8U)(newprio & 0x0Fu);
+#endif
+    bity_new              = (OS_PRIO)(1uL << y_new);
+    bitx_new              = (OS_PRIO)(1uL << x_new);
+
+    OSTCBPrioTbl[oldprio] = (OS_TCB *)0;                    /* Remove TCB from old priority            */
+    OSTCBPrioTbl[newprio] =  ptcb;                          /* Place pointer to TCB @ new priority     */
+    y_old                 =  ptcb->OSTCBY;
+    bity_old              =  ptcb->OSTCBBitY;
+    bitx_old              =  ptcb->OSTCBBitX;
+    if ((OSRdyTbl[y_old] &   bitx_old) != 0u) {             /* If task is ready make it not            */
+         OSRdyTbl[y_old] &= (OS_PRIO)~bitx_old;
+         if (OSRdyTbl[y_old] == 0u) {
+             OSRdyGrp &= (OS_PRIO)~bity_old;
+         }
+         OSRdyGrp        |= bity_new;                       /* Make new priority ready to run          */
+         OSRdyTbl[y_new] |= bitx_new;
+    }
+
+#if (OS_EVENT_EN)
+    pevent = ptcb->OSTCBEventPtr;
+    if (pevent != (OS_EVENT *)0) {
+        pevent->OSEventTbl[y_old] &= (OS_PRIO)~bitx_old;    /* Remove old task prio from wait list     */
+        if (pevent->OSEventTbl[y_old] == 0u) {
+            pevent->OSEventGrp    &= (OS_PRIO)~bity_old;
+        }
+        pevent->OSEventGrp        |= bity_new;              /* Add    new task prio to   wait list     */
+        pevent->OSEventTbl[y_new] |= bitx_new;
+    }
+#if (OS_EVENT_MULTI_EN > 0u)
+    if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) {
+        pevents =  ptcb->OSTCBEventMultiPtr;
+        pevent  = *pevents;
+        while (pevent != (OS_EVENT *)0) {
+            pevent->OSEventTbl[y_old] &= (OS_PRIO)~bitx_old;   /* Remove old task prio from wait lists */
+            if (pevent->OSEventTbl[y_old] == 0u) {
+                pevent->OSEventGrp    &= (OS_PRIO)~bity_old;
+            }
+            pevent->OSEventGrp        |= bity_new;          /* Add    new task prio to   wait lists    */
+            pevent->OSEventTbl[y_new] |= bitx_new;
+            pevents++;
+            pevent                     = *pevents;
+        }
+    }
+#endif
+#endif
+
+    ptcb->OSTCBPrio = newprio;                              /* Set new task priority                   */
+    ptcb->OSTCBY    = y_new;
+    ptcb->OSTCBX    = x_new;
+    ptcb->OSTCBBitY = bity_new;
+    ptcb->OSTCBBitX = bitx_new;
+    OS_EXIT_CRITICAL();
+    if (OSRunning == OS_TRUE) {
+        OS_Sched();                                         /* Find new highest priority task          */
+    }
+    return (OS_ERR_NONE);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                            CREATE A TASK
+*
+* Description: This function is used to have uC/OS-II manage the execution of a task.  Tasks can either
+*              be created prior to the start of multitasking or by a running task.  A task cannot be
+*              created by an ISR.
+*
+* Arguments  : task     is a pointer to the task's code
+*
+*              p_arg    is a pointer to an optional data area which can be used to pass parameters to
+*                       the task when the task first executes.  Where the task is concerned it thinks
+*                       it was invoked and passed the argument 'p_arg' as follows:
+*
+*                           void Task (void *p_arg)
+*                           {
+*                               for (;;) {
+*                                   Task code;
+*                               }
+*                           }
+*
+*              ptos     is a pointer to the task's top of stack.  If the configuration constant
+*                       OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
+*                       memory to low memory).  'pstk' will thus point to the highest (valid) memory
+*                       location of the stack.  If OS_STK_GROWTH is set to 0, 'pstk' will point to the
+*                       lowest memory location of the stack and the stack will grow with increasing
+*                       memory locations.
+*
+*              prio     is the task's priority.  A unique priority MUST be assigned to each task and the
+*                       lower the number, the higher the priority.
+*
+* Returns    : OS_ERR_NONE                      if the function was successful.
+*              OS_ERR_PRIO_EXIST                if the task priority already exist
+*                                               (each task MUST have a unique priority).
+*              OS_ERR_PRIO_INVALID              if the priority you specify is higher that the maximum
+*                                               allowed (i.e. >= OS_LOWEST_PRIO)
+*              OS_ERR_TASK_CREATE_ISR           if you tried to create a task from an ISR.
+*              OS_ERR_ILLEGAL_CREATE_RUN_TIME   if you tried to create a task after safety critical
+*                                               operation started.
+*********************************************************************************************************
+*/
+
+#if OS_TASK_CREATE_EN > 0u
+INT8U  OSTaskCreate (void   (*task)(void *p_arg),
+                     void    *p_arg,
+                     OS_STK  *ptos,
+                     INT8U    prio)
+{
+    OS_STK     *psp;
+    INT8U       err;
+#if OS_CRITICAL_METHOD == 3u                 /* Allocate storage for CPU status register               */
+    OS_CPU_SR   cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    if (OSSafetyCriticalStartFlag == OS_TRUE) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (OS_ERR_ILLEGAL_CREATE_RUN_TIME);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */
+        return (OS_ERR_PRIO_INVALID);
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    if (OSIntNesting > 0u) {                 /* Make sure we don't create the task from within an ISR  */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_CREATE_ISR);
+    }
+    if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority  */
+        OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ...  */
+                                             /* ... the same thing until task is created.              */
+        OS_EXIT_CRITICAL();
+        psp = OSTaskStkInit(task, p_arg, ptos, 0u);             /* Initialize the task's stack         */
+        err = OS_TCBInit(prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u);
+        if (err == OS_ERR_NONE) {
+            if (OSRunning == OS_TRUE) {      /* Find highest priority task if multitasking has started */
+                OS_Sched();
+            }
+        } else {
+            OS_ENTER_CRITICAL();
+            OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others                 */
+            OS_EXIT_CRITICAL();
+        }
+        return (err);
+    }
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_PRIO_EXIST);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                  CREATE A TASK (Extended Version)
+*
+* Description: This function is used to have uC/OS-II manage the execution of a task.  Tasks can either
+*              be created prior to the start of multitasking or by a running task.  A task cannot be
+*              created by an ISR.  This function is similar to OSTaskCreate() except that it allows
+*              additional information about a task to be specified.
+*
+* Arguments  : task      is a pointer to the task's code
+*
+*              p_arg     is a pointer to an optional data area which can be used to pass parameters to
+*                        the task when the task first executes.  Where the task is concerned it thinks
+*                        it was invoked and passed the argument 'p_arg' as follows:
+*
+*                            void Task (void *p_arg)
+*                            {
+*                                for (;;) {
+*                                    Task code;
+*                                }
+*                            }
+*
+*              ptos      is a pointer to the task's top of stack.  If the configuration constant
+*                        OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
+*                        memory to low memory).  'ptos' will thus point to the highest (valid) memory
+*                        location of the stack.  If OS_STK_GROWTH is set to 0, 'ptos' will point to the
+*                        lowest memory location of the stack and the stack will grow with increasing
+*                        memory locations.  'ptos' MUST point to a valid 'free' data item.
+*
+*              prio      is the task's priority.  A unique priority MUST be assigned to each task and the
+*                        lower the number, the higher the priority.
+*
+*              id        is the task's ID (0..65535)
+*
+*              pbos      is a pointer to the task's bottom of stack.  If the configuration constant
+*                        OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
+*                        memory to low memory).  'pbos' will thus point to the LOWEST (valid) memory
+*                        location of the stack.  If OS_STK_GROWTH is set to 0, 'pbos' will point to the
+*                        HIGHEST memory location of the stack and the stack will grow with increasing
+*                        memory locations.  'pbos' MUST point to a valid 'free' data item.
+*
+*              stk_size  is the size of the stack in number of elements.  If OS_STK is set to INT8U,
+*                        'stk_size' corresponds to the number of bytes available.  If OS_STK is set to
+*                        INT16U, 'stk_size' contains the number of 16-bit entries available.  Finally, if
+*                        OS_STK is set to INT32U, 'stk_size' contains the number of 32-bit entries
+*                        available on the stack.
+*
+*              pext      is a pointer to a user supplied memory location which is used as a TCB extension.
+*                        For example, this user memory can hold the contents of floating-point registers
+*                        during a context switch, the time each task takes to execute, the number of times
+*                        the task has been switched-in, etc.
+*
+*              opt       contains additional information (or options) about the behavior of the task.  The
+*                        LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application
+*                        specific.  See OS_TASK_OPT_??? in uCOS-II.H.  Current choices are:
+*
+*                        OS_TASK_OPT_STK_CHK      Stack checking to be allowed for the task
+*                        OS_TASK_OPT_STK_CLR      Clear the stack when the task is created
+*                        OS_TASK_OPT_SAVE_FP      If the CPU has floating-point registers, save them
+*                                                 during a context switch.
+*
+* Returns    : OS_ERR_NONE                      if the function was successful.
+*              OS_ERR_PRIO_EXIST                if the task priority already exist
+*                                               (each task MUST have a unique priority).
+*              OS_ERR_PRIO_INVALID              if the priority you specify is higher that the maximum
+*                                               allowed (i.e. > OS_LOWEST_PRIO)
+*              OS_ERR_TASK_CREATE_ISR           if you tried to create a task from an ISR.
+*              OS_ERR_ILLEGAL_CREATE_RUN_TIME   if you tried to create a task after safety critical
+*                                               operation started.
+*********************************************************************************************************
+*/
+/*$PAGE*/
+#if OS_TASK_CREATE_EXT_EN > 0u
+INT8U  OSTaskCreateExt (void   (*task)(void *p_arg),
+                        void    *p_arg,
+                        OS_STK  *ptos,
+                        INT8U    prio,
+                        INT16U   id,
+                        OS_STK  *pbos,
+                        INT32U   stk_size,
+                        void    *pext,
+                        INT16U   opt)
+{
+    OS_STK     *psp;
+    INT8U       err;
+#if OS_CRITICAL_METHOD == 3u                 /* Allocate storage for CPU status register               */
+    OS_CPU_SR   cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    if (OSSafetyCriticalStartFlag == OS_TRUE) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (OS_ERR_ILLEGAL_CREATE_RUN_TIME);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */
+        return (OS_ERR_PRIO_INVALID);
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    if (OSIntNesting > 0u) {                 /* Make sure we don't create the task from within an ISR  */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_CREATE_ISR);
+    }
+    if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority  */
+        OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ...  */
+                                             /* ... the same thing until task is created.              */
+        OS_EXIT_CRITICAL();
+
+#if (OS_TASK_STAT_STK_CHK_EN > 0u)
+        OS_TaskStkClr(pbos, stk_size, opt);                    /* Clear the task stack (if needed)     */
+#endif
+
+        psp = OSTaskStkInit(task, p_arg, ptos, opt);           /* Initialize the task's stack          */
+        err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt);
+        if (err == OS_ERR_NONE) {
+            if (OSRunning == OS_TRUE) {                        /* Find HPT if multitasking has started */
+                OS_Sched();
+            }
+        } else {
+            OS_ENTER_CRITICAL();
+            OSTCBPrioTbl[prio] = (OS_TCB *)0;                  /* Make this priority avail. to others  */
+            OS_EXIT_CRITICAL();
+        }
+        return (err);
+    }
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_PRIO_EXIST);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                            DELETE A TASK
+*
+* Description: This function allows you to delete a task.  The calling task can delete itself by
+*              its own priority number.  The deleted task is returned to the dormant state and can be
+*              re-activated by creating the deleted task again.
+*
+* Arguments  : prio    is the priority of the task to delete.  Note that you can explicitly delete
+*                      the current task without knowing its priority level by setting 'prio' to
+*                      OS_PRIO_SELF.
+*
+* Returns    : OS_ERR_NONE             if the call is successful
+*              OS_ERR_TASK_DEL_IDLE    if you attempted to delete uC/OS-II's idle task
+*              OS_ERR_PRIO_INVALID     if the priority you specify is higher that the maximum allowed
+*                                      (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
+*              OS_ERR_TASK_DEL         if the task is assigned to a Mutex PIP.
+*              OS_ERR_TASK_NOT_EXIST   if the task you want to delete does not exist.
+*              OS_ERR_TASK_DEL_ISR     if you tried to delete a task from an ISR
+*
+* Notes      : 1) To reduce interrupt latency, OSTaskDel() 'disables' the task:
+*                    a) by making it not ready
+*                    b) by removing it from any wait lists
+*                    c) by preventing OSTimeTick() from making the task ready to run.
+*                 The task can then be 'unlinked' from the miscellaneous structures in uC/OS-II.
+*              2) The function OS_Dummy() is called after OS_EXIT_CRITICAL() because, on most processors,
+*                 the next instruction following the enable interrupt instruction is ignored.
+*              3) An ISR cannot delete a task.
+*              4) The lock nesting counter is incremented because, for a brief instant, if the current
+*                 task is being deleted, the current task would not be able to be rescheduled because it
+*                 is removed from the ready list.  Incrementing the nesting counter prevents another task
+*                 from being schedule.  This means that an ISR would return to the current task which is
+*                 being deleted.  The rest of the deletion would thus be able to be completed.
+*********************************************************************************************************
+*/
+
+#if OS_TASK_DEL_EN > 0u
+INT8U  OSTaskDel (INT8U prio)
+{
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+    OS_FLAG_NODE *pnode;
+#endif
+    OS_TCB       *ptcb;
+#if OS_CRITICAL_METHOD == 3u                            /* Allocate storage for CPU status register    */
+    OS_CPU_SR     cpu_sr = 0u;
+#endif
+
+
+
+    if (OSIntNesting > 0u) {                            /* See if trying to delete from ISR            */
+        return (OS_ERR_TASK_DEL_ISR);
+    }
+    if (prio == OS_TASK_IDLE_PRIO) {                    /* Not allowed to delete idle task             */
+        return (OS_ERR_TASK_DEL_IDLE);
+    }
+#if OS_ARG_CHK_EN > 0u
+    if (prio >= OS_LOWEST_PRIO) {                       /* Task priority valid ?                       */
+        if (prio != OS_PRIO_SELF) {
+            return (OS_ERR_PRIO_INVALID);
+        }
+    }
+#endif
+
+/*$PAGE*/
+    OS_ENTER_CRITICAL();
+    if (prio == OS_PRIO_SELF) {                         /* See if requesting to delete self            */
+        prio = OSTCBCur->OSTCBPrio;                     /* Set priority to delete to current           */
+    }
+    ptcb = OSTCBPrioTbl[prio];
+    if (ptcb == (OS_TCB *)0) {                          /* Task to delete must exist                   */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_NOT_EXIST);
+    }
+    if (ptcb == OS_TCB_RESERVED) {                      /* Must not be assigned to Mutex               */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_DEL);
+    }
+
+    OSRdyTbl[ptcb->OSTCBY] &= (OS_PRIO)~ptcb->OSTCBBitX;
+    if (OSRdyTbl[ptcb->OSTCBY] == 0u) {                 /* Make task not ready                         */
+        OSRdyGrp           &= (OS_PRIO)~ptcb->OSTCBBitY;
+    }
+
+#if (OS_EVENT_EN)
+    if (ptcb->OSTCBEventPtr != (OS_EVENT *)0) {
+        OS_EventTaskRemove(ptcb, ptcb->OSTCBEventPtr);  /* Remove this task from any event   wait list */
+    }
+#if (OS_EVENT_MULTI_EN > 0u)
+    if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) {   /* Remove this task from any events' wait lists*/
+        OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr);
+    }
+#endif
+#endif
+
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+    pnode = ptcb->OSTCBFlagNode;
+    if (pnode != (OS_FLAG_NODE *)0) {                   /* If task is waiting on event flag            */
+        OS_FlagUnlink(pnode);                           /* Remove from wait list                       */
+    }
+#endif
+
+    ptcb->OSTCBDly      = 0u;                           /* Prevent OSTimeTick() from updating          */
+    ptcb->OSTCBStat     = OS_STAT_RDY;                  /* Prevent task from being resumed             */
+    ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
+    if (OSLockNesting < 255u) {                         /* Make sure we don't context switch           */
+        OSLockNesting++;
+    }
+    OS_EXIT_CRITICAL();                                 /* Enabling INT. ignores next instruc.         */
+    OS_Dummy();                                         /* ... Dummy ensures that INTs will be         */
+    OS_ENTER_CRITICAL();                                /* ... disabled HERE!                          */
+    if (OSLockNesting > 0u) {                           /* Remove context switch lock                  */
+        OSLockNesting--;
+    }
+    OSTaskDelHook(ptcb);                                /* Call user defined hook                      */
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
+    OS_TLS_TaskDel(ptcb);                               /* Call TLS hook                               */
+#endif
+#endif
+
+    OSTaskCtr--;                                        /* One less task being managed                 */
+    OSTCBPrioTbl[prio] = (OS_TCB *)0;                   /* Clear old priority entry                    */
+    if (ptcb->OSTCBPrev == (OS_TCB *)0) {               /* Remove from TCB chain                       */
+        ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;
+        OSTCBList                  = ptcb->OSTCBNext;
+    } else {
+        ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
+        ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
+    }
+    ptcb->OSTCBNext     = OSTCBFreeList;                /* Return TCB to free TCB list                 */
+    OSTCBFreeList       = ptcb;
+#if OS_TASK_NAME_EN > 0u
+    ptcb->OSTCBTaskName = (INT8U *)(void *)"?";
+#endif
+    OS_EXIT_CRITICAL();
+    if (OSRunning == OS_TRUE) {
+        OS_Sched();                                     /* Find new highest priority task              */
+    }
+    return (OS_ERR_NONE);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                  REQUEST THAT A TASK DELETE ITSELF
+*
+* Description: This function is used to:
+*                   a) notify a task to delete itself.
+*                   b) to see if a task requested that the current task delete itself.
+*              This function is a little tricky to understand.  Basically, you have a task that needs
+*              to be deleted however, this task has resources that it has allocated (memory buffers,
+*              semaphores, mailboxes, queues etc.).  The task cannot be deleted otherwise these
+*              resources would not be freed.  The requesting task calls OSTaskDelReq() to indicate that
+*              the task needs to be deleted.  Deleting of the task is however, deferred to the task to
+*              be deleted.  For example, suppose that task #10 needs to be deleted.  The requesting task
+*              example, task #5, would call OSTaskDelReq(10).  When task #10 gets to execute, it calls
+*              this function by specifying OS_PRIO_SELF and monitors the returned value.  If the return
+*              value is OS_ERR_TASK_DEL_REQ, another task requested a task delete.  Task #10 would look like
+*              this:
+*
+*                   void Task(void *p_arg)
+*                   {
+*                       .
+*                       .
+*                       while (1) {
+*                           OSTimeDly(1);
+*                           if (OSTaskDelReq(OS_PRIO_SELF) == OS_ERR_TASK_DEL_REQ) {
+*                               Release any owned resources;
+*                               De-allocate any dynamic memory;
+*                               OSTaskDel(OS_PRIO_SELF);
+*                           }
+*                       }
+*                   }
+*
+* Arguments  : prio    is the priority of the task to request the delete from
+*
+* Returns    : OS_ERR_NONE            if the task exist and the request has been registered
+*              OS_ERR_TASK_NOT_EXIST  if the task has been deleted.  This allows the caller to know whether
+*                                     the request has been executed.
+*              OS_ERR_TASK_DEL        if the task is assigned to a Mutex.
+*              OS_ERR_TASK_DEL_IDLE   if you requested to delete uC/OS-II's idle task
+*              OS_ERR_PRIO_INVALID    if the priority you specify is higher that the maximum allowed
+*                                     (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
+*              OS_ERR_TASK_DEL_REQ    if a task (possibly another task) requested that the running task be
+*                                     deleted.
+*********************************************************************************************************
+*/
+/*$PAGE*/
+#if OS_TASK_DEL_EN > 0u
+INT8U  OSTaskDelReq (INT8U prio)
+{
+    INT8U      stat;
+    OS_TCB    *ptcb;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    if (prio == OS_TASK_IDLE_PRIO) {                            /* Not allowed to delete idle task     */
+        return (OS_ERR_TASK_DEL_IDLE);
+    }
+#if OS_ARG_CHK_EN > 0u
+    if (prio >= OS_LOWEST_PRIO) {                               /* Task priority valid ?               */
+        if (prio != OS_PRIO_SELF) {
+            return (OS_ERR_PRIO_INVALID);
+        }
+    }
+#endif
+    if (prio == OS_PRIO_SELF) {                                 /* See if a task is requesting to ...  */
+        OS_ENTER_CRITICAL();                                    /* ... this task to delete itself      */
+        stat = OSTCBCur->OSTCBDelReq;                           /* Return request status to caller     */
+        OS_EXIT_CRITICAL();
+        return (stat);
+    }
+    OS_ENTER_CRITICAL();
+    ptcb = OSTCBPrioTbl[prio];
+    if (ptcb == (OS_TCB *)0) {                                  /* Task to delete must exist           */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_NOT_EXIST);                         /* Task must already be deleted        */
+    }
+    if (ptcb == OS_TCB_RESERVED) {                              /* Must NOT be assigned to a Mutex     */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_DEL);
+    }
+    ptcb->OSTCBDelReq = OS_ERR_TASK_DEL_REQ;                    /* Set flag indicating task to be DEL. */
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       GET THE NAME OF A TASK
+*
+* Description: This function is called to obtain the name of a task.
+*
+* Arguments  : prio      is the priority of the task that you want to obtain the name from.
+*
+*              pname     is a pointer to a pointer to an ASCII string that will receive the name of the task.
+*
+*              perr      is a pointer to an error code that can contain one of the following values:
+*
+*                        OS_ERR_NONE                if the requested task is resumed
+*                        OS_ERR_TASK_NOT_EXIST      if the task has not been created or is assigned to a Mutex
+*                        OS_ERR_PRIO_INVALID        if you specified an invalid priority:
+*                                                   A higher value than the idle task or not OS_PRIO_SELF.
+*                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
+*                        OS_ERR_NAME_GET_ISR        You called this function from an ISR
+*
+*
+* Returns    : The length of the string or 0 if the task does not exist.
+*********************************************************************************************************
+*/
+
+#if OS_TASK_NAME_EN > 0u
+INT8U  OSTaskNameGet (INT8U    prio,
+                      INT8U  **pname,
+                      INT8U   *perr)
+{
+    OS_TCB    *ptcb;
+    INT8U      len;
+#if OS_CRITICAL_METHOD == 3u                             /* Allocate storage for CPU status register   */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (prio > OS_LOWEST_PRIO) {                         /* Task priority valid ?                      */
+        if (prio != OS_PRIO_SELF) {
+            *perr = OS_ERR_PRIO_INVALID;                 /* No                                         */
+            return (0u);
+        }
+    }
+    if (pname == (INT8U **)0) {                          /* Is 'pname' a NULL pointer?                 */
+        *perr = OS_ERR_PNAME_NULL;                       /* Yes                                        */
+        return (0u);
+    }
+#endif
+    if (OSIntNesting > 0u) {                              /* See if trying to call from an ISR          */
+        *perr = OS_ERR_NAME_GET_ISR;
+        return (0u);
+    }
+    OS_ENTER_CRITICAL();
+    if (prio == OS_PRIO_SELF) {                          /* See if caller desires it's own name        */
+        prio = OSTCBCur->OSTCBPrio;
+    }
+    ptcb = OSTCBPrioTbl[prio];
+    if (ptcb == (OS_TCB *)0) {                           /* Does task exist?                           */
+        OS_EXIT_CRITICAL();                              /* No                                         */
+        *perr = OS_ERR_TASK_NOT_EXIST;
+        return (0u);
+    }
+    if (ptcb == OS_TCB_RESERVED) {                       /* Task assigned to a Mutex?                  */
+        OS_EXIT_CRITICAL();                              /* Yes                                        */
+        *perr = OS_ERR_TASK_NOT_EXIST;
+        return (0u);
+    }
+    *pname = ptcb->OSTCBTaskName;
+    len    = OS_StrLen(*pname);
+    OS_EXIT_CRITICAL();
+    *perr  = OS_ERR_NONE;
+    return (len);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       ASSIGN A NAME TO A TASK
+*
+* Description: This function is used to set the name of a task.
+*
+* Arguments  : prio      is the priority of the task that you want the assign a name to.
+*
+*              pname     is a pointer to an ASCII string that contains the name of the task.
+*
+*              perr       is a pointer to an error code that can contain one of the following values:
+*
+*                        OS_ERR_NONE                if the requested task is resumed
+*                        OS_ERR_TASK_NOT_EXIST      if the task has not been created or is assigned to a Mutex
+*                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
+*                        OS_ERR_PRIO_INVALID        if you specified an invalid priority:
+*                                                   A higher value than the idle task or not OS_PRIO_SELF.
+*                        OS_ERR_NAME_SET_ISR        if you called this function from an ISR
+*
+* Returns    : None
+*********************************************************************************************************
+*/
+#if OS_TASK_NAME_EN > 0u
+void  OSTaskNameSet (INT8U   prio,
+                     INT8U  *pname,
+                     INT8U  *perr)
+{
+    OS_TCB    *ptcb;
+#if OS_CRITICAL_METHOD == 3u                         /* Allocate storage for CPU status register       */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return;
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (prio > OS_LOWEST_PRIO) {                     /* Task priority valid ?                          */
+        if (prio != OS_PRIO_SELF) {
+            *perr = OS_ERR_PRIO_INVALID;             /* No                                             */
+            return;
+        }
+    }
+    if (pname == (INT8U *)0) {                       /* Is 'pname' a NULL pointer?                     */
+        *perr = OS_ERR_PNAME_NULL;                   /* Yes                                            */
+        return;
+    }
+#endif
+    if (OSIntNesting > 0u) {                         /* See if trying to call from an ISR              */
+        *perr = OS_ERR_NAME_SET_ISR;
+        return;
+    }
+    OS_ENTER_CRITICAL();
+    if (prio == OS_PRIO_SELF) {                      /* See if caller desires to set it's own name     */
+        prio = OSTCBCur->OSTCBPrio;
+    }
+    ptcb = OSTCBPrioTbl[prio];
+    if (ptcb == (OS_TCB *)0) {                       /* Does task exist?                               */
+        OS_EXIT_CRITICAL();                          /* No                                             */
+        *perr = OS_ERR_TASK_NOT_EXIST;
+        return;
+    }
+    if (ptcb == OS_TCB_RESERVED) {                   /* Task assigned to a Mutex?                      */
+        OS_EXIT_CRITICAL();                          /* Yes                                            */
+        *perr = OS_ERR_TASK_NOT_EXIST;
+        return;
+    }
+    ptcb->OSTCBTaskName = pname;
+    OS_EXIT_CRITICAL();
+    *perr               = OS_ERR_NONE;
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       RESUME A SUSPENDED TASK
+*
+* Description: This function is called to resume a previously suspended task.  This is the only call that
+*              will remove an explicit task suspension.
+*
+* Arguments  : prio     is the priority of the task to resume.
+*
+* Returns    : OS_ERR_NONE                if the requested task is resumed
+*              OS_ERR_PRIO_INVALID        if the priority you specify is higher that the maximum allowed
+*                                         (i.e. >= OS_LOWEST_PRIO)
+*              OS_ERR_TASK_RESUME_PRIO    if the task to resume does not exist
+*              OS_ERR_TASK_NOT_EXIST      if the task is assigned to a Mutex PIP
+*              OS_ERR_TASK_NOT_SUSPENDED  if the task to resume has not been suspended
+*********************************************************************************************************
+*/
+
+#if OS_TASK_SUSPEND_EN > 0u
+INT8U  OSTaskResume (INT8U prio)
+{
+    OS_TCB    *ptcb;
+#if OS_CRITICAL_METHOD == 3u                                  /* Storage for CPU status register       */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (prio >= OS_LOWEST_PRIO) {                             /* Make sure task priority is valid      */
+        return (OS_ERR_PRIO_INVALID);
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    ptcb = OSTCBPrioTbl[prio];
+    if (ptcb == (OS_TCB *)0) {                                /* Task to suspend must exist            */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_RESUME_PRIO);
+    }
+    if (ptcb == OS_TCB_RESERVED) {                            /* See if assigned to Mutex              */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_NOT_EXIST);
+    }
+    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) { /* Task must be suspended                */
+        ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_SUSPEND;    /* Remove suspension                     */
+        if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) == OS_STAT_RDY) { /* See if task is now ready         */
+            if (ptcb->OSTCBDly == 0u) {
+                OSRdyGrp               |= ptcb->OSTCBBitY;    /* Yes, Make task ready to run           */
+                OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
+                OS_EXIT_CRITICAL();
+                if (OSRunning == OS_TRUE) {
+                    OS_Sched();                               /* Find new highest priority task        */
+                }
+            } else {
+                OS_EXIT_CRITICAL();
+            }
+        } else {                                              /* Must be pending on event              */
+            OS_EXIT_CRITICAL();
+        }
+        return (OS_ERR_NONE);
+    }
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_TASK_NOT_SUSPENDED);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                           STACK CHECKING
+*
+* Description: This function is called to check the amount of free memory left on the specified task's
+*              stack.
+*
+* Arguments  : prio          is the task priority
+*
+*              p_stk_data    is a pointer to a data structure of type OS_STK_DATA.
+*
+* Returns    : OS_ERR_NONE            upon success
+*              OS_ERR_PRIO_INVALID    if the priority you specify is higher that the maximum allowed
+*                                     (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
+*              OS_ERR_TASK_NOT_EXIST  if the desired task has not been created or is assigned to a Mutex PIP
+*              OS_ERR_TASK_OPT        if you did NOT specified OS_TASK_OPT_STK_CHK when the task was created
+*              OS_ERR_PDATA_NULL      if 'p_stk_data' is a NULL pointer
+*********************************************************************************************************
+*/
+#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
+INT8U  OSTaskStkChk (INT8U         prio,
+                     OS_STK_DATA  *p_stk_data)
+{
+    OS_TCB    *ptcb;
+    OS_STK    *pchk;
+    INT32U     nfree;
+    INT32U     size;
+#if OS_CRITICAL_METHOD == 3u                           /* Allocate storage for CPU status register     */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (prio > OS_LOWEST_PRIO) {                       /* Make sure task priority is valid             */
+        if (prio != OS_PRIO_SELF) {
+            return (OS_ERR_PRIO_INVALID);
+        }
+    }
+    if (p_stk_data == (OS_STK_DATA *)0) {              /* Validate 'p_stk_data'                        */
+        return (OS_ERR_PDATA_NULL);
+    }
+#endif
+    p_stk_data->OSFree = 0u;                           /* Assume failure, set to 0 size                */
+    p_stk_data->OSUsed = 0u;
+    OS_ENTER_CRITICAL();
+    if (prio == OS_PRIO_SELF) {                        /* See if check for SELF                        */
+        prio = OSTCBCur->OSTCBPrio;
+    }
+    ptcb = OSTCBPrioTbl[prio];
+    if (ptcb == (OS_TCB *)0) {                         /* Make sure task exist                         */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_NOT_EXIST);
+    }
+    if (ptcb == OS_TCB_RESERVED) {
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_NOT_EXIST);
+    }
+    if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0u) { /* Make sure stack checking option is set      */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_OPT);
+    }
+    nfree = 0u;
+    size  = ptcb->OSTCBStkSize;
+    pchk  = ptcb->OSTCBStkBottom;
+    OS_EXIT_CRITICAL();
+#if OS_STK_GROWTH == 1u
+    while (*pchk++ == (OS_STK)0) {                    /* Compute the number of zero entries on the stk */
+        nfree++;
+    }
+#else
+    while (*pchk-- == (OS_STK)0) {
+        nfree++;
+    }
+#endif
+    p_stk_data->OSFree = nfree;                       /* Store   number of free entries on the stk     */
+    p_stk_data->OSUsed = size - nfree;                /* Compute number of entries used on the stk     */
+    return (OS_ERR_NONE);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                           SUSPEND A TASK
+*
+* Description: This function is called to suspend a task.  The task can be the calling task if the
+*              priority passed to OSTaskSuspend() is the priority of the calling task or OS_PRIO_SELF.
+*
+* Arguments  : prio     is the priority of the task to suspend.  If you specify OS_PRIO_SELF, the
+*                       calling task will suspend itself and rescheduling will occur.
+*
+* Returns    : OS_ERR_NONE               if the requested task is suspended
+*              OS_ERR_TASK_SUSPEND_IDLE  if you attempted to suspend the idle task which is not allowed.
+*              OS_ERR_PRIO_INVALID       if the priority you specify is higher that the maximum allowed
+*                                        (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
+*              OS_ERR_TASK_SUSPEND_PRIO  if the task to suspend does not exist
+*              OS_ERR_TASK_NOT_EXITS     if the task is assigned to a Mutex PIP
+*
+* Note       : You should use this function with great care.  If you suspend a task that is waiting for
+*              an event (i.e. a message, a semaphore, a queue ...) you will prevent this task from
+*              running when the event arrives.
+*********************************************************************************************************
+*/
+
+#if OS_TASK_SUSPEND_EN > 0u
+INT8U  OSTaskSuspend (INT8U prio)
+{
+    BOOLEAN    self;
+    OS_TCB    *ptcb;
+    INT8U      y;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (prio == OS_TASK_IDLE_PRIO) {                            /* Not allowed to suspend idle task    */
+        return (OS_ERR_TASK_SUSPEND_IDLE);
+    }
+    if (prio >= OS_LOWEST_PRIO) {                               /* Task priority valid ?               */
+        if (prio != OS_PRIO_SELF) {
+            return (OS_ERR_PRIO_INVALID);
+        }
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    if (prio == OS_PRIO_SELF) {                                 /* See if suspend SELF                 */
+        prio = OSTCBCur->OSTCBPrio;
+        self = OS_TRUE;
+    } else if (prio == OSTCBCur->OSTCBPrio) {                   /* See if suspending self              */
+        self = OS_TRUE;
+    } else {
+        self = OS_FALSE;                                        /* No suspending another task          */
+    }
+    ptcb = OSTCBPrioTbl[prio];
+    if (ptcb == (OS_TCB *)0) {                                  /* Task to suspend must exist          */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_SUSPEND_PRIO);
+    }
+    if (ptcb == OS_TCB_RESERVED) {                              /* See if assigned to Mutex            */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_NOT_EXIST);
+    }
+    y            = ptcb->OSTCBY;
+    OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX;                   /* Make task not ready                 */
+    if (OSRdyTbl[y] == 0u) {
+        OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
+    }
+    ptcb->OSTCBStat |= OS_STAT_SUSPEND;                         /* Status of task is 'SUSPENDED'       */
+    OS_EXIT_CRITICAL();
+    if (self == OS_TRUE) {                                      /* Context switch only if SELF         */
+        OS_Sched();                                             /* Find new highest priority task      */
+    }
+    return (OS_ERR_NONE);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                            QUERY A TASK
+*
+* Description: This function is called to obtain a copy of the desired task's TCB.
+*
+* Arguments  : prio         is the priority of the task to obtain information from.
+*
+*              p_task_data  is a pointer to where the desired task's OS_TCB will be stored.
+*
+* Returns    : OS_ERR_NONE            if the requested task is suspended
+*              OS_ERR_PRIO_INVALID    if the priority you specify is higher that the maximum allowed
+*                                     (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
+*              OS_ERR_PRIO            if the desired task has not been created
+*              OS_ERR_TASK_NOT_EXIST  if the task is assigned to a Mutex PIP
+*              OS_ERR_PDATA_NULL      if 'p_task_data' is a NULL pointer
+*********************************************************************************************************
+*/
+
+#if OS_TASK_QUERY_EN > 0u
+INT8U  OSTaskQuery (INT8U    prio,
+                    OS_TCB  *p_task_data)
+{
+    OS_TCB    *ptcb;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+#if OS_ARG_CHK_EN > 0u
+    if (prio > OS_LOWEST_PRIO) {                 /* Task priority valid ?                              */
+        if (prio != OS_PRIO_SELF) {
+            return (OS_ERR_PRIO_INVALID);
+        }
+    }
+    if (p_task_data == (OS_TCB *)0) {            /* Validate 'p_task_data'                             */
+        return (OS_ERR_PDATA_NULL);
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    if (prio == OS_PRIO_SELF) {                  /* See if suspend SELF                                */
+        prio = OSTCBCur->OSTCBPrio;
+    }
+    ptcb = OSTCBPrioTbl[prio];
+    if (ptcb == (OS_TCB *)0) {                   /* Task to query must exist                           */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_PRIO);
+    }
+    if (ptcb == OS_TCB_RESERVED) {               /* Task to query must not be assigned to a Mutex      */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_NOT_EXIST);
+    }
+                                                 /* Copy TCB into user storage area                    */
+    OS_MemCopy((INT8U *)p_task_data, (INT8U *)ptcb, sizeof(OS_TCB));
+    OS_EXIT_CRITICAL();
+    return (OS_ERR_NONE);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                              GET THE CURRENT VALUE OF A TASK REGISTER
+*
+* Description: This function is called to obtain the current value of a task register.  Task registers
+*              are application specific and can be used to store task specific values such as 'error
+*              numbers' (i.e. errno), statistics, etc.  Each task register can hold a 32-bit value.
+*
+* Arguments  : prio      is the priority of the task you want to get the task register from.  If you
+*                        specify OS_PRIO_SELF then the task register of the current task will be obtained.
+*
+*              id        is the 'id' of the desired task register.  Note that the 'id' must be less
+*                        than OS_TASK_REG_TBL_SIZE
+*
+*              perr      is a pointer to a variable that will hold an error code related to this call.
+*
+*                        OS_ERR_NONE            if the call was successful
+*                        OS_ERR_PRIO_INVALID    if you specified an invalid priority
+*                        OS_ERR_ID_INVALID      if the 'id' is not between 0 and OS_TASK_REG_TBL_SIZE-1
+*
+* Returns    : The current value of the task's register or 0 if an error is detected.
+*
+* Note(s)    : The maximum number of task variables is 254
+*********************************************************************************************************
+*/
+
+#if OS_TASK_REG_TBL_SIZE > 0u
+INT32U  OSTaskRegGet (INT8U   prio,
+                      INT8U   id,
+                      INT8U  *perr)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+    INT32U     value;
+    OS_TCB    *ptcb;
+
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (prio >= OS_LOWEST_PRIO) {
+        if (prio != OS_PRIO_SELF) {
+            *perr = OS_ERR_PRIO_INVALID;
+            return (0u);
+        }
+    }
+    if (id >= OS_TASK_REG_TBL_SIZE) {
+        *perr = OS_ERR_ID_INVALID;
+        return (0u);
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    if (prio == OS_PRIO_SELF) {                  /* See if need to get register from current task      */
+        ptcb = OSTCBCur;
+    } else {
+        ptcb = OSTCBPrioTbl[prio];
+    }
+    value = ptcb->OSTCBRegTbl[id];
+    OS_EXIT_CRITICAL();
+    *perr = OS_ERR_NONE;
+    return (value);
+}
+#endif
+
+/*$PAGE*/
+/*
+************************************************************************************************************************
+*                                    ALLOCATE THE NEXT AVAILABLE TASK REGISTER ID
+*
+* Description: This function is called to obtain a task register ID.  This function thus allows task registers IDs to be
+*              allocated dynamically instead of statically.
+*
+* Arguments  : p_err       is a pointer to a variable that will hold an error code related to this call.
+*
+*                            OS_ERR_NONE               if the call was successful
+*                            OS_ERR_NO_MORE_ID_AVAIL   if you are attempting to assign more task register IDs than you 
+*                                                           have available through OS_TASK_REG_TBL_SIZE.
+*
+* Returns    : The next available task register 'id' or OS_TASK_REG_TBL_SIZE if an error is detected.
+************************************************************************************************************************
+*/
+
+#if OS_TASK_REG_TBL_SIZE > 0u
+INT8U  OSTaskRegGetID (INT8U  *perr)
+{
+#if OS_CRITICAL_METHOD == 3u                                    /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+    INT8U      id;
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((INT8U)OS_TASK_REG_TBL_SIZE);
+    }
+#endif
+
+    OS_ENTER_CRITICAL();
+    if (OSTaskRegNextAvailID >= OS_TASK_REG_TBL_SIZE) {         /* See if we exceeded the number of IDs available     */
+       *perr = OS_ERR_NO_MORE_ID_AVAIL;                         /* Yes, cannot allocate more task register IDs        */
+        OS_EXIT_CRITICAL();
+        return ((INT8U)OS_TASK_REG_TBL_SIZE);
+    }
+     
+    id   = OSTaskRegNextAvailID;                                /* Assign the next available ID                       */
+    OSTaskRegNextAvailID++;                                     /* Increment available ID for next request            */
+    OS_EXIT_CRITICAL();
+   *perr = OS_ERR_NONE;
+    return (id);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                              SET THE CURRENT VALUE OF A TASK VARIABLE
+*
+* Description: This function is called to change the current value of a task register.  Task registers
+*              are application specific and can be used to store task specific values such as 'error
+*              numbers' (i.e. errno), statistics, etc.  Each task register can hold a 32-bit value.
+*
+* Arguments  : prio      is the priority of the task you want to set the task register for.  If you
+*                        specify OS_PRIO_SELF then the task register of the current task will be obtained.
+*
+*              id        is the 'id' of the desired task register.  Note that the 'id' must be less
+*                        than OS_TASK_REG_TBL_SIZE
+*
+*              value     is the desired value for the task register.
+*
+*              perr      is a pointer to a variable that will hold an error code related to this call.
+*
+*                        OS_ERR_NONE            if the call was successful
+*                        OS_ERR_PRIO_INVALID    if you specified an invalid priority
+*                        OS_ERR_ID_INVALID      if the 'id' is not between 0 and OS_TASK_REG_TBL_SIZE-1
+*
+* Returns    : The current value of the task's variable or 0 if an error is detected.
+*
+* Note(s)    : The maximum number of task variables is 254
+*********************************************************************************************************
+*/
+
+#if OS_TASK_REG_TBL_SIZE > 0u
+void  OSTaskRegSet (INT8U    prio,
+                    INT8U    id,
+                    INT32U   value,
+                    INT8U   *perr)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+    OS_TCB    *ptcb;
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return;
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (prio >= OS_LOWEST_PRIO) {
+        if (prio != OS_PRIO_SELF) {
+            *perr = OS_ERR_PRIO_INVALID;
+            return;
+        }
+    }
+    if (id >= OS_TASK_REG_TBL_SIZE) {
+        *perr = OS_ERR_ID_INVALID;
+        return;
+    }
+#endif
+    OS_ENTER_CRITICAL();
+    if (prio == OS_PRIO_SELF) {                  /* See if need to get register from current task      */
+        ptcb = OSTCBCur;
+    } else {
+        ptcb = OSTCBPrioTbl[prio];
+    }
+    ptcb->OSTCBRegTbl[id] = value;
+    OS_EXIT_CRITICAL();
+    *perr                 = OS_ERR_NONE;
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                    CATCH ACCIDENTAL TASK RETURN
+*
+* Description: This function is called if a task accidentally returns without deleting itself.  In other
+*              words, a task should either be an infinite loop or delete itself if it's done.
+*
+* Arguments  : none
+*
+* Returns    : none
+*
+* Note(s)    : This function is INTERNAL to uC/OS-II and your application should not call it.
+*********************************************************************************************************
+*/
+
+void  OS_TaskReturn (void)
+{
+    OSTaskReturnHook(OSTCBCur);                   /* Call hook to let user decide on what to do        */
+
+#if OS_TASK_DEL_EN > 0u
+    (void)OSTaskDel(OS_PRIO_SELF);                /* Delete task if it accidentally returns!           */
+#else
+    for (;;) {
+        OSTimeDly(OS_TICKS_PER_SEC);
+    }
+#endif
+}
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                          CLEAR TASK STACK
+*
+* Description: This function is used to clear the stack of a task (i.e. write all zeros)
+*
+* Arguments  : pbos     is a pointer to the task's bottom of stack.  If the configuration constant
+*                       OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
+*                       memory to low memory).  'pbos' will thus point to the lowest (valid) memory
+*                       location of the stack.  If OS_STK_GROWTH is set to 0, 'pbos' will point to the
+*                       highest memory location of the stack and the stack will grow with increasing
+*                       memory locations.  'pbos' MUST point to a valid 'free' data item.
+*
+*              size     is the number of 'stack elements' to clear.
+*
+*              opt      contains additional information (or options) about the behavior of the task.  The
+*                       LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application
+*                       specific.  See OS_TASK_OPT_??? in uCOS-II.H.
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
+void  OS_TaskStkClr (OS_STK  *pbos,
+                     INT32U   size,
+                     INT16U   opt)
+{
+    if ((opt & OS_TASK_OPT_STK_CHK) != 0x0000u) {      /* See if stack checking has been enabled       */
+        if ((opt & OS_TASK_OPT_STK_CLR) != 0x0000u) {  /* See if stack needs to be cleared             */
+#if OS_STK_GROWTH == 1u
+            while (size > 0u) {                        /* Stack grows from HIGH to LOW memory          */
+                size--;
+                *pbos++ = (OS_STK)0;                   /* Clear from bottom of stack and up!           */
+            }
+#else
+            while (size > 0u) {                        /* Stack grows from LOW to HIGH memory          */
+                size--;
+                *pbos-- = (OS_STK)0;                   /* Clear from bottom of stack and down          */
+            }
+#endif
+        }
+    }
+}
+
+#endif

+ 265 - 0
MiddleWare/uCOS_II/uCOS-II/Source/os_time.c

@@ -0,0 +1,265 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                             TIME MANAGEMENT
+*
+*                              (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : OS_TIME.C
+* By      : Jean J. Labrosse
+* Version : V2.92.11
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#define  MICRIUM_SOURCE
+
+#ifndef  OS_MASTER_FILE
+#include <ucos_ii.h>
+#endif
+
+/*
+*********************************************************************************************************
+*                                        DELAY TASK 'n' TICKS
+*
+* Description: This function is called to delay execution of the currently running task until the
+*              specified number of system ticks expires.  This, of course, directly equates to delaying
+*              the current task for some time to expire.  No delay will result If the specified delay is
+*              0.  If the specified delay is greater than 0 then, a context switch will result.
+*
+* Arguments  : ticks     is the time delay that the task will be suspended in number of clock 'ticks'.
+*                        Note that by specifying 0, the task will not be delayed.
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+void  OSTimeDly (INT32U ticks)
+{
+    INT8U      y;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
+        return;
+    }
+    if (OSLockNesting > 0u) {                    /* See if called with scheduler locked                */
+        return;
+    }
+    if (ticks > 0u) {                            /* 0 means no delay!                                  */
+        OS_ENTER_CRITICAL();
+        y            =  OSTCBCur->OSTCBY;        /* Delay current task                                 */
+        OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
+        if (OSRdyTbl[y] == 0u) {
+            OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
+        }
+        OSTCBCur->OSTCBDly = ticks;              /* Load ticks in TCB                                  */
+        OS_EXIT_CRITICAL();
+        OS_Sched();                              /* Find next task to run!                             */
+    }
+}
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                    DELAY TASK FOR SPECIFIED TIME
+*
+* Description: This function is called to delay execution of the currently running task until some time
+*              expires.  This call allows you to specify the delay time in HOURS, MINUTES, SECONDS and
+*              MILLISECONDS instead of ticks.
+*
+* Arguments  : hours     specifies the number of hours that the task will be delayed (max. is 255)
+*              minutes   specifies the number of minutes (max. 59)
+*              seconds   specifies the number of seconds (max. 59)
+*              ms        specifies the number of milliseconds (max. 999)
+*
+* Returns    : OS_ERR_NONE
+*              OS_ERR_TIME_INVALID_MINUTES
+*              OS_ERR_TIME_INVALID_SECONDS
+*              OS_ERR_TIME_INVALID_MS
+*              OS_ERR_TIME_ZERO_DLY
+*              OS_ERR_TIME_DLY_ISR
+*
+* Note(s)    : The resolution on the milliseconds depends on the tick rate.  For example, you can't do
+*              a 10 mS delay if the ticker interrupts every 100 mS.  In this case, the delay would be
+*              set to 0.  The actual delay is rounded to the nearest tick.
+*********************************************************************************************************
+*/
+
+#if OS_TIME_DLY_HMSM_EN > 0u
+INT8U  OSTimeDlyHMSM (INT8U   hours,
+                      INT8U   minutes,
+                      INT8U   seconds,
+                      INT16U  ms)
+{
+    INT32U ticks;
+
+
+    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
+        return (OS_ERR_TIME_DLY_ISR);
+    }
+    if (OSLockNesting > 0u) {                    /* See if called with scheduler locked                */
+        return (OS_ERR_SCHED_LOCKED);
+    }
+#if OS_ARG_CHK_EN > 0u
+    if (hours == 0u) {
+        if (minutes == 0u) {
+            if (seconds == 0u) {
+                if (ms == 0u) {
+                    return (OS_ERR_TIME_ZERO_DLY);
+                }
+            }
+        }
+    }
+    if (minutes > 59u) {
+        return (OS_ERR_TIME_INVALID_MINUTES);    /* Validate arguments to be within range              */
+    }
+    if (seconds > 59u) {
+        return (OS_ERR_TIME_INVALID_SECONDS);
+    }
+    if (ms > 999u) {
+        return (OS_ERR_TIME_INVALID_MS);
+    }
+#endif
+                                                 /* Compute the total number of clock ticks required.. */
+                                                 /* .. (rounded to the nearest tick)                   */
+    ticks = ((INT32U)hours * 3600uL + (INT32U)minutes * 60uL + (INT32U)seconds) * OS_TICKS_PER_SEC
+          + OS_TICKS_PER_SEC * ((INT32U)ms + 500uL / OS_TICKS_PER_SEC) / 1000uL;
+    OSTimeDly(ticks);
+    return (OS_ERR_NONE);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                        RESUME A DELAYED TASK
+*
+* Description: This function is used resume a task that has been delayed through a call to either
+*              OSTimeDly() or OSTimeDlyHMSM().  Note that you can call this function to resume a
+*              task that is waiting for an event with timeout.  This would make the task look
+*              like a timeout occurred.
+*
+* Arguments  : prio                      specifies the priority of the task to resume
+*
+* Returns    : OS_ERR_NONE               Task has been resumed
+*              OS_ERR_PRIO_INVALID       if the priority you specify is higher that the maximum allowed
+*                                        (i.e. >= OS_LOWEST_PRIO)
+*              OS_ERR_TIME_NOT_DLY       Task is not waiting for time to expire
+*              OS_ERR_TASK_NOT_EXIST     The desired task has not been created or has been assigned to a Mutex.
+*********************************************************************************************************
+*/
+
+#if OS_TIME_DLY_RESUME_EN > 0u
+INT8U  OSTimeDlyResume (INT8U prio)
+{
+    OS_TCB    *ptcb;
+#if OS_CRITICAL_METHOD == 3u                                   /* Storage for CPU status register      */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    if (prio >= OS_LOWEST_PRIO) {
+        return (OS_ERR_PRIO_INVALID);
+    }
+    OS_ENTER_CRITICAL();
+    ptcb = OSTCBPrioTbl[prio];                                 /* Make sure that task exist            */
+    if (ptcb == (OS_TCB *)0) {
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_NOT_EXIST);                        /* The task does not exist              */
+    }
+    if (ptcb == OS_TCB_RESERVED) {
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TASK_NOT_EXIST);                        /* The task does not exist              */
+    }
+    if (ptcb->OSTCBDly == 0u) {                                /* See if task is delayed               */
+        OS_EXIT_CRITICAL();
+        return (OS_ERR_TIME_NOT_DLY);                          /* Indicate that task was not delayed   */
+    }
+
+    ptcb->OSTCBDly = 0u;                                       /* Clear the time delay                 */
+    if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
+        ptcb->OSTCBStat     &= ~OS_STAT_PEND_ANY;              /* Yes, Clear status flag               */
+        ptcb->OSTCBStatPend  =  OS_STAT_PEND_TO;               /* Indicate PEND timeout                */
+    } else {
+        ptcb->OSTCBStatPend  =  OS_STAT_PEND_OK;
+    }
+    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {  /* Is task suspended?                   */
+        OSRdyGrp               |= ptcb->OSTCBBitY;             /* No,  Make ready                      */
+        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
+        OS_EXIT_CRITICAL();
+        OS_Sched();                                            /* See if this is new highest priority  */
+    } else {
+        OS_EXIT_CRITICAL();                                    /* Task may be suspended                */
+    }
+    return (OS_ERR_NONE);
+}
+#endif
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       GET CURRENT SYSTEM TIME
+*
+* Description: This function is used by your application to obtain the current value of the 32-bit
+*              counter which keeps track of the number of clock ticks.
+*
+* Arguments  : none
+*
+* Returns    : The current value of OSTime
+*********************************************************************************************************
+*/
+
+#if OS_TIME_GET_SET_EN > 0u
+INT32U  OSTimeGet (void)
+{
+    INT32U     ticks;
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    OS_ENTER_CRITICAL();
+    ticks = OSTime;
+    OS_EXIT_CRITICAL();
+    return (ticks);
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                          SET SYSTEM CLOCK
+*
+* Description: This function sets the 32-bit counter which keeps track of the number of clock ticks.
+*
+* Arguments  : ticks      specifies the new value that OSTime needs to take.
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+#if OS_TIME_GET_SET_EN > 0u
+void  OSTimeSet (INT32U ticks)
+{
+#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
+    OS_CPU_SR  cpu_sr = 0u;
+#endif
+
+
+
+    OS_ENTER_CRITICAL();
+    OSTime = ticks;
+    OS_EXIT_CRITICAL();
+}
+#endif

+ 1089 - 0
MiddleWare/uCOS_II/uCOS-II/Source/os_tmr.c

@@ -0,0 +1,1089 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                            TIMER MANAGEMENT
+*
+*                              (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+*
+* File    : OS_TMR.C
+* By      : Jean J. Labrosse
+* Version : V2.92.11
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#define  MICRIUM_SOURCE
+
+#ifndef  OS_MASTER_FILE
+#include <ucos_ii.h>
+#endif
+
+/*
+*********************************************************************************************************
+*                                                        NOTES
+*
+* 1) Your application MUST define the following #define constants:
+*
+*    OS_TASK_TMR_PRIO          The priority of the Timer management task
+*    OS_TASK_TMR_STK_SIZE      The size     of the Timer management task's stack
+*
+* 2) You must call OSTmrSignal() to notify the Timer management task that it's time to update the timers.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                              CONSTANTS
+*********************************************************************************************************
+*/
+
+#define  OS_TMR_LINK_DLY       0u
+#define  OS_TMR_LINK_PERIODIC  1u
+
+/*
+*********************************************************************************************************
+*                                          LOCAL PROTOTYPES
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+static  OS_TMR  *OSTmr_Alloc         (void);
+static  void     OSTmr_Free          (OS_TMR *ptmr);
+static  void     OSTmr_InitTask      (void);
+static  void     OSTmr_Link          (OS_TMR *ptmr, INT8U type);
+static  void     OSTmr_Unlink        (OS_TMR *ptmr);
+static  void     OSTmr_Task          (void   *p_arg);
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                           CREATE A TIMER
+*
+* Description: This function is called by your application code to create a timer.
+*
+* Arguments  : dly           Initial delay.
+*                            If the timer is configured for ONE-SHOT mode, this is the timeout used.
+*                            If the timer is configured for PERIODIC mode, this is the first timeout to 
+*                               wait for before the timer starts entering periodic mode.
+*
+*              period        The 'period' being repeated for the timer.
+*                               If you specified 'OS_TMR_OPT_PERIODIC' as an option, when the timer 
+*                               expires, it will automatically restart with the same period.
+*
+*              opt           Specifies either:
+*                               OS_TMR_OPT_ONE_SHOT       The timer counts down only once
+*                               OS_TMR_OPT_PERIODIC       The timer counts down and then reloads itself
+*
+*              callback      Is a pointer to a callback function that will be called when the timer expires. 
+*                               The callback function must be declared as follows:
+*
+*                               void MyCallback (OS_TMR *ptmr, void *p_arg);
+*
+*              callback_arg  Is an argument (a pointer) that is passed to the callback function when it is called.
+*
+*              pname         Is a pointer to an ASCII string that is used to name the timer.  Names are 
+*                               useful for debugging.
+*
+*              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
+*                               OS_ERR_NONE
+*                               OS_ERR_TMR_INVALID_DLY     you specified an invalid delay
+*                               OS_ERR_TMR_INVALID_PERIOD  you specified an invalid period
+*                               OS_ERR_TMR_INVALID_OPT     you specified an invalid option
+*                               OS_ERR_TMR_ISR             if the call was made from an ISR
+*                               OS_ERR_TMR_NON_AVAIL       if there are no free timers from the timer pool
+*
+* Returns    : A pointer to an OS_TMR data structure.
+*              This is the 'handle' that your application will use to reference the timer created.
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+OS_TMR  *OSTmrCreate (INT32U           dly,
+                      INT32U           period,
+                      INT8U            opt,
+                      OS_TMR_CALLBACK  callback,
+                      void            *callback_arg,
+                      INT8U           *pname,
+                      INT8U           *perr)
+{
+    OS_TMR   *ptmr;
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_TMR *)0);
+    }
+#endif
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    if (OSSafetyCriticalStartFlag == OS_TRUE) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return ((OS_TMR *)0);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    switch (opt) {                                          /* Validate arguments                                     */
+        case OS_TMR_OPT_PERIODIC:
+             if (period == 0u) {
+                 *perr = OS_ERR_TMR_INVALID_PERIOD;
+                 return ((OS_TMR *)0);
+             }
+             break;
+
+        case OS_TMR_OPT_ONE_SHOT:
+             if (dly == 0u) {
+                 *perr = OS_ERR_TMR_INVALID_DLY;
+                 return ((OS_TMR *)0);
+             }
+             break;
+
+        default:
+             *perr = OS_ERR_TMR_INVALID_OPT;
+             return ((OS_TMR *)0);
+    }
+#endif
+    if (OSIntNesting > 0u) {                                /* See if trying to call from an ISR                      */
+        *perr  = OS_ERR_TMR_ISR;
+        return ((OS_TMR *)0);
+    }
+    OSSchedLock();
+    ptmr = OSTmr_Alloc();                                   /* Obtain a timer from the free pool                      */
+    if (ptmr == (OS_TMR *)0) {
+        OSSchedUnlock();
+        *perr = OS_ERR_TMR_NON_AVAIL;
+        return ((OS_TMR *)0);
+    }
+    ptmr->OSTmrState       = OS_TMR_STATE_STOPPED;          /* Indicate that timer is not running yet                 */
+    ptmr->OSTmrDly         = dly;
+    ptmr->OSTmrPeriod      = period;
+    ptmr->OSTmrOpt         = opt;
+    ptmr->OSTmrCallback    = callback;
+    ptmr->OSTmrCallbackArg = callback_arg;
+#if OS_TMR_CFG_NAME_EN > 0u
+    if (pname == (INT8U *)0) {                              /* Is 'pname' a NULL pointer?                             */
+        ptmr->OSTmrName    = (INT8U *)(void *)"?";
+    } else {
+        ptmr->OSTmrName    = pname;
+    }
+#endif
+    OSSchedUnlock();
+    *perr = OS_ERR_NONE;
+    return (ptmr);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                           DELETE A TIMER
+*
+* Description: This function is called by your application code to delete a timer.
+*
+* Arguments  : ptmr          Is a pointer to the timer to stop and delete.
+*
+*              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
+*                               OS_ERR_NONE
+*                               OS_ERR_TMR_INVALID        'ptmr'  is a NULL pointer
+*                               OS_ERR_TMR_INVALID_TYPE   'ptmr'  is not pointing to an OS_TMR
+*                               OS_ERR_TMR_ISR            if the function was called from an ISR
+*                               OS_ERR_TMR_INACTIVE       if the timer was not created
+*                               OS_ERR_TMR_INVALID_STATE  the timer is in an invalid state
+*
+* Returns    : OS_TRUE       If the call was successful
+*              OS_FALSE      If not
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+BOOLEAN  OSTmrDel (OS_TMR  *ptmr,
+                   INT8U   *perr)
+{
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (OS_FALSE);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (ptmr == (OS_TMR *)0) {
+        *perr = OS_ERR_TMR_INVALID;
+        return (OS_FALSE);
+    }
+#endif
+    if (ptmr->OSTmrType != OS_TMR_TYPE) {                   /* Validate timer structure                               */
+        *perr = OS_ERR_TMR_INVALID_TYPE;
+        return (OS_FALSE);
+    }
+    if (OSIntNesting > 0u) {                                /* See if trying to call from an ISR                      */
+        *perr  = OS_ERR_TMR_ISR;
+        return (OS_FALSE);
+    }
+    OSSchedLock();
+    switch (ptmr->OSTmrState) {
+        case OS_TMR_STATE_RUNNING:
+             OSTmr_Unlink(ptmr);                            /* Remove from current wheel spoke                        */
+             OSTmr_Free(ptmr);                              /* Return timer to free list of timers                    */
+             OSSchedUnlock();
+             *perr = OS_ERR_NONE;
+             return (OS_TRUE);
+
+        case OS_TMR_STATE_STOPPED:                          /* Timer has not started or ...                           */
+        case OS_TMR_STATE_COMPLETED:                        /* ... timer has completed the ONE-SHOT time              */
+             OSTmr_Free(ptmr);                              /* Return timer to free list of timers                    */
+             OSSchedUnlock();
+             *perr = OS_ERR_NONE;
+             return (OS_TRUE);
+
+        case OS_TMR_STATE_UNUSED:                           /* Already deleted                                        */
+             OSSchedUnlock();
+             *perr = OS_ERR_TMR_INACTIVE;
+             return (OS_FALSE);
+
+        default:
+             OSSchedUnlock();
+             *perr = OS_ERR_TMR_INVALID_STATE;
+             return (OS_FALSE);
+    }
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                       GET THE NAME OF A TIMER
+*
+* Description: This function is called to obtain the name of a timer.
+*
+* Arguments  : ptmr          Is a pointer to the timer to obtain the name for
+*
+*              pdest         Is a pointer to pointer to where the name of the timer will be placed.
+*
+*              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
+*                               OS_ERR_NONE               The call was successful
+*                               OS_ERR_TMR_INVALID_DEST   'pdest' is a NULL pointer
+*                               OS_ERR_TMR_INVALID        'ptmr'  is a NULL pointer
+*                               OS_ERR_TMR_INVALID_TYPE   'ptmr'  is not pointing to an OS_TMR
+*                               OS_ERR_NAME_GET_ISR       if the call was made from an ISR
+*                               OS_ERR_TMR_INACTIVE       'ptmr'  points to a timer that is not active
+*                               OS_ERR_TMR_INVALID_STATE  the timer is in an invalid state
+*
+* Returns    : The length of the string or 0 if the timer does not exist.
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u && OS_TMR_CFG_NAME_EN > 0u
+INT8U  OSTmrNameGet (OS_TMR   *ptmr,
+                     INT8U   **pdest,
+                     INT8U    *perr)
+{
+    INT8U  len;
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (pdest == (INT8U **)0) {
+        *perr = OS_ERR_TMR_INVALID_DEST;
+        return (0u);
+    }
+    if (ptmr == (OS_TMR *)0) {
+        *perr = OS_ERR_TMR_INVALID;
+        return (0u);
+    }
+#endif
+    if (ptmr->OSTmrType != OS_TMR_TYPE) {              /* Validate timer structure                                    */
+        *perr = OS_ERR_TMR_INVALID_TYPE;
+        return (0u);
+    }
+    if (OSIntNesting > 0u) {                           /* See if trying to call from an ISR                           */
+        *perr = OS_ERR_NAME_GET_ISR;
+        return (0u);
+    }
+    OSSchedLock();
+    switch (ptmr->OSTmrState) {
+        case OS_TMR_STATE_RUNNING:
+        case OS_TMR_STATE_STOPPED:
+        case OS_TMR_STATE_COMPLETED:
+             *pdest = ptmr->OSTmrName;
+             len    = OS_StrLen(*pdest);
+             OSSchedUnlock();
+             *perr = OS_ERR_NONE;
+             return (len);
+
+        case OS_TMR_STATE_UNUSED:                      /* Timer is not allocated                                      */
+             OSSchedUnlock();
+             *perr = OS_ERR_TMR_INACTIVE;
+             return (0u);
+
+        default:
+             OSSchedUnlock();
+             *perr = OS_ERR_TMR_INVALID_STATE;
+             return (0u);
+    }
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                          GET HOW MUCH TIME IS LEFT BEFORE A TIMER EXPIRES
+*
+* Description: This function is called to get the number of ticks before a timer times out.
+*
+* Arguments  : ptmr          Is a pointer to the timer to obtain the remaining time from.
+*
+*              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
+*                               OS_ERR_NONE
+*                               OS_ERR_TMR_INVALID        'ptmr' is a NULL pointer
+*                               OS_ERR_TMR_INVALID_TYPE   'ptmr'  is not pointing to an OS_TMR
+*                               OS_ERR_TMR_ISR            if the call was made from an ISR
+*                               OS_ERR_TMR_INACTIVE       'ptmr' points to a timer that is not active
+*                               OS_ERR_TMR_INVALID_STATE  the timer is in an invalid state
+*
+* Returns    : The time remaining for the timer to expire.  The time represents 'timer' increments. 
+*              In other words, if OSTmr_Task() is signaled every 1/10 of a second then the returned 
+*              value represents the number of 1/10 of a second remaining before the timer expires.
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+INT32U  OSTmrRemainGet (OS_TMR  *ptmr,
+                        INT8U   *perr)
+{
+    INT32U  remain;
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (ptmr == (OS_TMR *)0) {
+        *perr = OS_ERR_TMR_INVALID;
+        return (0u);
+    }
+#endif
+    if (ptmr->OSTmrType != OS_TMR_TYPE) {              /* Validate timer structure                                    */
+        *perr = OS_ERR_TMR_INVALID_TYPE;
+        return (0u);
+    }
+    if (OSIntNesting > 0u) {                           /* See if trying to call from an ISR                           */
+        *perr = OS_ERR_TMR_ISR;
+        return (0u);
+    }
+    OSSchedLock();
+    switch (ptmr->OSTmrState) {
+        case OS_TMR_STATE_RUNNING:
+             remain = ptmr->OSTmrMatch - OSTmrTime;    /* Determine how much time is left to timeout                  */
+             OSSchedUnlock();
+             *perr  = OS_ERR_NONE;
+             return (remain);
+
+        case OS_TMR_STATE_STOPPED:                     /* It's assumed that the timer has not started yet             */
+             switch (ptmr->OSTmrOpt) {
+                 case OS_TMR_OPT_PERIODIC:
+                      if (ptmr->OSTmrDly == 0u) {
+                          remain = ptmr->OSTmrPeriod;
+                      } else {
+                          remain = ptmr->OSTmrDly;
+                      }
+                      OSSchedUnlock();
+                      *perr  = OS_ERR_NONE;
+                      break;
+
+                 case OS_TMR_OPT_ONE_SHOT:
+                 default:
+                      remain = ptmr->OSTmrDly;
+                      OSSchedUnlock();
+                      *perr  = OS_ERR_NONE;
+                      break;
+             }
+             return (remain);
+
+        case OS_TMR_STATE_COMPLETED:                   /* Only ONE-SHOT that timed out can be in this state           */
+             OSSchedUnlock();
+             *perr = OS_ERR_NONE;
+             return (0u);
+
+        case OS_TMR_STATE_UNUSED:
+             OSSchedUnlock();
+             *perr = OS_ERR_TMR_INACTIVE;
+             return (0u);
+
+        default:
+             OSSchedUnlock();
+             *perr = OS_ERR_TMR_INVALID_STATE;
+             return (0u);
+    }
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                  FIND OUT WHAT STATE A TIMER IS IN
+*
+* Description: This function is called to determine what state the timer is in:
+*
+*                  OS_TMR_STATE_UNUSED     the timer has not been created
+*                  OS_TMR_STATE_STOPPED    the timer has been created but has not been started or has been stopped
+*                  OS_TMR_STATE_COMPLETED  the timer is in ONE-SHOT mode and has completed it's timeout
+*                  OS_TMR_STATE_RUNNING    the timer is currently running
+*
+* Arguments  : ptmr          Is a pointer to the desired timer
+*
+*              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
+*                               OS_ERR_NONE
+*                               OS_ERR_TMR_INVALID        'ptmr' is a NULL pointer
+*                               OS_ERR_TMR_INVALID_TYPE   'ptmr'  is not pointing to an OS_TMR
+*                               OS_ERR_TMR_ISR            if the call was made from an ISR
+*                               OS_ERR_TMR_INACTIVE       'ptmr' points to a timer that is not active
+*                               OS_ERR_TMR_INVALID_STATE  if the timer is not in a valid state
+*
+* Returns    : The current state of the timer (see description).
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+INT8U  OSTmrStateGet (OS_TMR  *ptmr,
+                      INT8U   *perr)
+{
+    INT8U  state;
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (0u);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (ptmr == (OS_TMR *)0) {
+        *perr = OS_ERR_TMR_INVALID;
+        return (0u);
+    }
+#endif
+    if (ptmr->OSTmrType != OS_TMR_TYPE) {              /* Validate timer structure                                    */
+        *perr = OS_ERR_TMR_INVALID_TYPE;
+        return (0u);
+    }
+    if (OSIntNesting > 0u) {                           /* See if trying to call from an ISR                           */
+        *perr = OS_ERR_TMR_ISR;
+        return (0u);
+    }
+    OSSchedLock();
+    state = ptmr->OSTmrState;
+    switch (state) {
+        case OS_TMR_STATE_UNUSED:
+        case OS_TMR_STATE_STOPPED:
+        case OS_TMR_STATE_COMPLETED:
+        case OS_TMR_STATE_RUNNING:
+             *perr = OS_ERR_NONE;
+             break;
+
+        default:
+             *perr = OS_ERR_TMR_INVALID_STATE;
+             break;
+    }
+    OSSchedUnlock();
+    return (state);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                            START A TIMER
+*
+* Description: This function is called by your application code to start a timer.
+*
+* Arguments  : ptmr          Is a pointer to an OS_TMR
+*
+*              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
+*                               OS_ERR_NONE
+*                               OS_ERR_TMR_INVALID
+*                               OS_ERR_TMR_INVALID_TYPE    'ptmr'  is not pointing to an OS_TMR
+*                               OS_ERR_TMR_ISR             if the call was made from an ISR
+*                               OS_ERR_TMR_INACTIVE        if the timer was not created
+*                               OS_ERR_TMR_INVALID_STATE   the timer is in an invalid state
+*
+* Returns    : OS_TRUE    if the timer was started
+*              OS_FALSE   if an error was detected
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+BOOLEAN  OSTmrStart (OS_TMR   *ptmr,
+                     INT8U    *perr)
+{
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (OS_FALSE);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (ptmr == (OS_TMR *)0) {
+        *perr = OS_ERR_TMR_INVALID;
+        return (OS_FALSE);
+    }
+#endif
+    if (ptmr->OSTmrType != OS_TMR_TYPE) {                   /* Validate timer structure                               */
+        *perr = OS_ERR_TMR_INVALID_TYPE;
+        return (OS_FALSE);
+    }
+    if (OSIntNesting > 0u) {                                /* See if trying to call from an ISR                      */
+        *perr  = OS_ERR_TMR_ISR;
+        return (OS_FALSE);
+    }
+    OSSchedLock();
+    switch (ptmr->OSTmrState) {
+        case OS_TMR_STATE_RUNNING:                          /* Restart the timer                                      */
+             OSTmr_Unlink(ptmr);                            /* ... Stop the timer                                     */
+             OSTmr_Link(ptmr, OS_TMR_LINK_DLY);             /* ... Link timer to timer wheel                          */
+             OSSchedUnlock();
+             *perr = OS_ERR_NONE;
+             return (OS_TRUE);
+
+        case OS_TMR_STATE_STOPPED:                          /* Start the timer                                        */
+        case OS_TMR_STATE_COMPLETED:
+             OSTmr_Link(ptmr, OS_TMR_LINK_DLY);             /* ... Link timer to timer wheel                          */
+             OSSchedUnlock();
+             *perr = OS_ERR_NONE;
+             return (OS_TRUE);
+
+        case OS_TMR_STATE_UNUSED:                           /* Timer not created                                      */
+             OSSchedUnlock();
+             *perr = OS_ERR_TMR_INACTIVE;
+             return (OS_FALSE);
+
+        default:
+             OSSchedUnlock();
+             *perr = OS_ERR_TMR_INVALID_STATE;
+             return (OS_FALSE);
+    }
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                            STOP A TIMER
+*
+* Description: This function is called by your application code to stop a timer.
+*
+* Arguments  : ptmr          Is a pointer to the timer to stop.
+*
+*              opt           Allows you to specify an option to this functions which can be:
+*
+*                               OS_TMR_OPT_NONE          Do nothing special but stop the timer
+*                               OS_TMR_OPT_CALLBACK      Execute the callback function, pass it the 
+*                                                        callback argument specified when the timer 
+*                                                        was created.
+*                               OS_TMR_OPT_CALLBACK_ARG  Execute the callback function, pass it the 
+*                                                        callback argument specified in THIS function call.
+*
+*              callback_arg  Is a pointer to a 'new' callback argument that can be passed to the callback 
+*                            function instead of the timer's callback argument.  In other words, use 
+*                            'callback_arg' passed in THIS function INSTEAD of ptmr->OSTmrCallbackArg.
+*
+*              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
+*                               OS_ERR_NONE
+*                               OS_ERR_TMR_INVALID         'ptmr' is a NULL pointer
+*                               OS_ERR_TMR_INVALID_TYPE    'ptmr'  is not pointing to an OS_TMR
+*                               OS_ERR_TMR_ISR             if the function was called from an ISR
+*                               OS_ERR_TMR_INACTIVE        if the timer was not created
+*                               OS_ERR_TMR_INVALID_OPT     if you specified an invalid option for 'opt'
+*                               OS_ERR_TMR_STOPPED         if the timer was already stopped
+*                               OS_ERR_TMR_INVALID_STATE   the timer is in an invalid state
+*                               OS_ERR_TMR_NO_CALLBACK     if the timer does not have a callback function defined
+*
+* Returns    : OS_TRUE       If we stopped the timer (if the timer is already stopped, we also return OS_TRUE)
+*              OS_FALSE      If not
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+BOOLEAN  OSTmrStop (OS_TMR  *ptmr,
+                    INT8U    opt,
+                    void    *callback_arg,
+                    INT8U   *perr)
+{
+    OS_TMR_CALLBACK  pfnct;
+
+
+#ifdef OS_SAFETY_CRITICAL
+    if (perr == (INT8U *)0) {
+        OS_SAFETY_CRITICAL_EXCEPTION();
+        return (OS_FALSE);
+    }
+#endif
+
+#if OS_ARG_CHK_EN > 0u
+    if (ptmr == (OS_TMR *)0) {
+        *perr = OS_ERR_TMR_INVALID;
+        return (OS_FALSE);
+    }
+#endif
+    if (ptmr->OSTmrType != OS_TMR_TYPE) {                         /* Validate timer structure                         */
+        *perr = OS_ERR_TMR_INVALID_TYPE;
+        return (OS_FALSE);
+    }
+    if (OSIntNesting > 0u) {                                      /* See if trying to call from an ISR                */
+        *perr  = OS_ERR_TMR_ISR;
+        return (OS_FALSE);
+    }
+    OSSchedLock();
+    switch (ptmr->OSTmrState) {
+        case OS_TMR_STATE_RUNNING:
+             OSTmr_Unlink(ptmr);                                  /* Remove from current wheel spoke                  */
+             *perr = OS_ERR_NONE;
+             switch (opt) {
+                 case OS_TMR_OPT_CALLBACK:
+                      pfnct = ptmr->OSTmrCallback;                /* Execute callback function if available ...       */
+                      if (pfnct != (OS_TMR_CALLBACK)0) {
+                          (*pfnct)((void *)ptmr, ptmr->OSTmrCallbackArg);  /* Use callback arg when timer was created */
+                      } else {
+                          *perr = OS_ERR_TMR_NO_CALLBACK;
+                      }
+                      break;
+
+                 case OS_TMR_OPT_CALLBACK_ARG:
+                      pfnct = ptmr->OSTmrCallback;                /* Execute callback function if available ...       */
+                      if (pfnct != (OS_TMR_CALLBACK)0) {
+                          (*pfnct)((void *)ptmr, callback_arg);   /* ... using the 'callback_arg' provided in call    */
+                      } else {
+                          *perr = OS_ERR_TMR_NO_CALLBACK;
+                      }
+                      break;
+
+                 case OS_TMR_OPT_NONE:
+                      break;
+
+                 default:
+                     *perr = OS_ERR_TMR_INVALID_OPT;
+                     break;
+             }
+             OSSchedUnlock();
+             return (OS_TRUE);
+
+        case OS_TMR_STATE_COMPLETED:                              /* Timer has already completed the ONE-SHOT or ...  */
+        case OS_TMR_STATE_STOPPED:                                /* ... timer has not started yet.                   */
+             OSSchedUnlock();
+             *perr = OS_ERR_TMR_STOPPED;
+             return (OS_TRUE);
+
+        case OS_TMR_STATE_UNUSED:                                 /* Timer was not created                            */
+             OSSchedUnlock();
+             *perr = OS_ERR_TMR_INACTIVE;
+             return (OS_FALSE);
+
+        default:
+             OSSchedUnlock();
+             *perr = OS_ERR_TMR_INVALID_STATE;
+             return (OS_FALSE);
+    }
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                             SIGNAL THAT IT'S TIME TO UPDATE THE TIMERS
+*
+* Description: This function is typically called by the ISR that occurs at the timer tick rate and is 
+*              used to signal to OSTmr_Task() that it's time to update the timers.
+*
+* Arguments  : none
+*
+* Returns    : OS_ERR_NONE         The call was successful and the timer task was signaled.
+*              OS_ERR_SEM_OVF      If OSTmrSignal() was called more often than OSTmr_Task() can handle 
+*                                  the timers. This would indicate that your system is heavily loaded.
+*              OS_ERR_EVENT_TYPE   Unlikely you would get this error because the semaphore used for 
+*                                  signaling is created by uC/OS-II.
+*              OS_ERR_PEVENT_NULL  Again, unlikely you would ever get this error because the semaphore 
+*                                  used for signaling is created by uC/OS-II.
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+INT8U  OSTmrSignal (void)
+{
+    INT8U  err;
+
+
+    err = OSSemPost(OSTmrSemSignal);
+    return (err);
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                      ALLOCATE AND FREE A TIMER
+*
+* Description: This function is called to allocate a timer.
+*
+* Arguments  : none
+*
+* Returns    : a pointer to a timer if one is available
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+static  OS_TMR  *OSTmr_Alloc (void)
+{
+    OS_TMR *ptmr;
+
+
+    if (OSTmrFreeList == (OS_TMR *)0) {
+        return ((OS_TMR *)0);
+    }
+    ptmr            = (OS_TMR *)OSTmrFreeList;
+    OSTmrFreeList   = (OS_TMR *)ptmr->OSTmrNext;
+    ptmr->OSTmrNext = (OS_TCB *)0;
+    ptmr->OSTmrPrev = (OS_TCB *)0;
+    OSTmrUsed++;
+    OSTmrFree--;
+    return (ptmr);
+}
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                   RETURN A TIMER TO THE FREE LIST
+*
+* Description: This function is called to return a timer object to the free list of timers.
+*
+* Arguments  : ptmr     is a pointer to the timer to free
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+static  void  OSTmr_Free (OS_TMR *ptmr)
+{
+    ptmr->OSTmrState       = OS_TMR_STATE_UNUSED;      /* Clear timer object fields                                   */
+    ptmr->OSTmrOpt         = OS_TMR_OPT_NONE;
+    ptmr->OSTmrPeriod      = 0u;
+    ptmr->OSTmrMatch       = 0u;
+    ptmr->OSTmrCallback    = (OS_TMR_CALLBACK)0;
+    ptmr->OSTmrCallbackArg = (void *)0;
+#if OS_TMR_CFG_NAME_EN > 0u
+    ptmr->OSTmrName        = (INT8U *)(void *)"?";
+#endif
+
+    ptmr->OSTmrPrev        = (OS_TCB *)0;              /* Chain timer to free list                                    */
+    ptmr->OSTmrNext        = OSTmrFreeList;
+    OSTmrFreeList          = ptmr;
+
+    OSTmrUsed--;                                       /* Update timer object statistics                              */
+    OSTmrFree++;
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                                    INITIALIZATION
+*                                          INITIALIZE THE FREE LIST OF TIMERS
+*
+* Description: This function is called by OSInit() to initialize the free list of OS_TMRs.
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+void  OSTmr_Init (void)
+{
+#if OS_EVENT_NAME_EN > 0u
+    INT8U    err;
+#endif
+    INT16U   ix;
+    INT16U   ix_next;
+    OS_TMR  *ptmr1;
+    OS_TMR  *ptmr2;
+
+
+    OS_MemClr((INT8U *)&OSTmrTbl[0],      sizeof(OSTmrTbl));            /* Clear all the TMRs                         */
+    OS_MemClr((INT8U *)&OSTmrWheelTbl[0], sizeof(OSTmrWheelTbl));       /* Clear the timer wheel                      */
+
+    for (ix = 0u; ix < (OS_TMR_CFG_MAX - 1u); ix++) {                   /* Init. list of free TMRs                    */
+        ix_next = ix + 1u;
+        ptmr1 = &OSTmrTbl[ix];
+        ptmr2 = &OSTmrTbl[ix_next];
+        ptmr1->OSTmrType    = OS_TMR_TYPE;
+        ptmr1->OSTmrState   = OS_TMR_STATE_UNUSED;                      /* Indicate that timer is inactive            */
+        ptmr1->OSTmrNext    = (void *)ptmr2;                            /* Link to next timer                         */
+#if OS_TMR_CFG_NAME_EN > 0u
+        ptmr1->OSTmrName    = (INT8U *)(void *)"?";
+#endif
+    }
+    ptmr1               = &OSTmrTbl[ix];
+    ptmr1->OSTmrType    = OS_TMR_TYPE;
+    ptmr1->OSTmrState   = OS_TMR_STATE_UNUSED;                          /* Indicate that timer is inactive            */
+    ptmr1->OSTmrNext    = (void *)0;                                    /* Last OS_TMR                                */
+#if OS_TMR_CFG_NAME_EN > 0u
+    ptmr1->OSTmrName    = (INT8U *)(void *)"?";
+#endif
+    OSTmrTime           = 0u;
+    OSTmrUsed           = 0u;
+    OSTmrFree           = OS_TMR_CFG_MAX;
+    OSTmrFreeList       = &OSTmrTbl[0];
+    OSTmrSem            = OSSemCreate(1u);
+    OSTmrSemSignal      = OSSemCreate(0u);
+
+#if OS_EVENT_NAME_EN > 0u                                               /* Assign names to semaphores                 */
+    OSEventNameSet(OSTmrSem,       (INT8U *)(void *)"uC/OS-II TmrLock",   &err);
+    OSEventNameSet(OSTmrSemSignal, (INT8U *)(void *)"uC/OS-II TmrSignal", &err);
+#endif
+
+    OSTmr_InitTask();
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                INITIALIZE THE TIMER MANAGEMENT TASK
+*
+* Description: This function is called by OSTmrInit() to create the timer management task.
+*                               * Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+static  void  OSTmr_InitTask (void)
+{
+#if OS_TASK_NAME_EN > 0u
+    INT8U  err;
+#endif
+
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+    #if OS_STK_GROWTH == 1u
+    (void)OSTaskCreateExt(OSTmr_Task,
+                          (void *)0,                                       /* No arguments passed to OSTmrTask()      */
+                          &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u],        /* Set Top-Of-Stack                        */
+                          OS_TASK_TMR_PRIO,
+                          OS_TASK_TMR_ID,
+                          &OSTmrTaskStk[0],                                /* Set Bottom-Of-Stack                     */
+                          OS_TASK_TMR_STK_SIZE,
+                          (void *)0,                                       /* No TCB extension                        */
+                          OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);      /* Enable stack checking + clear stack     */
+    #else
+    (void)OSTaskCreateExt(OSTmr_Task,
+                          (void *)0,                                       /* No arguments passed to OSTmrTask()      */
+                          &OSTmrTaskStk[0],                                /* Set Top-Of-Stack                        */
+                          OS_TASK_TMR_PRIO,
+                          OS_TASK_TMR_ID,
+                          &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u],        /* Set Bottom-Of-Stack                     */
+                          OS_TASK_TMR_STK_SIZE,
+                          (void *)0,                                       /* No TCB extension                        */
+                          OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);      /* Enable stack checking + clear stack     */
+    #endif
+#else
+    #if OS_STK_GROWTH == 1u
+    (void)OSTaskCreate(OSTmr_Task,
+                       (void *)0,
+                       &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u],
+                       OS_TASK_TMR_PRIO);
+    #else
+    (void)OSTaskCreate(OSTmr_Task,
+                       (void *)0,
+                       &OSTmrTaskStk[0],
+                       OS_TASK_TMR_PRIO);
+    #endif
+#endif
+
+#if OS_TASK_NAME_EN > 0u
+    OSTaskNameSet(OS_TASK_TMR_PRIO, (INT8U *)(void *)"uC/OS-II Tmr", &err);
+#endif
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                 INSERT A TIMER INTO THE TIMER WHEEL
+*
+* Description: This function is called to insert the timer into the timer wheel.  The timer is always 
+*              inserted at the beginning of the list.
+*
+* Arguments  : ptmr          Is a pointer to the timer to insert.
+*
+*              type          Is either:
+*                               OS_TMR_LINK_PERIODIC    Means to re-insert the timer after a period expired
+*                               OS_TMR_LINK_DLY         Means to insert    the timer the first time
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+static  void  OSTmr_Link (OS_TMR  *ptmr,
+                          INT8U    type)
+{
+    OS_TMR       *ptmr1;
+    OS_TMR_WHEEL *pspoke;
+    INT16U        spoke;
+
+
+    ptmr->OSTmrState = OS_TMR_STATE_RUNNING;
+    if (type == OS_TMR_LINK_PERIODIC) {                            /* Determine when timer will expire                */
+        ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;
+    } else {
+        if (ptmr->OSTmrDly == 0u) {
+            ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;
+        } else {
+            ptmr->OSTmrMatch = ptmr->OSTmrDly    + OSTmrTime;
+        }
+    }
+    spoke  = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE);
+    pspoke = &OSTmrWheelTbl[spoke];
+
+    if (pspoke->OSTmrFirst == (OS_TMR *)0) {                       /* Link into timer wheel                           */
+        pspoke->OSTmrFirst   = ptmr;
+        ptmr->OSTmrNext      = (OS_TMR *)0;
+        pspoke->OSTmrEntries = 1u;
+    } else {
+        ptmr1                = pspoke->OSTmrFirst;                 /* Point to first timer in the spoke               */
+        pspoke->OSTmrFirst   = ptmr;
+        ptmr->OSTmrNext      = (void *)ptmr1;
+        ptmr1->OSTmrPrev     = (void *)ptmr;
+        pspoke->OSTmrEntries++;
+    }
+    ptmr->OSTmrPrev = (void *)0;                                   /* Timer always inserted as first node in list     */
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                 REMOVE A TIMER FROM THE TIMER WHEEL
+*
+* Description: This function is called to remove the timer from the timer wheel.
+*
+* Arguments  : ptmr          Is a pointer to the timer to remove.
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+static  void  OSTmr_Unlink (OS_TMR *ptmr)
+{
+    OS_TMR        *ptmr1;
+    OS_TMR        *ptmr2;
+    OS_TMR_WHEEL  *pspoke;
+    INT16U         spoke;
+
+
+    spoke  = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE);
+    pspoke = &OSTmrWheelTbl[spoke];
+
+    if (pspoke->OSTmrFirst == ptmr) {                       /* See if timer to remove is at the beginning of list     */
+        ptmr1              = (OS_TMR *)ptmr->OSTmrNext;
+        pspoke->OSTmrFirst = (OS_TMR *)ptmr1;
+        if (ptmr1 != (OS_TMR *)0) {
+            ptmr1->OSTmrPrev = (void *)0;
+        }
+    } else {
+        ptmr1            = (OS_TMR *)ptmr->OSTmrPrev;       /* Remove timer from somewhere in the list                */
+        ptmr2            = (OS_TMR *)ptmr->OSTmrNext;
+        ptmr1->OSTmrNext = ptmr2;
+        if (ptmr2 != (OS_TMR *)0) {
+            ptmr2->OSTmrPrev = (void *)ptmr1;
+        }
+    }
+    ptmr->OSTmrState = OS_TMR_STATE_STOPPED;
+    ptmr->OSTmrNext  = (void *)0;
+    ptmr->OSTmrPrev  = (void *)0;
+    pspoke->OSTmrEntries--;
+}
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                        TIMER MANAGEMENT TASK
+*
+* Description: This task is created by OSTmrInit().
+*
+* Arguments  : none
+*
+* Returns    : none
+*********************************************************************************************************
+*/
+
+#if OS_TMR_EN > 0u
+static  void  OSTmr_Task (void *p_arg)
+{
+    INT8U            err;
+    OS_TMR          *ptmr;
+    OS_TMR          *ptmr_next;
+    OS_TMR_CALLBACK  pfnct;
+    OS_TMR_WHEEL    *pspoke;
+    INT16U           spoke;
+
+
+    p_arg = p_arg;                                               /* Prevent compiler warning for not using 'p_arg'    */
+    for (;;) {
+        OSSemPend(OSTmrSemSignal, 0u, &err);                     /* Wait for signal indicating time to update timers  */
+        OSSchedLock();
+        OSTmrTime++;                                             /* Increment the current time                        */
+        spoke  = (INT16U)(OSTmrTime % OS_TMR_CFG_WHEEL_SIZE);    /* Position on current timer wheel entry             */
+        pspoke = &OSTmrWheelTbl[spoke];
+        ptmr   = pspoke->OSTmrFirst;
+        while (ptmr != (OS_TMR *)0) {
+            ptmr_next = (OS_TMR *)ptmr->OSTmrNext;               /* Point to next timer to update because current ... */
+                                                                 /* ... timer could get unlinked from the wheel.      */
+            if (OSTmrTime == ptmr->OSTmrMatch) {                 /* Process each timer that expires                   */
+                OSTmr_Unlink(ptmr);                              /* Remove from current wheel spoke                   */
+                if (ptmr->OSTmrOpt == OS_TMR_OPT_PERIODIC) {
+                    OSTmr_Link(ptmr, OS_TMR_LINK_PERIODIC);      /* Recalculate new position of timer in wheel        */
+                } else {
+                    ptmr->OSTmrState = OS_TMR_STATE_COMPLETED;   /* Indicate that the timer has completed             */
+                }
+                pfnct = ptmr->OSTmrCallback;                     /* Execute callback function if available            */
+                if (pfnct != (OS_TMR_CALLBACK)0) {
+                    (*pfnct)((void *)ptmr, ptmr->OSTmrCallbackArg);
+                }
+            }
+            ptmr = ptmr_next;
+        }
+        OSSchedUnlock();
+    }
+}
+#endif

+ 1970 - 0
MiddleWare/uCOS_II/uCOS-II/Source/ucos_ii.h

@@ -0,0 +1,1970 @@
+/*
+*********************************************************************************************************
+*                                              uC/OS-II
+*                                        The Real-Time Kernel
+*
+*                            (c) Copyright 1992-2013, Micrium, Weston, FL
+*                                           All Rights Reserved
+*
+* File    : uCOS_II.H
+* By      : Jean J. Labrosse
+* Version : V2.92.11
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micrium to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#ifndef OS_uCOS_II_H
+#define OS_uCOS_II_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                       uC/OS-II VERSION NUMBER
+    *********************************************************************************************************
+    */
+
+#define OS_VERSION 29211u /* Version of uC/OS-II (Vx.yy mult. by 10000)  */
+
+/*
+*********************************************************************************************************
+*                                        INCLUDE HEADER FILES
+*********************************************************************************************************
+*/
+
+// #include <app_cfg.h>
+#include <os_cfg.h>
+#include <os_cpu.h>
+
+    /*
+    *********************************************************************************************************
+    *                                            MISCELLANEOUS
+    *********************************************************************************************************
+    */
+
+#ifdef OS_GLOBALS
+#define OS_EXT
+#else
+#define OS_EXT extern
+#endif
+
+#ifndef OS_FALSE
+#define OS_FALSE 0u
+#endif
+
+#ifndef OS_TRUE
+#define OS_TRUE 1u
+#endif
+
+#define OS_ASCII_NUL (INT8U)0
+
+#define OS_PRIO_SELF 0xFFu           /* Indicate SELF priority                      */
+#define OS_PRIO_MUTEX_CEIL_DIS 0xFFu /* Disable mutex priority ceiling promotion    */
+
+#if OS_TASK_STAT_EN > 0u
+#define OS_N_SYS_TASKS 2u /* Number of system tasks                      */
+#else
+#define OS_N_SYS_TASKS 1u
+#endif
+
+#define OS_TASK_STAT_PRIO (OS_LOWEST_PRIO - 1u) /* Statistic task priority                     */
+#define OS_TASK_IDLE_PRIO (OS_LOWEST_PRIO)      /* IDLE      task priority                     */
+
+#if OS_LOWEST_PRIO <= 63u
+#define OS_EVENT_TBL_SIZE ((OS_LOWEST_PRIO) / 8u + 1u) /* Size of event table                         */
+#define OS_RDY_TBL_SIZE ((OS_LOWEST_PRIO) / 8u + 1u)   /* Size of ready table                         */
+#else
+#define OS_EVENT_TBL_SIZE ((OS_LOWEST_PRIO) / 16u + 1u) /* Size of event table                         */
+#define OS_RDY_TBL_SIZE ((OS_LOWEST_PRIO) / 16u + 1u)   /* Size of ready table                         */
+#endif
+
+#define OS_TASK_IDLE_ID 65535u /* ID numbers for Idle, Stat and Timer tasks   */
+#define OS_TASK_STAT_ID 65534u
+#define OS_TASK_TMR_ID 65533u
+
+#define OS_EVENT_EN (((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u) || (OS_SEM_EN > 0u) || (OS_MUTEX_EN > 0u))
+
+#define OS_TCB_RESERVED ((OS_TCB *)1)
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                             TASK STATUS (Bit definition for OSTCBStat)
+*********************************************************************************************************
+*/
+#define OS_STAT_RDY 0x00u     /* Ready to run                                            */
+#define OS_STAT_SEM 0x01u     /* Pending on semaphore                                    */
+#define OS_STAT_MBOX 0x02u    /* Pending on mailbox                                      */
+#define OS_STAT_Q 0x04u       /* Pending on queue                                        */
+#define OS_STAT_SUSPEND 0x08u /* Task is suspended                                       */
+#define OS_STAT_MUTEX 0x10u   /* Pending on mutual exclusion semaphore                   */
+#define OS_STAT_FLAG 0x20u    /* Pending on event flag group                             */
+#define OS_STAT_MULTI 0x80u   /* Pending on multiple events                              */
+
+#define OS_STAT_PEND_ANY (OS_STAT_SEM | OS_STAT_MBOX | OS_STAT_Q | OS_STAT_MUTEX | OS_STAT_FLAG)
+
+/*
+*********************************************************************************************************
+*                          TASK PEND STATUS (Status codes for OSTCBStatPend)
+*********************************************************************************************************
+*/
+#define OS_STAT_PEND_OK 0u    /* Pending status OK, not pending, or pending complete     */
+#define OS_STAT_PEND_TO 1u    /* Pending timed out                                       */
+#define OS_STAT_PEND_ABORT 2u /* Pending aborted                                         */
+
+/*
+*********************************************************************************************************
+*                                           OS_EVENT types
+*********************************************************************************************************
+*/
+#define OS_EVENT_TYPE_UNUSED 0u
+#define OS_EVENT_TYPE_MBOX 1u
+#define OS_EVENT_TYPE_Q 2u
+#define OS_EVENT_TYPE_SEM 3u
+#define OS_EVENT_TYPE_MUTEX 4u
+#define OS_EVENT_TYPE_FLAG 5u
+
+#define OS_TMR_TYPE 100u /* Used to identify Timers ...                             */
+                         /* ... (Must be different value than OS_EVENT_TYPE_xxx)    */
+
+/*
+*********************************************************************************************************
+*                                             EVENT FLAGS
+*********************************************************************************************************
+*/
+#define OS_FLAG_WAIT_CLR_ALL 0u /* Wait for ALL    the bits specified to be CLR (i.e. 0)   */
+#define OS_FLAG_WAIT_CLR_AND 0u
+
+#define OS_FLAG_WAIT_CLR_ANY 1u /* Wait for ANY of the bits specified to be CLR (i.e. 0)   */
+#define OS_FLAG_WAIT_CLR_OR 1u
+
+#define OS_FLAG_WAIT_SET_ALL 2u /* Wait for ALL    the bits specified to be SET (i.e. 1)   */
+#define OS_FLAG_WAIT_SET_AND 2u
+
+#define OS_FLAG_WAIT_SET_ANY 3u /* Wait for ANY of the bits specified to be SET (i.e. 1)   */
+#define OS_FLAG_WAIT_SET_OR 3u
+
+#define OS_FLAG_CONSUME 0x80u /* Consume the flags if condition(s) satisfied             */
+
+#define OS_FLAG_CLR 0u
+#define OS_FLAG_SET 1u
+
+    /*
+    *********************************************************************************************************
+    *                                     Values for OSTickStepState
+    *
+    * Note(s): This feature is used by uC/OS-View.
+    *********************************************************************************************************
+    */
+
+#if OS_TICK_STEP_EN > 0u
+#define OS_TICK_STEP_DIS 0u  /* Stepping is disabled, tick runs as normal               */
+#define OS_TICK_STEP_WAIT 1u /* Waiting for uC/OS-View to set OSTickStepState to _ONCE  */
+#define OS_TICK_STEP_ONCE 2u /* Process tick once and wait for next cmd from uC/OS-View */
+#endif
+
+/*
+*********************************************************************************************************
+*      Possible values for 'opt' argument of OSSemDel(), OSMboxDel(), OSQDel() and OSMutexDel()
+*********************************************************************************************************
+*/
+#define OS_DEL_NO_PEND 0u
+#define OS_DEL_ALWAYS 1u
+
+/*
+*********************************************************************************************************
+*                                        OS???Pend() OPTIONS
+*
+* These #defines are used to establish the options for OS???PendAbort().
+*********************************************************************************************************
+*/
+#define OS_PEND_OPT_NONE 0u      /* NO option selected                                      */
+#define OS_PEND_OPT_BROADCAST 1u /* Broadcast action to ALL tasks waiting                   */
+
+/*
+*********************************************************************************************************
+*                                     OS???PostOpt() OPTIONS
+*
+* These #defines are used to establish the options for OSMboxPostOpt() and OSQPostOpt().
+*********************************************************************************************************
+*/
+#define OS_POST_OPT_NONE 0x00u      /* NO option selected                                      */
+#define OS_POST_OPT_BROADCAST 0x01u /* Broadcast message to ALL tasks waiting                  */
+#define OS_POST_OPT_FRONT 0x02u     /* Post to highest priority task waiting                   */
+#define OS_POST_OPT_NO_SCHED 0x04u  /* Do not call the scheduler if this option is selected    */
+
+/*
+*********************************************************************************************************
+*                                TASK OPTIONS (see OSTaskCreateExt())
+*********************************************************************************************************
+*/
+#define OS_TASK_OPT_NONE 0x0000u    /* NO option selected                                      */
+#define OS_TASK_OPT_STK_CHK 0x0001u /* Enable stack checking for the task                      */
+#define OS_TASK_OPT_STK_CLR 0x0002u /* Clear the stack when the task is create                 */
+#define OS_TASK_OPT_SAVE_FP 0x0004u /* Save the contents of any floating-point registers       */
+#define OS_TASK_OPT_NO_TLS 0x0008u  /* Specify that task doesn't needs TLS                     */
+
+/*
+*********************************************************************************************************
+*                          TIMER OPTIONS (see OSTmrStart() and OSTmrStop())
+*********************************************************************************************************
+*/
+#define OS_TMR_OPT_NONE 0u /* No option selected                                      */
+
+#define OS_TMR_OPT_ONE_SHOT 1u /* Timer will not automatically restart when it expires    */
+#define OS_TMR_OPT_PERIODIC 2u /* Timer will     automatically restart when it expires    */
+
+#define OS_TMR_OPT_CALLBACK 3u     /* OSTmrStop() option to call 'callback' w/ timer arg.     */
+#define OS_TMR_OPT_CALLBACK_ARG 4u /* OSTmrStop() option to call 'callback' w/ new   arg.     */
+
+/*
+*********************************************************************************************************
+*                                            TIMER STATES
+*********************************************************************************************************
+*/
+#define OS_TMR_STATE_UNUSED 0u
+#define OS_TMR_STATE_STOPPED 1u
+#define OS_TMR_STATE_COMPLETED 2u
+#define OS_TMR_STATE_RUNNING 3u
+
+/*
+*********************************************************************************************************
+*                                             ERROR CODES
+*********************************************************************************************************
+*/
+#define OS_ERR_NONE 0u
+
+#define OS_ERR_EVENT_TYPE 1u
+#define OS_ERR_PEND_ISR 2u
+#define OS_ERR_POST_NULL_PTR 3u
+#define OS_ERR_PEVENT_NULL 4u
+#define OS_ERR_POST_ISR 5u
+#define OS_ERR_QUERY_ISR 6u
+#define OS_ERR_INVALID_OPT 7u
+#define OS_ERR_ID_INVALID 8u
+#define OS_ERR_PDATA_NULL 9u
+
+#define OS_ERR_TIMEOUT 10u
+#define OS_ERR_EVENT_NAME_TOO_LONG 11u
+#define OS_ERR_PNAME_NULL 12u
+#define OS_ERR_PEND_LOCKED 13u
+#define OS_ERR_PEND_ABORT 14u
+#define OS_ERR_DEL_ISR 15u
+#define OS_ERR_CREATE_ISR 16u
+#define OS_ERR_NAME_GET_ISR 17u
+#define OS_ERR_NAME_SET_ISR 18u
+#define OS_ERR_ILLEGAL_CREATE_RUN_TIME 19u
+
+#define OS_ERR_MBOX_FULL 20u
+
+#define OS_ERR_Q_FULL 30u
+#define OS_ERR_Q_EMPTY 31u
+
+#define OS_ERR_PRIO_EXIST 40u
+#define OS_ERR_PRIO 41u
+#define OS_ERR_PRIO_INVALID 42u
+
+#define OS_ERR_SCHED_LOCKED 50u
+#define OS_ERR_SEM_OVF 51u
+
+#define OS_ERR_TASK_CREATE_ISR 60u
+#define OS_ERR_TASK_DEL 61u
+#define OS_ERR_TASK_DEL_IDLE 62u
+#define OS_ERR_TASK_DEL_REQ 63u
+#define OS_ERR_TASK_DEL_ISR 64u
+#define OS_ERR_TASK_NAME_TOO_LONG 65u
+#define OS_ERR_TASK_NO_MORE_TCB 66u
+#define OS_ERR_TASK_NOT_EXIST 67u
+#define OS_ERR_TASK_NOT_SUSPENDED 68u
+#define OS_ERR_TASK_OPT 69u
+#define OS_ERR_TASK_RESUME_PRIO 70u
+#define OS_ERR_TASK_SUSPEND_IDLE 71u
+#define OS_ERR_TASK_SUSPEND_PRIO 72u
+#define OS_ERR_TASK_WAITING 73u
+
+#define OS_ERR_TIME_NOT_DLY 80u
+#define OS_ERR_TIME_INVALID_MINUTES 81u
+#define OS_ERR_TIME_INVALID_SECONDS 82u
+#define OS_ERR_TIME_INVALID_MS 83u
+#define OS_ERR_TIME_ZERO_DLY 84u
+#define OS_ERR_TIME_DLY_ISR 85u
+
+#define OS_ERR_MEM_INVALID_PART 90u
+#define OS_ERR_MEM_INVALID_BLKS 91u
+#define OS_ERR_MEM_INVALID_SIZE 92u
+#define OS_ERR_MEM_NO_FREE_BLKS 93u
+#define OS_ERR_MEM_FULL 94u
+#define OS_ERR_MEM_INVALID_PBLK 95u
+#define OS_ERR_MEM_INVALID_PMEM 96u
+#define OS_ERR_MEM_INVALID_PDATA 97u
+#define OS_ERR_MEM_INVALID_ADDR 98u
+#define OS_ERR_MEM_NAME_TOO_LONG 99u
+
+#define OS_ERR_NOT_MUTEX_OWNER 100u
+
+#define OS_ERR_FLAG_INVALID_PGRP 110u
+#define OS_ERR_FLAG_WAIT_TYPE 111u
+#define OS_ERR_FLAG_NOT_RDY 112u
+#define OS_ERR_FLAG_INVALID_OPT 113u
+#define OS_ERR_FLAG_GRP_DEPLETED 114u
+#define OS_ERR_FLAG_NAME_TOO_LONG 115u
+
+#define OS_ERR_PCP_LOWER 120u
+
+#define OS_ERR_TMR_INVALID_DLY 130u
+#define OS_ERR_TMR_INVALID_PERIOD 131u
+#define OS_ERR_TMR_INVALID_OPT 132u
+#define OS_ERR_TMR_INVALID_NAME 133u
+#define OS_ERR_TMR_NON_AVAIL 134u
+#define OS_ERR_TMR_INACTIVE 135u
+#define OS_ERR_TMR_INVALID_DEST 136u
+#define OS_ERR_TMR_INVALID_TYPE 137u
+#define OS_ERR_TMR_INVALID 138u
+#define OS_ERR_TMR_ISR 139u
+#define OS_ERR_TMR_NAME_TOO_LONG 140u
+#define OS_ERR_TMR_INVALID_STATE 141u
+#define OS_ERR_TMR_STOPPED 142u
+#define OS_ERR_TMR_NO_CALLBACK 143u
+
+#define OS_ERR_NO_MORE_ID_AVAIL 150u
+
+#define OS_ERR_TLS_NO_MORE_AVAIL 160u
+#define OS_ERR_TLS_ID_INVALID 161u
+#define OS_ERR_TLS_NOT_EN 162u
+#define OS_ERR_TLS_DESTRUCT_ASSIGNED 163u
+#define OS_ERR_OS_NOT_RUNNING 164u
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                       THREAD LOCAL STORAGE (TLS)
+    *********************************************************************************************************
+    */
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
+    typedef void *OS_TLS;
+
+    typedef INT8U OS_TLS_ID;
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                         EVENT CONTROL BLOCK
+    *********************************************************************************************************
+    */
+
+#if OS_LOWEST_PRIO <= 63u
+    typedef INT8U OS_PRIO;
+#else
+typedef INT16U OS_PRIO;
+#endif
+
+#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u)
+    typedef struct os_event
+    {
+        INT8U OSEventType;                     /* Type of event control block (see OS_EVENT_TYPE_xxxx)    */
+        void *OSEventPtr;                      /* Pointer to message or queue structure                   */
+        INT16U OSEventCnt;                     /* Semaphore Count (not used if other EVENT type)          */
+        OS_PRIO OSEventGrp;                    /* Group corresponding to tasks waiting for event to occur */
+        OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur                */
+
+#if OS_EVENT_NAME_EN > 0u
+        INT8U *OSEventName;
+#endif
+    } OS_EVENT;
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                      EVENT FLAGS CONTROL BLOCK
+    *********************************************************************************************************
+    */
+
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+
+#if OS_FLAGS_NBITS == 8u /* Determine the size of OS_FLAGS (8, 16 or 32 bits)       */
+    typedef INT8U OS_FLAGS;
+#endif
+
+#if OS_FLAGS_NBITS == 16u
+    typedef INT16U OS_FLAGS;
+#endif
+
+#if OS_FLAGS_NBITS == 32u
+    typedef INT32U OS_FLAGS;
+#endif
+
+    typedef struct os_flag_grp
+    {                         /* Event Flag Group                                        */
+        INT8U OSFlagType;     /* Should be set to OS_EVENT_TYPE_FLAG                     */
+        void *OSFlagWaitList; /* Pointer to first NODE of task waiting on event flag     */
+        OS_FLAGS OSFlagFlags; /* 8, 16 or 32 bit flags                                   */
+#if OS_FLAG_NAME_EN > 0u
+        INT8U *OSFlagName;
+#endif
+    } OS_FLAG_GRP;
+
+    typedef struct os_flag_node
+    {                             /* Event Flag Wait List Node                               */
+        void *OSFlagNodeNext;     /* Pointer to next     NODE in wait list                   */
+        void *OSFlagNodePrev;     /* Pointer to previous NODE in wait list                   */
+        void *OSFlagNodeTCB;      /* Pointer to TCB of waiting task                          */
+        void *OSFlagNodeFlagGrp;  /* Pointer to Event Flag Group                             */
+        OS_FLAGS OSFlagNodeFlags; /* Event flag to wait on                                   */
+        INT8U OSFlagNodeWaitType; /* Type of wait:                                           */
+                                  /*      OS_FLAG_WAIT_AND                                   */
+                                  /*      OS_FLAG_WAIT_ALL                                   */
+                                  /*      OS_FLAG_WAIT_OR                                    */
+                                  /*      OS_FLAG_WAIT_ANY                                   */
+    } OS_FLAG_NODE;
+#endif
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                        MESSAGE MAILBOX DATA
+    *********************************************************************************************************
+    */
+
+#if OS_MBOX_EN > 0u
+    typedef struct os_mbox_data
+    {
+        void *OSMsg;                           /* Pointer to message in mailbox                           */
+        OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur                */
+        OS_PRIO OSEventGrp;                    /* Group corresponding to tasks waiting for event to occur */
+    } OS_MBOX_DATA;
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                  MEMORY PARTITION DATA STRUCTURES
+    *********************************************************************************************************
+    */
+
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+    typedef struct os_mem
+    {                        /* MEMORY CONTROL BLOCK                                    */
+        void *OSMemAddr;     /* Pointer to beginning of memory partition                */
+        void *OSMemFreeList; /* Pointer to list of free memory blocks                   */
+        INT32U OSMemBlkSize; /* Size (in bytes) of each block of memory                 */
+        INT32U OSMemNBlks;   /* Total number of blocks in this partition                */
+        INT32U OSMemNFree;   /* Number of memory blocks remaining in this partition     */
+#if OS_MEM_NAME_EN > 0u
+        INT8U *OSMemName; /* Memory partition name                                   */
+#endif
+    } OS_MEM;
+
+    typedef struct os_mem_data
+    {
+        void *OSAddr;     /* Ptr to the beginning address of the memory partition    */
+        void *OSFreeList; /* Ptr to the beginning of the free list of memory blocks  */
+        INT32U OSBlkSize; /* Size (in bytes) of each memory block                    */
+        INT32U OSNBlks;   /* Total number of blocks in the partition                 */
+        INT32U OSNFree;   /* Number of memory blocks free                            */
+        INT32U OSNUsed;   /* Number of memory blocks used                            */
+    } OS_MEM_DATA;
+#endif
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                   MUTUAL EXCLUSION SEMAPHORE DATA
+    *********************************************************************************************************
+    */
+
+#if OS_MUTEX_EN > 0u
+    typedef struct os_mutex_data
+    {
+        OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur                */
+        OS_PRIO OSEventGrp;                    /* Group corresponding to tasks waiting for event to occur */
+        BOOLEAN OSValue;                       /* Mutex value (OS_FALSE = used, OS_TRUE = available)      */
+        INT8U OSOwnerPrio;                     /* Mutex owner's task priority or 0xFF if no owner         */
+        INT8U OSMutexPCP;                      /* Priority Ceiling Priority or 0xFF if PCP disabled       */
+    } OS_MUTEX_DATA;
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                         MESSAGE QUEUE DATA
+    *********************************************************************************************************
+    */
+
+#if OS_Q_EN > 0u
+    typedef struct os_q
+    {                        /* QUEUE CONTROL BLOCK                                     */
+        struct os_q *OSQPtr; /* Link to next queue control block in list of free blocks */
+        void **OSQStart;     /* Ptr to start of queue data                              */
+        void **OSQEnd;       /* Ptr to end   of queue data                              */
+        void **OSQIn;        /* Ptr to where next message will be inserted  in   the Q  */
+        void **OSQOut;       /* Ptr to where next message will be extracted from the Q  */
+        INT16U OSQSize;      /* Size of queue (maximum number of entries)               */
+        INT16U OSQEntries;   /* Current number of entries in the queue                  */
+    } OS_Q;
+
+    typedef struct os_q_data
+    {
+        void *OSMsg;                           /* Pointer to next message to be extracted from queue      */
+        INT16U OSNMsgs;                        /* Number of messages in message queue                     */
+        INT16U OSQSize;                        /* Size of message queue                                   */
+        OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur         */
+        OS_PRIO OSEventGrp;                    /* Group corresponding to tasks waiting for event to occur */
+    } OS_Q_DATA;
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                           SEMAPHORE DATA
+    *********************************************************************************************************
+    */
+
+#if OS_SEM_EN > 0u
+    typedef struct os_sem_data
+    {
+        INT16U OSCnt;                          /* Semaphore count                                         */
+        OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur                */
+        OS_PRIO OSEventGrp;                    /* Group corresponding to tasks waiting for event to occur */
+    } OS_SEM_DATA;
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                           TASK STACK DATA
+    *********************************************************************************************************
+    */
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+    typedef struct os_stk_data
+    {
+        INT32U OSFree; /* Number of free entries on the stack                     */
+        INT32U OSUsed; /* Number of entries used on the stack                     */
+    } OS_STK_DATA;
+#endif
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                         TASK CONTROL BLOCK
+    *********************************************************************************************************
+    */
+
+    typedef struct os_tcb
+    {
+        OS_STK *OSTCBStkPtr; /* Pointer to current top of stack                         */
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+        void *OSTCBExtPtr;      /* Pointer to user definable data for TCB extension        */
+        OS_STK *OSTCBStkBottom; /* Pointer to bottom of stack                              */
+        INT32U OSTCBStkSize;    /* Size of task stack (in number of stack elements)        */
+        INT16U OSTCBOpt;        /* Task options as passed by OSTaskCreateExt()             */
+        INT16U OSTCBId;         /* Task ID (0..65535)                                      */
+#endif
+
+        struct os_tcb *OSTCBNext; /* Pointer to next     TCB in the TCB list                 */
+        struct os_tcb *OSTCBPrev; /* Pointer to previous TCB in the TCB list                 */
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
+        OS_TLS OSTCBTLSTbl[OS_TLS_TBL_SIZE];
+#endif
+#endif
+
+#if (OS_EVENT_EN)
+        OS_EVENT *OSTCBEventPtr; /* Pointer to          event control block                 */
+#endif
+
+#if (OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u)
+        OS_EVENT **OSTCBEventMultiPtr; /* Pointer to multiple event control blocks                */
+#endif
+
+#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u)
+        void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost()         */
+#endif
+
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+#if OS_TASK_DEL_EN > 0u
+        OS_FLAG_NODE *OSTCBFlagNode; /* Pointer to event flag node                              */
+#endif
+        OS_FLAGS OSTCBFlagsRdy; /* Event flags that made task ready to run                 */
+#endif
+
+        INT32U OSTCBDly;     /* Nbr ticks to delay task or, timeout waiting for event   */
+        INT8U OSTCBStat;     /* Task      status                                        */
+        INT8U OSTCBStatPend; /* Task PEND status                                        */
+        INT8U OSTCBPrio;     /* Task priority (0 == highest)                            */
+
+        INT8U OSTCBX;      /* Bit position in group  corresponding to task priority   */
+        INT8U OSTCBY;      /* Index into ready table corresponding to task priority   */
+        OS_PRIO OSTCBBitX; /* Bit mask to access bit position in ready table          */
+        OS_PRIO OSTCBBitY; /* Bit mask to access bit position in ready group          */
+
+#if OS_TASK_DEL_EN > 0u
+        INT8U OSTCBDelReq; /* Indicates whether a task needs to delete itself         */
+#endif
+
+#if OS_TASK_PROFILE_EN > 0u
+        INT32U OSTCBCtxSwCtr;    /* Number of time the task was switched in                 */
+        INT32U OSTCBCyclesTot;   /* Total number of clock cycles the task has been running  */
+        INT32U OSTCBCyclesStart; /* Snapshot of cycle counter at start of task resumption   */
+        OS_STK *OSTCBStkBase;    /* Pointer to the beginning of the task stack              */
+        INT32U OSTCBStkUsed;     /* Number of bytes used from the stack                     */
+#endif
+
+#if OS_TASK_NAME_EN > 0u
+        INT8U *OSTCBTaskName;
+#endif
+
+#if OS_TASK_REG_TBL_SIZE > 0u
+        INT32U OSTCBRegTbl[OS_TASK_REG_TBL_SIZE];
+#endif
+    } OS_TCB;
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                          TIMER DATA TYPES
+    *********************************************************************************************************
+    */
+
+#if OS_TMR_EN > 0u
+    typedef void (*OS_TMR_CALLBACK)(void *ptmr, void *parg);
+
+    typedef struct os_tmr
+    {
+        INT8U OSTmrType;               /* Should be set to OS_TMR_TYPE                            */
+        OS_TMR_CALLBACK OSTmrCallback; /* Function to call when timer expires                     */
+        void *OSTmrCallbackArg;        /* Argument to pass to function when timer expires         */
+        void *OSTmrNext;               /* Double link list pointers                               */
+        void *OSTmrPrev;
+        INT32U OSTmrMatch;  /* Timer expires when OSTmrTime == OSTmrMatch              */
+        INT32U OSTmrDly;    /* Delay time before periodic update starts                */
+        INT32U OSTmrPeriod; /* Period to repeat timer                                  */
+#if OS_TMR_CFG_NAME_EN > 0u
+        INT8U *OSTmrName; /* Name to give the timer                                  */
+#endif
+        INT8U OSTmrOpt;   /* Options (see OS_TMR_OPT_xxx)                            */
+        INT8U OSTmrState; /* Indicates the state of the timer:                       */
+                          /*     OS_TMR_STATE_UNUSED                                 */
+                          /*     OS_TMR_STATE_RUNNING                                */
+                          /*     OS_TMR_STATE_STOPPED                                */
+    } OS_TMR;
+
+    typedef struct os_tmr_wheel
+    {
+        OS_TMR *OSTmrFirst; /* Pointer to first timer in linked list                   */
+        INT16U OSTmrEntries;
+    } OS_TMR_WHEEL;
+#endif
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                       THREAD LOCAL STORAGE (TLS)
+    *********************************************************************************************************
+    */
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
+    typedef void (*OS_TLS_DESTRUCT_PTR)(OS_TCB *ptcb,
+                                        OS_TLS_ID id,
+                                        OS_TLS value);
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                          GLOBAL VARIABLES
+    *********************************************************************************************************
+    */
+
+    OS_EXT INT32U OSCtxSwCtr; /* Counter of number of context switches           */
+
+#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u)
+    OS_EXT OS_EVENT *OSEventFreeList;          /* Pointer to list of free EVENT control blocks    */
+    OS_EXT OS_EVENT OSEventTbl[OS_MAX_EVENTS]; /* Table of EVENT control blocks                   */
+#endif
+
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+    OS_EXT OS_FLAG_GRP OSFlagTbl[OS_MAX_FLAGS]; /* Table containing event flag groups              */
+    OS_EXT OS_FLAG_GRP *OSFlagFreeList;         /* Pointer to free list of event flag groups       */
+#endif
+
+#if OS_TASK_STAT_EN > 0u
+    OS_EXT INT8U OSCPUUsage;                            /* Percentage of CPU used                          */
+    OS_EXT INT32U OSIdleCtrMax;                         /* Max. value that idle ctr can take in 1 sec.     */
+    OS_EXT INT32U OSIdleCtrRun;                         /* Val. reached by idle ctr at run time in 1 sec.  */
+    OS_EXT BOOLEAN OSStatRdy;                           /* Flag indicating that the statistic task is rdy  */
+    OS_EXT OS_STK OSTaskStatStk[OS_TASK_STAT_STK_SIZE]; /* Statistics task stack          */
+#endif
+
+    OS_EXT INT8U OSIntNesting; /* Interrupt nesting level                         */
+
+    OS_EXT INT8U OSLockNesting; /* Multitasking lock nesting level                 */
+
+    OS_EXT INT8U OSPrioCur;     /* Priority of current task                        */
+    OS_EXT INT8U OSPrioHighRdy; /* Priority of highest priority task               */
+
+    OS_EXT OS_PRIO OSRdyGrp;                  /* Ready list group                         */
+    OS_EXT OS_PRIO OSRdyTbl[OS_RDY_TBL_SIZE]; /* Table of tasks which are ready to run    */
+
+    OS_EXT BOOLEAN OSRunning; /* Flag indicating that kernel is running   */
+
+    OS_EXT INT8U OSTaskCtr; /* Number of tasks created                  */
+
+    OS_EXT volatile INT32U OSIdleCtr; /* Idle counter                   */
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    OS_EXT BOOLEAN OSSafetyCriticalStartFlag;
+#endif
+
+    OS_EXT OS_STK OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE]; /* Idle task stack                */
+
+    OS_EXT OS_TCB *OSTCBCur;                               /* Pointer to currently running TCB         */
+    OS_EXT OS_TCB *OSTCBFreeList;                          /* Pointer to list of free TCBs             */
+    OS_EXT OS_TCB *OSTCBHighRdy;                           /* Pointer to highest priority TCB R-to-R   */
+    OS_EXT OS_TCB *OSTCBList;                              /* Pointer to doubly linked list of TCBs    */
+    OS_EXT OS_TCB *OSTCBPrioTbl[OS_LOWEST_PRIO + 1u];      /* Table of pointers to created TCBs   */
+    OS_EXT OS_TCB OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS]; /* Table of TCBs                  */
+
+#if OS_TICK_STEP_EN > 0u
+    OS_EXT INT8U OSTickStepState; /* Indicates the state of the tick step feature    */
+#endif
+
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+    OS_EXT OS_MEM *OSMemFreeList;            /* Pointer to free list of memory partitions       */
+    OS_EXT OS_MEM OSMemTbl[OS_MAX_MEM_PART]; /* Storage for memory partition manager            */
+#endif
+
+#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+    OS_EXT OS_Q *OSQFreeList;      /* Pointer to list of free QUEUE control blocks    */
+    OS_EXT OS_Q OSQTbl[OS_MAX_QS]; /* Table of QUEUE control blocks                   */
+#endif
+
+#if OS_TASK_REG_TBL_SIZE > 0u
+    OS_EXT INT8U OSTaskRegNextAvailID; /* Next available Task register ID                 */
+#endif
+
+#if OS_TIME_GET_SET_EN > 0u
+    OS_EXT volatile INT32U OSTime; /* Current value of system time (in ticks)         */
+#endif
+
+#if OS_TMR_EN > 0u
+    OS_EXT INT16U OSTmrFree; /* Number of free entries in the timer pool        */
+    OS_EXT INT16U OSTmrUsed; /* Number of timers used                           */
+    OS_EXT INT32U OSTmrTime; /* Current timer time                              */
+
+    OS_EXT OS_EVENT *OSTmrSem;       /* Sem. used to gain exclusive access to timers    */
+    OS_EXT OS_EVENT *OSTmrSemSignal; /* Sem. used to signal the update of timers        */
+
+    OS_EXT OS_TMR OSTmrTbl[OS_TMR_CFG_MAX]; /* Table containing pool of timers                 */
+    OS_EXT OS_TMR *OSTmrFreeList;           /* Pointer to free list of timers                  */
+    OS_EXT OS_STK OSTmrTaskStk[OS_TASK_TMR_STK_SIZE];
+
+    OS_EXT OS_TMR_WHEEL OSTmrWheelTbl[OS_TMR_CFG_WHEEL_SIZE];
+#endif
+
+    extern INT8U const OSUnMapTbl[256]; /* Priority->Index    lookup table                 */
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                          FUNCTION PROTOTYPES
+    *                                     (Target Independent Functions)
+    *********************************************************************************************************
+    */
+
+    /*
+    *********************************************************************************************************
+    *                                            MISCELLANEOUS
+    *********************************************************************************************************
+    */
+
+#if (OS_EVENT_EN)
+
+#if (OS_EVENT_NAME_EN > 0u)
+    INT8U OSEventNameGet(OS_EVENT *pevent,
+                         INT8U **pname,
+                         INT8U *perr);
+
+    void OSEventNameSet(OS_EVENT *pevent,
+                        INT8U *pname,
+                        INT8U *perr);
+#endif
+
+#if (OS_EVENT_MULTI_EN > 0u)
+    INT16U OSEventPendMulti(OS_EVENT **pevents_pend,
+                            OS_EVENT **pevents_rdy,
+                            void **pmsgs_rdy,
+                            INT32U timeout,
+                            INT8U *perr);
+#endif
+
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                   TASK LOCAL STORAGE (TLS) SUPPORT
+    *********************************************************************************************************
+    */
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
+
+    OS_TLS_ID OS_TLS_GetID(INT8U *perr);
+
+    OS_TLS OS_TLS_GetValue(OS_TCB *ptcb,
+                           OS_TLS_ID id,
+                           INT8U *perr);
+
+    void OS_TLS_Init(INT8U *perr);
+
+    void OS_TLS_SetValue(OS_TCB *ptcb,
+                         OS_TLS_ID id,
+                         OS_TLS value,
+                         INT8U *perr);
+
+    void OS_TLS_SetDestruct(OS_TLS_ID id,
+                            OS_TLS_DESTRUCT_PTR pdestruct,
+                            INT8U *perr);
+
+    void OS_TLS_TaskCreate(OS_TCB *ptcb);
+
+    void OS_TLS_TaskDel(OS_TCB *ptcb);
+
+    void OS_TLS_TaskSw(void);
+
+#endif
+#endif
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                       EVENT FLAGS MANAGEMENT
+    *********************************************************************************************************
+    */
+
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+
+#if OS_FLAG_ACCEPT_EN > 0u
+    OS_FLAGS OSFlagAccept(OS_FLAG_GRP *pgrp,
+                          OS_FLAGS flags,
+                          INT8U wait_type,
+                          INT8U *perr);
+#endif
+
+    OS_FLAG_GRP *OSFlagCreate(OS_FLAGS flags,
+                              INT8U *perr);
+
+#if OS_FLAG_DEL_EN > 0u
+    OS_FLAG_GRP *OSFlagDel(OS_FLAG_GRP *pgrp,
+                           INT8U opt,
+                           INT8U *perr);
+#endif
+
+#if (OS_FLAG_EN > 0u) && (OS_FLAG_NAME_EN > 0u)
+    INT8U OSFlagNameGet(OS_FLAG_GRP *pgrp,
+                        INT8U **pname,
+                        INT8U *perr);
+
+    void OSFlagNameSet(OS_FLAG_GRP *pgrp,
+                       INT8U *pname,
+                       INT8U *perr);
+#endif
+
+    OS_FLAGS OSFlagPend(OS_FLAG_GRP *pgrp,
+                        OS_FLAGS flags,
+                        INT8U wait_type,
+                        INT32U timeout,
+                        INT8U *perr);
+
+    OS_FLAGS OSFlagPendGetFlagsRdy(void);
+    OS_FLAGS OSFlagPost(OS_FLAG_GRP *pgrp,
+                        OS_FLAGS flags,
+                        INT8U opt,
+                        INT8U *perr);
+
+#if OS_FLAG_QUERY_EN > 0u
+    OS_FLAGS OSFlagQuery(OS_FLAG_GRP *pgrp,
+                         INT8U *perr);
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                     MESSAGE MAILBOX MANAGEMENT
+    *********************************************************************************************************
+    */
+
+#if OS_MBOX_EN > 0u
+
+#if OS_MBOX_ACCEPT_EN > 0u
+    void *OSMboxAccept(OS_EVENT *pevent);
+#endif
+
+    OS_EVENT *OSMboxCreate(void *pmsg);
+
+#if OS_MBOX_DEL_EN > 0u
+    OS_EVENT *OSMboxDel(OS_EVENT *pevent,
+                        INT8U opt,
+                        INT8U *perr);
+#endif
+
+    void *OSMboxPend(OS_EVENT *pevent,
+                     INT32U timeout,
+                     INT8U *perr);
+
+#if OS_MBOX_PEND_ABORT_EN > 0u
+    INT8U OSMboxPendAbort(OS_EVENT *pevent,
+                          INT8U opt,
+                          INT8U *perr);
+#endif
+
+#if OS_MBOX_POST_EN > 0u
+    INT8U OSMboxPost(OS_EVENT *pevent,
+                     void *pmsg);
+#endif
+
+#if OS_MBOX_POST_OPT_EN > 0u
+    INT8U OSMboxPostOpt(OS_EVENT *pevent,
+                        void *pmsg,
+                        INT8U opt);
+#endif
+
+#if OS_MBOX_QUERY_EN > 0u
+    INT8U OSMboxQuery(OS_EVENT *pevent,
+                      OS_MBOX_DATA *p_mbox_data);
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                          MEMORY MANAGEMENT
+    *********************************************************************************************************
+    */
+
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+
+    OS_MEM *OSMemCreate(void *addr,
+                        INT32U nblks,
+                        INT32U blksize,
+                        INT8U *perr);
+
+    void *OSMemGet(OS_MEM *pmem,
+                   INT8U *perr);
+#if OS_MEM_NAME_EN > 0u
+    INT8U OSMemNameGet(OS_MEM *pmem,
+                       INT8U **pname,
+                       INT8U *perr);
+
+    void OSMemNameSet(OS_MEM *pmem,
+                      INT8U *pname,
+                      INT8U *perr);
+#endif
+    INT8U OSMemPut(OS_MEM *pmem,
+                   void *pblk);
+
+#if OS_MEM_QUERY_EN > 0u
+    INT8U OSMemQuery(OS_MEM *pmem,
+                     OS_MEM_DATA *p_mem_data);
+#endif
+
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                MUTUAL EXCLUSION SEMAPHORE MANAGEMENT
+    *********************************************************************************************************
+    */
+
+#if OS_MUTEX_EN > 0u
+
+#if OS_MUTEX_ACCEPT_EN > 0u
+    BOOLEAN OSMutexAccept(OS_EVENT *pevent,
+                          INT8U *perr);
+#endif
+
+    OS_EVENT *OSMutexCreate(INT8U prio,
+                            INT8U *perr);
+
+#if OS_MUTEX_DEL_EN > 0u
+    OS_EVENT *OSMutexDel(OS_EVENT *pevent,
+                         INT8U opt,
+                         INT8U *perr);
+#endif
+
+    void OSMutexPend(OS_EVENT *pevent,
+                     INT32U timeout,
+                     INT8U *perr);
+
+    INT8U OSMutexPost(OS_EVENT *pevent);
+
+#if OS_MUTEX_QUERY_EN > 0u
+    INT8U OSMutexQuery(OS_EVENT *pevent,
+                       OS_MUTEX_DATA *p_mutex_data);
+#endif
+
+#endif
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                      MESSAGE QUEUE MANAGEMENT
+    *********************************************************************************************************
+    */
+
+#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+
+#if OS_Q_ACCEPT_EN > 0u
+    void *OSQAccept(OS_EVENT *pevent,
+                    INT8U *perr);
+#endif
+
+    OS_EVENT *OSQCreate(void **start,
+                        INT16U size);
+
+#if OS_Q_DEL_EN > 0u
+    OS_EVENT *OSQDel(OS_EVENT *pevent,
+                     INT8U opt,
+                     INT8U *perr);
+#endif
+
+#if OS_Q_FLUSH_EN > 0u
+    INT8U OSQFlush(OS_EVENT *pevent);
+#endif
+
+    void *OSQPend(OS_EVENT *pevent,
+                  INT32U timeout,
+                  INT8U *perr);
+
+#if OS_Q_PEND_ABORT_EN > 0u
+    INT8U OSQPendAbort(OS_EVENT *pevent,
+                       INT8U opt,
+                       INT8U *perr);
+#endif
+
+#if OS_Q_POST_EN > 0u
+    INT8U OSQPost(OS_EVENT *pevent,
+                  void *pmsg);
+#endif
+
+#if OS_Q_POST_FRONT_EN > 0u
+    INT8U OSQPostFront(OS_EVENT *pevent,
+                       void *pmsg);
+#endif
+
+#if OS_Q_POST_OPT_EN > 0u
+    INT8U OSQPostOpt(OS_EVENT *pevent,
+                     void *pmsg,
+                     INT8U opt);
+#endif
+
+#if OS_Q_QUERY_EN > 0u
+    INT8U OSQQuery(OS_EVENT *pevent,
+                   OS_Q_DATA *p_q_data);
+#endif
+
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                        SEMAPHORE MANAGEMENT
+*********************************************************************************************************
+*/
+#if OS_SEM_EN > 0u
+
+#if OS_SEM_ACCEPT_EN > 0u
+    INT16U OSSemAccept(OS_EVENT *pevent);
+#endif
+
+    OS_EVENT *OSSemCreate(INT16U cnt);
+
+#if OS_SEM_DEL_EN > 0u
+    OS_EVENT *OSSemDel(OS_EVENT *pevent,
+                       INT8U opt,
+                       INT8U *perr);
+#endif
+
+    void OSSemPend(OS_EVENT *pevent,
+                   INT32U timeout,
+                   INT8U *perr);
+
+#if OS_SEM_PEND_ABORT_EN > 0u
+    INT8U OSSemPendAbort(OS_EVENT *pevent,
+                         INT8U opt,
+                         INT8U *perr);
+#endif
+
+    INT8U OSSemPost(OS_EVENT *pevent);
+
+#if OS_SEM_QUERY_EN > 0u
+    INT8U OSSemQuery(OS_EVENT *pevent,
+                     OS_SEM_DATA *p_sem_data);
+#endif
+
+#if OS_SEM_SET_EN > 0u
+    void OSSemSet(OS_EVENT *pevent,
+                  INT16U cnt,
+                  INT8U *perr);
+#endif
+
+#endif
+
+/*$PAGE*/
+/*
+*********************************************************************************************************
+*                                           TASK MANAGEMENT
+*********************************************************************************************************
+*/
+#if OS_TASK_CHANGE_PRIO_EN > 0u
+    INT8U OSTaskChangePrio(INT8U oldprio,
+                           INT8U newprio);
+#endif
+
+#if OS_TASK_CREATE_EN > 0u
+    INT8U OSTaskCreate(void (*task)(void *p_arg),
+                       void *p_arg,
+                       OS_STK *ptos,
+                       INT8U prio);
+#endif
+
+#if OS_TASK_CREATE_EXT_EN > 0u
+    INT8U OSTaskCreateExt(void (*task)(void *p_arg),
+                          void *p_arg,
+                          OS_STK *ptos,
+                          INT8U prio,
+                          INT16U id,
+                          OS_STK *pbos,
+                          INT32U stk_size,
+                          void *pext,
+                          INT16U opt);
+#endif
+
+#if OS_TASK_DEL_EN > 0u
+    INT8U OSTaskDel(INT8U prio);
+    INT8U OSTaskDelReq(INT8U prio);
+#endif
+
+#if OS_TASK_NAME_EN > 0u
+    INT8U OSTaskNameGet(INT8U prio,
+                        INT8U **pname,
+                        INT8U *perr);
+
+    void OSTaskNameSet(INT8U prio,
+                       INT8U *pname,
+                       INT8U *perr);
+#endif
+
+#if OS_TASK_SUSPEND_EN > 0u
+    INT8U OSTaskResume(INT8U prio);
+    INT8U OSTaskSuspend(INT8U prio);
+#endif
+
+#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
+    INT8U OSTaskStkChk(INT8U prio,
+                       OS_STK_DATA *p_stk_data);
+#endif
+
+#if OS_TASK_QUERY_EN > 0u
+    INT8U OSTaskQuery(INT8U prio,
+                      OS_TCB *p_task_data);
+#endif
+
+#if OS_TASK_REG_TBL_SIZE > 0u
+    INT32U OSTaskRegGet(INT8U prio,
+                        INT8U id,
+                        INT8U *perr);
+
+    INT8U OSTaskRegGetID(INT8U *perr);
+
+    void OSTaskRegSet(INT8U prio,
+                      INT8U id,
+                      INT32U value,
+                      INT8U *perr);
+#endif
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                           TIME MANAGEMENT
+    *********************************************************************************************************
+    */
+
+    void OSTimeDly(INT32U ticks);
+
+#if OS_TIME_DLY_HMSM_EN > 0u
+    INT8U OSTimeDlyHMSM(INT8U hours,
+                        INT8U minutes,
+                        INT8U seconds,
+                        INT16U ms);
+#endif
+
+#if OS_TIME_DLY_RESUME_EN > 0u
+    INT8U OSTimeDlyResume(INT8U prio);
+#endif
+
+#if OS_TIME_GET_SET_EN > 0u
+    INT32U OSTimeGet(void);
+    void OSTimeSet(INT32U ticks);
+#endif
+
+    void OSTimeTick(void);
+
+    /*
+    *********************************************************************************************************
+    *                                          TIMER MANAGEMENT
+    *********************************************************************************************************
+    */
+
+#if OS_TMR_EN > 0u
+    OS_TMR *OSTmrCreate(INT32U dly,
+                        INT32U period,
+                        INT8U opt,
+                        OS_TMR_CALLBACK callback,
+                        void *callback_arg,
+                        INT8U *pname,
+                        INT8U *perr);
+
+    BOOLEAN OSTmrDel(OS_TMR *ptmr,
+                     INT8U *perr);
+
+#if OS_TMR_CFG_NAME_EN > 0u
+    INT8U OSTmrNameGet(OS_TMR *ptmr,
+                       INT8U **pdest,
+                       INT8U *perr);
+#endif
+    INT32U OSTmrRemainGet(OS_TMR *ptmr,
+                          INT8U *perr);
+
+    INT8U OSTmrStateGet(OS_TMR *ptmr,
+                        INT8U *perr);
+
+    BOOLEAN OSTmrStart(OS_TMR *ptmr,
+                       INT8U *perr);
+
+    BOOLEAN OSTmrStop(OS_TMR *ptmr,
+                      INT8U opt,
+                      void *callback_arg,
+                      INT8U *perr);
+
+    INT8U OSTmrSignal(void);
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                            MISCELLANEOUS
+    *********************************************************************************************************
+    */
+
+    void OSInit(void);
+
+    void OSIntEnter(void);
+    void OSIntExit(void);
+
+#ifdef OS_SAFETY_CRITICAL_IEC61508
+    void OSSafetyCriticalStart(void);
+#endif
+
+#if OS_SCHED_LOCK_EN > 0u
+    void OSSchedLock(void);
+    void OSSchedUnlock(void);
+#endif
+
+    void OSStart(void);
+
+    void OSStatInit(void);
+
+    INT16U OSVersion(void);
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                      INTERNAL FUNCTION PROTOTYPES
+    *                            (Your application MUST NOT call these functions)
+    *********************************************************************************************************
+    */
+
+#if OS_TASK_DEL_EN > 0u
+    void OS_Dummy(void);
+#endif
+
+#if (OS_EVENT_EN)
+    INT8U OS_EventTaskRdy(OS_EVENT *pevent,
+                          void *pmsg,
+                          INT8U msk,
+                          INT8U pend_stat);
+
+    void OS_EventTaskWait(OS_EVENT *pevent);
+
+    void OS_EventTaskRemove(OS_TCB *ptcb,
+                            OS_EVENT *pevent);
+
+#if (OS_EVENT_MULTI_EN > 0u)
+    void OS_EventTaskWaitMulti(OS_EVENT **pevents_wait);
+
+    void OS_EventTaskRemoveMulti(OS_TCB *ptcb,
+                                 OS_EVENT **pevents_multi);
+#endif
+
+    void OS_EventWaitListInit(OS_EVENT *pevent);
+#endif
+
+#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+    void OS_FlagInit(void);
+    void OS_FlagUnlink(OS_FLAG_NODE *pnode);
+#endif
+
+    void OS_MemClr(INT8U *pdest,
+                   INT16U size);
+
+    void OS_MemCopy(INT8U *pdest,
+                    INT8U *psrc,
+                    INT16U size);
+
+#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+    void OS_MemInit(void);
+#endif
+
+#if OS_Q_EN > 0u
+    void OS_QInit(void);
+#endif
+
+    void OS_Sched(void);
+
+#if (OS_EVENT_NAME_EN > 0u) || (OS_FLAG_NAME_EN > 0u) || (OS_MEM_NAME_EN > 0u) || (OS_TASK_NAME_EN > 0u)
+    INT8U OS_StrLen(INT8U *psrc);
+#endif
+
+    void OS_TaskIdle(void *p_arg);
+
+    void OS_TaskReturn(void);
+
+#if OS_TASK_STAT_EN > 0u
+    void OS_TaskStat(void *p_arg);
+#endif
+
+#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
+    void OS_TaskStkClr(OS_STK *pbos,
+                       INT32U size,
+                       INT16U opt);
+#endif
+
+#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
+    void OS_TaskStatStkChk(void);
+#endif
+
+    INT8U OS_TCBInit(INT8U prio,
+                     OS_STK *ptos,
+                     OS_STK *pbos,
+                     INT16U id,
+                     INT32U stk_size,
+                     void *pext,
+                     INT16U opt);
+
+#if OS_TMR_EN > 0u
+    void OSTmr_Init(void);
+#endif
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                          FUNCTION PROTOTYPES
+    *                                      (Target Specific Functions)
+    *********************************************************************************************************
+    */
+
+#if OS_DEBUG_EN > 0u
+    void OSDebugInit(void);
+#endif
+
+    void OSInitHookBegin(void);
+    void OSInitHookEnd(void);
+
+    void OSTaskCreateHook(OS_TCB *ptcb);
+    void OSTaskDelHook(OS_TCB *ptcb);
+
+    void OSTaskIdleHook(void);
+
+    void OSTaskReturnHook(OS_TCB *ptcb);
+
+    void OSTaskStatHook(void);
+    OS_STK *OSTaskStkInit(void (*task)(void *p_arg),
+                          void *p_arg,
+                          OS_STK *ptos,
+                          INT16U opt);
+
+#if OS_TASK_SW_HOOK_EN > 0u
+    void OSTaskSwHook(void);
+#endif
+
+    void OSTCBInitHook(OS_TCB *ptcb);
+
+#if OS_TIME_TICK_HOOK_EN > 0u
+    void OSTimeTickHook(void);
+#endif
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                          FUNCTION PROTOTYPES
+    *                                   (Application Specific Functions)
+    *********************************************************************************************************
+    */
+
+#if OS_APP_HOOKS_EN > 0u
+    void App_TaskCreateHook(OS_TCB *ptcb);
+    void App_TaskDelHook(OS_TCB *ptcb);
+    void App_TaskIdleHook(void);
+
+    void App_TaskReturnHook(OS_TCB *ptcb);
+
+    void App_TaskStatHook(void);
+
+#if OS_TASK_SW_HOOK_EN > 0u
+    void App_TaskSwHook(void);
+#endif
+
+    void App_TCBInitHook(OS_TCB *ptcb);
+
+#if OS_TIME_TICK_HOOK_EN > 0u
+    void App_TimeTickHook(void);
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                          FUNCTION PROTOTYPES
+    *
+    * IMPORTANT: These prototypes MUST be placed in OS_CPU.H
+    *********************************************************************************************************
+    */
+
+#if 0
+void          OSStartHighRdy          (void);
+void          OSIntCtxSw              (void);
+void          OSCtxSw                 (void);
+#endif
+
+    /*$PAGE*/
+    /*
+    *********************************************************************************************************
+    *                                   LOOK FOR MISSING #define CONSTANTS
+    *
+    * This section is used to generate ERROR messages at compile time if certain #define constants are
+    * MISSING in OS_CFG.H.  This allows you to quickly determine the source of the error.
+    *
+    * You SHOULD NOT change this section UNLESS you would like to add more comments as to the source of the
+    * compile time error.
+    *********************************************************************************************************
+    */
+
+    /*
+    *********************************************************************************************************
+    *                                             EVENT FLAGS
+    *********************************************************************************************************
+    */
+
+#ifndef OS_FLAG_EN
+#error "OS_CFG.H, Missing OS_FLAG_EN: Enable (1) or Disable (0) code generation for Event Flags"
+#else
+#ifndef OS_MAX_FLAGS
+#error "OS_CFG.H, Missing OS_MAX_FLAGS: Max. number of Event Flag Groups in your application"
+#else
+#if OS_MAX_FLAGS > 65500u
+#error "OS_CFG.H, OS_MAX_FLAGS must be <= 65500"
+#endif
+#endif
+
+#ifndef OS_FLAGS_NBITS
+#error "OS_CFG.H, Missing OS_FLAGS_NBITS: Determine #bits used for event flags, MUST be either 8, 16 or 32"
+#endif
+
+#ifndef OS_FLAG_WAIT_CLR_EN
+#error "OS_CFG.H, Missing OS_FLAG_WAIT_CLR_EN: Include code for Wait on Clear EVENT FLAGS"
+#endif
+
+#ifndef OS_FLAG_ACCEPT_EN
+#error "OS_CFG.H, Missing OS_FLAG_ACCEPT_EN: Include code for OSFlagAccept()"
+#endif
+
+#ifndef OS_FLAG_DEL_EN
+#error "OS_CFG.H, Missing OS_FLAG_DEL_EN: Include code for OSFlagDel()"
+#endif
+
+#ifndef OS_FLAG_NAME_EN
+#error "OS_CFG.H, Missing OS_FLAG_NAME_EN: Enable flag group names"
+#endif
+
+#ifndef OS_FLAG_QUERY_EN
+#error "OS_CFG.H, Missing OS_FLAG_QUERY_EN: Include code for OSFlagQuery()"
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                          MESSAGE MAILBOXES
+    *********************************************************************************************************
+    */
+
+#ifndef OS_MBOX_EN
+#error "OS_CFG.H, Missing OS_MBOX_EN: Enable (1) or Disable (0) code generation for MAILBOXES"
+#else
+#ifndef OS_MBOX_ACCEPT_EN
+#error "OS_CFG.H, Missing OS_MBOX_ACCEPT_EN: Include code for OSMboxAccept()"
+#endif
+
+#ifndef OS_MBOX_DEL_EN
+#error "OS_CFG.H, Missing OS_MBOX_DEL_EN: Include code for OSMboxDel()"
+#endif
+
+#ifndef OS_MBOX_PEND_ABORT_EN
+#error "OS_CFG.H, Missing OS_MBOX_PEND_ABORT_EN: Include code for OSMboxPendAbort()"
+#endif
+
+#ifndef OS_MBOX_POST_EN
+#error "OS_CFG.H, Missing OS_MBOX_POST_EN: Include code for OSMboxPost()"
+#endif
+
+#ifndef OS_MBOX_POST_OPT_EN
+#error "OS_CFG.H, Missing OS_MBOX_POST_OPT_EN: Include code for OSMboxPostOpt()"
+#endif
+
+#ifndef OS_MBOX_QUERY_EN
+#error "OS_CFG.H, Missing OS_MBOX_QUERY_EN: Include code for OSMboxQuery()"
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                          MEMORY MANAGEMENT
+    *********************************************************************************************************
+    */
+
+#ifndef OS_MEM_EN
+#error "OS_CFG.H, Missing OS_MEM_EN: Enable (1) or Disable (0) code generation for MEMORY MANAGER"
+#else
+#ifndef OS_MAX_MEM_PART
+#error "OS_CFG.H, Missing OS_MAX_MEM_PART: Max. number of memory partitions"
+#else
+#if OS_MAX_MEM_PART > 65500u
+#error "OS_CFG.H, OS_MAX_MEM_PART must be <= 65500"
+#endif
+#endif
+
+#ifndef OS_MEM_NAME_EN
+#error "OS_CFG.H, Missing OS_MEM_NAME_EN: Enable memory partition names"
+#endif
+
+#ifndef OS_MEM_QUERY_EN
+#error "OS_CFG.H, Missing OS_MEM_QUERY_EN: Include code for OSMemQuery()"
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                     MUTUAL EXCLUSION SEMAPHORES
+    *********************************************************************************************************
+    */
+
+#ifndef OS_MUTEX_EN
+#error "OS_CFG.H, Missing OS_MUTEX_EN: Enable (1) or Disable (0) code generation for MUTEX"
+#else
+#ifndef OS_MUTEX_ACCEPT_EN
+#error "OS_CFG.H, Missing OS_MUTEX_ACCEPT_EN: Include code for OSMutexAccept()"
+#endif
+
+#ifndef OS_MUTEX_DEL_EN
+#error "OS_CFG.H, Missing OS_MUTEX_DEL_EN: Include code for OSMutexDel()"
+#endif
+
+#ifndef OS_MUTEX_QUERY_EN
+#error "OS_CFG.H, Missing OS_MUTEX_QUERY_EN: Include code for OSMutexQuery()"
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                           MESSAGE QUEUES
+    *********************************************************************************************************
+    */
+
+#ifndef OS_Q_EN
+#error "OS_CFG.H, Missing OS_Q_EN: Enable (1) or Disable (0) code generation for QUEUES"
+#else
+#ifndef OS_MAX_QS
+#error "OS_CFG.H, Missing OS_MAX_QS: Max. number of queue control blocks"
+#else
+#if OS_MAX_QS > 65500u
+#error "OS_CFG.H, OS_MAX_QS must be <= 65500"
+#endif
+#endif
+
+#ifndef OS_Q_ACCEPT_EN
+#error "OS_CFG.H, Missing OS_Q_ACCEPT_EN: Include code for OSQAccept()"
+#endif
+
+#ifndef OS_Q_DEL_EN
+#error "OS_CFG.H, Missing OS_Q_DEL_EN: Include code for OSQDel()"
+#endif
+
+#ifndef OS_Q_FLUSH_EN
+#error "OS_CFG.H, Missing OS_Q_FLUSH_EN: Include code for OSQFlush()"
+#endif
+
+#ifndef OS_Q_PEND_ABORT_EN
+#error "OS_CFG.H, Missing OS_Q_PEND_ABORT_EN: Include code for OSQPendAbort()"
+#endif
+
+#ifndef OS_Q_POST_EN
+#error "OS_CFG.H, Missing OS_Q_POST_EN: Include code for OSQPost()"
+#endif
+
+#ifndef OS_Q_POST_FRONT_EN
+#error "OS_CFG.H, Missing OS_Q_POST_FRONT_EN: Include code for OSQPostFront()"
+#endif
+
+#ifndef OS_Q_POST_OPT_EN
+#error "OS_CFG.H, Missing OS_Q_POST_OPT_EN: Include code for OSQPostOpt()"
+#endif
+
+#ifndef OS_Q_QUERY_EN
+#error "OS_CFG.H, Missing OS_Q_QUERY_EN: Include code for OSQQuery()"
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                             SEMAPHORES
+    *********************************************************************************************************
+    */
+
+#ifndef OS_SEM_EN
+#error "OS_CFG.H, Missing OS_SEM_EN: Enable (1) or Disable (0) code generation for SEMAPHORES"
+#else
+#ifndef OS_SEM_ACCEPT_EN
+#error "OS_CFG.H, Missing OS_SEM_ACCEPT_EN: Include code for OSSemAccept()"
+#endif
+
+#ifndef OS_SEM_DEL_EN
+#error "OS_CFG.H, Missing OS_SEM_DEL_EN: Include code for OSSemDel()"
+#endif
+
+#ifndef OS_SEM_PEND_ABORT_EN
+#error "OS_CFG.H, Missing OS_SEM_PEND_ABORT_EN: Include code for OSSemPendAbort()"
+#endif
+
+#ifndef OS_SEM_QUERY_EN
+#error "OS_CFG.H, Missing OS_SEM_QUERY_EN: Include code for OSSemQuery()"
+#endif
+
+#ifndef OS_SEM_SET_EN
+#error "OS_CFG.H, Missing OS_SEM_SET_EN: Include code for OSSemSet()"
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                           TASK MANAGEMENT
+    *********************************************************************************************************
+    */
+
+#ifndef OS_MAX_TASKS
+#error "OS_CFG.H, Missing OS_MAX_TASKS: Max. number of tasks in your application"
+#else
+#if OS_MAX_TASKS < 2u
+#error "OS_CFG.H,         OS_MAX_TASKS must be >= 2"
+#endif
+
+#if OS_MAX_TASKS > ((OS_LOWEST_PRIO - OS_N_SYS_TASKS) + 1u)
+#error "OS_CFG.H,         OS_MAX_TASKS must be <= OS_LOWEST_PRIO - OS_N_SYS_TASKS + 1"
+#endif
+
+#endif
+
+#if OS_LOWEST_PRIO > 254u
+#error "OS_CFG.H,         OS_LOWEST_PRIO must be <= 254 in V2.8x and higher"
+#endif
+
+#ifndef OS_TASK_IDLE_STK_SIZE
+#error "OS_CFG.H, Missing OS_TASK_IDLE_STK_SIZE: Idle task stack size"
+#endif
+
+#ifndef OS_TASK_STAT_EN
+#error "OS_CFG.H, Missing OS_TASK_STAT_EN: Enable (1) or Disable(0) the statistics task"
+#endif
+
+#ifndef OS_TASK_STAT_STK_SIZE
+#error "OS_CFG.H, Missing OS_TASK_STAT_STK_SIZE: Statistics task stack size"
+#endif
+
+#ifndef OS_TASK_STAT_STK_CHK_EN
+#error "OS_CFG.H, Missing OS_TASK_STAT_STK_CHK_EN: Check task stacks from statistics task"
+#endif
+
+#ifndef OS_TASK_CHANGE_PRIO_EN
+#error "OS_CFG.H, Missing OS_TASK_CHANGE_PRIO_EN: Include code for OSTaskChangePrio()"
+#endif
+
+#ifndef OS_TASK_CREATE_EN
+#error "OS_CFG.H, Missing OS_TASK_CREATE_EN: Include code for OSTaskCreate()"
+#endif
+
+#ifndef OS_TASK_CREATE_EXT_EN
+#error "OS_CFG.H, Missing OS_TASK_CREATE_EXT_EN: Include code for OSTaskCreateExt()"
+#else
+#if (OS_TASK_CREATE_EXT_EN == 0u) && (OS_TASK_CREATE_EN == 0u)
+#error "OS_CFG.H,         OS_TASK_CREATE_EXT_EN or OS_TASK_CREATE_EN must be Enable (1)"
+#endif
+#endif
+
+#ifndef OS_TASK_DEL_EN
+#error "OS_CFG.H, Missing OS_TASK_DEL_EN: Include code for OSTaskDel()"
+#endif
+
+#ifndef OS_TASK_NAME_EN
+#error "OS_CFG.H, Missing OS_TASK_NAME_EN: Enable task names"
+#endif
+
+#ifndef OS_TASK_SUSPEND_EN
+#error "OS_CFG.H, Missing OS_TASK_SUSPEND_EN: Include code for OSTaskSuspend() and OSTaskResume()"
+#endif
+
+#ifndef OS_TASK_QUERY_EN
+#error "OS_CFG.H, Missing OS_TASK_QUERY_EN: Include code for OSTaskQuery()"
+#endif
+
+#ifndef OS_TASK_REG_TBL_SIZE
+#error "OS_CFG.H, Missing OS_TASK_REG_TBL_SIZE: Include code for task specific registers"
+#else
+#if OS_TASK_REG_TBL_SIZE > 255u
+#error "OS_CFG.H,         OS_TASK_REG_TBL_SIZE must be <= 255"
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                           TIME MANAGEMENT
+    *********************************************************************************************************
+    */
+
+#ifndef OS_TICKS_PER_SEC
+#error "OS_CFG.H, Missing OS_TICKS_PER_SEC: Sets the number of ticks in one second"
+#endif
+
+#ifndef OS_TIME_DLY_HMSM_EN
+#error "OS_CFG.H, Missing OS_TIME_DLY_HMSM_EN: Include code for OSTimeDlyHMSM()"
+#endif
+
+#ifndef OS_TIME_DLY_RESUME_EN
+#error "OS_CFG.H, Missing OS_TIME_DLY_RESUME_EN: Include code for OSTimeDlyResume()"
+#endif
+
+#ifndef OS_TIME_GET_SET_EN
+#error "OS_CFG.H, Missing OS_TIME_GET_SET_EN: Include code for OSTimeGet() and OSTimeSet()"
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                          TIMER MANAGEMENT
+    *********************************************************************************************************
+    */
+
+#ifndef OS_TMR_EN
+#error "OS_CFG.H, Missing OS_TMR_EN: When (1) enables code generation for Timer Management"
+#elif OS_TMR_EN > 0u
+#if OS_SEM_EN == 0u
+#error "OS_CFG.H, Semaphore management is required (set OS_SEM_EN to 1) when enabling Timer Management."
+#error "          Timer management require TWO semaphores."
+#endif
+
+#ifndef OS_TMR_CFG_MAX
+#error "OS_CFG.H, Missing OS_TMR_CFG_MAX: Determines the total number of timers in an application (2 .. 65500)"
+#else
+#if OS_TMR_CFG_MAX < 2u
+#error "OS_CFG.H, OS_TMR_CFG_MAX should be between 2 and 65500"
+#endif
+
+#if OS_TMR_CFG_MAX > 65500u
+#error "OS_CFG.H, OS_TMR_CFG_MAX should be between 2 and 65500"
+#endif
+#endif
+
+#ifndef OS_TMR_CFG_WHEEL_SIZE
+#error "OS_CFG.H, Missing OS_TMR_CFG_WHEEL_SIZE: Sets the size of the timer wheel (1 .. 1023)"
+#else
+#if OS_TMR_CFG_WHEEL_SIZE < 2u
+#error "OS_CFG.H, OS_TMR_CFG_WHEEL_SIZE should be between 2 and 1024"
+#endif
+
+#if OS_TMR_CFG_WHEEL_SIZE > 1024u
+#error "OS_CFG.H, OS_TMR_CFG_WHEEL_SIZE should be between 2 and 1024"
+#endif
+#endif
+
+#ifndef OS_TMR_CFG_NAME_EN
+#error "OS_CFG.H, Missing OS_TMR_CFG_NAME_EN: Enable Timer names"
+#endif
+
+#ifndef OS_TMR_CFG_TICKS_PER_SEC
+#error "OS_CFG.H, Missing OS_TMR_CFG_TICKS_PER_SEC: Determines the rate at which the timer management task will run (Hz)"
+#endif
+
+#ifndef OS_TASK_TMR_STK_SIZE
+#error "OS_CFG.H, Missing OS_TASK_TMR_STK_SIZE: Determines the size of the Timer Task's stack"
+#endif
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                            MISCELLANEOUS
+    *********************************************************************************************************
+    */
+
+#ifndef OS_ARG_CHK_EN
+#error "OS_CFG.H, Missing OS_ARG_CHK_EN: Enable (1) or Disable (0) argument checking"
+#endif
+
+#ifndef OS_CPU_HOOKS_EN
+#error "OS_CFG.H, Missing OS_CPU_HOOKS_EN: uC/OS-II hooks are found in the processor port files when 1"
+#endif
+
+#ifndef OS_APP_HOOKS_EN
+#error "OS_CFG.H, Missing OS_APP_HOOKS_EN: Application-defined hooks are called from the uC/OS-II hooks"
+#endif
+
+#ifndef OS_DEBUG_EN
+#error "OS_CFG.H, Missing OS_DEBUG_EN: Allows you to include variables for debugging or not"
+#endif
+
+#ifndef OS_LOWEST_PRIO
+#error "OS_CFG.H, Missing OS_LOWEST_PRIO: Defines the lowest priority that can be assigned"
+#endif
+
+#ifndef OS_MAX_EVENTS
+#error "OS_CFG.H, Missing OS_MAX_EVENTS: Max. number of event control blocks in your application"
+#else
+#if OS_MAX_EVENTS > 65500u
+#error "OS_CFG.H, OS_MAX_EVENTS must be <= 65500"
+#endif
+#endif
+
+#ifndef OS_SCHED_LOCK_EN
+#error "OS_CFG.H, Missing OS_SCHED_LOCK_EN: Include code for OSSchedLock() and OSSchedUnlock()"
+#endif
+
+#ifndef OS_EVENT_MULTI_EN
+#error "OS_CFG.H, Missing OS_EVENT_MULTI_EN: Include code for OSEventPendMulti()"
+#endif
+
+#ifndef OS_TASK_PROFILE_EN
+#error "OS_CFG.H, Missing OS_TASK_PROFILE_EN: Include data structure for run-time task profiling"
+#endif
+
+#ifndef OS_TASK_SW_HOOK_EN
+#error "OS_CFG.H, Missing OS_TASK_SW_HOOK_EN: Allows you to include the code for OSTaskSwHook() or not"
+#endif
+
+#ifndef OS_TICK_STEP_EN
+#error "OS_CFG.H, Missing OS_TICK_STEP_EN: Allows to 'step' one tick at a time with uC/OS-View"
+#endif
+
+#ifndef OS_TIME_TICK_HOOK_EN
+#error "OS_CFG.H, Missing OS_TIME_TICK_HOOK_EN: Allows you to include the code for OSTimeTickHook() or not"
+#endif
+
+    /*
+    *********************************************************************************************************
+    *                                         SAFETY CRITICAL USE
+    *********************************************************************************************************
+    */
+
+#ifdef SAFETY_CRITICAL_RELEASE
+
+#if OS_ARG_CHK_EN < 1u
+#error "OS_CFG.H, OS_ARG_CHK_EN must be enabled for safety-critical release code"
+#endif
+
+#if OS_APP_HOOKS_EN > 0u
+#error "OS_CFG.H, OS_APP_HOOKS_EN must be disabled for safety-critical release code"
+#endif
+
+#if OS_DEBUG_EN > 0u
+#error "OS_CFG.H, OS_DEBUG_EN must be disabled for safety-critical release code"
+#endif
+
+#ifdef CANTATA
+#error "OS_CFG.H, CANTATA must be disabled for safety-critical release code"
+#endif
+
+#ifdef OS_SCHED_LOCK_EN
+#error "OS_CFG.H, OS_SCHED_LOCK_EN must be disabled for safety-critical release code"
+#endif
+
+#ifdef VSC_VALIDATION_MODE
+#error "OS_CFG.H, VSC_VALIDATION_MODE must be disabled for safety-critical release code"
+#endif
+
+#if OS_TASK_STAT_EN > 0u
+#error "OS_CFG.H, OS_TASK_STAT_EN must be disabled for safety-critical release code"
+#endif
+
+#if OS_TICK_STEP_EN > 0u
+#error "OS_CFG.H, OS_TICK_STEP_EN must be disabled for safety-critical release code"
+#endif
+
+#if OS_FLAG_EN > 0u
+#if OS_FLAG_DEL_EN > 0
+#error "OS_CFG.H, OS_FLAG_DEL_EN must be disabled for safety-critical release code"
+#endif
+#endif
+
+#if OS_MBOX_EN > 0u
+#if OS_MBOX_DEL_EN > 0u
+#error "OS_CFG.H, OS_MBOX_DEL_EN must be disabled for safety-critical release code"
+#endif
+#endif
+
+#if OS_MUTEX_EN > 0u
+#if OS_MUTEX_DEL_EN > 0u
+#error "OS_CFG.H, OS_MUTEX_DEL_EN must be disabled for safety-critical release code"
+#endif
+#endif
+
+#if OS_Q_EN > 0u
+#if OS_Q_DEL_EN > 0u
+#error "OS_CFG.H, OS_Q_DEL_EN must be disabled for safety-critical release code"
+#endif
+#endif
+
+#if OS_SEM_EN > 0u
+#if OS_SEM_DEL_EN > 0u
+#error "OS_CFG.H, OS_SEM_DEL_EN must be disabled for safety-critical release code"
+#endif
+#endif
+
+#if OS_TASK_DEL_EN > 0u
+#error "OS_CFG.H, OS_TASK_DEL_EN must be disabled for safety-critical release code"
+#endif
+
+#if OS_CRITICAL_METHOD != 3u
+#error "OS_CPU.H, OS_CRITICAL_METHOD must be type 3 for safety-critical release code"
+#endif
+
+#endif /* ------------------------ SAFETY_CRITICAL_RELEASE ------------------------ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 1 - 1
User/Bsp/LED/led.c

@@ -1,6 +1,6 @@
 #include "led.h"
 
-void LED_Init(void)
+void led_init(void)
 {
     /* 1、打开外设时钟 */
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOC, ENABLE);

+ 1 - 1
User/Bsp/LED/led.h

@@ -3,6 +3,6 @@
 
 #include "stm32f4xx.h"
 
-void LED_Init(void);
+void led_init(void);
 
 #endif

+ 6 - 0
User/Bsp/bsp.c

@@ -0,0 +1,6 @@
+#include "led.h"
+
+void bsp_init(void)
+{
+    led_init();
+}

+ 0 - 0
User/Bsp/interface/interface.c


+ 216 - 0
User/Bsp/interface/interface.h

@@ -0,0 +1,216 @@
+// #ifndef __INTERFACE_H
+// #define __INTERFACE_H
+
+// #include <stm32f4xx.h>
+// #include "stm32f4xx_rcu.h"
+// #include "includes.h"
+
+// typedef enum
+// {
+//     kI2C0 = 0,
+//     kI2C1,
+//     kI2C2,
+//     kADC0,
+//     kADC2,
+//     kSPI2,
+//     kUart0,
+//     kUart5,
+//     kCAN0,
+//     kCAN1,
+//     kEthernet,
+//     kInput,
+//     kOutput,
+//     kPMU,
+//     kDMA1,
+//     //    kTIMER1,
+//     kInterfaceEnd,
+// } interface_type;
+
+// typedef enum
+// {
+//     kRunLed,
+//     kPRelayCtr,
+//     kNRelayCtr,
+//     kPreRelayCtr,
+//     kFanCtr,
+//     kOut1Ctr, // charger
+//     kOut2Ctr, // charger heat
+//     kExtWatchDog,
+//     kExtRelayLed,
+//     kExtFaultLed,
+//     kISOPRelayCtr,
+//     kISONRelayCtr,
+//     kSoftI2C3_SDA,
+//     kSoftI2C3_SCL,
+//     kSoftI2C4_SDA,
+//     kSoftI2C4_SCL,
+//     kOutputEnd,
+// } Output_Type;
+
+// typedef enum
+// {
+//     kLDetect,
+//     kInputEnd,
+// } Input_type;
+
+// typedef struct
+// {
+//     INT32U GPIOx;
+//     INT32U GPIO_Pin;
+//     INT8U GPIO_AF;
+// } GPIO_AF_Info;
+
+// typedef struct
+// {
+//     interface_type type;
+//     Output_Type Out_Type;
+//     Input_type In_Type;
+//     INT32U GPIOx;
+//     INT32U GPIO_Pin;
+//     INT32U GPIO_Mode;
+//     GPIO_AF_Info AF_Info;
+//     INT8U GPIO_OType;
+//     INT32U GPIO_Speed;
+//     INT32U GPIO_PuPd;
+// } Interface_struct;
+
+// typedef struct
+// {
+//     interface_type type;
+//     rcu_periph_enum AXBPeriph_Clock;
+// } Gpio_Clock;
+
+// // soft I2C
+// #define SI2C3_SDA_PIN GPIO_PIN_3
+// #define SI2C3_SDA_PORT GPIOD
+// #define SI2C3_SCL_PIN GPIO_PIN_2
+// #define SI2C3_SCL_PORT GPIOD
+// #define SI2C4_SDA_PIN GPIO_PIN_15
+// #define SI2C4_SDA_PORT GPIOE
+// #define SI2C4_SCL_PIN GPIO_PIN_14
+// #define SI2C4_SCL_PORT GPIOE
+
+// #define SI2C3_SDA_HIGH gpio_bit_set(SI2C3_SDA_PORT, SI2C3_SDA_PIN)
+// #define SI2C3_SDA_LOW gpio_bit_reset(SI2C3_SDA_PORT, SI2C3_SDA_PIN)
+// #define SI2C3_SCL_HIGH gpio_bit_set(SI2C3_SCL_PORT, SI2C3_SCL_PIN)
+// #define SI2C3_SCL_LOW gpio_bit_reset(SI2C3_SCL_PORT, SI2C3_SCL_PIN)
+// #define SI2C4_SDA_HIGH gpio_bit_set(SI2C4_SDA_PORT, SI2C4_SDA_PIN)
+// #define SI2C4_SDA_LOW gpio_bit_reset(SI2C4_SDA_PORT, SI2C4_SDA_PIN)
+// #define SI2C4_SCL_HIGH gpio_bit_set(SI2C4_SCL_PORT, SI2C4_SCL_PIN)
+// #define SI2C4_SCL_LOW gpio_bit_reset(SI2C4_SCL_PORT, SI2C4_SCL_PIN)
+
+// #define SI2C3_SDA_OUT gpio_mode_set(SI2C3_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, SI2C3_SDA_PIN)
+// #define SI2C3_SDA_IN gpio_mode_set(SI2C3_SDA_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, SI2C3_SDA_PIN)
+// #define SI2C3_SDA_READ gpio_input_bit_get(SI2C3_SDA_PORT, SI2C3_SDA_PIN)
+// #define SI2C4_SDA_OUT gpio_mode_set(SI2C4_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, SI2C4_SDA_PIN)
+// #define SI2C4_SDA_IN gpio_mode_set(SI2C4_SDA_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, SI2C4_SDA_PIN)
+// #define SI2C4_SDA_READ gpio_input_bit_get(SI2C4_SDA_PORT, SI2C4_SDA_PIN)
+
+// // uart
+// #define UART0_ENABLE_PORT GPIOE
+// #define UART0_ENABLE_PIN GPIO_PIN_5
+// #define UART5_ENABLE_PORT GPIOE
+// #define UART5_ENABLE_PIN GPIO_PIN_6
+// #define UART0_TX_ENABLE gpio_bit_set(UART0_ENABLE_PORT, UART0_ENABLE_PIN)
+// #define UART0_RX_ENABLE gpio_bit_reset(UART0_ENABLE_PORT, UART0_ENABLE_PIN)
+// #define UART5_TX_ENABLE gpio_bit_set(UART5_ENABLE_PORT, UART5_ENABLE_PIN)
+// #define UART5_RX_ENABLE gpio_bit_reset(UART5_ENABLE_PORT, UART5_ENABLE_PIN)
+
+// // SPI
+// #define SPI2_CS_PORT GPIOA
+// #define SPI2_CS_PIN GPIO_PIN_15
+// #define SPI2_CS_HIGH gpio_bit_set(SPI2_CS_PORT, SPI2_CS_PIN)
+// #define SPI2_CS_LOW gpio_bit_reset(SPI2_CS_PORT, SPI2_CS_PIN)
+
+// // ethernet
+// //#define		ENET_REF_CLK					GPIO_PIN_1
+// //#define		ENET_REF_CLK_Port			GPIOA
+// //#define		ENET_MDC							GPIO_PIN_1
+// //#define		ENET_MDC_Port					GPIOC
+// //#define		ENET_MDIO							GPIO_PIN_2
+// //#define		ENET_MDIO_Port				GPIOA
+// //#define		ENET_CRSDV						GPIO_PIN_7
+// //#define		ENET_CRSDV_Port				GPIOA
+// //#define		ENET_RXD0							GPIO_PIN_4
+// //#define		ENET_RXD0_Port				GPIOC
+// //#define		ENET_RXD1							GPIO_PIN_5
+// //#define		ENET_RXD1_Port				GPIOC
+// //#define		ENET_TXEN							GPIO_PIN_11
+// //#define		ENET_TXEN_Port				GPIOG
+// //#define		ENET_RXER							GPIO_PIN_12
+// //#define		ENET_RXER_Port				GPIOG
+// //#define		ENET_TXD0							GPIO_PIN_13
+// //#define		ENET_TXD0_Port				GPIOG
+// //#define		ENET_TXD1							GPIO_PIN_14
+// //#define		ENET_TXD1_Port				GPIOG
+// #define ETH_RESET_PORT GPIOE
+// #define ETH_RESET_PIN GPIO_PIN_2
+// #define ETH_RXER_PORT GPIOG
+// #define ETH_RXER_PIN GPIO_PIN_12
+// #define ETH_RESET_ON gpio_bit_reset(ETH_RESET_PORT, ETH_RESET_PIN)
+// #define ETH_RESET_OFF gpio_bit_set(ETH_RESET_PORT, ETH_RESET_PIN)
+
+// // output
+// #define LED_RUN_PORT GPIOE
+// #define LED_RUN_PIN GPIO_PIN_3
+// #define PRelayCtr_PORT GPIOD
+// #define PRelayCtr_PIN GPIO_PIN_6
+// #define NRelayCtr_PORT GPIOD
+// #define NRelayCtr_PIN GPIO_PIN_5
+// #define PreRelayCtr_PORT GPIOG
+// #define PreRelayCtr_PIN GPIO_PIN_9
+// #define Fan_PORT GPIOG
+// #define Fan_PIN GPIO_PIN_10
+// #define OUT1CTR_PORT GPIOD
+// #define OUT1CTR_PIN GPIO_PIN_7
+// #define OUT2CTR_PORT GPIOE
+// #define OUT2CTR_PIN GPIO_PIN_1
+// #define EXTWATCHDOG_PORT GPIOC
+// #define EXTWATCHDOG_PIN GPIO_PIN_3
+// #define ExtRelayLed_PORT GPIOD
+// #define ExtRelayLed_PIN GPIO_PIN_11
+// #define ExtFaultLed_PORT GPIOD
+// #define ExtFaultLed_PIN GPIO_PIN_10
+// #define ISOPRelayCtr_PORT GPIOF
+// #define ISOPRelayCtr_PIN GPIO_PIN_14
+// #define ISONRelayCtr_PORT GPIOF
+// #define ISONRelayCtr_PIN GPIO_PIN_15
+
+// // input
+// #define LDetect1_PORT GPIOD
+// #define LDetect1_PIN GPIO_PIN_13
+
+// // output operation
+// #define LED_RUN_ON gpio_bit_set(LED_RUN_PORT, LED_RUN_PIN)
+// #define LED_RUN_OFF gpio_bit_reset(LED_RUN_PORT, LED_RUN_PIN)
+// #define LED_RUN_TOGGLE gpio_bit_write(LED_RUN_PORT, LED_RUN_PIN, (FlagStatus)(1 - (gpio_output_bit_get(LED_RUN_PORT, LED_RUN_PIN))))
+// #define PRelayCtr_ON gpio_bit_set(PRelayCtr_PORT, PRelayCtr_PIN)
+// #define PRelayCtr_OFF gpio_bit_reset(PRelayCtr_PORT, PRelayCtr_PIN)
+// #define NRelayCtr_ON gpio_bit_set(NRelayCtr_PORT, NRelayCtr_PIN)
+// #define NRelayCtr_OFF gpio_bit_reset(NRelayCtr_PORT, NRelayCtr_PIN)
+// #define PreRelayCtr_ON gpio_bit_set(PreRelayCtr_PORT, PreRelayCtr_PIN)
+// #define PreRelayCtr_OFF gpio_bit_reset(PreRelayCtr_PORT, PreRelayCtr_PIN)
+// #define FAN_ON gpio_bit_set(Fan_PORT, Fan_PIN)
+// #define FAN_OFF gpio_bit_reset(Fan_PORT, Fan_PIN)
+// #define OUT1CTR_ON gpio_bit_set(OUT1CTR_PORT, OUT1CTR_PIN)
+// #define OUT1CTR_OFF gpio_bit_reset(OUT1CTR_PORT, OUT1CTR_PIN)
+// #define OUT2CTR_ON gpio_bit_set(OUT2CTR_PORT, OUT2CTR_PIN)
+// #define OUT2CTR_OFF gpio_bit_reset(OUT2CTR_PORT, OUT2CTR_PIN)
+// #define FEED_DOG_ON gpio_bit_set(EXTWATCHDOG_PORT, EXTWATCHDOG_PIN)
+// #define FEED_DOG_OFF gpio_bit_reset(EXTWATCHDOG_PORT, EXTWATCHDOG_PIN)
+// #define FEED_DOG_TOGGLE gpio_bit_write(EXTWATCHDOG_PORT, EXTWATCHDOG_PIN, (FlagStatus)(1 - (gpio_output_bit_get(EXTWATCHDOG_PORT, EXTWATCHDOG_PIN))))
+// #define ExtRelayLed_ON gpio_bit_set(ExtRelayLed_PORT, ExtRelayLed_PIN)
+// #define ExtRelayLed_OFF gpio_bit_reset(ExtRelayLed_PORT, ExtRelayLed_PIN)
+// #define ExtFaultLed_ON gpio_bit_set(ExtFaultLed_PORT, ExtFaultLed_PIN)
+// #define ExtFaultLed_OFF gpio_bit_reset(ExtFaultLed_PORT, ExtFaultLed_PIN)
+// #define ISOPRelay_ON gpio_bit_set(ISOPRelayCtr_PORT, ISOPRelayCtr_PIN)
+// #define ISOPRelay_OFF gpio_bit_reset(ISOPRelayCtr_PORT, ISOPRelayCtr_PIN)
+// #define ISONRelay_ON gpio_bit_set(ISONRelayCtr_PORT, ISONRelayCtr_PIN)
+// #define ISONRelay_OFF gpio_bit_reset(ISONRelayCtr_PORT, ISONRelayCtr_PIN)
+
+// // input result
+// #define L_IN1_IS_LOW (gpio_input_bit_get(LDetect1_PORT, LDetect1_PIN) == RESET)
+
+// void gpio_clock_init(void);
+// void interface_init(void);
+// #endif

+ 252 - 0
User/UCOS-CONFIG/app_hooks.c

@@ -0,0 +1,252 @@
+/*
+*********************************************************************************************************
+*                                            EXAMPLE CODE
+*
+*               This file is provided as an example on how to use Micrium products.
+*
+*               Please feel free to use any application code labeled as 'EXAMPLE CODE' in
+*               your application products.  Example code may be used as is, in whole or in
+*               part, or may be used as a reference only. This file can be modified as
+*               required to meet the end-product requirements.
+*
+*               Please help us continue to provide the Embedded community with the finest
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                             uC/OS-II
+*                                         Application Hooks
+*
+* Filename      : app_hooks.c
+* Version       : V1.00
+* Programmer(s) : FT
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                             INCLUDE FILES
+*********************************************************************************************************
+*/
+
+#include <includes.h>
+
+/*
+*********************************************************************************************************
+*                                       EXTERN  GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                           LOCAL CONSTANTS
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                          LOCAL DATA TYPES
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                            LOCAL TABLES
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                       LOCAL GLOBAL VARIABLES
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                      LOCAL FUNCTION PROTOTYPES
+*********************************************************************************************************
+*/
+
+/*
+**********************************************************************************************************
+**********************************************************************************************************
+**                                        GLOBAL FUNCTIONS
+**********************************************************************************************************
+**********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*********************************************************************************************************
+**                                         uC/OS-II APP HOOKS
+*********************************************************************************************************
+*********************************************************************************************************
+*/
+
+#if (OS_APP_HOOKS_EN > 0)
+
+/*
+*********************************************************************************************************
+*                                      TASK CREATION HOOK (APPLICATION)
+*
+* Description : This function is called when a task is created.
+*
+* Argument(s) : ptcb   is a pointer to the task control block of the task being created.
+*
+* Note(s)     : (1) Interrupts are disabled during this call.
+*********************************************************************************************************
+*/
+
+void App_TaskCreateHook(OS_TCB *ptcb)
+{
+#if (APP_CFG_PROBE_OS_PLUGIN_EN == DEF_ENABLED) && (OS_PROBE_HOOKS_EN > 0)
+    OSProbe_TaskCreateHook(ptcb);
+#endif
+}
+
+/*
+*********************************************************************************************************
+*                                    TASK DELETION HOOK (APPLICATION)
+*
+* Description : This function is called when a task is deleted.
+*
+* Argument(s) : ptcb   is a pointer to the task control block of the task being deleted.
+*
+* Note(s)     : (1) Interrupts are disabled during this call.
+*********************************************************************************************************
+*/
+
+void App_TaskDelHook(OS_TCB *ptcb)
+{
+    (void)ptcb;
+}
+
+/*
+*********************************************************************************************************
+*                                      IDLE TASK HOOK (APPLICATION)
+*
+* Description : This function is called by OSTaskIdleHook(), which is called by the idle task.  This hook
+*               has been added to allow you to do such things as STOP the CPU to conserve power.
+*
+* Argument(s) : none.
+*
+* Note(s)     : (1) Interrupts are enabled during this call.
+*********************************************************************************************************
+*/
+
+#if OS_VERSION >= 251
+void App_TaskIdleHook(void)
+{
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                        STATISTIC TASK HOOK (APPLICATION)
+*
+* Description : This function is called by OSTaskStatHook(), which is called every second by uC/OS-II's
+*               statistics task.  This allows your application to add functionality to the statistics task.
+*
+* Argument(s) : none.
+*********************************************************************************************************
+*/
+
+void App_TaskStatHook(void)
+{
+}
+
+/*
+*********************************************************************************************************
+*                                            TASK RETURN HOOK (APPLICATION)
+*
+* Description: This function is called if a task accidentally returns.  In other words, a task should
+*              either be an infinite loop or delete itself when done.
+*
+* Arguments  : ptcb      is a pointer to the task control block of the task that is returning.
+*
+* Note(s)    : none
+*********************************************************************************************************
+*/
+
+#if OS_VERSION >= 289
+void App_TaskReturnHook(OS_TCB *ptcb)
+{
+    (void)ptcb;
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                        TASK SWITCH HOOK (APPLICATION)
+*
+* Description : This function is called when a task switch is performed.  This allows you to perform other
+*               operations during a context switch.
+*
+* Argument(s) : none.
+*
+* Note(s)     : (1) Interrupts are disabled during this call.
+*
+*               (2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that
+*                   will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the
+*                  task being switched out (i.e. the preempted task).
+*********************************************************************************************************
+*/
+
+#if OS_TASK_SW_HOOK_EN > 0
+void App_TaskSwHook(void)
+{
+#if (APP_CFG_PROBE_OS_PLUGIN_EN > 0) && (OS_PROBE_HOOKS_EN > 0)
+    OSProbe_TaskSwHook();
+#endif
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                     OS_TCBInit() HOOK (APPLICATION)
+*
+* Description : This function is called by OSTCBInitHook(), which is called by OS_TCBInit() after setting
+*               up most of the TCB.
+*
+* Argument(s) : ptcb    is a pointer to the TCB of the task being created.
+*
+* Note(s)     : (1) Interrupts may or may not be ENABLED during this call.
+*********************************************************************************************************
+*/
+
+#if OS_VERSION >= 204
+void App_TCBInitHook(OS_TCB *ptcb)
+{
+    (void)ptcb;
+}
+#endif
+
+/*
+*********************************************************************************************************
+*                                        TICK HOOK (APPLICATION)
+*
+* Description : This function is called every tick.
+*
+* Argument(s) : none.
+*
+* Note(s)     : (1) Interrupts may or may not be ENABLED during this call.
+*********************************************************************************************************
+*/
+
+#if OS_TIME_TICK_HOOK_EN > 0
+void App_TimeTickHook(void)
+{
+#if (APP_CFG_PROBE_OS_PLUGIN_EN == DEF_ENABLED) && (OS_PROBE_HOOKS_EN > 0)
+    OSProbe_TickHook();
+#endif
+    HAL_IncTick(); /* STM32CubeF4 library function call.                   */
+}
+#endif
+#endif

+ 215 - 0
User/UCOS-CONFIG/cpu_cfg.h

@@ -0,0 +1,215 @@
+/*
+*********************************************************************************************************
+*                                                uC/CPU
+*                                    CPU CONFIGURATION & PORT LAYER
+*
+*                          (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*
+*               uC/CPU is provided in source form to registered licensees ONLY.  It is 
+*               illegal to distribute this source code to any third party unless you receive 
+*               written permission by an authorized Micrium representative.  Knowledge of 
+*               the source code may NOT be used to develop a similar product.
+*
+*               Please help us continue to provide the Embedded community with the finest 
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find our product's user manual, API reference, release notes and
+*               more information at https://doc.micrium.com.
+*               You can contact us at www.micrium.com.
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                       CPU CONFIGURATION FILE
+*
+*                                              TEMPLATE
+*
+* Filename      : cpu_cfg.h
+* Version       : V1.30.02
+* Programmer(s) : SR
+*                 ITJ
+*                 JBL
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*********************************************************************************************************
+*/
+
+#ifndef  CPU_CFG_MODULE_PRESENT
+#define  CPU_CFG_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*                                       CPU NAME CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_NAME_EN to enable/disable CPU host name feature :
+*
+*               (a) CPU host name storage
+*               (b) CPU host name API functions
+*
+*           (2) Configure CPU_CFG_NAME_SIZE with the desired ASCII string size of the CPU host name, 
+*               including the terminating NULL character.
+*
+*               See also 'cpu_core.h  GLOBAL VARIABLES  Note #1'.
+*********************************************************************************************************
+*/
+
+                                                                /* Configure CPU host name feature (see Note #1) :      */
+#define  CPU_CFG_NAME_EN                        DEF_ENABLED
+                                                                /*   DEF_DISABLED  CPU host name DISABLED               */
+                                                                /*   DEF_ENABLED   CPU host name ENABLED                */
+
+                                                                /* Configure CPU host name ASCII string size ...        */
+#define  CPU_CFG_NAME_SIZE                                16    /* ... (see Note #2).                                   */
+
+
+/*
+*********************************************************************************************************
+*                                     CPU TIMESTAMP CONFIGURATION
+*
+* Note(s) : (1) Configure CPU_CFG_TS_xx_EN to enable/disable CPU timestamp features :
+*
+*               (a) CPU_CFG_TS_32_EN   enable/disable 32-bit CPU timestamp feature
+*               (b) CPU_CFG_TS_64_EN   enable/disable 64-bit CPU timestamp feature
+*
+*           (2) (a) Configure CPU_CFG_TS_TMR_SIZE with the CPU timestamp timer's word size :
+*
+*                       CPU_WORD_SIZE_08         8-bit word size
+*                       CPU_WORD_SIZE_16        16-bit word size
+*                       CPU_WORD_SIZE_32        32-bit word size
+*                       CPU_WORD_SIZE_64        64-bit word size
+*
+*               (b) If the size of the CPU timestamp timer is not a binary multiple of 8-bit octets 
+*                   (e.g. 20-bits or even 24-bits), then the next lower, binary-multiple octet word 
+*                   size SHOULD be configured (e.g. to 16-bits).  However, the minimum supported word 
+*                   size for CPU timestamp timers is 8-bits.
+*
+*                   See also 'cpu_core.h  FUNCTION PROTOTYPES  CPU_TS_TmrRd()  Note #2a'.
+*********************************************************************************************************
+*/
+
+                                                                /* Configure CPU timestamp features (see Note #1) :     */
+#define  CPU_CFG_TS_32_EN                       DEF_ENABLED
+#define  CPU_CFG_TS_64_EN                       DEF_DISABLED
+                                                                /*   DEF_DISABLED  CPU timestamps DISABLED              */
+                                                                /*   DEF_ENABLED   CPU timestamps ENABLED               */
+
+                                                                /* Configure CPU timestamp timer word size ...          */
+                                                                /* ... (see Note #2) :                                  */
+#define  CPU_CFG_TS_TMR_SIZE                    CPU_WORD_SIZE_32
+
+
+/*
+*********************************************************************************************************
+*                        CPU INTERRUPTS DISABLED TIME MEASUREMENT CONFIGURATION
+*
+* Note(s) : (1) (a) Configure CPU_CFG_INT_DIS_MEAS_EN to enable/disable measuring CPU's interrupts 
+*                   disabled time :
+*
+*                   (a)  Enabled,       if CPU_CFG_INT_DIS_MEAS_EN      #define'd in 'cpu_cfg.h'
+*
+*                   (b) Disabled,       if CPU_CFG_INT_DIS_MEAS_EN  NOT #define'd in 'cpu_cfg.h'
+*
+*                   See also 'cpu_core.h  FUNCTION PROTOTYPES  Note #1'.
+*
+*               (b) Configure CPU_CFG_INT_DIS_MEAS_OVRHD_NBR with the number of times to measure & 
+*                   average the interrupts disabled time measurements overhead.
+*
+*                   See also 'cpu_core.c  CPU_IntDisMeasInit()  Note #3a'.
+*********************************************************************************************************
+*/
+
+#if 1                                                           /* Configure CPU interrupts disabled time ...           */
+#define  CPU_CFG_INT_DIS_MEAS_EN                                /* ... measurements feature (see Note #1a).             */
+#endif
+
+                                                                /* Configure number of interrupts disabled overhead ... */
+#define  CPU_CFG_INT_DIS_MEAS_OVRHD_NBR                    1u   /* ... time measurements (see Note #1b).                */
+
+
+/*
+*********************************************************************************************************
+*                                    CPU COUNT ZEROS CONFIGURATION
+*
+* Note(s) : (1) (a) Configure CPU_CFG_LEAD_ZEROS_ASM_PRESENT  to define count leading  zeros bits 
+*                   function(s) in :
+*
+*                   (1) 'cpu_a.asm',  if CPU_CFG_LEAD_ZEROS_ASM_PRESENT       #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable assembly-optimized function(s)
+*
+*                   (2) 'cpu_core.c', if CPU_CFG_LEAD_ZEROS_ASM_PRESENT   NOT #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable C-source-optimized function(s) otherwise
+*
+*               (b) Configure CPU_CFG_TRAIL_ZEROS_ASM_PRESENT to define count trailing zeros bits 
+*                   function(s) in :
+*
+*                   (1) 'cpu_a.asm',  if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT      #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable assembly-optimized function(s)
+*
+*                   (2) 'cpu_core.c', if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT  NOT #define'd in 'cpu.h'/
+*                                         'cpu_cfg.h' to enable C-source-optimized function(s) otherwise
+*********************************************************************************************************
+*/
+
+#if 1                                                           /* Configure CPU count leading  zeros bits ...          */
+#define  CPU_CFG_LEAD_ZEROS_ASM_PRESENT                         /* ... assembly-version (see Note #1a).                 */
+#endif
+
+#if 0                                                           /* Configure CPU count trailing zeros bits ...          */
+#define  CPU_CFG_TRAIL_ZEROS_ASM_PRESENT                        /* ... assembly-version (see Note #1b).                 */
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                      CPU ENDIAN TYPE OVERRIDE
+*
+* Note(s) : (1) Configure CPU_CFG_ENDIAN_TYPE to override the default CPU endian type defined in cpu.h.
+*
+*               (a) CPU_ENDIAN_TYPE_BIG         Big-   endian word order (CPU words' most  significant
+*                                                                         octet @ lowest memory address)
+*               (b) CPU_ENDIAN_TYPE_LITTLE      Little-endian word order (CPU words' least significant
+*                                                                         octet @ lowest memory address)
+*
+*           (2) Defining CPU_CFG_ENDIAN_TYPE here is only valid for supported bi-endian architectures.
+*               See  'cpu.h  CPU WORD CONFIGURATION  Note #3' for details
+*********************************************************************************************************
+*/
+
+#if 0
+#define  CPU_CFG_ENDIAN_TYPE            CPU_ENDIAN_TYPE_BIG     /* Defines CPU data    word-memory order (see Note #2). */
+#endif
+
+
+/*
+*********************************************************************************************************
+*                                          CACHE MANAGEMENT
+*
+* Note(s) : (1) Configure CPU_CFG_CACHE_MGMT_EN to enable the cache managment API.
+
+*
+*           (2) Defining CPU_CFG_CACHE_MGMT_EN to DEF_ENABLED only enable the cache management function.
+*               Cache are assumed to be configured and enabled by the time CPU_init() is called.
+*********************************************************************************************************
+*/
+
+#define  CPU_CFG_CACHE_MGMT_EN            DEF_DISABLED          /* Defines CPU data    word-memory order (see Note #1). */
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*********************************************************************************************************
+*/
+
+#endif                                                          /* End of CPU cfg module include.                       */
+

+ 59 - 0
User/UCOS-CONFIG/includes.h

@@ -0,0 +1,59 @@
+/*
+*********************************************************************************************************
+*                                              EXAMPLE CODE
+*
+*                          (c) Copyright 2003-2013; Micrium, Inc.; Weston, FL
+*
+*               All rights reserved.  Protected by international copyright laws.
+*               Knowledge of the source code may NOT be used to develop a similar product.
+*               Please help us continue to provide the Embedded community with the finest
+*               software available.  Your honesty is greatly appreciated.
+*********************************************************************************************************
+*/
+#ifndef __INCLUDES_H__
+#define __INCLUDES_H__
+
+/*
+*********************************************************************************************************
+*                                         STANDARD LIBRARIES
+*********************************************************************************************************
+*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+/*
+*********************************************************************************************************
+*                                              LIBRARIES
+*********************************************************************************************************
+*/
+
+#include <cpu.h>
+#include <lib_def.h>
+#include <lib_ascii.h>
+#include <lib_math.h>
+#include <lib_mem.h>
+#include <lib_str.h>
+
+/*
+*********************************************************************************************************
+*                                              APP / BSP
+*********************************************************************************************************
+*/
+
+#include <bsp.h>
+
+/*
+*********************************************************************************************************
+*                                                 OS
+*********************************************************************************************************
+*/
+
+#include <ucos_ii.h>
+
+#define TRUE 1
+#define FALSE 0
+
+#endif

+ 171 - 0
User/UCOS-CONFIG/lib_cfg.h

@@ -0,0 +1,171 @@
+/*
+*********************************************************************************************************
+*                                            EXAMPLE CODE
+*
+*               This file is provided as an example on how to use Micrium products.
+*
+*               Please feel free to use any application code labeled as 'EXAMPLE CODE' in
+*               your application products.  Example code may be used as is, in whole or in
+*               part, or may be used as a reference only. This file can be modified as
+*               required to meet the end-product requirements.
+*
+*               Please help us continue to provide the Embedded community with the finest
+*               software available.  Your honesty is greatly appreciated.
+*
+*               You can find information about uC/LIB by visiting doc.micrium.com.
+*               You can contact us at: http://www.micrium.com
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*
+*                                  CUSTOM LIBRARY CONFIGURATION FILE
+*
+*                                              TEMPLATE
+*
+* Filename      : lib_cfg.h
+* Version       : V1.38.01.00
+* Programmer(s) : FBJ
+*                 JFD
+*********************************************************************************************************
+*/
+
+
+/*
+*********************************************************************************************************
+*                                               MODULE
+*********************************************************************************************************
+*/
+
+#ifndef  LIB_CFG_MODULE_PRESENT
+#define  LIB_CFG_MODULE_PRESENT
+
+
+/*
+*********************************************************************************************************
+*********************************************************************************************************
+*                                    MEMORY LIBRARY CONFIGURATION
+*********************************************************************************************************
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                             MEMORY LIBRARY ARGUMENT CHECK CONFIGURATION
+*
+* Note(s) : (1) Configure LIB_MEM_CFG_ARG_CHK_EXT_EN to enable/disable the memory library suite external
+*               argument check feature :
+*
+*               (a) When ENABLED,     arguments received from any port interface provided by the developer
+*                   or application are checked/validated.
+*
+*               (b) When DISABLED, NO arguments received from any port interface provided by the developer
+*                   or application are checked/validated.
+*********************************************************************************************************
+*/
+
+                                                                /* External argument check.                             */
+                                                                /* Indicates if arguments received from any port ...    */
+                                                                /* ... interface provided by the developer or ...       */
+                                                                /* ... application are checked/validated.               */
+#define  LIB_MEM_CFG_ARG_CHK_EXT_EN         DEF_DISABLED
+
+
+/*
+*********************************************************************************************************
+*                         MEMORY LIBRARY ASSEMBLY OPTIMIZATION CONFIGURATION
+*
+* Note(s) : (1) Configure LIB_MEM_CFG_OPTIMIZE_ASM_EN to enable/disable assembly-optimized memory function(s).
+*********************************************************************************************************
+*/
+
+                                                                /* Assembly-optimized function(s).                      */
+                                                                /* Enable/disable assembly-optimized memory ...         */
+                                                                /* ... function(s). [see Note #1]                       */
+#define  LIB_MEM_CFG_OPTIMIZE_ASM_EN        DEF_ENABLED
+
+
+/*
+*********************************************************************************************************
+*                                   MEMORY ALLOCATION CONFIGURATION
+*
+* Note(s) : (1) Configure LIB_MEM_CFG_DBG_INFO_EN to enable/disable memory allocation usage tracking
+*               that associates a name with each segment or dynamic pool allocated.
+*
+*           (2) (a) Configure LIB_MEM_CFG_HEAP_SIZE with the desired size of heap memory (in octets).
+*
+*               (b) Configure LIB_MEM_CFG_HEAP_BASE_ADDR to specify a base address for heap memory :
+*
+*                   (1) Heap initialized to specified application memory, if LIB_MEM_CFG_HEAP_BASE_ADDR
+*                                                                                #define'd in 'lib_cfg.h';
+*                                                                         CANNOT #define to address 0x0
+*
+*                   (2) Heap declared to Mem_Heap[] in 'lib_mem.c',       if LIB_MEM_CFG_HEAP_BASE_ADDR
+*                                                                            NOT #define'd in 'lib_cfg.h'
+*********************************************************************************************************
+*/
+
+                                                                /* Allocation debugging information.                    */
+                                                                /* Enable/disable allocation of debug information ...   */
+                                                                /* ... associated to each memory allocation.            */
+#define  LIB_MEM_CFG_DBG_INFO_EN            DEF_DISABLED
+
+
+                                                                /* Heap memory size (in bytes).                         */
+                                                                /* Configure the desired size of the heap memory. ...   */
+                                                                /* ... Set to 0 to disable heap allocation features.    */
+#define  LIB_MEM_CFG_HEAP_SIZE             (1u * 1024u)
+
+
+                                                                /* Heap memory padding alignment (in bytes).            */
+                                                                /* Configure the desired size of padding alignment ...  */
+                                                                /* ... of each buffer allocated from the heap.          */
+#define  LIB_MEM_CFG_HEAP_PADDING_ALIGN     LIB_MEM_PADDING_ALIGN_NONE
+
+#if 0                                                           /* Remove this to have heap alloc at specified addr.    */
+#define  LIB_MEM_CFG_HEAP_BASE_ADDR         0x00000000          /* Configure heap memory base address (see Note #2b).   */
+#endif
+
+
+/*
+*********************************************************************************************************
+*********************************************************************************************************
+*                                    STRING LIBRARY CONFIGURATION
+*********************************************************************************************************
+*********************************************************************************************************
+*/
+
+/*
+*********************************************************************************************************
+*                                 STRING FLOATING POINT CONFIGURATION
+*
+* Note(s) : (1) Configure LIB_STR_CFG_FP_EN to enable/disable floating point string function(s).
+*
+*           (2) Configure LIB_STR_CFG_FP_MAX_NBR_DIG_SIG to configure the maximum number of significant
+*               digits to calculate &/or display for floating point string function(s).
+*
+*               See also 'lib_str.h  STRING FLOATING POINT DEFINES  Note #1'.
+*********************************************************************************************************
+*/
+
+                                                                /* Floating point feature(s).                           */
+                                                                /* Enable/disable floating point to string functions.   */
+#define  LIB_STR_CFG_FP_EN                      DEF_DISABLED
+
+
+                                                                /* Floating point number of significant digits.         */
+                                                                /* Configure the maximum number of significant ...      */
+                                                                /* ... digits to calculate &/or display for ...         */
+                                                                /* ... floating point string function(s).               */
+#define  LIB_STR_CFG_FP_MAX_NBR_DIG_SIG         LIB_STR_FP_MAX_NBR_DIG_SIG_DFLT
+
+
+/*
+*********************************************************************************************************
+*                                             MODULE END
+*********************************************************************************************************
+*/
+
+#endif                                                          /* End of lib cfg module include.                       */
+

+ 141 - 0
User/UCOS-CONFIG/os_cfg.h

@@ -0,0 +1,141 @@
+/*
+*********************************************************************************************************
+*                                                uC/OS-II
+*                                          The Real-Time Kernel
+*                                  uC/OS-II Configuration File for V2.8x
+*
+*                               (c) Copyright 2005-2009, Micrium, Weston, FL
+*                                          All Rights Reserved
+*
+*
+* File    : OS_CFG.H
+* By      : Jean J. Labrosse
+* Version : V2.88
+*
+* LICENSING TERMS:
+* ---------------
+*   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
+* If you plan on using  uC/OS-II  in a commercial product you need to contact Micriµm to properly license
+* its use in your product. We provide ALL the source code for your convenience and to help you experience
+* uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a
+* licensing fee.
+*********************************************************************************************************
+*/
+
+#ifndef OS_CFG_H
+#define OS_CFG_H
+
+
+                                       /* ---------------------- MISCELLANEOUS ----------------------- */
+#define OS_APP_HOOKS_EN           0    /* Application-defined hooks are called from the uC/OS-II hooks */
+#define OS_ARG_CHK_EN             0    /* Enable (1) or Disable (0) argument checking                  */
+#define OS_CPU_HOOKS_EN           1    /* uC/OS-II hooks are found in the processor port files         */
+
+#define OS_DEBUG_EN               1    /* Enable(1) debug variables                                    */
+
+#define OS_EVENT_MULTI_EN         1    /* Include code for OSEventPendMulti()                          */
+#define OS_EVENT_NAME_EN          1    /* Enable names for Sem, Mutex, Mbox and Q                      */
+
+#define OS_LOWEST_PRIO           63    /* Defines the lowest priority that can be assigned ...         */
+                                       /* ... MUST NEVER be higher than 254!                           */
+
+#define OS_MAX_EVENTS            40    /* Max. number of event control blocks in your application      */
+#define OS_MAX_FLAGS              5    /* Max. number of Event Flag Groups    in your application      */
+#define OS_MAX_MEM_PART           5    /* Max. number of memory partitions                             */
+#define OS_MAX_QS                 8    /* Max. number of queue control blocks in your application      */
+#define OS_MAX_TASKS             20    /* Max. number of tasks in your application, MUST be >= 2       */
+
+#define OS_SCHED_LOCK_EN          1    /* Include code for OSSchedLock() and OSSchedUnlock()           */
+
+#define OS_TICK_STEP_EN           1    /* Enable tick stepping feature for uC/OS-View                  */
+#define OS_TICKS_PER_SEC        1000//200    /* Set the number of ticks in one second                        */     
+                                       /* --------------------- TASK STACK SIZE ---------------------- */
+#define OS_TASK_TMR_STK_SIZE    128    /* Timer      task stack size (# of OS_STK wide entries)        */
+#define OS_TASK_STAT_STK_SIZE   128    /* Statistics task stack size (# of OS_STK wide entries)        */
+#define OS_TASK_IDLE_STK_SIZE   128    /* Idle       task stack size (# of OS_STK wide entries)        */
+
+
+                                       /* --------------------- TASK MANAGEMENT ---------------------- */
+#define OS_TASK_CHANGE_PRIO_EN    1    /*     Include code for OSTaskChangePrio()                      */
+#define OS_TASK_CREATE_EN         1    /*     Include code for OSTaskCreate()                          */
+#define OS_TASK_CREATE_EXT_EN     1    /*     Include code for OSTaskCreateExt()                       */
+#define OS_TASK_DEL_EN            1    /*     Include code for OSTaskDel()                             */
+#define OS_TASK_NAME_EN           1    /*     Enable task names                                        */
+#define OS_TASK_PROFILE_EN        1    /*     Include variables in OS_TCB for profiling                */
+#define OS_TASK_QUERY_EN          1    /*     Include code for OSTaskQuery()                           */
+#define OS_TASK_STAT_EN           1    /*     Enable (1) or Disable(0) the statistics task             */
+#define OS_TASK_STAT_STK_CHK_EN   1    /*     Check task stacks from statistic task                    */
+#define OS_TASK_SUSPEND_EN        1    /*     Include code for OSTaskSuspend() and OSTaskResume()      */
+#define OS_TASK_SW_HOOK_EN        1    /*     Include code for OSTaskSwHook()                          */
+#define OS_TASK_REG_TBL_SIZE      1    /*     Size of task variables array (#of INT32U entries)        */
+
+
+                                       /* ----------------------- EVENT FLAGS ------------------------ */
+#define OS_FLAG_EN                1    /* Enable (1) or Disable (0) code generation for EVENT FLAGS    */
+#define OS_FLAG_ACCEPT_EN         1    /*     Include code for OSFlagAccept()                          */
+#define OS_FLAG_DEL_EN            1    /*     Include code for OSFlagDel()                             */
+#define OS_FLAG_NAME_EN           1    /*     Enable names for event flag group                        */
+#define OS_FLAG_QUERY_EN          1    /*     Include code for OSFlagQuery()                           */
+#define OS_FLAG_WAIT_CLR_EN       1    /* Include code for Wait on Clear EVENT FLAGS                   */
+#define OS_FLAGS_NBITS           16    /* Size in #bits of OS_FLAGS data type (8, 16 or 32)            */
+
+
+                                       /* -------------------- MESSAGE MAILBOXES --------------------- */
+#define OS_MBOX_EN                1    /* Enable (1) or Disable (0) code generation for MAILBOXES      */
+#define OS_MBOX_ACCEPT_EN         1    /*     Include code for OSMboxAccept()                          */
+#define OS_MBOX_DEL_EN            1    /*     Include code for OSMboxDel()                             */
+#define OS_MBOX_PEND_ABORT_EN     1    /*     Include code for OSMboxPendAbort()                       */
+#define OS_MBOX_POST_EN           1    /*     Include code for OSMboxPost()                            */
+#define OS_MBOX_POST_OPT_EN       1    /*     Include code for OSMboxPostOpt()                         */
+#define OS_MBOX_QUERY_EN          1    /*     Include code for OSMboxQuery()                           */
+
+
+                                       /* --------------------- MEMORY MANAGEMENT -------------------- */
+#define OS_MEM_EN                 1    /* Enable (1) or Disable (0) code generation for MEMORY MANAGER */
+#define OS_MEM_NAME_EN            1    /*     Enable memory partition names                            */
+#define OS_MEM_QUERY_EN           1    /*     Include code for OSMemQuery()                            */
+
+
+                                       /* ---------------- MUTUAL EXCLUSION SEMAPHORES --------------- */
+#define OS_MUTEX_EN               1    /* Enable (1) or Disable (0) code generation for MUTEX          */
+#define OS_MUTEX_ACCEPT_EN        1    /*     Include code for OSMutexAccept()                         */
+#define OS_MUTEX_DEL_EN           1    /*     Include code for OSMutexDel()                            */
+#define OS_MUTEX_QUERY_EN         1    /*     Include code for OSMutexQuery()                          */
+
+
+                                       /* ---------------------- MESSAGE QUEUES ---------------------- */
+#define OS_Q_EN                   1    /* Enable (1) or Disable (0) code generation for QUEUES         */
+#define OS_Q_ACCEPT_EN            1    /*     Include code for OSQAccept()                             */
+#define OS_Q_DEL_EN               1    /*     Include code for OSQDel()                                */
+#define OS_Q_FLUSH_EN             1    /*     Include code for OSQFlush()                              */
+#define OS_Q_PEND_ABORT_EN        1    /*     Include code for OSQPendAbort()                          */
+#define OS_Q_POST_EN              1    /*     Include code for OSQPost()                               */
+#define OS_Q_POST_FRONT_EN        1    /*     Include code for OSQPostFront()                          */
+#define OS_Q_POST_OPT_EN          1    /*     Include code for OSQPostOpt()                            */
+#define OS_Q_QUERY_EN             1    /*     Include code for OSQQuery()                              */
+
+
+                                       /* ------------------------ SEMAPHORES ------------------------ */
+#define OS_SEM_EN                 1    /* Enable (1) or Disable (0) code generation for SEMAPHORES     */
+#define OS_SEM_ACCEPT_EN          1    /*    Include code for OSSemAccept()                            */
+#define OS_SEM_DEL_EN             1    /*    Include code for OSSemDel()                               */
+#define OS_SEM_PEND_ABORT_EN      1    /*    Include code for OSSemPendAbort()                         */
+#define OS_SEM_QUERY_EN           1    /*    Include code for OSSemQuery()                             */
+#define OS_SEM_SET_EN             1    /*    Include code for OSSemSet()                               */
+
+
+                                       /* --------------------- TIME MANAGEMENT ---------------------- */
+#define OS_TIME_DLY_HMSM_EN       1    /*     Include code for OSTimeDlyHMSM()                         */
+#define OS_TIME_DLY_RESUME_EN     1    /*     Include code for OSTimeDlyResume()                       */
+#define OS_TIME_GET_SET_EN        1    /*     Include code for OSTimeGet() and OSTimeSet()             */
+#define OS_TIME_TICK_HOOK_EN      1    /*     Include code for OSTimeTickHook()                        */
+
+
+                                       /* --------------------- TIMER MANAGEMENT --------------------- */
+#define OS_TMR_EN                 0    /* Enable (1) or Disable (0) code generation for TIMERS         */
+#define OS_TMR_CFG_MAX           16    /*     Maximum number of timers                                 */
+#define OS_TMR_CFG_NAME_EN        1    /*     Determine timer names                                    */
+#define OS_TMR_CFG_WHEEL_SIZE     8    /*     Size of timer wheel (#Spokes)                            */
+#define OS_TMR_CFG_TICKS_PER_SEC 10    /*     Rate at which timer management task runs (Hz)            */
+
+#endif

+ 91 - 7
User/main.c

@@ -7,10 +7,18 @@
 *********************************************************************************************************
 */
 
-#include "stm32f4xx.h"
+#include "main.h"
 
-#include "led.h"
+#define INIT_STK_SIZE 64
+#define LED0_STK_SIZE 64
+#define LED1_STK_SIZE 64
 
+CPU_STK init_task_stk[INIT_STK_SIZE];
+CPU_STK LED0_TASK_STK[LED0_STK_SIZE];
+CPU_STK LED1_TASK_STK[LED1_STK_SIZE];
+#define INIT_TASK_PRIO 10
+#define LED0_RX_PRIO 7
+#define LED1_RX_PRIO 6
 void Delay(uint32_t count)
 {
     for (; count != 0; count--)
@@ -30,8 +38,8 @@ int main(void)
     *(unsigned int *)(0x40022000 + 0x14) |= (1 << 10);
     /* PI10 输出低电平 */
     *(unsigned int *)(0x40022000 + 0x14) &= ~(1 << 10);
-#elif 1
-    LED_Init();
+#elif 0
+    bsp_init();
     while (1)
     {
         GPIO_ResetBits(GPIOI, GPIO_Pin_10);
@@ -54,9 +62,85 @@ int main(void)
         // GPIO_SetBits(GPIOC, GPIO_Pin_2);
         // Delay(0xFFFFFF);
     };
+#elif 1
+    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
+
+    OSInit();
+    bsp_init();
+
+    /* init task */
+    /* 创建一个启动任务(也就是主任务)。启动任务会创建所有的应用程序任务 */
+    OSTaskCreateExt(init_task,                                   /* 启动任务函数指针 */
+                    (void *)0,                                   /* 传递给任务的参数 */
+                    (OS_STK *)&init_task_stk[INIT_STK_SIZE - 1], /* 指向任务栈栈顶的指针 */
+                    INIT_TASK_PRIO,                              /* 任务的优先级,必须唯一,数字越低优先级越高 */
+                    INIT_TASK_PRIO,                              /* 任务ID,一般和任务优先级相同 */
+                    (OS_STK *)&init_task_stk[0],                 /* 指向任务栈栈底的指针。OS_STK_GROWTH 决定堆栈增长方向 */
+                    INIT_STK_SIZE,                               /* 任务栈大小 */
+                    (void *)0,                                   /* 一块用户内存区的指针,用于任务控制块TCB的扩展功能
+                                                        (如任务切换时保存CPU浮点寄存器的数据)。一般不用,填0即可 */
+                    OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* 任务选项字 */
+
+    OSStart();
+
 #endif
 }
 
-// void SystemInit(void)
-// {
-// }
+/*!
+    \brief      init task
+    \param[in]  pvParameters not used
+    \param[out] none
+    \retval     none
+*/
+void init_task(void *pvParameters)
+{
+    SysTick_Config(SystemCoreClock / OS_TICKS_PER_SEC);
+    /* configure the systick handler priority */
+    NVIC_SetPriority(SysTick_IRQn, 0x00U);
+
+    OSTaskCreateExt(led0_task,                                   /* 启动任务函数指针 */
+                    (void *)0,                                   /* 传递给任务的参数 */
+                    (OS_STK *)&LED0_TASK_STK[LED0_STK_SIZE - 1], /* 指向任务栈栈顶的指针 */
+                    LED0_RX_PRIO,                                /* 任务的优先级,必须唯一,数字越低优先级越高 */
+                    LED0_RX_PRIO,                                /* 任务ID,一般和任务优先级相同 */
+                    (OS_STK *)&LED0_TASK_STK[0],                 /* 指向任务栈栈底的指针。OS_STK_GROWTH 决定堆栈增长方向 */
+                    LED0_STK_SIZE,                               /* 任务栈大小 */
+                    (void *)0,                                   /* 一块用户内存区的指针,用于任务控制块TCB的扩展功能
+                                                        (如任务切换时保存CPU浮点寄存器的数据)。一般不用,填0即可 */
+                    OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* 任务选项字 */
+
+    OSTaskCreateExt(led1_task,                                   /* 启动任务函数指针 */
+                    (void *)0,                                   /* 传递给任务的参数 */
+                    (OS_STK *)&LED1_TASK_STK[LED1_STK_SIZE - 1], /* 指向任务栈栈顶的指针 */
+                    LED1_RX_PRIO,                                /* 任务的优先级,必须唯一,数字越低优先级越高 */
+                    LED1_RX_PRIO,                                /* 任务ID,一般和任务优先级相同 */
+                    (OS_STK *)&LED1_TASK_STK[0],                 /* 指向任务栈栈底的指针。OS_STK_GROWTH 决定堆栈增长方向 */
+                    LED1_STK_SIZE,                               /* 任务栈大小 */
+                    (void *)0,                                   /* 一块用户内存区的指针,用于任务控制块TCB的扩展功能
+                                                        (如任务切换时保存CPU浮点寄存器的数据)。一般不用,填0即可 */
+                    OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* 任务选项字 */
+}
+
+void led0_task(void *pdata)
+{
+    pdata = pdata;
+    while (1)
+    {
+        GPIO_SetBits(GPIOI, GPIO_Pin_10);
+        OSTimeDly(100);
+        GPIO_ResetBits(GPIOI, GPIO_Pin_10);
+        OSTimeDly(400);
+    }
+}
+
+void led1_task(void *pdata)
+{
+    pdata = pdata;
+    while (1)
+    {
+        GPIO_SetBits(GPIOC, GPIO_Pin_2);
+        OSTimeDly(500);
+        GPIO_ResetBits(GPIOC, GPIO_Pin_2);
+        OSTimeDly(200);
+    }
+}

+ 11 - 0
User/main.h

@@ -0,0 +1,11 @@
+#ifndef __MAIN_H
+#define __MAIN_H
+
+#include "stm32f4xx.h"
+#include "includes.h"
+
+void bsp_init(void);
+void init_task(void *pvParameters);
+void led0_task(void *pdata);
+void led1_task(void *pdata);
+#endif

+ 7 - 7
User/stm32f4xx_it.c

@@ -129,19 +129,19 @@ void DebugMon_Handler(void)
  * @param  None
  * @retval None
  */
-void PendSV_Handler(void)
-{
-}
+// void PendSV_Handler(void)
+// {
+// }
 
 /**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
-void SysTick_Handler(void)
-{
-    // TimingDelay_Decrement();
-}
+// void SysTick_Handler(void)
+// {
+//     // TimingDelay_Decrement();
+// }
 
 /******************************************************************************/
 /*                 STM32F4xx Peripherals Interrupt Handlers                   */

+ 42 - 41
User/stm32f4xx_it.h

@@ -1,55 +1,56 @@
 /**
-  ******************************************************************************
-  * @file    Project/STM32F4xx_StdPeriph_Templates/stm32f4xx_it.h 
-  * @author  MCD Application Team
-  * @version V1.5.0
-  * @date    06-March-2015
-  * @brief   This file contains the headers of the interrupt handlers.
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
-  *
-  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
-  * You may not use this file except in compliance with the License.
-  * You may obtain a copy of the License at:
-  *
-  *        http://www.st.com/software_license_agreement_liberty_v2
-  *
-  * Unless required by applicable law or agreed to in writing, software 
-  * distributed under the License is distributed on an "AS IS" BASIS, 
-  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  * See the License for the specific language governing permissions and
-  * limitations under the License.
-  *
-  ******************************************************************************
-  */
+ ******************************************************************************
+ * @file    Project/STM32F4xx_StdPeriph_Templates/stm32f4xx_it.h
+ * @author  MCD Application Team
+ * @version V1.5.0
+ * @date    06-March-2015
+ * @brief   This file contains the headers of the interrupt handlers.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *        http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
 
 /* Define to prevent recursive inclusion -------------------------------------*/
 #ifndef __STM32F4xx_IT_H
 #define __STM32F4xx_IT_H
 
 #ifdef __cplusplus
- extern "C" {
-#endif 
+extern "C"
+{
+#endif
 
 /* Includes ------------------------------------------------------------------*/
 #include "stm32f4xx.h"
 
-/* Exported types ------------------------------------------------------------*/
-/* Exported constants --------------------------------------------------------*/
-/* Exported macro ------------------------------------------------------------*/
-/* Exported functions ------------------------------------------------------- */
-
-void NMI_Handler(void);
-void HardFault_Handler(void);
-void MemManage_Handler(void);
-void BusFault_Handler(void);
-void UsageFault_Handler(void);
-void SVC_Handler(void);
-void DebugMon_Handler(void);
-void PendSV_Handler(void);
-void SysTick_Handler(void);
+  /* Exported types ------------------------------------------------------------*/
+  /* Exported constants --------------------------------------------------------*/
+  /* Exported macro ------------------------------------------------------------*/
+  /* Exported functions ------------------------------------------------------- */
+
+  void NMI_Handler(void);
+  void HardFault_Handler(void);
+  void MemManage_Handler(void);
+  void BusFault_Handler(void);
+  void UsageFault_Handler(void);
+  void SVC_Handler(void);
+  void DebugMon_Handler(void);
+  void PendSV_Handler(void);
+  void SysTick_Handler(void);
 
 #ifdef __cplusplus
 }

Datei-Diff unterdrückt, da er zu groß ist
+ 477 - 477
User/system_stm32f4xx.c


+ 23 - 2
platformio.ini

@@ -14,10 +14,17 @@ monitor_speed = 115200
 
 build_flags = 
   -IUser
-  -IUser/BSP/LED
+  -IUser/bsp/led
+  -IUser/UCOS-CONFIG
   -ILibraries/CMSIS/Include
   -ILibraries/CMSIS/Device/ST/STM32F4xx/Include
   -ILibraries/STM32F4xx_StdPeriph_Driver/inc
+  -IMiddleWare/uCOS_II/uC-CPU
+  -IMiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/GNU
+  -IMiddleWare/uCOS_II/uC-LIB
+  -IMiddleWare/uCOS_II/uCOS-BSP
+  -IMiddleWare/uCOS_II/uCOS-II/Source
+  -IMiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/GNU
   ; 定义全局宏
   -D STM32F40_41xxx
   -D USE_STDPERIPH_DRIVER
@@ -26,11 +33,25 @@ build_unflags =
   -DSTM32F407xx
   -DSTM32F4
 
-src_filter = +<User/> +<Project/GCC/> +<Libraries/STM32F4xx_StdPeriph_Driver/src/> +<MiddleWare/> 
+src_filter = +<User/> +<Project/GCC/> +<Libraries/STM32F4xx_StdPeriph_Driver/src/>
             -<Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_qspi.c>
             -<Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_fmpi2c.c>
             -<Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_fmc.c>
             -<Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_cec.c>
             -<Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_spdifrx.c>
+            +<MiddleWare/uCOS_II>
+            -<MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M0>
+            -<MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M3>
+            -<MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/RealView>
+            -<MiddleWare/uCOS_II/uC-CPU/ARM-Cortex-M4/IAR>
+            -<MiddleWare/uCOS_II/uC-LIB/Ports/ARM-Cortex-M0>
+            -<MiddleWare/uCOS_II/uC-LIB/Ports/ARM-Cortex-M3>
+            -<MiddleWare/uCOS_II/uC-LIB/Ports/ARM-Cortex-M4/IAR>
+            -<MiddleWare/uCOS_II/uC-LIB/Ports/ARM-Cortex-M4/RealView>
+            -<MiddleWare/uCOS_II/uC-LIB/Ports/ARM-Cortex-M4/RealView>
+            -<MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M0>
+            -<MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M3>
+            -<MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/IAR>
+            -<MiddleWare/uCOS_II/uCOS-II/Ports/ARM-Cortex-M4/Generic/RealView>
 debug_tool = stlink
 upload_protocol = stlink

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.