diff --git a/Core/Src/main.c b/Core/Src/main.c
index da059fb..b02d3bd 100644
--- a/Core/Src/main.c
+++ b/Core/Src/main.c
@@ -22,7 +22,7 @@
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
-
+#include "ucos_ii.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@@ -46,13 +46,12 @@ DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;
/* USER CODE BEGIN PV */
-
static const uint8_t uart1_test_message[] = "USART1 DMA TX TEST\r\n";
static volatile uint32_t uart1_tx_ok_count;
static volatile uint32_t uart1_tx_busy_count;
static volatile uint32_t uart1_tx_error_count;
static volatile uint32_t uart1_tx_complete_count;
-
+static OS_STK AppTaskStartStk[APP_TASK_START_STK_SIZE];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
@@ -61,12 +60,45 @@ static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
+static void AppTaskStart(void *p_arg);
+
+
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
+static void AppTaskStart(void *p_arg)
+{
+ HAL_StatusTypeDef uart_status;
+
+ (void)p_arg;
+
+ while (1)
+ {
+ uart_status = HAL_UART_Transmit_DMA(&huart1,
+ (uint8_t *)uart1_test_message,
+ sizeof(uart1_test_message) - 1U);
+
+ if (uart_status == HAL_OK)
+ {
+ uart1_tx_ok_count++;
+ }
+ else if (uart_status == HAL_BUSY)
+ {
+ uart1_tx_busy_count++;
+ }
+ else
+ {
+ uart1_tx_error_count++;
+ }
+
+ OSTimeDly(OS_TICKS_PER_SEC);
+ }
+}
+
+
/* USER CODE END 0 */
/**
@@ -102,7 +134,24 @@ int main(void)
MX_USB_DEVICE_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
-
+ INT8U os_err;
+ OSInit();
+ os_err = OSTaskCreateExt(AppTaskStart,
+ 0,
+ &AppTaskStartStk[APP_TASK_START_STK_SIZE - 1u],
+ APP_TASK_START_PRIO,
+ APP_TASK_START_PRIO,
+ &AppTaskStartStk[0],
+ APP_TASK_START_STK_SIZE,
+ 0,
+ (OS_TASK_OPT_STK_CHK |
+ OS_TASK_OPT_STK_CLR));
+
+ if (os_err != OS_ERR_NONE)
+ {
+ Error_Handler();
+ }
+ OSStart();
/* USER CODE END 2 */
/* Infinite loop */
@@ -112,26 +161,7 @@ int main(void)
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
- HAL_StatusTypeDef uart_status;
-
- uart_status = HAL_UART_Transmit_DMA(&huart1,
- (uint8_t *)uart1_test_message,
- sizeof(uart1_test_message) - 1U);
-
- if (uart_status == HAL_OK)
- {
- uart1_tx_ok_count++;
- }
- else if (uart_status == HAL_BUSY)
- {
- uart1_tx_busy_count++;
- }
- else
- {
- uart1_tx_error_count++;
- }
- HAL_Delay(1000U);
}
/* USER CODE END 3 */
}
diff --git a/Core/Src/stm32f4xx_it.c b/Core/Src/stm32f4xx_it.c
index 47664e9..bd7fbca 100644
--- a/Core/Src/stm32f4xx_it.c
+++ b/Core/Src/stm32f4xx_it.c
@@ -22,6 +22,7 @@
#include "stm32f4xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
+#include "ucos_ii.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@@ -191,7 +192,10 @@ void SysTick_Handler(void)
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
-
+ if (OSRunning == OS_TRUE)
+ {
+ OS_CPU_SysTickHandler();
+ }
/* USER CODE END SysTick_IRQn 1 */
}
diff --git a/EWARM/Modbus.ewp b/EWARM/Modbus.ewp
index 419f78d..55c8775 100644
--- a/EWARM/Modbus.ewp
+++ b/EWARM/Modbus.ewp
@@ -1,1181 +1,1261 @@
- 3
-
- Modbus
-
- ARM
-
- 1
-
- General
- 3
-
- 31
- 1
+ 3
+
+ Modbus
+
+ ARM
+ 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ICCARM
- 2
-
- 35
- 1
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- AARM
- 2
-
- 10
- 1
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OBJCOPY
- 0
-
- 1
- 1
- 1
-
-
-
-
-
-
-
-
- CUSTOM
- 3
-
-
-
- 0
-
-
-
- BICOMP
- 0
-
-
-
- BUILDACTION
- 1
-
-
-
-
-
-
- ILINK
- 0
-
- 22
- 1
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- IARCHIVE
- 0
-
- 0
- 1
- 1
-
-
-
-
-
-
- BILINK
- 0
-
-
-
- Coder
- 0
-
-
-
-
- Application
+
+ General
+ 3
+
+ 31
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ICCARM
+ 2
+
+ 35
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AARM
+ 2
+
+ 10
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ OBJCOPY
+ 0
+
+ 1
+ 1
+ 1
+
+
+
+
+
+
+
+
+ CUSTOM
+ 3
+
+
+
+ 0
+
+
+
+ BICOMP
+ 0
+
+
+
+ BUILDACTION
+ 1
+
+
+
+
+
+
+ ILINK
+ 0
+
+ 23
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IARCHIVE
+ 0
+
+ 0
+ 1
+ 1
+
+
+
+
+
+
+ BILINK
+ 0
+
+
+
+ Coder
+ 0
+
+
+
- EWARM
-
- $PROJ_DIR$/startup_stm32f407xx.s
-
-
-
- User
-
- Core
-
- $PROJ_DIR$/../Core/Src/main.c
-
-
- $PROJ_DIR$/../Core/Src/stm32f4xx_it.c
-
-
- $PROJ_DIR$/../Core/Src/stm32f4xx_hal_msp.c
-
-
-
- USB_DEVICE
+ Application
- App
-
- $PROJ_DIR$/../USB_DEVICE/App/usb_device.c
-
-
- $PROJ_DIR$/../USB_DEVICE/App/usbd_desc.c
-
-
- $PROJ_DIR$/../USB_DEVICE/App/usbd_cdc_if.c
-
+ EWARM
+
+ $PROJ_DIR$\startup_stm32f407xx.s
+
- Target
-
- $PROJ_DIR$/../USB_DEVICE/Target/usbd_conf.c
-
+ User
+
+ Core
+
+ $PROJ_DIR$\..\Core\Src\main.c
+
+
+ $PROJ_DIR$\..\Core\Src\stm32f4xx_hal_msp.c
+
+
+ $PROJ_DIR$\..\Core\Src\stm32f4xx_it.c
+
+
+
+ USB_DEVICE
+
+ App
+
+ $PROJ_DIR$\..\USB_DEVICE\App\usb_device.c
+
+
+ $PROJ_DIR$\..\USB_DEVICE\App\usbd_cdc_if.c
+
+
+ $PROJ_DIR$\..\USB_DEVICE\App\usbd_desc.c
+
+
+
+ Target
+
+ $PROJ_DIR$\..\USB_DEVICE\Target\usbd_conf.c
+
+
+
-
-
-
- Drivers
- STM32F4xx_HAL_Driver
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c
-
-
- $PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c
-
+ Drivers
+
+ CMSIS
+
+ $PROJ_DIR$\..\Core\Src\system_stm32f4xx.c
+
+
+
+ STM32F4xx_HAL_Driver
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_exti.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd_ex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_usb.c
+
+
- CMSIS
-
- $PROJ_DIR$/../Core/Src/system_stm32f4xx.c
-
+ Micrium
+
+ Micrium Config
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\Config\app_cfg.h
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\Config\cpu_cfg.h
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\Config\os_cfg.h
+
+
+
+ uCOS-II Port
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Ports\ARM-Cortex-M4\IAR\os_cpu_a.asm
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Ports\ARM-Cortex-M4\IAR\os_cpu_c.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Ports\ARM-Cortex-M4\IAR\os_dbg.c
+
+
+
+ uCOS-II Source
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_core.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_flag.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_mbox.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_mem.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_mutex.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_q.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_sem.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_task.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_time.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_tmr.c
+
+
-
-
- Middlewares
- USB_Device_Library
-
- $PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c
-
-
- $PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c
-
-
- $PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c
-
-
- $PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c
-
+ Middlewares
+
+ USB_Device_Library
+
+ $PROJ_DIR$\..\Middlewares\ST\STM32_USB_Device_Library\Class\CDC\Src\usbd_cdc.c
+
+
+ $PROJ_DIR$\..\Middlewares\ST\STM32_USB_Device_Library\Core\Src\usbd_core.c
+
+
+ $PROJ_DIR$\..\Middlewares\ST\STM32_USB_Device_Library\Core\Src\usbd_ctlreq.c
+
+
+ $PROJ_DIR$\..\Middlewares\ST\STM32_USB_Device_Library\Core\Src\usbd_ioreq.c
+
+
-
-
diff --git a/EWARM/Modbus.ewt b/EWARM/Modbus.ewt
new file mode 100644
index 0000000..be6db69
--- /dev/null
+++ b/EWARM/Modbus.ewt
@@ -0,0 +1,1375 @@
+
+
+ 3
+
+ Modbus
+
+ ARM
+
+ 1
+
+ C-STAT
+ 262
+
+ 262
+
+ 0
+
+ 1
+ 600
+ 1
+ 10
+ 0
+ 1
+ 100
+
+
+ 1.6.2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ RuntimeChecking
+ 0
+
+ 2
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Application
+
+ EWARM
+
+ $PROJ_DIR$\startup_stm32f407xx.s
+
+
+
+ User
+
+ Core
+
+ $PROJ_DIR$\..\Core\Src\main.c
+
+
+ $PROJ_DIR$\..\Core\Src\stm32f4xx_hal_msp.c
+
+
+ $PROJ_DIR$\..\Core\Src\stm32f4xx_it.c
+
+
+
+ USB_DEVICE
+
+ App
+
+ $PROJ_DIR$\..\USB_DEVICE\App\usb_device.c
+
+
+ $PROJ_DIR$\..\USB_DEVICE\App\usbd_cdc_if.c
+
+
+ $PROJ_DIR$\..\USB_DEVICE\App\usbd_desc.c
+
+
+
+ Target
+
+ $PROJ_DIR$\..\USB_DEVICE\Target\usbd_conf.c
+
+
+
+
+
+
+ Drivers
+
+ CMSIS
+
+ $PROJ_DIR$\..\Core\Src\system_stm32f4xx.c
+
+
+
+ STM32F4xx_HAL_Driver
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_exti.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd_ex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c
+
+
+ $PROJ_DIR$\..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_usb.c
+
+
+
+
+ Micrium
+
+ Micrium Config
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\Config\app_cfg.h
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\Config\cpu_cfg.h
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\Config\os_cfg.h
+
+
+
+ uCOS-II Port
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Ports\ARM-Cortex-M4\IAR\os_cpu_a.asm
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Ports\ARM-Cortex-M4\IAR\os_cpu_c.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Ports\ARM-Cortex-M4\IAR\os_dbg.c
+
+
+
+ uCOS-II Source
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_core.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_flag.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_mbox.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_mem.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_mutex.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_q.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_sem.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_task.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_time.c
+
+
+ $PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source\os_tmr.c
+
+
+
+
+ Middlewares
+
+ USB_Device_Library
+
+ $PROJ_DIR$\..\Middlewares\ST\STM32_USB_Device_Library\Class\CDC\Src\usbd_cdc.c
+
+
+ $PROJ_DIR$\..\Middlewares\ST\STM32_USB_Device_Library\Core\Src\usbd_core.c
+
+
+ $PROJ_DIR$\..\Middlewares\ST\STM32_USB_Device_Library\Core\Src\usbd_ctlreq.c
+
+
+ $PROJ_DIR$\..\Middlewares\ST\STM32_USB_Device_Library\Core\Src\usbd_ioreq.c
+
+
+
+
diff --git a/EWARM/startup_stm32f407xx.s b/EWARM/startup_stm32f407xx.s
index 9b0da01..21f1af4 100644
--- a/EWARM/startup_stm32f407xx.s
+++ b/EWARM/startup_stm32f407xx.s
@@ -48,6 +48,7 @@
EXTERN __iar_program_start
EXTERN SystemInit
+ EXTERN OS_CPU_PendSVHandler
PUBLIC __vector_table
DATA
@@ -67,7 +68,7 @@ __vector_table
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
- DCD PendSV_Handler ; PendSV Handler
+ DCD OS_CPU_PendSVHandler ; uC/OS-II context switch
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
diff --git a/Middlewares/Third_Party/Micrium/Config/app_cfg.h b/Middlewares/Third_Party/Micrium/Config/app_cfg.h
new file mode 100644
index 0000000..80634a2
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/Config/app_cfg.h
@@ -0,0 +1,10 @@
+#ifndef APP_CFG_H
+#define APP_CFG_H
+
+#define APP_TASK_START_PRIO 5u
+#define APP_TASK_TEST_PRIO 6u
+
+#define APP_TASK_START_STK_SIZE 256u
+#define APP_TASK_TEST_STK_SIZE 256u
+
+#endif
\ No newline at end of file
diff --git a/Middlewares/Third_Party/Micrium/Config/cpu_cfg.h b/Middlewares/Third_Party/Micrium/Config/cpu_cfg.h
new file mode 100644
index 0000000..90c45ff
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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. */
+
diff --git a/Middlewares/Third_Party/Micrium/Config/os_cfg.h b/Middlewares/Third_Party/Micrium/Config/os_cfg.h
new file mode 100644
index 0000000..4e2235d
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/Config/os_cfg.h
@@ -0,0 +1,145 @@
+/*
+*********************************************************************************************************
+* uC/OS-II
+* The Real-Time Kernel
+* uC/OS-II Configuration File for V2.9x
+*
+* (c) Copyright 2005-2014, Micrium, Weston, FL
+* All Rights Reserved
+*
+*
+* File : OS_CFG.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_CFG_H
+#define OS_CFG_H
+
+
+ /* ---------------------- MISCELLANEOUS ----------------------- */
+#define OS_APP_HOOKS_EN 0u /* Application-defined hooks are called from the uC/OS-II hooks */
+#define OS_ARG_CHK_EN 0u /* Enable (1) or Disable (0) argument checking */
+#define OS_CPU_HOOKS_EN 1u /* uC/OS-II hooks are found in the processor port files */
+
+#define OS_DEBUG_EN 1u /* Enable(1) debug variables */
+
+#define OS_EVENT_MULTI_EN 1u /* Include code for OSEventPendMulti() */
+#define OS_EVENT_NAME_EN 1u /* Enable names for Sem, Mutex, Mbox and Q */
+
+#define OS_LOWEST_PRIO 63u /* Defines the lowest priority that can be assigned ... */
+ /* ... MUST NEVER be higher than 254! */
+
+#define OS_MAX_EVENTS 20u /* Max. number of event control blocks in your application */
+#define OS_MAX_FLAGS 5u /* Max. number of Event Flag Groups in your application */
+#define OS_MAX_MEM_PART 5u /* Max. number of memory partitions */
+#define OS_MAX_QS 4u /* Max. number of queue control blocks in your application */
+#define OS_MAX_TASKS 10u /* Max. number of tasks in your application, MUST be >= 2 */
+
+#define OS_SCHED_LOCK_EN 1u /* Include code for OSSchedLock() and OSSchedUnlock() */
+
+#define OS_TICK_STEP_EN 1u /* Enable tick stepping feature for uC/OS-View */
+#define OS_TICKS_PER_SEC 1000u /* Set the number of ticks in one second */
+
+#define OS_TLS_TBL_SIZE 0u /* Size of Thread-Local Storage Table */
+
+
+ /* --------------------- TASK STACK SIZE ---------------------- */
+#define OS_TASK_TMR_STK_SIZE 128u /* Timer task stack size (# of OS_STK wide entries) */
+#define OS_TASK_STAT_STK_SIZE 128u /* Statistics task stack size (# of OS_STK wide entries) */
+#define OS_TASK_IDLE_STK_SIZE 128u /* Idle task stack size (# of OS_STK wide entries) */
+
+
+ /* --------------------- TASK MANAGEMENT ---------------------- */
+#define OS_TASK_CHANGE_PRIO_EN 1u /* Include code for OSTaskChangePrio() */
+#define OS_TASK_CREATE_EN 1u /* Include code for OSTaskCreate() */
+#define OS_TASK_CREATE_EXT_EN 1u /* Include code for OSTaskCreateExt() */
+#define OS_TASK_DEL_EN 1u /* Include code for OSTaskDel() */
+#define OS_TASK_NAME_EN 1u /* Enable task names */
+#define OS_TASK_PROFILE_EN 1u /* Include variables in OS_TCB for profiling */
+#define OS_TASK_QUERY_EN 1u /* Include code for OSTaskQuery() */
+#define OS_TASK_REG_TBL_SIZE 1u /* Size of task variables array (#of INT32U entries) */
+#define OS_TASK_STAT_EN 0u /* Enable (1) or Disable(0) the statistics task */
+#define OS_TASK_STAT_STK_CHK_EN 0u /* Check task stacks from statistic task */
+#define OS_TASK_SUSPEND_EN 1u /* Include code for OSTaskSuspend() and OSTaskResume() */
+#define OS_TASK_SW_HOOK_EN 1u /* Include code for OSTaskSwHook() */
+
+
+ /* ----------------------- EVENT FLAGS ------------------------ */
+#define OS_FLAG_EN 1u /* Enable (1) or Disable (0) code generation for EVENT FLAGS */
+#define OS_FLAG_ACCEPT_EN 1u /* Include code for OSFlagAccept() */
+#define OS_FLAG_DEL_EN 1u /* Include code for OSFlagDel() */
+#define OS_FLAG_NAME_EN 1u /* Enable names for event flag group */
+#define OS_FLAG_QUERY_EN 1u /* Include code for OSFlagQuery() */
+#define OS_FLAG_WAIT_CLR_EN 1u /* Include code for Wait on Clear EVENT FLAGS */
+#define OS_FLAGS_NBITS 16u /* Size in #bits of OS_FLAGS data type (8, 16 or 32) */
+
+
+ /* -------------------- MESSAGE MAILBOXES --------------------- */
+#define OS_MBOX_EN 1u /* Enable (1) or Disable (0) code generation for MAILBOXES */
+#define OS_MBOX_ACCEPT_EN 1u /* Include code for OSMboxAccept() */
+#define OS_MBOX_DEL_EN 1u /* Include code for OSMboxDel() */
+#define OS_MBOX_PEND_ABORT_EN 1u /* Include code for OSMboxPendAbort() */
+#define OS_MBOX_POST_EN 1u /* Include code for OSMboxPost() */
+#define OS_MBOX_POST_OPT_EN 1u /* Include code for OSMboxPostOpt() */
+#define OS_MBOX_QUERY_EN 1u /* Include code for OSMboxQuery() */
+
+
+ /* --------------------- MEMORY MANAGEMENT -------------------- */
+#define OS_MEM_EN 0u /* Enable (1) or Disable (0) code generation for MEMORY MANAGER */
+#define OS_MEM_NAME_EN 1u /* Enable memory partition names */
+#define OS_MEM_QUERY_EN 1u /* Include code for OSMemQuery() */
+
+
+ /* ---------------- MUTUAL EXCLUSION SEMAPHORES --------------- */
+#define OS_MUTEX_EN 1u /* Enable (1) or Disable (0) code generation for MUTEX */
+#define OS_MUTEX_ACCEPT_EN 1u /* Include code for OSMutexAccept() */
+#define OS_MUTEX_DEL_EN 1u /* Include code for OSMutexDel() */
+#define OS_MUTEX_QUERY_EN 1u /* Include code for OSMutexQuery() */
+
+
+ /* ---------------------- MESSAGE QUEUES ---------------------- */
+#define OS_Q_EN 1u /* Enable (1) or Disable (0) code generation for QUEUES */
+#define OS_Q_ACCEPT_EN 1u /* Include code for OSQAccept() */
+#define OS_Q_DEL_EN 1u /* Include code for OSQDel() */
+#define OS_Q_FLUSH_EN 1u /* Include code for OSQFlush() */
+#define OS_Q_PEND_ABORT_EN 1u /* Include code for OSQPendAbort() */
+#define OS_Q_POST_EN 1u /* Include code for OSQPost() */
+#define OS_Q_POST_FRONT_EN 1u /* Include code for OSQPostFront() */
+#define OS_Q_POST_OPT_EN 1u /* Include code for OSQPostOpt() */
+#define OS_Q_QUERY_EN 1u /* Include code for OSQQuery() */
+
+
+ /* ------------------------ SEMAPHORES ------------------------ */
+#define OS_SEM_EN 1u /* Enable (1) or Disable (0) code generation for SEMAPHORES */
+#define OS_SEM_ACCEPT_EN 1u /* Include code for OSSemAccept() */
+#define OS_SEM_DEL_EN 1u /* Include code for OSSemDel() */
+#define OS_SEM_PEND_ABORT_EN 1u /* Include code for OSSemPendAbort() */
+#define OS_SEM_QUERY_EN 1u /* Include code for OSSemQuery() */
+#define OS_SEM_SET_EN 1u /* Include code for OSSemSet() */
+
+
+ /* --------------------- TIME MANAGEMENT ---------------------- */
+#define OS_TIME_DLY_HMSM_EN 1u /* Include code for OSTimeDlyHMSM() */
+#define OS_TIME_DLY_RESUME_EN 1u /* Include code for OSTimeDlyResume() */
+#define OS_TIME_GET_SET_EN 1u /* Include code for OSTimeGet() and OSTimeSet() */
+#define OS_TIME_TICK_HOOK_EN 1u /* Include code for OSTimeTickHook() */
+
+
+ /* --------------------- TIMER MANAGEMENT --------------------- */
+#define OS_TMR_EN 0u /* Enable (1) or Disable (0) code generation for TIMERS */
+#define OS_TMR_CFG_MAX 16u /* Maximum number of timers */
+#define OS_TMR_CFG_NAME_EN 1u /* Determine timer names */
+#define OS_TMR_CFG_WHEEL_SIZE 7u /* Size of timer wheel (#Spokes) */
+#define OS_TMR_CFG_TICKS_PER_SEC 10u /* Rate at which timer management task runs (Hz) */
+
+#endif
diff --git a/Middlewares/Third_Party/Micrium/uC-CPU/ARM-Cortex-M4/IAR/cpu.h b/Middlewares/Third_Party/Micrium/uC-CPU/ARM-Cortex-M4/IAR/cpu.h
new file mode 100644
index 0000000..f84de5c
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\cpu_cfg.h
+*
+* (b) (1) \\cpu_def.h
+* (2) \\\\cpu*.*
+*
+* where
+* directory path for Your Product's Application
+* directory path for common CPU-compiler software
+* directory name for specific CPU
+* directory name for specific compiler
+*
+* (2) Compiler MUST be configured to include as additional include path directories :
+*
+* (a) '\\' directory See Note #1a
+*
+* (b) (1) '\\' directory See Note #1b1
+* (2) '\\\\' 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
+
+#include
+#include /* 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 :
+*
+* \\\\
+*
+* where
+* directory path for common CPU-compiler software
+* directory name for specific CPU
+* 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. */
+
diff --git a/Middlewares/Third_Party/Micrium/uC-CPU/ARM-Cortex-M4/IAR/cpu_a.asm b/Middlewares/Third_Party/Micrium/uC-CPU/ARM-Cortex-M4/IAR/cpu_a.asm
new file mode 100644
index 0000000..ad2e1e2
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+
diff --git a/Middlewares/Third_Party/Micrium/uC-CPU/ARM-Cortex-M4/IAR/cpu_c.c b/Middlewares/Third_Party/Micrium/uC-CPU/ARM-Cortex-M4/IAR/cpu_c.c
new file mode 100644
index 0000000..fc52ddd
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+#include
+
+#include
+
+#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
diff --git a/Middlewares/Third_Party/Micrium/uC-CPU/cpu_core.c b/Middlewares/Third_Party/Micrium/uC-CPU/cpu_core.c
new file mode 100644
index 0000000..7d6ee40
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+
diff --git a/Middlewares/Third_Party/Micrium/uC-CPU/cpu_core.h b/Middlewares/Third_Party/Micrium/uC-CPU/cpu_core.h
new file mode 100644
index 0000000..59a0551
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\cpu_cfg.h
+*
+* (b) (1) \\cpu_*.*
+* (2) \\\\cpu*.*
+*
+* where
+* directory path for Your Product's Application
+* directory path for common CPU-compiler software
+* directory name for specific processor (CPU)
+* 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) :
+*
+* \\lib_*.*
+*
+* where
+* directory path for custom library software
+*
+* (3) Compiler MUST be configured to include as additional include path directories :
+*
+* (a) '\\' directory See Note #1a
+*
+* (b) (1) '\\' directory See Note #1b1
+* (2) '\\\\' directory See Note #1b2
+*
+* (c) '\\' directory See Note #2a
+*********************************************************************************************************
+*/
+
+#include
+#include
+#include
+
+#if (CPU_CFG_NAME_EN == DEF_ENABLED)
+#include
+#include
+#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. */
+
diff --git a/Middlewares/Third_Party/Micrium/uC-CPU/cpu_def.h b/Middlewares/Third_Party/Micrium/uC-CPU/cpu_def.h
new file mode 100644
index 0000000..c22fa41
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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 :
+*
+* \\\\
+*
+* where
+* directory path for common CPU-compiler software
+* directory name for specific CPU
+* 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. */
+
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/Ports/ARM-Cortex-M4/GNU/lib_mem_a.s b/Middlewares/Third_Party/Micrium/uC-LIB/Ports/ARM-Cortex-M4/GNU/lib_mem_a.s
new file mode 100644
index 0000000..942bbca
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib*.*
+@
+@ (2) \\Ports\\\lib*_a.*
+@
+@ where
+@ directory path for custom library software
+@ directory name for specific processor (CPU)
+@ 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
+
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/Ports/ARM-Cortex-M4/IAR/lib_mem_a.asm b/Middlewares/Third_Party/Micrium/uC-LIB/Ports/ARM-Cortex-M4/IAR/lib_mem_a.asm
new file mode 100644
index 0000000..044d7d2
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib*.*
+;
+; (2) \\Ports\\\lib*_a.*
+;
+; where
+; directory path for custom library software
+; directory name for specific processor (CPU)
+; 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
+
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/Ports/ARM-Cortex-M4/RealView/lib_mem_a.asm b/Middlewares/Third_Party/Micrium/uC-LIB/Ports/ARM-Cortex-M4/RealView/lib_mem_a.asm
new file mode 100644
index 0000000..b9013fc
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib*.*
+;
+; (2) \\Ports\\\lib*_a.*
+;
+; where
+; directory path for custom library software
+; directory name for specific processor (CPU)
+; 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
+
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/lib_ascii.c b/Middlewares/Third_Party/Micrium/uC-LIB/lib_ascii.c
new file mode 100644
index 0000000..52839ea
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib_*.*
+*
+* (2) \\Ports\\\lib*_a.*
+*
+* where
+* directory path for custom library software
+* directory name for specific processor (CPU)
+* 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
+
+
+/*
+*********************************************************************************************************
+* 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);
+}
+
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/lib_ascii.h b/Middlewares/Third_Party/Micrium/uC-LIB/lib_ascii.h
new file mode 100644
index 0000000..c3d484f
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib_*.*
+*
+* (2) \\Ports\\\lib*_a.*
+*
+* where
+* directory path for custom library software
+* directory name for specific processor (CPU)
+* 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) \\lib_*.*
+*
+* where
+* directory path for custom library software
+*
+* (2) CPU-configuration software files are located in the following directories :
+*
+* (a) \\cpu_*.*
+* (b) \\\\cpu*.*
+*
+* where
+* directory path for common CPU-compiler software
+* directory name for specific processor (CPU)
+* directory name for specific compiler
+*
+* (3) Compiler MUST be configured to include as additional include path directories :
+*
+* (a) '\\' directory See Note #1a
+*
+* (b) (1) '\\' directory See Note #2a
+* (2) '\\\\' directory See Note #2b
+*
+* (4) NO compiler-supplied standard library functions SHOULD be used.
+*********************************************************************************************************
+*/
+
+#include
+#include
+
+
+/*
+*********************************************************************************************************
+* 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. */
+
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/lib_def.h b/Middlewares/Third_Party/Micrium/uC-LIB/lib_def.h
new file mode 100644
index 0000000..0ada21d
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib_*.*
+*
+* (2) \\Ports\\\lib*_a.*
+*
+* where
+* directory path for custom library software
+* directory name for specific processor (CPU)
+* 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) \\lib_*.*
+*
+* where
+* directory path for custom library software
+*
+* (2) CPU-configuration software files are located in the following directories :
+*
+* (a) \\cpu_*.*
+* (b) \\\\cpu*.*
+*
+* where
+* directory path for common CPU-compiler software
+* directory name for specific processor (CPU)
+* directory name for specific compiler
+*
+* (3) Compiler MUST be configured to include as additional include path directories :
+*
+* (a) '\\' directory See Note #1a
+*
+* (b) (1) '\\' directory See Note #2a
+* (2) '\\\\' directory See Note #2b
+*********************************************************************************************************
+*/
+
+#include
+#include
+
+
+/*
+*********************************************************************************************************
+* 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. */
+
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/lib_math.c b/Middlewares/Third_Party/Micrium/uC-LIB/lib_math.c
new file mode 100644
index 0000000..1c6ffc3
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib_*.*
+*
+* (2) \\Ports\\\lib*_a.*
+*
+* where
+* directory path for custom library software
+* directory name for specific processor (CPU)
+* 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
+
+
+/*
+*********************************************************************************************************
+* 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);
+}
+
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/lib_math.h b/Middlewares/Third_Party/Micrium/uC-LIB/lib_math.h
new file mode 100644
index 0000000..ef550a4
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib_*.*
+*
+* (2) \\Ports\\\lib*_a.*
+*
+* where
+* directory path for custom library software
+* directory name for specific processor (CPU)
+* 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) \\lib_*.*
+*
+* where
+* directory path for custom library software
+*
+* (2) CPU-configuration software files are located in the following directories :
+*
+* (a) \\cpu_*.*
+* (b) \\\\cpu*.*
+*
+* where
+* directory path for common CPU-compiler software
+* directory name for specific processor (CPU)
+* directory name for specific compiler
+*
+* (3) Compiler MUST be configured to include as additional include path directories :
+*
+* (a) '\\' directory See Note #1a
+*
+* (b) (1) '\\' directory See Note #2a
+* (2) '\\\\' directory See Note #2b
+*
+* (4) NO compiler-supplied standard library functions SHOULD be used.
+*********************************************************************************************************
+*/
+
+#include
+#include
+
+#include
+
+
+/*
+*********************************************************************************************************
+* 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. */
+
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/lib_mem.c b/Middlewares/Third_Party/Micrium/uC-LIB/lib_mem.c
new file mode 100644
index 0000000..0c403a7
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib_*.*
+*
+* (2) \\Ports\\\lib*_a.*
+*
+* where
+* directory path for custom library software
+* directory name for specific processor (CPU)
+* 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
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/lib_mem.h b/Middlewares/Third_Party/Micrium/uC-LIB/lib_mem.h
new file mode 100644
index 0000000..2e77a35
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib_*.*
+*
+* (2) \\Ports\\\lib*_a.*
+*
+* where
+* directory path for custom library software
+* directory name for specific processor (CPU)
+* 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) \\lib_cfg.h
+*
+* (b) \\lib_*.*
+*
+* where
+* directory path for Your Product's Application
+* directory path for custom library software
+*
+* (2) CPU-configuration software files are located in the following directories :
+*
+* (a) \\cpu_*.*
+* (b) \\\\cpu*.*
+*
+* where
+* directory path for common CPU-compiler software
+* directory name for specific processor (CPU)
+* directory name for specific compiler
+*
+* (3) Compiler MUST be configured to include as additional include path directories :
+*
+* (a) '\\' directory See Note #1a
+*
+* (b) '\\' directory See Note #1b
+*
+* (c) (1) '\\' directory See Note #2a
+* (2) '\\\\' directory See Note #2b
+*
+* (4) NO compiler-supplied standard library functions SHOULD be used.
+*********************************************************************************************************
+*/
+
+#include
+#include
+
+#include
+#include
+
+
+/*
+*********************************************************************************************************
+* 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. */
+
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/lib_str.c b/Middlewares/Third_Party/Micrium/uC-LIB/lib_str.c
new file mode 100644
index 0000000..65f0465
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib_*.*
+*
+* (2) \\Ports\\\lib*_a.*
+*
+* where
+* directory path for custom library software
+* directory name for specific processor (CPU)
+* 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
+
+
+/*
+*********************************************************************************************************
+* 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);
+}
+
diff --git a/Middlewares/Third_Party/Micrium/uC-LIB/lib_str.h b/Middlewares/Third_Party/Micrium/uC-LIB/lib_str.h
new file mode 100644
index 0000000..c6340a4
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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) \\lib_*.*
+*
+* (2) \\Ports\\\lib*_a.*
+*
+* where
+* directory path for custom library software
+* directory name for specific processor (CPU)
+* 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) \\lib_cfg.h
+*
+* (b) \\lib_*.*
+*
+* where
+* directory path for Your Product's Application
+* directory path for custom library software
+*
+* (2) CPU-configuration software files are located in the following directories :
+*
+* (a) \\cpu_*.*
+* (b) \\\\cpu*.*
+*
+* where
+* directory path for common CPU-compiler software
+* directory name for specific processor (CPU)
+* directory name for specific compiler
+*
+* (3) Compiler MUST be configured to include as additional include path directories :
+*
+* (a) '\\' directory See Note #1a
+*
+* (b) '\\' directory See Note #1b
+*
+* (c) (1) '\\' directory See Note #2a
+* (2) '\\\\' 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
+
+#include
+#include
+
+#include
+
+#if 0 /* See Note #4. */
+#include
+#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. */
+
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/IAR/os_cpu.h b/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/IAR/os_cpu.h
new file mode 100644
index 0000000..11fa92a
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/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
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/IAR/os_cpu_a.asm b/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/IAR/os_cpu_a.asm
new file mode 100644
index 0000000..680cdf1
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/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
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/IAR/os_cpu_c.c b/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/IAR/os_cpu_c.c
new file mode 100644
index 0000000..acdd0b7
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/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
+#include
+
+
+/*
+*********************************************************************************************************
+* 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;
+}
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/IAR/os_dbg.c b/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/IAR/os_dbg.c
new file mode 100644
index 0000000..2d36f2a
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/uCOS-II/Ports/ARM-Cortex-M4/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
+
+#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
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/os.h b/Middlewares/Third_Party/Micrium/uCOS-II/Source/os.h
new file mode 100644
index 0000000..98c30c7
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+
+
+typedef INT8U OS_ERR;
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_core.c b/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_core.c
new file mode 100644
index 0000000..53a3a6c
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+#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);
+}
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_flag.c b/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_flag.c
new file mode 100644
index 0000000..ee27d05
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+#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
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_mbox.c b/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_mbox.c
new file mode 100644
index 0000000..0322474
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+#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 */
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_mem.c b/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_mem.c
new file mode 100644
index 0000000..fea5a6d
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+#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 */
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_mutex.c b/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_mutex.c
new file mode 100644
index 0000000..b75ae18
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+#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 */
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_q.c b/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_q.c
new file mode 100644
index 0000000..29dba06
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+#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 */
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_sem.c b/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_sem.c
new file mode 100644
index 0000000..93bfb1a
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+#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 */
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_task.c b/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_task.c
new file mode 100644
index 0000000..8d11a72
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+#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
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_time.c b/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_time.c
new file mode 100644
index 0000000..d3a9a11
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+#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
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_tmr.c b/Middlewares/Third_Party/Micrium/uCOS-II/Source/os_tmr.c
new file mode 100644
index 0000000..7d1b48c
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/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
+#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
diff --git a/Middlewares/Third_Party/Micrium/uCOS-II/Source/ucos_ii.h b/Middlewares/Third_Party/Micrium/uCOS-II/Source/ucos_ii.h
new file mode 100644
index 0000000..8fc083a
--- /dev/null
+++ b/Middlewares/Third_Party/Micrium/uCOS-II/Source/ucos_ii.h
@@ -0,0 +1,1982 @@
+/*
+*********************************************************************************************************
+* 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
+#include
+#include
+
+/*
+*********************************************************************************************************
+* 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