| @@ -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 */ | |||
| } | |||
| @@ -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 */ | |||
| } | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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. */ | |||
| @@ -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 | |||
| @@ -0,0 +1,754 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/CPU | |||
| * CPU CONFIGURATION & PORT LAYER | |||
| * | |||
| * (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL | |||
| * | |||
| * All rights reserved. Protected by international copyright laws. | |||
| * | |||
| * uC/CPU is provided in source form to registered licensees ONLY. It is | |||
| * illegal to distribute this source code to any third party unless you receive | |||
| * written permission by an authorized Micrium representative. Knowledge of | |||
| * the source code may NOT be used to develop a similar product. | |||
| * | |||
| * Please help us continue to provide the Embedded community with the finest | |||
| * software available. Your honesty is greatly appreciated. | |||
| * | |||
| * You can find our product's user manual, API reference, release notes and | |||
| * more information at https://doc.micrium.com. | |||
| * You can contact us at www.micrium.com. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * | |||
| * CPU PORT FILE | |||
| * | |||
| * ARM-Cortex-M4 | |||
| * IAR C Compiler | |||
| * | |||
| * Filename : cpu.h | |||
| * Version : V1.30.02.00 | |||
| * Programmer(s) : JJL | |||
| * BAN | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MODULE | |||
| * | |||
| * Note(s) : (1) This CPU header file is protected from multiple pre-processor inclusion through use of | |||
| * the CPU module present pre-processor macro definition. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #ifndef CPU_MODULE_PRESENT /* See Note #1. */ | |||
| #define CPU_MODULE_PRESENT | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU INCLUDE FILES | |||
| * | |||
| * Note(s) : (1) The following CPU files are located in the following directories : | |||
| * | |||
| * (a) \<Your Product Application>\cpu_cfg.h | |||
| * | |||
| * (b) (1) \<CPU-Compiler Directory>\cpu_def.h | |||
| * (2) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.* | |||
| * | |||
| * where | |||
| * <Your Product Application> directory path for Your Product's Application | |||
| * <CPU-Compiler Directory> directory path for common CPU-compiler software | |||
| * <cpu> directory name for specific CPU | |||
| * <compiler> directory name for specific compiler | |||
| * | |||
| * (2) Compiler MUST be configured to include as additional include path directories : | |||
| * | |||
| * (a) '\<Your Product Application>\' directory See Note #1a | |||
| * | |||
| * (b) (1) '\<CPU-Compiler Directory>\' directory See Note #1b1 | |||
| * (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory See Note #1b2 | |||
| * | |||
| * (3) Since NO custom library modules are included, 'cpu.h' may ONLY use configurations from | |||
| * CPU configuration file 'cpu_cfg.h' that do NOT reference any custom library definitions. | |||
| * | |||
| * In other words, 'cpu.h' may use 'cpu_cfg.h' configurations that are #define'd to numeric | |||
| * constants or to NULL (i.e. NULL-valued #define's); but may NOT use configurations to | |||
| * custom library #define's (e.g. DEF_DISABLED or DEF_ENABLED). | |||
| ********************************************************************************************************* | |||
| */ | |||
| #include <intrinsics.h> | |||
| #include <cpu_def.h> | |||
| #include <cpu_cfg.h> /* See Note #3. */ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CONFIGURE STANDARD DATA TYPES | |||
| * | |||
| * Note(s) : (1) Configure standard data types according to CPU-/compiler-specifications. | |||
| * | |||
| * (2) (a) (1) 'CPU_FNCT_VOID' data type defined to replace the commonly-used function pointer | |||
| * data type of a pointer to a function which returns void & has no arguments. | |||
| * | |||
| * (2) Example function pointer usage : | |||
| * | |||
| * CPU_FNCT_VOID FnctName; | |||
| * | |||
| * FnctName(); | |||
| * | |||
| * (b) (1) 'CPU_FNCT_PTR' data type defined to replace the commonly-used function pointer | |||
| * data type of a pointer to a function which returns void & has a single void | |||
| * pointer argument. | |||
| * | |||
| * (2) Example function pointer usage : | |||
| * | |||
| * CPU_FNCT_PTR FnctName; | |||
| * void *p_obj | |||
| * | |||
| * FnctName(p_obj); | |||
| ********************************************************************************************************* | |||
| */ | |||
| typedef void CPU_VOID; | |||
| typedef char CPU_CHAR; /* 8-bit character */ | |||
| typedef unsigned char CPU_BOOLEAN; /* 8-bit boolean or logical */ | |||
| typedef unsigned char CPU_INT08U; /* 8-bit unsigned integer */ | |||
| typedef signed char CPU_INT08S; /* 8-bit signed integer */ | |||
| typedef unsigned short CPU_INT16U; /* 16-bit unsigned integer */ | |||
| typedef signed short CPU_INT16S; /* 16-bit signed integer */ | |||
| typedef unsigned int CPU_INT32U; /* 32-bit unsigned integer */ | |||
| typedef signed int CPU_INT32S; /* 32-bit signed integer */ | |||
| typedef unsigned long long CPU_INT64U; /* 64-bit unsigned integer */ | |||
| typedef signed long long CPU_INT64S; /* 64-bit signed integer */ | |||
| typedef float CPU_FP32; /* 32-bit floating point */ | |||
| typedef double CPU_FP64; /* 64-bit floating point */ | |||
| typedef volatile CPU_INT08U CPU_REG08; /* 8-bit register */ | |||
| typedef volatile CPU_INT16U CPU_REG16; /* 16-bit register */ | |||
| typedef volatile CPU_INT32U CPU_REG32; /* 32-bit register */ | |||
| typedef volatile CPU_INT64U CPU_REG64; /* 64-bit register */ | |||
| typedef void (*CPU_FNCT_VOID)(void); /* See Note #2a. */ | |||
| typedef void (*CPU_FNCT_PTR )(void *p_obj); /* See Note #2b. */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU WORD CONFIGURATION | |||
| * | |||
| * Note(s) : (1) Configure CPU_CFG_ADDR_SIZE, CPU_CFG_DATA_SIZE, & CPU_CFG_DATA_SIZE_MAX with CPU's &/or | |||
| * compiler's word sizes : | |||
| * | |||
| * CPU_WORD_SIZE_08 8-bit word size | |||
| * CPU_WORD_SIZE_16 16-bit word size | |||
| * CPU_WORD_SIZE_32 32-bit word size | |||
| * CPU_WORD_SIZE_64 64-bit word size | |||
| * | |||
| * (2) Configure CPU_CFG_ENDIAN_TYPE with CPU's data-word-memory order : | |||
| * | |||
| * (a) CPU_ENDIAN_TYPE_BIG Big- endian word order (CPU words' most significant | |||
| * octet @ lowest memory address) | |||
| * (b) CPU_ENDIAN_TYPE_LITTLE Little-endian word order (CPU words' least significant | |||
| * octet @ lowest memory address) | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* Define CPU word sizes (see Note #1) : */ | |||
| #define CPU_CFG_ADDR_SIZE CPU_WORD_SIZE_32 /* Defines CPU address word size (in octets). */ | |||
| #define CPU_CFG_DATA_SIZE CPU_WORD_SIZE_32 /* Defines CPU data word size (in octets). */ | |||
| #define CPU_CFG_DATA_SIZE_MAX CPU_WORD_SIZE_64 /* Defines CPU maximum word size (in octets). */ | |||
| #define CPU_CFG_ENDIAN_TYPE CPU_ENDIAN_TYPE_LITTLE /* Defines CPU data word-memory order (see Note #2). */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CONFIGURE CPU ADDRESS & DATA TYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* CPU address type based on address bus size. */ | |||
| #if (CPU_CFG_ADDR_SIZE == CPU_WORD_SIZE_32) | |||
| typedef CPU_INT32U CPU_ADDR; | |||
| #elif (CPU_CFG_ADDR_SIZE == CPU_WORD_SIZE_16) | |||
| typedef CPU_INT16U CPU_ADDR; | |||
| #else | |||
| typedef CPU_INT08U CPU_ADDR; | |||
| #endif | |||
| /* CPU data type based on data bus size. */ | |||
| #if (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_32) | |||
| typedef CPU_INT32U CPU_DATA; | |||
| #elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_16) | |||
| typedef CPU_INT16U CPU_DATA; | |||
| #else | |||
| typedef CPU_INT08U CPU_DATA; | |||
| #endif | |||
| typedef CPU_DATA CPU_ALIGN; /* Defines CPU data-word-alignment size. */ | |||
| typedef CPU_ADDR CPU_SIZE_T; /* Defines CPU standard 'size_t' size. */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU STACK CONFIGURATION | |||
| * | |||
| * Note(s) : (1) Configure CPU_CFG_STK_GROWTH in 'cpu.h' with CPU's stack growth order : | |||
| * | |||
| * (a) CPU_STK_GROWTH_LO_TO_HI CPU stack pointer increments to the next higher stack | |||
| * memory address after data is pushed onto the stack | |||
| * (b) CPU_STK_GROWTH_HI_TO_LO CPU stack pointer decrements to the next lower stack | |||
| * memory address after data is pushed onto the stack | |||
| * | |||
| * (2) Configure CPU_CFG_STK_ALIGN_BYTES with the highest minimum alignement required for | |||
| * cpu stacks. | |||
| * | |||
| * (a) ARM Procedure Calls Standard requires an 8 bytes stack alignment. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define CPU_CFG_STK_GROWTH CPU_STK_GROWTH_HI_TO_LO /* Defines CPU stack growth order (see Note #1). */ | |||
| #define CPU_CFG_STK_ALIGN_BYTES (8u) /* Defines CPU stack alignment in bytes. (see Note #2). */ | |||
| typedef CPU_INT32U CPU_STK; /* Defines CPU stack data type. */ | |||
| typedef CPU_ADDR CPU_STK_SIZE; /* Defines CPU stack size data type. */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CRITICAL SECTION CONFIGURATION | |||
| * | |||
| * Note(s) : (1) Configure CPU_CFG_CRITICAL_METHOD with CPU's/compiler's critical section method : | |||
| * | |||
| * Enter/Exit critical sections by ... | |||
| * | |||
| * CPU_CRITICAL_METHOD_INT_DIS_EN Disable/Enable interrupts | |||
| * CPU_CRITICAL_METHOD_STATUS_STK Push/Pop interrupt status onto stack | |||
| * CPU_CRITICAL_METHOD_STATUS_LOCAL Save/Restore interrupt status to local variable | |||
| * | |||
| * (a) CPU_CRITICAL_METHOD_INT_DIS_EN is NOT a preferred method since it does NOT support | |||
| * multiple levels of interrupts. However, with some CPUs/compilers, this is the only | |||
| * available method. | |||
| * | |||
| * (b) CPU_CRITICAL_METHOD_STATUS_STK is one preferred method since it supports multiple | |||
| * levels of interrupts. However, this method assumes that the compiler provides C-level | |||
| * &/or assembly-level functionality for the following : | |||
| * | |||
| * ENTER CRITICAL SECTION : | |||
| * (1) Push/save interrupt status onto a local stack | |||
| * (2) Disable interrupts | |||
| * | |||
| * EXIT CRITICAL SECTION : | |||
| * (3) Pop/restore interrupt status from a local stack | |||
| * | |||
| * (c) CPU_CRITICAL_METHOD_STATUS_LOCAL is one preferred method since it supports multiple | |||
| * levels of interrupts. However, this method assumes that the compiler provides C-level | |||
| * &/or assembly-level functionality for the following : | |||
| * | |||
| * ENTER CRITICAL SECTION : | |||
| * (1) Save interrupt status into a local variable | |||
| * (2) Disable interrupts | |||
| * | |||
| * EXIT CRITICAL SECTION : | |||
| * (3) Restore interrupt status from a local variable | |||
| * | |||
| * (2) Critical section macro's most likely require inline assembly. If the compiler does NOT | |||
| * allow inline assembly in C source files, critical section macro's MUST call an assembly | |||
| * subroutine defined in a 'cpu_a.asm' file located in the following software directory : | |||
| * | |||
| * \<CPU-Compiler Directory>\<cpu>\<compiler>\ | |||
| * | |||
| * where | |||
| * <CPU-Compiler Directory> directory path for common CPU-compiler software | |||
| * <cpu> directory name for specific CPU | |||
| * <compiler> directory name for specific compiler | |||
| * | |||
| * (3) (a) To save/restore interrupt status, a local variable 'cpu_sr' of type 'CPU_SR' MAY need | |||
| * to be declared (e.g. if 'CPU_CRITICAL_METHOD_STATUS_LOCAL' method is configured). | |||
| * | |||
| * (1) 'cpu_sr' local variable SHOULD be declared via the CPU_SR_ALLOC() macro which, if | |||
| * used, MUST be declared following ALL other local variables. | |||
| * | |||
| * Example : | |||
| * | |||
| * void Fnct (void) | |||
| * { | |||
| * CPU_INT08U val_08; | |||
| * CPU_INT16U val_16; | |||
| * CPU_INT32U val_32; | |||
| * CPU_SR_ALLOC(); MUST be declared after ALL other local variables | |||
| * : | |||
| * : | |||
| * } | |||
| * | |||
| * (b) Configure 'CPU_SR' data type with the appropriate-sized CPU data type large enough to | |||
| * completely store the CPU's/compiler's status word. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* Configure CPU critical method (see Note #1) : */ | |||
| #define CPU_CFG_CRITICAL_METHOD CPU_CRITICAL_METHOD_STATUS_LOCAL | |||
| typedef CPU_INT32U CPU_SR; /* Defines CPU status register size (see Note #3b). */ | |||
| /* Allocates CPU status register word (see Note #3a). */ | |||
| #if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL) | |||
| #define CPU_SR_ALLOC() CPU_SR cpu_sr = (CPU_SR)0 | |||
| #else | |||
| #define CPU_SR_ALLOC() | |||
| #endif | |||
| /* Save CPU status word & disable interrupts.*/ | |||
| #define CPU_INT_DIS() do { cpu_sr = __get_PRIMASK(); __disable_interrupt(); } while (0) | |||
| #define CPU_INT_EN() do { __set_PRIMASK(cpu_sr); } while (0) /* Restore CPU status word. */ | |||
| #ifdef CPU_CFG_INT_DIS_MEAS_EN | |||
| /* Disable interrupts, ... */ | |||
| /* & start interrupts disabled time measurement.*/ | |||
| #define CPU_CRITICAL_ENTER() do { CPU_INT_DIS(); \ | |||
| CPU_IntDisMeasStart(); } while (0) | |||
| /* Stop & measure interrupts disabled time, */ | |||
| /* ... & re-enable interrupts. */ | |||
| #define CPU_CRITICAL_EXIT() do { CPU_IntDisMeasStop(); \ | |||
| CPU_INT_EN(); } while (0) | |||
| #else | |||
| #define CPU_CRITICAL_ENTER() do { CPU_INT_DIS(); } while (0) /* Disable interrupts. */ | |||
| #define CPU_CRITICAL_EXIT() do { CPU_INT_EN(); } while (0) /* Re-enable interrupts. */ | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MEMORY BARRIERS CONFIGURATION | |||
| * | |||
| * Note(s) : (1) (a) Configure memory barriers if required by the architecture. | |||
| * | |||
| * CPU_MB Full memory barrier. | |||
| * CPU_RMB Read (Loads) memory barrier. | |||
| * CPU_WMB Write (Stores) memory barrier. | |||
| * | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define CPU_MB() __DSB() | |||
| #define CPU_RMB() __DSB() | |||
| #define CPU_WMB() __DSB() | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU COUNT ZEROS CONFIGURATION | |||
| * | |||
| * Note(s) : (1) (a) Configure CPU_CFG_LEAD_ZEROS_ASM_PRESENT to define count leading zeros bits | |||
| * function(s) in : | |||
| * | |||
| * (1) 'cpu_a.asm', if CPU_CFG_LEAD_ZEROS_ASM_PRESENT #define'd in 'cpu.h'/ | |||
| * 'cpu_cfg.h' to enable assembly-optimized function(s) | |||
| * | |||
| * (2) 'cpu_core.c', if CPU_CFG_LEAD_ZEROS_ASM_PRESENT NOT #define'd in 'cpu.h'/ | |||
| * 'cpu_cfg.h' to enable C-source-optimized function(s) otherwise | |||
| * | |||
| * (b) Configure CPU_CFG_TRAIL_ZEROS_ASM_PRESENT to define count trailing zeros bits | |||
| * function(s) in : | |||
| * | |||
| * (1) 'cpu_a.asm', if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT #define'd in 'cpu.h'/ | |||
| * 'cpu_cfg.h' to enable assembly-optimized function(s) | |||
| * | |||
| * (2) 'cpu_core.c', if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT NOT #define'd in 'cpu.h'/ | |||
| * 'cpu_cfg.h' to enable C-source-optimized function(s) otherwise | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* Configure CPU count leading zeros bits ... */ | |||
| #define CPU_CFG_LEAD_ZEROS_ASM_PRESENT /* ... assembly-version (see Note #1a). */ | |||
| /* Configure CPU count trailing zeros bits ... */ | |||
| #define CPU_CFG_TRAIL_ZEROS_ASM_PRESENT /* ... assembly-version (see Note #1b). */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * FUNCTION PROTOTYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| void CPU_IntDis (void); | |||
| void CPU_IntEn (void); | |||
| void CPU_IntSrcDis (CPU_INT08U pos); | |||
| void CPU_IntSrcEn (CPU_INT08U pos); | |||
| void CPU_IntSrcPendClr(CPU_INT08U pos); | |||
| CPU_INT16S CPU_IntSrcPrioGet(CPU_INT08U pos); | |||
| void CPU_IntSrcPrioSet(CPU_INT08U pos, | |||
| CPU_INT08U prio); | |||
| CPU_SR CPU_SR_Save (void); | |||
| void CPU_SR_Restore (CPU_SR cpu_sr); | |||
| void CPU_WaitForInt (void); | |||
| void CPU_WaitForExcept(void); | |||
| CPU_DATA CPU_RevBits (CPU_DATA val); | |||
| void CPU_BitBandClr (CPU_ADDR addr, | |||
| CPU_INT08U bit_nbr); | |||
| void CPU_BitBandSet (CPU_ADDR addr, | |||
| CPU_INT08U bit_nbr); | |||
| /* | |||
| ********************************************************************************************************* | |||
| * INTERRUPT SOURCES | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define CPU_INT_STK_PTR 0u | |||
| #define CPU_INT_RESET 1u | |||
| #define CPU_INT_NMI 2u | |||
| #define CPU_INT_HFAULT 3u | |||
| #define CPU_INT_MEM 4u | |||
| #define CPU_INT_BUSFAULT 5u | |||
| #define CPU_INT_USAGEFAULT 6u | |||
| #define CPU_INT_RSVD_07 7u | |||
| #define CPU_INT_RSVD_08 8u | |||
| #define CPU_INT_RSVD_09 9u | |||
| #define CPU_INT_RSVD_10 10u | |||
| #define CPU_INT_SVCALL 11u | |||
| #define CPU_INT_DBGMON 12u | |||
| #define CPU_INT_RSVD_13 13u | |||
| #define CPU_INT_PENDSV 14u | |||
| #define CPU_INT_SYSTICK 15u | |||
| #define CPU_INT_EXT0 16u | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU REGISTERS | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define CPU_REG_NVIC_NVIC (*((CPU_REG32 *)(0xE000E004))) /* Int Ctrl'er Type Reg. */ | |||
| #define CPU_REG_NVIC_ST_CTRL (*((CPU_REG32 *)(0xE000E010))) /* SysTick Ctrl & Status Reg. */ | |||
| #define CPU_REG_NVIC_ST_RELOAD (*((CPU_REG32 *)(0xE000E014))) /* SysTick Reload Value Reg. */ | |||
| #define CPU_REG_NVIC_ST_CURRENT (*((CPU_REG32 *)(0xE000E018))) /* SysTick Current Value Reg. */ | |||
| #define CPU_REG_NVIC_ST_CAL (*((CPU_REG32 *)(0xE000E01C))) /* SysTick Calibration Value Reg. */ | |||
| #define CPU_REG_NVIC_SETEN(n) (*((CPU_REG32 *)(0xE000E100 + (n) * 4u))) /* IRQ Set En Reg. */ | |||
| #define CPU_REG_NVIC_CLREN(n) (*((CPU_REG32 *)(0xE000E180 + (n) * 4u))) /* IRQ Clr En Reg. */ | |||
| #define CPU_REG_NVIC_SETPEND(n) (*((CPU_REG32 *)(0xE000E200 + (n) * 4u))) /* IRQ Set Pending Reg. */ | |||
| #define CPU_REG_NVIC_CLRPEND(n) (*((CPU_REG32 *)(0xE000E280 + (n) * 4u))) /* IRQ Clr Pending Reg. */ | |||
| #define CPU_REG_NVIC_ACTIVE(n) (*((CPU_REG32 *)(0xE000E300 + (n) * 4u))) /* IRQ Active Reg. */ | |||
| #define CPU_REG_NVIC_PRIO(n) (*((CPU_REG32 *)(0xE000E400 + (n) * 4u))) /* IRQ Prio Reg. */ | |||
| #define CPU_REG_NVIC_CPUID (*((CPU_REG32 *)(0xE000ED00))) /* CPUID Base Reg. */ | |||
| #define CPU_REG_NVIC_ICSR (*((CPU_REG32 *)(0xE000ED04))) /* Int Ctrl State Reg. */ | |||
| #define CPU_REG_NVIC_VTOR (*((CPU_REG32 *)(0xE000ED08))) /* Vect Tbl Offset Reg. */ | |||
| #define CPU_REG_NVIC_AIRCR (*((CPU_REG32 *)(0xE000ED0C))) /* App Int/Reset Ctrl Reg. */ | |||
| #define CPU_REG_NVIC_SCR (*((CPU_REG32 *)(0xE000ED10))) /* System Ctrl Reg. */ | |||
| #define CPU_REG_NVIC_CCR (*((CPU_REG32 *)(0xE000ED14))) /* Cfg Ctrl Reg. */ | |||
| #define CPU_REG_NVIC_SHPRI1 (*((CPU_REG32 *)(0xE000ED18))) /* System Handlers 4 to 7 Prio. */ | |||
| #define CPU_REG_NVIC_SHPRI2 (*((CPU_REG32 *)(0xE000ED1C))) /* System Handlers 8 to 11 Prio. */ | |||
| #define CPU_REG_NVIC_SHPRI3 (*((CPU_REG32 *)(0xE000ED20))) /* System Handlers 12 to 15 Prio. */ | |||
| #define CPU_REG_NVIC_SHCSR (*((CPU_REG32 *)(0xE000ED24))) /* System Handler Ctrl & State Reg. */ | |||
| #define CPU_REG_NVIC_CFSR (*((CPU_REG32 *)(0xE000ED28))) /* Configurable Fault Status Reg. */ | |||
| #define CPU_REG_NVIC_HFSR (*((CPU_REG32 *)(0xE000ED2C))) /* Hard Fault Status Reg. */ | |||
| #define CPU_REG_NVIC_DFSR (*((CPU_REG32 *)(0xE000ED30))) /* Debug Fault Status Reg. */ | |||
| #define CPU_REG_NVIC_MMFAR (*((CPU_REG32 *)(0xE000ED34))) /* Mem Manage Addr Reg. */ | |||
| #define CPU_REG_NVIC_BFAR (*((CPU_REG32 *)(0xE000ED38))) /* Bus Fault Addr Reg. */ | |||
| #define CPU_REG_NVIC_AFSR (*((CPU_REG32 *)(0xE000ED3C))) /* Aux Fault Status Reg. */ | |||
| #define CPU_REG_NVIC_CPACR (*((CPU_REG32 *)(0xE000ED88))) /* Coprocessor Access Control Reg. */ | |||
| #define CPU_REG_NVIC_PFR0 (*((CPU_REG32 *)(0xE000ED40))) /* Processor Feature Reg 0. */ | |||
| #define CPU_REG_NVIC_PFR1 (*((CPU_REG32 *)(0xE000ED44))) /* Processor Feature Reg 1. */ | |||
| #define CPU_REG_NVIC_DFR0 (*((CPU_REG32 *)(0xE000ED48))) /* Debug Feature Reg 0. */ | |||
| #define CPU_REG_NVIC_AFR0 (*((CPU_REG32 *)(0xE000ED4C))) /* Aux Feature Reg 0. */ | |||
| #define CPU_REG_NVIC_MMFR0 (*((CPU_REG32 *)(0xE000ED50))) /* Memory Model Feature Reg 0. */ | |||
| #define CPU_REG_NVIC_MMFR1 (*((CPU_REG32 *)(0xE000ED54))) /* Memory Model Feature Reg 1. */ | |||
| #define CPU_REG_NVIC_MMFR2 (*((CPU_REG32 *)(0xE000ED58))) /* Memory Model Feature Reg 2. */ | |||
| #define CPU_REG_NVIC_MMFR3 (*((CPU_REG32 *)(0xE000ED5C))) /* Memory Model Feature Reg 3. */ | |||
| #define CPU_REG_NVIC_ISAFR0 (*((CPU_REG32 *)(0xE000ED60))) /* ISA Feature Reg 0. */ | |||
| #define CPU_REG_NVIC_ISAFR1 (*((CPU_REG32 *)(0xE000ED64))) /* ISA Feature Reg 1. */ | |||
| #define CPU_REG_NVIC_ISAFR2 (*((CPU_REG32 *)(0xE000ED68))) /* ISA Feature Reg 2. */ | |||
| #define CPU_REG_NVIC_ISAFR3 (*((CPU_REG32 *)(0xE000ED6C))) /* ISA Feature Reg 3. */ | |||
| #define CPU_REG_NVIC_ISAFR4 (*((CPU_REG32 *)(0xE000ED70))) /* ISA Feature Reg 4. */ | |||
| #define CPU_REG_NVIC_SW_TRIG (*((CPU_REG32 *)(0xE000EF00))) /* Software Trigger Int Reg. */ | |||
| #define CPU_REG_MPU_TYPE (*((CPU_REG32 *)(0xE000ED90))) /* MPU Type Reg. */ | |||
| #define CPU_REG_MPU_CTRL (*((CPU_REG32 *)(0xE000ED94))) /* MPU Ctrl Reg. */ | |||
| #define CPU_REG_MPU_REG_NBR (*((CPU_REG32 *)(0xE000ED98))) /* MPU Region Nbr Reg. */ | |||
| #define CPU_REG_MPU_REG_BASE (*((CPU_REG32 *)(0xE000ED9C))) /* MPU Region Base Addr Reg. */ | |||
| #define CPU_REG_MPU_REG_ATTR (*((CPU_REG32 *)(0xE000EDA0))) /* MPU Region Attrib & Size Reg. */ | |||
| #define CPU_REG_DBG_CTRL (*((CPU_REG32 *)(0xE000EDF0))) /* Debug Halting Ctrl & Status Reg. */ | |||
| #define CPU_REG_DBG_SELECT (*((CPU_REG32 *)(0xE000EDF4))) /* Debug Core Reg Selector Reg. */ | |||
| #define CPU_REG_DBG_DATA (*((CPU_REG32 *)(0xE000EDF8))) /* Debug Core Reg Data Reg. */ | |||
| #define CPU_REG_DBG_INT (*((CPU_REG32 *)(0xE000EDFC))) /* Debug Except & Monitor Ctrl Reg. */ | |||
| #define CPU_REG_SCB_FPCCR (*((CPU_REG32 *)(0xE000EF34))) /* Floating-Point Context Control Reg. */ | |||
| #define CPU_REG_SCB_FPCAR (*((CPU_REG32 *)(0xE000EF38))) /* Floating-Point Context Address Reg. */ | |||
| #define CPU_REG_SCB_FPDSCR (*((CPU_REG32 *)(0xE000EF3C))) /* FP Default Status Control Reg. */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU REGISTER BITS | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* ---------- SYSTICK CTRL & STATUS REG BITS ---------- */ | |||
| #define CPU_REG_NVIC_ST_CTRL_COUNTFLAG 0x00010000 | |||
| #define CPU_REG_NVIC_ST_CTRL_CLKSOURCE 0x00000004 | |||
| #define CPU_REG_NVIC_ST_CTRL_TICKINT 0x00000002 | |||
| #define CPU_REG_NVIC_ST_CTRL_ENABLE 0x00000001 | |||
| /* -------- SYSTICK CALIBRATION VALUE REG BITS -------- */ | |||
| #define CPU_REG_NVIC_ST_CAL_NOREF 0x80000000 | |||
| #define CPU_REG_NVIC_ST_CAL_SKEW 0x40000000 | |||
| /* -------------- INT CTRL STATE REG BITS ------------- */ | |||
| #define CPU_REG_NVIC_ICSR_NMIPENDSET 0x80000000 | |||
| #define CPU_REG_NVIC_ICSR_PENDSVSET 0x10000000 | |||
| #define CPU_REG_NVIC_ICSR_PENDSVCLR 0x08000000 | |||
| #define CPU_REG_NVIC_ICSR_PENDSTSET 0x04000000 | |||
| #define CPU_REG_NVIC_ICSR_PENDSTCLR 0x02000000 | |||
| #define CPU_REG_NVIC_ICSR_ISRPREEMPT 0x00800000 | |||
| #define CPU_REG_NVIC_ICSR_ISRPENDING 0x00400000 | |||
| #define CPU_REG_NVIC_ICSR_RETTOBASE 0x00000800 | |||
| /* ------------- VECT TBL OFFSET REG BITS ------------- */ | |||
| #define CPU_REG_NVIC_VTOR_TBLBASE 0x20000000 | |||
| /* ------------ APP INT/RESET CTRL REG BITS ----------- */ | |||
| #define CPU_REG_NVIC_AIRCR_ENDIANNESS 0x00008000 | |||
| #define CPU_REG_NVIC_AIRCR_SYSRESETREQ 0x00000004 | |||
| #define CPU_REG_NVIC_AIRCR_VECTCLRACTIVE 0x00000002 | |||
| #define CPU_REG_NVIC_AIRCR_VECTRESET 0x00000001 | |||
| /* --------------- SYSTEM CTRL REG BITS --------------- */ | |||
| #define CPU_REG_NVIC_SCR_SEVONPEND 0x00000010 | |||
| #define CPU_REG_NVIC_SCR_SLEEPDEEP 0x00000004 | |||
| #define CPU_REG_NVIC_SCR_SLEEPONEXIT 0x00000002 | |||
| /* ----------------- CFG CTRL REG BITS ---------------- */ | |||
| #define CPU_REG_NVIC_CCR_STKALIGN 0x00000200 | |||
| #define CPU_REG_NVIC_CCR_BFHFNMIGN 0x00000100 | |||
| #define CPU_REG_NVIC_CCR_DIV_0_TRP 0x00000010 | |||
| #define CPU_REG_NVIC_CCR_UNALIGN_TRP 0x00000008 | |||
| #define CPU_REG_NVIC_CCR_USERSETMPEND 0x00000002 | |||
| #define CPU_REG_NVIC_CCR_NONBASETHRDENA 0x00000001 | |||
| /* ------- SYSTEM HANDLER CTRL & STATE REG BITS ------- */ | |||
| #define CPU_REG_NVIC_SHCSR_USGFAULTENA 0x00040000 | |||
| #define CPU_REG_NVIC_SHCSR_BUSFAULTENA 0x00020000 | |||
| #define CPU_REG_NVIC_SHCSR_MEMFAULTENA 0x00010000 | |||
| #define CPU_REG_NVIC_SHCSR_SVCALLPENDED 0x00008000 | |||
| #define CPU_REG_NVIC_SHCSR_BUSFAULTPENDED 0x00004000 | |||
| #define CPU_REG_NVIC_SHCSR_MEMFAULTPENDED 0x00002000 | |||
| #define CPU_REG_NVIC_SHCSR_USGFAULTPENDED 0x00001000 | |||
| #define CPU_REG_NVIC_SHCSR_SYSTICKACT 0x00000800 | |||
| #define CPU_REG_NVIC_SHCSR_PENDSVACT 0x00000400 | |||
| #define CPU_REG_NVIC_SHCSR_MONITORACT 0x00000100 | |||
| #define CPU_REG_NVIC_SHCSR_SVCALLACT 0x00000080 | |||
| #define CPU_REG_NVIC_SHCSR_USGFAULTACT 0x00000008 | |||
| #define CPU_REG_NVIC_SHCSR_BUSFAULTACT 0x00000002 | |||
| #define CPU_REG_NVIC_SHCSR_MEMFAULTACT 0x00000001 | |||
| /* -------- CONFIGURABLE FAULT STATUS REG BITS -------- */ | |||
| #define CPU_REG_NVIC_CFSR_DIVBYZERO 0x02000000 | |||
| #define CPU_REG_NVIC_CFSR_UNALIGNED 0x01000000 | |||
| #define CPU_REG_NVIC_CFSR_NOCP 0x00080000 | |||
| #define CPU_REG_NVIC_CFSR_INVPC 0x00040000 | |||
| #define CPU_REG_NVIC_CFSR_INVSTATE 0x00020000 | |||
| #define CPU_REG_NVIC_CFSR_UNDEFINSTR 0x00010000 | |||
| #define CPU_REG_NVIC_CFSR_BFARVALID 0x00008000 | |||
| #define CPU_REG_NVIC_CFSR_STKERR 0x00001000 | |||
| #define CPU_REG_NVIC_CFSR_UNSTKERR 0x00000800 | |||
| #define CPU_REG_NVIC_CFSR_IMPRECISERR 0x00000400 | |||
| #define CPU_REG_NVIC_CFSR_PRECISERR 0x00000200 | |||
| #define CPU_REG_NVIC_CFSR_IBUSERR 0x00000100 | |||
| #define CPU_REG_NVIC_CFSR_MMARVALID 0x00000080 | |||
| #define CPU_REG_NVIC_CFSR_MSTKERR 0x00000010 | |||
| #define CPU_REG_NVIC_CFSR_MUNSTKERR 0x00000008 | |||
| #define CPU_REG_NVIC_CFSR_DACCVIOL 0x00000002 | |||
| #define CPU_REG_NVIC_CFSR_IACCVIOL 0x00000001 | |||
| /* ------------ HARD FAULT STATUS REG BITS ------------ */ | |||
| #define CPU_REG_NVIC_HFSR_DEBUGEVT 0x80000000 | |||
| #define CPU_REG_NVIC_HFSR_FORCED 0x40000000 | |||
| #define CPU_REG_NVIC_HFSR_VECTTBL 0x00000002 | |||
| /* ------------ DEBUG FAULT STATUS REG BITS ----------- */ | |||
| #define CPU_REG_NVIC_DFSR_EXTERNAL 0x00000010 | |||
| #define CPU_REG_NVIC_DFSR_VCATCH 0x00000008 | |||
| #define CPU_REG_NVIC_DFSR_DWTTRAP 0x00000004 | |||
| #define CPU_REG_NVIC_DFSR_BKPT 0x00000002 | |||
| #define CPU_REG_NVIC_DFSR_HALTED 0x00000001 | |||
| /* -------- COPROCESSOR ACCESS CONTROL REG BITS ------- */ | |||
| #define CPU_REG_NVIC_CPACR_CP10_FULL_ACCESS 0x00300000 | |||
| #define CPU_REG_NVIC_CPACR_CP11_FULL_ACCESS 0x00C00000 | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU REGISTER MASK | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define CPU_MSK_NVIC_ICSR_VECT_ACTIVE 0x000001FF | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CONFIGURATION ERRORS | |||
| ********************************************************************************************************* | |||
| */ | |||
| #ifndef CPU_CFG_ADDR_SIZE | |||
| #error "CPU_CFG_ADDR_SIZE not #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_WORD_SIZE_08 8-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_16 16-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_32 32-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_64 64-bit alignment]" | |||
| #elif ((CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_08) && \ | |||
| (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_16) && \ | |||
| (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_32) && \ | |||
| (CPU_CFG_ADDR_SIZE != CPU_WORD_SIZE_64)) | |||
| #error "CPU_CFG_ADDR_SIZE illegally #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_WORD_SIZE_08 8-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_16 16-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_32 32-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_64 64-bit alignment]" | |||
| #endif | |||
| #ifndef CPU_CFG_DATA_SIZE | |||
| #error "CPU_CFG_DATA_SIZE not #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_WORD_SIZE_08 8-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_16 16-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_32 32-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_64 64-bit alignment]" | |||
| #elif ((CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_08) && \ | |||
| (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_16) && \ | |||
| (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_32) && \ | |||
| (CPU_CFG_DATA_SIZE != CPU_WORD_SIZE_64)) | |||
| #error "CPU_CFG_DATA_SIZE illegally #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_WORD_SIZE_08 8-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_16 16-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_32 32-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_64 64-bit alignment]" | |||
| #endif | |||
| #ifndef CPU_CFG_DATA_SIZE_MAX | |||
| #error "CPU_CFG_DATA_SIZE_MAX not #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_WORD_SIZE_08 8-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_16 16-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_32 32-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_64 64-bit alignment]" | |||
| #elif ((CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_08) && \ | |||
| (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_16) && \ | |||
| (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_32) && \ | |||
| (CPU_CFG_DATA_SIZE_MAX != CPU_WORD_SIZE_64)) | |||
| #error "CPU_CFG_DATA_SIZE_MAX illegally #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_WORD_SIZE_08 8-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_16 16-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_32 32-bit alignment]" | |||
| #error " [ || CPU_WORD_SIZE_64 64-bit alignment]" | |||
| #endif | |||
| #if (CPU_CFG_DATA_SIZE_MAX < CPU_CFG_DATA_SIZE) | |||
| #error "CPU_CFG_DATA_SIZE_MAX illegally #define'd in 'cpu.h' " | |||
| #error " [MUST be >= CPU_CFG_DATA_SIZE]" | |||
| #endif | |||
| #ifndef CPU_CFG_ENDIAN_TYPE | |||
| #error "CPU_CFG_ENDIAN_TYPE not #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_ENDIAN_TYPE_BIG ]" | |||
| #error " [ || CPU_ENDIAN_TYPE_LITTLE]" | |||
| #elif ((CPU_CFG_ENDIAN_TYPE != CPU_ENDIAN_TYPE_BIG ) && \ | |||
| (CPU_CFG_ENDIAN_TYPE != CPU_ENDIAN_TYPE_LITTLE)) | |||
| #error "CPU_CFG_ENDIAN_TYPE illegally #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_ENDIAN_TYPE_BIG ]" | |||
| #error " [ || CPU_ENDIAN_TYPE_LITTLE]" | |||
| #endif | |||
| #ifndef CPU_CFG_STK_GROWTH | |||
| #error "CPU_CFG_STK_GROWTH not #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_STK_GROWTH_LO_TO_HI]" | |||
| #error " [ || CPU_STK_GROWTH_HI_TO_LO]" | |||
| #elif ((CPU_CFG_STK_GROWTH != CPU_STK_GROWTH_LO_TO_HI) && \ | |||
| (CPU_CFG_STK_GROWTH != CPU_STK_GROWTH_HI_TO_LO)) | |||
| #error "CPU_CFG_STK_GROWTH illegally #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_STK_GROWTH_LO_TO_HI]" | |||
| #error " [ || CPU_STK_GROWTH_HI_TO_LO]" | |||
| #endif | |||
| #ifndef CPU_CFG_CRITICAL_METHOD | |||
| #error "CPU_CFG_CRITICAL_METHOD not #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_CRITICAL_METHOD_INT_DIS_EN ]" | |||
| #error " [ || CPU_CRITICAL_METHOD_STATUS_STK ]" | |||
| #error " [ || CPU_CRITICAL_METHOD_STATUS_LOCAL]" | |||
| #elif ((CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_INT_DIS_EN ) && \ | |||
| (CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_STATUS_STK ) && \ | |||
| (CPU_CFG_CRITICAL_METHOD != CPU_CRITICAL_METHOD_STATUS_LOCAL)) | |||
| #error "CPU_CFG_CRITICAL_METHOD illegally #define'd in 'cpu.h' " | |||
| #error " [MUST be CPU_CRITICAL_METHOD_INT_DIS_EN ]" | |||
| #error " [ || CPU_CRITICAL_METHOD_STATUS_STK ]" | |||
| #error " [ || CPU_CRITICAL_METHOD_STATUS_LOCAL]" | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MODULE END | |||
| * | |||
| * Note(s) : (1) See 'cpu.h MODULE'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* End of CPU module include. */ | |||
| @@ -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 | |||
| @@ -0,0 +1,746 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/CPU | |||
| * CPU CONFIGURATION & PORT LAYER | |||
| * | |||
| * (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL | |||
| * | |||
| * All rights reserved. Protected by international copyright laws. | |||
| * | |||
| * uC/CPU is provided in source form to registered licensees ONLY. It is | |||
| * illegal to distribute this source code to any third party unless you receive | |||
| * written permission by an authorized Micrium representative. Knowledge of | |||
| * the source code may NOT be used to develop a similar product. | |||
| * | |||
| * Please help us continue to provide the Embedded community with the finest | |||
| * software available. Your honesty is greatly appreciated. | |||
| * | |||
| * You can find our product's user manual, API reference, release notes and | |||
| * more information at https://doc.micrium.com. | |||
| * You can contact us at www.micrium.com. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * | |||
| * CPU PORT FILE | |||
| * | |||
| * ARM-Cortex-M4 | |||
| * IAR C Compiler | |||
| * | |||
| * Filename : cpu_c.c | |||
| * Version : V1.30.02.00 | |||
| * Programmer(s) : JJL | |||
| * BAN | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * INCLUDE FILES | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MICRIUM_SOURCE | |||
| #include <cpu.h> | |||
| #include <cpu_core.h> | |||
| #include <lib_def.h> | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL DEFINES | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define CPU_INT_SRC_POS_MAX ((((CPU_REG_NVIC_NVIC + 1) & 0x1F) * 32) + 16) | |||
| #define CPU_BIT_BAND_SRAM_REG_LO 0x20000000 | |||
| #define CPU_BIT_BAND_SRAM_REG_HI 0x200FFFFF | |||
| #define CPU_BIT_BAND_SRAM_BASE 0x22000000 | |||
| #define CPU_BIT_BAND_PERIPH_REG_LO 0x40000000 | |||
| #define CPU_BIT_BAND_PERIPH_REG_HI 0x400FFFFF | |||
| #define CPU_BIT_BAND_PERIPH_BASE 0x42000000 | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL CONSTANTS | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL DATA TYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL TABLES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL GLOBAL VARIABLES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL FUNCTION PROTOTYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL CONFIGURATION ERRORS | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU_BitBandClr() | |||
| * | |||
| * Description : Clear bit in bit-band region. | |||
| * | |||
| * Argument(s) : addr Byte address in memory space. | |||
| * | |||
| * bit_nbr Bit number in byte. | |||
| * | |||
| * Return(s) : none. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : none. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void CPU_BitBandClr (CPU_ADDR addr, | |||
| CPU_INT08U bit_nbr) | |||
| { | |||
| CPU_ADDR bit_word_off; | |||
| CPU_ADDR bit_word_addr; | |||
| if ((addr >= CPU_BIT_BAND_SRAM_REG_LO) && | |||
| (addr <= CPU_BIT_BAND_SRAM_REG_HI)) { | |||
| bit_word_off = ((addr - CPU_BIT_BAND_SRAM_REG_LO ) * 32) + (bit_nbr * 4); | |||
| bit_word_addr = CPU_BIT_BAND_SRAM_BASE + bit_word_off; | |||
| *(volatile CPU_INT32U *)(bit_word_addr) = 0; | |||
| } else if ((addr >= CPU_BIT_BAND_PERIPH_REG_LO) && | |||
| (addr <= CPU_BIT_BAND_PERIPH_REG_HI)) { | |||
| bit_word_off = ((addr - CPU_BIT_BAND_PERIPH_REG_LO) * 32) + (bit_nbr * 4); | |||
| bit_word_addr = CPU_BIT_BAND_PERIPH_BASE + bit_word_off; | |||
| *(volatile CPU_INT32U *)(bit_word_addr) = 0; | |||
| } | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU_BitBandSet() | |||
| * | |||
| * Description : Set bit in bit-band region. | |||
| * | |||
| * Argument(s) : addr Byte address in memory space. | |||
| * | |||
| * bit_nbr Bit number in byte. | |||
| * | |||
| * Return(s) : none. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : none. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void CPU_BitBandSet (CPU_ADDR addr, | |||
| CPU_INT08U bit_nbr) | |||
| { | |||
| CPU_ADDR bit_word_off; | |||
| CPU_ADDR bit_word_addr; | |||
| if ((addr >= CPU_BIT_BAND_SRAM_REG_LO) && | |||
| (addr <= CPU_BIT_BAND_SRAM_REG_HI)) { | |||
| bit_word_off = ((addr - CPU_BIT_BAND_SRAM_REG_LO ) * 32) + (bit_nbr * 4); | |||
| bit_word_addr = CPU_BIT_BAND_SRAM_BASE + bit_word_off; | |||
| *(volatile CPU_INT32U *)(bit_word_addr) = 1; | |||
| } else if ((addr >= CPU_BIT_BAND_PERIPH_REG_LO) && | |||
| (addr <= CPU_BIT_BAND_PERIPH_REG_HI)) { | |||
| bit_word_off = ((addr - CPU_BIT_BAND_PERIPH_REG_LO) * 32) + (bit_nbr * 4); | |||
| bit_word_addr = CPU_BIT_BAND_PERIPH_BASE + bit_word_off; | |||
| *(volatile CPU_INT32U *)(bit_word_addr) = 1; | |||
| } | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU_IntSrcDis() | |||
| * | |||
| * Description : Disable an interrupt source. | |||
| * | |||
| * Argument(s) : pos Position of interrupt vector in interrupt table : | |||
| * | |||
| * 0 Invalid (see Note #1a). | |||
| * 1 Invalid (see Note #1b). | |||
| * 2 Non-maskable interrupt. | |||
| * 3 Hard Fault. | |||
| * 4 Memory Management. | |||
| * 5 Bus Fault. | |||
| * 6 Usage Fault. | |||
| * 7-10 Reserved. | |||
| * 11 SVCall | |||
| * 12 Debug monitor. | |||
| * 13 Reserved | |||
| * 14 PendSV. | |||
| * 15 SysTick. | |||
| * 16+ External Interrupt. | |||
| * | |||
| * Return(s) : none. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) Several table positions do not contain interrupt sources : | |||
| * | |||
| * (a) Position 0 contains the stack pointer. | |||
| * (b) Positions 7-10, 13 are reserved. | |||
| * | |||
| * (2) Several interrupts cannot be disabled/enabled : | |||
| * | |||
| * (a) Reset. | |||
| * (b) NMI. | |||
| * (c) Hard fault. | |||
| * (d) SVCall. | |||
| * (e) Debug monitor. | |||
| * (f) PendSV. | |||
| * | |||
| * (3) The maximum Cortex-M3 table position is 256. A particular Cortex-M3 may have fewer | |||
| * than 240 external exceptions and, consequently, fewer than 256 table positions. | |||
| * This function assumes that the specified table position is valid if the interrupt | |||
| * controller type register's INTLINESNUM field is large enough so that the position | |||
| * COULD be valid. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void CPU_IntSrcDis (CPU_INT08U pos) | |||
| { | |||
| CPU_INT08U group; | |||
| CPU_INT08U pos_max; | |||
| CPU_INT08U nbr; | |||
| CPU_SR_ALLOC(); | |||
| switch (pos) { | |||
| case CPU_INT_STK_PTR: /* ---------------- INVALID OR RESERVED --------------- */ | |||
| case CPU_INT_RSVD_07: | |||
| case CPU_INT_RSVD_08: | |||
| case CPU_INT_RSVD_09: | |||
| case CPU_INT_RSVD_10: | |||
| case CPU_INT_RSVD_13: | |||
| break; | |||
| /* ----------------- SYSTEM EXCEPTIONS ---------------- */ | |||
| case CPU_INT_RESET: /* Reset (see Note #2). */ | |||
| case CPU_INT_NMI: /* Non-maskable interrupt (see Note #2). */ | |||
| case CPU_INT_HFAULT: /* Hard fault (see Note #2). */ | |||
| case CPU_INT_SVCALL: /* SVCall (see Note #2). */ | |||
| case CPU_INT_DBGMON: /* Debug monitor (see Note #2). */ | |||
| case CPU_INT_PENDSV: /* PendSV (see Note #2). */ | |||
| break; | |||
| case CPU_INT_MEM: /* Memory management. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_MEMFAULTENA; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_BUSFAULT: /* Bus fault. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_BUSFAULTENA; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_USAGEFAULT: /* Usage fault. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| CPU_REG_NVIC_SHCSR &= ~CPU_REG_NVIC_SHCSR_USGFAULTENA; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_SYSTICK: /* SysTick. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| CPU_REG_NVIC_ST_CTRL &= ~CPU_REG_NVIC_ST_CTRL_ENABLE; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| /* ---------------- EXTERNAL INTERRUPT ---------------- */ | |||
| default: | |||
| pos_max = CPU_INT_SRC_POS_MAX; | |||
| if (pos < pos_max) { /* See Note #3. */ | |||
| group = (pos - 16) / 32; | |||
| nbr = (pos - 16) % 32; | |||
| CPU_CRITICAL_ENTER(); | |||
| CPU_REG_NVIC_CLREN(group) = DEF_BIT(nbr); | |||
| CPU_CRITICAL_EXIT(); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU_IntSrcEn() | |||
| * | |||
| * Description : Enable an interrupt source. | |||
| * | |||
| * Argument(s) : pos Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()'). | |||
| * | |||
| * Return(s) : none. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) See 'CPU_IntSrcDis() Note #1'. | |||
| * | |||
| * (2) See 'CPU_IntSrcDis() Note #2'. | |||
| * | |||
| * (3) See 'CPU_IntSrcDis() Note #3'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void CPU_IntSrcEn (CPU_INT08U pos) | |||
| { | |||
| CPU_INT08U group; | |||
| CPU_INT08U nbr; | |||
| CPU_INT08U pos_max; | |||
| CPU_SR_ALLOC(); | |||
| switch (pos) { | |||
| case CPU_INT_STK_PTR: /* ---------------- INVALID OR RESERVED --------------- */ | |||
| case CPU_INT_RSVD_07: | |||
| case CPU_INT_RSVD_08: | |||
| case CPU_INT_RSVD_09: | |||
| case CPU_INT_RSVD_10: | |||
| case CPU_INT_RSVD_13: | |||
| break; | |||
| /* ----------------- SYSTEM EXCEPTIONS ---------------- */ | |||
| case CPU_INT_RESET: /* Reset (see Note #2). */ | |||
| case CPU_INT_NMI: /* Non-maskable interrupt (see Note #2). */ | |||
| case CPU_INT_HFAULT: /* Hard fault (see Note #2). */ | |||
| case CPU_INT_SVCALL: /* SVCall (see Note #2). */ | |||
| case CPU_INT_DBGMON: /* Debug monitor (see Note #2). */ | |||
| case CPU_INT_PENDSV: /* PendSV (see Note #2). */ | |||
| break; | |||
| case CPU_INT_MEM: /* Memory management. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_MEMFAULTENA; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_BUSFAULT: /* Bus fault. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_BUSFAULTENA; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_USAGEFAULT: /* Usage fault. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| CPU_REG_NVIC_SHCSR |= CPU_REG_NVIC_SHCSR_USGFAULTENA; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_SYSTICK: /* SysTick. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_ENABLE; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| /* ---------------- EXTERNAL INTERRUPT ---------------- */ | |||
| default: | |||
| pos_max = CPU_INT_SRC_POS_MAX; | |||
| if (pos < pos_max) { /* See Note #3. */ | |||
| group = (pos - 16) / 32; | |||
| nbr = (pos - 16) % 32; | |||
| CPU_CRITICAL_ENTER(); | |||
| CPU_REG_NVIC_SETEN(group) = DEF_BIT(nbr); | |||
| CPU_CRITICAL_EXIT(); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU_IntSrcPendClr() | |||
| * | |||
| * Description : Clear a pending interrupt. | |||
| * | |||
| * Argument(s) : pos Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()'). | |||
| * | |||
| * Return(s) : none. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) See 'CPU_IntSrcDis() Note #1'. | |||
| * | |||
| * (2) The pending status of several interrupts cannot be clear/set : | |||
| * | |||
| * (a) Reset. | |||
| * (b) NMI. | |||
| * (c) Hard fault. | |||
| * (d) Memory Managment. | |||
| * (e) Bus Fault. | |||
| * (f) Usage Fault. | |||
| * (g) SVCall. | |||
| * (h) Debug monitor. | |||
| * (i) PendSV. | |||
| * (j) Systick | |||
| * | |||
| * (3) See 'CPU_IntSrcDis() Note #3'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void CPU_IntSrcPendClr (CPU_INT08U pos) | |||
| { | |||
| CPU_INT08U group; | |||
| CPU_INT08U nbr; | |||
| CPU_INT08U pos_max; | |||
| CPU_SR_ALLOC(); | |||
| switch (pos) { | |||
| case CPU_INT_STK_PTR: /* ---------------- INVALID OR RESERVED --------------- */ | |||
| case CPU_INT_RSVD_07: | |||
| case CPU_INT_RSVD_08: | |||
| case CPU_INT_RSVD_09: | |||
| case CPU_INT_RSVD_10: | |||
| case CPU_INT_RSVD_13: | |||
| break; | |||
| /* ----------------- SYSTEM EXCEPTIONS ---------------- */ | |||
| case CPU_INT_RESET: /* Reset (see Note #2). */ | |||
| case CPU_INT_NMI: /* Non-maskable interrupt (see Note #2). */ | |||
| case CPU_INT_HFAULT: /* Hard fault (see Note #2). */ | |||
| case CPU_INT_MEM: /* Memory management (see Note #2). */ | |||
| case CPU_INT_SVCALL: /* SVCall (see Note #2). */ | |||
| case CPU_INT_DBGMON: /* Debug monitor (see Note #2). */ | |||
| case CPU_INT_PENDSV: /* PendSV (see Note #2). */ | |||
| case CPU_INT_BUSFAULT: /* Bus fault. */ | |||
| case CPU_INT_USAGEFAULT: /* Usage fault. */ | |||
| case CPU_INT_SYSTICK: /* SysTick. */ | |||
| break; | |||
| /* ---------------- EXTERNAL INTERRUPT ---------------- */ | |||
| default: | |||
| pos_max = CPU_INT_SRC_POS_MAX; | |||
| if (pos < pos_max) { /* See Note #3. */ | |||
| group = (pos - 16) / 32; | |||
| nbr = (pos - 16) % 32; | |||
| CPU_CRITICAL_ENTER(); | |||
| CPU_REG_NVIC_CLRPEND(group) = DEF_BIT(nbr); | |||
| CPU_CRITICAL_EXIT(); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU_IntSrcPrioSet() | |||
| * | |||
| * Description : Set priority of an interrupt source. | |||
| * | |||
| * Argument(s) : pos Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()'). | |||
| * | |||
| * prio Priority. Use a lower priority number for a higher priority. | |||
| * | |||
| * Return(s) : none. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) See 'CPU_IntSrcDis() Note #1'. | |||
| * | |||
| * (2) Several interrupts priorities CANNOT be set : | |||
| * | |||
| * (a) Reset (always -3). | |||
| * (b) NMI (always -2). | |||
| * (c) Hard fault (always -1). | |||
| * | |||
| * (3) See 'CPU_IntSrcDis() Note #3'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void CPU_IntSrcPrioSet (CPU_INT08U pos, | |||
| CPU_INT08U prio) | |||
| { | |||
| CPU_INT08U group; | |||
| CPU_INT08U nbr; | |||
| CPU_INT08U pos_max; | |||
| CPU_INT32U temp; | |||
| CPU_SR_ALLOC(); | |||
| switch (pos) { | |||
| case CPU_INT_STK_PTR: /* ---------------- INVALID OR RESERVED --------------- */ | |||
| case CPU_INT_RSVD_07: | |||
| case CPU_INT_RSVD_08: | |||
| case CPU_INT_RSVD_09: | |||
| case CPU_INT_RSVD_10: | |||
| case CPU_INT_RSVD_13: | |||
| break; | |||
| /* ----------------- SYSTEM EXCEPTIONS ---------------- */ | |||
| case CPU_INT_RESET: /* Reset (see Note #2). */ | |||
| case CPU_INT_NMI: /* Non-maskable interrupt (see Note #2). */ | |||
| case CPU_INT_HFAULT: /* Hard fault (see Note #2). */ | |||
| break; | |||
| case CPU_INT_MEM: /* Memory management. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI1; | |||
| temp &= ~(DEF_OCTET_MASK << (0 * DEF_OCTET_NBR_BITS)); | |||
| temp |= (prio << (0 * DEF_OCTET_NBR_BITS)); | |||
| CPU_REG_NVIC_SHPRI1 = temp; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_BUSFAULT: /* Bus fault. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI1; | |||
| temp &= ~(DEF_OCTET_MASK << (1 * DEF_OCTET_NBR_BITS)); | |||
| temp |= (prio << (1 * DEF_OCTET_NBR_BITS)); | |||
| CPU_REG_NVIC_SHPRI1 = temp; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_USAGEFAULT: /* Usage fault. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI1; | |||
| temp &= ~(DEF_OCTET_MASK << (2 * DEF_OCTET_NBR_BITS)); | |||
| temp |= (prio << (2 * DEF_OCTET_NBR_BITS)); | |||
| CPU_REG_NVIC_SHPRI1 = temp; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_SVCALL: /* SVCall. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI2; | |||
| temp &= ~((CPU_INT32U)DEF_OCTET_MASK << (3 * DEF_OCTET_NBR_BITS)); | |||
| temp |= (prio << (3 * DEF_OCTET_NBR_BITS)); | |||
| CPU_REG_NVIC_SHPRI2 = temp; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_DBGMON: /* Debug monitor. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI3; | |||
| temp &= ~(DEF_OCTET_MASK << (0 * DEF_OCTET_NBR_BITS)); | |||
| temp |= (prio << (0 * DEF_OCTET_NBR_BITS)); | |||
| CPU_REG_NVIC_SHPRI3 = temp; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_PENDSV: /* PendSV. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI3; | |||
| temp &= ~(DEF_OCTET_MASK << (2 * DEF_OCTET_NBR_BITS)); | |||
| temp |= (prio << (2 * DEF_OCTET_NBR_BITS)); | |||
| CPU_REG_NVIC_SHPRI3 = temp; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_SYSTICK: /* SysTick. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI3; | |||
| temp &= ~((CPU_INT32U)DEF_OCTET_MASK << (3 * DEF_OCTET_NBR_BITS)); | |||
| temp |= (prio << (3 * DEF_OCTET_NBR_BITS)); | |||
| CPU_REG_NVIC_SHPRI3 = temp; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| /* ---------------- EXTERNAL INTERRUPT ---------------- */ | |||
| default: | |||
| pos_max = CPU_INT_SRC_POS_MAX; | |||
| if (pos < pos_max) { /* See Note #3. */ | |||
| group = (pos - 16) / 4; | |||
| nbr = (pos - 16) % 4; | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_PRIO(group); | |||
| temp &= ~(DEF_OCTET_MASK << (nbr * DEF_OCTET_NBR_BITS)); | |||
| temp |= (prio << (nbr * DEF_OCTET_NBR_BITS)); | |||
| CPU_REG_NVIC_PRIO(group) = temp; | |||
| CPU_CRITICAL_EXIT(); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU_IntSrcPrioGet() | |||
| * | |||
| * Description : Get priority of an interrupt source. | |||
| * | |||
| * Argument(s) : pos Position of interrupt vector in interrupt table (see 'CPU_IntSrcDis()'). | |||
| * | |||
| * Return(s) : Priority of interrupt source. If the interrupt source specified is invalid, then | |||
| * DEF_INT_16S_MIN_VAL is returned. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) See 'CPU_IntSrcDis() Note #1'. | |||
| * | |||
| * (2) See 'CPU_IntSrcPrioSet() Note #2'. | |||
| * | |||
| * (3) See 'CPU_IntSrcDis() Note #3'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_INT16S CPU_IntSrcPrioGet (CPU_INT08U pos) | |||
| { | |||
| CPU_INT08U group; | |||
| CPU_INT08U nbr; | |||
| CPU_INT08U pos_max; | |||
| CPU_INT16S prio; | |||
| CPU_INT32U temp; | |||
| CPU_SR_ALLOC(); | |||
| switch (pos) { | |||
| case CPU_INT_STK_PTR: /* ---------------- INVALID OR RESERVED --------------- */ | |||
| case CPU_INT_RSVD_07: | |||
| case CPU_INT_RSVD_08: | |||
| case CPU_INT_RSVD_09: | |||
| case CPU_INT_RSVD_10: | |||
| case CPU_INT_RSVD_13: | |||
| prio = DEF_INT_16S_MIN_VAL; | |||
| break; | |||
| /* ----------------- SYSTEM EXCEPTIONS ---------------- */ | |||
| case CPU_INT_RESET: /* Reset (see Note #2). */ | |||
| prio = -3; | |||
| break; | |||
| case CPU_INT_NMI: /* Non-maskable interrupt (see Note #2). */ | |||
| prio = -2; | |||
| break; | |||
| case CPU_INT_HFAULT: /* Hard fault (see Note #2). */ | |||
| prio = -1; | |||
| break; | |||
| case CPU_INT_MEM: /* Memory management. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI1; | |||
| prio = (temp >> (0 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_BUSFAULT: /* Bus fault. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI1; | |||
| prio = (temp >> (1 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_USAGEFAULT: /* Usage fault. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI1; | |||
| prio = (temp >> (2 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_SVCALL: /* SVCall. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI2; | |||
| prio = (temp >> (3 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_DBGMON: /* Debug monitor. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI3; | |||
| prio = (temp >> (0 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_PENDSV: /* PendSV. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI3; | |||
| prio = (temp >> (2 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| case CPU_INT_SYSTICK: /* SysTick. */ | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_SHPRI3; | |||
| prio = (temp >> (3 * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK; | |||
| CPU_CRITICAL_EXIT(); | |||
| break; | |||
| /* ---------------- EXTERNAL INTERRUPT ---------------- */ | |||
| default: | |||
| pos_max = CPU_INT_SRC_POS_MAX; | |||
| if (pos < pos_max) { /* See Note #3. */ | |||
| group = (pos - 16) / 4; | |||
| nbr = (pos - 16) % 4; | |||
| CPU_CRITICAL_ENTER(); | |||
| temp = CPU_REG_NVIC_PRIO(group); | |||
| CPU_CRITICAL_EXIT(); | |||
| prio = (temp >> (nbr * DEF_OCTET_NBR_BITS)) & DEF_OCTET_MASK; | |||
| } else { | |||
| prio = DEF_INT_16S_MIN_VAL; | |||
| } | |||
| break; | |||
| } | |||
| return (prio); | |||
| } | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,220 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/CPU | |||
| * CPU CONFIGURATION & PORT LAYER | |||
| * | |||
| * (c) Copyright 2004-2015; Micrium, Inc.; Weston, FL | |||
| * | |||
| * All rights reserved. Protected by international copyright laws. | |||
| * | |||
| * uC/CPU is provided in source form to registered licensees ONLY. It is | |||
| * illegal to distribute this source code to any third party unless you receive | |||
| * written permission by an authorized Micrium representative. Knowledge of | |||
| * the source code may NOT be used to develop a similar product. | |||
| * | |||
| * Please help us continue to provide the Embedded community with the finest | |||
| * software available. Your honesty is greatly appreciated. | |||
| * | |||
| * You can find our product's user manual, API reference, release notes and | |||
| * more information at https://doc.micrium.com. | |||
| * You can contact us at www.micrium.com. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * | |||
| * CPU CONFIGURATION DEFINES | |||
| * | |||
| * Filename : cpu_def.h | |||
| * Version : V1.30.02 | |||
| * Programmer(s) : ITJ | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MODULE | |||
| * | |||
| * Note(s) : (1) This CPU definition header file is protected from multiple pre-processor inclusion | |||
| * through use of the CPU definition module present pre-processor macro definition. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #ifndef CPU_DEF_MODULE_PRESENT | |||
| #define CPU_DEF_MODULE_PRESENT | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CORE CPU MODULE VERSION NUMBER | |||
| * | |||
| * Note(s) : (1) (a) The core CPU module software version is denoted as follows : | |||
| * | |||
| * Vx.yy.zz | |||
| * | |||
| * where | |||
| * V denotes 'Version' label | |||
| * x denotes major software version revision number | |||
| * yy denotes minor software version revision number | |||
| * zz denotes sub-minor software version revision number | |||
| * | |||
| * (b) The software version label #define is formatted as follows : | |||
| * | |||
| * ver = x.yyzz * 100 * 100 | |||
| * | |||
| * where | |||
| * ver denotes software version number scaled as an integer value | |||
| * x.yyzz denotes software version number, where the unscaled integer | |||
| * portion denotes the major version number & the unscaled | |||
| * fractional portion denotes the (concatenated) minor | |||
| * version numbers | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define CPU_CORE_VERSION 13002u /* See Note #1. */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU WORD CONFIGURATION | |||
| * | |||
| * Note(s) : (1) Configure CPU_CFG_ADDR_SIZE & CPU_CFG_DATA_SIZE in 'cpu.h' with CPU's word sizes : | |||
| * | |||
| * CPU_WORD_SIZE_08 8-bit word size | |||
| * CPU_WORD_SIZE_16 16-bit word size | |||
| * CPU_WORD_SIZE_32 32-bit word size | |||
| * CPU_WORD_SIZE_64 64-bit word size | |||
| * | |||
| * (2) Configure CPU_CFG_ENDIAN_TYPE in 'cpu.h' with CPU's data-word-memory order : | |||
| * | |||
| * (a) CPU_ENDIAN_TYPE_BIG Big- endian word order (CPU words' most significant | |||
| * octet @ lowest memory address) | |||
| * (b) CPU_ENDIAN_TYPE_LITTLE Little-endian word order (CPU words' least significant | |||
| * octet @ lowest memory address) | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* ---------------------- CPU WORD SIZE ----------------------- */ | |||
| #define CPU_WORD_SIZE_08 1u /* 8-bit word size (in octets). */ | |||
| #define CPU_WORD_SIZE_16 2u /* 16-bit word size (in octets). */ | |||
| #define CPU_WORD_SIZE_32 4u /* 32-bit word size (in octets). */ | |||
| #define CPU_WORD_SIZE_64 8u /* 64-bit word size (in octets). */ | |||
| /* ------------------ CPU WORD-ENDIAN ORDER ------------------- */ | |||
| #define CPU_ENDIAN_TYPE_NONE 0u | |||
| #define CPU_ENDIAN_TYPE_BIG 1u /* Big- endian word order (see Note #1a). */ | |||
| #define CPU_ENDIAN_TYPE_LITTLE 2u /* Little-endian word order (see Note #1b). */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CPU STACK CONFIGURATION | |||
| * | |||
| * Note(s) : (1) Configure CPU_CFG_STK_GROWTH in 'cpu.h' with CPU's stack growth order : | |||
| * | |||
| * (a) CPU_STK_GROWTH_LO_TO_HI CPU stack pointer increments to the next higher stack | |||
| * memory address after data is pushed onto the stack | |||
| * (b) CPU_STK_GROWTH_HI_TO_LO CPU stack pointer decrements to the next lower stack | |||
| * memory address after data is pushed onto the stack | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* ------------------ CPU STACK GROWTH ORDER ------------------ */ | |||
| #define CPU_STK_GROWTH_NONE 0u | |||
| #define CPU_STK_GROWTH_LO_TO_HI 1u /* CPU stk incs towards higher mem addrs (see Note #1a). */ | |||
| #define CPU_STK_GROWTH_HI_TO_LO 2u /* CPU stk decs towards lower mem addrs (see Note #1b). */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CRITICAL SECTION CONFIGURATION | |||
| * | |||
| * Note(s) : (1) Configure CPU_CFG_CRITICAL_METHOD with CPU's/compiler's critical section method : | |||
| * | |||
| * Enter/Exit critical sections by ... | |||
| * | |||
| * CPU_CRITICAL_METHOD_INT_DIS_EN Disable/Enable interrupts | |||
| * CPU_CRITICAL_METHOD_STATUS_STK Push/Pop interrupt status onto stack | |||
| * CPU_CRITICAL_METHOD_STATUS_LOCAL Save/Restore interrupt status to local variable | |||
| * | |||
| * (a) CPU_CRITICAL_METHOD_INT_DIS_EN is NOT a preferred method since it does NOT support | |||
| * multiple levels of interrupts. However, with some CPUs/compilers, this is the only | |||
| * available method. | |||
| * | |||
| * (b) CPU_CRITICAL_METHOD_STATUS_STK is one preferred method since it supports multiple | |||
| * levels of interrupts. However, this method assumes that the compiler provides C-level | |||
| * &/or assembly-level functionality for the following : | |||
| * | |||
| * ENTER CRITICAL SECTION : | |||
| * (1) Push/save interrupt status onto a local stack | |||
| * (2) Disable interrupts | |||
| * | |||
| * EXIT CRITICAL SECTION : | |||
| * (3) Pop/restore interrupt status from a local stack | |||
| * | |||
| * (c) CPU_CRITICAL_METHOD_STATUS_LOCAL is one preferred method since it supports multiple | |||
| * levels of interrupts. However, this method assumes that the compiler provides C-level | |||
| * &/or assembly-level functionality for the following : | |||
| * | |||
| * ENTER CRITICAL SECTION : | |||
| * (1) Save interrupt status into a local variable | |||
| * (2) Disable interrupts | |||
| * | |||
| * EXIT CRITICAL SECTION : | |||
| * (3) Restore interrupt status from a local variable | |||
| * | |||
| * (2) Critical section macro's most likely require inline assembly. If the compiler does NOT | |||
| * allow inline assembly in C source files, critical section macro's MUST call an assembly | |||
| * subroutine defined in a 'cpu_a.asm' file located in the following software directory : | |||
| * | |||
| * \<CPU-Compiler Directory>\<cpu>\<compiler>\ | |||
| * | |||
| * where | |||
| * <CPU-Compiler Directory> directory path for common CPU-compiler software | |||
| * <cpu> directory name for specific CPU | |||
| * <compiler> directory name for specific compiler | |||
| * | |||
| * (3) (a) To save/restore interrupt status, a local variable 'cpu_sr' of type 'CPU_SR' MAY need | |||
| * to be declared (e.g. if 'CPU_CRITICAL_METHOD_STATUS_LOCAL' method is configured). | |||
| * | |||
| * (1) 'cpu_sr' local variable SHOULD be declared via the CPU_SR_ALLOC() macro which, | |||
| * if used, MUST be declared following ALL other local variables (see any 'cpu.h | |||
| * CRITICAL SECTION CONFIGURATION Note #3a1'). | |||
| * | |||
| * Example : | |||
| * | |||
| * void Fnct (void) | |||
| * { | |||
| * CPU_INT08U val_08; | |||
| * CPU_INT16U val_16; | |||
| * CPU_INT32U val_32; | |||
| * CPU_SR_ALLOC(); MUST be declared after ALL other local variables | |||
| * : | |||
| * : | |||
| * } | |||
| * | |||
| * (b) Configure 'CPU_SR' data type with the appropriate-sized CPU data type large enough to | |||
| * completely store the CPU's/compiler's status word. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* --------------- CPU CRITICAL SECTION METHODS --------------- */ | |||
| #define CPU_CRITICAL_METHOD_NONE 0u /* */ | |||
| #define CPU_CRITICAL_METHOD_INT_DIS_EN 1u /* DIS/EN ints (see Note #1a). */ | |||
| #define CPU_CRITICAL_METHOD_STATUS_STK 2u /* Push/Pop int status onto stk (see Note #1b). */ | |||
| #define CPU_CRITICAL_METHOD_STATUS_LOCAL 3u /* Save/Restore int status to local var (see Note #1c). */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MODULE END | |||
| * | |||
| * Note(s) : (1) See 'cpu_def.h MODULE'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #endif /* End of CPU def module include. */ | |||
| @@ -0,0 +1,309 @@ | |||
| @******************************************************************************************************** | |||
| @ uC/LIB | |||
| @ CUSTOM LIBRARY MODULES | |||
| @ | |||
| @ (c) Copyright 2004-2011; Micrium, Inc.; Weston, FL | |||
| @ | |||
| @ All rights reserved. Protected by international copyright laws. | |||
| @ | |||
| @ uC/LIB is provided in source form to registered licensees ONLY. It is | |||
| @ illegal to distribute this source code to any third party unless you receive | |||
| @ written permission by an authorized Micrium representative. Knowledge of | |||
| @ the source code may NOT be used to develop a similar product. | |||
| @ | |||
| @ Please help us continue to provide the Embedded community with the finest | |||
| @ software available. Your honesty is greatly appreciated. | |||
| @ | |||
| @ You can contact us at www.micrium.com. | |||
| @******************************************************************************************************** | |||
| @******************************************************************************************************** | |||
| @ | |||
| @ STANDARD MEMORY OPERATIONS | |||
| @ | |||
| @ ARM-Cortex-M4 | |||
| @ GNU Compiler | |||
| @ | |||
| @ Filename : lib_mem_a.s | |||
| @ Version : V1.38.01.00 | |||
| @ Programmer(s) : JDH | |||
| @ DC | |||
| @******************************************************************************************************** | |||
| @ Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software. | |||
| @ | |||
| @ (a) ALL standard library functions are implemented in the custom library modules : | |||
| @ | |||
| @ (1) \<Custom Library Directory>\lib*.* | |||
| @ | |||
| @ (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.* | |||
| @ | |||
| @ where | |||
| @ <Custom Library Directory> directory path for custom library software | |||
| @ <cpu> directory name for specific processor (CPU) | |||
| @ <compiler> directory name for specific compiler | |||
| @ | |||
| @ (b) Product-specific library functions are implemented in individual products. | |||
| @ | |||
| @ (2) Assumes ARM CPU mode configured for Little Endian. | |||
| @******************************************************************************************************** | |||
| @******************************************************************************************************** | |||
| @ PUBLIC FUNCTIONS | |||
| @******************************************************************************************************** | |||
| .global Mem_Copy | |||
| @******************************************************************************************************** | |||
| @ CODE GENERATION DIRECTIVES | |||
| @******************************************************************************************************** | |||
| .text | |||
| .align 2 | |||
| .thumb | |||
| .syntax unified | |||
| @$PAGE | |||
| @******************************************************************************************************** | |||
| @ Mem_Copy() | |||
| @ | |||
| @ Description : Copy data octets from one buffer to another buffer. | |||
| @ | |||
| @ Argument(s) : pdest Pointer to destination memory buffer. | |||
| @ | |||
| @ psrc Pointer to source memory buffer. | |||
| @ | |||
| @ size Number of data buffer octets to copy. | |||
| @ | |||
| @ Return(s) : none. | |||
| @ | |||
| @ Caller(s) : Application. | |||
| @ | |||
| @ Note(s) : (1) Null copies allowed (i.e. 0-octet size). | |||
| @ | |||
| @ (2) Memory buffers NOT checked for overlapping. | |||
| @ | |||
| @ (3) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN' | |||
| @ address boundary. | |||
| @ | |||
| @ (4) ARM Cortex-M3 processors use a subset of the ARM Thumb-2 instruction set which does | |||
| @ NOT support 16-bit conditional branch instructions but ONLY supports 8-bit conditional | |||
| @ branch instructions. | |||
| @ | |||
| @ Therefore, branches exceeding 8-bit, signed, relative offsets : | |||
| @ | |||
| @ (a) CANNOT be implemented with conditional branches@ but ... | |||
| @ (b) MUST be implemented with non-conditional branches. | |||
| @******************************************************************************************************** | |||
| @ void Mem_Copy (void *pdest, @ ==> R0 | |||
| @ void *psrc, @ ==> R1 | |||
| @ CPU_SIZE_T size) @ ==> R2 | |||
| .thumb_func | |||
| Mem_Copy: | |||
| CMP R0, #0 | |||
| BNE Mem_Copy_1 | |||
| BX LR @ return if pdest == NULL | |||
| Mem_Copy_1: | |||
| CMP R1, #0 | |||
| BNE Mem_Copy_2 | |||
| BX LR @ return if psrc == NULL | |||
| Mem_Copy_2: | |||
| CMP R2, #0 | |||
| BNE Mem_Copy_3 | |||
| BX LR @ return if size == 0 | |||
| Mem_Copy_3: | |||
| STMFD SP!, {R3-R12} @ save registers on stack | |||
| @$PAGE | |||
| Chk_Align_32: @ check if both dest & src 32-bit aligned | |||
| AND R3, R0, #0x03 | |||
| AND R4, R1, #0x03 | |||
| CMP R3, R4 | |||
| BNE Chk_Align_16 @ not 32-bit aligned, check for 16-bit alignment | |||
| RSB R3, R3, #0x04 @ compute 1-2-3 pre-copy bytes (to align to the next 32-bit boundary) | |||
| AND R3, R3, #0x03 | |||
| Pre_Copy_1: | |||
| CMP R3, #1 @ copy 1-2-3 bytes (to align to the next 32-bit boundary) | |||
| BCC Copy_32_1 @ start real 32-bit copy | |||
| CMP R2, #1 @ check if any more data to copy | |||
| BCS Pre_Copy_1_Cont | |||
| B Mem_Copy_END @ no more data to copy (see Note #4b) | |||
| Pre_Copy_1_Cont: | |||
| LDRB R4, [R1], #1 | |||
| STRB R4, [R0], #1 | |||
| SUB R3, R3, #1 | |||
| SUB R2, R2, #1 | |||
| B Pre_Copy_1 | |||
| Chk_Align_16: @ check if both dest & src 16-bit aligned | |||
| AND R3, R0, #0x01 | |||
| AND R4, R1, #0x01 | |||
| CMP R3, R4 | |||
| BEQ Pre_Copy_2 | |||
| B Copy_08_1 @ not 16-bit aligned, start 8-bit copy (see Note #4b) | |||
| Pre_Copy_2: | |||
| CMP R3, #1 @ copy 1 byte (to align to the next 16-bit boundary) | |||
| BCC Copy_16_1 @ start real 16-bit copy | |||
| LDRB R4, [R1], #1 | |||
| STRB R4, [R0], #1 | |||
| SUB R3, R3, #1 | |||
| SUB R2, R2, #1 | |||
| B Pre_Copy_2 | |||
| Copy_32_1: | |||
| CMP R2, #360 @ Copy 9 chunks of 10 32-bit words (360 octets per loop) | |||
| BCC Copy_32_2 | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| SUB R2, R2, #360 | |||
| B Copy_32_1 | |||
| Copy_32_2: | |||
| CMP R2, #(04*10*01) @ Copy chunks of 10 32-bit words (40 octets per loop) | |||
| BCC Copy_32_3 | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| SUB R2, R2, #(04*10*01) | |||
| B Copy_32_2 | |||
| Copy_32_3: | |||
| CMP R2, #(04*01*01) @ Copy remaining 32-bit words | |||
| BCC Copy_16_1 | |||
| LDR R3, [R1], #4 | |||
| STR R3, [R0], #4 | |||
| SUB R2, R2, #(04*01*01) | |||
| B Copy_32_3 | |||
| @$PAGE | |||
| Copy_16_1: | |||
| CMP R2, #(02*01*16) @ Copy chunks of 16 16-bit words (32 bytes per loop) | |||
| BCC Copy_16_2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| SUB R2, R2, #(02*01*16) | |||
| B Copy_16_1 | |||
| Copy_16_2: | |||
| CMP R2, #(02*01*01) @ Copy remaining 16-bit words | |||
| BCC Copy_08_1 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| SUB R2, R2, #(02*01*01) | |||
| B Copy_16_2 | |||
| @$PAGE | |||
| Copy_08_1: | |||
| CMP R2, #(01*01*16) @ Copy chunks of 16 8-bit words (16 bytes per loop) | |||
| BCC Copy_08_2 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| SUB R2, R2, #(01*01*16) | |||
| B Copy_08_1 | |||
| Copy_08_2: | |||
| CMP R2, #(01*01*01) @ Copy remaining 8-bit words | |||
| BCC Mem_Copy_END | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| SUB R2, R2, #(01*01*01) | |||
| B Copy_08_2 | |||
| Mem_Copy_END: | |||
| LDMFD SP!, {R3-R12} @ restore registers from stack | |||
| BX LR @ return | |||
| .end | |||
| @@ -0,0 +1,306 @@ | |||
| ;******************************************************************************************************** | |||
| ; uC/LIB | |||
| ; CUSTOM LIBRARY MODULES | |||
| ; | |||
| ; (c) Copyright 2004-2011; Micrium, Inc.; Weston, FL | |||
| ; | |||
| ; All rights reserved. Protected by international copyright laws. | |||
| ; | |||
| ; uC/LIB is provided in source form to registered licensees ONLY. It is | |||
| ; illegal to distribute this source code to any third party unless you receive | |||
| ; written permission by an authorized Micrium representative. Knowledge of | |||
| ; the source code may NOT be used to develop a similar product. | |||
| ; | |||
| ; Please help us continue to provide the Embedded community with the finest | |||
| ; software available. Your honesty is greatly appreciated. | |||
| ; | |||
| ; You can contact us at www.micrium.com. | |||
| ;******************************************************************************************************** | |||
| ;******************************************************************************************************** | |||
| ; | |||
| ; STANDARD MEMORY OPERATIONS | |||
| ; | |||
| ; ARM-Cortex-M4 | |||
| ; IAR Compiler | |||
| ; | |||
| ; Filename : lib_mem_a.asm | |||
| ; Version : V1.38.01.00 | |||
| ; Programmer(s) : JDH | |||
| ; BAN | |||
| ;******************************************************************************************************** | |||
| ; Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software. | |||
| ; | |||
| ; (a) ALL standard library functions are implemented in the custom library modules : | |||
| ; | |||
| ; (1) \<Custom Library Directory>\lib*.* | |||
| ; | |||
| ; (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.* | |||
| ; | |||
| ; where | |||
| ; <Custom Library Directory> directory path for custom library software | |||
| ; <cpu> directory name for specific processor (CPU) | |||
| ; <compiler> directory name for specific compiler | |||
| ; | |||
| ; (b) Product-specific library functions are implemented in individual products. | |||
| ; | |||
| ; (2) Assumes ARM CPU mode configured for Little Endian. | |||
| ;******************************************************************************************************** | |||
| ;******************************************************************************************************** | |||
| ; PUBLIC FUNCTIONS | |||
| ;******************************************************************************************************** | |||
| PUBLIC Mem_Copy | |||
| ;******************************************************************************************************** | |||
| ; CODE GENERATION DIRECTIVES | |||
| ;******************************************************************************************************** | |||
| RSEG CODE:CODE:NOROOT(2) | |||
| ;$PAGE | |||
| ;******************************************************************************************************** | |||
| ; Mem_Copy() | |||
| ; | |||
| ; Description : Copy data octets from one buffer to another buffer. | |||
| ; | |||
| ; Argument(s) : pdest Pointer to destination memory buffer. | |||
| ; | |||
| ; psrc Pointer to source memory buffer. | |||
| ; | |||
| ; size Number of data buffer octets to copy. | |||
| ; | |||
| ; Return(s) : none. | |||
| ; | |||
| ; Caller(s) : Application. | |||
| ; | |||
| ; Note(s) : (1) Null copies allowed (i.e. 0-octet size). | |||
| ; | |||
| ; (2) Memory buffers NOT checked for overlapping. | |||
| ; | |||
| ; (3) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN' | |||
| ; address boundary. | |||
| ; | |||
| ; (4) ARM Cortex-M3 processors use a subset of the ARM Thumb-2 instruction set which does | |||
| ; NOT support 16-bit conditional branch instructions but ONLY supports 8-bit conditional | |||
| ; branch instructions. | |||
| ; | |||
| ; Therefore, branches exceeding 8-bit, signed, relative offsets : | |||
| ; | |||
| ; (a) CANNOT be implemented with conditional branches; but ... | |||
| ; (b) MUST be implemented with non-conditional branches. | |||
| ;******************************************************************************************************** | |||
| ; void Mem_Copy (void *pdest, ; ==> R0 | |||
| ; void *psrc, ; ==> R1 | |||
| ; CPU_SIZE_T size) ; ==> R2 | |||
| Mem_Copy: | |||
| CMP R0, #0 | |||
| BNE Mem_Copy_1 | |||
| BX LR ; return if pdest == NULL | |||
| Mem_Copy_1: | |||
| CMP R1, #0 | |||
| BNE Mem_Copy_2 | |||
| BX LR ; return if psrc == NULL | |||
| Mem_Copy_2: | |||
| CMP R2, #0 | |||
| BNE Mem_Copy_3 | |||
| BX LR ; return if size == 0 | |||
| Mem_Copy_3: | |||
| STMFD SP!, {R3-R12} ; save registers on stack | |||
| ;$PAGE | |||
| Chk_Align_32: ; check if both dest & src 32-bit aligned | |||
| AND R3, R0, #0x03 | |||
| AND R4, R1, #0x03 | |||
| CMP R3, R4 | |||
| BNE Chk_Align_16 ; not 32-bit aligned, check for 16-bit alignment | |||
| RSB R3, R3, #0x04 ; compute 1-2-3 pre-copy bytes (to align to the next 32-bit boundary) | |||
| AND R3, R3, #0x03 | |||
| Pre_Copy_1: | |||
| CMP R3, #1 ; copy 1-2-3 bytes (to align to the next 32-bit boundary) | |||
| BCC Copy_32_1 ; start real 32-bit copy | |||
| CMP R2, #1 ; check if any more data to copy | |||
| BCS Pre_Copy_1_Cont | |||
| B Mem_Copy_END ; no more data to copy (see Note #4b) | |||
| Pre_Copy_1_Cont: | |||
| LDRB R4, [R1], #1 | |||
| STRB R4, [R0], #1 | |||
| SUB R3, R3, #1 | |||
| SUB R2, R2, #1 | |||
| B Pre_Copy_1 | |||
| Chk_Align_16: ; check if both dest & src 16-bit aligned | |||
| AND R3, R0, #0x01 | |||
| AND R4, R1, #0x01 | |||
| CMP R3, R4 | |||
| BEQ Pre_Copy_2 | |||
| B Copy_08_1 ; not 16-bit aligned, start 8-bit copy (see Note #4b) | |||
| Pre_Copy_2: | |||
| CMP R3, #1 ; copy 1 byte (to align to the next 16-bit boundary) | |||
| BCC Copy_16_1 ; start real 16-bit copy | |||
| LDRB R4, [R1], #1 | |||
| STRB R4, [R0], #1 | |||
| SUB R3, R3, #1 | |||
| SUB R2, R2, #1 | |||
| B Pre_Copy_2 | |||
| Copy_32_1: | |||
| CMP R2, #(04*10*09) ; Copy 9 chunks of 10 32-bit words (360 octets per loop) | |||
| BCC Copy_32_2 | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| SUB R2, R2, #(04*10*09) | |||
| B Copy_32_1 | |||
| Copy_32_2: | |||
| CMP R2, #(04*10*01) ; Copy chunks of 10 32-bit words (40 octets per loop) | |||
| BCC Copy_32_3 | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| SUB R2, R2, #(04*10*01) | |||
| B Copy_32_2 | |||
| Copy_32_3: | |||
| CMP R2, #(04*01*01) ; Copy remaining 32-bit words | |||
| BCC Copy_16_1 | |||
| LDR R3, [R1], #4 | |||
| STR R3, [R0], #4 | |||
| SUB R2, R2, #(04*01*01) | |||
| B Copy_32_3 | |||
| ;$PAGE | |||
| Copy_16_1: | |||
| CMP R2, #(02*01*16) ; Copy chunks of 16 16-bit words (32 bytes per loop) | |||
| BCC Copy_16_2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| SUB R2, R2, #(02*01*16) | |||
| B Copy_16_1 | |||
| Copy_16_2: | |||
| CMP R2, #(02*01*01) ; Copy remaining 16-bit words | |||
| BCC Copy_08_1 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| SUB R2, R2, #(02*01*01) | |||
| B Copy_16_2 | |||
| ;$PAGE | |||
| Copy_08_1: | |||
| CMP R2, #(01*01*16) ; Copy chunks of 16 8-bit words (16 bytes per loop) | |||
| BCC Copy_08_2 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| SUB R2, R2, #(01*01*16) | |||
| B Copy_08_1 | |||
| Copy_08_2: | |||
| CMP R2, #(01*01*01) ; Copy remaining 8-bit words | |||
| BCC Mem_Copy_END | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| SUB R2, R2, #(01*01*01) | |||
| B Copy_08_2 | |||
| Mem_Copy_END: | |||
| LDMFD SP!, {R3-R12} ; restore registers from stack | |||
| BX LR ; return | |||
| END | |||
| @@ -0,0 +1,312 @@ | |||
| ;******************************************************************************************************** | |||
| ; uC/LIB | |||
| ; CUSTOM LIBRARY MODULES | |||
| ; | |||
| ; (c) Copyright 2004-2011; Micrium, Inc.; Weston, FL | |||
| ; | |||
| ; All rights reserved. Protected by international copyright laws. | |||
| ; | |||
| ; uC/LIB is provided in source form to registered licensees ONLY. It is | |||
| ; illegal to distribute this source code to any third party unless you receive | |||
| ; written permission by an authorized Micrium representative. Knowledge of | |||
| ; the source code may NOT be used to develop a similar product. | |||
| ; | |||
| ; Please help us continue to provide the Embedded community with the finest | |||
| ; software available. Your honesty is greatly appreciated. | |||
| ; | |||
| ; You can contact us at www.micrium.com. | |||
| ;******************************************************************************************************** | |||
| ;******************************************************************************************************** | |||
| ; | |||
| ; STANDARD MEMORY OPERATIONS | |||
| ; | |||
| ; ARM-Cortex-M4 | |||
| ; RealView Development Suite | |||
| ; RealView Microcontroller Development Kit (MDK) | |||
| ; ARM Developer Suite (ADS) | |||
| ; Keil uVision | |||
| ; | |||
| ; Filename : lib_mem_a.asm | |||
| ; Version : V1.38.01.00 | |||
| ; Programmer(s) : JDH | |||
| ; BAN | |||
| ;******************************************************************************************************** | |||
| ; Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software. | |||
| ; | |||
| ; (a) ALL standard library functions are implemented in the custom library modules : | |||
| ; | |||
| ; (1) \<Custom Library Directory>\lib*.* | |||
| ; | |||
| ; (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.* | |||
| ; | |||
| ; where | |||
| ; <Custom Library Directory> directory path for custom library software | |||
| ; <cpu> directory name for specific processor (CPU) | |||
| ; <compiler> directory name for specific compiler | |||
| ; | |||
| ; (b) Product-specific library functions are implemented in individual products. | |||
| ; | |||
| ; (2) Assumes ARM CPU mode configured for Little Endian. | |||
| ;******************************************************************************************************** | |||
| ;******************************************************************************************************** | |||
| ; PUBLIC FUNCTIONS | |||
| ;******************************************************************************************************** | |||
| EXPORT Mem_Copy | |||
| ;******************************************************************************************************** | |||
| ; CODE GENERATION DIRECTIVES | |||
| ;******************************************************************************************************** | |||
| AREA |.text|, CODE, READONLY, ALIGN=2 | |||
| THUMB | |||
| REQUIRE8 | |||
| PRESERVE8 | |||
| ;$PAGE | |||
| ;******************************************************************************************************** | |||
| ; Mem_Copy() | |||
| ; | |||
| ; Description : Copy data octets from one buffer to another buffer. | |||
| ; | |||
| ; Argument(s) : pdest Pointer to destination memory buffer. | |||
| ; | |||
| ; psrc Pointer to source memory buffer. | |||
| ; | |||
| ; size Number of data buffer octets to copy. | |||
| ; | |||
| ; Return(s) : none. | |||
| ; | |||
| ; Caller(s) : Application. | |||
| ; | |||
| ; Note(s) : (1) Null copies allowed (i.e. 0-octet size). | |||
| ; | |||
| ; (2) Memory buffers NOT checked for overlapping. | |||
| ; | |||
| ; (3) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN' | |||
| ; address boundary. | |||
| ; | |||
| ; (4) ARM Cortex-M3 processors use a subset of the ARM Thumb-2 instruction set which does | |||
| ; NOT support 16-bit conditional branch instructions but ONLY supports 8-bit conditional | |||
| ; branch instructions. | |||
| ; | |||
| ; Therefore, branches exceeding 8-bit, signed, relative offsets : | |||
| ; | |||
| ; (a) CANNOT be implemented with conditional branches; but ... | |||
| ; (b) MUST be implemented with non-conditional branches. | |||
| ;******************************************************************************************************** | |||
| ; void Mem_Copy (void *pdest, ; ==> R0 | |||
| ; void *psrc, ; ==> R1 | |||
| ; CPU_SIZE_T size) ; ==> R2 | |||
| Mem_Copy | |||
| CMP R0, #0 | |||
| BNE Mem_Copy_1 | |||
| BX LR ; return if pdest == NULL | |||
| Mem_Copy_1 | |||
| CMP R1, #0 | |||
| BNE Mem_Copy_2 | |||
| BX LR ; return if psrc == NULL | |||
| Mem_Copy_2 | |||
| CMP R2, #0 | |||
| BNE Mem_Copy_3 | |||
| BX LR ; return if size == 0 | |||
| Mem_Copy_3 | |||
| STMFD SP!, {R3-R12} ; save registers on stack | |||
| ;$PAGE | |||
| Chk_Align_32 ; check if both dest & src 32-bit aligned | |||
| AND R3, R0, #0x03 | |||
| AND R4, R1, #0x03 | |||
| CMP R3, R4 | |||
| BNE Chk_Align_16 ; not 32-bit aligned, check for 16-bit alignment | |||
| RSB R3, R3, #0x04 ; compute 1-2-3 pre-copy bytes (to align to the next 32-bit boundary) | |||
| AND R3, R3, #0x03 | |||
| Pre_Copy_1 | |||
| CMP R3, #1 ; copy 1-2-3 bytes (to align to the next 32-bit boundary) | |||
| BCC Copy_32_1 ; start real 32-bit copy | |||
| CMP R2, #1 ; check if any more data to copy | |||
| BCS Pre_Copy_1_Cont | |||
| B Mem_Copy_END ; no more data to copy (see Note #4b) | |||
| Pre_Copy_1_Cont | |||
| LDRB R4, [R1], #1 | |||
| STRB R4, [R0], #1 | |||
| SUB R3, R3, #1 | |||
| SUB R2, R2, #1 | |||
| B Pre_Copy_1 | |||
| Chk_Align_16 ; check if both dest & src 16-bit aligned | |||
| AND R3, R0, #0x01 | |||
| AND R4, R1, #0x01 | |||
| CMP R3, R4 | |||
| BEQ Pre_Copy_2 | |||
| B Copy_08_1 ; not 16-bit aligned, start 8-bit copy (see Note #4b) | |||
| Pre_Copy_2 | |||
| CMP R3, #1 ; copy 1 byte (to align to the next 16-bit boundary) | |||
| BCC Copy_16_1 ; start real 16-bit copy | |||
| LDRB R4, [R1], #1 | |||
| STRB R4, [R0], #1 | |||
| SUB R3, R3, #1 | |||
| SUB R2, R2, #1 | |||
| B Pre_Copy_2 | |||
| Copy_32_1 | |||
| CMP R2, #(04*10*09) ; Copy 9 chunks of 10 32-bit words (360 octets per loop) | |||
| BCC Copy_32_2 | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| SUB R2, R2, #(04*10*09) | |||
| B Copy_32_1 | |||
| Copy_32_2 | |||
| CMP R2, #(04*10*01) ; Copy chunks of 10 32-bit words (40 octets per loop) | |||
| BCC Copy_32_3 | |||
| LDMIA R1!, {R3-R12} | |||
| STMIA R0!, {R3-R12} | |||
| SUB R2, R2, #(04*10*01) | |||
| B Copy_32_2 | |||
| Copy_32_3 | |||
| CMP R2, #(04*01*01) ; Copy remaining 32-bit words | |||
| BCC Copy_16_1 | |||
| LDR R3, [R1], #4 | |||
| STR R3, [R0], #4 | |||
| SUB R2, R2, #(04*01*01) | |||
| B Copy_32_3 | |||
| ;$PAGE | |||
| Copy_16_1 | |||
| CMP R2, #(02*01*16) ; Copy chunks of 16 16-bit words (32 bytes per loop) | |||
| BCC Copy_16_2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| SUB R2, R2, #(02*01*16) | |||
| B Copy_16_1 | |||
| Copy_16_2 | |||
| CMP R2, #(02*01*01) ; Copy remaining 16-bit words | |||
| BCC Copy_08_1 | |||
| LDRH R3, [R1], #2 | |||
| STRH R3, [R0], #2 | |||
| SUB R2, R2, #(02*01*01) | |||
| B Copy_16_2 | |||
| ;$PAGE | |||
| Copy_08_1 | |||
| CMP R2, #(01*01*16) ; Copy chunks of 16 8-bit words (16 bytes per loop) | |||
| BCC Copy_08_2 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| SUB R2, R2, #(01*01*16) | |||
| B Copy_08_1 | |||
| Copy_08_2 | |||
| CMP R2, #(01*01*01) ; Copy remaining 8-bit words | |||
| BCC Mem_Copy_END | |||
| LDRB R3, [R1], #1 | |||
| STRB R3, [R0], #1 | |||
| SUB R2, R2, #(01*01*01) | |||
| B Copy_08_2 | |||
| Mem_Copy_END | |||
| LDMFD SP!, {R3-R12} ; restore registers from stack | |||
| BX LR ; return | |||
| END | |||
| @@ -0,0 +1,655 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/LIB | |||
| * CUSTOM LIBRARY MODULES | |||
| * | |||
| * (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL | |||
| * | |||
| * All rights reserved. Protected by international copyright laws. | |||
| * | |||
| * uC/LIB is provided in source form to registered licensees ONLY. It is | |||
| * illegal to distribute this source code to any third party unless you receive | |||
| * written permission by an authorized Micrium representative. Knowledge of | |||
| * the source code may NOT be used to develop a similar product. | |||
| * | |||
| * Please help us continue to provide the Embedded community with the finest | |||
| * software available. Your honesty is greatly appreciated. | |||
| * | |||
| * You can find our product's user manual, API reference, release notes and | |||
| * more information at: https://doc.micrium.com | |||
| * | |||
| * You can contact us at: http://www.micrium.com | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * | |||
| * ASCII CHARACTER OPERATIONS | |||
| * | |||
| * Filename : lib_ascii.c | |||
| * Version : V1.38.01 | |||
| * Programmer(s) : BAN | |||
| * ITJ | |||
| ********************************************************************************************************* | |||
| * Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software. | |||
| * | |||
| * (a) ALL standard library functions are implemented in the custom library modules : | |||
| * | |||
| * (1) \<Custom Library Directory>\lib_*.* | |||
| * | |||
| * (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.* | |||
| * | |||
| * where | |||
| * <Custom Library Directory> directory path for custom library software | |||
| * <cpu> directory name for specific processor (CPU) | |||
| * <compiler> directory name for specific compiler | |||
| * | |||
| * (b) Product-specific library functions are implemented in individual products. | |||
| * | |||
| * | |||
| * (2) (a) ECMA-6 '7-Bit coded Character Set' (6th edition), which corresponds to the | |||
| * 3rd edition of ISO 646, specifies several versions of a 7-bit character set : | |||
| * | |||
| * (1) THE GENERAL VERSION, which allows characters at 0x23 and 0x24 to be given a | |||
| * set alternate form and allows the characters 0x40, 0x5B, 0x5D, 0x60, 0x7B & | |||
| * 0x7D to be assigned a "unique graphic character" or to be declared as unused. | |||
| * All other characters are explicitly specified. | |||
| * | |||
| * (2) THE INTERNATIONAL REFERENCE VERSION, which explicitly specifies all characters | |||
| * in the 7-bit character set. | |||
| * | |||
| * (3) NATIONAL & APPLICATION-ORIENTED VERSIONS, which may be derived from the | |||
| * standard in specified ways. | |||
| * | |||
| * (b) The character set represented in this file reproduces the Internation Reference | |||
| * Version. This is identical to the 7-bit character set which occupies Unicode | |||
| * characters 0x0000 through 0x007F. The character names are taken from v5.0 of the | |||
| * Unicode specification, with certain abbreviations so that the resulting #define | |||
| * names will not violate ANSI C naming restriction : | |||
| * | |||
| * (1) For the Latin capital & lowercase letters, the name components 'LETTER_CAPITAL' | |||
| * & 'LETTER_SMALL' are replaced by 'UPPER' & 'LOWER', respectively. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * INCLUDE FILES | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MICRIUM_SOURCE | |||
| #define LIB_ASCII_MODULE | |||
| #include <lib_ascii.h> | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL DEFINES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL CONSTANTS | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL DATA TYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL TABLES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL GLOBAL VARIABLES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL FUNCTION PROTOTYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL CONFIGURATION ERRORS | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsAlpha() | |||
| * | |||
| * Description : Determine whether a character is an alphabetic character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is an alphabetic character. | |||
| * | |||
| * DEF_NO, if character is NOT an alphabetic character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.2.(2) states that "isalpha() returns true only for the | |||
| * characters for which isupper() or islower() is true". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsAlpha (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN alpha; | |||
| alpha = ASCII_IS_ALPHA(c); | |||
| return (alpha); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsAlphaNum() | |||
| * | |||
| * Description : Determine whether a character is an alphanumeric character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is an alphanumeric character. | |||
| * | |||
| * DEF_NO, if character is NOT an alphanumeric character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.1.(2) states that "isalnum() ... tests for any character | |||
| * for which isalpha() or isdigit() is true". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsAlphaNum (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN alpha_num; | |||
| alpha_num = ASCII_IS_ALPHA_NUM(c); | |||
| return (alpha_num); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsLower() | |||
| * | |||
| * Description : Determine whether a character is a lowercase alphabetic character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a lowercase alphabetic character. | |||
| * | |||
| * DEF_NO, if character is NOT a lowercase alphabetic character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.7.(2) states that "islower() returns true only for | |||
| * the lowercase letters". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsLower (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN lower; | |||
| lower = ASCII_IS_LOWER(c); | |||
| return (lower); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsUpper() | |||
| * | |||
| * Description : Determine whether a character is an uppercase alphabetic character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is an uppercase alphabetic character. | |||
| * | |||
| * DEF_NO, if character is NOT an uppercase alphabetic character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.11.(2) states that "isupper() returns true only for | |||
| * the uppercase letters". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsUpper (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN upper; | |||
| upper = ASCII_IS_UPPER(c); | |||
| return (upper); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsDig() | |||
| * | |||
| * Description : Determine whether a character is a decimal-digit character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a decimal-digit character. | |||
| * | |||
| * DEF_NO, if character is NOT a decimal-digit character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.5.(2) states that "isdigit() ... tests for any | |||
| * decimal-digit character". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsDig (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN dig; | |||
| dig = ASCII_IS_DIG(c); | |||
| return (dig); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsDigOct() | |||
| * | |||
| * Description : Determine whether a character is an octal-digit character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is an octal-digit character. | |||
| * | |||
| * DEF_NO, if character is NOT an octal-digit character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : none. | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsDigOct (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN dig_oct; | |||
| dig_oct = ASCII_IS_DIG_OCT(c); | |||
| return (dig_oct); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsDigHex() | |||
| * | |||
| * Description : Determine whether a character is a hexadecimal-digit character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a hexadecimal-digit character. | |||
| * | |||
| * DEF_NO, if character is NOT a hexadecimal-digit character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.12.(2) states that "isxdigit() ... tests for any | |||
| * hexadecimal-digit character". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsDigHex (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN dig_hex; | |||
| dig_hex = ASCII_IS_DIG_HEX(c); | |||
| return (dig_hex); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsBlank() | |||
| * | |||
| * Description : Determine whether a character is a standard blank character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a standard blank character. | |||
| * | |||
| * DEF_NO, if character is NOT a standard blank character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.3.(2) states that "isblank() returns true only for | |||
| * the standard blank characters". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.1.3.(2) defines "the standard blank characters" as | |||
| * the "space (' '), and horizontal tab ('\t')". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsBlank (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN blank; | |||
| blank = ASCII_IS_BLANK(c); | |||
| return (blank); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsSpace() | |||
| * | |||
| * Description : Determine whether a character is a white-space character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a white-space character. | |||
| * | |||
| * DEF_NO, if character is NOT a white-space character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.10.(2) states that "isspace() returns true only | |||
| * for the standard white-space characters". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.1.10.(2) defines "the standard white-space characters" | |||
| * as the "space (' '), form feed ('\f'), new-line ('\n'), carriage return ('\r'), | |||
| * horizontal tab ('\t'), and vertical tab ('\v')". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsSpace (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN space; | |||
| space = ASCII_IS_SPACE(c); | |||
| return (space); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsPrint() | |||
| * | |||
| * Description : Determine whether a character is a printing character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a printing character. | |||
| * | |||
| * DEF_NO, if character is NOT a printing character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.8.(2) states that "isprint() ... tests for any | |||
| * printing character including space (' ')". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US | |||
| * ASCII character set, the printing characters are those whose values lie from | |||
| * 0x20 (space) through 0x7E (tilde)". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsPrint (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN print; | |||
| print = ASCII_IS_PRINT(c); | |||
| return (print); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsGraph() | |||
| * | |||
| * Description : Determine whether a character is any printing character except a space character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a graphic character. | |||
| * | |||
| * DEF_NO, if character is NOT a graphic character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.6.(2) states that "isgraph() ... tests for any | |||
| * printing character except space (' ')". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US | |||
| * ASCII character set, the printing characters are those whose values lie from | |||
| * 0x20 (space) through 0x7E (tilde)". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsGraph (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN graph; | |||
| graph = ASCII_IS_GRAPH(c); | |||
| return (graph); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsPunct() | |||
| * | |||
| * Description : Determine whether a character is a punctuation character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a punctuation character. | |||
| * | |||
| * DEF_NO, if character is NOT a punctuation character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.9.(2) states that "ispunct() returns true for every | |||
| * printing character for which neither isspace() nor isalnum() is true". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsPunct (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN punct; | |||
| punct = ASCII_IS_PUNCT(c); | |||
| return (punct); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IsCtrl() | |||
| * | |||
| * Description : Determine whether a character is a control character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a control character. | |||
| * | |||
| * DEF_NO, if character is NOT a control character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.4.(2) states that "iscntrl() ... tests for any | |||
| * control character". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US | |||
| * ASCII character set, ... the control characters are those whose values lie from | |||
| * 0 (NUL) through 0x1F (US), and the character 0x7F (DEL)". | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsCtrl (CPU_CHAR c) | |||
| { | |||
| CPU_BOOLEAN ctrl; | |||
| ctrl = ASCII_IS_CTRL(c); | |||
| return (ctrl); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_ToLower() | |||
| * | |||
| * Description : Convert uppercase alphabetic character to its corresponding lowercase alphabetic character. | |||
| * | |||
| * Argument(s) : c Character to convert. | |||
| * | |||
| * Return(s) : Lowercase equivalent of 'c', if character 'c' is an uppercase character (see Note #1b1). | |||
| * | |||
| * Character 'c', otherwise (see Note #1b2). | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.2.1.(2) states that "tolower() ... converts an | |||
| * uppercase letter to a corresponding lowercase letter". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.2.1.(3) states that : | |||
| * | |||
| * (1) (A) "if the argument is a character for which isupper() is true and there are | |||
| * one or more corresponding characters ... for which islower() is true," ... | |||
| * (B) "tolower() ... returns one of the corresponding characters;" ... | |||
| * | |||
| * (2) "otherwise, the argument is returned unchanged." | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_CHAR ASCII_ToLower (CPU_CHAR c) | |||
| { | |||
| CPU_CHAR lower; | |||
| lower = ASCII_TO_LOWER(c); | |||
| return (lower); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_ToUpper() | |||
| * | |||
| * Description : Convert lowercase alphabetic character to its corresponding uppercase alphabetic character. | |||
| * | |||
| * Argument(s) : c Character to convert. | |||
| * | |||
| * Return(s) : Uppercase equivalent of 'c', if character 'c' is a lowercase character (see Note #1b1). | |||
| * | |||
| * Character 'c', otherwise (see Note #1b2). | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.2.2.(2) states that "toupper() ... converts a | |||
| * lowercase letter to a corresponding uppercase letter". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.2.2.(3) states that : | |||
| * | |||
| * (1) (A) "if the argument is a character for which islower() is true and there are | |||
| * one or more corresponding characters ... for which isupper() is true," ... | |||
| * (B) "toupper() ... returns one of the corresponding characters;" ... | |||
| * | |||
| * (2) "otherwise, the argument is returned unchanged." | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_CHAR ASCII_ToUpper (CPU_CHAR c) | |||
| { | |||
| CPU_CHAR upper; | |||
| upper = ASCII_TO_UPPER(c); | |||
| return (upper); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_Cmp() | |||
| * | |||
| * Description : Determine if two characters are identical (case-insensitive). | |||
| * | |||
| * Argument(s) : c1 First character. | |||
| * | |||
| * c2 Second character. | |||
| * | |||
| * Return(s) : DEF_YES, if the characters are identical. | |||
| * | |||
| * DEF_NO, if the characters are NOT identical. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : none. | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_Cmp (CPU_CHAR c1, | |||
| CPU_CHAR c2) | |||
| { | |||
| CPU_CHAR c1_upper; | |||
| CPU_CHAR c2_upper; | |||
| CPU_BOOLEAN cmp; | |||
| c1_upper = ASCII_ToUpper(c1); | |||
| c2_upper = ASCII_ToUpper(c2); | |||
| cmp = (c1_upper == c2_upper) ? (DEF_YES) : (DEF_NO); | |||
| return (cmp); | |||
| } | |||
| @@ -0,0 +1,842 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/LIB | |||
| * CUSTOM LIBRARY MODULES | |||
| * | |||
| * (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL | |||
| * | |||
| * All rights reserved. Protected by international copyright laws. | |||
| * | |||
| * uC/LIB is provided in source form to registered licensees ONLY. It is | |||
| * illegal to distribute this source code to any third party unless you receive | |||
| * written permission by an authorized Micrium representative. Knowledge of | |||
| * the source code may NOT be used to develop a similar product. | |||
| * | |||
| * Please help us continue to provide the Embedded community with the finest | |||
| * software available. Your honesty is greatly appreciated. | |||
| * | |||
| * You can find our product's user manual, API reference, release notes and | |||
| * more information at: https://doc.micrium.com | |||
| * | |||
| * You can contact us at: http://www.micrium.com | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * | |||
| * ASCII CHARACTER OPERATIONS | |||
| * | |||
| * Filename : lib_ascii.h | |||
| * Version : V1.38.01 | |||
| * Programmer(s) : BAN | |||
| ********************************************************************************************************* | |||
| * Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software. | |||
| * | |||
| * (a) ALL standard library functions are implemented in the custom library modules : | |||
| * | |||
| * (1) \<Custom Library Directory>\lib_*.* | |||
| * | |||
| * (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.* | |||
| * | |||
| * where | |||
| * <Custom Library Directory> directory path for custom library software | |||
| * <cpu> directory name for specific processor (CPU) | |||
| * <compiler> directory name for specific compiler | |||
| * | |||
| * (b) Product-specific library functions are implemented in individual products. | |||
| * | |||
| * | |||
| * (2) (a) ECMA-6 '7-Bit coded Character Set' (6th edition), which corresponds to the | |||
| * 3rd edition of ISO 646, specifies several versions of a 7-bit character set : | |||
| * | |||
| * (1) THE GENERAL VERSION, which allows characters at 0x23 and 0x24 to be given a | |||
| * set alternate form and allows the characters 0x40, 0x5B, 0x5D, 0x60, 0x7B & | |||
| * 0x7D to be assigned a "unique graphic character" or to be declared as unused. | |||
| * All other characters are explicitly specified. | |||
| * | |||
| * (2) THE INTERNATIONAL REFERENCE VERSION, which explicitly specifies all characters | |||
| * in the 7-bit character set. | |||
| * | |||
| * (3) NATIONAL & APPLICATION-ORIENTED VERSIONS, which may be derived from the | |||
| * standard in specified ways. | |||
| * | |||
| * (b) The character set represented in this file reproduces the Internation Reference | |||
| * Version. This is identical to the 7-bit character set which occupies Unicode | |||
| * characters 0x0000 through 0x007F. The character names are taken from v5.0 of the | |||
| * Unicode specification, with certain abbreviations so that the resulting #define | |||
| * names will not violate ANSI C naming restriction : | |||
| * | |||
| * (1) For the Latin capital & lowercase letters, the name components 'LETTER_CAPITAL' | |||
| * & 'LETTER_SMALL' are replaced by 'UPPER' & 'LOWER', respectively. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MODULE | |||
| * | |||
| * Note(s) : (1) This ASCII library header file is protected from multiple pre-processor inclusion through | |||
| * use of the ASCII library module present pre-processor macro definition. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #ifndef LIB_ASCII_MODULE_PRESENT /* See Note #1. */ | |||
| #define LIB_ASCII_MODULE_PRESENT | |||
| /* | |||
| ********************************************************************************************************* | |||
| * INCLUDE FILES | |||
| * | |||
| * Note(s) : (1) The custom library software files are located in the following directories : | |||
| * | |||
| * (a) \<Custom Library Directory>\lib_*.* | |||
| * | |||
| * where | |||
| * <Custom Library Directory> directory path for custom library software | |||
| * | |||
| * (2) CPU-configuration software files are located in the following directories : | |||
| * | |||
| * (a) \<CPU-Compiler Directory>\cpu_*.* | |||
| * (b) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.* | |||
| * | |||
| * where | |||
| * <CPU-Compiler Directory> directory path for common CPU-compiler software | |||
| * <cpu> directory name for specific processor (CPU) | |||
| * <compiler> directory name for specific compiler | |||
| * | |||
| * (3) Compiler MUST be configured to include as additional include path directories : | |||
| * | |||
| * (a) '\<Custom Library Directory>\' directory See Note #1a | |||
| * | |||
| * (b) (1) '\<CPU-Compiler Directory>\' directory See Note #2a | |||
| * (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory See Note #2b | |||
| * | |||
| * (4) NO compiler-supplied standard library functions SHOULD be used. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #include <cpu.h> | |||
| #include <lib_def.h> | |||
| /* | |||
| ********************************************************************************************************* | |||
| * EXTERNS | |||
| ********************************************************************************************************* | |||
| */ | |||
| #ifdef LIB_ASCII_MODULE | |||
| #define LIB_ASCII_EXT | |||
| #else | |||
| #define LIB_ASCII_EXT extern | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DEFINES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII CHARACTER DEFINES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* -------------------- C0 CONTROLS ------------------- */ | |||
| #define ASCII_CHAR_NULL 0x00 /* '\0' */ | |||
| #define ASCII_CHAR_START_OF_HEADING 0x01 | |||
| #define ASCII_CHAR_START_OF_TEXT 0x02 | |||
| #define ASCII_CHAR_END_OF_TEXT 0x03 | |||
| #define ASCII_CHAR_END_OF_TRANSMISSION 0x04 | |||
| #define ASCII_CHAR_ENQUIRY 0x05 | |||
| #define ASCII_CHAR_ACKNOWLEDGE 0x06 | |||
| #define ASCII_CHAR_BELL 0x07 /* '\a' */ | |||
| #define ASCII_CHAR_BACKSPACE 0x08 /* '\b' */ | |||
| #define ASCII_CHAR_CHARACTER_TABULATION 0x09 /* '\t' */ | |||
| #define ASCII_CHAR_LINE_FEED 0x0A /* '\n' */ | |||
| #define ASCII_CHAR_LINE_TABULATION 0x0B /* '\v' */ | |||
| #define ASCII_CHAR_FORM_FEED 0x0C /* '\f' */ | |||
| #define ASCII_CHAR_CARRIAGE_RETURN 0x0D /* '\r' */ | |||
| #define ASCII_CHAR_SHIFT_OUT 0x0E | |||
| #define ASCII_CHAR_SHIFT_IN 0x0F | |||
| #define ASCII_CHAR_DATA_LINK_ESCAPE 0x10 | |||
| #define ASCII_CHAR_DEVICE_CONTROL_ONE 0x11 | |||
| #define ASCII_CHAR_DEVICE_CONTROL_TWO 0x12 | |||
| #define ASCII_CHAR_DEVICE_CONTROL_THREE 0x13 | |||
| #define ASCII_CHAR_DEVICE_CONTROL_FOUR 0x14 | |||
| #define ASCII_CHAR_NEGATIVE_ACKNOWLEDGE 0x15 | |||
| #define ASCII_CHAR_SYNCHRONOUS_IDLE 0x16 | |||
| #define ASCII_CHAR_END_OF_TRANSMISSION_BLOCK 0x17 | |||
| #define ASCII_CHAR_CANCEL 0x18 | |||
| #define ASCII_CHAR_END_OF_MEDIUM 0x19 | |||
| #define ASCII_CHAR_SUBSITUTE 0x1A | |||
| #define ASCII_CHAR_ESCAPE 0x1B | |||
| #define ASCII_CHAR_INFO_SEPARATOR_FOUR 0x1C | |||
| #define ASCII_CHAR_INFO_SEPARATOR_THREE 0x1D | |||
| #define ASCII_CHAR_INFO_SEPARATOR_TWO 0x1E | |||
| #define ASCII_CHAR_INFO_SEPARATOR_ONE 0x1F | |||
| #define ASCII_CHAR_NUL ASCII_CHAR_NULL | |||
| #define ASCII_CHAR_SOH ASCII_CHAR_START_OF_HEADING | |||
| #define ASCII_CHAR_START_HEADING ASCII_CHAR_START_OF_HEADING | |||
| #define ASCII_CHAR_STX ASCII_CHAR_START_OF_TEXT | |||
| #define ASCII_CHAR_START_TEXT ASCII_CHAR_START_OF_TEXT | |||
| #define ASCII_CHAR_ETX ASCII_CHAR_END_OF_TEXT | |||
| #define ASCII_CHAR_END_TEXT ASCII_CHAR_END_OF_TEXT | |||
| #define ASCII_CHAR_EOT ASCII_CHAR_END_OF_TRANSMISSION | |||
| #define ASCII_CHAR_END_TRANSMISSION ASCII_CHAR_END_OF_TRANSMISSION | |||
| #define ASCII_CHAR_ENQ ASCII_CHAR_ENQUIRY | |||
| #define ASCII_CHAR_ACK ASCII_CHAR_ACKNOWLEDGE | |||
| #define ASCII_CHAR_BEL ASCII_CHAR_BELL | |||
| #define ASCII_CHAR_BS ASCII_CHAR_BACKSPACE | |||
| #define ASCII_CHAR_HT ASCII_CHAR_CHARACTER_TABULATION | |||
| #define ASCII_CHAR_TAB ASCII_CHAR_CHARACTER_TABULATION | |||
| #define ASCII_CHAR_LF ASCII_CHAR_LINE_FEED | |||
| #define ASCII_CHAR_VT ASCII_CHAR_LINE_TABULATION | |||
| #define ASCII_CHAR_FF ASCII_CHAR_FORM_FEED | |||
| #define ASCII_CHAR_CR ASCII_CHAR_CARRIAGE_RETURN | |||
| #define ASCII_CHAR_SO ASCII_CHAR_SHIFT_OUT | |||
| #define ASCII_CHAR_SI ASCII_CHAR_SHIFT_IN | |||
| #define ASCII_CHAR_DLE ASCII_CHAR_DATA_LINK_ESCAPE | |||
| #define ASCII_CHAR_DC1 ASCII_CHAR_DEVICE_CONTROL_ONE | |||
| #define ASCII_CHAR_DC2 ASCII_CHAR_DEVICE_CONTROL_TWO | |||
| #define ASCII_CHAR_DC3 ASCII_CHAR_DEVICE_CONTROL_THREE | |||
| #define ASCII_CHAR_DC4 ASCII_CHAR_DEVICE_CONTROL_FOUR | |||
| #define ASCII_CHAR_DEV_CTRL_ONE ASCII_CHAR_DEVICE_CONTROL_ONE | |||
| #define ASCII_CHAR_DEV_CTRL_TWO ASCII_CHAR_DEVICE_CONTROL_TWO | |||
| #define ASCII_CHAR_DEV_CTRL_THREE ASCII_CHAR_DEVICE_CONTROL_THREE | |||
| #define ASCII_CHAR_DEV_CTRL_FOUR ASCII_CHAR_DEVICE_CONTROL_FOUR | |||
| #define ASCII_CHAR_NAK ASCII_CHAR_NEGATIVE_ACKNOWLEDGE | |||
| #define ASCII_CHAR_NEG_ACK ASCII_CHAR_NEGATIVE_ACKNOWLEDGE | |||
| #define ASCII_CHAR_SYN ASCII_CHAR_SYNCHRONOUS_IDLE | |||
| #define ASCII_CHAR_SYNC_IDLE ASCII_CHAR_SYNCHRONOUS_IDLE | |||
| #define ASCII_CHAR_ETB ASCII_CHAR_END_OF_TRANSMISSION_BLOCK | |||
| #define ASCII_CHAR_END_TRANSMISSION_BLK ASCII_CHAR_END_OF_TRANSMISSION_BLOCK | |||
| #define ASCII_CHAR_CAN ASCII_CHAR_CANCEL | |||
| #define ASCII_CHAR_EM ASCII_CHAR_END_OF_MEDIUM | |||
| #define ASCII_CHAR_END_MEDIUM ASCII_CHAR_END_OF_MEDIUM | |||
| #define ASCII_CHAR_SUB ASCII_CHAR_SUBSITUTE | |||
| #define ASCII_CHAR_ESC ASCII_CHAR_ESCAPE | |||
| #define ASCII_CHAR_IS1 ASCII_CHAR_INFO_SEPARATOR_ONE | |||
| #define ASCII_CHAR_IS2 ASCII_CHAR_INFO_SEPARATOR_TWO | |||
| #define ASCII_CHAR_IS3 ASCII_CHAR_INFO_SEPARATOR_THREE | |||
| #define ASCII_CHAR_IS4 ASCII_CHAR_INFO_SEPARATOR_FOUR | |||
| /* ------------ ASCII PUNCTUATION & SYMBOLS ----------- */ | |||
| #define ASCII_CHAR_SPACE 0x20 /* ' ' */ | |||
| #define ASCII_CHAR_EXCLAMATION_MARK 0x21 /* '!' */ | |||
| #define ASCII_CHAR_QUOTATION_MARK 0x22 /* '\"' */ | |||
| #define ASCII_CHAR_NUMBER_SIGN 0x23 /* '#' */ | |||
| #define ASCII_CHAR_DOLLAR_SIGN 0x24 /* '$' */ | |||
| #define ASCII_CHAR_PERCENTAGE_SIGN 0x25 /* '%' */ | |||
| #define ASCII_CHAR_AMPERSAND 0x26 /* '&' */ | |||
| #define ASCII_CHAR_APOSTROPHE 0x27 /* '\'' */ | |||
| #define ASCII_CHAR_LEFT_PARENTHESIS 0x28 /* '(' */ | |||
| #define ASCII_CHAR_RIGHT_PARENTHESIS 0x29 /* ')' */ | |||
| #define ASCII_CHAR_ASTERISK 0x2A /* '*' */ | |||
| #define ASCII_CHAR_PLUS_SIGN 0x2B /* '+' */ | |||
| #define ASCII_CHAR_COMMA 0x2C /* ',' */ | |||
| #define ASCII_CHAR_HYPHEN_MINUS 0x2D /* '-' */ | |||
| #define ASCII_CHAR_FULL_STOP 0x2E /* '.' */ | |||
| #define ASCII_CHAR_SOLIDUS 0x2F /* '/' */ | |||
| #define ASCII_CHAR_PAREN_LEFT ASCII_CHAR_LEFT_PARENTHESIS | |||
| #define ASCII_CHAR_PAREN_RIGHT ASCII_CHAR_RIGHT_PARENTHESIS | |||
| /* ------------------- ASCII DIGITS ------------------- */ | |||
| #define ASCII_CHAR_DIGIT_ZERO 0x30 /* '0' */ | |||
| #define ASCII_CHAR_DIGIT_ONE 0x31 /* '1' */ | |||
| #define ASCII_CHAR_DIGIT_TWO 0x32 /* '2' */ | |||
| #define ASCII_CHAR_DIGIT_THREE 0x33 /* '3' */ | |||
| #define ASCII_CHAR_DIGIT_FOUR 0x34 /* '4' */ | |||
| #define ASCII_CHAR_DIGIT_FIVE 0x35 /* '5' */ | |||
| #define ASCII_CHAR_DIGIT_SIX 0x36 /* '6' */ | |||
| #define ASCII_CHAR_DIGIT_SEVEN 0x37 /* '7' */ | |||
| #define ASCII_CHAR_DIGIT_EIGHT 0x38 /* '8' */ | |||
| #define ASCII_CHAR_DIGIT_NINE 0x39 /* '9' */ | |||
| #define ASCII_CHAR_DIG_ZERO ASCII_CHAR_DIGIT_ZERO | |||
| #define ASCII_CHAR_DIG_ONE ASCII_CHAR_DIGIT_ONE | |||
| #define ASCII_CHAR_DIG_TWO ASCII_CHAR_DIGIT_TWO | |||
| #define ASCII_CHAR_DIG_THREE ASCII_CHAR_DIGIT_THREE | |||
| #define ASCII_CHAR_DIG_FOUR ASCII_CHAR_DIGIT_FOUR | |||
| #define ASCII_CHAR_DIG_FIVE ASCII_CHAR_DIGIT_FIVE | |||
| #define ASCII_CHAR_DIG_SIX ASCII_CHAR_DIGIT_SIX | |||
| #define ASCII_CHAR_DIG_SEVEN ASCII_CHAR_DIGIT_SEVEN | |||
| #define ASCII_CHAR_DIG_EIGHT ASCII_CHAR_DIGIT_EIGHT | |||
| #define ASCII_CHAR_DIG_NINE ASCII_CHAR_DIGIT_NINE | |||
| /* ------------ ASCII PUNCTUATION & SYMBOLS ----------- */ | |||
| #define ASCII_CHAR_COLON 0x3A /* ':' */ | |||
| #define ASCII_CHAR_SEMICOLON 0x3B /* ';' */ | |||
| #define ASCII_CHAR_LESS_THAN_SIGN 0x3C /* '<' */ | |||
| #define ASCII_CHAR_EQUALS_SIGN 0x3D /* '=' */ | |||
| #define ASCII_CHAR_GREATER_THAN_SIGN 0x3E /* '>' */ | |||
| #define ASCII_CHAR_QUESTION_MARK 0x3F /* '\?' */ | |||
| #define ASCII_CHAR_COMMERCIAL_AT 0x40 /* '@' */ | |||
| #define ASCII_CHAR_AT_SIGN ASCII_CHAR_COMMERCIAL_AT | |||
| /* ------------- UPPERCASE LATIN ALPHABET ------------- */ | |||
| #define ASCII_CHAR_LATIN_UPPER_A 0x41 /* 'A' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_B 0x42 /* 'B' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_C 0x43 /* 'C' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_D 0x44 /* 'D' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_E 0x45 /* 'E' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_F 0x46 /* 'F' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_G 0x47 /* 'G' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_H 0x48 /* 'H' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_I 0x49 /* 'I' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_J 0x4A /* 'J' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_K 0x4B /* 'K' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_L 0x4C /* 'L' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_M 0x4D /* 'M' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_N 0x4E /* 'N' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_O 0x4F /* 'O' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_P 0x50 /* 'P' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_Q 0x51 /* 'Q' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_R 0x52 /* 'R' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_S 0x53 /* 'S' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_T 0x54 /* 'T' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_U 0x55 /* 'U' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_V 0x56 /* 'V' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_W 0x57 /* 'W' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_X 0x58 /* 'X' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_Y 0x59 /* 'Y' */ | |||
| #define ASCII_CHAR_LATIN_UPPER_Z 0x5A /* 'Z' */ | |||
| /* ------------ ASCII PUNCTUATION & SYMBOLS ----------- */ | |||
| #define ASCII_CHAR_LEFT_SQUARE_BRACKET 0x5B /* '[' */ | |||
| #define ASCII_CHAR_REVERSE_SOLIDUS 0x5C /* '\\' */ | |||
| #define ASCII_CHAR_RIGHT_SQUARE_BRACKET 0x5D /* ']' */ | |||
| #define ASCII_CHAR_CIRCUMFLEX_ACCENT 0x5E /* '^' */ | |||
| #define ASCII_CHAR_LOW_LINE 0x5F /* '_' */ | |||
| #define ASCII_CHAR_GRAVE_ACCENT 0x60 /* '`' */ | |||
| #define ASCII_CHAR_BRACKET_SQUARE_LEFT ASCII_CHAR_LEFT_SQUARE_BRACKET | |||
| #define ASCII_CHAR_BRACKET_SQUARE_RIGHT ASCII_CHAR_RIGHT_SQUARE_BRACKET | |||
| /* ------------- LOWERCASE LATIN ALPHABET ------------- */ | |||
| #define ASCII_CHAR_LATIN_LOWER_A 0x61 /* 'a' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_B 0x62 /* 'b' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_C 0x63 /* 'c' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_D 0x64 /* 'd' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_E 0x65 /* 'e' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_F 0x66 /* 'f' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_G 0x67 /* 'g' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_H 0x68 /* 'h' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_I 0x69 /* 'i' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_J 0x6A /* 'j' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_K 0x6B /* 'k' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_L 0x6C /* 'l' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_M 0x6D /* 'm' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_N 0x6E /* 'n' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_O 0x6F /* 'o' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_P 0x70 /* 'p' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_Q 0x71 /* 'q' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_R 0x72 /* 'r' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_S 0x73 /* 's' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_T 0x74 /* 't' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_U 0x75 /* 'u' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_V 0x76 /* 'v' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_W 0x77 /* 'w' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_X 0x78 /* 'x' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_Y 0x79 /* 'y' */ | |||
| #define ASCII_CHAR_LATIN_LOWER_Z 0x7A /* 'z' */ | |||
| /* ------------ ASCII PUNCTUATION & SYMBOLS ----------- */ | |||
| #define ASCII_CHAR_LEFT_CURLY_BRACKET 0x7B /* '{' */ | |||
| #define ASCII_CHAR_VERTICAL_LINE 0x7C /* '|' */ | |||
| #define ASCII_CHAR_RIGHT_CURLY_BRACKET 0x7D /* '}' */ | |||
| #define ASCII_CHAR_TILDE 0x7E /* '~' */ | |||
| #define ASCII_CHAR_BRACKET_CURLY_LEFT ASCII_CHAR_LEFT_CURLY_BRACKET | |||
| #define ASCII_CHAR_BRACKET_CURLY_RIGHT ASCII_CHAR_RIGHT_CURLY_BRACKET | |||
| /* ---------------- CONTROL CHARACTERS ---------------- */ | |||
| #define ASCII_CHAR_DELETE 0x7F | |||
| #define ASCII_CHAR_DEL ASCII_CHAR_DELETE | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DATA TYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * GLOBAL VARIABLES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MACRO'S | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII CHARACTER CLASSIFICATION MACRO's | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.(1) states that "character classification functions ... | |||
| * return nonzero (true) if and only if the value of the argument 'c' conforms to ... the | |||
| * description of the function." | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_DIG() | |||
| * | |||
| * Description : Determine whether a character is a decimal-digit character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a decimal-digit character. | |||
| * | |||
| * DEF_NO, if character is NOT a decimal-digit character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.5.(2) states that "isdigit() ... tests for any | |||
| * decimal-digit character". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_DIG(c) ((((c) >= ASCII_CHAR_DIG_ZERO) && ((c) <= ASCII_CHAR_DIG_NINE)) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_DIG_OCT() | |||
| * | |||
| * Description : Determine whether a character is an octal-digit character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is an octal-digit character. | |||
| * | |||
| * DEF_NO, if character is NOT an octal-digit character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : none. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_DIG_OCT(c) ((((c) >= ASCII_CHAR_DIG_ZERO) && ((c) <= ASCII_CHAR_DIG_SEVEN)) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_DIG_HEX() | |||
| * | |||
| * Description : Determine whether a character is a hexadecimal-digit character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a hexadecimal-digit character. | |||
| * | |||
| * DEF_NO, if character is NOT a hexadecimal-digit character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.12.(2) states that "isxdigit() ... tests for any | |||
| * hexadecimal-digit character". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_DIG_HEX(c) (((((c) >= ASCII_CHAR_DIG_ZERO ) && ((c) <= ASCII_CHAR_DIG_NINE )) || \ | |||
| (((c) >= ASCII_CHAR_LATIN_UPPER_A) && ((c) <= ASCII_CHAR_LATIN_UPPER_F)) || \ | |||
| (((c) >= ASCII_CHAR_LATIN_LOWER_A) && ((c) <= ASCII_CHAR_LATIN_LOWER_F))) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_LOWER() | |||
| * | |||
| * Description : Determine whether a character is a lowercase alphabetic character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a lowercase alphabetic character. | |||
| * | |||
| * DEF_NO, if character is NOT a lowercase alphabetic character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.7.(2) states that "islower() returns true only for | |||
| * the lowercase letters". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_LOWER(c) ((((c) >= ASCII_CHAR_LATIN_LOWER_A) && ((c) <= ASCII_CHAR_LATIN_LOWER_Z)) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_UPPER() | |||
| * | |||
| * Description : Determine whether a character is an uppercase alphabetic character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is an uppercase alphabetic character. | |||
| * | |||
| * DEF_NO, if character is NOT an uppercase alphabetic character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.11.(2) states that "isupper() returns true only for | |||
| * the uppercase letters". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_UPPER(c) ((((c) >= ASCII_CHAR_LATIN_UPPER_A) && ((c) <= ASCII_CHAR_LATIN_UPPER_Z)) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_ALPHA() | |||
| * | |||
| * Description : Determine whether a character is an alphabetic character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is an alphabetic character. | |||
| * | |||
| * DEF_NO, if character is NOT an alphabetic character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.2.(2) states that "isalpha() returns true only for the | |||
| * characters for which isupper() or islower() is true". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_ALPHA(c) ((((ASCII_IS_UPPER(c)) == DEF_YES) || \ | |||
| ((ASCII_IS_LOWER(c)) == DEF_YES)) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_ALPHA_NUM() | |||
| * | |||
| * Description : Determine whether a character is an alphanumeric character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is an alphanumeric character. | |||
| * | |||
| * DEF_NO, if character is NOT an alphanumeric character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.1.(2) states that "isalnum() ... tests for any character | |||
| * for which isalpha() or isdigit() is true". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_ALPHA_NUM(c) ((((ASCII_IS_ALPHA(c)) == DEF_YES) || \ | |||
| ((ASCII_IS_DIG (c)) == DEF_YES)) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_BLANK() | |||
| * | |||
| * Description : Determine whether a character is a standard blank character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a standard blank character. | |||
| * | |||
| * DEF_NO, if character is NOT a standard blank character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.3.(2) states that "isblank() returns true only for | |||
| * the standard blank characters". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.1.3.(2) defines "the standard blank characters" as | |||
| * the "space (' '), and horizontal tab ('\t')". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_BLANK(c) ((((c) == ASCII_CHAR_SPACE) || ((c) == ASCII_CHAR_HT)) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_SPACE() | |||
| * | |||
| * Description : Determine whether a character is a white-space character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a white-space character. | |||
| * | |||
| * DEF_NO, if character is NOT a white-space character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.10.(2) states that "isspace() returns true only | |||
| * for the standard white-space characters". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.1.10.(2) defines "the standard white-space characters" | |||
| * as the "space (' '), form feed ('\f'), new-line ('\n'), carriage return ('\r'), | |||
| * horizontal tab ('\t'), and vertical tab ('\v')". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_SPACE(c) ((((c) == ASCII_CHAR_SPACE) || ((c) == ASCII_CHAR_CR) || \ | |||
| ((c) == ASCII_CHAR_LF ) || ((c) == ASCII_CHAR_FF) || \ | |||
| ((c) == ASCII_CHAR_HT ) || ((c) == ASCII_CHAR_VT)) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_PRINT() | |||
| * | |||
| * Description : Determine whether a character is a printing character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a printing character. | |||
| * | |||
| * DEF_NO, if character is NOT a printing character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.8.(2) states that "isprint() ... tests for any | |||
| * printing character including space (' ')". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US | |||
| * ASCII character set, the printing characters are those whose values lie from | |||
| * 0x20 (space) through 0x7E (tilde)". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_PRINT(c) ((((c) >= ASCII_CHAR_SPACE) && ((c) <= ASCII_CHAR_TILDE)) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_GRAPH() | |||
| * | |||
| * Description : Determine whether a character is any printing character except a space character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a graphic character. | |||
| * | |||
| * DEF_NO, if character is NOT a graphic character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.6.(2) states that "isgraph() ... tests for any | |||
| * printing character except space (' ')". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US | |||
| * ASCII character set, the printing characters are those whose values lie from | |||
| * 0x20 (space) through 0x7E (tilde)". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_GRAPH(c) ((((c) >= ASCII_CHAR_EXCLAMATION_MARK) && ((c) <= ASCII_CHAR_TILDE)) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_PUNCT() | |||
| * | |||
| * Description : Determine whether a character is a punctuation character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a punctuation character. | |||
| * | |||
| * DEF_NO, if character is NOT a punctuation character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) ISO/IEC 9899:TC2, Section 7.4.1.9.(2) states that "ispunct() returns true for every | |||
| * printing character for which neither isspace() nor isalnum() is true". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_PUNCT(c) ((((ASCII_IS_PRINT(c)) == DEF_YES) && \ | |||
| ((ASCII_IS_SPACE(c)) == DEF_NO ) && \ | |||
| ((ASCII_IS_ALPHA_NUM(c)) == DEF_NO )) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_IS_CTRL() | |||
| * | |||
| * Description : Determine whether a character is a control character. | |||
| * | |||
| * Argument(s) : c Character to examine. | |||
| * | |||
| * Return(s) : DEF_YES, if character is a control character. | |||
| * | |||
| * DEF_NO, if character is NOT a control character. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.1.4.(2) states that "iscntrl() ... tests for any | |||
| * control character". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.(3), Note 169, states that in "the seven-bit US | |||
| * ASCII character set, ... the control characters are those whose values lie from | |||
| * 0 (NUL) through 0x1F (US), and the character 0x7F (DEL)". | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_IS_CTRL(c) (((((CPU_INT08S)(c) >= ASCII_CHAR_NULL ) && ((c) <= ASCII_CHAR_IS1)) || \ | |||
| ((c) == ASCII_CHAR_DEL)) ? (DEF_YES) : (DEF_NO)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII CHARACTER CASE MAPPING MACRO's | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_TO_LOWER() | |||
| * | |||
| * Description : Convert uppercase alphabetic character to its corresponding lowercase alphabetic character. | |||
| * | |||
| * Argument(s) : c Character to convert. | |||
| * | |||
| * Return(s) : Lowercase equivalent of 'c', if character 'c' is an uppercase character (see Note #1b1). | |||
| * | |||
| * Character 'c', otherwise (see Note #1b2). | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.2.1.(2) states that "tolower() ... converts an | |||
| * uppercase letter to a corresponding lowercase letter". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.2.1.(3) states that : | |||
| * | |||
| * (1) (A) "if the argument is a character for which isupper() is true and there are | |||
| * one or more corresponding characters ... for which islower() is true," ... | |||
| * (B) "tolower() ... returns one of the corresponding characters;" ... | |||
| * | |||
| * (2) "otherwise, the argument is returned unchanged." | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_TO_LOWER(c) (((ASCII_IS_UPPER(c)) == DEF_YES) ? ((c) + (ASCII_CHAR_LATIN_LOWER_A - ASCII_CHAR_LATIN_UPPER_A)) : (c)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII_TO_UPPER() | |||
| * | |||
| * Description : Convert lowercase alphabetic character to its corresponding uppercase alphabetic character. | |||
| * | |||
| * Argument(s) : c Character to convert. | |||
| * | |||
| * Return(s) : Uppercase equivalent of 'c', if character 'c' is a lowercase character (see Note #1b1). | |||
| * | |||
| * Character 'c', otherwise (see Note #1b2). | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) ISO/IEC 9899:TC2, Section 7.4.2.2.(2) states that "toupper() ... converts a | |||
| * lowercase letter to a corresponding uppercase letter". | |||
| * | |||
| * (b) ISO/IEC 9899:TC2, Section 7.4.2.2.(3) states that : | |||
| * | |||
| * (1) (A) "if the argument is a character for which islower() is true and there are | |||
| * one or more corresponding characters ... for which isupper() is true," ... | |||
| * (B) "toupper() ... returns one of the corresponding characters;" ... | |||
| * | |||
| * (2) "otherwise, the argument is returned unchanged." | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define ASCII_TO_UPPER(c) (((ASCII_IS_LOWER(c)) == DEF_YES) ? ((c) - (ASCII_CHAR_LATIN_LOWER_A - ASCII_CHAR_LATIN_UPPER_A)) : (c)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * FUNCTION PROTOTYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| CPU_BOOLEAN ASCII_IsAlpha (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsAlphaNum(CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsLower (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsUpper (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsDig (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsDigOct (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsDigHex (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsBlank (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsSpace (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsPrint (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsGraph (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsPunct (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_IsCtrl (CPU_CHAR c); | |||
| CPU_CHAR ASCII_ToLower (CPU_CHAR c); | |||
| CPU_CHAR ASCII_ToUpper (CPU_CHAR c); | |||
| CPU_BOOLEAN ASCII_Cmp (CPU_CHAR c1, | |||
| CPU_CHAR c2); | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CONFIGURATION ERRORS | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MODULE END | |||
| * | |||
| * Note(s) : (1) See 'lib_ascii.h MODULE'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #endif /* End of lib ascii module include. */ | |||
| @@ -0,0 +1,281 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/LIB | |||
| * CUSTOM LIBRARY MODULES | |||
| * | |||
| * (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL | |||
| * | |||
| * All rights reserved. Protected by international copyright laws. | |||
| * | |||
| * uC/LIB is provided in source form to registered licensees ONLY. It is | |||
| * illegal to distribute this source code to any third party unless you receive | |||
| * written permission by an authorized Micrium representative. Knowledge of | |||
| * the source code may NOT be used to develop a similar product. | |||
| * | |||
| * Please help us continue to provide the Embedded community with the finest | |||
| * software available. Your honesty is greatly appreciated. | |||
| * | |||
| * You can find our product's user manual, API reference, release notes and | |||
| * more information at: https://doc.micrium.com | |||
| * | |||
| * You can contact us at: http://www.micrium.com | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * | |||
| * MATHEMATIC OPERATIONS | |||
| * | |||
| * Filename : lib_math.c | |||
| * Version : V1.38.01 | |||
| * Programmer(s) : SR | |||
| * ITJ | |||
| ********************************************************************************************************* | |||
| * Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software. | |||
| * | |||
| * (a) ALL standard library functions are implemented in the custom library modules : | |||
| * | |||
| * (1) \<Custom Library Directory>\lib_*.* | |||
| * | |||
| * (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.* | |||
| * | |||
| * where | |||
| * <Custom Library Directory> directory path for custom library software | |||
| * <cpu> directory name for specific processor (CPU) | |||
| * <compiler> directory name for specific compiler | |||
| * | |||
| * (b) Product-specific library functions are implemented in individual products. | |||
| * | |||
| ********************************************************************************************************* | |||
| * Notice(s) : (1) The Institute of Electrical and Electronics Engineers and The Open Group, have given | |||
| * us permission to reprint portions of their documentation. Portions of this text are | |||
| * reprinted and reproduced in electronic form from the IEEE Std 1003.1, 2004 Edition, | |||
| * Standard for Information Technology -- Portable Operating System Interface (POSIX), | |||
| * The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute | |||
| * of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any | |||
| * discrepancy between these versions and the original IEEE and The Open Group Standard, | |||
| * the original IEEE and The Open Group Standard is the referee document. The original | |||
| * Standard can be obtained online at http://www.opengroup.org/unix/online.html. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * INCLUDE FILES | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MICRIUM_SOURCE | |||
| #define LIB_MATH_MODULE | |||
| #include <lib_math.h> | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL DEFINES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL CONSTANTS | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL DATA TYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL TABLES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL GLOBAL VARIABLES | |||
| ********************************************************************************************************* | |||
| */ | |||
| RAND_NBR Math_RandSeedCur; /* Cur rand nbr seed. */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL FUNCTION PROTOTYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL CONFIGURATION ERRORS | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * Math_Init() | |||
| * | |||
| * Description : (1) Initialize Mathematic Module : | |||
| * | |||
| * (a) Initialize random number seed value | |||
| * | |||
| * | |||
| * Argument(s) : none. | |||
| * | |||
| * Return(s) : none. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (2) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that "if rand() | |||
| * is called before any calls to srand() are made, the same sequence shall be generated | |||
| * as when srand() is first called with a seed value of 1". | |||
| ********************************************************************************************************* | |||
| */ | |||
| void Math_Init (void) | |||
| { | |||
| Math_RandSetSeed((RAND_NBR)RAND_SEED_INIT_VAL); /* See Note #2. */ | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * Math_RandSetSeed() | |||
| * | |||
| * Description : Set the current pseudo-random number generator seed. | |||
| * | |||
| * Argument(s) : seed Initial (or current) value to set for the pseudo-random number sequence. | |||
| * | |||
| * Return(s) : none. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that "srand() | |||
| * ... uses the argument as a seed for a new sequence of pseudo-random numbers to be | |||
| * returned by subsequent calls to rand()". | |||
| * | |||
| * (2) 'Math_RandSeedCur' MUST always be accessed exclusively in critical sections. | |||
| * | |||
| * See also 'Math_Rand() Note #1b'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void Math_RandSetSeed (RAND_NBR seed) | |||
| { | |||
| CPU_SR_ALLOC(); | |||
| CPU_CRITICAL_ENTER(); | |||
| Math_RandSeedCur = seed; | |||
| CPU_CRITICAL_EXIT(); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * Math_Rand() | |||
| * | |||
| * Description : Calculate the next pseudo-random number. | |||
| * | |||
| * Argument(s) : none. | |||
| * | |||
| * Return(s) : Next pseudo-random number in the sequence after 'Math_RandSeedCur'. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : (1) (a) The pseudo-random number generator is implemented as a Linear Congruential | |||
| * Generator (LCG). | |||
| * | |||
| * (b) The pseudo-random number generated is in the range [0, RAND_LCG_PARAM_M]. | |||
| * | |||
| * See also 'Math_RandSeed() Note #1'. | |||
| * | |||
| * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that "rand() | |||
| * ... need not be reentrant ... [and] is not required to be thread-safe". | |||
| * | |||
| * (b) However, in order to implement Math_Rand() as re-entrant; 'Math_RandSeedCur' MUST | |||
| * always be accessed & updated exclusively in critical sections. | |||
| * | |||
| * See also 'Math_RandSeed() Note #2'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| RAND_NBR Math_Rand (void) | |||
| { | |||
| RAND_NBR seed; | |||
| RAND_NBR rand_nbr; | |||
| CPU_SR_ALLOC(); | |||
| CPU_CRITICAL_ENTER(); | |||
| seed = Math_RandSeedCur; | |||
| rand_nbr = Math_RandSeed(seed); | |||
| Math_RandSeedCur = rand_nbr; | |||
| CPU_CRITICAL_EXIT(); | |||
| return (rand_nbr); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * Math_RandSeed() | |||
| * | |||
| * Description : Calculate the next pseudo-random number. | |||
| * | |||
| * Argument(s) : seed Initial (or current) value for the pseudo-random number sequence. | |||
| * | |||
| * Return(s) : Next pseudo-random number in the sequence after 'seed'. | |||
| * | |||
| * Caller(s) : Math_Rand(), | |||
| * Application. | |||
| * | |||
| * Note(s) : (1) (a) BSD/ANSI-C implements rand() as a Linear Congruential Generator (LCG) : | |||
| * | |||
| * (A) random_number = [(a * random_number ) + b] modulo m | |||
| * n + 1 n | |||
| * | |||
| * where | |||
| * (1) (a) random_number Next random number to generate | |||
| * n+1 | |||
| * (b) random_number Previous random number generated | |||
| * n | |||
| * | |||
| * (2) a = RAND_LCG_PARAM_A LCG multiplier | |||
| * (3) b = RAND_LCG_PARAM_B LCG incrementor | |||
| * (4) m = RAND_LCG_PARAM_M + 1 LCG modulus | |||
| * | |||
| * (b) The pseudo-random number generated is in the range [0, RAND_LCG_PARAM_M]. | |||
| * | |||
| See also 'lib_math.h RANDOM NUMBER DEFINES Note #1b'. | |||
| * | |||
| * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that "rand() | |||
| * ... need not be reentrant ... [and] is not required to be thread-safe". | |||
| * | |||
| * (b) However, Math_RandSeed() is re-entrant since it calculates the next random number | |||
| * using ONLY local variables. | |||
| ********************************************************************************************************* | |||
| */ | |||
| RAND_NBR Math_RandSeed (RAND_NBR seed) | |||
| { | |||
| RAND_NBR rand_nbr; | |||
| rand_nbr = (((RAND_NBR)RAND_LCG_PARAM_A * seed) + (RAND_NBR)RAND_LCG_PARAM_B) % ((RAND_NBR)RAND_LCG_PARAM_M + 1u); | |||
| return (rand_nbr); | |||
| } | |||
| @@ -0,0 +1,298 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/LIB | |||
| * CUSTOM LIBRARY MODULES | |||
| * | |||
| * (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL | |||
| * | |||
| * All rights reserved. Protected by international copyright laws. | |||
| * | |||
| * uC/LIB is provided in source form to registered licensees ONLY. It is | |||
| * illegal to distribute this source code to any third party unless you receive | |||
| * written permission by an authorized Micrium representative. Knowledge of | |||
| * the source code may NOT be used to develop a similar product. | |||
| * | |||
| * Please help us continue to provide the Embedded community with the finest | |||
| * software available. Your honesty is greatly appreciated. | |||
| * | |||
| * You can find our product's user manual, API reference, release notes and | |||
| * more information at: https://doc.micrium.com | |||
| * | |||
| * You can contact us at: http://www.micrium.com | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * | |||
| * MATHEMATIC OPERATIONS | |||
| * | |||
| * Filename : lib_math.h | |||
| * Version : V1.38.01 | |||
| * Programmer(s) : SR | |||
| * ITJ | |||
| ********************************************************************************************************* | |||
| * Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software. | |||
| * | |||
| * (a) ALL standard library functions are implemented in the custom library modules : | |||
| * | |||
| * (1) \<Custom Library Directory>\lib_*.* | |||
| * | |||
| * (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.* | |||
| * | |||
| * where | |||
| * <Custom Library Directory> directory path for custom library software | |||
| * <cpu> directory name for specific processor (CPU) | |||
| * <compiler> directory name for specific compiler | |||
| * | |||
| * (b) Product-specific library functions are implemented in individual products. | |||
| * | |||
| ********************************************************************************************************* | |||
| * Notice(s) : (1) The Institute of Electrical and Electronics Engineers and The Open Group, have given | |||
| * us permission to reprint portions of their documentation. Portions of this text are | |||
| * reprinted and reproduced in electronic form from the IEEE Std 1003.1, 2004 Edition, | |||
| * Standard for Information Technology -- Portable Operating System Interface (POSIX), | |||
| * The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute | |||
| * of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any | |||
| * discrepancy between these versions and the original IEEE and The Open Group Standard, | |||
| * the original IEEE and The Open Group Standard is the referee document. The original | |||
| * Standard can be obtained online at http://www.opengroup.org/unix/online.html. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MODULE | |||
| * | |||
| * Note(s) : (1) This mathematics library header file is protected from multiple pre-processor inclusion | |||
| * through use of the mathematics library module present pre-processor macro definition. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #ifndef LIB_MATH_MODULE_PRESENT /* See Note #1. */ | |||
| #define LIB_MATH_MODULE_PRESENT | |||
| /* | |||
| ********************************************************************************************************* | |||
| * INCLUDE FILES | |||
| * | |||
| * Note(s) : (1) The custom library software files are located in the following directories : | |||
| * | |||
| * (a) \<Custom Library Directory>\lib_*.* | |||
| * | |||
| * where | |||
| * <Custom Library Directory> directory path for custom library software | |||
| * | |||
| * (2) CPU-configuration software files are located in the following directories : | |||
| * | |||
| * (a) \<CPU-Compiler Directory>\cpu_*.* | |||
| * (b) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.* | |||
| * | |||
| * where | |||
| * <CPU-Compiler Directory> directory path for common CPU-compiler software | |||
| * <cpu> directory name for specific processor (CPU) | |||
| * <compiler> directory name for specific compiler | |||
| * | |||
| * (3) Compiler MUST be configured to include as additional include path directories : | |||
| * | |||
| * (a) '\<Custom Library Directory>\' directory See Note #1a | |||
| * | |||
| * (b) (1) '\<CPU-Compiler Directory>\' directory See Note #2a | |||
| * (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory See Note #2b | |||
| * | |||
| * (4) NO compiler-supplied standard library functions SHOULD be used. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #include <cpu.h> | |||
| #include <cpu_core.h> | |||
| #include <lib_def.h> | |||
| /* | |||
| ********************************************************************************************************* | |||
| * EXTERNS | |||
| ********************************************************************************************************* | |||
| */ | |||
| #ifdef LIB_MATH_MODULE | |||
| #define LIB_MATH_EXT | |||
| #else | |||
| #define LIB_MATH_EXT extern | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DEFINES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * RANDOM NUMBER DEFINES | |||
| * | |||
| * Note(s) : (1) (a) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that "if rand() | |||
| * is called before any calls to srand() are made, the same sequence shall be generated | |||
| * as when srand() is first called with a seed value of 1". | |||
| * | |||
| * (b) (1) BSD/ANSI-C implements rand() as a Linear Congruential Generator (LCG) : | |||
| * | |||
| * (A) random_number = [(a * random_number ) + b] modulo m | |||
| * n + 1 n | |||
| * | |||
| * where | |||
| * (1) (a) random_number Next random number to generate | |||
| * n+1 | |||
| * (b) random_number Previous random number generated | |||
| * n | |||
| * (c) random_number Initial random number seed | |||
| * 0 See also Note #1a | |||
| * | |||
| * (2) a = 1103515245 LCG multiplier | |||
| * (3) b = 12345 LCG incrementor | |||
| * (4) m = RAND_MAX + 1 LCG modulus See also Note #1b2 | |||
| * | |||
| * (2) (A) IEEE Std 1003.1, 2004 Edition, Section 'rand() : DESCRIPTION' states that | |||
| * "rand() ... shall compute a sequence of pseudo-random integers in the range | |||
| * [0, {RAND_MAX}] with a period of at least 2^32". | |||
| * | |||
| * (B) However, BSD/ANSI-C 'stdlib.h' defines "RAND_MAX" as "0x7fffffff", or 2^31; | |||
| * which therefore limits the range AND period to no more than 2^31. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define RAND_SEED_INIT_VAL 1u /* See Note #1a. */ | |||
| #define RAND_LCG_PARAM_M 0x7FFFFFFFu /* See Note #1b2B. */ | |||
| #define RAND_LCG_PARAM_A 1103515245u /* See Note #1b1A2. */ | |||
| #define RAND_LCG_PARAM_B 12345u /* See Note #1b1A3. */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DATA TYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * RANDOM NUMBER DATA TYPE | |||
| ********************************************************************************************************* | |||
| */ | |||
| typedef CPU_INT32U RAND_NBR; | |||
| /* | |||
| ********************************************************************************************************* | |||
| * GLOBAL VARIABLES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MACROS | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MATH_IS_PWR2() | |||
| * | |||
| * Description : Determine if a value is a power of 2. | |||
| * | |||
| * Argument(s) : nbr Value. | |||
| * | |||
| * Return(s) : DEF_YES, 'nbr' is a power of 2. | |||
| * | |||
| * DEF_NO, 'nbr' is not a power of 2. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : none. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MATH_IS_PWR2(nbr) ((((nbr) != 0u) && (((nbr) & ((nbr) - 1u)) == 0u)) ? DEF_YES : DEF_NO) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MATH_ROUND_INC_UP_PWR2() | |||
| * | |||
| * Description : Round value up to the next (power of 2) increment. | |||
| * | |||
| * Argument(s) : nbr Value to round. | |||
| * | |||
| * inc Increment to use. MUST be a power of 2. | |||
| * | |||
| * Return(s) : Rounded up value. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : none. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MATH_ROUND_INC_UP_PWR2(nbr, inc) (((nbr) & ~((inc) - 1)) + (((nbr) & ((inc) - 1)) == 0 ? 0 : (inc))) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MATH_ROUND_INC_UP() | |||
| * | |||
| * Description : Round value up to the next increment. | |||
| * | |||
| * Argument(s) : nbr Value to round. | |||
| * | |||
| * inc Increment to use. | |||
| * | |||
| * Return(s) : Rounded up value. | |||
| * | |||
| * Caller(s) : Application. | |||
| * | |||
| * Note(s) : none. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MATH_ROUND_INC_UP(nbr, inc) (((nbr) + ((inc) - 1)) / (inc) * (inc)) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * FUNCTION PROTOTYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| void Math_Init (void); | |||
| /* ------------------ RAND NBR FNCTS ------------------ */ | |||
| void Math_RandSetSeed(RAND_NBR seed); | |||
| RAND_NBR Math_Rand (void); | |||
| RAND_NBR Math_RandSeed (RAND_NBR seed); | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CONFIGURATION ERRORS | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MODULE END | |||
| * | |||
| * Note(s) : (1) See 'lib_math.h MODULE'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #endif /* End of lib math module include. */ | |||
| @@ -0,0 +1,429 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/LIB | |||
| * CUSTOM LIBRARY MODULES | |||
| * | |||
| * (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL | |||
| * | |||
| * All rights reserved. Protected by international copyright laws. | |||
| * | |||
| * uC/LIB is provided in source form to registered licensees ONLY. It is | |||
| * illegal to distribute this source code to any third party unless you receive | |||
| * written permission by an authorized Micrium representative. Knowledge of | |||
| * the source code may NOT be used to develop a similar product. | |||
| * | |||
| * Please help us continue to provide the Embedded community with the finest | |||
| * software available. Your honesty is greatly appreciated. | |||
| * | |||
| * You can find our product's user manual, API reference, release notes and | |||
| * more information at: https://doc.micrium.com | |||
| * | |||
| * You can contact us at: http://www.micrium.com | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * | |||
| * ASCII STRING MANAGEMENT | |||
| * | |||
| * Filename : lib_str.h | |||
| * Version : V1.38.01 | |||
| * Programmer(s) : ITJ | |||
| * JDH | |||
| ********************************************************************************************************* | |||
| * Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software. | |||
| * | |||
| * (a) ALL standard library functions are implemented in the custom library modules : | |||
| * | |||
| * (1) \<Custom Library Directory>\lib_*.* | |||
| * | |||
| * (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.* | |||
| * | |||
| * where | |||
| * <Custom Library Directory> directory path for custom library software | |||
| * <cpu> directory name for specific processor (CPU) | |||
| * <compiler> directory name for specific compiler | |||
| * | |||
| * (b) Product-specific library functions are implemented in individual products. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MODULE | |||
| * | |||
| * Note(s) : (1) This string library header file is protected from multiple pre-processor inclusion through | |||
| * use of the string library module present pre-processor macro definition. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #ifndef LIB_STR_MODULE_PRESENT /* See Note #1. */ | |||
| #define LIB_STR_MODULE_PRESENT | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASCII STRING CONFIGURATION DEFINES | |||
| * | |||
| * Note(s) : (1) Some ASCII string configuration #define's MUST be available PRIOR to including any | |||
| * application configuration (see 'INCLUDE FILES Note #1a'). | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * STRING FLOATING POINT DEFINES | |||
| * | |||
| * Note(s) : (1) (a) (1) The maximum accuracy for 32-bit floating-point numbers : | |||
| * | |||
| * | |||
| * Maximum Accuracy log [Internal-Base ^ (Number-Internal-Base-Digits)] | |||
| * 32-bit Floating-point Number = ----------------------------------------------------- | |||
| * log [External-Base] | |||
| * | |||
| * log [2 ^ 24] | |||
| * = -------------- | |||
| * log [10] | |||
| * | |||
| * < 7.225 Base-10 Digits | |||
| * | |||
| * where | |||
| * Internal-Base Internal number base of floating- | |||
| * point numbers (i.e. 2) | |||
| * External-Base External number base of floating- | |||
| * point numbers (i.e. 10) | |||
| * Number-Internal-Base-Digits Number of internal number base | |||
| * significant digits (i.e. 24) | |||
| * | |||
| * (2) Also, since some 32-bit floating-point calculations are converted to 32-bit | |||
| * unsigned numbers, the maximum accuracy is limited to the maximum accuracy | |||
| * for 32-bit unsigned numbers of 9 digits. | |||
| * | |||
| * (b) Some CPUs' &/or compilers' floating-point implementations MAY further reduce the | |||
| * maximum accuracy. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define LIB_STR_FP_MAX_NBR_DIG_SIG_MIN 1u | |||
| #define LIB_STR_FP_MAX_NBR_DIG_SIG_MAX 9u /* See Note #1a2. */ | |||
| #define LIB_STR_FP_MAX_NBR_DIG_SIG_DFLT 7u /* See Note #1a1. */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * INCLUDE FILES | |||
| * | |||
| * Note(s) : (1) The custom library software files are located in the following directories : | |||
| * | |||
| * (a) \<Your Product Application>\lib_cfg.h | |||
| * | |||
| * (b) \<Custom Library Directory>\lib_*.* | |||
| * | |||
| * where | |||
| * <Your Product Application> directory path for Your Product's Application | |||
| * <Custom Library Directory> directory path for custom library software | |||
| * | |||
| * (2) CPU-configuration software files are located in the following directories : | |||
| * | |||
| * (a) \<CPU-Compiler Directory>\cpu_*.* | |||
| * (b) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.* | |||
| * | |||
| * where | |||
| * <CPU-Compiler Directory> directory path for common CPU-compiler software | |||
| * <cpu> directory name for specific processor (CPU) | |||
| * <compiler> directory name for specific compiler | |||
| * | |||
| * (3) Compiler MUST be configured to include as additional include path directories : | |||
| * | |||
| * (a) '\<Your Product Application>\' directory See Note #1a | |||
| * | |||
| * (b) '\<Custom Library Directory>\' directory See Note #1b | |||
| * | |||
| * (c) (1) '\<CPU-Compiler Directory>\' directory See Note #2a | |||
| * (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory See Note #2b | |||
| * | |||
| * (4) NO compiler-supplied standard library functions SHOULD be used. | |||
| * | |||
| * #### The reference to standard library header files SHOULD be removed once all custom | |||
| * library functions are implemented WITHOUT reference to ANY standard library function(s). | |||
| * | |||
| * See also 'STANDARD LIBRARY MACRO'S Note #1'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #include <cpu.h> | |||
| #include <lib_def.h> | |||
| #include <lib_ascii.h> | |||
| #include <lib_cfg.h> | |||
| #if 0 /* See Note #4. */ | |||
| #include <stdio.h> | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * EXTERNS | |||
| ********************************************************************************************************* | |||
| */ | |||
| #ifdef LIB_STR_MODULE | |||
| #define LIB_STR_EXT | |||
| #else | |||
| #define LIB_STR_EXT extern | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DEFAULT CONFIGURATION | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * STRING FLOATING POINT CONFIGURATION | |||
| * | |||
| * Note(s) : (1) Configure LIB_STR_CFG_FP_EN to enable/disable floating point string function(s). | |||
| * | |||
| * (2) Configure LIB_STR_CFG_FP_MAX_NBR_DIG_SIG to configure the maximum number of significant | |||
| * digits to calculate &/or display for floating point string function(s). | |||
| * | |||
| * See also 'STRING FLOATING POINT DEFINES Note #1'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* Configure floating point feature(s) [see Note #1] : */ | |||
| #ifndef LIB_STR_CFG_FP_EN | |||
| #define LIB_STR_CFG_FP_EN DEF_DISABLED | |||
| /* DEF_DISABLED Floating point functions DISABLED */ | |||
| /* DEF_ENABLED Floating point functions ENABLED */ | |||
| #endif | |||
| /* Configure floating point feature(s)' number of ... */ | |||
| /* ... significant digits (see Note #2). */ | |||
| #ifndef LIB_STR_CFG_FP_MAX_NBR_DIG_SIG | |||
| #define LIB_STR_CFG_FP_MAX_NBR_DIG_SIG LIB_STR_FP_MAX_NBR_DIG_SIG_DFLT | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DEFINES | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define STR_CR_LF "\r\n" | |||
| #define STR_LF_CR "\n\r" | |||
| #define STR_NEW_LINE STR_CR_LF | |||
| #define STR_PARENT_PATH ".." | |||
| #define STR_CR_LF_LEN (sizeof(STR_CR_LF) - 1) | |||
| #define STR_LF_CR_LEN (sizeof(STR_LF_CR) - 1) | |||
| #define STR_NEW_LINE_LEN (sizeof(STR_NEW_LINE) - 1) | |||
| #define STR_PARENT_PATH_LEN (sizeof(STR_PARENT_PATH) - 1) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DATA TYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * GLOBAL VARIABLES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MACRO'S | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * STANDARD LIBRARY MACRO'S | |||
| * | |||
| * Note(s) : (1) NO compiler-supplied standard library functions SHOULD be used. | |||
| * | |||
| * #### The reference to standard memory functions SHOULD be removed once all custom library | |||
| * functions are implemented WITHOUT reference to ANY standard library function(s). | |||
| * | |||
| * See also 'INCLUDE FILES Note #3'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* See Note #1. */ | |||
| #define Str_FmtPrint snprintf | |||
| #define Str_FmtScan sscanf | |||
| /* | |||
| ********************************************************************************************************* | |||
| * FUNCTION PROTOTYPES | |||
| ********************************************************************************************************* | |||
| */ | |||
| /* ------------------ STR LEN FNCTS ------------------ */ | |||
| CPU_SIZE_T Str_Len (const CPU_CHAR *pstr); | |||
| CPU_SIZE_T Str_Len_N (const CPU_CHAR *pstr, | |||
| CPU_SIZE_T len_max); | |||
| /* ------------------ STR COPY FNCTS ------------------ */ | |||
| CPU_CHAR *Str_Copy ( CPU_CHAR *pstr_dest, | |||
| const CPU_CHAR *pstr_src); | |||
| CPU_CHAR *Str_Copy_N ( CPU_CHAR *pstr_dest, | |||
| const CPU_CHAR *pstr_src, | |||
| CPU_SIZE_T len_max); | |||
| CPU_CHAR *Str_Cat ( CPU_CHAR *pstr_dest, | |||
| const CPU_CHAR *pstr_cat); | |||
| CPU_CHAR *Str_Cat_N ( CPU_CHAR *pstr_dest, | |||
| const CPU_CHAR *pstr_cat, | |||
| CPU_SIZE_T len_max); | |||
| /* ------------------ STR CMP FNCTS ------------------ */ | |||
| CPU_INT16S Str_Cmp (const CPU_CHAR *p1_str, | |||
| const CPU_CHAR *p2_str); | |||
| CPU_INT16S Str_Cmp_N (const CPU_CHAR *p1_str, | |||
| const CPU_CHAR *p2_str, | |||
| CPU_SIZE_T len_max); | |||
| CPU_INT16S Str_CmpIgnoreCase (const CPU_CHAR *p1_str, | |||
| const CPU_CHAR *p2_str); | |||
| CPU_INT16S Str_CmpIgnoreCase_N(const CPU_CHAR *p1_str, | |||
| const CPU_CHAR *p2_str, | |||
| CPU_SIZE_T len_max); | |||
| /* ------------------ STR SRCH FNCTS ------------------ */ | |||
| CPU_CHAR *Str_Char (const CPU_CHAR *pstr, | |||
| CPU_CHAR srch_char); | |||
| CPU_CHAR *Str_Char_N (const CPU_CHAR *pstr, | |||
| CPU_SIZE_T len_max, | |||
| CPU_CHAR srch_char); | |||
| CPU_CHAR *Str_Char_Last (const CPU_CHAR *pstr, | |||
| CPU_CHAR srch_char); | |||
| CPU_CHAR *Str_Char_Last_N (const CPU_CHAR *pstr, | |||
| CPU_SIZE_T len_max, | |||
| CPU_CHAR srch_char); | |||
| CPU_CHAR *Str_Char_Replace ( CPU_CHAR *pstr, | |||
| CPU_CHAR char_srch, | |||
| CPU_CHAR char_replace); | |||
| CPU_CHAR *Str_Char_Replace_N ( CPU_CHAR *pstr, | |||
| CPU_CHAR char_srch, | |||
| CPU_CHAR char_replace, | |||
| CPU_SIZE_T len_max); | |||
| CPU_CHAR *Str_Str (const CPU_CHAR *pstr, | |||
| const CPU_CHAR *pstr_srch); | |||
| CPU_CHAR *Str_Str_N (const CPU_CHAR *pstr, | |||
| const CPU_CHAR *pstr_srch, | |||
| CPU_SIZE_T len_max); | |||
| /* ------------------ STR FMT FNCTS ------------------ */ | |||
| CPU_CHAR *Str_FmtNbr_Int32U ( CPU_INT32U nbr, | |||
| CPU_INT08U nbr_dig, | |||
| CPU_INT08U nbr_base, | |||
| CPU_CHAR lead_char, | |||
| CPU_BOOLEAN lower_case, | |||
| CPU_BOOLEAN nul, | |||
| CPU_CHAR *pstr); | |||
| CPU_CHAR *Str_FmtNbr_Int32S ( CPU_INT32S nbr, | |||
| CPU_INT08U nbr_dig, | |||
| CPU_INT08U nbr_base, | |||
| CPU_CHAR lead_char, | |||
| CPU_BOOLEAN lower_case, | |||
| CPU_BOOLEAN nul, | |||
| CPU_CHAR *pstr); | |||
| #if (LIB_STR_CFG_FP_EN == DEF_ENABLED) | |||
| CPU_CHAR *Str_FmtNbr_32 ( CPU_FP32 nbr, | |||
| CPU_INT08U nbr_dig, | |||
| CPU_INT08U nbr_dp, | |||
| CPU_CHAR lead_char, | |||
| CPU_BOOLEAN nul, | |||
| CPU_CHAR *pstr); | |||
| #endif | |||
| /* ----------------- STR PARSE FNCTS ------------------ */ | |||
| CPU_INT32U Str_ParseNbr_Int32U(const CPU_CHAR *pstr, | |||
| CPU_CHAR **pstr_next, | |||
| CPU_INT08U nbr_base); | |||
| CPU_INT32S Str_ParseNbr_Int32S(const CPU_CHAR *pstr, | |||
| CPU_CHAR **pstr_next, | |||
| CPU_INT08U nbr_base); | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CONFIGURATION ERRORS | |||
| ********************************************************************************************************* | |||
| */ | |||
| #ifndef LIB_STR_CFG_FP_EN | |||
| #error "LIB_STR_CFG_FP_EN not #define'd in 'lib_cfg.h'" | |||
| #error " [MUST be DEF_DISABLED] " | |||
| #error " [ || DEF_ENABLED ] " | |||
| #elif ((LIB_STR_CFG_FP_EN != DEF_DISABLED) && \ | |||
| (LIB_STR_CFG_FP_EN != DEF_ENABLED )) | |||
| #error "LIB_STR_CFG_FP_EN illegally #define'd in 'lib_cfg.h'" | |||
| #error " [MUST be DEF_DISABLED] " | |||
| #error " [ || DEF_ENABLED ] " | |||
| #elif (LIB_STR_CFG_FP_EN == DEF_ENABLED) | |||
| #ifndef LIB_STR_CFG_FP_MAX_NBR_DIG_SIG | |||
| #error "LIB_STR_CFG_FP_MAX_NBR_DIG_SIG not #define'd in 'lib_cfg.h' " | |||
| #error " [MUST be >= LIB_STR_FP_MAX_NBR_DIG_SIG_MIN]" | |||
| #error " [ && <= LIB_STR_FP_MAX_NBR_DIG_SIG_MAX]" | |||
| #elif (DEF_CHK_VAL(LIB_STR_CFG_FP_MAX_NBR_DIG_SIG, \ | |||
| LIB_STR_FP_MAX_NBR_DIG_SIG_MIN, \ | |||
| LIB_STR_FP_MAX_NBR_DIG_SIG_MAX) != DEF_OK) | |||
| #error "LIB_STR_CFG_FP_MAX_NBR_DIG_SIG illegally #define'd in 'lib_cfg.h' " | |||
| #error " [MUST be >= LIB_STR_FP_MAX_NBR_DIG_SIG_MIN]" | |||
| #error " [ && <= LIB_STR_FP_MAX_NBR_DIG_SIG_MAX]" | |||
| #endif | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * MODULE END | |||
| * | |||
| * Note(s) : (1) See 'lib_str.h MODULE'. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #endif /* End of lib str module include. */ | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -0,0 +1,624 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/OS-II | |||
| * The Real-Time Kernel | |||
| * | |||
| * | |||
| * (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL | |||
| * All rights reserved. Protected by international copyright laws. | |||
| * | |||
| * ARM Cortex-M4 Port | |||
| * | |||
| * File : OS_CPU_C.C | |||
| * Version : V2.92.09 | |||
| * By : JJL | |||
| * BAN | |||
| * | |||
| * LICENSING TERMS: | |||
| * --------------- | |||
| * uC/OS-II is provided in source form for FREE short-term evaluation, for educational use or | |||
| * for peaceful research. If you plan or intend to use uC/OS-II in a commercial application/ | |||
| * product then, you need to contact Micrium to properly license uC/OS-II for its use in your | |||
| * experience uC/OS-II. The fact that the source is provided does NOT mean that you can use | |||
| * it commercially without paying a licensing fee. | |||
| * | |||
| * Knowledge of the source code may NOT be used to develop a similar product. | |||
| * | |||
| * Please help us continue to provide the embedded community with the finest software available. | |||
| * Your honesty is greatly appreciated. | |||
| * | |||
| * You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036. | |||
| * | |||
| * For : ARMv7 Cortex-M4 | |||
| * Mode : Thumb-2 ISA | |||
| * Toolchain : IAR EWARM | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define OS_CPU_GLOBALS | |||
| /* | |||
| ********************************************************************************************************* | |||
| * INCLUDE FILES | |||
| ********************************************************************************************************* | |||
| */ | |||
| #include <ucos_ii.h> | |||
| #include <lib_def.h> | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL VARIABLES | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_TMR_EN > 0u | |||
| static INT16U OSTmrCtr; | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * SYS TICK DEFINES | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define OS_CPU_CM4_NVIC_ST_CTRL (*((volatile INT32U *)0xE000E010uL)) /* SysTick Ctrl & Status Reg. */ | |||
| #define OS_CPU_CM4_NVIC_ST_RELOAD (*((volatile INT32U *)0xE000E014uL)) /* SysTick Reload Value Reg. */ | |||
| #define OS_CPU_CM4_NVIC_ST_CURRENT (*((volatile INT32U *)0xE000E018uL)) /* SysTick Current Value Reg. */ | |||
| #define OS_CPU_CM4_NVIC_ST_CAL (*((volatile INT32U *)0xE000E01CuL)) /* SysTick Cal Value Reg. */ | |||
| #define OS_CPU_CM4_NVIC_SHPRI1 (*((volatile INT32U *)0xE000ED18uL)) /* System Handlers 4 to 7 Prio. */ | |||
| #define OS_CPU_CM4_NVIC_SHPRI2 (*((volatile INT32U *)0xE000ED1CuL)) /* System Handlers 8 to 11 Prio. */ | |||
| #define OS_CPU_CM4_NVIC_SHPRI3 (*((volatile INT32U *)0xE000ED20uL)) /* System Handlers 12 to 15 Prio. */ | |||
| #define OS_CPU_CM4_NVIC_ST_CTRL_COUNT 0x00010000uL /* Count flag. */ | |||
| #define OS_CPU_CM4_NVIC_ST_CTRL_CLK_SRC 0x00000004uL /* Clock Source. */ | |||
| #define OS_CPU_CM4_NVIC_ST_CTRL_INTEN 0x00000002uL /* Interrupt enable. */ | |||
| #define OS_CPU_CM4_NVIC_ST_CTRL_ENABLE 0x00000001uL /* Counter mode. */ | |||
| #define OS_CPU_CM4_NVIC_PRIO_MIN 0xFFu /* Min handler prio. */ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * OS INITIALIZATION HOOK | |||
| * (BEGINNING) | |||
| * | |||
| * Description: This function is called by OSInit() at the beginning of OSInit(). | |||
| * | |||
| * Arguments : none | |||
| * | |||
| * Note(s) : 1) Interrupts should be disabled during this call. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_CPU_HOOKS_EN > 0u | |||
| void OSInitHookBegin (void) | |||
| { | |||
| INT32U size; | |||
| OS_STK *pstk; | |||
| /* Clear exception stack for stack checking. */ | |||
| pstk = &OS_CPU_ExceptStk[0]; | |||
| size = OS_CPU_EXCEPT_STK_SIZE; | |||
| while (size > 0u) { | |||
| size--; | |||
| *pstk++ = (OS_STK)0; | |||
| } | |||
| /* Align the ISR stack to 8-bytes */ | |||
| OS_CPU_ExceptStkBase = (OS_STK *)&OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; | |||
| OS_CPU_ExceptStkBase = (OS_STK *)((OS_STK)(OS_CPU_ExceptStkBase) & 0xFFFFFFF8); | |||
| #if OS_TMR_EN > 0u | |||
| OSTmrCtr = 0u; | |||
| #endif | |||
| } | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * OS INITIALIZATION HOOK | |||
| * (END) | |||
| * | |||
| * Description: This function is called by OSInit() at the end of OSInit(). | |||
| * | |||
| * Arguments : none | |||
| * | |||
| * Note(s) : 1) Interrupts should be disabled during this call. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_CPU_HOOKS_EN > 0u | |||
| void OSInitHookEnd (void) | |||
| { | |||
| } | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * TASK CREATION HOOK | |||
| * | |||
| * Description: This function is called when a task is created. | |||
| * | |||
| * Arguments : ptcb is a pointer to the task control block of the task being created. | |||
| * | |||
| * Note(s) : 1) Interrupts are disabled during this call. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_CPU_HOOKS_EN > 0u | |||
| void OSTaskCreateHook (OS_TCB *ptcb) | |||
| { | |||
| #if OS_APP_HOOKS_EN > 0u | |||
| App_TaskCreateHook(ptcb); | |||
| #else | |||
| (void)ptcb; /* Prevent compiler warning */ | |||
| #endif | |||
| } | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * TASK DELETION HOOK | |||
| * | |||
| * Description: This function is called when a task is deleted. | |||
| * | |||
| * Arguments : ptcb is a pointer to the task control block of the task being deleted. | |||
| * | |||
| * Note(s) : 1) Interrupts are disabled during this call. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_CPU_HOOKS_EN > 0u | |||
| void OSTaskDelHook (OS_TCB *ptcb) | |||
| { | |||
| #if OS_APP_HOOKS_EN > 0u | |||
| App_TaskDelHook(ptcb); | |||
| #else | |||
| (void)ptcb; /* Prevent compiler warning */ | |||
| #endif | |||
| } | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * IDLE TASK HOOK | |||
| * | |||
| * Description: This function is called by the idle task. This hook has been added to allow you to do | |||
| * such things as STOP the CPU to conserve power. | |||
| * | |||
| * Arguments : none | |||
| * | |||
| * Note(s) : 1) Interrupts are enabled during this call. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_CPU_HOOKS_EN > 0u | |||
| void OSTaskIdleHook (void) | |||
| { | |||
| #if OS_APP_HOOKS_EN > 0u | |||
| App_TaskIdleHook(); | |||
| #endif | |||
| } | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * TASK RETURN HOOK | |||
| * | |||
| * Description: This function is called if a task accidentally returns. In other words, a task should | |||
| * either be an infinite loop or delete itself when done. | |||
| * | |||
| * Arguments : ptcb is a pointer to the task control block of the task that is returning. | |||
| * | |||
| * Note(s) : none | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_CPU_HOOKS_EN > 0u | |||
| void OSTaskReturnHook (OS_TCB *ptcb) | |||
| { | |||
| #if OS_APP_HOOKS_EN > 0u | |||
| App_TaskReturnHook(ptcb); | |||
| #else | |||
| (void)ptcb; | |||
| #endif | |||
| } | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * STATISTIC TASK HOOK | |||
| * | |||
| * Description: This function is called every second by uC/OS-II's statistics task. This allows your | |||
| * application to add functionality to the statistics task. | |||
| * | |||
| * Arguments : none | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_CPU_HOOKS_EN > 0u | |||
| void OSTaskStatHook (void) | |||
| { | |||
| #if OS_APP_HOOKS_EN > 0u | |||
| App_TaskStatHook(); | |||
| #endif | |||
| } | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * INITIALIZE A TASK'S STACK | |||
| * | |||
| * Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the | |||
| * stack frame of the task being created. This function is highly processor specific. | |||
| * | |||
| * Arguments : task is a pointer to the task code | |||
| * | |||
| * p_arg is a pointer to a user supplied data area that will be passed to the task | |||
| * when the task first executes. | |||
| * | |||
| * ptos is a pointer to the top of stack. It is assumed that 'ptos' points to | |||
| * a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then | |||
| * 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if | |||
| * OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address | |||
| * of the stack. | |||
| * | |||
| * opt specifies options that can be used to alter the behavior of OSTaskStkInit(). | |||
| * (see uCOS_II.H for OS_TASK_OPT_xxx). | |||
| * | |||
| * Returns : Always returns the location of the new top-of-stack once the processor registers have | |||
| * been placed on the stack in the proper order. | |||
| * | |||
| * Note(s) : (1) Interrupts are enabled when task starts executing. | |||
| * | |||
| * (2) All tasks run in Thread mode, using process stack. | |||
| * | |||
| * (3) There are two different stack frames depending on whether the Floating-Point(FP) | |||
| * co-processor is enabled or not. | |||
| * | |||
| * (a) The stack frame shown in the diagram is used when the FP co-processor is not present and | |||
| * OS_TASK_OPT_SAVE_FP is disabled. In this case, the FP registers and FP Status Control | |||
| * register are not saved in the stack frame. | |||
| * | |||
| * (b) If the FP co-processor is present but the OS_TASK_OPT_SAVE_FP is not set, then the stack | |||
| * frame is saved as shown in diagram (a). Moreover, if OS_TASK_OPT_SAVE_FP is set, then the | |||
| * FP registers and FP Status Control register are saved in the stack frame. | |||
| * | |||
| * (1) When enabling the FP co-processor, make sure to clear bits ASPEN and LSPEN in the | |||
| * Floating-Point Context Control Register (FPCCR). | |||
| * | |||
| * +------------+ +------------+ | |||
| * | | | | | |||
| * +------------+ +------------+ | |||
| * | xPSR | | xPSR | | |||
| * +------------+ +------------+ | |||
| * |Return Addr | |Return Addr | | |||
| * +------------+ +------------+ | |||
| * | LR(R14) | | LR(R14) | | |||
| * +------------+ +------------+ | |||
| * | R12 | | R12 | | |||
| * +------------+ +------------+ | |||
| * | R3 | | R3 | | |||
| * +------------+ +------------+ | |||
| * | R2 | | R0 | | |||
| * +------------+ +------------+ | |||
| * | R1 | | R1 | | |||
| * +------------+ +------------+ | |||
| * | R0 | | R0 | | |||
| * +------------+ +------------+ | |||
| * | R11 | | R11 | | |||
| * +------------+ +------------+ | |||
| * | R10 | | R10 | | |||
| * +------------+ +------------+ | |||
| * | R9 | | R9 | | |||
| * +------------+ +------------+ | |||
| * | R8 | | R8 | | |||
| * +------------+ +------------+ | |||
| * | R7 | | R7 | | |||
| * +------------+ +------------+ | |||
| * | R6 | | R6 | | |||
| * +------------+ +------------+ | |||
| * | R5 | | R5 | | |||
| * +------------+ +------------+ | |||
| * | R4 | | R4 | | |||
| * +------------+ +------------+ | |||
| * (a) | FPSCR | | |||
| * +------------+ | |||
| * | S31 | | |||
| * +------------+ | |||
| * . | |||
| * . | |||
| * . | |||
| * +------------+ | |||
| * | S1 | | |||
| +------------+ | |||
| * | S0 | | |||
| * +------------+ | |||
| * (b) | |||
| * | |||
| * (4) The SP must be 8-byte aligned in conforming to the Procedure Call Standard for the ARM architecture | |||
| * | |||
| * (a) Section 2.1 of the ABI for the ARM Architecture Advisory Note. SP must be 8-byte aligned | |||
| * on entry to AAPCS-Conforming functions states : | |||
| * | |||
| * The Procedure Call Standard for the ARM Architecture [AAPCS] requires primitive | |||
| * data types to be naturally aligned according to their sizes (for size = 1, 2, 4, 8 bytes). | |||
| * Doing otherwise creates more problems than it solves. | |||
| * | |||
| * In return for preserving the natural alignment of data, conforming code is permitted | |||
| * to rely on that alignment. To support aligning data allocated on the stack, the stack | |||
| * pointer (SP) is required to be 8-byte aligned on entry to a conforming function. In | |||
| * practice this requirement is met if: | |||
| * | |||
| * (1) At each call site, the current size of the calling function’s stack frame is a multiple of 8 bytes. | |||
| * This places an obligation on compilers and assembly language programmers. | |||
| * | |||
| * (2) SP is a multiple of 8 when control first enters a program. | |||
| * This places an obligation on authors of low level OS, RTOS, and runtime library | |||
| * code to align SP at all points at which control first enters | |||
| * a body of (AAPCS-conforming) code. | |||
| * | |||
| * In turn, this requires the value of SP to be aligned to 0 modulo 8: | |||
| * | |||
| * (3) By exception handlers, before calling AAPCS-conforming code. | |||
| * | |||
| * (4) By OS/RTOS/run-time system code, before giving control to an application. | |||
| * | |||
| * (b) Section 2.3.1 corrective steps from the the SP must be 8-byte aligned on entry | |||
| * to AAPCS-conforming functions advisory note also states. | |||
| * | |||
| * " This requirement extends to operating systems and run-time code for all architecture versions | |||
| * prior to ARMV7 and to the A, R and M architecture profiles thereafter. Special considerations | |||
| * associated with ARMV7M are discussed in §2.3.3" | |||
| * | |||
| * (1) Even if the SP 8-byte aligment is not a requirement for the ARMv7M profile, the stack is aligned | |||
| * to 8-byte boundaries to support legacy execution enviroments. | |||
| * | |||
| * (c) Section 5.2.1.2 from the Procedure Call Standard for the ARM | |||
| * architecture states : "The stack must also conform to the following | |||
| * constraint at a public interface: | |||
| * | |||
| * (1) SP mod 8 = 0. The stack must be double-word aligned" | |||
| * | |||
| * (d) From the ARM Technical Support Knowledge Base. 8 Byte stack aligment. | |||
| * | |||
| * "8 byte stack alignment is a requirement of the ARM Architecture Procedure | |||
| * Call Standard [AAPCS]. This specifies that functions must maintain an 8 byte | |||
| * aligned stack address (e.g. 0x00, 0x08, 0x10, 0x18, 0x20) on all external | |||
| * interfaces. In practice this requirement is met if: | |||
| * | |||
| * (1) At each external interface, the current stack pointer | |||
| * is a multiple of 8 bytes. | |||
| * | |||
| * (2) Your OS maintains 8 byte stack alignment on its external interfaces | |||
| * e.g. on task switches" | |||
| * | |||
| ********************************************************************************************************** | |||
| */ | |||
| OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) | |||
| { | |||
| OS_STK *p_stk; | |||
| p_stk = ptos + 1u; /* Load stack pointer */ | |||
| /* Align the stack to 8-bytes. */ | |||
| p_stk = (OS_STK *)((OS_STK)(p_stk) & 0xFFFFFFF8u); | |||
| /* Registers stacked as if auto-saved on exception */ | |||
| *(--p_stk) = (OS_STK)0x01000000uL; /* xPSR */ | |||
| *(--p_stk) = (OS_STK)task; /* Entry Point */ | |||
| *(--p_stk) = (OS_STK)OS_TaskReturn; /* R14 (LR) */ | |||
| *(--p_stk) = (OS_STK)0x12121212uL; /* R12 */ | |||
| *(--p_stk) = (OS_STK)0x03030303uL; /* R3 */ | |||
| *(--p_stk) = (OS_STK)0x02020202uL; /* R2 */ | |||
| *(--p_stk) = (OS_STK)0x01010101uL; /* R1 */ | |||
| *(--p_stk) = (OS_STK)p_arg; /* R0 : argument */ | |||
| /* Remaining registers saved on process stack */ | |||
| *(--p_stk) = (OS_STK)0x11111111uL; /* R11 */ | |||
| *(--p_stk) = (OS_STK)0x10101010uL; /* R10 */ | |||
| *(--p_stk) = (OS_STK)0x09090909uL; /* R9 */ | |||
| *(--p_stk) = (OS_STK)0x08080808uL; /* R8 */ | |||
| *(--p_stk) = (OS_STK)0x07070707uL; /* R7 */ | |||
| *(--p_stk) = (OS_STK)0x06060606uL; /* R6 */ | |||
| *(--p_stk) = (OS_STK)0x05050505uL; /* R5 */ | |||
| *(--p_stk) = (OS_STK)0x04040404uL; /* R4 */ | |||
| #if (OS_CPU_ARM_FP_EN > 0u) | |||
| if ((opt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) { | |||
| *--p_stk = (OS_STK)0x02000000u; /* FPSCR */ | |||
| /* Initialize S0-S31 floating point registers */ | |||
| *--p_stk = (OS_STK)0x41F80000u; /* S31 */ | |||
| *--p_stk = (OS_STK)0x41F00000u; /* S30 */ | |||
| *--p_stk = (OS_STK)0x41E80000u; /* S29 */ | |||
| *--p_stk = (OS_STK)0x41E00000u; /* S28 */ | |||
| *--p_stk = (OS_STK)0x41D80000u; /* S27 */ | |||
| *--p_stk = (OS_STK)0x41D00000u; /* S26 */ | |||
| *--p_stk = (OS_STK)0x41C80000u; /* S25 */ | |||
| *--p_stk = (OS_STK)0x41C00000u; /* S24 */ | |||
| *--p_stk = (OS_STK)0x41B80000u; /* S23 */ | |||
| *--p_stk = (OS_STK)0x41B00000u; /* S22 */ | |||
| *--p_stk = (OS_STK)0x41A80000u; /* S21 */ | |||
| *--p_stk = (OS_STK)0x41A00000u; /* S20 */ | |||
| *--p_stk = (OS_STK)0x41980000u; /* S19 */ | |||
| *--p_stk = (OS_STK)0x41900000u; /* S18 */ | |||
| *--p_stk = (OS_STK)0x41880000u; /* S17 */ | |||
| *--p_stk = (OS_STK)0x41800000u; /* S16 */ | |||
| *--p_stk = (OS_STK)0x41700000u; /* S15 */ | |||
| *--p_stk = (OS_STK)0x41600000u; /* S14 */ | |||
| *--p_stk = (OS_STK)0x41500000u; /* S13 */ | |||
| *--p_stk = (OS_STK)0x41400000u; /* S12 */ | |||
| *--p_stk = (OS_STK)0x41300000u; /* S11 */ | |||
| *--p_stk = (OS_STK)0x41200000u; /* S10 */ | |||
| *--p_stk = (OS_STK)0x41100000u; /* S9 */ | |||
| *--p_stk = (OS_STK)0x41000000u; /* S8 */ | |||
| *--p_stk = (OS_STK)0x40E00000u; /* S7 */ | |||
| *--p_stk = (OS_STK)0x40C00000u; /* S6 */ | |||
| *--p_stk = (OS_STK)0x40A00000u; /* S5 */ | |||
| *--p_stk = (OS_STK)0x40800000u; /* S4 */ | |||
| *--p_stk = (OS_STK)0x40400000u; /* S3 */ | |||
| *--p_stk = (OS_STK)0x40000000u; /* S2 */ | |||
| *--p_stk = (OS_STK)0x3F800000u; /* S1 */ | |||
| *--p_stk = (OS_STK)0x00000000u; /* S0 */ | |||
| } | |||
| #endif | |||
| return (p_stk); | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * TASK SWITCH HOOK | |||
| * | |||
| * Description: This function is called when a task switch is performed. This allows you to perform other | |||
| * operations during a context switch. | |||
| * | |||
| * Arguments : none | |||
| * | |||
| * Note(s) : 1) Interrupts are disabled during this call. | |||
| * 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that | |||
| * will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the | |||
| * task being switched out (i.e. the preempted task). | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) | |||
| void OSTaskSwHook (void) | |||
| { | |||
| #if (OS_CPU_ARM_FP_EN > 0u) | |||
| if ((OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) { | |||
| OS_CPU_FP_Reg_Push(OSTCBCur->OSTCBStkPtr); | |||
| } | |||
| if ((OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) { | |||
| OS_CPU_FP_Reg_Pop(OSTCBHighRdy->OSTCBStkPtr); | |||
| } | |||
| #endif | |||
| #if OS_APP_HOOKS_EN > 0u | |||
| App_TaskSwHook(); | |||
| #endif | |||
| } | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * OS_TCBInit() HOOK | |||
| * | |||
| * Description: This function is called by OS_TCBInit() after setting up most of the TCB. | |||
| * | |||
| * Arguments : ptcb is a pointer to the TCB of the task being created. | |||
| * | |||
| * Note(s) : 1) Interrupts may or may not be ENABLED during this call. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_CPU_HOOKS_EN > 0u | |||
| void OSTCBInitHook (OS_TCB *ptcb) | |||
| { | |||
| #if OS_APP_HOOKS_EN > 0u | |||
| App_TCBInitHook(ptcb); | |||
| #else | |||
| (void)ptcb; /* Prevent compiler warning */ | |||
| #endif | |||
| } | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * TICK HOOK | |||
| * | |||
| * Description: This function is called every tick. | |||
| * | |||
| * Arguments : none | |||
| * | |||
| * Note(s) : 1) Interrupts may or may not be ENABLED during this call. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) | |||
| void OSTimeTickHook (void) | |||
| { | |||
| #if OS_APP_HOOKS_EN > 0u | |||
| App_TimeTickHook(); | |||
| #endif | |||
| #if OS_TMR_EN > 0u | |||
| OSTmrCtr++; | |||
| if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { | |||
| OSTmrCtr = 0; | |||
| OSTmrSignal(); | |||
| } | |||
| #endif | |||
| } | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * SYS TICK HANDLER | |||
| * | |||
| * Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-II tick | |||
| * interrupt. | |||
| * | |||
| * Arguments : None. | |||
| * | |||
| * Note(s) : 1) This function MUST be placed on entry 15 of the Cortex-M3 vector table. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void OS_CPU_SysTickHandler (void) | |||
| { | |||
| OS_CPU_SR cpu_sr; | |||
| OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */ | |||
| OSIntNesting++; | |||
| OS_EXIT_CRITICAL(); | |||
| OSTimeTick(); /* Call uC/OS-II's OSTimeTick() */ | |||
| OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR */ | |||
| } | |||
| /* | |||
| ********************************************************************************************************* | |||
| * INITIALIZE SYS TICK | |||
| * | |||
| * Description: Initialize the SysTick. | |||
| * | |||
| * Arguments : cnts Number of SysTick counts between two OS tick interrupts. | |||
| * | |||
| * Note(s) : 1) This function MUST be called after OSStart() & after processor initialization. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void OS_CPU_SysTickInit (INT32U cnts) | |||
| { | |||
| INT32U prio; | |||
| OS_CPU_CM4_NVIC_ST_RELOAD = cnts - 1u; | |||
| /* Set SysTick handler prio. */ | |||
| prio = OS_CPU_CM4_NVIC_SHPRI3; | |||
| prio &= DEF_BIT_FIELD(24, 0); | |||
| prio |= DEF_BIT_MASK(OS_CPU_CFG_SYSTICK_PRIO, 24); | |||
| OS_CPU_CM4_NVIC_SHPRI3 = prio; | |||
| /* Enable timer. */ | |||
| OS_CPU_CM4_NVIC_ST_CTRL |= OS_CPU_CM4_NVIC_ST_CTRL_CLK_SRC | | |||
| OS_CPU_CM4_NVIC_ST_CTRL_ENABLE; | |||
| /* Enable timer interrupt. */ | |||
| OS_CPU_CM4_NVIC_ST_CTRL |= OS_CPU_CM4_NVIC_ST_CTRL_INTEN; | |||
| } | |||
| @@ -0,0 +1,315 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/OS-II | |||
| * The Real-Time Kernel | |||
| * DEBUGGER CONSTANTS | |||
| * | |||
| * (c) Copyright 1992-2009, Micrium, Weston, FL | |||
| * All Rights Reserved | |||
| * | |||
| * File : OS_DBG.C | |||
| * By : Jean J. Labrosse | |||
| * Version : V2.92.09 | |||
| * | |||
| * LICENSING TERMS: | |||
| * --------------- | |||
| * uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research. | |||
| * If you plan on using uC/OS-II in a commercial product you need to contact Micriµm to properly license | |||
| * its use in your product. We provide ALL the source code for your convenience and to help you experience | |||
| * uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a | |||
| * licensing fee. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #include <ucos_ii.h> | |||
| #define OS_COMPILER_OPT __root | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DEBUG DATA | |||
| ********************************************************************************************************* | |||
| */ | |||
| OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ | |||
| #if OS_DEBUG_EN > 0u | |||
| OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ | |||
| OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; | |||
| OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ | |||
| OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; | |||
| #if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) | |||
| OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ | |||
| OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ | |||
| #else | |||
| OS_COMPILER_OPT INT16U const OSEventSize = 0u; | |||
| OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; | |||
| #endif | |||
| OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; | |||
| OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; | |||
| #if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) | |||
| OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ | |||
| OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ | |||
| OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ | |||
| #else | |||
| OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; | |||
| OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; | |||
| OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; | |||
| #endif | |||
| OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; | |||
| OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; | |||
| OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; | |||
| OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; | |||
| OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; | |||
| OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ | |||
| OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; | |||
| #if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) | |||
| OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ | |||
| OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); | |||
| #else | |||
| OS_COMPILER_OPT INT16U const OSMemSize = 0u; | |||
| OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; | |||
| #endif | |||
| OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; | |||
| OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ | |||
| OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; | |||
| OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ | |||
| #if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) | |||
| OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ | |||
| #else | |||
| OS_COMPILER_OPT INT16U const OSQSize = 0u; | |||
| #endif | |||
| OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ | |||
| OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; | |||
| OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ | |||
| OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; | |||
| OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; | |||
| OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; | |||
| OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; | |||
| OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; | |||
| OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ | |||
| OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; | |||
| OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; | |||
| OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; | |||
| OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; | |||
| OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; | |||
| OS_COMPILER_OPT INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; | |||
| OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ | |||
| OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ | |||
| OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; | |||
| OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; | |||
| OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; | |||
| OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; | |||
| OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; | |||
| OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; | |||
| OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; | |||
| OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; | |||
| #if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) | |||
| OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); | |||
| OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); | |||
| OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); | |||
| OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); | |||
| #else | |||
| OS_COMPILER_OPT INT16U const OSTmrSize = 0u; | |||
| OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; | |||
| OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; | |||
| OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; | |||
| #endif | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DEBUG DATA | |||
| * TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_DEBUG_EN > 0u | |||
| OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) | |||
| #if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) | |||
| + sizeof(OSEventFreeList) | |||
| + sizeof(OSEventTbl) | |||
| #endif | |||
| #if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) | |||
| + sizeof(OSFlagTbl) | |||
| + sizeof(OSFlagFreeList) | |||
| #endif | |||
| #if OS_TASK_STAT_EN > 0u | |||
| + sizeof(OSCPUUsage) | |||
| + sizeof(OSIdleCtrMax) | |||
| + sizeof(OSIdleCtrRun) | |||
| + sizeof(OSStatRdy) | |||
| + sizeof(OSTaskStatStk) | |||
| #endif | |||
| #if OS_TICK_STEP_EN > 0u | |||
| + sizeof(OSTickStepState) | |||
| #endif | |||
| #if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) | |||
| + sizeof(OSMemFreeList) | |||
| + sizeof(OSMemTbl) | |||
| #endif | |||
| #if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) | |||
| + sizeof(OSQFreeList) | |||
| + sizeof(OSQTbl) | |||
| #endif | |||
| #if OS_TIME_GET_SET_EN > 0u | |||
| + sizeof(OSTime) | |||
| #endif | |||
| #if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) | |||
| + sizeof(OSTmrFree) | |||
| + sizeof(OSTmrUsed) | |||
| + sizeof(OSTmrTime) | |||
| + sizeof(OSTmrSem) | |||
| + sizeof(OSTmrSemSignal) | |||
| + sizeof(OSTmrTbl) | |||
| + sizeof(OSTmrFreeList) | |||
| + sizeof(OSTmrTaskStk) | |||
| + sizeof(OSTmrWheelTbl) | |||
| #endif | |||
| + sizeof(OSIntNesting) | |||
| + sizeof(OSLockNesting) | |||
| + sizeof(OSPrioCur) | |||
| + sizeof(OSPrioHighRdy) | |||
| + sizeof(OSRdyGrp) | |||
| + sizeof(OSRdyTbl) | |||
| + sizeof(OSRunning) | |||
| + sizeof(OSTaskCtr) | |||
| + sizeof(OSIdleCtr) | |||
| + sizeof(OSTaskIdleStk) | |||
| + sizeof(OSTCBCur) | |||
| + sizeof(OSTCBFreeList) | |||
| + sizeof(OSTCBHighRdy) | |||
| + sizeof(OSTCBList) | |||
| + sizeof(OSTCBPrioTbl) | |||
| + sizeof(OSTCBTbl); | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * OS DEBUG INITIALIZATION | |||
| * | |||
| * Description: This function is used to make sure that debug variables that are unused in the application | |||
| * are not optimized away. This function might not be necessary for all compilers. In this | |||
| * case, you should simply DELETE the code in this function while still leaving the declaration | |||
| * of the function itself. | |||
| * | |||
| * Arguments : none | |||
| * | |||
| * Returns : none | |||
| * | |||
| * Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out | |||
| * the 'const' variables which are declared in this file. | |||
| * (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function | |||
| * if your compiler DOES NOT optimize out the 'const' variables above. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_DEBUG_EN > 0u | |||
| void OSDebugInit (void) | |||
| { | |||
| void *ptemp; | |||
| ptemp = (void *)&OSDebugEn; | |||
| ptemp = (void *)&OSEndiannessTest; | |||
| ptemp = (void *)&OSEventMax; | |||
| ptemp = (void *)&OSEventNameEn; | |||
| ptemp = (void *)&OSEventEn; | |||
| ptemp = (void *)&OSEventSize; | |||
| ptemp = (void *)&OSEventTblSize; | |||
| ptemp = (void *)&OSEventMultiEn; | |||
| ptemp = (void *)&OSFlagEn; | |||
| ptemp = (void *)&OSFlagGrpSize; | |||
| ptemp = (void *)&OSFlagNodeSize; | |||
| ptemp = (void *)&OSFlagWidth; | |||
| ptemp = (void *)&OSFlagMax; | |||
| ptemp = (void *)&OSFlagNameEn; | |||
| ptemp = (void *)&OSLowestPrio; | |||
| ptemp = (void *)&OSMboxEn; | |||
| ptemp = (void *)&OSMemEn; | |||
| ptemp = (void *)&OSMemMax; | |||
| ptemp = (void *)&OSMemNameEn; | |||
| ptemp = (void *)&OSMemSize; | |||
| ptemp = (void *)&OSMemTblSize; | |||
| ptemp = (void *)&OSMutexEn; | |||
| ptemp = (void *)&OSPtrSize; | |||
| ptemp = (void *)&OSQEn; | |||
| ptemp = (void *)&OSQMax; | |||
| ptemp = (void *)&OSQSize; | |||
| ptemp = (void *)&OSRdyTblSize; | |||
| ptemp = (void *)&OSSemEn; | |||
| ptemp = (void *)&OSStkWidth; | |||
| ptemp = (void *)&OSTaskCreateEn; | |||
| ptemp = (void *)&OSTaskCreateExtEn; | |||
| ptemp = (void *)&OSTaskDelEn; | |||
| ptemp = (void *)&OSTaskIdleStkSize; | |||
| ptemp = (void *)&OSTaskProfileEn; | |||
| ptemp = (void *)&OSTaskMax; | |||
| ptemp = (void *)&OSTaskNameEn; | |||
| ptemp = (void *)&OSTaskStatEn; | |||
| ptemp = (void *)&OSTaskStatStkSize; | |||
| ptemp = (void *)&OSTaskStatStkChkEn; | |||
| ptemp = (void *)&OSTaskSwHookEn; | |||
| ptemp = (void *)&OSTCBPrioTblMax; | |||
| ptemp = (void *)&OSTCBSize; | |||
| ptemp = (void *)&OSTicksPerSec; | |||
| ptemp = (void *)&OSTimeTickHookEn; | |||
| #if OS_TMR_EN > 0u | |||
| ptemp = (void *)&OSTmrTbl[0]; | |||
| ptemp = (void *)&OSTmrWheelTbl[0]; | |||
| ptemp = (void *)&OSTmrEn; | |||
| ptemp = (void *)&OSTmrCfgMax; | |||
| ptemp = (void *)&OSTmrCfgNameEn; | |||
| ptemp = (void *)&OSTmrCfgWheelSize; | |||
| ptemp = (void *)&OSTmrCfgTicksPerSec; | |||
| ptemp = (void *)&OSTmrSize; | |||
| ptemp = (void *)&OSTmrTblSize; | |||
| ptemp = (void *)&OSTmrWheelSize; | |||
| ptemp = (void *)&OSTmrWheelTblSize; | |||
| #endif | |||
| ptemp = (void *)&OSVersionNbr; | |||
| ptemp = (void *)&OSDataSize; | |||
| ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,29 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/OS-II | |||
| * The Real-Time Kernel | |||
| * | |||
| * (c) Copyright 1992-2013, Micrium, Weston, FL | |||
| * All Rights Reserved | |||
| * | |||
| * File : os.h | |||
| * By : Jean J. Labrosse | |||
| * Version : V2.92.10 | |||
| * | |||
| * LICENSING TERMS: | |||
| * --------------- | |||
| * uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research. | |||
| * If you plan on using uC/OS-II in a commercial product you need to contact Micrium to properly license | |||
| * its use in your product. We provide ALL the source code for your convenience and to help you experience | |||
| * uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a | |||
| * licensing fee. | |||
| * | |||
| * Note : This file is included in the uC/OS-II for compatibility with uC/OS-III and should not be used | |||
| * in normal circumstances. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #include <ucos_ii.h> | |||
| typedef INT8U OS_ERR; | |||
| @@ -0,0 +1,654 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/OS-II | |||
| * The Real-Time Kernel | |||
| * MESSAGE MAILBOX MANAGEMENT | |||
| * | |||
| * (c) Copyright 1992-2013, Micrium, Weston, FL | |||
| * All Rights Reserved | |||
| * | |||
| * File : OS_MBOX.C | |||
| * By : Jean J. Labrosse | |||
| * Version : V2.92.11 | |||
| * | |||
| * LICENSING TERMS: | |||
| * --------------- | |||
| * uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research. | |||
| * If you plan on using uC/OS-II in a commercial product you need to contact Micrium to properly license | |||
| * its use in your product. We provide ALL the source code for your convenience and to help you experience | |||
| * uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a | |||
| * licensing fee. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MICRIUM_SOURCE | |||
| #ifndef OS_MASTER_FILE | |||
| #include <ucos_ii.h> | |||
| #endif | |||
| #if OS_MBOX_EN > 0u | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ACCEPT MESSAGE FROM MAILBOX | |||
| * | |||
| * Description: This function checks the mailbox to see if a message is available. Unlike OSMboxPend(), | |||
| * OSMboxAccept() does not suspend the calling task if a message is not available. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block | |||
| * | |||
| * Returns : != (void *)0 is the message in the mailbox if one is available. The mailbox is cleared | |||
| * so the next time OSMboxAccept() is called, the mailbox will be empty. | |||
| * == (void *)0 if the mailbox is empty or, | |||
| * if 'pevent' is a NULL pointer or, | |||
| * if you didn't pass the proper event pointer. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MBOX_ACCEPT_EN > 0u | |||
| void *OSMboxAccept (OS_EVENT *pevent) | |||
| { | |||
| void *pmsg; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return ((void *)0); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ | |||
| return ((void *)0); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| pmsg = pevent->OSEventPtr; | |||
| pevent->OSEventPtr = (void *)0; /* Clear the mailbox */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (pmsg); /* Return the message received (or NULL) */ | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CREATE A MESSAGE MAILBOX | |||
| * | |||
| * Description: This function creates a message mailbox if free event control blocks are available. | |||
| * | |||
| * Arguments : pmsg is a pointer to a message that you wish to deposit in the mailbox. If | |||
| * you set this value to the NULL pointer (i.e. (void *)0) then the mailbox | |||
| * will be considered empty. | |||
| * | |||
| * Returns : != (OS_EVENT *)0 is a pointer to the event control clock (OS_EVENT) associated with the | |||
| * created mailbox | |||
| * == (OS_EVENT *)0 if no event control blocks were available | |||
| ********************************************************************************************************* | |||
| */ | |||
| OS_EVENT *OSMboxCreate (void *pmsg) | |||
| { | |||
| OS_EVENT *pevent; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL_IEC61508 | |||
| if (OSSafetyCriticalStartFlag == OS_TRUE) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| #endif | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */ | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| pevent = OSEventFreeList; /* Get next free event control block */ | |||
| if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */ | |||
| OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| if (pevent != (OS_EVENT *)0) { | |||
| pevent->OSEventType = OS_EVENT_TYPE_MBOX; | |||
| pevent->OSEventCnt = 0u; | |||
| pevent->OSEventPtr = pmsg; /* Deposit message in event control block */ | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| OS_EventWaitListInit(pevent); | |||
| } | |||
| return (pevent); /* Return pointer to event control block */ | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DELETE A MAIBOX | |||
| * | |||
| * Description: This function deletes a mailbox and readies all tasks pending on the mailbox. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired | |||
| * mailbox. | |||
| * | |||
| * opt determines delete options as follows: | |||
| * opt == OS_DEL_NO_PEND Delete the mailbox ONLY if no task pending | |||
| * opt == OS_DEL_ALWAYS Deletes the mailbox even if tasks are waiting. | |||
| * In this case, all the tasks pending will be readied. | |||
| * | |||
| * perr is a pointer to an error code that can contain one of the following values: | |||
| * OS_ERR_NONE The call was successful and the mailbox was deleted | |||
| * OS_ERR_DEL_ISR If you attempted to delete the mailbox from an ISR | |||
| * OS_ERR_INVALID_OPT An invalid option was specified | |||
| * OS_ERR_TASK_WAITING One or more tasks were waiting on the mailbox | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mailbox | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. | |||
| * | |||
| * Returns : pevent upon error | |||
| * (OS_EVENT *)0 if the mailbox was successfully deleted. | |||
| * | |||
| * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of | |||
| * the mailbox MUST check the return code of OSMboxPend(). | |||
| * 2) OSMboxAccept() callers will not know that the intended mailbox has been deleted! | |||
| * 3) This call can potentially disable interrupts for a long time. The interrupt disable | |||
| * time is directly proportional to the number of tasks waiting on the mailbox. | |||
| * 4) Because ALL tasks pending on the mailbox will be readied, you MUST be careful in | |||
| * applications where the mailbox is used for mutual exclusion because the resource(s) | |||
| * will no longer be guarded by the mailbox. | |||
| * 5) All tasks that were waiting for the mailbox will be readied and returned an | |||
| * OS_ERR_PEND_ABORT if OSMboxDel() was called with OS_DEL_ALWAYS | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MBOX_DEL_EN > 0u | |||
| OS_EVENT *OSMboxDel (OS_EVENT *pevent, | |||
| INT8U opt, | |||
| INT8U *perr) | |||
| { | |||
| BOOLEAN tasks_waiting; | |||
| OS_EVENT *pevent_return; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return (pevent); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return (pevent); | |||
| } | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ | |||
| return (pevent); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on mailbox */ | |||
| tasks_waiting = OS_TRUE; /* Yes */ | |||
| } else { | |||
| tasks_waiting = OS_FALSE; /* No */ | |||
| } | |||
| switch (opt) { | |||
| case OS_DEL_NO_PEND: /* Delete mailbox only if no task waiting */ | |||
| if (tasks_waiting == OS_FALSE) { | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| pevent->OSEventType = OS_EVENT_TYPE_UNUSED; | |||
| pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ | |||
| pevent->OSEventCnt = 0u; | |||
| OSEventFreeList = pevent; /* Get next free event control block */ | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| pevent_return = (OS_EVENT *)0; /* Mailbox has been deleted */ | |||
| } else { | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_TASK_WAITING; | |||
| pevent_return = pevent; | |||
| } | |||
| break; | |||
| case OS_DEL_ALWAYS: /* Always delete the mailbox */ | |||
| while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for mailbox */ | |||
| (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT); | |||
| } | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| pevent->OSEventType = OS_EVENT_TYPE_UNUSED; | |||
| pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ | |||
| pevent->OSEventCnt = 0u; | |||
| OSEventFreeList = pevent; /* Get next free event control block */ | |||
| OS_EXIT_CRITICAL(); | |||
| if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ | |||
| OS_Sched(); /* Find highest priority task ready to run */ | |||
| } | |||
| *perr = OS_ERR_NONE; | |||
| pevent_return = (OS_EVENT *)0; /* Mailbox has been deleted */ | |||
| break; | |||
| default: | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_INVALID_OPT; | |||
| pevent_return = pevent; | |||
| break; | |||
| } | |||
| return (pevent_return); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * PEND ON MAILBOX FOR A MESSAGE | |||
| * | |||
| * Description: This function waits for a message to be sent to a mailbox | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired mailbox | |||
| * | |||
| * timeout is an optional timeout period (in clock ticks). If non-zero, your task will | |||
| * wait for a message to arrive at the mailbox up to the amount of time | |||
| * specified by this argument. If you specify 0, however, your task will wait | |||
| * forever at the specified mailbox or, until a message arrives. | |||
| * | |||
| * perr is a pointer to where an error message will be deposited. Possible error | |||
| * messages are: | |||
| * | |||
| * OS_ERR_NONE The call was successful and your task received a | |||
| * message. | |||
| * OS_ERR_TIMEOUT A message was not received within the specified 'timeout'. | |||
| * OS_ERR_PEND_ABORT The wait on the mailbox was aborted. | |||
| * OS_ERR_EVENT_TYPE Invalid event type | |||
| * OS_ERR_PEND_ISR If you called this function from an ISR and the result | |||
| * would lead to a suspension. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked | |||
| * | |||
| * Returns : != (void *)0 is a pointer to the message received | |||
| * == (void *)0 if no message was received or, | |||
| * if 'pevent' is a NULL pointer or, | |||
| * if you didn't pass the proper pointer to the event control block. | |||
| ********************************************************************************************************* | |||
| */ | |||
| /*$PAGE*/ | |||
| void *OSMboxPend (OS_EVENT *pevent, | |||
| INT32U timeout, | |||
| INT8U *perr) | |||
| { | |||
| void *pmsg; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((void *)0); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return ((void *)0); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return ((void *)0); | |||
| } | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ | |||
| return ((void *)0); | |||
| } | |||
| if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ | |||
| *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ | |||
| return ((void *)0); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| pmsg = pevent->OSEventPtr; | |||
| if (pmsg != (void *)0) { /* See if there is already a message */ | |||
| pevent->OSEventPtr = (void *)0; /* Clear the mailbox */ | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| return (pmsg); /* Return the message received (or NULL) */ | |||
| } | |||
| OSTCBCur->OSTCBStat |= OS_STAT_MBOX; /* Message not available, task will pend */ | |||
| OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; | |||
| OSTCBCur->OSTCBDly = timeout; /* Load timeout in TCB */ | |||
| OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find next highest priority task ready to run */ | |||
| OS_ENTER_CRITICAL(); | |||
| switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ | |||
| case OS_STAT_PEND_OK: | |||
| pmsg = OSTCBCur->OSTCBMsg; | |||
| *perr = OS_ERR_NONE; | |||
| break; | |||
| case OS_STAT_PEND_ABORT: | |||
| pmsg = (void *)0; | |||
| *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */ | |||
| break; | |||
| case OS_STAT_PEND_TO: | |||
| default: | |||
| OS_EventTaskRemove(OSTCBCur, pevent); | |||
| pmsg = (void *)0; | |||
| *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */ | |||
| break; | |||
| } | |||
| OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ | |||
| OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ | |||
| OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ | |||
| #if (OS_EVENT_MULTI_EN > 0u) | |||
| OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; | |||
| #endif | |||
| OSTCBCur->OSTCBMsg = (void *)0; /* Clear received message */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (pmsg); /* Return received message */ | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ABORT WAITING ON A MESSAGE MAILBOX | |||
| * | |||
| * Description: This function aborts & readies any tasks currently waiting on a mailbox. This function | |||
| * should be used to fault-abort the wait on the mailbox, rather than to normally signal | |||
| * the mailbox via OSMboxPost() or OSMboxPostOpt(). | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired mailbox. | |||
| * | |||
| * opt determines the type of ABORT performed: | |||
| * OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the | |||
| * mailbox | |||
| * OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the | |||
| * mailbox | |||
| * | |||
| * perr is a pointer to where an error message will be deposited. Possible error | |||
| * messages are: | |||
| * | |||
| * OS_ERR_NONE No tasks were waiting on the mailbox. | |||
| * OS_ERR_PEND_ABORT At least one task waiting on the mailbox was readied | |||
| * and informed of the aborted wait; check return value | |||
| * for the number of tasks whose wait on the mailbox | |||
| * was aborted. | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mailbox. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. | |||
| * | |||
| * Returns : == 0 if no tasks were waiting on the mailbox, or upon error. | |||
| * > 0 if one or more tasks waiting on the mailbox are now readied and informed. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MBOX_PEND_ABORT_EN > 0u | |||
| INT8U OSMboxPendAbort (OS_EVENT *pevent, | |||
| INT8U opt, | |||
| INT8U *perr) | |||
| { | |||
| INT8U nbr_tasks; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return (0u); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return (0u); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return (0u); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any task waiting on mailbox? */ | |||
| nbr_tasks = 0u; | |||
| switch (opt) { | |||
| case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */ | |||
| while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on mailbox */ | |||
| (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT); | |||
| nbr_tasks++; | |||
| } | |||
| break; | |||
| case OS_PEND_OPT_NONE: | |||
| default: /* No, ready HPT waiting on mailbox */ | |||
| (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT); | |||
| nbr_tasks++; | |||
| break; | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find HPT ready to run */ | |||
| *perr = OS_ERR_PEND_ABORT; | |||
| return (nbr_tasks); | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| return (0u); /* No tasks waiting on mailbox */ | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * POST MESSAGE TO A MAILBOX | |||
| * | |||
| * Description: This function sends a message to a mailbox | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired mailbox | |||
| * | |||
| * pmsg is a pointer to the message to send. You MUST NOT send a NULL pointer. | |||
| * | |||
| * Returns : OS_ERR_NONE The call was successful and the message was sent | |||
| * OS_ERR_MBOX_FULL If the mailbox already contains a message. You can can only send one | |||
| * message at a time and thus, the message MUST be consumed before you | |||
| * are allowed to send another one. | |||
| * OS_ERR_EVENT_TYPE If you are attempting to post to a non mailbox. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer | |||
| * | |||
| * Note(s) : 1) HPT means Highest Priority Task | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MBOX_POST_EN > 0u | |||
| INT8U OSMboxPost (OS_EVENT *pevent, | |||
| void *pmsg) | |||
| { | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| if (pmsg == (void *)0) { /* Make sure we are not posting a NULL pointer */ | |||
| return (OS_ERR_POST_NULL_PTR); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any task pending on mailbox */ | |||
| /* Ready HPT waiting on event */ | |||
| (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK); | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find highest priority task ready to run */ | |||
| return (OS_ERR_NONE); | |||
| } | |||
| if (pevent->OSEventPtr != (void *)0) { /* Make sure mailbox doesn't already have a msg */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_MBOX_FULL); | |||
| } | |||
| pevent->OSEventPtr = pmsg; /* Place message in mailbox */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * POST MESSAGE TO A MAILBOX | |||
| * | |||
| * Description: This function sends a message to a mailbox | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired mailbox | |||
| * | |||
| * pmsg is a pointer to the message to send. You MUST NOT send a NULL pointer. | |||
| * | |||
| * opt determines the type of POST performed: | |||
| * OS_POST_OPT_NONE POST to a single waiting task | |||
| * (Identical to OSMboxPost()) | |||
| * OS_POST_OPT_BROADCAST POST to ALL tasks that are waiting on the mailbox | |||
| * | |||
| * OS_POST_OPT_NO_SCHED Indicates that the scheduler will NOT be invoked | |||
| * | |||
| * Returns : OS_ERR_NONE The call was successful and the message was sent | |||
| * OS_ERR_MBOX_FULL If the mailbox already contains a message. You can can only send one | |||
| * message at a time and thus, the message MUST be consumed before you | |||
| * are allowed to send another one. | |||
| * OS_ERR_EVENT_TYPE If you are attempting to post to a non mailbox. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer | |||
| * | |||
| * Note(s) : 1) HPT means Highest Priority Task | |||
| * | |||
| * Warning : Interrupts can be disabled for a long time if you do a 'broadcast'. In fact, the | |||
| * interrupt disable time is proportional to the number of tasks waiting on the mailbox. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MBOX_POST_OPT_EN > 0u | |||
| INT8U OSMboxPostOpt (OS_EVENT *pevent, | |||
| void *pmsg, | |||
| INT8U opt) | |||
| { | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| if (pmsg == (void *)0) { /* Make sure we are not posting a NULL pointer */ | |||
| return (OS_ERR_POST_NULL_PTR); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any task pending on mailbox */ | |||
| if ((opt & OS_POST_OPT_BROADCAST) != 0x00u) { /* Do we need to post msg to ALL waiting tasks ? */ | |||
| while (pevent->OSEventGrp != 0u) { /* Yes, Post to ALL tasks waiting on mailbox */ | |||
| (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK); | |||
| } | |||
| } else { /* No, Post to HPT waiting on mbox */ | |||
| (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK); | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| if ((opt & OS_POST_OPT_NO_SCHED) == 0u) { /* See if scheduler needs to be invoked */ | |||
| OS_Sched(); /* Find HPT ready to run */ | |||
| } | |||
| return (OS_ERR_NONE); | |||
| } | |||
| if (pevent->OSEventPtr != (void *)0) { /* Make sure mailbox doesn't already have a msg */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_MBOX_FULL); | |||
| } | |||
| pevent->OSEventPtr = pmsg; /* Place message in mailbox */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * QUERY A MESSAGE MAILBOX | |||
| * | |||
| * Description: This function obtains information about a message mailbox. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired mailbox | |||
| * | |||
| * p_mbox_data is a pointer to a structure that will contain information about the message | |||
| * mailbox. | |||
| * | |||
| * Returns : OS_ERR_NONE The call was successful and the message was sent | |||
| * OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non mailbox. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * OS_ERR_PDATA_NULL If 'p_mbox_data' is a NULL pointer | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MBOX_QUERY_EN > 0u | |||
| INT8U OSMboxQuery (OS_EVENT *pevent, | |||
| OS_MBOX_DATA *p_mbox_data) | |||
| { | |||
| INT8U i; | |||
| OS_PRIO *psrc; | |||
| OS_PRIO *pdest; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| if (p_mbox_data == (OS_MBOX_DATA *)0) { /* Validate 'p_mbox_data' */ | |||
| return (OS_ERR_PDATA_NULL); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| p_mbox_data->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */ | |||
| psrc = &pevent->OSEventTbl[0]; | |||
| pdest = &p_mbox_data->OSEventTbl[0]; | |||
| for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) { | |||
| *pdest++ = *psrc++; | |||
| } | |||
| p_mbox_data->OSMsg = pevent->OSEventPtr; /* Get message from mailbox */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif /* OS_MBOX_QUERY_EN */ | |||
| #endif /* OS_MBOX_EN */ | |||
| @@ -0,0 +1,462 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/OS-II | |||
| * The Real-Time Kernel | |||
| * MEMORY MANAGEMENT | |||
| * | |||
| * (c) Copyright 1992-2013, Micrium, Weston, FL | |||
| * All Rights Reserved | |||
| * | |||
| * File : OS_MEM.C | |||
| * By : Jean J. Labrosse | |||
| * Version : V2.92.11 | |||
| * | |||
| * LICENSING TERMS: | |||
| * --------------- | |||
| * uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research. | |||
| * If you plan on using uC/OS-II in a commercial product you need to contact Micrium to properly license | |||
| * its use in your product. We provide ALL the source code for your convenience and to help you experience | |||
| * uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a | |||
| * licensing fee. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MICRIUM_SOURCE | |||
| #ifndef OS_MASTER_FILE | |||
| #include <ucos_ii.h> | |||
| #endif | |||
| #if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CREATE A MEMORY PARTITION | |||
| * | |||
| * Description : Create a fixed-sized memory partition that will be managed by uC/OS-II. | |||
| * | |||
| * Arguments : addr is the starting address of the memory partition | |||
| * | |||
| * nblks is the number of memory blocks to create from the partition. | |||
| * | |||
| * blksize is the size (in bytes) of each block in the memory partition. | |||
| * | |||
| * perr is a pointer to a variable containing an error message which will be set by | |||
| * this function to either: | |||
| * | |||
| * OS_ERR_NONE if the memory partition has been created correctly. | |||
| * OS_ERR_MEM_INVALID_ADDR if you are specifying an invalid address for the memory | |||
| * storage of the partition or, the block does not align | |||
| * on a pointer boundary | |||
| * OS_ERR_MEM_INVALID_PART no free partitions available | |||
| * OS_ERR_MEM_INVALID_BLKS user specified an invalid number of blocks (must be >= 2) | |||
| * OS_ERR_MEM_INVALID_SIZE user specified an invalid block size | |||
| * - must be greater than the size of a pointer | |||
| * - must be able to hold an integral number of pointers | |||
| * Returns : != (OS_MEM *)0 is the partition was created | |||
| * == (OS_MEM *)0 if the partition was not created because of invalid arguments or, no | |||
| * free partition is available. | |||
| ********************************************************************************************************* | |||
| */ | |||
| OS_MEM *OSMemCreate (void *addr, | |||
| INT32U nblks, | |||
| INT32U blksize, | |||
| INT8U *perr) | |||
| { | |||
| OS_MEM *pmem; | |||
| INT8U *pblk; | |||
| void **plink; | |||
| INT32U loops; | |||
| INT32U i; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((OS_MEM *)0); | |||
| } | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL_IEC61508 | |||
| if (OSSafetyCriticalStartFlag == OS_TRUE) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((OS_MEM *)0); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (addr == (void *)0) { /* Must pass a valid address for the memory part.*/ | |||
| *perr = OS_ERR_MEM_INVALID_ADDR; | |||
| return ((OS_MEM *)0); | |||
| } | |||
| if (((INT32U)addr & (sizeof(void *) - 1u)) != 0u){ /* Must be pointer size aligned */ | |||
| *perr = OS_ERR_MEM_INVALID_ADDR; | |||
| return ((OS_MEM *)0); | |||
| } | |||
| if (nblks < 2u) { /* Must have at least 2 blocks per partition */ | |||
| *perr = OS_ERR_MEM_INVALID_BLKS; | |||
| return ((OS_MEM *)0); | |||
| } | |||
| if (blksize < sizeof(void *)) { /* Must contain space for at least a pointer */ | |||
| *perr = OS_ERR_MEM_INVALID_SIZE; | |||
| return ((OS_MEM *)0); | |||
| } | |||
| #endif | |||
| OS_ENTER_CRITICAL(); | |||
| pmem = OSMemFreeList; /* Get next free memory partition */ | |||
| if (OSMemFreeList != (OS_MEM *)0) { /* See if pool of free partitions was empty */ | |||
| OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList; | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| if (pmem == (OS_MEM *)0) { /* See if we have a memory partition */ | |||
| *perr = OS_ERR_MEM_INVALID_PART; | |||
| return ((OS_MEM *)0); | |||
| } | |||
| plink = (void **)addr; /* Create linked list of free memory blocks */ | |||
| pblk = (INT8U *)addr; | |||
| loops = nblks - 1u; | |||
| for (i = 0u; i < loops; i++) { | |||
| pblk += blksize; /* Point to the FOLLOWING block */ | |||
| *plink = (void *)pblk; /* Save pointer to NEXT block in CURRENT block */ | |||
| plink = (void **)pblk; /* Position to NEXT block */ | |||
| } | |||
| *plink = (void *)0; /* Last memory block points to NULL */ | |||
| pmem->OSMemAddr = addr; /* Store start address of memory partition */ | |||
| pmem->OSMemFreeList = addr; /* Initialize pointer to pool of free blocks */ | |||
| pmem->OSMemNFree = nblks; /* Store number of free blocks in MCB */ | |||
| pmem->OSMemNBlks = nblks; | |||
| pmem->OSMemBlkSize = blksize; /* Store block size of each memory blocks */ | |||
| *perr = OS_ERR_NONE; | |||
| return (pmem); | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * GET A MEMORY BLOCK | |||
| * | |||
| * Description : Get a memory block from a partition | |||
| * | |||
| * Arguments : pmem is a pointer to the memory partition control block | |||
| * | |||
| * perr is a pointer to a variable containing an error message which will be set by this | |||
| * function to either: | |||
| * | |||
| * OS_ERR_NONE if the memory partition has been created correctly. | |||
| * OS_ERR_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to caller | |||
| * OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' | |||
| * | |||
| * Returns : A pointer to a memory block if no error is detected | |||
| * A pointer to NULL if an error is detected | |||
| ********************************************************************************************************* | |||
| */ | |||
| void *OSMemGet (OS_MEM *pmem, | |||
| INT8U *perr) | |||
| { | |||
| void *pblk; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((void *)0); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pmem == (OS_MEM *)0) { /* Must point to a valid memory partition */ | |||
| *perr = OS_ERR_MEM_INVALID_PMEM; | |||
| return ((void *)0); | |||
| } | |||
| #endif | |||
| OS_ENTER_CRITICAL(); | |||
| if (pmem->OSMemNFree > 0u) { /* See if there are any free memory blocks */ | |||
| pblk = pmem->OSMemFreeList; /* Yes, point to next free memory block */ | |||
| pmem->OSMemFreeList = *(void **)pblk; /* Adjust pointer to new free list */ | |||
| pmem->OSMemNFree--; /* One less memory block in this partition */ | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; /* No error */ | |||
| return (pblk); /* Return memory block to caller */ | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_MEM_NO_FREE_BLKS; /* No, Notify caller of empty memory partition */ | |||
| return ((void *)0); /* Return NULL pointer to caller */ | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * GET THE NAME OF A MEMORY PARTITION | |||
| * | |||
| * Description: This function is used to obtain the name assigned to a memory partition. | |||
| * | |||
| * Arguments : pmem is a pointer to the memory partition | |||
| * | |||
| * pname is a pointer to a pointer to an ASCII string that will receive the name of the memory partition. | |||
| * | |||
| * perr is a pointer to an error code that can contain one of the following values: | |||
| * | |||
| * OS_ERR_NONE if the name was copied to 'pname' | |||
| * OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' | |||
| * OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' | |||
| * OS_ERR_NAME_GET_ISR You called this function from an ISR | |||
| * | |||
| * Returns : The length of the string or 0 if 'pmem' is a NULL pointer. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MEM_NAME_EN > 0u | |||
| INT8U OSMemNameGet (OS_MEM *pmem, | |||
| INT8U **pname, | |||
| INT8U *perr) | |||
| { | |||
| INT8U len; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return (0u); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pmem == (OS_MEM *)0) { /* Is 'pmem' a NULL pointer? */ | |||
| *perr = OS_ERR_MEM_INVALID_PMEM; | |||
| return (0u); | |||
| } | |||
| if (pname == (INT8U **)0) { /* Is 'pname' a NULL pointer? */ | |||
| *perr = OS_ERR_PNAME_NULL; | |||
| return (0u); | |||
| } | |||
| #endif | |||
| if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ | |||
| *perr = OS_ERR_NAME_GET_ISR; | |||
| return (0u); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| *pname = pmem->OSMemName; | |||
| len = OS_StrLen(*pname); | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| return (len); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ASSIGN A NAME TO A MEMORY PARTITION | |||
| * | |||
| * Description: This function assigns a name to a memory partition. | |||
| * | |||
| * Arguments : pmem is a pointer to the memory partition | |||
| * | |||
| * pname is a pointer to an ASCII string that contains the name of the memory partition. | |||
| * | |||
| * perr is a pointer to an error code that can contain one of the following values: | |||
| * | |||
| * OS_ERR_NONE if the name was copied to 'pname' | |||
| * OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' | |||
| * OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' | |||
| * OS_ERR_MEM_NAME_TOO_LONG if the name doesn't fit in the storage area | |||
| * OS_ERR_NAME_SET_ISR if you called this function from an ISR | |||
| * | |||
| * Returns : None | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MEM_NAME_EN > 0u | |||
| void OSMemNameSet (OS_MEM *pmem, | |||
| INT8U *pname, | |||
| INT8U *perr) | |||
| { | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return; | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pmem == (OS_MEM *)0) { /* Is 'pmem' a NULL pointer? */ | |||
| *perr = OS_ERR_MEM_INVALID_PMEM; | |||
| return; | |||
| } | |||
| if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */ | |||
| *perr = OS_ERR_PNAME_NULL; | |||
| return; | |||
| } | |||
| #endif | |||
| if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ | |||
| *perr = OS_ERR_NAME_SET_ISR; | |||
| return; | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| pmem->OSMemName = pname; | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * RELEASE A MEMORY BLOCK | |||
| * | |||
| * Description : Returns a memory block to a partition | |||
| * | |||
| * Arguments : pmem is a pointer to the memory partition control block | |||
| * | |||
| * pblk is a pointer to the memory block being released. | |||
| * | |||
| * Returns : OS_ERR_NONE if the memory block was inserted into the partition | |||
| * OS_ERR_MEM_FULL if you are returning a memory block to an already FULL memory | |||
| * partition (You freed more blocks than you allocated!) | |||
| * OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' | |||
| * OS_ERR_MEM_INVALID_PBLK if you passed a NULL pointer for the block to release. | |||
| ********************************************************************************************************* | |||
| */ | |||
| INT8U OSMemPut (OS_MEM *pmem, | |||
| void *pblk) | |||
| { | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pmem == (OS_MEM *)0) { /* Must point to a valid memory partition */ | |||
| return (OS_ERR_MEM_INVALID_PMEM); | |||
| } | |||
| if (pblk == (void *)0) { /* Must release a valid block */ | |||
| return (OS_ERR_MEM_INVALID_PBLK); | |||
| } | |||
| #endif | |||
| OS_ENTER_CRITICAL(); | |||
| if (pmem->OSMemNFree >= pmem->OSMemNBlks) { /* Make sure all blocks not already returned */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_MEM_FULL); | |||
| } | |||
| *(void **)pblk = pmem->OSMemFreeList; /* Insert released block into free block list */ | |||
| pmem->OSMemFreeList = pblk; | |||
| pmem->OSMemNFree++; /* One more memory block in this partition */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); /* Notify caller that memory block was released */ | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * QUERY MEMORY PARTITION | |||
| * | |||
| * Description : This function is used to determine the number of free memory blocks and the number of | |||
| * used memory blocks from a memory partition. | |||
| * | |||
| * Arguments : pmem is a pointer to the memory partition control block | |||
| * | |||
| * p_mem_data is a pointer to a structure that will contain information about the memory | |||
| * partition. | |||
| * | |||
| * Returns : OS_ERR_NONE if no errors were found. | |||
| * OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' | |||
| * OS_ERR_MEM_INVALID_PDATA if you passed a NULL pointer to the data recipient. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MEM_QUERY_EN > 0u | |||
| INT8U OSMemQuery (OS_MEM *pmem, | |||
| OS_MEM_DATA *p_mem_data) | |||
| { | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pmem == (OS_MEM *)0) { /* Must point to a valid memory partition */ | |||
| return (OS_ERR_MEM_INVALID_PMEM); | |||
| } | |||
| if (p_mem_data == (OS_MEM_DATA *)0) { /* Must release a valid storage area for the data */ | |||
| return (OS_ERR_MEM_INVALID_PDATA); | |||
| } | |||
| #endif | |||
| OS_ENTER_CRITICAL(); | |||
| p_mem_data->OSAddr = pmem->OSMemAddr; | |||
| p_mem_data->OSFreeList = pmem->OSMemFreeList; | |||
| p_mem_data->OSBlkSize = pmem->OSMemBlkSize; | |||
| p_mem_data->OSNBlks = pmem->OSMemNBlks; | |||
| p_mem_data->OSNFree = pmem->OSMemNFree; | |||
| OS_EXIT_CRITICAL(); | |||
| p_mem_data->OSNUsed = p_mem_data->OSNBlks - p_mem_data->OSNFree; | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif /* OS_MEM_QUERY_EN */ | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * INITIALIZE MEMORY PARTITION MANAGER | |||
| * | |||
| * Description : This function is called by uC/OS-II to initialize the memory partition manager. Your | |||
| * application MUST NOT call this function. | |||
| * | |||
| * Arguments : none | |||
| * | |||
| * Returns : none | |||
| * | |||
| * Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void OS_MemInit (void) | |||
| { | |||
| #if OS_MAX_MEM_PART == 1u | |||
| OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl)); /* Clear the memory partition table */ | |||
| OSMemFreeList = (OS_MEM *)&OSMemTbl[0]; /* Point to beginning of free list */ | |||
| #if OS_MEM_NAME_EN > 0u | |||
| OSMemFreeList->OSMemName = (INT8U *)"?"; /* Unknown name */ | |||
| #endif | |||
| #endif | |||
| #if OS_MAX_MEM_PART >= 2u | |||
| OS_MEM *pmem; | |||
| INT16U i; | |||
| OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl)); /* Clear the memory partition table */ | |||
| for (i = 0u; i < (OS_MAX_MEM_PART - 1u); i++) { /* Init. list of free memory partitions */ | |||
| pmem = &OSMemTbl[i]; /* Point to memory control block (MCB) */ | |||
| pmem->OSMemFreeList = (void *)&OSMemTbl[i + 1u]; /* Chain list of free partitions */ | |||
| #if OS_MEM_NAME_EN > 0u | |||
| pmem->OSMemName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| } | |||
| pmem = &OSMemTbl[i]; | |||
| pmem->OSMemFreeList = (void *)0; /* Initialize last node */ | |||
| #if OS_MEM_NAME_EN > 0u | |||
| pmem->OSMemName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| OSMemFreeList = &OSMemTbl[0]; /* Point to beginning of free list */ | |||
| #endif | |||
| } | |||
| #endif /* OS_MEM_EN */ | |||
| @@ -0,0 +1,763 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/OS-II | |||
| * The Real-Time Kernel | |||
| * MUTUAL EXCLUSION SEMAPHORE MANAGEMENT | |||
| * | |||
| * (c) Copyright 1992-2013, Micrium, Weston, FL | |||
| * All Rights Reserved | |||
| * | |||
| * File : OS_MUTEX.C | |||
| * By : Jean J. Labrosse | |||
| * Version : V2.92.11 | |||
| * | |||
| * LICENSING TERMS: | |||
| * --------------- | |||
| * uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research. | |||
| * If you plan on using uC/OS-II in a commercial product you need to contact Micrium to properly license | |||
| * its use in your product. We provide ALL the source code for your convenience and to help you experience | |||
| * uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a | |||
| * licensing fee. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MICRIUM_SOURCE | |||
| #ifndef OS_MASTER_FILE | |||
| #include <ucos_ii.h> | |||
| #endif | |||
| #if OS_MUTEX_EN > 0u | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL CONSTANTS | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define OS_MUTEX_KEEP_LOWER_8 ((INT16U)0x00FFu) | |||
| #define OS_MUTEX_KEEP_UPPER_8 ((INT16U)0xFF00u) | |||
| #define OS_MUTEX_AVAILABLE ((INT16U)0x00FFu) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * LOCAL CONSTANTS | |||
| ********************************************************************************************************* | |||
| */ | |||
| static void OSMutex_RdyAtPrio(OS_TCB *ptcb, INT8U prio); | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ACCEPT MUTUAL EXCLUSION SEMAPHORE | |||
| * | |||
| * Description: This function checks the mutual exclusion semaphore to see if a resource is available. | |||
| * Unlike OSMutexPend(), OSMutexAccept() does not suspend the calling task if the resource is | |||
| * not available or the event did not occur. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block | |||
| * | |||
| * perr is a pointer to an error code which will be returned to your application: | |||
| * OS_ERR_NONE if the call was successful. | |||
| * OS_ERR_EVENT_TYPE if 'pevent' is not a pointer to a mutex | |||
| * OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer | |||
| * OS_ERR_PEND_ISR if you called this function from an ISR | |||
| * OS_ERR_PCP_LOWER If the priority of the task that owns the Mutex is | |||
| * HIGHER (i.e. a lower number) than the PCP. This error | |||
| * indicates that you did not set the PCP higher (lower | |||
| * number) than ALL the tasks that compete for the Mutex. | |||
| * Unfortunately, this is something that could not be | |||
| * detected when the Mutex is created because we don't know | |||
| * what tasks will be using the Mutex. | |||
| * | |||
| * Returns : == OS_TRUE if the resource is available, the mutual exclusion semaphore is acquired | |||
| * == OS_FALSE a) if the resource is not available | |||
| * b) you didn't pass a pointer to a mutual exclusion semaphore | |||
| * c) you called this function from an ISR | |||
| * | |||
| * Warning(s) : This function CANNOT be called from an ISR because mutual exclusion semaphores are | |||
| * intended to be used by tasks only. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MUTEX_ACCEPT_EN > 0u | |||
| BOOLEAN OSMutexAccept (OS_EVENT *pevent, | |||
| INT8U *perr) | |||
| { | |||
| INT8U pcp; /* Priority Ceiling Priority (PCP) */ | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return (OS_FALSE); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return (OS_FALSE); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return (OS_FALSE); | |||
| } | |||
| if (OSIntNesting > 0u) { /* Make sure it's not called from an ISR */ | |||
| *perr = OS_ERR_PEND_ISR; | |||
| return (OS_FALSE); | |||
| } | |||
| OS_ENTER_CRITICAL(); /* Get value (0 or 1) of Mutex */ | |||
| pcp = (INT8U)(pevent->OSEventCnt >> 8u); /* Get PCP from mutex */ | |||
| if ((pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) { | |||
| pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Mask off LSByte (Acquire Mutex) */ | |||
| pevent->OSEventCnt |= OSTCBCur->OSTCBPrio; /* Save current task priority in LSByte */ | |||
| pevent->OSEventPtr = (void *)OSTCBCur; /* Link TCB of task owning Mutex */ | |||
| if ((pcp != OS_PRIO_MUTEX_CEIL_DIS) && | |||
| (OSTCBCur->OSTCBPrio <= pcp)) { /* PCP 'must' have a SMALLER prio ... */ | |||
| OS_EXIT_CRITICAL(); /* ... than current task! */ | |||
| *perr = OS_ERR_PCP_LOWER; | |||
| } else { | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| } | |||
| return (OS_TRUE); | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| return (OS_FALSE); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CREATE A MUTUAL EXCLUSION SEMAPHORE | |||
| * | |||
| * Description: This function creates a mutual exclusion semaphore. | |||
| * | |||
| * Arguments : prio is the priority to use when accessing the mutual exclusion semaphore. In | |||
| * other words, when the semaphore is acquired and a higher priority task | |||
| * attempts to obtain the semaphore then the priority of the task owning the | |||
| * semaphore is raised to this priority. It is assumed that you will specify | |||
| * a priority that is LOWER in value than ANY of the tasks competing for the | |||
| * mutex. If the priority is specified as OS_PRIO_MUTEX_CEIL_DIS, then the | |||
| * priority ceiling promotion is disabled. This way, the tasks accessing the | |||
| * semaphore do not have their priority promoted. | |||
| * | |||
| * perr is a pointer to an error code which will be returned to your application: | |||
| * OS_ERR_NONE if the call was successful. | |||
| * OS_ERR_CREATE_ISR if you attempted to create a MUTEX from an ISR | |||
| * OS_ERR_PRIO_EXIST if a task at the priority ceiling priority | |||
| * already exist. | |||
| * OS_ERR_PEVENT_NULL No more event control blocks available. | |||
| * OS_ERR_PRIO_INVALID if the priority you specify is higher that the | |||
| * maximum allowed (i.e. > OS_LOWEST_PRIO) | |||
| * | |||
| * Returns : != (void *)0 is a pointer to the event control clock (OS_EVENT) associated with the | |||
| * created mutex. | |||
| * == (void *)0 if an error is detected. | |||
| * | |||
| * Note(s) : 1) The LEAST significant 8 bits of '.OSEventCnt' hold the priority number of the task | |||
| * owning the mutex or 0xFF if no task owns the mutex. | |||
| * | |||
| * 2) The MOST significant 8 bits of '.OSEventCnt' hold the priority number used to | |||
| * reduce priority inversion or 0xFF (OS_PRIO_MUTEX_CEIL_DIS) if priority ceiling | |||
| * promotion is disabled. | |||
| ********************************************************************************************************* | |||
| */ | |||
| OS_EVENT *OSMutexCreate (INT8U prio, | |||
| INT8U *perr) | |||
| { | |||
| OS_EVENT *pevent; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL_IEC61508 | |||
| if (OSSafetyCriticalStartFlag == OS_TRUE) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (prio != OS_PRIO_MUTEX_CEIL_DIS) { | |||
| if (prio >= OS_LOWEST_PRIO) { /* Validate PCP */ | |||
| *perr = OS_ERR_PRIO_INVALID; | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| } | |||
| #endif | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| *perr = OS_ERR_CREATE_ISR; /* ... can't CREATE mutex from an ISR */ | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (prio != OS_PRIO_MUTEX_CEIL_DIS) { | |||
| if (OSTCBPrioTbl[prio] != (OS_TCB *)0) { /* Mutex priority must not already exist */ | |||
| OS_EXIT_CRITICAL(); /* Task already exist at priority ... */ | |||
| *perr = OS_ERR_PRIO_EXIST; /* ... ceiling priority */ | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| OSTCBPrioTbl[prio] = OS_TCB_RESERVED; /* Reserve the table entry */ | |||
| } | |||
| pevent = OSEventFreeList; /* Get next free event control block */ | |||
| if (pevent == (OS_EVENT *)0) { /* See if an ECB was available */ | |||
| if (prio != OS_PRIO_MUTEX_CEIL_DIS) { | |||
| OSTCBPrioTbl[prio] = (OS_TCB *)0; /* No, Release the table entry */ | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_PEVENT_NULL; /* No more event control blocks */ | |||
| return (pevent); | |||
| } | |||
| OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; /* Adjust the free list */ | |||
| OS_EXIT_CRITICAL(); | |||
| pevent->OSEventType = OS_EVENT_TYPE_MUTEX; | |||
| pevent->OSEventCnt = (INT16U)((INT16U)prio << 8u) | OS_MUTEX_AVAILABLE; /* Resource is avail. */ | |||
| pevent->OSEventPtr = (void *)0; /* No task owning the mutex */ | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| OS_EventWaitListInit(pevent); | |||
| *perr = OS_ERR_NONE; | |||
| return (pevent); | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DELETE A MUTEX | |||
| * | |||
| * Description: This function deletes a mutual exclusion semaphore and readies all tasks pending on the it. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired mutex. | |||
| * | |||
| * opt determines delete options as follows: | |||
| * opt == OS_DEL_NO_PEND Delete mutex ONLY if no task pending | |||
| * opt == OS_DEL_ALWAYS Deletes the mutex even if tasks are waiting. | |||
| * In this case, all the tasks pending will be readied. | |||
| * | |||
| * perr is a pointer to an error code that can contain one of the following values: | |||
| * OS_ERR_NONE The call was successful and the mutex was deleted | |||
| * OS_ERR_DEL_ISR If you attempted to delete the MUTEX from an ISR | |||
| * OS_ERR_INVALID_OPT An invalid option was specified | |||
| * OS_ERR_TASK_WAITING One or more tasks were waiting on the mutex | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. | |||
| * | |||
| * Returns : pevent upon error | |||
| * (OS_EVENT *)0 if the mutex was successfully deleted. | |||
| * | |||
| * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of | |||
| * the mutex MUST check the return code of OSMutexPend(). | |||
| * | |||
| * 2) This call can potentially disable interrupts for a long time. The interrupt disable | |||
| * time is directly proportional to the number of tasks waiting on the mutex. | |||
| * | |||
| * 3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the | |||
| * resource(s) will no longer be guarded by the mutex. | |||
| * | |||
| * 4) IMPORTANT: In the 'OS_DEL_ALWAYS' case, we assume that the owner of the Mutex (if there | |||
| * is one) is ready-to-run and is thus NOT pending on another kernel object or | |||
| * has delayed itself. In other words, if a task owns the mutex being deleted, | |||
| * that task will be made ready-to-run at its original priority. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MUTEX_DEL_EN > 0u | |||
| OS_EVENT *OSMutexDel (OS_EVENT *pevent, | |||
| INT8U opt, | |||
| INT8U *perr) | |||
| { | |||
| BOOLEAN tasks_waiting; | |||
| OS_EVENT *pevent_return; | |||
| INT8U pcp; /* Priority ceiling priority */ | |||
| INT8U prio; | |||
| OS_TCB *ptcb; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return (pevent); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return (pevent); | |||
| } | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ | |||
| return (pevent); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on mutex */ | |||
| tasks_waiting = OS_TRUE; /* Yes */ | |||
| } else { | |||
| tasks_waiting = OS_FALSE; /* No */ | |||
| } | |||
| switch (opt) { | |||
| case OS_DEL_NO_PEND: /* DELETE MUTEX ONLY IF NO TASK WAITING --- */ | |||
| if (tasks_waiting == OS_FALSE) { | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| pcp = (INT8U)(pevent->OSEventCnt >> 8u); | |||
| if (pcp != OS_PRIO_MUTEX_CEIL_DIS) { | |||
| OSTCBPrioTbl[pcp] = (OS_TCB *)0; /* Free up the PCP */ | |||
| } | |||
| pevent->OSEventType = OS_EVENT_TYPE_UNUSED; | |||
| pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ | |||
| pevent->OSEventCnt = 0u; | |||
| OSEventFreeList = pevent; | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| pevent_return = (OS_EVENT *)0; /* Mutex has been deleted */ | |||
| } else { | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_TASK_WAITING; | |||
| pevent_return = pevent; | |||
| } | |||
| break; | |||
| case OS_DEL_ALWAYS: /* ALWAYS DELETE THE MUTEX ---------------- */ | |||
| pcp = (INT8U)(pevent->OSEventCnt >> 8u); /* Get PCP of mutex */ | |||
| if (pcp != OS_PRIO_MUTEX_CEIL_DIS) { | |||
| prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get owner's orig prio */ | |||
| ptcb = (OS_TCB *)pevent->OSEventPtr; | |||
| if (ptcb != (OS_TCB *)0) { /* See if any task owns the mutex */ | |||
| if (ptcb->OSTCBPrio == pcp) { /* See if original prio was changed */ | |||
| OSMutex_RdyAtPrio(ptcb, prio); /* Yes, Restore the task's original prio */ | |||
| } | |||
| } | |||
| } | |||
| while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for mutex */ | |||
| (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_ABORT); | |||
| } | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| pcp = (INT8U)(pevent->OSEventCnt >> 8u); | |||
| if (pcp != OS_PRIO_MUTEX_CEIL_DIS) { | |||
| OSTCBPrioTbl[pcp] = (OS_TCB *)0; /* Free up the PCP */ | |||
| } | |||
| pevent->OSEventType = OS_EVENT_TYPE_UNUSED; | |||
| pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ | |||
| pevent->OSEventCnt = 0u; | |||
| OSEventFreeList = pevent; /* Get next free event control block */ | |||
| OS_EXIT_CRITICAL(); | |||
| if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ | |||
| OS_Sched(); /* Find highest priority task ready to run */ | |||
| } | |||
| *perr = OS_ERR_NONE; | |||
| pevent_return = (OS_EVENT *)0; /* Mutex has been deleted */ | |||
| break; | |||
| default: | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_INVALID_OPT; | |||
| pevent_return = pevent; | |||
| break; | |||
| } | |||
| return (pevent_return); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * PEND ON MUTUAL EXCLUSION SEMAPHORE | |||
| * | |||
| * Description: This function waits for a mutual exclusion semaphore. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired | |||
| * mutex. | |||
| * | |||
| * timeout is an optional timeout period (in clock ticks). If non-zero, your task will | |||
| * wait for the resource up to the amount of time specified by this argument. | |||
| * If you specify 0, however, your task will wait forever at the specified | |||
| * mutex or, until the resource becomes available. | |||
| * | |||
| * perr is a pointer to where an error message will be deposited. Possible error | |||
| * messages are: | |||
| * OS_ERR_NONE The call was successful and your task owns the mutex | |||
| * OS_ERR_TIMEOUT The mutex was not available within the specified 'timeout'. | |||
| * OS_ERR_PEND_ABORT The wait on the mutex was aborted. | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex | |||
| * OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer | |||
| * OS_ERR_PEND_ISR If you called this function from an ISR and the result | |||
| * would lead to a suspension. | |||
| * OS_ERR_PCP_LOWER If the priority of the task that owns the Mutex is | |||
| * HIGHER (i.e. a lower number) than the PCP. This error | |||
| * indicates that you did not set the PCP higher (lower | |||
| * number) than ALL the tasks that compete for the Mutex. | |||
| * Unfortunately, this is something that could not be | |||
| * detected when the Mutex is created because we don't know | |||
| * what tasks will be using the Mutex. | |||
| * OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked | |||
| * | |||
| * Returns : none | |||
| * | |||
| * Note(s) : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex. | |||
| * | |||
| * 2) You MUST NOT change the priority of the task that owns the mutex | |||
| ********************************************************************************************************* | |||
| */ | |||
| void OSMutexPend (OS_EVENT *pevent, | |||
| INT32U timeout, | |||
| INT8U *perr) | |||
| { | |||
| INT8U pcp; /* Priority Ceiling Priority (PCP) */ | |||
| INT8U mprio; /* Mutex owner priority */ | |||
| BOOLEAN rdy; /* Flag indicating task was ready */ | |||
| OS_TCB *ptcb; | |||
| OS_EVENT *pevent2; | |||
| INT8U y; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return; | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return; | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return; | |||
| } | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ | |||
| return; | |||
| } | |||
| if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ | |||
| *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ | |||
| return; | |||
| } | |||
| /*$PAGE*/ | |||
| OS_ENTER_CRITICAL(); | |||
| pcp = (INT8U)(pevent->OSEventCnt >> 8u); /* Get PCP from mutex */ | |||
| /* Is Mutex available? */ | |||
| if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) { | |||
| pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Yes, Acquire the resource */ | |||
| pevent->OSEventCnt |= OSTCBCur->OSTCBPrio; /* Save priority of owning task */ | |||
| pevent->OSEventPtr = (void *)OSTCBCur; /* Point to owning task's OS_TCB */ | |||
| if ((pcp != OS_PRIO_MUTEX_CEIL_DIS) && | |||
| (OSTCBCur->OSTCBPrio <= pcp)) { /* PCP 'must' have a SMALLER prio ... */ | |||
| OS_EXIT_CRITICAL(); /* ... than current task! */ | |||
| *perr = OS_ERR_PCP_LOWER; | |||
| } else { | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| } | |||
| return; | |||
| } | |||
| if (pcp != OS_PRIO_MUTEX_CEIL_DIS) { | |||
| mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get priority of mutex owner */ | |||
| ptcb = (OS_TCB *)(pevent->OSEventPtr); /* Point to TCB of mutex owner */ | |||
| if (ptcb->OSTCBPrio > pcp) { /* Need to promote prio of owner?*/ | |||
| if (mprio > OSTCBCur->OSTCBPrio) { | |||
| y = ptcb->OSTCBY; | |||
| if ((OSRdyTbl[y] & ptcb->OSTCBBitX) != 0u) { /* See if mutex owner is ready */ | |||
| OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; /* Yes, Remove owner from Rdy ...*/ | |||
| if (OSRdyTbl[y] == 0u) { /* ... list at current prio */ | |||
| OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY; | |||
| } | |||
| rdy = OS_TRUE; | |||
| } else { | |||
| pevent2 = ptcb->OSTCBEventPtr; | |||
| if (pevent2 != (OS_EVENT *)0) { /* Remove from event wait list */ | |||
| y = ptcb->OSTCBY; | |||
| pevent2->OSEventTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; | |||
| if (pevent2->OSEventTbl[y] == 0u) { | |||
| pevent2->OSEventGrp &= (OS_PRIO)~ptcb->OSTCBBitY; | |||
| } | |||
| } | |||
| rdy = OS_FALSE; /* No */ | |||
| } | |||
| ptcb->OSTCBPrio = pcp; /* Change owner task prio to PCP */ | |||
| #if OS_LOWEST_PRIO <= 63u | |||
| ptcb->OSTCBY = (INT8U)( ptcb->OSTCBPrio >> 3u); | |||
| ptcb->OSTCBX = (INT8U)( ptcb->OSTCBPrio & 0x07u); | |||
| #else | |||
| ptcb->OSTCBY = (INT8U)((INT8U)(ptcb->OSTCBPrio >> 4u) & 0xFFu); | |||
| ptcb->OSTCBX = (INT8U)( ptcb->OSTCBPrio & 0x0Fu); | |||
| #endif | |||
| ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY); | |||
| ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX); | |||
| if (rdy == OS_TRUE) { /* If task was ready at owner's priority ...*/ | |||
| OSRdyGrp |= ptcb->OSTCBBitY; /* ... make it ready at new priority. */ | |||
| OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; | |||
| } else { | |||
| pevent2 = ptcb->OSTCBEventPtr; | |||
| if (pevent2 != (OS_EVENT *)0) { /* Add to event wait list */ | |||
| pevent2->OSEventGrp |= ptcb->OSTCBBitY; | |||
| pevent2->OSEventTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; | |||
| } | |||
| } | |||
| OSTCBPrioTbl[pcp] = ptcb; | |||
| } | |||
| } | |||
| } | |||
| OSTCBCur->OSTCBStat |= OS_STAT_MUTEX; /* Mutex not available, pend current task */ | |||
| OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; | |||
| OSTCBCur->OSTCBDly = timeout; /* Store timeout in current task's TCB */ | |||
| OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find next highest priority task ready */ | |||
| OS_ENTER_CRITICAL(); | |||
| switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ | |||
| case OS_STAT_PEND_OK: | |||
| *perr = OS_ERR_NONE; | |||
| break; | |||
| case OS_STAT_PEND_ABORT: | |||
| *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted getting mutex */ | |||
| break; | |||
| case OS_STAT_PEND_TO: | |||
| default: | |||
| OS_EventTaskRemove(OSTCBCur, pevent); | |||
| *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get mutex within TO */ | |||
| break; | |||
| } | |||
| OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ | |||
| OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ | |||
| OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ | |||
| #if (OS_EVENT_MULTI_EN > 0u) | |||
| OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; | |||
| #endif | |||
| OS_EXIT_CRITICAL(); | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * POST TO A MUTUAL EXCLUSION SEMAPHORE | |||
| * | |||
| * Description: This function signals a mutual exclusion semaphore | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired | |||
| * mutex. | |||
| * | |||
| * Returns : OS_ERR_NONE The call was successful and the mutex was signaled. | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex | |||
| * OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer | |||
| * OS_ERR_POST_ISR Attempted to post from an ISR (not valid for MUTEXes) | |||
| * OS_ERR_NOT_MUTEX_OWNER The task that did the post is NOT the owner of the MUTEX. | |||
| * OS_ERR_PCP_LOWER If the priority of the new task that owns the Mutex is | |||
| * HIGHER (i.e. a lower number) than the PCP. This error | |||
| * indicates that you did not set the PCP higher (lower | |||
| * number) than ALL the tasks that compete for the Mutex. | |||
| * Unfortunately, this is something that could not be | |||
| * detected when the Mutex is created because we don't know | |||
| * what tasks will be using the Mutex. | |||
| ********************************************************************************************************* | |||
| */ | |||
| INT8U OSMutexPost (OS_EVENT *pevent) | |||
| { | |||
| INT8U pcp; /* Priority ceiling priority */ | |||
| INT8U prio; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| return (OS_ERR_POST_ISR); /* ... can't POST mutex from an ISR */ | |||
| } | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| pcp = (INT8U)(pevent->OSEventCnt >> 8u); /* Get priority ceiling priority of mutex */ | |||
| prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get owner's original priority */ | |||
| if (OSTCBCur != (OS_TCB *)pevent->OSEventPtr) { /* See if posting task owns the MUTEX */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NOT_MUTEX_OWNER); | |||
| } | |||
| if (pcp != OS_PRIO_MUTEX_CEIL_DIS) { | |||
| if (OSTCBCur->OSTCBPrio == pcp) { /* Did we have to raise current task's priority? */ | |||
| OSMutex_RdyAtPrio(OSTCBCur, prio); /* Restore the task's original priority */ | |||
| } | |||
| OSTCBPrioTbl[pcp] = OS_TCB_RESERVED; /* Reserve table entry */ | |||
| } | |||
| if (pevent->OSEventGrp != 0u) { /* Any task waiting for the mutex? */ | |||
| /* Yes, Make HPT waiting for mutex ready */ | |||
| prio = OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_OK); | |||
| pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Save priority of mutex's new owner */ | |||
| pevent->OSEventCnt |= prio; | |||
| pevent->OSEventPtr = OSTCBPrioTbl[prio]; /* Link to new mutex owner's OS_TCB */ | |||
| if ((pcp != OS_PRIO_MUTEX_CEIL_DIS) && | |||
| (prio <= pcp)) { /* PCP 'must' have a SMALLER prio ... */ | |||
| OS_EXIT_CRITICAL(); /* ... than current task! */ | |||
| OS_Sched(); /* Find highest priority task ready to run */ | |||
| return (OS_ERR_PCP_LOWER); | |||
| } else { | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find highest priority task ready to run */ | |||
| return (OS_ERR_NONE); | |||
| } | |||
| } | |||
| pevent->OSEventCnt |= OS_MUTEX_AVAILABLE; /* No, Mutex is now available */ | |||
| pevent->OSEventPtr = (void *)0; | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * QUERY A MUTUAL EXCLUSION SEMAPHORE | |||
| * | |||
| * Description: This function obtains information about a mutex | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired mutex | |||
| * | |||
| * p_mutex_data is a pointer to a structure that will contain information about the mutex | |||
| * | |||
| * Returns : OS_ERR_NONE The call was successful and the message was sent | |||
| * OS_ERR_QUERY_ISR If you called this function from an ISR | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * OS_ERR_PDATA_NULL If 'p_mutex_data' is a NULL pointer | |||
| * OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non mutex. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_MUTEX_QUERY_EN > 0u | |||
| INT8U OSMutexQuery (OS_EVENT *pevent, | |||
| OS_MUTEX_DATA *p_mutex_data) | |||
| { | |||
| INT8U i; | |||
| OS_PRIO *psrc; | |||
| OS_PRIO *pdest; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| return (OS_ERR_QUERY_ISR); /* ... can't QUERY mutex from an ISR */ | |||
| } | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| if (p_mutex_data == (OS_MUTEX_DATA *)0) { /* Validate 'p_mutex_data' */ | |||
| return (OS_ERR_PDATA_NULL); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| p_mutex_data->OSMutexPCP = (INT8U)(pevent->OSEventCnt >> 8u); | |||
| p_mutex_data->OSOwnerPrio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); | |||
| if (p_mutex_data->OSOwnerPrio == 0xFFu) { | |||
| p_mutex_data->OSValue = OS_TRUE; | |||
| } else { | |||
| p_mutex_data->OSValue = OS_FALSE; | |||
| } | |||
| p_mutex_data->OSEventGrp = pevent->OSEventGrp; /* Copy wait list */ | |||
| psrc = &pevent->OSEventTbl[0]; | |||
| pdest = &p_mutex_data->OSEventTbl[0]; | |||
| for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) { | |||
| *pdest++ = *psrc++; | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif /* OS_MUTEX_QUERY_EN */ | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * RESTORE A TASK BACK TO ITS ORIGINAL PRIORITY | |||
| * | |||
| * Description: This function makes a task ready at the specified priority | |||
| * | |||
| * Arguments : ptcb is a pointer to OS_TCB of the task to make ready | |||
| * | |||
| * prio is the desired priority | |||
| * | |||
| * Returns : none | |||
| ********************************************************************************************************* | |||
| */ | |||
| static void OSMutex_RdyAtPrio (OS_TCB *ptcb, | |||
| INT8U prio) | |||
| { | |||
| INT8U y; | |||
| y = ptcb->OSTCBY; /* Remove owner from ready list at 'pcp' */ | |||
| OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; | |||
| if (OSRdyTbl[y] == 0u) { | |||
| OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY; | |||
| } | |||
| ptcb->OSTCBPrio = prio; | |||
| OSPrioCur = prio; /* The current task is now at this priority */ | |||
| #if OS_LOWEST_PRIO <= 63u | |||
| ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 3u) & 0x07u); | |||
| ptcb->OSTCBX = (INT8U)(prio & 0x07u); | |||
| #else | |||
| ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 4u) & 0x0Fu); | |||
| ptcb->OSTCBX = (INT8U) (prio & 0x0Fu); | |||
| #endif | |||
| ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY); | |||
| ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX); | |||
| OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready at original priority */ | |||
| OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; | |||
| OSTCBPrioTbl[prio] = ptcb; | |||
| } | |||
| #endif /* OS_MUTEX_EN */ | |||
| @@ -0,0 +1,901 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/OS-II | |||
| * The Real-Time Kernel | |||
| * MESSAGE QUEUE MANAGEMENT | |||
| * | |||
| * (c) Copyright 1992-2013, Micrium, Weston, FL | |||
| * All Rights Reserved | |||
| * | |||
| * File : OS_Q.C | |||
| * By : Jean J. Labrosse | |||
| * Version : V2.92.11 | |||
| * | |||
| * LICENSING TERMS: | |||
| * --------------- | |||
| * uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research. | |||
| * If you plan on using uC/OS-II in a commercial product you need to contact Micrium to properly license | |||
| * its use in your product. We provide ALL the source code for your convenience and to help you experience | |||
| * uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a | |||
| * licensing fee. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MICRIUM_SOURCE | |||
| #ifndef OS_MASTER_FILE | |||
| #include <ucos_ii.h> | |||
| #endif | |||
| #if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ACCEPT MESSAGE FROM QUEUE | |||
| * | |||
| * Description: This function checks the queue to see if a message is available. Unlike OSQPend(), | |||
| * OSQAccept() does not suspend the calling task if a message is not available. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block | |||
| * | |||
| * perr is a pointer to where an error message will be deposited. Possible error | |||
| * messages are: | |||
| * | |||
| * OS_ERR_NONE The call was successful and your task received a | |||
| * message. | |||
| * OS_ERR_EVENT_TYPE You didn't pass a pointer to a queue | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * OS_ERR_Q_EMPTY The queue did not contain any messages | |||
| * | |||
| * Returns : != (void *)0 is the message in the queue if one is available. The message is removed | |||
| * from the so the next time OSQAccept() is called, the queue will contain | |||
| * one less entry. | |||
| * == (void *)0 if you received a NULL pointer message | |||
| * if the queue is empty or, | |||
| * if 'pevent' is a NULL pointer or, | |||
| * if you passed an invalid event type | |||
| * | |||
| * Note(s) : As of V2.60, you can now pass NULL pointers through queues. Because of this, the argument | |||
| * 'perr' has been added to the API to tell you about the outcome of the call. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_Q_ACCEPT_EN > 0u | |||
| void *OSQAccept (OS_EVENT *pevent, | |||
| INT8U *perr) | |||
| { | |||
| void *pmsg; | |||
| OS_Q *pq; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((void *)0); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return ((void *)0); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return ((void *)0); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| pq = (OS_Q *)pevent->OSEventPtr; /* Point at queue control block */ | |||
| if (pq->OSQEntries > 0u) { /* See if any messages in the queue */ | |||
| pmsg = *pq->OSQOut++; /* Yes, extract oldest message from the queue */ | |||
| pq->OSQEntries--; /* Update the number of entries in the queue */ | |||
| if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of the queue */ | |||
| pq->OSQOut = pq->OSQStart; | |||
| } | |||
| *perr = OS_ERR_NONE; | |||
| } else { | |||
| *perr = OS_ERR_Q_EMPTY; | |||
| pmsg = (void *)0; /* Queue is empty */ | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| return (pmsg); /* Return message received (or NULL) */ | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CREATE A MESSAGE QUEUE | |||
| * | |||
| * Description: This function creates a message queue if free event control blocks are available. | |||
| * | |||
| * Arguments : start is a pointer to the base address of the message queue storage area. The | |||
| * storage area MUST be declared as an array of pointers to 'void' as follows | |||
| * | |||
| * void *MessageStorage[size] | |||
| * | |||
| * size is the number of elements in the storage area | |||
| * | |||
| * Returns : != (OS_EVENT *)0 is a pointer to the event control clock (OS_EVENT) associated with the | |||
| * created queue | |||
| * == (OS_EVENT *)0 if no event control blocks were available or an error was detected | |||
| ********************************************************************************************************* | |||
| */ | |||
| OS_EVENT *OSQCreate (void **start, | |||
| INT16U size) | |||
| { | |||
| OS_EVENT *pevent; | |||
| OS_Q *pq; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL_IEC61508 | |||
| if (OSSafetyCriticalStartFlag == OS_TRUE) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| #endif | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */ | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| pevent = OSEventFreeList; /* Get next free event control block */ | |||
| if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */ | |||
| OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| if (pevent != (OS_EVENT *)0) { /* See if we have an event control block */ | |||
| OS_ENTER_CRITICAL(); | |||
| pq = OSQFreeList; /* Get a free queue control block */ | |||
| if (pq != (OS_Q *)0) { /* Were we able to get a queue control block ? */ | |||
| OSQFreeList = OSQFreeList->OSQPtr; /* Yes, Adjust free list pointer to next free*/ | |||
| OS_EXIT_CRITICAL(); | |||
| pq->OSQStart = start; /* Initialize the queue */ | |||
| pq->OSQEnd = &start[size]; | |||
| pq->OSQIn = start; | |||
| pq->OSQOut = start; | |||
| pq->OSQSize = size; | |||
| pq->OSQEntries = 0u; | |||
| pevent->OSEventType = OS_EVENT_TYPE_Q; | |||
| pevent->OSEventCnt = 0u; | |||
| pevent->OSEventPtr = pq; | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| OS_EventWaitListInit(pevent); /* Initialize the wait list */ | |||
| } else { | |||
| pevent->OSEventPtr = (void *)OSEventFreeList; /* No, Return event control block on error */ | |||
| OSEventFreeList = pevent; | |||
| OS_EXIT_CRITICAL(); | |||
| pevent = (OS_EVENT *)0; | |||
| } | |||
| } | |||
| return (pevent); | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DELETE A MESSAGE QUEUE | |||
| * | |||
| * Description: This function deletes a message queue and readies all tasks pending on the queue. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired | |||
| * queue. | |||
| * | |||
| * opt determines delete options as follows: | |||
| * opt == OS_DEL_NO_PEND Delete the queue ONLY if no task pending | |||
| * opt == OS_DEL_ALWAYS Deletes the queue even if tasks are waiting. | |||
| * In this case, all the tasks pending will be readied. | |||
| * | |||
| * perr is a pointer to an error code that can contain one of the following values: | |||
| * OS_ERR_NONE The call was successful and the queue was deleted | |||
| * OS_ERR_DEL_ISR If you tried to delete the queue from an ISR | |||
| * OS_ERR_INVALID_OPT An invalid option was specified | |||
| * OS_ERR_TASK_WAITING One or more tasks were waiting on the queue | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. | |||
| * | |||
| * Returns : pevent upon error | |||
| * (OS_EVENT *)0 if the queue was successfully deleted. | |||
| * | |||
| * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of | |||
| * the queue MUST check the return code of OSQPend(). | |||
| * 2) OSQAccept() callers will not know that the intended queue has been deleted unless | |||
| * they check 'pevent' to see that it's a NULL pointer. | |||
| * 3) This call can potentially disable interrupts for a long time. The interrupt disable | |||
| * time is directly proportional to the number of tasks waiting on the queue. | |||
| * 4) Because ALL tasks pending on the queue will be readied, you MUST be careful in | |||
| * applications where the queue is used for mutual exclusion because the resource(s) | |||
| * will no longer be guarded by the queue. | |||
| * 5) If the storage for the message queue was allocated dynamically (i.e. using a malloc() | |||
| * type call) then your application MUST release the memory storage by call the counterpart | |||
| * call of the dynamic allocation scheme used. If the queue storage was created statically | |||
| * then, the storage can be reused. | |||
| * 6) All tasks that were waiting for the queue will be readied and returned an | |||
| * OS_ERR_PEND_ABORT if OSQDel() was called with OS_DEL_ALWAYS | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_Q_DEL_EN > 0u | |||
| OS_EVENT *OSQDel (OS_EVENT *pevent, | |||
| INT8U opt, | |||
| INT8U *perr) | |||
| { | |||
| BOOLEAN tasks_waiting; | |||
| OS_EVENT *pevent_return; | |||
| OS_Q *pq; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return (pevent); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return (pevent); | |||
| } | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ | |||
| return (pevent); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on queue */ | |||
| tasks_waiting = OS_TRUE; /* Yes */ | |||
| } else { | |||
| tasks_waiting = OS_FALSE; /* No */ | |||
| } | |||
| switch (opt) { | |||
| case OS_DEL_NO_PEND: /* Delete queue only if no task waiting */ | |||
| if (tasks_waiting == OS_FALSE) { | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| pq = (OS_Q *)pevent->OSEventPtr; /* Return OS_Q to free list */ | |||
| pq->OSQPtr = OSQFreeList; | |||
| OSQFreeList = pq; | |||
| pevent->OSEventType = OS_EVENT_TYPE_UNUSED; | |||
| pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ | |||
| pevent->OSEventCnt = 0u; | |||
| OSEventFreeList = pevent; /* Get next free event control block */ | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| pevent_return = (OS_EVENT *)0; /* Queue has been deleted */ | |||
| } else { | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_TASK_WAITING; | |||
| pevent_return = pevent; | |||
| } | |||
| break; | |||
| case OS_DEL_ALWAYS: /* Always delete the queue */ | |||
| while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for queue */ | |||
| (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT); | |||
| } | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| pq = (OS_Q *)pevent->OSEventPtr; /* Return OS_Q to free list */ | |||
| pq->OSQPtr = OSQFreeList; | |||
| OSQFreeList = pq; | |||
| pevent->OSEventType = OS_EVENT_TYPE_UNUSED; | |||
| pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ | |||
| pevent->OSEventCnt = 0u; | |||
| OSEventFreeList = pevent; /* Get next free event control block */ | |||
| OS_EXIT_CRITICAL(); | |||
| if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ | |||
| OS_Sched(); /* Find highest priority task ready to run */ | |||
| } | |||
| *perr = OS_ERR_NONE; | |||
| pevent_return = (OS_EVENT *)0; /* Queue has been deleted */ | |||
| break; | |||
| default: | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_INVALID_OPT; | |||
| pevent_return = pevent; | |||
| break; | |||
| } | |||
| return (pevent_return); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * FLUSH QUEUE | |||
| * | |||
| * Description : This function is used to flush the contents of the message queue. | |||
| * | |||
| * Arguments : none | |||
| * | |||
| * Returns : OS_ERR_NONE upon success | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * | |||
| * WARNING : You should use this function with great care because, when to flush the queue, you LOOSE | |||
| * the references to what the queue entries are pointing to and thus, you could cause | |||
| * 'memory leaks'. In other words, the data you are pointing to that's being referenced | |||
| * by the queue entries should, most likely, need to be de-allocated (i.e. freed). | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_Q_FLUSH_EN > 0u | |||
| INT8U OSQFlush (OS_EVENT *pevent) | |||
| { | |||
| OS_Q *pq; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| #endif | |||
| OS_ENTER_CRITICAL(); | |||
| pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue storage structure */ | |||
| pq->OSQIn = pq->OSQStart; | |||
| pq->OSQOut = pq->OSQStart; | |||
| pq->OSQEntries = 0u; | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * PEND ON A QUEUE FOR A MESSAGE | |||
| * | |||
| * Description: This function waits for a message to be sent to a queue | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired queue | |||
| * | |||
| * timeout is an optional timeout period (in clock ticks). If non-zero, your task will | |||
| * wait for a message to arrive at the queue up to the amount of time | |||
| * specified by this argument. If you specify 0, however, your task will wait | |||
| * forever at the specified queue or, until a message arrives. | |||
| * | |||
| * perr is a pointer to where an error message will be deposited. Possible error | |||
| * messages are: | |||
| * | |||
| * OS_ERR_NONE The call was successful and your task received a | |||
| * message. | |||
| * OS_ERR_TIMEOUT A message was not received within the specified 'timeout'. | |||
| * OS_ERR_PEND_ABORT The wait on the queue was aborted. | |||
| * OS_ERR_EVENT_TYPE You didn't pass a pointer to a queue | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * OS_ERR_PEND_ISR If you called this function from an ISR and the result | |||
| * would lead to a suspension. | |||
| * OS_ERR_PEND_LOCKED If you called this function with the scheduler is locked | |||
| * | |||
| * Returns : != (void *)0 is a pointer to the message received | |||
| * == (void *)0 if you received a NULL pointer message or, | |||
| * if no message was received or, | |||
| * if 'pevent' is a NULL pointer or, | |||
| * if you didn't pass a pointer to a queue. | |||
| * | |||
| * Note(s) : As of V2.60, this function allows you to receive NULL pointer messages. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void *OSQPend (OS_EVENT *pevent, | |||
| INT32U timeout, | |||
| INT8U *perr) | |||
| { | |||
| void *pmsg; | |||
| OS_Q *pq; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((void *)0); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return ((void *)0); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return ((void *)0); | |||
| } | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ | |||
| return ((void *)0); | |||
| } | |||
| if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ | |||
| *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ | |||
| return ((void *)0); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| pq = (OS_Q *)pevent->OSEventPtr; /* Point at queue control block */ | |||
| if (pq->OSQEntries > 0u) { /* See if any messages in the queue */ | |||
| pmsg = *pq->OSQOut++; /* Yes, extract oldest message from the queue */ | |||
| pq->OSQEntries--; /* Update the number of entries in the queue */ | |||
| if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of the queue */ | |||
| pq->OSQOut = pq->OSQStart; | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| return (pmsg); /* Return message received */ | |||
| } | |||
| OSTCBCur->OSTCBStat |= OS_STAT_Q; /* Task will have to pend for a message to be posted */ | |||
| OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; | |||
| OSTCBCur->OSTCBDly = timeout; /* Load timeout into TCB */ | |||
| OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find next highest priority task ready to run */ | |||
| OS_ENTER_CRITICAL(); | |||
| switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ | |||
| case OS_STAT_PEND_OK: /* Extract message from TCB (Put there by QPost) */ | |||
| pmsg = OSTCBCur->OSTCBMsg; | |||
| *perr = OS_ERR_NONE; | |||
| break; | |||
| case OS_STAT_PEND_ABORT: | |||
| pmsg = (void *)0; | |||
| *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */ | |||
| break; | |||
| case OS_STAT_PEND_TO: | |||
| default: | |||
| OS_EventTaskRemove(OSTCBCur, pevent); | |||
| pmsg = (void *)0; | |||
| *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */ | |||
| break; | |||
| } | |||
| OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ | |||
| OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ | |||
| OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ | |||
| #if (OS_EVENT_MULTI_EN > 0u) | |||
| OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; | |||
| #endif | |||
| OSTCBCur->OSTCBMsg = (void *)0; /* Clear received message */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (pmsg); /* Return received message */ | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ABORT WAITING ON A MESSAGE QUEUE | |||
| * | |||
| * Description: This function aborts & readies any tasks currently waiting on a queue. This function | |||
| * should be used to fault-abort the wait on the queue, rather than to normally signal | |||
| * the queue via OSQPost(), OSQPostFront() or OSQPostOpt(). | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired queue. | |||
| * | |||
| * opt determines the type of ABORT performed: | |||
| * OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the | |||
| * queue | |||
| * OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the | |||
| * queue | |||
| * | |||
| * perr is a pointer to where an error message will be deposited. Possible error | |||
| * messages are: | |||
| * | |||
| * OS_ERR_NONE No tasks were waiting on the queue. | |||
| * OS_ERR_PEND_ABORT At least one task waiting on the queue was readied | |||
| * and informed of the aborted wait; check return value | |||
| * for the number of tasks whose wait on the queue | |||
| * was aborted. | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. | |||
| * | |||
| * Returns : == 0 if no tasks were waiting on the queue, or upon error. | |||
| * > 0 if one or more tasks waiting on the queue are now readied and informed. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_Q_PEND_ABORT_EN > 0u | |||
| INT8U OSQPendAbort (OS_EVENT *pevent, | |||
| INT8U opt, | |||
| INT8U *perr) | |||
| { | |||
| INT8U nbr_tasks; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return (0u); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return (0u); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return (0u); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any task waiting on queue? */ | |||
| nbr_tasks = 0u; | |||
| switch (opt) { | |||
| case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */ | |||
| while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on queue */ | |||
| (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT); | |||
| nbr_tasks++; | |||
| } | |||
| break; | |||
| case OS_PEND_OPT_NONE: | |||
| default: /* No, ready HPT waiting on queue */ | |||
| (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT); | |||
| nbr_tasks++; | |||
| break; | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find HPT ready to run */ | |||
| *perr = OS_ERR_PEND_ABORT; | |||
| return (nbr_tasks); | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| return (0u); /* No tasks waiting on queue */ | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * POST MESSAGE TO A QUEUE | |||
| * | |||
| * Description: This function sends a message to a queue | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired queue | |||
| * | |||
| * pmsg is a pointer to the message to send. | |||
| * | |||
| * Returns : OS_ERR_NONE The call was successful and the message was sent | |||
| * OS_ERR_Q_FULL If the queue cannot accept any more messages because it is full. | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * | |||
| * Note(s) : As of V2.60, this function allows you to send NULL pointer messages. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_Q_POST_EN > 0u | |||
| INT8U OSQPost (OS_EVENT *pevent, | |||
| void *pmsg) | |||
| { | |||
| OS_Q *pq; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any task pending on queue */ | |||
| /* Ready highest priority task waiting on event */ | |||
| (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK); | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find highest priority task ready to run */ | |||
| return (OS_ERR_NONE); | |||
| } | |||
| pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue control block */ | |||
| if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_Q_FULL); | |||
| } | |||
| *pq->OSQIn++ = pmsg; /* Insert message into queue */ | |||
| pq->OSQEntries++; /* Update the nbr of entries in the queue */ | |||
| if (pq->OSQIn == pq->OSQEnd) { /* Wrap IN ptr if we are at end of queue */ | |||
| pq->OSQIn = pq->OSQStart; | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * POST MESSAGE TO THE FRONT OF A QUEUE | |||
| * | |||
| * Description: This function sends a message to a queue but unlike OSQPost(), the message is posted at | |||
| * the front instead of the end of the queue. Using OSQPostFront() allows you to send | |||
| * 'priority' messages. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired queue | |||
| * | |||
| * pmsg is a pointer to the message to send. | |||
| * | |||
| * Returns : OS_ERR_NONE The call was successful and the message was sent | |||
| * OS_ERR_Q_FULL If the queue cannot accept any more messages because it is full. | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * | |||
| * Note(s) : As of V2.60, this function allows you to send NULL pointer messages. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_Q_POST_FRONT_EN > 0u | |||
| INT8U OSQPostFront (OS_EVENT *pevent, | |||
| void *pmsg) | |||
| { | |||
| OS_Q *pq; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any task pending on queue */ | |||
| /* Ready highest priority task waiting on event */ | |||
| (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK); | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find highest priority task ready to run */ | |||
| return (OS_ERR_NONE); | |||
| } | |||
| pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue control block */ | |||
| if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_Q_FULL); | |||
| } | |||
| if (pq->OSQOut == pq->OSQStart) { /* Wrap OUT ptr if we are at the 1st queue entry */ | |||
| pq->OSQOut = pq->OSQEnd; | |||
| } | |||
| pq->OSQOut--; | |||
| *pq->OSQOut = pmsg; /* Insert message into queue */ | |||
| pq->OSQEntries++; /* Update the nbr of entries in the queue */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * POST MESSAGE TO A QUEUE | |||
| * | |||
| * Description: This function sends a message to a queue. This call has been added to reduce code size | |||
| * since it can replace both OSQPost() and OSQPostFront(). Also, this function adds the | |||
| * capability to broadcast a message to ALL tasks waiting on the message queue. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired queue | |||
| * | |||
| * pmsg is a pointer to the message to send. | |||
| * | |||
| * opt determines the type of POST performed: | |||
| * OS_POST_OPT_NONE POST to a single waiting task | |||
| * (Identical to OSQPost()) | |||
| * OS_POST_OPT_BROADCAST POST to ALL tasks that are waiting on the queue | |||
| * OS_POST_OPT_FRONT POST as LIFO (Simulates OSQPostFront()) | |||
| * OS_POST_OPT_NO_SCHED Indicates that the scheduler will NOT be invoked | |||
| * | |||
| * Returns : OS_ERR_NONE The call was successful and the message was sent | |||
| * OS_ERR_Q_FULL If the queue cannot accept any more messages because it is full. | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * | |||
| * Warning : Interrupts can be disabled for a long time if you do a 'broadcast'. In fact, the | |||
| * interrupt disable time is proportional to the number of tasks waiting on the queue. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_Q_POST_OPT_EN > 0u | |||
| INT8U OSQPostOpt (OS_EVENT *pevent, | |||
| void *pmsg, | |||
| INT8U opt) | |||
| { | |||
| OS_Q *pq; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0x00u) { /* See if any task pending on queue */ | |||
| if ((opt & OS_POST_OPT_BROADCAST) != 0x00u) { /* Do we need to post msg to ALL waiting tasks ? */ | |||
| while (pevent->OSEventGrp != 0u) { /* Yes, Post to ALL tasks waiting on queue */ | |||
| (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK); | |||
| } | |||
| } else { /* No, Post to HPT waiting on queue */ | |||
| (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK); | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| if ((opt & OS_POST_OPT_NO_SCHED) == 0u) { /* See if scheduler needs to be invoked */ | |||
| OS_Sched(); /* Find highest priority task ready to run */ | |||
| } | |||
| return (OS_ERR_NONE); | |||
| } | |||
| pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue control block */ | |||
| if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_Q_FULL); | |||
| } | |||
| if ((opt & OS_POST_OPT_FRONT) != 0x00u) { /* Do we post to the FRONT of the queue? */ | |||
| if (pq->OSQOut == pq->OSQStart) { /* Yes, Post as LIFO, Wrap OUT pointer if we ... */ | |||
| pq->OSQOut = pq->OSQEnd; /* ... are at the 1st queue entry */ | |||
| } | |||
| pq->OSQOut--; | |||
| *pq->OSQOut = pmsg; /* Insert message into queue */ | |||
| } else { /* No, Post as FIFO */ | |||
| *pq->OSQIn++ = pmsg; /* Insert message into queue */ | |||
| if (pq->OSQIn == pq->OSQEnd) { /* Wrap IN ptr if we are at end of queue */ | |||
| pq->OSQIn = pq->OSQStart; | |||
| } | |||
| } | |||
| pq->OSQEntries++; /* Update the nbr of entries in the queue */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * QUERY A MESSAGE QUEUE | |||
| * | |||
| * Description: This function obtains information about a message queue. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired queue | |||
| * | |||
| * p_q_data is a pointer to a structure that will contain information about the message | |||
| * queue. | |||
| * | |||
| * Returns : OS_ERR_NONE The call was successful and the message was sent | |||
| * OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non queue. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer | |||
| * OS_ERR_PDATA_NULL If 'p_q_data' is a NULL pointer | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_Q_QUERY_EN > 0u | |||
| INT8U OSQQuery (OS_EVENT *pevent, | |||
| OS_Q_DATA *p_q_data) | |||
| { | |||
| OS_Q *pq; | |||
| INT8U i; | |||
| OS_PRIO *psrc; | |||
| OS_PRIO *pdest; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| if (p_q_data == (OS_Q_DATA *)0) { /* Validate 'p_q_data' */ | |||
| return (OS_ERR_PDATA_NULL); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| p_q_data->OSEventGrp = pevent->OSEventGrp; /* Copy message queue wait list */ | |||
| psrc = &pevent->OSEventTbl[0]; | |||
| pdest = &p_q_data->OSEventTbl[0]; | |||
| for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) { | |||
| *pdest++ = *psrc++; | |||
| } | |||
| pq = (OS_Q *)pevent->OSEventPtr; | |||
| if (pq->OSQEntries > 0u) { | |||
| p_q_data->OSMsg = *pq->OSQOut; /* Get next message to return if available */ | |||
| } else { | |||
| p_q_data->OSMsg = (void *)0; | |||
| } | |||
| p_q_data->OSNMsgs = pq->OSQEntries; | |||
| p_q_data->OSQSize = pq->OSQSize; | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif /* OS_Q_QUERY_EN */ | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * QUEUE MODULE INITIALIZATION | |||
| * | |||
| * Description : This function is called by uC/OS-II to initialize the message queue module. Your | |||
| * application MUST NOT call this function. | |||
| * | |||
| * Arguments : none | |||
| * | |||
| * Returns : none | |||
| * | |||
| * Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it. | |||
| ********************************************************************************************************* | |||
| */ | |||
| void OS_QInit (void) | |||
| { | |||
| #if OS_MAX_QS == 1u | |||
| OSQFreeList = &OSQTbl[0]; /* Only ONE queue! */ | |||
| OSQFreeList->OSQPtr = (OS_Q *)0; | |||
| #endif | |||
| #if OS_MAX_QS >= 2u | |||
| INT16U ix; | |||
| INT16U ix_next; | |||
| OS_Q *pq1; | |||
| OS_Q *pq2; | |||
| OS_MemClr((INT8U *)&OSQTbl[0], sizeof(OSQTbl)); /* Clear the queue table */ | |||
| for (ix = 0u; ix < (OS_MAX_QS - 1u); ix++) { /* Init. list of free QUEUE control blocks */ | |||
| ix_next = ix + 1u; | |||
| pq1 = &OSQTbl[ix]; | |||
| pq2 = &OSQTbl[ix_next]; | |||
| pq1->OSQPtr = pq2; | |||
| } | |||
| pq1 = &OSQTbl[ix]; | |||
| pq1->OSQPtr = (OS_Q *)0; | |||
| OSQFreeList = &OSQTbl[0]; | |||
| #endif | |||
| } | |||
| #endif /* OS_Q_EN */ | |||
| @@ -0,0 +1,637 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/OS-II | |||
| * The Real-Time Kernel | |||
| * SEMAPHORE MANAGEMENT | |||
| * | |||
| * (c) Copyright 1992-2013, Micrium, Weston, FL | |||
| * All Rights Reserved | |||
| * | |||
| * File : OS_SEM.C | |||
| * By : Jean J. Labrosse | |||
| * Version : V2.92.11 | |||
| * | |||
| * LICENSING TERMS: | |||
| * --------------- | |||
| * uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research. | |||
| * If you plan on using uC/OS-II in a commercial product you need to contact Micrium to properly license | |||
| * its use in your product. We provide ALL the source code for your convenience and to help you experience | |||
| * uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a | |||
| * licensing fee. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MICRIUM_SOURCE | |||
| #ifndef OS_MASTER_FILE | |||
| #include <ucos_ii.h> | |||
| #endif | |||
| #if OS_SEM_EN > 0u | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ACCEPT SEMAPHORE | |||
| * | |||
| * Description: This function checks the semaphore to see if a resource is available or, if an event | |||
| * occurred. Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the | |||
| * resource is not available or the event did not occur. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block | |||
| * | |||
| * Returns : > 0 if the resource is available or the event did not occur the semaphore is | |||
| * decremented to obtain the resource. | |||
| * == 0 if the resource is not available or the event did not occur or, | |||
| * if 'pevent' is a NULL pointer or, | |||
| * if you didn't pass a pointer to a semaphore | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_SEM_ACCEPT_EN > 0u | |||
| INT16U OSSemAccept (OS_EVENT *pevent) | |||
| { | |||
| INT16U cnt; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (0u); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ | |||
| return (0u); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| cnt = pevent->OSEventCnt; | |||
| if (cnt > 0u) { /* See if resource is available */ | |||
| pevent->OSEventCnt--; /* Yes, decrement semaphore and notify caller */ | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| return (cnt); /* Return semaphore count */ | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * CREATE A SEMAPHORE | |||
| * | |||
| * Description: This function creates a semaphore. | |||
| * | |||
| * Arguments : cnt is the initial value for the semaphore. If the value is 0, no resource is | |||
| * available (or no event has occurred). You initialize the semaphore to a | |||
| * non-zero value to specify how many resources are available (e.g. if you have | |||
| * 10 resources, you would initialize the semaphore to 10). | |||
| * | |||
| * Returns : != (void *)0 is a pointer to the event control block (OS_EVENT) associated with the | |||
| * created semaphore | |||
| * == (void *)0 if no event control blocks were available | |||
| ********************************************************************************************************* | |||
| */ | |||
| OS_EVENT *OSSemCreate (INT16U cnt) | |||
| { | |||
| OS_EVENT *pevent; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL_IEC61508 | |||
| if (OSSafetyCriticalStartFlag == OS_TRUE) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| #endif | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */ | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| pevent = OSEventFreeList; /* Get next free event control block */ | |||
| if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */ | |||
| OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| if (pevent != (OS_EVENT *)0) { /* Get an event control block */ | |||
| pevent->OSEventType = OS_EVENT_TYPE_SEM; | |||
| pevent->OSEventCnt = cnt; /* Set semaphore value */ | |||
| pevent->OSEventPtr = (void *)0; /* Unlink from ECB free list */ | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| OS_EventWaitListInit(pevent); /* Initialize to 'nobody waiting' on sem. */ | |||
| } | |||
| return (pevent); | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DELETE A SEMAPHORE | |||
| * | |||
| * Description: This function deletes a semaphore and readies all tasks pending on the semaphore. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired | |||
| * semaphore. | |||
| * | |||
| * opt determines delete options as follows: | |||
| * opt == OS_DEL_NO_PEND Delete semaphore ONLY if no task pending | |||
| * opt == OS_DEL_ALWAYS Deletes the semaphore even if tasks are waiting. | |||
| * In this case, all the tasks pending will be readied. | |||
| * | |||
| * perr is a pointer to an error code that can contain one of the following values: | |||
| * OS_ERR_NONE The call was successful and the semaphore was deleted | |||
| * OS_ERR_DEL_ISR If you attempted to delete the semaphore from an ISR | |||
| * OS_ERR_INVALID_OPT An invalid option was specified | |||
| * OS_ERR_TASK_WAITING One or more tasks were waiting on the semaphore | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. | |||
| * | |||
| * Returns : pevent upon error | |||
| * (OS_EVENT *)0 if the semaphore was successfully deleted. | |||
| * | |||
| * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of | |||
| * the semaphore MUST check the return code of OSSemPend(). | |||
| * 2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless | |||
| * they check 'pevent' to see that it's a NULL pointer. | |||
| * 3) This call can potentially disable interrupts for a long time. The interrupt disable | |||
| * time is directly proportional to the number of tasks waiting on the semaphore. | |||
| * 4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in | |||
| * applications where the semaphore is used for mutual exclusion because the resource(s) | |||
| * will no longer be guarded by the semaphore. | |||
| * 5) All tasks that were waiting for the semaphore will be readied and returned an | |||
| * OS_ERR_PEND_ABORT if OSSemDel() was called with OS_DEL_ALWAYS | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_SEM_DEL_EN > 0u | |||
| OS_EVENT *OSSemDel (OS_EVENT *pevent, | |||
| INT8U opt, | |||
| INT8U *perr) | |||
| { | |||
| BOOLEAN tasks_waiting; | |||
| OS_EVENT *pevent_return; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return ((OS_EVENT *)0); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return (pevent); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return (pevent); | |||
| } | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ | |||
| return (pevent); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on semaphore */ | |||
| tasks_waiting = OS_TRUE; /* Yes */ | |||
| } else { | |||
| tasks_waiting = OS_FALSE; /* No */ | |||
| } | |||
| switch (opt) { | |||
| case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */ | |||
| if (tasks_waiting == OS_FALSE) { | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| pevent->OSEventType = OS_EVENT_TYPE_UNUSED; | |||
| pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ | |||
| pevent->OSEventCnt = 0u; | |||
| OSEventFreeList = pevent; /* Get next free event control block */ | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */ | |||
| } else { | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_TASK_WAITING; | |||
| pevent_return = pevent; | |||
| } | |||
| break; | |||
| case OS_DEL_ALWAYS: /* Always delete the semaphore */ | |||
| while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for semaphore */ | |||
| (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT); | |||
| } | |||
| #if OS_EVENT_NAME_EN > 0u | |||
| pevent->OSEventName = (INT8U *)(void *)"?"; | |||
| #endif | |||
| pevent->OSEventType = OS_EVENT_TYPE_UNUSED; | |||
| pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ | |||
| pevent->OSEventCnt = 0u; | |||
| OSEventFreeList = pevent; /* Get next free event control block */ | |||
| OS_EXIT_CRITICAL(); | |||
| if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ | |||
| OS_Sched(); /* Find highest priority task ready to run */ | |||
| } | |||
| *perr = OS_ERR_NONE; | |||
| pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */ | |||
| break; | |||
| default: | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_INVALID_OPT; | |||
| pevent_return = pevent; | |||
| break; | |||
| } | |||
| return (pevent_return); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * PEND ON SEMAPHORE | |||
| * | |||
| * Description: This function waits for a semaphore. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired | |||
| * semaphore. | |||
| * | |||
| * timeout is an optional timeout period (in clock ticks). If non-zero, your task will | |||
| * wait for the resource up to the amount of time specified by this argument. | |||
| * If you specify 0, however, your task will wait forever at the specified | |||
| * semaphore or, until the resource becomes available (or the event occurs). | |||
| * | |||
| * perr is a pointer to where an error message will be deposited. Possible error | |||
| * messages are: | |||
| * | |||
| * OS_ERR_NONE The call was successful and your task owns the resource | |||
| * or, the event you are waiting for occurred. | |||
| * OS_ERR_TIMEOUT The semaphore was not received within the specified | |||
| * 'timeout'. | |||
| * OS_ERR_PEND_ABORT The wait on the semaphore was aborted. | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore. | |||
| * OS_ERR_PEND_ISR If you called this function from an ISR and the result | |||
| * would lead to a suspension. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. | |||
| * OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked | |||
| * | |||
| * Returns : none | |||
| ********************************************************************************************************* | |||
| */ | |||
| /*$PAGE*/ | |||
| void OSSemPend (OS_EVENT *pevent, | |||
| INT32U timeout, | |||
| INT8U *perr) | |||
| { | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return; | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return; | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return; | |||
| } | |||
| if (OSIntNesting > 0u) { /* See if called from ISR ... */ | |||
| *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ | |||
| return; | |||
| } | |||
| if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ | |||
| *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ | |||
| return; | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventCnt > 0u) { /* If sem. is positive, resource available ... */ | |||
| pevent->OSEventCnt--; /* ... decrement semaphore only if positive. */ | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| return; | |||
| } | |||
| /* Otherwise, must wait until event occurs */ | |||
| OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */ | |||
| OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; | |||
| OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */ | |||
| OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find next highest priority task ready */ | |||
| OS_ENTER_CRITICAL(); | |||
| switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ | |||
| case OS_STAT_PEND_OK: | |||
| *perr = OS_ERR_NONE; | |||
| break; | |||
| case OS_STAT_PEND_ABORT: | |||
| *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */ | |||
| break; | |||
| case OS_STAT_PEND_TO: | |||
| default: | |||
| OS_EventTaskRemove(OSTCBCur, pevent); | |||
| *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */ | |||
| break; | |||
| } | |||
| OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ | |||
| OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ | |||
| OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ | |||
| #if (OS_EVENT_MULTI_EN > 0u) | |||
| OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; | |||
| #endif | |||
| OS_EXIT_CRITICAL(); | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * ABORT WAITING ON A SEMAPHORE | |||
| * | |||
| * Description: This function aborts & readies any tasks currently waiting on a semaphore. This function | |||
| * should be used to fault-abort the wait on the semaphore, rather than to normally signal | |||
| * the semaphore via OSSemPost(). | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired | |||
| * semaphore. | |||
| * | |||
| * opt determines the type of ABORT performed: | |||
| * OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the | |||
| * semaphore | |||
| * OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the | |||
| * semaphore | |||
| * | |||
| * perr is a pointer to where an error message will be deposited. Possible error | |||
| * messages are: | |||
| * | |||
| * OS_ERR_NONE No tasks were waiting on the semaphore. | |||
| * OS_ERR_PEND_ABORT At least one task waiting on the semaphore was readied | |||
| * and informed of the aborted wait; check return value | |||
| * for the number of tasks whose wait on the semaphore | |||
| * was aborted. | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. | |||
| * | |||
| * Returns : == 0 if no tasks were waiting on the semaphore, or upon error. | |||
| * > 0 if one or more tasks waiting on the semaphore are now readied and informed. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_SEM_PEND_ABORT_EN > 0u | |||
| INT8U OSSemPendAbort (OS_EVENT *pevent, | |||
| INT8U opt, | |||
| INT8U *perr) | |||
| { | |||
| INT8U nbr_tasks; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return (0u); | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return (0u); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return (0u); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any task waiting on semaphore? */ | |||
| nbr_tasks = 0u; | |||
| switch (opt) { | |||
| case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */ | |||
| while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on semaphore */ | |||
| (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT); | |||
| nbr_tasks++; | |||
| } | |||
| break; | |||
| case OS_PEND_OPT_NONE: | |||
| default: /* No, ready HPT waiting on semaphore */ | |||
| (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT); | |||
| nbr_tasks++; | |||
| break; | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find HPT ready to run */ | |||
| *perr = OS_ERR_PEND_ABORT; | |||
| return (nbr_tasks); | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| return (0u); /* No tasks waiting on semaphore */ | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * POST TO A SEMAPHORE | |||
| * | |||
| * Description: This function signals a semaphore | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired | |||
| * semaphore. | |||
| * | |||
| * Returns : OS_ERR_NONE The call was successful and the semaphore was signaled. | |||
| * OS_ERR_SEM_OVF If the semaphore count exceeded its limit. In other words, you have | |||
| * signaled the semaphore more often than you waited on it with either | |||
| * OSSemAccept() or OSSemPend(). | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. | |||
| ********************************************************************************************************* | |||
| */ | |||
| INT8U OSSemPost (OS_EVENT *pevent) | |||
| { | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| if (pevent->OSEventGrp != 0u) { /* See if any task waiting for semaphore */ | |||
| /* Ready HPT waiting on event */ | |||
| (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK); | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find HPT ready to run */ | |||
| return (OS_ERR_NONE); | |||
| } | |||
| if (pevent->OSEventCnt < 65535u) { /* Make sure semaphore will not overflow */ | |||
| pevent->OSEventCnt++; /* Increment semaphore count to register event */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| OS_EXIT_CRITICAL(); /* Semaphore value has reached its maximum */ | |||
| return (OS_ERR_SEM_OVF); | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * QUERY A SEMAPHORE | |||
| * | |||
| * Description: This function obtains information about a semaphore | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block associated with the desired | |||
| * semaphore | |||
| * | |||
| * p_sem_data is a pointer to a structure that will contain information about the | |||
| * semaphore. | |||
| * | |||
| * Returns : OS_ERR_NONE The call was successful and the message was sent | |||
| * OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non semaphore. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. | |||
| * OS_ERR_PDATA_NULL If 'p_sem_data' is a NULL pointer | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_SEM_QUERY_EN > 0u | |||
| INT8U OSSemQuery (OS_EVENT *pevent, | |||
| OS_SEM_DATA *p_sem_data) | |||
| { | |||
| INT8U i; | |||
| OS_PRIO *psrc; | |||
| OS_PRIO *pdest; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| return (OS_ERR_PEVENT_NULL); | |||
| } | |||
| if (p_sem_data == (OS_SEM_DATA *)0) { /* Validate 'p_sem_data' */ | |||
| return (OS_ERR_PDATA_NULL); | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ | |||
| return (OS_ERR_EVENT_TYPE); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| p_sem_data->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */ | |||
| psrc = &pevent->OSEventTbl[0]; | |||
| pdest = &p_sem_data->OSEventTbl[0]; | |||
| for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) { | |||
| *pdest++ = *psrc++; | |||
| } | |||
| p_sem_data->OSCnt = pevent->OSEventCnt; /* Get semaphore count */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif /* OS_SEM_QUERY_EN */ | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * SET SEMAPHORE | |||
| * | |||
| * Description: This function sets the semaphore count to the value specified as an argument. Typically, | |||
| * this value would be 0. | |||
| * | |||
| * You would typically use this function when a semaphore is used as a signaling mechanism | |||
| * and, you want to reset the count value. | |||
| * | |||
| * Arguments : pevent is a pointer to the event control block | |||
| * | |||
| * cnt is the new value for the semaphore count. You would pass 0 to reset the | |||
| * semaphore count. | |||
| * | |||
| * perr is a pointer to an error code returned by the function as follows: | |||
| * | |||
| * OS_ERR_NONE The call was successful and the semaphore value was set. | |||
| * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore. | |||
| * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. | |||
| * OS_ERR_TASK_WAITING If tasks are waiting on the semaphore. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_SEM_SET_EN > 0u | |||
| void OSSemSet (OS_EVENT *pevent, | |||
| INT16U cnt, | |||
| INT8U *perr) | |||
| { | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| #ifdef OS_SAFETY_CRITICAL | |||
| if (perr == (INT8U *)0) { | |||
| OS_SAFETY_CRITICAL_EXCEPTION(); | |||
| return; | |||
| } | |||
| #endif | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ | |||
| *perr = OS_ERR_PEVENT_NULL; | |||
| return; | |||
| } | |||
| #endif | |||
| if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ | |||
| *perr = OS_ERR_EVENT_TYPE; | |||
| return; | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| *perr = OS_ERR_NONE; | |||
| if (pevent->OSEventCnt > 0u) { /* See if semaphore already has a count */ | |||
| pevent->OSEventCnt = cnt; /* Yes, set it to the new value specified. */ | |||
| } else { /* No */ | |||
| if (pevent->OSEventGrp == 0u) { /* See if task(s) waiting? */ | |||
| pevent->OSEventCnt = cnt; /* No, OK to set the value */ | |||
| } else { | |||
| *perr = OS_ERR_TASK_WAITING; | |||
| } | |||
| } | |||
| OS_EXIT_CRITICAL(); | |||
| } | |||
| #endif | |||
| #endif /* OS_SEM_EN */ | |||
| @@ -0,0 +1,265 @@ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * uC/OS-II | |||
| * The Real-Time Kernel | |||
| * TIME MANAGEMENT | |||
| * | |||
| * (c) Copyright 1992-2013, Micrium, Weston, FL | |||
| * All Rights Reserved | |||
| * | |||
| * File : OS_TIME.C | |||
| * By : Jean J. Labrosse | |||
| * Version : V2.92.11 | |||
| * | |||
| * LICENSING TERMS: | |||
| * --------------- | |||
| * uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research. | |||
| * If you plan on using uC/OS-II in a commercial product you need to contact Micrium to properly license | |||
| * its use in your product. We provide ALL the source code for your convenience and to help you experience | |||
| * uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a | |||
| * licensing fee. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #define MICRIUM_SOURCE | |||
| #ifndef OS_MASTER_FILE | |||
| #include <ucos_ii.h> | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DELAY TASK 'n' TICKS | |||
| * | |||
| * Description: This function is called to delay execution of the currently running task until the | |||
| * specified number of system ticks expires. This, of course, directly equates to delaying | |||
| * the current task for some time to expire. No delay will result If the specified delay is | |||
| * 0. If the specified delay is greater than 0 then, a context switch will result. | |||
| * | |||
| * Arguments : ticks is the time delay that the task will be suspended in number of clock 'ticks'. | |||
| * Note that by specifying 0, the task will not be delayed. | |||
| * | |||
| * Returns : none | |||
| ********************************************************************************************************* | |||
| */ | |||
| void OSTimeDly (INT32U ticks) | |||
| { | |||
| INT8U y; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ | |||
| return; | |||
| } | |||
| if (OSLockNesting > 0u) { /* See if called with scheduler locked */ | |||
| return; | |||
| } | |||
| if (ticks > 0u) { /* 0 means no delay! */ | |||
| OS_ENTER_CRITICAL(); | |||
| y = OSTCBCur->OSTCBY; /* Delay current task */ | |||
| OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX; | |||
| if (OSRdyTbl[y] == 0u) { | |||
| OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY; | |||
| } | |||
| OSTCBCur->OSTCBDly = ticks; /* Load ticks in TCB */ | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* Find next task to run! */ | |||
| } | |||
| } | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * DELAY TASK FOR SPECIFIED TIME | |||
| * | |||
| * Description: This function is called to delay execution of the currently running task until some time | |||
| * expires. This call allows you to specify the delay time in HOURS, MINUTES, SECONDS and | |||
| * MILLISECONDS instead of ticks. | |||
| * | |||
| * Arguments : hours specifies the number of hours that the task will be delayed (max. is 255) | |||
| * minutes specifies the number of minutes (max. 59) | |||
| * seconds specifies the number of seconds (max. 59) | |||
| * ms specifies the number of milliseconds (max. 999) | |||
| * | |||
| * Returns : OS_ERR_NONE | |||
| * OS_ERR_TIME_INVALID_MINUTES | |||
| * OS_ERR_TIME_INVALID_SECONDS | |||
| * OS_ERR_TIME_INVALID_MS | |||
| * OS_ERR_TIME_ZERO_DLY | |||
| * OS_ERR_TIME_DLY_ISR | |||
| * | |||
| * Note(s) : The resolution on the milliseconds depends on the tick rate. For example, you can't do | |||
| * a 10 mS delay if the ticker interrupts every 100 mS. In this case, the delay would be | |||
| * set to 0. The actual delay is rounded to the nearest tick. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_TIME_DLY_HMSM_EN > 0u | |||
| INT8U OSTimeDlyHMSM (INT8U hours, | |||
| INT8U minutes, | |||
| INT8U seconds, | |||
| INT16U ms) | |||
| { | |||
| INT32U ticks; | |||
| if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ | |||
| return (OS_ERR_TIME_DLY_ISR); | |||
| } | |||
| if (OSLockNesting > 0u) { /* See if called with scheduler locked */ | |||
| return (OS_ERR_SCHED_LOCKED); | |||
| } | |||
| #if OS_ARG_CHK_EN > 0u | |||
| if (hours == 0u) { | |||
| if (minutes == 0u) { | |||
| if (seconds == 0u) { | |||
| if (ms == 0u) { | |||
| return (OS_ERR_TIME_ZERO_DLY); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| if (minutes > 59u) { | |||
| return (OS_ERR_TIME_INVALID_MINUTES); /* Validate arguments to be within range */ | |||
| } | |||
| if (seconds > 59u) { | |||
| return (OS_ERR_TIME_INVALID_SECONDS); | |||
| } | |||
| if (ms > 999u) { | |||
| return (OS_ERR_TIME_INVALID_MS); | |||
| } | |||
| #endif | |||
| /* Compute the total number of clock ticks required.. */ | |||
| /* .. (rounded to the nearest tick) */ | |||
| ticks = ((INT32U)hours * 3600uL + (INT32U)minutes * 60uL + (INT32U)seconds) * OS_TICKS_PER_SEC | |||
| + OS_TICKS_PER_SEC * ((INT32U)ms + 500uL / OS_TICKS_PER_SEC) / 1000uL; | |||
| OSTimeDly(ticks); | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * RESUME A DELAYED TASK | |||
| * | |||
| * Description: This function is used resume a task that has been delayed through a call to either | |||
| * OSTimeDly() or OSTimeDlyHMSM(). Note that you can call this function to resume a | |||
| * task that is waiting for an event with timeout. This would make the task look | |||
| * like a timeout occurred. | |||
| * | |||
| * Arguments : prio specifies the priority of the task to resume | |||
| * | |||
| * Returns : OS_ERR_NONE Task has been resumed | |||
| * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed | |||
| * (i.e. >= OS_LOWEST_PRIO) | |||
| * OS_ERR_TIME_NOT_DLY Task is not waiting for time to expire | |||
| * OS_ERR_TASK_NOT_EXIST The desired task has not been created or has been assigned to a Mutex. | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_TIME_DLY_RESUME_EN > 0u | |||
| INT8U OSTimeDlyResume (INT8U prio) | |||
| { | |||
| OS_TCB *ptcb; | |||
| #if OS_CRITICAL_METHOD == 3u /* Storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| if (prio >= OS_LOWEST_PRIO) { | |||
| return (OS_ERR_PRIO_INVALID); | |||
| } | |||
| OS_ENTER_CRITICAL(); | |||
| ptcb = OSTCBPrioTbl[prio]; /* Make sure that task exist */ | |||
| if (ptcb == (OS_TCB *)0) { | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_TASK_NOT_EXIST); /* The task does not exist */ | |||
| } | |||
| if (ptcb == OS_TCB_RESERVED) { | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_TASK_NOT_EXIST); /* The task does not exist */ | |||
| } | |||
| if (ptcb->OSTCBDly == 0u) { /* See if task is delayed */ | |||
| OS_EXIT_CRITICAL(); | |||
| return (OS_ERR_TIME_NOT_DLY); /* Indicate that task was not delayed */ | |||
| } | |||
| ptcb->OSTCBDly = 0u; /* Clear the time delay */ | |||
| if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) { | |||
| ptcb->OSTCBStat &= ~OS_STAT_PEND_ANY; /* Yes, Clear status flag */ | |||
| ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /* Indicate PEND timeout */ | |||
| } else { | |||
| ptcb->OSTCBStatPend = OS_STAT_PEND_OK; | |||
| } | |||
| if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? */ | |||
| OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready */ | |||
| OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; | |||
| OS_EXIT_CRITICAL(); | |||
| OS_Sched(); /* See if this is new highest priority */ | |||
| } else { | |||
| OS_EXIT_CRITICAL(); /* Task may be suspended */ | |||
| } | |||
| return (OS_ERR_NONE); | |||
| } | |||
| #endif | |||
| /*$PAGE*/ | |||
| /* | |||
| ********************************************************************************************************* | |||
| * GET CURRENT SYSTEM TIME | |||
| * | |||
| * Description: This function is used by your application to obtain the current value of the 32-bit | |||
| * counter which keeps track of the number of clock ticks. | |||
| * | |||
| * Arguments : none | |||
| * | |||
| * Returns : The current value of OSTime | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_TIME_GET_SET_EN > 0u | |||
| INT32U OSTimeGet (void) | |||
| { | |||
| INT32U ticks; | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| OS_ENTER_CRITICAL(); | |||
| ticks = OSTime; | |||
| OS_EXIT_CRITICAL(); | |||
| return (ticks); | |||
| } | |||
| #endif | |||
| /* | |||
| ********************************************************************************************************* | |||
| * SET SYSTEM CLOCK | |||
| * | |||
| * Description: This function sets the 32-bit counter which keeps track of the number of clock ticks. | |||
| * | |||
| * Arguments : ticks specifies the new value that OSTime needs to take. | |||
| * | |||
| * Returns : none | |||
| ********************************************************************************************************* | |||
| */ | |||
| #if OS_TIME_GET_SET_EN > 0u | |||
| void OSTimeSet (INT32U ticks) | |||
| { | |||
| #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ | |||
| OS_CPU_SR cpu_sr = 0u; | |||
| #endif | |||
| OS_ENTER_CRITICAL(); | |||
| OSTime = ticks; | |||
| OS_EXIT_CRITICAL(); | |||
| } | |||
| #endif | |||