Backup before error handling refactoring
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
*
|
||||
* (c) Copyright 2009-2010; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* ARM Cortex-M3 Port
|
||||
*
|
||||
* File : OS_CPU.H
|
||||
* Version : V3.01.2
|
||||
* By : JJL
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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.
|
||||
*
|
||||
* For : ARMv7M Cortex-M3
|
||||
* Mode : Thumb2
|
||||
* Toolchain : GNU C Compiler
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef OS_CPU_H
|
||||
#define OS_CPU_H
|
||||
|
||||
#ifdef OS_CPU_GLOBALS
|
||||
#define OS_CPU_EXT
|
||||
#else
|
||||
#define OS_CPU_EXT extern
|
||||
#endif
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* MACROS
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef NVIC_INT_CTRL
|
||||
#define NVIC_INT_CTRL *((CPU_REG32 *)0xE000ED04)
|
||||
#endif
|
||||
|
||||
#ifndef NVIC_PENDSVSET
|
||||
#define NVIC_PENDSVSET 0x10000000
|
||||
#endif
|
||||
|
||||
#define OS_TASK_SW() NVIC_INT_CTRL = NVIC_PENDSVSET
|
||||
#define OSIntCtxSw() NVIC_INT_CTRL = NVIC_PENDSVSET
|
||||
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TIMESTAMP CONFIGURATION
|
||||
*
|
||||
* Note(s) : (1) OS_TS_GET() is generally defined as CPU_TS_Get32() to allow CPU timestamp timer to be of
|
||||
* any data type size.
|
||||
*
|
||||
* (2) For architectures that provide 32-bit or higher precision free running counters
|
||||
* (i.e. cycle count registers):
|
||||
*
|
||||
* (a) OS_TS_GET() may be defined as CPU_TS_TmrRd() to improve performance when retrieving
|
||||
* the timestamp.
|
||||
*
|
||||
* (b) CPU_TS_TmrRd() MUST be configured to be greater or equal to 32-bits to avoid
|
||||
* truncation of TS.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#if OS_CFG_TS_EN == 1u
|
||||
#define OS_TS_GET() (CPU_TS)CPU_TS_TmrRd() /* See Note #2a. */
|
||||
#else
|
||||
#define OS_TS_GET() (CPU_TS)0u
|
||||
#endif
|
||||
|
||||
#if (CPU_CFG_TS_32_EN == DEF_ENABLED) && \
|
||||
(CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)
|
||||
/* CPU_CFG_TS_TMR_SIZE MUST be >= 32-bit (see Note #2b). */
|
||||
#error "cpu_cfg.h, CPU_CFG_TS_TMR_SIZE MUST be >= CPU_WORD_SIZE_32"
|
||||
#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
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* GLOBAL VARIABLES
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
OS_CPU_EXT CPU_STK *OS_CPU_ExceptStkBase;
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* FUNCTION PROTOTYPES
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSStartHighRdy (void);
|
||||
|
||||
void OS_CPU_PendSVHandler (void);
|
||||
|
||||
|
||||
void OS_CPU_SysTickHandler(void);
|
||||
void OS_CPU_SysTickInit (CPU_INT32U cnts);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,158 @@
|
||||
@
|
||||
@********************************************************************************************************
|
||||
@ uC/OS-III
|
||||
@ The Real-Time Kernel
|
||||
@
|
||||
@
|
||||
@ (c) Copyright 2009-2011; Micrium Inc.; Weston, FL
|
||||
@ All rights reserved. Protected by international copyright laws.
|
||||
@
|
||||
@ ARM Cortex-M3 Port
|
||||
@
|
||||
@ File : OS_CPU_A.ASM
|
||||
@ Version : V3.01.2
|
||||
@ By : JJL
|
||||
@ FT
|
||||
@
|
||||
@ For : ARMv7M Cortex-M3
|
||||
@ Mode : Thumb2
|
||||
@ Toolchain : GNU C Compiler
|
||||
@********************************************************************************************************
|
||||
@
|
||||
|
||||
@********************************************************************************************************
|
||||
@ PUBLIC FUNCTIONS
|
||||
@********************************************************************************************************
|
||||
|
||||
.extern OSRunning @ External references.
|
||||
.extern OSPrioCur
|
||||
.extern OSPrioHighRdy
|
||||
.extern OSTCBCurPtr
|
||||
.extern OSTCBHighRdyPtr
|
||||
.extern OSIntExit
|
||||
.extern OSTaskSwHook
|
||||
.extern OS_CPU_ExceptStkBase
|
||||
|
||||
|
||||
.global OSStartHighRdy @ Functions declared in this file.
|
||||
.global OS_CPU_PendSVHandler
|
||||
|
||||
@********************************************************************************************************
|
||||
@ EQUATES
|
||||
@********************************************************************************************************
|
||||
|
||||
.equ NVIC_INT_CTRL, 0xE000ED04 @ Interrupt control state register.
|
||||
.equ NVIC_SYSPRI14, 0xE000ED22 @ System priority register (priority 14).
|
||||
.equ NVIC_PENDSV_PRI, 0xFF @ PendSV priority value (lowest).
|
||||
.equ NVIC_PENDSVSET, 0x10000000 @ Value to trigger PendSV exception.
|
||||
|
||||
|
||||
@********************************************************************************************************
|
||||
@ CODE GENERATION DIRECTIVES
|
||||
@********************************************************************************************************
|
||||
|
||||
.section .text, "ax"
|
||||
.align 2
|
||||
.thumb
|
||||
.syntax unified
|
||||
|
||||
.global OSStartHighRdy
|
||||
.type OSStartHighRdy, %function
|
||||
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, =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
|
||||
|
||||
|
||||
@********************************************************************************************************
|
||||
@ 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, OSTCBCurPtr->OSTCBStkPtr = SP;
|
||||
@ d) Call OSTaskSwHook();
|
||||
@ e) Get current high priority, OSPrioCur = OSPrioHighRdy;
|
||||
@ f) Get current ready thread TCB, OSTCBCurPtr = OSTCBHighRdyPtr;
|
||||
@ g) Get new process SP from TCB, SP = OSTCBHighRdyPtr->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) OSTCBCurPtr points to the OS_TCB of the task to suspend
|
||||
@ OSTCBHighRdyPtr 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).
|
||||
@********************************************************************************************************
|
||||
|
||||
.global OS_CPU_PendSVHandler
|
||||
.type OS_CPU_PendSVHandler, %function
|
||||
.thumb_func
|
||||
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, =OSTCBCurPtr @ OSTCBCurPtr->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, =OSTCBCurPtr @ OSTCBCurPtr = OSTCBHighRdyPtr;
|
||||
LDR R1, =OSTCBHighRdyPtr
|
||||
LDR R2, [R1]
|
||||
STR R2, [R0]
|
||||
|
||||
LDR R0, [R2] @ R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
|
||||
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, #0x04 @ Ensure exception return uses process stack
|
||||
CPSIE I
|
||||
BX LR @ Exception return will restore remaining context
|
||||
|
||||
.end
|
||||
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
*
|
||||
* (c) Copyright 2009-2010; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* ARM Cortex-M3 Port
|
||||
*
|
||||
* File : OS_CPU_C.C
|
||||
* Version : V3.01.2
|
||||
* By : JJL
|
||||
* FT
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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.
|
||||
*
|
||||
* For : ARMv7M Cortex-M3
|
||||
* Mode : Thumb2
|
||||
* Toolchain : GNU C Compiler
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#define OS_CPU_GLOBALS
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_cpu_c__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* INCLUDE FILES
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include <os.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static CPU_INT32U sw_debug_count = 0;
|
||||
static CPU_INT32U tick_debug_count = 0;
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSIdleTaskHook (void)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppIdleTaskHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppIdleTaskHookPtr)();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* OS INITIALIZATION HOOK
|
||||
*
|
||||
* Description: This function is called by OSInit() at the beginning of OSInit().
|
||||
*
|
||||
* Arguments : None.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSInitHook (void)
|
||||
{
|
||||
CPU_STK_SIZE i;
|
||||
CPU_STK *p_stk;
|
||||
|
||||
|
||||
p_stk = OSCfg_ISRStkBasePtr; /* Clear the ISR stack */
|
||||
for (i = 0u; i < OSCfg_ISRStkSize; i++) {
|
||||
*p_stk++ = (CPU_STK)0u;
|
||||
}
|
||||
OS_CPU_ExceptStkBase = (CPU_STK *)(OSCfg_ISRStkBasePtr + OSCfg_ISRStkSize - 1u);
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* STATISTIC TASK HOOK
|
||||
*
|
||||
* Description: This function is called every second by uC/OS-III's statistics task. This allows your
|
||||
* application to add functionality to the statistics task.
|
||||
*
|
||||
* Arguments : None.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSStatTaskHook (void)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppStatTaskHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppStatTaskHookPtr)();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TASK CREATION HOOK
|
||||
*
|
||||
* Description: This function is called when a task is created.
|
||||
*
|
||||
* Arguments : p_tcb Pointer to the task control block of the task being created.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskCreateHook (OS_TCB *p_tcb)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskCreateHookPtr != (OS_APP_HOOK_TCB)0) {
|
||||
(*OS_AppTaskCreateHookPtr)(p_tcb);
|
||||
}
|
||||
#else
|
||||
(void)p_tcb; /* Prevent compiler warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TASK DELETION HOOK
|
||||
*
|
||||
* Description: This function is called when a task is deleted.
|
||||
*
|
||||
* Arguments : p_tcb Pointer to the task control block of the task being deleted.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskDelHook (OS_TCB *p_tcb)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskDelHookPtr != (OS_APP_HOOK_TCB)0) {
|
||||
(*OS_AppTaskDelHookPtr)(p_tcb);
|
||||
}
|
||||
#else
|
||||
(void)p_tcb; /* Prevent compiler warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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 : p_tcb Pointer to the task control block of the task that is returning.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskReturnHook (OS_TCB *p_tcb)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskReturnHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppTaskReturnHookPtr)(p_tcb);
|
||||
}
|
||||
#else
|
||||
(void)p_tcb; /* Prevent compiler warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
**********************************************************************************************************
|
||||
* INITIALIZE A TASK'S STACK
|
||||
*
|
||||
* Description: This function is called by OS_Task_Create() or OSTaskCreateExt() to initialize the stack
|
||||
* frame of the task being created. This function is highly processor specific.
|
||||
*
|
||||
* Arguments : p_task Pointer to the task entry point address.
|
||||
*
|
||||
* p_arg Pointer to a user supplied data area that will be passed to the task
|
||||
* when the task first executes.
|
||||
*
|
||||
* p_stk_base Pointer to the base address of the stack.
|
||||
*
|
||||
* stk_size Size of the stack, in number of CPU_STK elements.
|
||||
*
|
||||
* opt Options used to alter the behavior of OS_Task_StkInit().
|
||||
* (see OS.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.
|
||||
**********************************************************************************************************
|
||||
*/
|
||||
|
||||
CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task,
|
||||
void *p_arg,
|
||||
CPU_STK *p_stk_base,
|
||||
CPU_STK *p_stk_limit,
|
||||
CPU_STK_SIZE stk_size,
|
||||
OS_OPT opt)
|
||||
{
|
||||
CPU_STK *p_stk;
|
||||
|
||||
|
||||
(void)opt; /* Prevent compiler warning */
|
||||
|
||||
p_stk = &p_stk_base[stk_size]; /* Load stack pointer */
|
||||
/* Registers stacked as if auto-saved on exception */
|
||||
*--p_stk = (CPU_STK)0x01000000u; /* xPSR */
|
||||
*--p_stk = (CPU_STK)p_task; /* Entry Point */
|
||||
*--p_stk = (CPU_STK)OS_TaskReturn; /* R14 (LR) */
|
||||
*--p_stk = (CPU_STK)0x12121212u; /* R12 */
|
||||
*--p_stk = (CPU_STK)0x03030303u; /* R3 */
|
||||
*--p_stk = (CPU_STK)0x02020202u; /* R2 */
|
||||
*--p_stk = (CPU_STK)p_stk_limit; /* R1 */
|
||||
*--p_stk = (CPU_STK)p_arg; /* R0 : argument */
|
||||
/* Remaining registers saved on process stack */
|
||||
*--p_stk = (CPU_STK)0x11111111u; /* R11 */
|
||||
*--p_stk = (CPU_STK)0x10101010u; /* R10 */
|
||||
*--p_stk = (CPU_STK)0x09090909u; /* R9 */
|
||||
*--p_stk = (CPU_STK)0x08080808u; /* R8 */
|
||||
*--p_stk = (CPU_STK)0x07070707u; /* R7 */
|
||||
*--p_stk = (CPU_STK)0x06060606u; /* R6 */
|
||||
*--p_stk = (CPU_STK)0x05050505u; /* R5 */
|
||||
*--p_stk = (CPU_STK)0x04040404u; /* R4 */
|
||||
|
||||
return (p_stk);
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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 'OSTCBHighRdyPtr' points to the TCB of the task
|
||||
* that will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCurPtr' points
|
||||
* to the task being switched out (i.e. the preempted task).
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskSwHook (void)
|
||||
{
|
||||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||||
CPU_TS ts;
|
||||
#endif
|
||||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||||
CPU_TS int_dis_time;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskSwHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppTaskSwHookPtr)();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||||
ts = OS_TS_GET();
|
||||
if (OSTCBCurPtr != OSTCBHighRdyPtr) {
|
||||
OSTCBCurPtr->CyclesDelta = ts - OSTCBCurPtr->CyclesStart;
|
||||
OSTCBCurPtr->CyclesTotal += (OS_CYCLES)OSTCBCurPtr->CyclesDelta;
|
||||
}
|
||||
|
||||
OSTCBHighRdyPtr->CyclesStart = ts;
|
||||
#endif
|
||||
|
||||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||||
int_dis_time = CPU_IntDisMeasMaxCurReset(); /* Keep track of per-task interrupt disable time */
|
||||
if (OSTCBCurPtr->IntDisTimeMax < int_dis_time) {
|
||||
OSTCBCurPtr->IntDisTimeMax = int_dis_time;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
|
||||
/* Keep track of per-task scheduler lock time */
|
||||
if (OSTCBCurPtr->SchedLockTimeMax < OSSchedLockTimeMaxCur) {
|
||||
OSTCBCurPtr->SchedLockTimeMax = OSSchedLockTimeMaxCur;
|
||||
}
|
||||
OSSchedLockTimeMaxCur = (CPU_TS)0; /* Reset the per-task value */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TICK HOOK
|
||||
*
|
||||
* Description: This function is called every tick.
|
||||
*
|
||||
* Arguments : None.
|
||||
*
|
||||
* Note(s) : 1) This function is assumed to be called from the Tick ISR.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTimeTickHook (void)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTimeTickHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppTimeTickHookPtr)();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
OSIntNestingCtr++; /* Tell uC/OS-III that we are starting an ISR */
|
||||
CPU_CRITICAL_EXIT();
|
||||
|
||||
OSTimeTick(); /* Call uC/OS-III's OSTimeTick() */
|
||||
|
||||
OSIntExit(); /* Tell uC/OS-III that we are leaving the ISR */
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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 (CPU_INT32U cnts)
|
||||
{
|
||||
CPU_INT32U prio;
|
||||
|
||||
|
||||
CPU_REG_NVIC_ST_RELOAD = cnts - 1u;
|
||||
|
||||
/* Set SysTick handler prio. */
|
||||
prio = CPU_REG_NVIC_SHPRI3;
|
||||
prio &= DEF_BIT_FIELD(24, 0);
|
||||
prio |= DEF_BIT_MASK(OS_CPU_CFG_SYSTICK_PRIO, 24);
|
||||
|
||||
CPU_REG_NVIC_SHPRI3 = prio;
|
||||
|
||||
/* Enable timer. */
|
||||
CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_CLKSOURCE |
|
||||
CPU_REG_NVIC_ST_CTRL_ENABLE;
|
||||
/* Enable timer interrupt. */
|
||||
CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_TICKINT;
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
*
|
||||
* (c) Copyright 2009-2010; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* ARM Cortex-M3 Port
|
||||
*
|
||||
* File : OS_CPU.H
|
||||
* Version : V3.01.2
|
||||
* By : JJL
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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.
|
||||
*
|
||||
* For : ARMv7M Cortex-M3
|
||||
* Mode : Thumb2
|
||||
* 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
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* MACROS
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef NVIC_INT_CTRL
|
||||
#define NVIC_INT_CTRL *((CPU_REG32 *)0xE000ED04)
|
||||
#endif
|
||||
|
||||
#ifndef NVIC_PENDSVSET
|
||||
#define NVIC_PENDSVSET 0x10000000
|
||||
#endif
|
||||
|
||||
#define OS_TASK_SW() NVIC_INT_CTRL = NVIC_PENDSVSET
|
||||
#define OSIntCtxSw() NVIC_INT_CTRL = NVIC_PENDSVSET
|
||||
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TIMESTAMP CONFIGURATION
|
||||
*
|
||||
* Note(s) : (1) OS_TS_GET() is generally defined as CPU_TS_Get32() to allow CPU timestamp timer to be of
|
||||
* any data type size.
|
||||
*
|
||||
* (2) For architectures that provide 32-bit or higher precision free running counters
|
||||
* (i.e. cycle count registers):
|
||||
*
|
||||
* (a) OS_TS_GET() may be defined as CPU_TS_TmrRd() to improve performance when retrieving
|
||||
* the timestamp.
|
||||
*
|
||||
* (b) CPU_TS_TmrRd() MUST be configured to be greater or equal to 32-bits to avoid
|
||||
* truncation of TS.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#if OS_CFG_TS_EN == 1u
|
||||
#define OS_TS_GET() (CPU_TS)CPU_TS_TmrRd() /* See Note #2a. */
|
||||
#else
|
||||
#define OS_TS_GET() (CPU_TS)0u
|
||||
#endif
|
||||
|
||||
#if (CPU_CFG_TS_32_EN == DEF_ENABLED) && \
|
||||
(CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)
|
||||
/* CPU_CFG_TS_TMR_SIZE MUST be >= 32-bit (see Note #2b). */
|
||||
#error "cpu_cfg.h, CPU_CFG_TS_TMR_SIZE MUST be >= CPU_WORD_SIZE_32"
|
||||
#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
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* GLOBAL VARIABLES
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
OS_CPU_EXT CPU_STK *OS_CPU_ExceptStkBase;
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* FUNCTION PROTOTYPES
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSStartHighRdy (void);
|
||||
|
||||
void OS_CPU_PendSVHandler (void);
|
||||
|
||||
|
||||
void OS_CPU_SysTickHandler(void);
|
||||
void OS_CPU_SysTickInit (CPU_INT32U cnts);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,170 @@
|
||||
;
|
||||
;********************************************************************************************************
|
||||
; uC/OS-III
|
||||
; The Real-Time Kernel
|
||||
;
|
||||
;
|
||||
; (c) Copyright 2009-2010; Micrium, Inc.; Weston, FL
|
||||
; All rights reserved. Protected by international copyright laws.
|
||||
;
|
||||
; ARM Cortex-M3 Port
|
||||
;
|
||||
; File : OS_CPU_A.ASM
|
||||
; Version : V3.01.2
|
||||
; By : JJL
|
||||
; BAN
|
||||
;
|
||||
; For : ARMv7M Cortex-M3
|
||||
; Mode : Thumb2
|
||||
; Toolchain : IAR EWARM
|
||||
;********************************************************************************************************
|
||||
;
|
||||
|
||||
;********************************************************************************************************
|
||||
; PUBLIC FUNCTIONS
|
||||
;********************************************************************************************************
|
||||
|
||||
EXTERN OSRunning ; External references
|
||||
EXTERN OSPrioCur
|
||||
EXTERN OSPrioHighRdy
|
||||
EXTERN OSTCBCurPtr
|
||||
EXTERN OSTCBHighRdyPtr
|
||||
EXTERN OSIntExit
|
||||
EXTERN OSTaskSwHook
|
||||
EXTERN OS_CPU_ExceptStkBase
|
||||
|
||||
|
||||
PUBLIC OSStartHighRdy ; Functions declared in this file
|
||||
PUBLIC OS_CPU_PendSVHandler
|
||||
|
||||
;PAGE
|
||||
;********************************************************************************************************
|
||||
; 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
|
||||
|
||||
|
||||
;PAGE
|
||||
;********************************************************************************************************
|
||||
; 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) Trigger PendSV exception;
|
||||
; e) 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, =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
|
||||
|
||||
|
||||
;PAGE
|
||||
;********************************************************************************************************
|
||||
; 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, OSTCBCurPtr->OSTCBStkPtr = SP;
|
||||
; d) Call OSTaskSwHook();
|
||||
; e) Get current high priority, OSPrioCur = OSPrioHighRdy;
|
||||
; f) Get current ready thread TCB, OSTCBCurPtr = OSTCBHighRdyPtr;
|
||||
; g) Get new process SP from TCB, SP = OSTCBHighRdyPtr->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) OSTCBCurPtr points to the OS_TCB of the task to suspend
|
||||
; OSTCBHighRdyPtr 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, =OSTCBCurPtr ; OSTCBCurPtr->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, =OSTCBCurPtr ; OSTCBCurPtr = OSTCBHighRdyPtr;
|
||||
LDR R1, =OSTCBHighRdyPtr
|
||||
LDR R2, [R1]
|
||||
STR R2, [R0]
|
||||
|
||||
LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
|
||||
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, #0x04 ; Ensure exception return uses process stack
|
||||
CPSIE I
|
||||
BX LR ; Exception return will restore remaining context
|
||||
|
||||
END
|
||||
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
*
|
||||
* (c) Copyright 2009-2010; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* ARM Cortex-M3 Port
|
||||
*
|
||||
* File : OS_CPU_C.C
|
||||
* Version : V3.02.01
|
||||
* By : JJL
|
||||
* BAN
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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 : ARMv7M Cortex-M3
|
||||
* Mode : Thumb2
|
||||
* Toolchain : IAR EWARM
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#define OS_CPU_GLOBALS
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_cpu_c__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* INCLUDE FILES
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include <os.h>
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSIdleTaskHook (void)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppIdleTaskHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppIdleTaskHookPtr)();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* OS INITIALIZATION HOOK
|
||||
*
|
||||
* Description: This function is called by OSInit() at the beginning of OSInit().
|
||||
*
|
||||
* Arguments : None.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSInitHook (void)
|
||||
{
|
||||
OS_CPU_ExceptStkBase = (CPU_STK *)(OSCfg_ISRStkBasePtr + OSCfg_ISRStkSize - 1u);
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* STATISTIC TASK HOOK
|
||||
*
|
||||
* Description: This function is called every second by uC/OS-III's statistics task. This allows your
|
||||
* application to add functionality to the statistics task.
|
||||
*
|
||||
* Arguments : None.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSStatTaskHook (void)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppStatTaskHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppStatTaskHookPtr)();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TASK CREATION HOOK
|
||||
*
|
||||
* Description: This function is called when a task is created.
|
||||
*
|
||||
* Arguments : p_tcb Pointer to the task control block of the task being created.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskCreateHook (OS_TCB *p_tcb)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskCreateHookPtr != (OS_APP_HOOK_TCB)0) {
|
||||
(*OS_AppTaskCreateHookPtr)(p_tcb);
|
||||
}
|
||||
#else
|
||||
(void)p_tcb; /* Prevent compiler warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TASK DELETION HOOK
|
||||
*
|
||||
* Description: This function is called when a task is deleted.
|
||||
*
|
||||
* Arguments : p_tcb Pointer to the task control block of the task being deleted.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskDelHook (OS_TCB *p_tcb)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskDelHookPtr != (OS_APP_HOOK_TCB)0) {
|
||||
(*OS_AppTaskDelHookPtr)(p_tcb);
|
||||
}
|
||||
#else
|
||||
(void)p_tcb; /* Prevent compiler warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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 : p_tcb Pointer to the task control block of the task that is returning.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskReturnHook (OS_TCB *p_tcb)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskReturnHookPtr != (OS_APP_HOOK_TCB)0) {
|
||||
(*OS_AppTaskReturnHookPtr)(p_tcb);
|
||||
}
|
||||
#else
|
||||
(void)p_tcb; /* Prevent compiler warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
**********************************************************************************************************
|
||||
* INITIALIZE A TASK'S STACK
|
||||
*
|
||||
* Description: This function is called by OS_Task_Create() or OSTaskCreateExt() to initialize the stack
|
||||
* frame of the task being created. This function is highly processor specific.
|
||||
*
|
||||
* Arguments : p_task Pointer to the task entry point address.
|
||||
*
|
||||
* p_arg Pointer to a user supplied data area that will be passed to the task
|
||||
* when the task first executes.
|
||||
*
|
||||
* p_stk_base Pointer to the base address of the stack.
|
||||
*
|
||||
* stk_size Size of the stack, in number of CPU_STK elements.
|
||||
*
|
||||
* opt Options used to alter the behavior of OS_Task_StkInit().
|
||||
* (see OS.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.
|
||||
**********************************************************************************************************
|
||||
*/
|
||||
|
||||
CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task,
|
||||
void *p_arg,
|
||||
CPU_STK *p_stk_base,
|
||||
CPU_STK *p_stk_limit,
|
||||
CPU_STK_SIZE stk_size,
|
||||
OS_OPT opt)
|
||||
{
|
||||
CPU_STK *p_stk;
|
||||
|
||||
|
||||
(void)opt; /* Prevent compiler warning */
|
||||
|
||||
p_stk = &p_stk_base[stk_size]; /* Load stack pointer */
|
||||
/* Registers stacked as if auto-saved on exception */
|
||||
*--p_stk = (CPU_STK)0x01000000u; /* xPSR */
|
||||
*--p_stk = (CPU_STK)p_task; /* Entry Point */
|
||||
*--p_stk = (CPU_STK)OS_TaskReturn; /* R14 (LR) */
|
||||
*--p_stk = (CPU_STK)0x12121212u; /* R12 */
|
||||
*--p_stk = (CPU_STK)0x03030303u; /* R3 */
|
||||
*--p_stk = (CPU_STK)0x02020202u; /* R2 */
|
||||
*--p_stk = (CPU_STK)p_stk_limit; /* R1 */
|
||||
*--p_stk = (CPU_STK)p_arg; /* R0 : argument */
|
||||
/* Remaining registers saved on process stack */
|
||||
*--p_stk = (CPU_STK)0x11111111u; /* R11 */
|
||||
*--p_stk = (CPU_STK)0x10101010u; /* R10 */
|
||||
*--p_stk = (CPU_STK)0x09090909u; /* R9 */
|
||||
*--p_stk = (CPU_STK)0x08080808u; /* R8 */
|
||||
*--p_stk = (CPU_STK)0x07070707u; /* R7 */
|
||||
*--p_stk = (CPU_STK)0x06060606u; /* R6 */
|
||||
*--p_stk = (CPU_STK)0x05050505u; /* R5 */
|
||||
*--p_stk = (CPU_STK)0x04040404u; /* R4 */
|
||||
|
||||
return (p_stk);
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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 'OSTCBHighRdyPtr' points to the TCB of the task
|
||||
* that will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCurPtr' points
|
||||
* to the task being switched out (i.e. the preempted task).
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskSwHook (void)
|
||||
{
|
||||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||||
CPU_TS ts;
|
||||
#endif
|
||||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||||
CPU_TS int_dis_time;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskSwHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppTaskSwHookPtr)();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||||
ts = OS_TS_GET();
|
||||
if (OSTCBCurPtr != OSTCBHighRdyPtr) {
|
||||
OSTCBCurPtr->CyclesDelta = ts - OSTCBCurPtr->CyclesStart;
|
||||
OSTCBCurPtr->CyclesTotal += (OS_CYCLES)OSTCBCurPtr->CyclesDelta;
|
||||
}
|
||||
|
||||
OSTCBHighRdyPtr->CyclesStart = ts;
|
||||
#endif
|
||||
|
||||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||||
int_dis_time = CPU_IntDisMeasMaxCurReset(); /* Keep track of per-task interrupt disable time */
|
||||
if (OSTCBCurPtr->IntDisTimeMax < int_dis_time) {
|
||||
OSTCBCurPtr->IntDisTimeMax = int_dis_time;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
|
||||
/* Keep track of per-task scheduler lock time */
|
||||
if (OSTCBCurPtr->SchedLockTimeMax < OSSchedLockTimeMaxCur) {
|
||||
OSTCBCurPtr->SchedLockTimeMax = OSSchedLockTimeMaxCur;
|
||||
}
|
||||
OSSchedLockTimeMaxCur = (CPU_TS)0; /* Reset the per-task value */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TICK HOOK
|
||||
*
|
||||
* Description: This function is called every tick.
|
||||
*
|
||||
* Arguments : None.
|
||||
*
|
||||
* Note(s) : 1) This function is assumed to be called from the Tick ISR.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTimeTickHook (void)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTimeTickHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppTimeTickHookPtr)();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
OSIntNestingCtr++; /* Tell uC/OS-III that we are starting an ISR */
|
||||
CPU_CRITICAL_EXIT();
|
||||
|
||||
OSTimeTick(); /* Call uC/OS-III's OSTimeTick() */
|
||||
|
||||
OSIntExit(); /* Tell uC/OS-III that we are leaving the ISR */
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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 (CPU_INT32U cnts)
|
||||
{
|
||||
CPU_INT32U prio;
|
||||
|
||||
|
||||
CPU_REG_NVIC_ST_RELOAD = cnts - 1u;
|
||||
|
||||
/* Set SysTick handler prio. */
|
||||
prio = CPU_REG_NVIC_SHPRI3;
|
||||
prio &= DEF_BIT_FIELD(24, 0);
|
||||
prio |= DEF_BIT_MASK(OS_CPU_CFG_SYSTICK_PRIO, 24);
|
||||
|
||||
CPU_REG_NVIC_SHPRI3 = prio;
|
||||
|
||||
/* Enable timer. */
|
||||
CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_CLKSOURCE |
|
||||
CPU_REG_NVIC_ST_CTRL_ENABLE;
|
||||
/* Enable timer interrupt. */
|
||||
CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_TICKINT;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
*
|
||||
* (c) Copyright 2009-2010; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* ARM Cortex-M3 Port
|
||||
*
|
||||
* File : OS_CPU.H
|
||||
* Version : V3.01.2
|
||||
* By : JJL
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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.
|
||||
*
|
||||
* For : ARMv7M Cortex-M3
|
||||
* Mode : Thumb2
|
||||
* Toolchain : RealView
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef OS_CPU_H
|
||||
#define OS_CPU_H
|
||||
|
||||
#ifdef OS_CPU_GLOBALS
|
||||
#define OS_CPU_EXT
|
||||
#else
|
||||
#define OS_CPU_EXT extern
|
||||
#endif
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* MACROS
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef NVIC_INT_CTRL
|
||||
#define NVIC_INT_CTRL *((CPU_REG32 *)0xE000ED04)
|
||||
#endif
|
||||
|
||||
#ifndef NVIC_PENDSVSET
|
||||
#define NVIC_PENDSVSET 0x10000000
|
||||
#endif
|
||||
|
||||
#define OS_TASK_SW() NVIC_INT_CTRL = NVIC_PENDSVSET
|
||||
#define OSIntCtxSw() NVIC_INT_CTRL = NVIC_PENDSVSET
|
||||
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TIMESTAMP CONFIGURATION
|
||||
*
|
||||
* Note(s) : (1) OS_TS_GET() is generally defined as CPU_TS_Get32() to allow CPU timestamp timer to be of
|
||||
* any data type size.
|
||||
*
|
||||
* (2) For architectures that provide 32-bit or higher precision free running counters
|
||||
* (i.e. cycle count registers):
|
||||
*
|
||||
* (a) OS_TS_GET() may be defined as CPU_TS_TmrRd() to improve performance when retrieving
|
||||
* the timestamp.
|
||||
*
|
||||
* (b) CPU_TS_TmrRd() MUST be configured to be greater or equal to 32-bits to avoid
|
||||
* truncation of TS.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#if OS_CFG_TS_EN == 1u
|
||||
#define OS_TS_GET() (CPU_TS)CPU_TS_TmrRd() /* See Note #2a. */
|
||||
#else
|
||||
#define OS_TS_GET() (CPU_TS)0u
|
||||
#endif
|
||||
|
||||
#if (CPU_CFG_TS_32_EN == DEF_ENABLED) && \
|
||||
(CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)
|
||||
/* CPU_CFG_TS_TMR_SIZE MUST be >= 32-bit (see Note #2b). */
|
||||
#error "cpu_cfg.h, CPU_CFG_TS_TMR_SIZE MUST be >= CPU_WORD_SIZE_32"
|
||||
#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
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* GLOBAL VARIABLES
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
OS_CPU_EXT CPU_STK *OS_CPU_ExceptStkBase;
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* FUNCTION PROTOTYPES
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSStartHighRdy (void);
|
||||
|
||||
void OS_CPU_PendSVHandler (void);
|
||||
|
||||
|
||||
void OS_CPU_SysTickHandler(void);
|
||||
void OS_CPU_SysTickInit (CPU_INT32U cnts);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,175 @@
|
||||
;
|
||||
;********************************************************************************************************
|
||||
; uC/OS-III
|
||||
; The Real-Time Kernel
|
||||
;
|
||||
;
|
||||
; (c) Copyright 2009-2010; Micrium, Inc.; Weston, FL
|
||||
; All rights reserved. Protected by international copyright laws.
|
||||
;
|
||||
; ARM Cortex-M3 Port
|
||||
;
|
||||
; File : OS_CPU_A.ASM
|
||||
; Version : V3.01.2
|
||||
; By : JJL
|
||||
; BAN
|
||||
;
|
||||
; For : ARMv7M Cortex-M3
|
||||
; Mode : Thumb2
|
||||
; Toolchain : RealView Development Suite
|
||||
; RealView Microcontroller Development Kit (MDK)
|
||||
; ARM Developer Suite (ADS)
|
||||
; Keil uVision
|
||||
;********************************************************************************************************
|
||||
;
|
||||
|
||||
;********************************************************************************************************
|
||||
; PUBLIC FUNCTIONS
|
||||
;********************************************************************************************************
|
||||
|
||||
IMPORT OSRunning ; External references
|
||||
IMPORT OSPrioCur
|
||||
IMPORT OSPrioHighRdy
|
||||
IMPORT OSTCBCurPtr
|
||||
IMPORT OSTCBHighRdyPtr
|
||||
IMPORT OSIntExit
|
||||
IMPORT OSTaskSwHook
|
||||
IMPORT OS_CPU_ExceptStkBase
|
||||
|
||||
|
||||
EXPORT OSStartHighRdy ; Functions declared in this file
|
||||
EXPORT OS_CPU_PendSVHandler
|
||||
|
||||
;PAGE
|
||||
;********************************************************************************************************
|
||||
; 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
|
||||
;********************************************************************************************************
|
||||
|
||||
PRESERVE8
|
||||
THUMB
|
||||
|
||||
AREA CODE, CODE, READONLY
|
||||
|
||||
|
||||
;PAGE
|
||||
;********************************************************************************************************
|
||||
; 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) Trigger PendSV exception;
|
||||
; e) 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, =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
|
||||
|
||||
|
||||
;PAGE
|
||||
;********************************************************************************************************
|
||||
; 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, OSTCBCurPtr->OSTCBStkPtr = SP;
|
||||
; d) Call OSTaskSwHook();
|
||||
; e) Get current high priority, OSPrioCur = OSPrioHighRdy;
|
||||
; f) Get current ready thread TCB, OSTCBCurPtr = OSTCBHighRdyPtr;
|
||||
; g) Get new process SP from TCB, SP = OSTCBHighRdyPtr->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) OSTCBCurPtr points to the OS_TCB of the task to suspend
|
||||
; OSTCBHighRdyPtr 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, =OSTCBCurPtr ; OSTCBCurPtr->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, =OSTCBCurPtr ; OSTCBCurPtr = OSTCBHighRdyPtr;
|
||||
LDR R1, =OSTCBHighRdyPtr
|
||||
LDR R2, [R1]
|
||||
STR R2, [R0]
|
||||
|
||||
LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
|
||||
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, #0x04 ; Ensure exception return uses process stack
|
||||
CPSIE I
|
||||
BX LR ; Exception return will restore remaining context
|
||||
|
||||
END
|
||||
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
*
|
||||
* (c) Copyright 2009-2010; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* ARM Cortex-M3 Port
|
||||
*
|
||||
* File : OS_CPU_C.C
|
||||
* Version : V3.01.2
|
||||
* By : JJL
|
||||
* BAN
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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.
|
||||
*
|
||||
* For : ARMv7M Cortex-M3
|
||||
* Mode : Thumb2
|
||||
* Toolchain : RealView
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#define OS_CPU_GLOBALS
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_cpu_c__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* INCLUDE FILES
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include <os.h>
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSIdleTaskHook (void)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppIdleTaskHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppIdleTaskHookPtr)();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* OS INITIALIZATION HOOK
|
||||
*
|
||||
* Description: This function is called by OSInit() at the beginning of OSInit().
|
||||
*
|
||||
* Arguments : None.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSInitHook (void)
|
||||
{
|
||||
CPU_STK_SIZE i;
|
||||
CPU_STK *p_stk;
|
||||
|
||||
|
||||
p_stk = OSCfg_ISRStkBasePtr; /* Clear the ISR stack */
|
||||
for (i = 0u; i < OSCfg_ISRStkSize; i++) {
|
||||
*p_stk++ = (CPU_STK)0u;
|
||||
}
|
||||
OS_CPU_ExceptStkBase = (CPU_STK *)(OSCfg_ISRStkBasePtr + OSCfg_ISRStkSize - 1u);
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* STATISTIC TASK HOOK
|
||||
*
|
||||
* Description: This function is called every second by uC/OS-III's statistics task. This allows your
|
||||
* application to add functionality to the statistics task.
|
||||
*
|
||||
* Arguments : None.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSStatTaskHook (void)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppStatTaskHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppStatTaskHookPtr)();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TASK CREATION HOOK
|
||||
*
|
||||
* Description: This function is called when a task is created.
|
||||
*
|
||||
* Arguments : p_tcb Pointer to the task control block of the task being created.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskCreateHook (OS_TCB *p_tcb)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskCreateHookPtr != (OS_APP_HOOK_TCB)0) {
|
||||
(*OS_AppTaskCreateHookPtr)(p_tcb);
|
||||
}
|
||||
#else
|
||||
(void)p_tcb; /* Prevent compiler warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TASK DELETION HOOK
|
||||
*
|
||||
* Description: This function is called when a task is deleted.
|
||||
*
|
||||
* Arguments : p_tcb Pointer to the task control block of the task being deleted.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskDelHook (OS_TCB *p_tcb)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskDelHookPtr != (OS_APP_HOOK_TCB)0) {
|
||||
(*OS_AppTaskDelHookPtr)(p_tcb);
|
||||
}
|
||||
#else
|
||||
(void)p_tcb; /* Prevent compiler warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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 : p_tcb Pointer to the task control block of the task that is returning.
|
||||
*
|
||||
* Note(s) : None.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskReturnHook (OS_TCB *p_tcb)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskReturnHookPtr != (OS_APP_HOOK_TCB)0) {
|
||||
(*OS_AppTaskReturnHookPtr)(p_tcb);
|
||||
}
|
||||
#else
|
||||
(void)p_tcb; /* Prevent compiler warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
**********************************************************************************************************
|
||||
* INITIALIZE A TASK'S STACK
|
||||
*
|
||||
* Description: This function is called by OS_Task_Create() or OSTaskCreateExt() to initialize the stack
|
||||
* frame of the task being created. This function is highly processor specific.
|
||||
*
|
||||
* Arguments : p_task Pointer to the task entry point address.
|
||||
*
|
||||
* p_arg Pointer to a user supplied data area that will be passed to the task
|
||||
* when the task first executes.
|
||||
*
|
||||
* p_stk_base Pointer to the base address of the stack.
|
||||
*
|
||||
* stk_size Size of the stack, in number of CPU_STK elements.
|
||||
*
|
||||
* opt Options used to alter the behavior of OS_Task_StkInit().
|
||||
* (see OS.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.
|
||||
**********************************************************************************************************
|
||||
*/
|
||||
|
||||
CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task,
|
||||
void *p_arg,
|
||||
CPU_STK *p_stk_base,
|
||||
CPU_STK *p_stk_limit,
|
||||
CPU_STK_SIZE stk_size,
|
||||
OS_OPT opt)
|
||||
{
|
||||
CPU_STK *p_stk;
|
||||
|
||||
|
||||
(void)opt; /* Prevent compiler warning */
|
||||
|
||||
p_stk = &p_stk_base[stk_size]; /* Load stack pointer */
|
||||
/* Registers stacked as if auto-saved on exception */
|
||||
*--p_stk = (CPU_STK)0x01000000u; /* xPSR */
|
||||
*--p_stk = (CPU_STK)p_task; /* Entry Point */
|
||||
*--p_stk = (CPU_STK)OS_TaskReturn; /* R14 (LR) */
|
||||
*--p_stk = (CPU_STK)0x12121212u; /* R12 */
|
||||
*--p_stk = (CPU_STK)0x03030303u; /* R3 */
|
||||
*--p_stk = (CPU_STK)0x02020202u; /* R2 */
|
||||
*--p_stk = (CPU_STK)p_stk_limit; /* R1 */
|
||||
*--p_stk = (CPU_STK)p_arg; /* R0 : argument */
|
||||
/* Remaining registers saved on process stack */
|
||||
*--p_stk = (CPU_STK)0x11111111u; /* R11 */
|
||||
*--p_stk = (CPU_STK)0x10101010u; /* R10 */
|
||||
*--p_stk = (CPU_STK)0x09090909u; /* R9 */
|
||||
*--p_stk = (CPU_STK)0x08080808u; /* R8 */
|
||||
*--p_stk = (CPU_STK)0x07070707u; /* R7 */
|
||||
*--p_stk = (CPU_STK)0x06060606u; /* R6 */
|
||||
*--p_stk = (CPU_STK)0x05050505u; /* R5 */
|
||||
*--p_stk = (CPU_STK)0x04040404u; /* R4 */
|
||||
|
||||
return (p_stk);
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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 'OSTCBHighRdyPtr' points to the TCB of the task
|
||||
* that will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCurPtr' points
|
||||
* to the task being switched out (i.e. the preempted task).
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTaskSwHook (void)
|
||||
{
|
||||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||||
CPU_TS ts;
|
||||
#endif
|
||||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||||
CPU_TS int_dis_time;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTaskSwHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppTaskSwHookPtr)();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||||
ts = OS_TS_GET();
|
||||
if (OSTCBCurPtr != OSTCBHighRdyPtr) {
|
||||
OSTCBCurPtr->CyclesDelta = ts - OSTCBCurPtr->CyclesStart;
|
||||
OSTCBCurPtr->CyclesTotal += (OS_CYCLES)OSTCBCurPtr->CyclesDelta;
|
||||
}
|
||||
|
||||
OSTCBHighRdyPtr->CyclesStart = ts;
|
||||
#endif
|
||||
|
||||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||||
int_dis_time = CPU_IntDisMeasMaxCurReset(); /* Keep track of per-task interrupt disable time */
|
||||
if (OSTCBCurPtr->IntDisTimeMax < int_dis_time) {
|
||||
OSTCBCurPtr->IntDisTimeMax = int_dis_time;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
|
||||
/* Keep track of per-task scheduler lock time */
|
||||
if (OSTCBCurPtr->SchedLockTimeMax < OSSchedLockTimeMaxCur) {
|
||||
OSTCBCurPtr->SchedLockTimeMax = OSSchedLockTimeMaxCur;
|
||||
}
|
||||
OSSchedLockTimeMaxCur = (CPU_TS)0; /* Reset the per-task value */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* TICK HOOK
|
||||
*
|
||||
* Description: This function is called every tick.
|
||||
*
|
||||
* Arguments : None.
|
||||
*
|
||||
* Note(s) : 1) This function is assumed to be called from the Tick ISR.
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTimeTickHook (void)
|
||||
{
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
if (OS_AppTimeTickHookPtr != (OS_APP_HOOK_VOID)0) {
|
||||
(*OS_AppTimeTickHookPtr)();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
OSIntNestingCtr++; /* Tell uC/OS-III that we are starting an ISR */
|
||||
CPU_CRITICAL_EXIT();
|
||||
|
||||
OSTimeTick(); /* Call uC/OS-III's OSTimeTick() */
|
||||
|
||||
OSIntExit(); /* Tell uC/OS-III that we are leaving the ISR */
|
||||
}
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 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 (CPU_INT32U cnts)
|
||||
{
|
||||
CPU_INT32U prio;
|
||||
|
||||
|
||||
CPU_REG_NVIC_ST_RELOAD = cnts - 1u;
|
||||
|
||||
/* Set SysTick handler prio. */
|
||||
prio = CPU_REG_NVIC_SHPRI3;
|
||||
prio &= DEF_BIT_FIELD(24, 0);
|
||||
prio |= DEF_BIT_MASK(OS_CPU_CFG_SYSTICK_PRIO, 24);
|
||||
|
||||
CPU_REG_NVIC_SHPRI3 = prio;
|
||||
|
||||
/* Enable timer. */
|
||||
CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_CLKSOURCE |
|
||||
CPU_REG_NVIC_ST_CTRL_ENABLE;
|
||||
/* Enable timer interrupt. */
|
||||
CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_TICKINT;
|
||||
}
|
||||
|
||||
2431
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os.h
Normal file
2431
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os.h
Normal file
File diff suppressed because it is too large
Load Diff
299
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_cfg_app.c
Normal file
299
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_cfg_app.c
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* OS CONFIGURATION (APPLICATION SPECIFICS)
|
||||
*
|
||||
* File : OS_CFG_APP.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
* Note(s) : DO NOT CHANGE THIS FILE!
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os_cfg_app.h>
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_cfg_app__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
#define OS_CFG_IDLE_TASK_STK_LIMIT ((OS_CFG_IDLE_TASK_STK_SIZE * OS_CFG_TASK_STK_LIMIT_PCT_EMPTY) / 100u)
|
||||
#define OS_CFG_INT_Q_TASK_STK_LIMIT ((OS_CFG_INT_Q_TASK_STK_SIZE * OS_CFG_TASK_STK_LIMIT_PCT_EMPTY) / 100u)
|
||||
#define OS_CFG_STAT_TASK_STK_LIMIT ((OS_CFG_STAT_TASK_STK_SIZE * OS_CFG_TASK_STK_LIMIT_PCT_EMPTY) / 100u)
|
||||
#define OS_CFG_TICK_TASK_STK_LIMIT ((OS_CFG_TICK_TASK_STK_SIZE * OS_CFG_TASK_STK_LIMIT_PCT_EMPTY) / 100u)
|
||||
#define OS_CFG_TMR_TASK_STK_LIMIT ((OS_CFG_TMR_TASK_STK_SIZE * OS_CFG_TASK_STK_LIMIT_PCT_EMPTY) / 100u)
|
||||
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* DATA STORAGE
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
CPU_STK OSCfg_IdleTaskStk [OS_CFG_IDLE_TASK_STK_SIZE];
|
||||
|
||||
#if (OS_CFG_ISR_POST_DEFERRED_EN > 0u)
|
||||
OS_INT_Q OSCfg_IntQ [OS_CFG_INT_Q_SIZE];
|
||||
CPU_STK OSCfg_IntQTaskStk [OS_CFG_INT_Q_TASK_STK_SIZE];
|
||||
#endif
|
||||
|
||||
#if (OS_CFG_ISR_STK_SIZE > 0u)
|
||||
CPU_STK OSCfg_ISRStk [OS_CFG_ISR_STK_SIZE];
|
||||
#endif
|
||||
|
||||
#if (OS_MSG_EN > 0u)
|
||||
OS_MSG OSCfg_MsgPool [OS_CFG_MSG_POOL_SIZE];
|
||||
#endif
|
||||
|
||||
#if (OS_CFG_STAT_TASK_EN > 0u)
|
||||
CPU_STK OSCfg_StatTaskStk [OS_CFG_STAT_TASK_STK_SIZE];
|
||||
#endif
|
||||
|
||||
CPU_STK OSCfg_TickTaskStk [OS_CFG_TICK_TASK_STK_SIZE];
|
||||
OS_TICK_SPOKE OSCfg_TickWheel [OS_CFG_TICK_WHEEL_SIZE];
|
||||
|
||||
#if (OS_CFG_TMR_EN > 0u)
|
||||
CPU_STK OSCfg_TmrTaskStk [OS_CFG_TMR_TASK_STK_SIZE];
|
||||
OS_TMR_SPOKE OSCfg_TmrWheel [OS_CFG_TMR_WHEEL_SIZE];
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* CONSTANTS
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
CPU_STK * const OSCfg_IdleTaskStkBasePtr = (CPU_STK *)&OSCfg_IdleTaskStk[0];
|
||||
CPU_STK_SIZE const OSCfg_IdleTaskStkLimit = (CPU_STK_SIZE)OS_CFG_IDLE_TASK_STK_LIMIT;
|
||||
CPU_STK_SIZE const OSCfg_IdleTaskStkSize = (CPU_STK_SIZE)OS_CFG_IDLE_TASK_STK_SIZE;
|
||||
CPU_INT32U const OSCfg_IdleTaskStkSizeRAM = (CPU_INT32U )sizeof(OSCfg_IdleTaskStk);
|
||||
|
||||
|
||||
#if (OS_CFG_ISR_POST_DEFERRED_EN > 0u)
|
||||
OS_INT_Q * const OSCfg_IntQBasePtr = (OS_INT_Q *)&OSCfg_IntQ[0];
|
||||
OS_OBJ_QTY const OSCfg_IntQSize = (OS_OBJ_QTY )OS_CFG_INT_Q_SIZE;
|
||||
CPU_INT32U const OSCfg_IntQSizeRAM = (CPU_INT32U )sizeof(OSCfg_IntQ);
|
||||
CPU_STK * const OSCfg_IntQTaskStkBasePtr = (CPU_STK *)&OSCfg_IntQTaskStk[0];
|
||||
CPU_STK_SIZE const OSCfg_IntQTaskStkLimit = (CPU_STK_SIZE)OS_CFG_INT_Q_TASK_STK_LIMIT;
|
||||
CPU_STK_SIZE const OSCfg_IntQTaskStkSize = (CPU_STK_SIZE)OS_CFG_INT_Q_TASK_STK_SIZE;
|
||||
CPU_INT32U const OSCfg_IntQTaskStkSizeRAM = (CPU_INT32U )sizeof(OSCfg_IntQTaskStk);
|
||||
#else
|
||||
OS_INT_Q * const OSCfg_IntQBasePtr = (OS_INT_Q *)0;
|
||||
OS_OBJ_QTY const OSCfg_IntQSize = (OS_OBJ_QTY )0;
|
||||
CPU_INT32U const OSCfg_IntQSizeRAM = (CPU_INT32U )0;
|
||||
CPU_STK * const OSCfg_IntQTaskStkBasePtr = (CPU_STK *)0;
|
||||
CPU_STK_SIZE const OSCfg_IntQTaskStkLimit = (CPU_STK_SIZE)0;
|
||||
CPU_STK_SIZE const OSCfg_IntQTaskStkSize = (CPU_STK_SIZE)0;
|
||||
CPU_INT32U const OSCfg_IntQTaskStkSizeRAM = (CPU_INT32U )0;
|
||||
#endif
|
||||
|
||||
|
||||
#if (OS_CFG_ISR_STK_SIZE > 0u)
|
||||
CPU_STK * const OSCfg_ISRStkBasePtr = (CPU_STK *)&OSCfg_ISRStk[0];
|
||||
CPU_STK_SIZE const OSCfg_ISRStkSize = (CPU_STK_SIZE)OS_CFG_ISR_STK_SIZE;
|
||||
CPU_INT32U const OSCfg_ISRStkSizeRAM = (CPU_INT32U )sizeof(OSCfg_ISRStk);
|
||||
#else
|
||||
CPU_STK * const OSCfg_ISRStkBasePtr = (CPU_STK *)0;
|
||||
CPU_STK_SIZE const OSCfg_ISRStkSize = (CPU_STK_SIZE)0;
|
||||
CPU_INT32U const OSCfg_ISRStkSizeRAM = (CPU_INT32U )0;
|
||||
#endif
|
||||
|
||||
|
||||
#if (OS_MSG_EN > 0u)
|
||||
OS_MSG_SIZE const OSCfg_MsgPoolSize = (OS_MSG_SIZE)OS_CFG_MSG_POOL_SIZE;
|
||||
CPU_INT32U const OSCfg_MsgPoolSizeRAM = (CPU_INT32U )sizeof(OSCfg_MsgPool);
|
||||
OS_MSG * const OSCfg_MsgPoolBasePtr = (OS_MSG *)&OSCfg_MsgPool[0];
|
||||
#else
|
||||
OS_MSG_SIZE const OSCfg_MsgPoolSize = (OS_MSG_SIZE)0;
|
||||
CPU_INT32U const OSCfg_MsgPoolSizeRAM = (CPU_INT32U )0;
|
||||
OS_MSG * const OSCfg_MsgPoolBasePtr = (OS_MSG *)0;
|
||||
#endif
|
||||
|
||||
|
||||
#if (OS_CFG_STAT_TASK_EN > 0u)
|
||||
OS_PRIO const OSCfg_StatTaskPrio = (OS_PRIO )OS_CFG_STAT_TASK_PRIO;
|
||||
OS_RATE_HZ const OSCfg_StatTaskRate_Hz = (OS_RATE_HZ )OS_CFG_STAT_TASK_RATE_HZ;
|
||||
CPU_STK * const OSCfg_StatTaskStkBasePtr = (CPU_STK *)&OSCfg_StatTaskStk[0];
|
||||
CPU_STK_SIZE const OSCfg_StatTaskStkLimit = (CPU_STK_SIZE)OS_CFG_STAT_TASK_STK_LIMIT;
|
||||
CPU_STK_SIZE const OSCfg_StatTaskStkSize = (CPU_STK_SIZE)OS_CFG_STAT_TASK_STK_SIZE;
|
||||
CPU_INT32U const OSCfg_StatTaskStkSizeRAM = (CPU_INT32U )sizeof(OSCfg_StatTaskStk);
|
||||
#else
|
||||
OS_PRIO const OSCfg_StatTaskPrio = (OS_PRIO )0;
|
||||
OS_RATE_HZ const OSCfg_StatTaskRate_Hz = (OS_RATE_HZ )0;
|
||||
CPU_STK * const OSCfg_StatTaskStkBasePtr = (CPU_STK *)0;
|
||||
CPU_STK_SIZE const OSCfg_StatTaskStkLimit = (CPU_STK_SIZE)0;
|
||||
CPU_STK_SIZE const OSCfg_StatTaskStkSize = (CPU_STK_SIZE)0;
|
||||
CPU_INT32U const OSCfg_StatTaskStkSizeRAM = (CPU_INT32U )0;
|
||||
#endif
|
||||
|
||||
|
||||
CPU_STK_SIZE const OSCfg_StkSizeMin = (CPU_STK_SIZE)OS_CFG_STK_SIZE_MIN;
|
||||
|
||||
|
||||
OS_RATE_HZ const OSCfg_TickRate_Hz = (OS_RATE_HZ )OS_CFG_TICK_RATE_HZ;
|
||||
OS_PRIO const OSCfg_TickTaskPrio = (OS_PRIO )OS_CFG_TICK_TASK_PRIO;
|
||||
CPU_STK * const OSCfg_TickTaskStkBasePtr = (CPU_STK *)&OSCfg_TickTaskStk[0];
|
||||
CPU_STK_SIZE const OSCfg_TickTaskStkLimit = (CPU_STK_SIZE)OS_CFG_TICK_TASK_STK_LIMIT;
|
||||
CPU_STK_SIZE const OSCfg_TickTaskStkSize = (CPU_STK_SIZE)OS_CFG_TICK_TASK_STK_SIZE;
|
||||
CPU_INT32U const OSCfg_TickTaskStkSizeRAM = (CPU_INT32U )sizeof(OSCfg_TickTaskStk);
|
||||
OS_OBJ_QTY const OSCfg_TickWheelSize = (OS_OBJ_QTY )OS_CFG_TICK_WHEEL_SIZE;
|
||||
CPU_INT32U const OSCfg_TickWheelSizeRAM = (CPU_INT32U )sizeof(OSCfg_TickWheel);
|
||||
|
||||
|
||||
#if (OS_CFG_TMR_EN > 0u)
|
||||
OS_PRIO const OSCfg_TmrTaskPrio = (OS_PRIO )OS_CFG_TMR_TASK_PRIO;
|
||||
OS_RATE_HZ const OSCfg_TmrTaskRate_Hz = (OS_RATE_HZ )OS_CFG_TMR_TASK_RATE_HZ;
|
||||
CPU_STK * const OSCfg_TmrTaskStkBasePtr = (CPU_STK *)&OSCfg_TmrTaskStk[0];
|
||||
CPU_STK_SIZE const OSCfg_TmrTaskStkLimit = (CPU_STK_SIZE)OS_CFG_TMR_TASK_STK_LIMIT;
|
||||
CPU_STK_SIZE const OSCfg_TmrTaskStkSize = (CPU_STK_SIZE)OS_CFG_TMR_TASK_STK_SIZE;
|
||||
CPU_INT32U const OSCfg_TmrTaskStkSizeRAM = (CPU_INT32U )sizeof(OSCfg_TmrTaskStk);
|
||||
OS_OBJ_QTY const OSCfg_TmrWheelSize = (OS_OBJ_QTY )OS_CFG_TMR_WHEEL_SIZE;
|
||||
CPU_INT32U const OSCfg_TmrWheelSizeRAM = (CPU_INT32U )sizeof(OSCfg_TmrWheel);
|
||||
#else
|
||||
OS_PRIO const OSCfg_TmrTaskPrio = (OS_PRIO )0;
|
||||
OS_RATE_HZ const OSCfg_TmrTaskRate_Hz = (OS_RATE_HZ )0;
|
||||
CPU_STK * const OSCfg_TmrTaskStkBasePtr = (CPU_STK *)0;
|
||||
CPU_STK_SIZE const OSCfg_TmrTaskStkLimit = (CPU_STK_SIZE)0;
|
||||
CPU_STK_SIZE const OSCfg_TmrTaskStkSize = (CPU_STK_SIZE)0;
|
||||
CPU_INT32U const OSCfg_TmrTaskStkSizeRAM = (CPU_INT32U )0;
|
||||
OS_OBJ_QTY const OSCfg_TmrWheelSize = (OS_OBJ_QTY )0;
|
||||
CPU_INT32U const OSCfg_TmrWheelSizeRAM = (CPU_INT32U )0;
|
||||
#endif
|
||||
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* TOTAL SIZE OF APPLICATION CONFIGURATION
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
CPU_INT32U const OSCfg_DataSizeRAM = sizeof(OSCfg_IdleTaskStk)
|
||||
|
||||
#if (OS_CFG_ISR_POST_DEFERRED_EN > 0u)
|
||||
+ sizeof(OSCfg_IntQ)
|
||||
+ sizeof(OSCfg_IntQTaskStk)
|
||||
#endif
|
||||
|
||||
#if (OS_MSG_EN > 0u)
|
||||
+ sizeof(OSCfg_MsgPool)
|
||||
#endif
|
||||
|
||||
#if (OS_CFG_STAT_TASK_EN > 0u)
|
||||
+ sizeof(OSCfg_StatTaskStk)
|
||||
#endif
|
||||
|
||||
#if (OS_CFG_TMR_EN > 0u)
|
||||
+ sizeof(OSCfg_TmrTaskStk)
|
||||
+ sizeof(OSCfg_TmrWheel)
|
||||
#endif
|
||||
|
||||
#if (OS_CFG_ISR_STK_SIZE > 0u)
|
||||
+ sizeof(OSCfg_ISRStk)
|
||||
#endif
|
||||
+ sizeof(OSCfg_TickTaskStk)
|
||||
+ sizeof(OSCfg_TickWheel);
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* OS CONFIGURATION 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSCfg_Init (void)
|
||||
{
|
||||
(void)&OSCfg_DataSizeRAM;
|
||||
|
||||
(void)&OSCfg_IdleTaskStkBasePtr;
|
||||
(void)&OSCfg_IdleTaskStkLimit;
|
||||
(void)&OSCfg_IdleTaskStkSize;
|
||||
(void)&OSCfg_IdleTaskStkSizeRAM;
|
||||
|
||||
#if (OS_CFG_ISR_POST_DEFERRED_EN > 0u)
|
||||
(void)&OSCfg_IntQBasePtr;
|
||||
(void)&OSCfg_IntQSize;
|
||||
(void)&OSCfg_IntQSizeRAM;
|
||||
(void)&OSCfg_IntQTaskStkBasePtr;
|
||||
(void)&OSCfg_IntQTaskStkLimit;
|
||||
(void)&OSCfg_IntQTaskStkSize;
|
||||
(void)&OSCfg_IntQTaskStkSizeRAM;
|
||||
#endif
|
||||
|
||||
(void)&OSCfg_ISRStkBasePtr;
|
||||
(void)&OSCfg_ISRStkSize;
|
||||
(void)&OSCfg_ISRStkSizeRAM;
|
||||
|
||||
#if (OS_MSG_EN > 0u)
|
||||
(void)&OSCfg_MsgPoolSize;
|
||||
(void)&OSCfg_MsgPoolSizeRAM;
|
||||
(void)&OSCfg_MsgPoolBasePtr;
|
||||
#endif
|
||||
|
||||
#if (OS_CFG_STAT_TASK_EN > 0u)
|
||||
(void)&OSCfg_StatTaskPrio;
|
||||
(void)&OSCfg_StatTaskRate_Hz;
|
||||
(void)&OSCfg_StatTaskStkBasePtr;
|
||||
(void)&OSCfg_StatTaskStkLimit;
|
||||
(void)&OSCfg_StatTaskStkSize;
|
||||
(void)&OSCfg_StatTaskStkSizeRAM;
|
||||
#endif
|
||||
|
||||
(void)&OSCfg_StkSizeMin;
|
||||
|
||||
(void)&OSCfg_TickRate_Hz;
|
||||
(void)&OSCfg_TickTaskPrio;
|
||||
(void)&OSCfg_TickTaskStkBasePtr;
|
||||
(void)&OSCfg_TickTaskStkLimit;
|
||||
(void)&OSCfg_TickTaskStkSize;
|
||||
(void)&OSCfg_TickTaskStkSizeRAM;
|
||||
(void)&OSCfg_TickWheelSize;
|
||||
(void)&OSCfg_TickWheelSizeRAM;
|
||||
|
||||
#if (OS_CFG_TMR_EN > 0u)
|
||||
(void)&OSCfg_TmrTaskPrio;
|
||||
(void)&OSCfg_TmrTaskRate_Hz;
|
||||
(void)&OSCfg_TmrTaskStkBasePtr;
|
||||
(void)&OSCfg_TmrTaskStkLimit;
|
||||
(void)&OSCfg_TmrTaskStkSize;
|
||||
(void)&OSCfg_TmrTaskStkSizeRAM;
|
||||
(void)&OSCfg_TmrWheelSize;
|
||||
(void)&OSCfg_TmrWheelSizeRAM;
|
||||
#endif
|
||||
}
|
||||
2642
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_core.c
Normal file
2642
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_core.c
Normal file
File diff suppressed because it is too large
Load Diff
496
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_dbg.c
Normal file
496
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_dbg.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* DEBUGGER CONSTANTS
|
||||
*
|
||||
* File : OS_DBG.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_dbg__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
CPU_INT08U const OSDbg_DbgEn = OS_CFG_DBG_EN; /* Debug constants are defined below */
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* DEBUG DATA
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
CPU_INT08U const OSDbg_ArgChkEn = OS_CFG_ARG_CHK_EN;
|
||||
CPU_INT08U const OSDbg_AppHooksEn = OS_CFG_APP_HOOKS_EN;
|
||||
|
||||
CPU_INT32U const OSDbg_EndiannessTest = 0x12345678LU; /* Variable to test CPU endianness */
|
||||
|
||||
CPU_INT08U const OSDbg_CalledFromISRChkEn = OS_CFG_CALLED_FROM_ISR_CHK_EN;
|
||||
|
||||
CPU_INT08U const OSDbg_FlagEn = OS_CFG_FLAG_EN;
|
||||
OS_FLAG_GRP const OSDbg_FlagGrp = { 0u };
|
||||
#if OS_CFG_FLAG_EN > 0u
|
||||
CPU_INT08U const OSDbg_FlagDelEn = OS_CFG_FLAG_DEL_EN;
|
||||
CPU_INT08U const OSDbg_FlagModeClrEn = OS_CFG_FLAG_MODE_CLR_EN;
|
||||
CPU_INT08U const OSDbg_FlagPendAbortEn = OS_CFG_FLAG_PEND_ABORT_EN;
|
||||
CPU_INT16U const OSDbg_FlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */
|
||||
CPU_INT16U const OSDbg_FlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */
|
||||
#else
|
||||
CPU_INT08U const OSDbg_FlagDelEn = 0u;
|
||||
CPU_INT08U const OSDbg_FlagModeClrEn = 0u;
|
||||
CPU_INT08U const OSDbg_FlagPendAbortEn = 0u;
|
||||
CPU_INT16U const OSDbg_FlagGrpSize = 0u;
|
||||
CPU_INT16U const OSDbg_FlagWidth = 0u;
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
|
||||
CPU_INT16U const OSDbg_IntQ = sizeof(OS_INT_Q);
|
||||
#else
|
||||
CPU_INT16U const OSDbg_IntQ = 0u;
|
||||
#endif
|
||||
|
||||
CPU_INT08U const OSDbg_ISRPostDeferredEn = OS_CFG_ISR_POST_DEFERRED_EN;
|
||||
|
||||
OS_MEM const OSDbg_Mem = { 0u };
|
||||
CPU_INT08U const OSDbg_MemEn = OS_CFG_MEM_EN;
|
||||
#if OS_CFG_MEM_EN > 0u
|
||||
CPU_INT16U const OSDbg_MemSize = sizeof(OS_MEM); /* Mem. Partition header size (bytes) */
|
||||
#else
|
||||
CPU_INT16U const OSDbg_MemSize = 0u;
|
||||
#endif
|
||||
|
||||
|
||||
#if (OS_MSG_EN) > 0u
|
||||
CPU_INT08U const OSDbg_MsgEn = 1u;
|
||||
CPU_INT16U const OSDbg_MsgSize = sizeof(OS_MSG); /* OS_MSG size */
|
||||
CPU_INT16U const OSDbg_MsgPoolSize = sizeof(OS_MSG_POOL);
|
||||
CPU_INT16U const OSDbg_MsgQSize = sizeof(OS_MSG_Q);
|
||||
#else
|
||||
CPU_INT08U const OSDbg_MsgEn = 0u;
|
||||
CPU_INT16U const OSDbg_MsgSize = 0u;
|
||||
CPU_INT16U const OSDbg_MsgPoolSize = 0u;
|
||||
CPU_INT16U const OSDbg_MsgQSize = 0u;
|
||||
#endif
|
||||
|
||||
|
||||
OS_MUTEX const OSDbg_Mutex = { 0u };
|
||||
CPU_INT08U const OSDbg_MutexEn = OS_CFG_MUTEX_EN;
|
||||
#if OS_CFG_MUTEX_EN > 0u
|
||||
CPU_INT08U const OSDbg_MutexDelEn = OS_CFG_MUTEX_DEL_EN;
|
||||
CPU_INT08U const OSDbg_MutexPendAbortEn = OS_CFG_MUTEX_PEND_ABORT_EN;
|
||||
CPU_INT16U const OSDbg_MutexSize = sizeof(OS_MUTEX); /* Size in bytes of OS_MUTEX */
|
||||
#else
|
||||
CPU_INT08U const OSDbg_MutexDelEn = 0u;
|
||||
CPU_INT08U const OSDbg_MutexPendAbortEn = 0u;
|
||||
CPU_INT16U const OSDbg_MutexSize = 0u;
|
||||
#endif
|
||||
|
||||
CPU_INT08U const OSDbg_ObjTypeChkEn = OS_CFG_OBJ_TYPE_CHK_EN;
|
||||
|
||||
|
||||
CPU_INT08U const OSDbg_PendMultiEn = OS_CFG_PEND_MULTI_EN;
|
||||
CPU_INT16U const OSDbg_PendDataSize = sizeof(OS_PEND_DATA);
|
||||
CPU_INT16U const OSDbg_PendListSize = sizeof(OS_PEND_LIST);
|
||||
CPU_INT16U const OSDbg_PendObjSize = sizeof(OS_PEND_OBJ);
|
||||
|
||||
|
||||
CPU_INT16U const OSDbg_PrioMax = OS_CFG_PRIO_MAX; /* Maximum number of priorities */
|
||||
CPU_INT16U const OSDbg_PrioTblSize = sizeof(OSPrioTbl);
|
||||
|
||||
CPU_INT16U const OSDbg_PtrSize = sizeof(void *); /* Size in Bytes of a pointer */
|
||||
|
||||
|
||||
OS_Q const OSDbg_Q = { 0u };
|
||||
CPU_INT08U const OSDbg_QEn = OS_CFG_Q_EN;
|
||||
#if OS_CFG_Q_EN > 0u
|
||||
CPU_INT08U const OSDbg_QDelEn = OS_CFG_Q_DEL_EN;
|
||||
CPU_INT08U const OSDbg_QFlushEn = OS_CFG_Q_FLUSH_EN;
|
||||
CPU_INT08U const OSDbg_QPendAbortEn = OS_CFG_Q_PEND_ABORT_EN;
|
||||
CPU_INT16U const OSDbg_QSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */
|
||||
#else
|
||||
CPU_INT08U const OSDbg_QDelEn = 0u;
|
||||
CPU_INT08U const OSDbg_QFlushEn = 0u;
|
||||
CPU_INT08U const OSDbg_QPendAbortEn = 0u;
|
||||
CPU_INT16U const OSDbg_QSize = 0u;
|
||||
#endif
|
||||
|
||||
|
||||
CPU_INT08U const OSDbg_SchedRoundRobinEn = OS_CFG_SCHED_ROUND_ROBIN_EN;
|
||||
|
||||
|
||||
OS_SEM const OSDbg_Sem = { 0u };
|
||||
CPU_INT08U const OSDbg_SemEn = OS_CFG_SEM_EN;
|
||||
#if OS_CFG_SEM_EN > 0u
|
||||
CPU_INT08U const OSDbg_SemDelEn = OS_CFG_SEM_DEL_EN;
|
||||
CPU_INT08U const OSDbg_SemPendAbortEn = OS_CFG_SEM_PEND_ABORT_EN;
|
||||
CPU_INT08U const OSDbg_SemSetEn = OS_CFG_SEM_SET_EN;
|
||||
CPU_INT16U const OSDbg_SemSize = sizeof(OS_SEM); /* Size in bytes of OS_SEM */
|
||||
#else
|
||||
CPU_INT08U const OSDbg_SemDelEn = 0u;
|
||||
CPU_INT08U const OSDbg_SemPendAbortEn = 0u;
|
||||
CPU_INT08U const OSDbg_SemSetEn = 0u;
|
||||
CPU_INT16U const OSDbg_SemSize = 0u;
|
||||
#endif
|
||||
|
||||
|
||||
CPU_INT16U const OSDbg_RdyList = sizeof(OS_RDY_LIST);
|
||||
CPU_INT32U const OSDbg_RdyListSize = sizeof(OSRdyList); /* Number of bytes in the ready table */
|
||||
|
||||
CPU_INT08U const OSDbg_StkWidth = sizeof(CPU_STK);
|
||||
|
||||
CPU_INT08U const OSDbg_StatTaskEn = OS_CFG_STAT_TASK_EN;
|
||||
CPU_INT08U const OSDbg_StatTaskStkChkEn = OS_CFG_STAT_TASK_STK_CHK_EN;
|
||||
|
||||
CPU_INT08U const OSDbg_TaskChangePrioEn = OS_CFG_TASK_CHANGE_PRIO_EN;
|
||||
CPU_INT08U const OSDbg_TaskDelEn = OS_CFG_TASK_DEL_EN;
|
||||
CPU_INT08U const OSDbg_TaskQEn = OS_CFG_TASK_Q_EN;
|
||||
CPU_INT08U const OSDbg_TaskQPendAbortEn = OS_CFG_TASK_Q_PEND_ABORT_EN;
|
||||
CPU_INT08U const OSDbg_TaskProfileEn = OS_CFG_TASK_PROFILE_EN;
|
||||
CPU_INT16U const OSDbg_TaskRegTblSize = OS_CFG_TASK_REG_TBL_SIZE;
|
||||
CPU_INT08U const OSDbg_TaskSemPendAbortEn = OS_CFG_TASK_SEM_PEND_ABORT_EN;
|
||||
CPU_INT08U const OSDbg_TaskSuspendEn = OS_CFG_TASK_SUSPEND_EN;
|
||||
|
||||
|
||||
CPU_INT16U const OSDbg_TCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */
|
||||
|
||||
CPU_INT16U const OSDbg_TickSpokeSize = sizeof(OS_TICK_SPOKE);
|
||||
|
||||
CPU_INT08U const OSDbg_TimeDlyHMSMEn = OS_CFG_TIME_DLY_HMSM_EN;
|
||||
CPU_INT08U const OSDbg_TimeDlyResumeEn = OS_CFG_TIME_DLY_RESUME_EN;
|
||||
|
||||
#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
|
||||
CPU_INT16U const OSDbg_TLS_TblSize = OS_CFG_TLS_TBL_SIZE * sizeof(OS_TLS);
|
||||
#else
|
||||
CPU_INT16U const OSDbg_TLS_TblSize = 0u;
|
||||
#endif
|
||||
|
||||
|
||||
OS_TMR const OSDbg_Tmr = { 0u };
|
||||
CPU_INT08U const OSDbg_TmrEn = OS_CFG_TMR_EN;
|
||||
#if OS_CFG_TMR_EN > 0u
|
||||
CPU_INT08U const OSDbg_TmrDelEn = OS_CFG_TMR_DEL_EN;
|
||||
CPU_INT16U const OSDbg_TmrSize = sizeof(OS_TMR);
|
||||
CPU_INT16U const OSDbg_TmrSpokeSize = sizeof(OS_TMR_SPOKE);
|
||||
#else
|
||||
CPU_INT08U const OSDbg_TmrDelEn = 0u;
|
||||
CPU_INT16U const OSDbg_TmrSize = 0u;
|
||||
CPU_INT16U const OSDbg_TmrSpokeSize = 0u;
|
||||
#endif
|
||||
|
||||
CPU_INT16U const OSDbg_VersionNbr = OS_VERSION;
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* DEBUG DATA
|
||||
* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-III
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
CPU_INT32U const OSDbg_DataSize = sizeof(OSIntNestingCtr)
|
||||
|
||||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||||
+ sizeof(OS_AppTaskCreateHookPtr)
|
||||
+ sizeof(OS_AppTaskDelHookPtr)
|
||||
+ sizeof(OS_AppTaskReturnHookPtr)
|
||||
|
||||
+ sizeof(OS_AppIdleTaskHookPtr)
|
||||
+ sizeof(OS_AppStatTaskHookPtr)
|
||||
+ sizeof(OS_AppTaskSwHookPtr)
|
||||
+ sizeof(OS_AppTimeTickHookPtr)
|
||||
#endif
|
||||
|
||||
+ sizeof(OSIdleTaskCtr)
|
||||
+ sizeof(OSIdleTaskTCB)
|
||||
|
||||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||||
+ sizeof(OSIntDisTimeMax)
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
|
||||
+ sizeof(OSIntQInPtr)
|
||||
+ sizeof(OSIntQOutPtr)
|
||||
+ sizeof(OSIntQNbrEntries)
|
||||
+ sizeof(OSIntQNbrEntriesMax)
|
||||
+ sizeof(OSIntQOvfCtr)
|
||||
+ sizeof(OSIntQTaskTCB)
|
||||
+ sizeof(OSIntQTaskTimeMax)
|
||||
#endif
|
||||
|
||||
+ sizeof(OSRunning)
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL_IEC61508
|
||||
+ sizeof(OSSafetyCriticalStartFlag)
|
||||
#endif
|
||||
|
||||
#if OS_CFG_FLAG_EN > 0u
|
||||
+ sizeof(OSFlagDbgListPtr)
|
||||
+ sizeof(OSFlagQty)
|
||||
#endif
|
||||
|
||||
#if OS_CFG_MEM_EN > 0u
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
+ sizeof(OSMemDbgListPtr)
|
||||
#endif
|
||||
+ sizeof(OSMemQty)
|
||||
#endif
|
||||
|
||||
#if OS_MSG_EN > 0u
|
||||
+ sizeof(OSMsgPool)
|
||||
#endif
|
||||
|
||||
#if OS_CFG_MUTEX_EN > 0u
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
+ sizeof(OSMutexDbgListPtr)
|
||||
#endif
|
||||
+ sizeof(OSMutexQty)
|
||||
#endif
|
||||
|
||||
+ sizeof(OSPrioCur)
|
||||
+ sizeof(OSPrioHighRdy)
|
||||
+ sizeof(OSPrioSaved)
|
||||
+ sizeof(OSPrioTbl)
|
||||
|
||||
#if OS_CFG_Q_EN > 0u
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
+ sizeof(OSQDbgListPtr)
|
||||
#endif
|
||||
+ sizeof(OSQQty)
|
||||
#endif
|
||||
|
||||
+ sizeof(OSRdyList)
|
||||
|
||||
+ sizeof(OSSchedLockNestingCtr)
|
||||
|
||||
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
|
||||
+ sizeof(OSSchedLockTimeBegin)
|
||||
+ sizeof(OSSchedLockTimeMax)
|
||||
+ sizeof(OSSchedLockTimeMaxCur)
|
||||
#endif
|
||||
|
||||
#if OS_CFG_SCHED_ROUND_ROBIN_EN
|
||||
+ sizeof(OSSchedRoundRobinDfltTimeQuanta)
|
||||
+ sizeof(OSSchedRoundRobinEn)
|
||||
#endif
|
||||
|
||||
#if OS_CFG_SEM_EN > 0u
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
+ sizeof(OSSemDbgListPtr)
|
||||
#endif
|
||||
+ sizeof(OSSemQty)
|
||||
#endif
|
||||
+ sizeof(OSTaskCtxSwCtr)
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
+ sizeof(OSTaskDbgListPtr)
|
||||
#endif
|
||||
+ sizeof(OSTaskQty)
|
||||
|
||||
#if OS_CFG_STAT_TASK_EN > 0u
|
||||
+ sizeof(OSStatResetFlag)
|
||||
+ sizeof(OSStatTaskCPUUsage)
|
||||
+ sizeof(OSStatTaskCPUUsageMax)
|
||||
+ sizeof(OSStatTaskCtr)
|
||||
+ sizeof(OSStatTaskCtrMax)
|
||||
+ sizeof(OSStatTaskCtrRun)
|
||||
+ sizeof(OSStatTaskRdy)
|
||||
+ sizeof(OSStatTaskTCB)
|
||||
+ sizeof(OSStatTaskTimeMax)
|
||||
#endif
|
||||
|
||||
+ sizeof(OSTickCtr)
|
||||
+ sizeof(OSTickTaskTCB)
|
||||
+ sizeof(OSTickTaskTimeMax)
|
||||
|
||||
#if OS_CFG_TMR_EN > 0u
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
+ sizeof(OSTmrDbgListPtr)
|
||||
#endif
|
||||
+ sizeof(OSTmrQty)
|
||||
+ sizeof(OSTmrTaskTCB)
|
||||
+ sizeof(OSTmrTaskTimeMax)
|
||||
+ sizeof(OSTmrTickCtr)
|
||||
+ sizeof(OSTmrUpdateCnt)
|
||||
+ sizeof(OSTmrUpdateCtr)
|
||||
#endif
|
||||
|
||||
#if OS_CFG_TASK_REG_TBL_SIZE > 0u
|
||||
+ sizeof(OSTaskRegNextAvailID)
|
||||
#endif
|
||||
|
||||
+ sizeof(OSTCBCurPtr)
|
||||
+ sizeof(OSTCBHighRdyPtr);
|
||||
|
||||
/*$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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_Dbg_Init (void)
|
||||
{
|
||||
CPU_INT08U const *p_temp08;
|
||||
CPU_INT16U const *p_temp16;
|
||||
CPU_INT32U const *p_temp32;
|
||||
|
||||
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_DbgEn;
|
||||
|
||||
p_temp32 = (CPU_INT32U const *)&OSDbg_DataSize;
|
||||
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_ArgChkEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_AppHooksEn;
|
||||
|
||||
p_temp32 = (CPU_INT32U const *)&OSDbg_EndiannessTest;
|
||||
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_CalledFromISRChkEn;
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_FlagGrp;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_FlagEn;
|
||||
#if OS_CFG_FLAG_EN > 0u
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_FlagDelEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_FlagModeClrEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_FlagPendAbortEn;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_FlagGrpSize;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_FlagWidth;
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_IntQ;
|
||||
#endif
|
||||
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_ISRPostDeferredEn;
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_Mem;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_MemEn;
|
||||
#if OS_CFG_MEM_EN > 0u
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_MemSize;
|
||||
#endif
|
||||
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_MsgEn;
|
||||
#if (OS_MSG_EN) > 0u
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_MsgSize;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_MsgPoolSize;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_MsgQSize;
|
||||
#endif
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_Mutex;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_MutexEn;
|
||||
#if (OS_CFG_MUTEX_EN) > 0u
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_MutexDelEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_MutexPendAbortEn;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_MutexSize;
|
||||
#endif
|
||||
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_ObjTypeChkEn;
|
||||
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_PendMultiEn;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_PendDataSize;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_PendListSize;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_PendObjSize;
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_PrioMax;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_PrioTblSize;
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_PtrSize;
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_Q;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_QEn;
|
||||
#if (OS_CFG_Q_EN) > 0u
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_QDelEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_QFlushEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_QPendAbortEn;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_QSize;
|
||||
#endif
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_SchedRoundRobinEn;
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_Sem;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_SemEn;
|
||||
#if (OS_CFG_SEM_EN) > 0u
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_SemDelEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_SemPendAbortEn;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_SemSetEn;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_SemSize;
|
||||
#endif
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_RdyList;
|
||||
p_temp32 = (CPU_INT32U const *)&OSDbg_RdyListSize;
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_StkWidth;
|
||||
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_StatTaskEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_StatTaskStkChkEn;
|
||||
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_TaskChangePrioEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_TaskDelEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_TaskQEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_TaskQPendAbortEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_TaskProfileEn;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_TaskRegTblSize;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_TaskSemPendAbortEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_TaskSuspendEn;
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_TCBSize;
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_TickSpokeSize;
|
||||
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_TimeDlyHMSMEn;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_TimeDlyResumeEn;
|
||||
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_Tmr;
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_TmrEn;
|
||||
#if (OS_CFG_TMR_EN) > 0u
|
||||
p_temp08 = (CPU_INT08U const *)&OSDbg_TmrDelEn;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_TmrSize;
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_TmrSpokeSize;
|
||||
#endif
|
||||
|
||||
p_temp16 = (CPU_INT16U const *)&OSDbg_VersionNbr;
|
||||
|
||||
p_temp08 = p_temp08; /* Prevent compiler warning for not using 'p_temp' */
|
||||
p_temp16 = p_temp16;
|
||||
p_temp32 = p_temp32;
|
||||
}
|
||||
#endif
|
||||
1272
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_flag.c
Normal file
1272
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_flag.c
Normal file
File diff suppressed because it is too large
Load Diff
408
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_int.c
Normal file
408
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_int.c
Normal file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* ISR QUEUE MANAGEMENT
|
||||
*
|
||||
* File : OS_INT.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_int__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
|
||||
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* POST TO ISR QUEUE
|
||||
*
|
||||
* Description: This function places contents of posts into an intermediate queue to help defer processing of interrupts
|
||||
* at the task level.
|
||||
*
|
||||
* Arguments : type is the type of kernel object the post is destined to:
|
||||
*
|
||||
* OS_OBJ_TYPE_SEM
|
||||
* OS_OBJ_TYPE_Q
|
||||
* OS_OBJ_TYPE_FLAG
|
||||
* OS_OBJ_TYPE_TASK_MSG
|
||||
* OS_OBJ_TYPE_TASK_SIGNAL
|
||||
*
|
||||
* p_obj is a pointer to the kernel object to post to. This can be a pointer to a semaphore,
|
||||
* ----- a message queue or a task control clock.
|
||||
*
|
||||
* p_void is a pointer to a message that is being posted. This is used when posting to a message
|
||||
* queue or directly to a task.
|
||||
*
|
||||
* msg_size is the size of the message being posted
|
||||
*
|
||||
* flags if the post is done to an event flag group then this corresponds to the flags being
|
||||
* posted
|
||||
*
|
||||
* ts is a timestamp as to when the post was done
|
||||
*
|
||||
* opt this corresponds to post options and applies to:
|
||||
*
|
||||
* OSFlagPost()
|
||||
* OSSemPost()
|
||||
* OSQPost()
|
||||
* OSTaskQPost()
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE if the post to the ISR queue was successful
|
||||
* OS_ERR_INT_Q_FULL if the ISR queue is full and cannot accepts any further posts. This
|
||||
* generally indicates that you are receiving interrupts faster than you
|
||||
* can process them or, that you didn't make the ISR queue large enough.
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_IntQPost (OS_OBJ_TYPE type,
|
||||
void *p_obj,
|
||||
void *p_void,
|
||||
OS_MSG_SIZE msg_size,
|
||||
OS_FLAGS flags,
|
||||
OS_OPT opt,
|
||||
CPU_TS ts,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
if (OSIntQNbrEntries < OSCfg_IntQSize) { /* Make sure we haven't already filled the ISR queue */
|
||||
OSIntQNbrEntries++;
|
||||
|
||||
if (OSIntQNbrEntriesMax < OSIntQNbrEntries) {
|
||||
OSIntQNbrEntriesMax = OSIntQNbrEntries;
|
||||
}
|
||||
|
||||
OSIntQInPtr->Type = type; /* Save object type being posted */
|
||||
OSIntQInPtr->ObjPtr = p_obj; /* Save pointer to object being posted */
|
||||
OSIntQInPtr->MsgPtr = p_void; /* Save pointer to message if posting to a message queue */
|
||||
OSIntQInPtr->MsgSize = msg_size; /* Save the message size if posting to a message queue */
|
||||
OSIntQInPtr->Flags = flags; /* Save the flags if posting to an event flag group */
|
||||
OSIntQInPtr->Opt = opt; /* Save post options */
|
||||
OSIntQInPtr->TS = ts; /* Save time stamp */
|
||||
|
||||
OSIntQInPtr = OSIntQInPtr->NextPtr; /* Point to the next interrupt handler queue entry */
|
||||
|
||||
OSRdyList[0].NbrEntries = (OS_OBJ_QTY)1; /* Make the interrupt handler task ready to run */
|
||||
OSRdyList[0].HeadPtr = &OSIntQTaskTCB;
|
||||
OSRdyList[0].TailPtr = &OSIntQTaskTCB;
|
||||
OS_PrioInsert(0u); /* Add task priority 0 in the priority table */
|
||||
if (OSPrioCur != 0) { /* Chk if OSIntQTask is not running */
|
||||
OSPrioSaved = OSPrioCur; /* Save current priority */
|
||||
}
|
||||
|
||||
*p_err = OS_ERR_NONE;
|
||||
} else {
|
||||
OSIntQOvfCtr++; /* Count the number of ISR queue overflows */
|
||||
*p_err = OS_ERR_INT_Q_FULL;
|
||||
}
|
||||
CPU_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INTERRUPT QUEUE MANAGEMENT TASK
|
||||
*
|
||||
* Description: This task is created by OS_IntQTaskInit().
|
||||
*
|
||||
* Arguments : p_arg is a pointer to an optional argument that is passed during task creation. For this function
|
||||
* the argument is not used and will be a NULL pointer.
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_IntQRePost (void)
|
||||
{
|
||||
CPU_TS ts;
|
||||
OS_ERR err;
|
||||
|
||||
|
||||
switch (OSIntQOutPtr->Type) { /* Re-post to task */
|
||||
case OS_OBJ_TYPE_FLAG:
|
||||
#if OS_CFG_FLAG_EN > 0u
|
||||
(void)OS_FlagPost((OS_FLAG_GRP *) OSIntQOutPtr->ObjPtr,
|
||||
(OS_FLAGS ) OSIntQOutPtr->Flags,
|
||||
(OS_OPT ) OSIntQOutPtr->Opt,
|
||||
(CPU_TS ) OSIntQOutPtr->TS,
|
||||
(OS_ERR *)&err);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OS_OBJ_TYPE_Q:
|
||||
#if OS_CFG_Q_EN > 0u
|
||||
OS_QPost((OS_Q *) OSIntQOutPtr->ObjPtr,
|
||||
(void *) OSIntQOutPtr->MsgPtr,
|
||||
(OS_MSG_SIZE) OSIntQOutPtr->MsgSize,
|
||||
(OS_OPT ) OSIntQOutPtr->Opt,
|
||||
(CPU_TS ) OSIntQOutPtr->TS,
|
||||
(OS_ERR *)&err);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OS_OBJ_TYPE_SEM:
|
||||
#if OS_CFG_SEM_EN > 0u
|
||||
(void)OS_SemPost((OS_SEM *) OSIntQOutPtr->ObjPtr,
|
||||
(OS_OPT ) OSIntQOutPtr->Opt,
|
||||
(CPU_TS ) OSIntQOutPtr->TS,
|
||||
(OS_ERR *)&err);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OS_OBJ_TYPE_TASK_MSG:
|
||||
#if OS_CFG_TASK_Q_EN > 0u
|
||||
OS_TaskQPost((OS_TCB *) OSIntQOutPtr->ObjPtr,
|
||||
(void *) OSIntQOutPtr->MsgPtr,
|
||||
(OS_MSG_SIZE) OSIntQOutPtr->MsgSize,
|
||||
(OS_OPT ) OSIntQOutPtr->Opt,
|
||||
(CPU_TS ) OSIntQOutPtr->TS,
|
||||
(OS_ERR *)&err);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OS_OBJ_TYPE_TASK_RESUME:
|
||||
#if OS_CFG_TASK_SUSPEND_EN > 0u
|
||||
(void)OS_TaskResume((OS_TCB *) OSIntQOutPtr->ObjPtr,
|
||||
(OS_ERR *)&err);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OS_OBJ_TYPE_TASK_SIGNAL:
|
||||
(void)OS_TaskSemPost((OS_TCB *) OSIntQOutPtr->ObjPtr,
|
||||
(OS_OPT ) OSIntQOutPtr->Opt,
|
||||
(CPU_TS ) OSIntQOutPtr->TS,
|
||||
(OS_ERR *)&err);
|
||||
break;
|
||||
|
||||
case OS_OBJ_TYPE_TASK_SUSPEND:
|
||||
#if OS_CFG_TASK_SUSPEND_EN > 0u
|
||||
(void)OS_TaskSuspend((OS_TCB *) OSIntQOutPtr->ObjPtr,
|
||||
(OS_ERR *)&err);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OS_OBJ_TYPE_TICK:
|
||||
#if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
|
||||
OS_SchedRoundRobin(&OSRdyList[OSPrioSaved]);
|
||||
#endif
|
||||
|
||||
(void)OS_TaskSemPost((OS_TCB *)&OSTickTaskTCB, /* Signal tick task */
|
||||
(OS_OPT ) OS_OPT_POST_NONE,
|
||||
(CPU_TS ) OSIntQOutPtr->TS,
|
||||
(OS_ERR *)&err);
|
||||
#if OS_CFG_TMR_EN > 0u
|
||||
OSTmrUpdateCtr--;
|
||||
if (OSTmrUpdateCtr == (OS_CTR)0u) {
|
||||
OSTmrUpdateCtr = OSTmrUpdateCnt;
|
||||
ts = OS_TS_GET(); /* Get timestamp */
|
||||
(void)OS_TaskSemPost((OS_TCB *)&OSTmrTaskTCB, /* Signal timer task */
|
||||
(OS_OPT ) OS_OPT_POST_NONE,
|
||||
(CPU_TS ) ts,
|
||||
(OS_ERR *)&err);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INTERRUPT QUEUE MANAGEMENT TASK
|
||||
*
|
||||
* Description: This task is created by OS_IntQTaskInit().
|
||||
*
|
||||
* Arguments : p_arg is a pointer to an optional argument that is passed during task creation. For this function
|
||||
* the argument is not used and will be a NULL pointer.
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_IntQTask (void *p_arg)
|
||||
{
|
||||
CPU_BOOLEAN done;
|
||||
CPU_TS ts_start;
|
||||
CPU_TS ts_end;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
p_arg = p_arg; /* Not using 'p_arg', prevent compiler warning */
|
||||
while (DEF_ON) {
|
||||
done = DEF_FALSE;
|
||||
while (done == DEF_FALSE) {
|
||||
CPU_CRITICAL_ENTER();
|
||||
if (OSIntQNbrEntries == (OS_OBJ_QTY)0u) {
|
||||
OSRdyList[0].NbrEntries = (OS_OBJ_QTY)0u; /* Remove from ready list */
|
||||
OSRdyList[0].HeadPtr = (OS_TCB *)0;
|
||||
OSRdyList[0].TailPtr = (OS_TCB *)0;
|
||||
OS_PrioRemove(0u); /* Remove from the priority table */
|
||||
CPU_CRITICAL_EXIT();
|
||||
OSSched();
|
||||
done = DEF_TRUE; /* No more entries in the queue, we are done */
|
||||
} else {
|
||||
CPU_CRITICAL_EXIT();
|
||||
ts_start = OS_TS_GET();
|
||||
OS_IntQRePost();
|
||||
ts_end = OS_TS_GET() - ts_start; /* Measure execution time of tick task */
|
||||
if (OSIntQTaskTimeMax < ts_end) {
|
||||
OSIntQTaskTimeMax = ts_end;
|
||||
}
|
||||
CPU_CRITICAL_ENTER();
|
||||
OSIntQOutPtr = OSIntQOutPtr->NextPtr; /* Point to next item in the ISR queue */
|
||||
OSIntQNbrEntries--;
|
||||
CPU_CRITICAL_EXIT();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INITIALIZE THE ISR QUEUE
|
||||
*
|
||||
* Description: This function is called by OSInit() to initialize the ISR queue.
|
||||
*
|
||||
* Arguments : p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_INT_Q If you didn't provide an ISR queue in OS_CFG.C
|
||||
* OS_ERR_INT_Q_SIZE If you didn't specify a large enough ISR queue.
|
||||
* OS_ERR_STK_INVALID If you specified a NULL pointer for the task of the ISR task
|
||||
* handler
|
||||
* OS_ERR_STK_SIZE_INVALID If you didn't specify a stack size greater than the minimum
|
||||
* specified by OS_CFG_STK_SIZE_MIN
|
||||
* OS_ERR_??? An error code returned by OSTaskCreate().
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_IntQTaskInit (OS_ERR *p_err)
|
||||
{
|
||||
OS_INT_Q *p_int_q;
|
||||
OS_INT_Q *p_int_q_next;
|
||||
OS_OBJ_QTY i;
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
OSIntQOvfCtr = (OS_QTY)0u; /* Clear the ISR queue overflow counter */
|
||||
|
||||
if (OSCfg_IntQBasePtr == (OS_INT_Q *)0) {
|
||||
*p_err = OS_ERR_INT_Q;
|
||||
return;
|
||||
}
|
||||
|
||||
if (OSCfg_IntQSize < (OS_OBJ_QTY)2u) {
|
||||
*p_err = OS_ERR_INT_Q_SIZE;
|
||||
return;
|
||||
}
|
||||
|
||||
OSIntQTaskTimeMax = (CPU_TS)0;
|
||||
|
||||
p_int_q = OSCfg_IntQBasePtr; /* Initialize the circular ISR queue */
|
||||
p_int_q_next = p_int_q;
|
||||
p_int_q_next++;
|
||||
for (i = 0u; i < OSCfg_IntQSize; i++) {
|
||||
p_int_q->Type = OS_OBJ_TYPE_NONE;
|
||||
p_int_q->ObjPtr = (void *)0;
|
||||
p_int_q->MsgPtr = (void *)0;
|
||||
p_int_q->MsgSize = (OS_MSG_SIZE)0u;
|
||||
p_int_q->Flags = (OS_FLAGS )0u;
|
||||
p_int_q->Opt = (OS_OPT )0u;
|
||||
p_int_q->NextPtr = p_int_q_next;
|
||||
p_int_q++;
|
||||
p_int_q_next++;
|
||||
}
|
||||
p_int_q--;
|
||||
p_int_q_next = OSCfg_IntQBasePtr;
|
||||
p_int_q->NextPtr = p_int_q_next;
|
||||
OSIntQInPtr = p_int_q_next;
|
||||
OSIntQOutPtr = p_int_q_next;
|
||||
OSIntQNbrEntries = (OS_OBJ_QTY)0u;
|
||||
OSIntQNbrEntriesMax = (OS_OBJ_QTY)0u;
|
||||
|
||||
/* -------------- CREATE THE ISR QUEUE TASK ------------- */
|
||||
if (OSCfg_IntQTaskStkBasePtr == (CPU_STK *)0) {
|
||||
*p_err = OS_ERR_INT_Q_STK_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
if (OSCfg_IntQTaskStkSize < OSCfg_StkSizeMin) {
|
||||
*p_err = OS_ERR_INT_Q_STK_SIZE_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
OSTaskCreate((OS_TCB *)&OSIntQTaskTCB,
|
||||
(CPU_CHAR *)((void *)"uC/OS-III ISR Queue Task"),
|
||||
(OS_TASK_PTR )OS_IntQTask,
|
||||
(void *)0,
|
||||
(OS_PRIO )0u, /* This task is ALWAYS at priority '0' (i.e. highest) */
|
||||
(CPU_STK *)OSCfg_IntQTaskStkBasePtr,
|
||||
(CPU_STK_SIZE)OSCfg_IntQTaskStkLimit,
|
||||
(CPU_STK_SIZE)OSCfg_IntQTaskStkSize,
|
||||
(OS_MSG_QTY )0u,
|
||||
(OS_TICK )0u,
|
||||
(void *)0,
|
||||
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
|
||||
(OS_ERR *)p_err);
|
||||
}
|
||||
|
||||
#endif
|
||||
347
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_mem.c
Normal file
347
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_mem.c
Normal file
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* MEMORY PARTITION MANAGEMENT
|
||||
*
|
||||
* File : OS_MEM.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_mem__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
|
||||
#if OS_CFG_MEM_EN > 0u
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* CREATE A MEMORY PARTITION
|
||||
*
|
||||
* Description : Create a fixed-sized memory partition that will be managed by uC/OS-III.
|
||||
*
|
||||
* Arguments : p_mem is a pointer to a memory partition control block which is allocated in user memory space.
|
||||
*
|
||||
* p_name is a pointer to an ASCII string to provide a name to the memory partition.
|
||||
*
|
||||
* p_addr is the starting address of the memory partition
|
||||
*
|
||||
* n_blks is the number of memory blocks to create from the partition.
|
||||
*
|
||||
* blk_size is the size (in bytes) of each block in the memory partition.
|
||||
*
|
||||
* p_err 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_ILLEGAL_CREATE_RUN_TIME if you are trying to create the memory partition after you
|
||||
* called OSSafetyCriticalStart().
|
||||
* OS_ERR_MEM_INVALID_BLKS user specified an invalid number of blocks (must be >= 2)
|
||||
* OS_ERR_MEM_INVALID_P_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_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 : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSMemCreate (OS_MEM *p_mem,
|
||||
CPU_CHAR *p_name,
|
||||
void *p_addr,
|
||||
OS_MEM_QTY n_blks,
|
||||
OS_MEM_SIZE blk_size,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
CPU_DATA align_msk;
|
||||
#endif
|
||||
OS_MEM_QTY i;
|
||||
OS_MEM_QTY loops;
|
||||
CPU_INT08U *p_blk;
|
||||
void **p_link;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL_IEC61508
|
||||
if (OSSafetyCriticalStartFlag == DEF_TRUE) {
|
||||
*p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
|
||||
*p_err = OS_ERR_MEM_CREATE_ISR;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_addr == (void *)0) { /* Must pass a valid address for the memory part. */
|
||||
*p_err = OS_ERR_MEM_INVALID_P_ADDR;
|
||||
return;
|
||||
}
|
||||
if (n_blks < (OS_MEM_QTY)2) { /* Must have at least 2 blocks per partition */
|
||||
*p_err = OS_ERR_MEM_INVALID_BLKS;
|
||||
return;
|
||||
}
|
||||
if (blk_size < sizeof(void *)) { /* Must contain space for at least a pointer */
|
||||
*p_err = OS_ERR_MEM_INVALID_SIZE;
|
||||
return;
|
||||
}
|
||||
align_msk = sizeof(void *) - 1u;
|
||||
if (align_msk > 0u) {
|
||||
if (((CPU_ADDR)p_addr & align_msk) != 0u){ /* Must be pointer size aligned */
|
||||
*p_err = OS_ERR_MEM_INVALID_P_ADDR;
|
||||
return;
|
||||
}
|
||||
if ((blk_size & align_msk) != 0u) { /* Block size must be a multiple address size */
|
||||
*p_err = OS_ERR_MEM_INVALID_SIZE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
p_link = (void **)p_addr; /* Create linked list of free memory blocks */
|
||||
p_blk = (CPU_INT08U *)p_addr;
|
||||
loops = n_blks - 1u;
|
||||
for (i = 0u; i < loops; i++) {
|
||||
p_blk += blk_size;
|
||||
*p_link = (void *)p_blk; /* Save pointer to NEXT block in CURRENT block */
|
||||
p_link = (void **)(void *)p_blk; /* Position to NEXT block */
|
||||
}
|
||||
*p_link = (void *)0; /* Last memory block points to NULL */
|
||||
|
||||
OS_CRITICAL_ENTER();
|
||||
p_mem->Type = OS_OBJ_TYPE_MEM; /* Set the type of object */
|
||||
p_mem->NamePtr = p_name; /* Save name of memory partition */
|
||||
p_mem->AddrPtr = p_addr; /* Store start address of memory partition */
|
||||
p_mem->FreeListPtr = p_addr; /* Initialize pointer to pool of free blocks */
|
||||
p_mem->NbrFree = n_blks; /* Store number of free blocks in MCB */
|
||||
p_mem->NbrMax = n_blks;
|
||||
p_mem->BlkSize = blk_size; /* Store block size of each memory blocks */
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OS_MemDbgListAdd(p_mem);
|
||||
#endif
|
||||
|
||||
OSMemQty++;
|
||||
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* GET A MEMORY BLOCK
|
||||
*
|
||||
* Description : Get a memory block from a partition
|
||||
*
|
||||
* Arguments : p_mem is a pointer to the memory partition control block
|
||||
*
|
||||
* p_err 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_P_MEM if you passed a NULL pointer for 'p_mem'
|
||||
* OS_ERR_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to the caller
|
||||
*
|
||||
* 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 *p_mem,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
void *p_blk;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((void *)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_mem == (OS_MEM *)0) { /* Must point to a valid memory partition */
|
||||
*p_err = OS_ERR_MEM_INVALID_P_MEM;
|
||||
return ((void *)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
if (p_mem->NbrFree == (OS_MEM_QTY)0) { /* See if there are any free memory blocks */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_MEM_NO_FREE_BLKS; /* No, Notify caller of empty memory partition */
|
||||
return ((void *)0); /* Return NULL pointer to caller */
|
||||
}
|
||||
p_blk = p_mem->FreeListPtr; /* Yes, point to next free memory block */
|
||||
p_mem->FreeListPtr = *(void **)p_blk; /* Adjust pointer to new free list */
|
||||
p_mem->NbrFree--; /* One less memory block in this partition */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE; /* No error */
|
||||
return (p_blk); /* Return memory block to caller */
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* RELEASE A MEMORY BLOCK
|
||||
*
|
||||
* Description : Returns a memory block to a partition
|
||||
*
|
||||
* Arguments : p_mem is a pointer to the memory partition control block
|
||||
*
|
||||
* p_blk is a pointer to the memory block being released.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* 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_P_BLK if you passed a NULL pointer for the block to release.
|
||||
* OS_ERR_MEM_INVALID_P_MEM if you passed a NULL pointer for 'p_mem'
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSMemPut (OS_MEM *p_mem,
|
||||
void *p_blk,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_mem == (OS_MEM *)0) { /* Must point to a valid memory partition */
|
||||
*p_err = OS_ERR_MEM_INVALID_P_MEM;
|
||||
return;
|
||||
}
|
||||
if (p_blk == (void *)0) { /* Must release a valid block */
|
||||
*p_err = OS_ERR_MEM_INVALID_P_BLK;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
if (p_mem->NbrFree >= p_mem->NbrMax) { /* Make sure all blocks not already returned */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_MEM_FULL;
|
||||
return;
|
||||
}
|
||||
*(void **)p_blk = p_mem->FreeListPtr; /* Insert released block into free block list */
|
||||
p_mem->FreeListPtr = p_blk;
|
||||
p_mem->NbrFree++; /* One more memory block in this partition */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE; /* Notify caller that memory block was released */
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* ADD MEMORY PARTITION TO DEBUG LIST
|
||||
*
|
||||
* Description : This function is called by OSMemCreate() to add the memory partition to the debug table.
|
||||
*
|
||||
* Arguments : p_mem Is a pointer to the memory partition
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
void OS_MemDbgListAdd (OS_MEM *p_mem)
|
||||
{
|
||||
p_mem->DbgPrevPtr = (OS_MEM *)0;
|
||||
if (OSMemDbgListPtr == (OS_MEM *)0) {
|
||||
p_mem->DbgNextPtr = (OS_MEM *)0;
|
||||
} else {
|
||||
p_mem->DbgNextPtr = OSMemDbgListPtr;
|
||||
OSMemDbgListPtr->DbgPrevPtr = p_mem;
|
||||
}
|
||||
OSMemDbgListPtr = p_mem;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INITIALIZE MEMORY PARTITION MANAGER
|
||||
*
|
||||
* Description : This function is called by uC/OS-III 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-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_MemInit (OS_ERR *p_err)
|
||||
{
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OSMemDbgListPtr = (OS_MEM *)0;
|
||||
#endif
|
||||
|
||||
OSMemQty = (OS_OBJ_QTY)0;
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
#endif
|
||||
349
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_msg.c
Normal file
349
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_msg.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* MESSAGE HANDLING SERVICES
|
||||
*
|
||||
* File : OS_MSG.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_msg__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
|
||||
#if OS_MSG_EN > 0u
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INITIALIZE THE POOL OF 'OS_MSG'
|
||||
*
|
||||
* Description: This function is called by OSInit() to initialize the free list of OS_MSGs.
|
||||
*
|
||||
* Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_MSG_POOL_NULL_PTR
|
||||
* OS_ERR_MSG_POOL_EMPTY
|
||||
* OS_ERR_NONE
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_MsgPoolInit (OS_ERR *p_err)
|
||||
{
|
||||
OS_MSG *p_msg1;
|
||||
OS_MSG *p_msg2;
|
||||
OS_MSG_QTY i;
|
||||
OS_MSG_QTY loops;
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (OSCfg_MsgPoolBasePtr == (OS_MSG *)0) {
|
||||
*p_err = OS_ERR_MSG_POOL_NULL_PTR;
|
||||
return;
|
||||
}
|
||||
if (OSCfg_MsgPoolSize == (OS_MSG_QTY)0) {
|
||||
*p_err = OS_ERR_MSG_POOL_EMPTY;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
p_msg1 = OSCfg_MsgPoolBasePtr;
|
||||
p_msg2 = OSCfg_MsgPoolBasePtr;
|
||||
p_msg2++;
|
||||
loops = OSCfg_MsgPoolSize - 1u;
|
||||
for (i = 0u; i < loops; i++) { /* Init. list of free OS_MSGs */
|
||||
p_msg1->NextPtr = p_msg2;
|
||||
p_msg1->MsgPtr = (void *)0;
|
||||
p_msg1->MsgSize = (OS_MSG_SIZE)0u;
|
||||
p_msg1->MsgTS = (CPU_TS )0u;
|
||||
p_msg1++;
|
||||
p_msg2++;
|
||||
}
|
||||
p_msg1->NextPtr = (OS_MSG *)0; /* Last OS_MSG */
|
||||
p_msg1->MsgPtr = (void *)0;
|
||||
p_msg1->MsgSize = (OS_MSG_SIZE)0u;
|
||||
p_msg1->MsgTS = (CPU_TS )0u;
|
||||
|
||||
OSMsgPool.NextPtr = OSCfg_MsgPoolBasePtr;
|
||||
OSMsgPool.NbrFree = OSCfg_MsgPoolSize;
|
||||
OSMsgPool.NbrUsed = (OS_MSG_QTY)0;
|
||||
OSMsgPool.NbrUsedMax = (OS_MSG_QTY)0;
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* RELEASE ALL MESSAGE IN MESSAGE QUEUE
|
||||
*
|
||||
* Description: This function returns all the messages in a message queue to the free list.
|
||||
*
|
||||
* Arguments : p_msg_q is a pointer to the OS_MSG_Q structure containing messages to free.
|
||||
* -------
|
||||
*
|
||||
* Returns : the number of OS_MSGs returned to the free list
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
OS_MSG_QTY OS_MsgQFreeAll (OS_MSG_Q *p_msg_q)
|
||||
{
|
||||
OS_MSG *p_msg;
|
||||
OS_MSG_QTY qty;
|
||||
|
||||
|
||||
|
||||
qty = p_msg_q->NbrEntries; /* Get the number of OS_MSGs being freed */
|
||||
if (p_msg_q->NbrEntries > (OS_MSG_QTY)0) {
|
||||
p_msg = p_msg_q->InPtr; /* Point to end of message chain */
|
||||
p_msg->NextPtr = OSMsgPool.NextPtr;
|
||||
OSMsgPool.NextPtr = p_msg_q->OutPtr; /* Point to beginning of message chain */
|
||||
OSMsgPool.NbrUsed -= p_msg_q->NbrEntries; /* Update statistics for free list of messages */
|
||||
OSMsgPool.NbrFree += p_msg_q->NbrEntries;
|
||||
p_msg_q->NbrEntries = (OS_MSG_QTY)0; /* Flush the message queue */
|
||||
p_msg_q->NbrEntriesMax = (OS_MSG_QTY)0;
|
||||
p_msg_q->InPtr = (OS_MSG *)0;
|
||||
p_msg_q->OutPtr = (OS_MSG *)0;
|
||||
}
|
||||
return (qty);
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INITIALIZE A MESSAGE QUEUE
|
||||
*
|
||||
* Description: This function is called to initialize a message queue
|
||||
*
|
||||
* Arguments : p_msg_q is a pointer to the message queue to initialize
|
||||
* -------
|
||||
*
|
||||
* max is the maximum number of entries that a message queue can have.
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_MsgQInit (OS_MSG_Q *p_msg_q,
|
||||
OS_MSG_QTY size)
|
||||
{
|
||||
p_msg_q->NbrEntriesSize = (OS_MSG_QTY)size;
|
||||
p_msg_q->NbrEntries = (OS_MSG_QTY)0;
|
||||
p_msg_q->NbrEntriesMax = (OS_MSG_QTY)0;
|
||||
p_msg_q->InPtr = (OS_MSG *)0;
|
||||
p_msg_q->OutPtr = (OS_MSG *)0;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* RETRIEVE MESSAGE FROM MESSAGE QUEUE
|
||||
*
|
||||
* Description: This function retrieves a message from a message queue
|
||||
*
|
||||
* Arguments : p_msg_q is a pointer to the message queue where we want to extract the message from
|
||||
* -------
|
||||
*
|
||||
* p_msg_size is a pointer to where the size (in bytes) of the message will be placed
|
||||
*
|
||||
* p_ts is a pointer to where the time stamp will be placed
|
||||
*
|
||||
* p_err is a pointer to an error code that will be returned from this call.
|
||||
*
|
||||
* OS_ERR_Q_EMPTY
|
||||
* OS_ERR_NONE
|
||||
*
|
||||
* Returns : The message (a pointer)
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void *OS_MsgQGet (OS_MSG_Q *p_msg_q,
|
||||
OS_MSG_SIZE *p_msg_size,
|
||||
CPU_TS *p_ts,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_MSG *p_msg;
|
||||
void *p_void;
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((void *)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_msg_q->NbrEntries == (OS_MSG_QTY)0) { /* Is the queue empty? */
|
||||
*p_msg_size = (OS_MSG_SIZE)0; /* Yes */
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = (CPU_TS )0;
|
||||
}
|
||||
*p_err = OS_ERR_Q_EMPTY;
|
||||
return ((void *)0);
|
||||
}
|
||||
|
||||
p_msg = p_msg_q->OutPtr; /* No, get the next message to extract from the queue */
|
||||
p_void = p_msg->MsgPtr;
|
||||
*p_msg_size = p_msg->MsgSize;
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = p_msg->MsgTS;
|
||||
}
|
||||
|
||||
p_msg_q->OutPtr = p_msg->NextPtr; /* Point to next message to extract */
|
||||
|
||||
if (p_msg_q->OutPtr == (OS_MSG *)0) { /* Are there any more messages in the queue? */
|
||||
p_msg_q->InPtr = (OS_MSG *)0; /* No */
|
||||
p_msg_q->NbrEntries = (OS_MSG_QTY)0;
|
||||
} else {
|
||||
p_msg_q->NbrEntries--; /* Yes, One less message in the queue */
|
||||
}
|
||||
|
||||
p_msg->NextPtr = OSMsgPool.NextPtr; /* Return message control block to free list */
|
||||
OSMsgPool.NextPtr = p_msg;
|
||||
OSMsgPool.NbrFree++;
|
||||
OSMsgPool.NbrUsed--;
|
||||
|
||||
*p_err = OS_ERR_NONE;
|
||||
return (p_void);
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* DEPOSIT MESSAGE IN MESSAGE QUEUE
|
||||
*
|
||||
* Description: This function places a message in a message queue
|
||||
*
|
||||
* Arguments : p_msg_q is a pointer to the OS_TCB of the task to post the message to
|
||||
* -------
|
||||
*
|
||||
* p_void is a pointer to the message to send.
|
||||
*
|
||||
* msg_size is the size of the message (in bytes)
|
||||
*
|
||||
* opt specifies whether the message will be posted in FIFO or LIFO order
|
||||
*
|
||||
* OS_OPT_POST_FIFO
|
||||
* OS_OPT_POST_LIFO
|
||||
*
|
||||
* ts is a timestamp as to when the message was posted
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_Q_MAX if the queue is full
|
||||
* OS_ERR_MSG_POOL_EMPTY if we no longer have any OS_MSG to use
|
||||
* OS_ERR_NONE the message was deposited in the queue
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_MsgQPut (OS_MSG_Q *p_msg_q,
|
||||
void *p_void,
|
||||
OS_MSG_SIZE msg_size,
|
||||
OS_OPT opt,
|
||||
CPU_TS ts,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_MSG *p_msg;
|
||||
OS_MSG *p_msg_in;
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_msg_q->NbrEntries >= p_msg_q->NbrEntriesSize) {
|
||||
*p_err = OS_ERR_Q_MAX; /* Message queue cannot accept any more messages */
|
||||
return;
|
||||
}
|
||||
|
||||
if (OSMsgPool.NbrFree == (OS_MSG_QTY)0) {
|
||||
*p_err = OS_ERR_MSG_POOL_EMPTY; /* No more OS_MSG to use */
|
||||
return;
|
||||
}
|
||||
|
||||
p_msg = OSMsgPool.NextPtr; /* Remove message control block from free list */
|
||||
OSMsgPool.NextPtr = p_msg->NextPtr;
|
||||
OSMsgPool.NbrFree--;
|
||||
OSMsgPool.NbrUsed++;
|
||||
if (OSMsgPool.NbrUsedMax < OSMsgPool.NbrUsed) {
|
||||
OSMsgPool.NbrUsedMax = OSMsgPool.NbrUsed;
|
||||
}
|
||||
|
||||
if (p_msg_q->NbrEntries == (OS_MSG_QTY)0) { /* Is this first message placed in the queue? */
|
||||
p_msg_q->InPtr = p_msg; /* Yes */
|
||||
p_msg_q->OutPtr = p_msg;
|
||||
p_msg_q->NbrEntries = (OS_MSG_QTY)1;
|
||||
p_msg->NextPtr = (OS_MSG *)0;
|
||||
} else { /* No */
|
||||
if ((opt & OS_OPT_POST_LIFO) == OS_OPT_POST_FIFO) { /* Is it FIFO or LIFO? */
|
||||
p_msg_in = p_msg_q->InPtr; /* FIFO, add to the head */
|
||||
p_msg_in->NextPtr = p_msg;
|
||||
p_msg_q->InPtr = p_msg;
|
||||
p_msg->NextPtr = (OS_MSG *)0;
|
||||
} else {
|
||||
p_msg->NextPtr = p_msg_q->OutPtr; /* LIFO, add to the tail */
|
||||
p_msg_q->OutPtr = p_msg;
|
||||
}
|
||||
p_msg_q->NbrEntries++;
|
||||
}
|
||||
if (p_msg_q->NbrEntriesMax < p_msg_q->NbrEntries) {
|
||||
p_msg_q->NbrEntriesMax = p_msg_q->NbrEntries;
|
||||
}
|
||||
p_msg->MsgPtr = p_void; /* Deposit message in the message queue entry */
|
||||
p_msg->MsgSize = msg_size;
|
||||
p_msg->MsgTS = ts;
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
#endif
|
||||
874
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_mutex.c
Normal file
874
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_mutex.c
Normal file
@@ -0,0 +1,874 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* MUTEX MANAGEMENT
|
||||
*
|
||||
* File : OS_MUTEX.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_mutex__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
|
||||
#if OS_CFG_MUTEX_EN > 0u
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* CREATE A MUTEX
|
||||
*
|
||||
* Description: This function creates a mutex.
|
||||
*
|
||||
* Arguments : p_mutex is a pointer to the mutex to initialize. Your application is responsible for allocating
|
||||
* storage for the mutex.
|
||||
*
|
||||
* p_name is a pointer to the name you would like to give the mutex.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE if the call was successful
|
||||
* OS_ERR_CREATE_ISR if you called this function from an ISR
|
||||
* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the Mutex after you called
|
||||
* OSSafetyCriticalStart().
|
||||
* OS_ERR_NAME if 'p_name' is a NULL pointer
|
||||
* OS_ERR_OBJ_CREATED if the mutex has already been created
|
||||
* OS_ERR_OBJ_PTR_NULL if 'p_mutex' is a NULL pointer
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSMutexCreate (OS_MUTEX *p_mutex,
|
||||
CPU_CHAR *p_name,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL_IEC61508
|
||||
if (OSSafetyCriticalStartFlag == DEF_TRUE) {
|
||||
*p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to be called from an ISR */
|
||||
*p_err = OS_ERR_CREATE_ISR;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
OS_CRITICAL_ENTER();
|
||||
p_mutex->Type = OS_OBJ_TYPE_MUTEX; /* Mark the data structure as a mutex */
|
||||
p_mutex->NamePtr = p_name;
|
||||
p_mutex->OwnerTCBPtr = (OS_TCB *)0;
|
||||
p_mutex->OwnerNestingCtr = (OS_NESTING_CTR)0; /* Mutex is available */
|
||||
p_mutex->TS = (CPU_TS )0;
|
||||
p_mutex->OwnerOriginalPrio = OS_CFG_PRIO_MAX;
|
||||
OS_PendListInit(&p_mutex->PendList); /* Initialize the waiting list */
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OS_MutexDbgListAdd(p_mutex);
|
||||
#endif
|
||||
OSMutexQty++;
|
||||
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* DELETE A MUTEX
|
||||
*
|
||||
* Description: This function deletes a mutex and readies all tasks pending on the mutex.
|
||||
*
|
||||
* Arguments : p_mutex is a pointer to the mutex to delete
|
||||
*
|
||||
* opt determines delete options as follows:
|
||||
*
|
||||
* OS_OPT_DEL_NO_PEND Delete mutex ONLY if no task pending
|
||||
* OS_OPT_DEL_ALWAYS Deletes the mutex even if tasks are waiting.
|
||||
* In this case, all the tasks pending will be readied.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* 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_OBJ_PTR_NULL If 'p_mutex' is a NULL pointer.
|
||||
* OS_ERR_OBJ_TYPE If 'p_mutex' is not pointing to a mutex
|
||||
* OS_ERR_OPT_INVALID An invalid option was specified
|
||||
* OS_ERR_STATE_INVALID Task is in an invalid state
|
||||
* OS_ERR_TASK_WAITING One or more tasks were waiting on the mutex
|
||||
*
|
||||
* Returns : == 0 if no tasks were waiting on the mutex, or upon error.
|
||||
* > 0 if one or more tasks waiting on the mutex are now readied and informed.
|
||||
*
|
||||
* 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) OSMutexAccept() callers will not know that the intended mutex has been deleted.
|
||||
*
|
||||
* 3) Because ALL tasks pending on the mutex will be readied, you MUST be careful in applications where the
|
||||
* mutex is used for mutual exclusion because the resource(s) will no longer be guarded by the mutex.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#if OS_CFG_MUTEX_DEL_EN > 0u
|
||||
OS_OBJ_QTY OSMutexDel (OS_MUTEX *p_mutex,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_OBJ_QTY cnt;
|
||||
OS_OBJ_QTY nbr_tasks;
|
||||
OS_PEND_DATA *p_pend_data;
|
||||
OS_PEND_LIST *p_pend_list;
|
||||
OS_TCB *p_tcb;
|
||||
OS_TCB *p_tcb_owner;
|
||||
CPU_TS ts;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to delete a mutex from an ISR */
|
||||
*p_err = OS_ERR_DEL_ISR;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
switch (opt) { /* Validate 'opt' */
|
||||
case OS_OPT_DEL_NO_PEND:
|
||||
case OS_OPT_DEL_ALWAYS:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_mutex->Type != OS_OBJ_TYPE_MUTEX) { /* Make sure mutex was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
OS_CRITICAL_ENTER();
|
||||
p_pend_list = &p_mutex->PendList;
|
||||
cnt = p_pend_list->NbrEntries;
|
||||
nbr_tasks = cnt;
|
||||
switch (opt) {
|
||||
case OS_OPT_DEL_NO_PEND: /* Delete mutex only if no task waiting */
|
||||
if (nbr_tasks == (OS_OBJ_QTY)0) {
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OS_MutexDbgListRemove(p_mutex);
|
||||
#endif
|
||||
OSMutexQty--;
|
||||
OS_MutexClr(p_mutex);
|
||||
OS_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
} else {
|
||||
OS_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_TASK_WAITING;
|
||||
}
|
||||
break;
|
||||
|
||||
case OS_OPT_DEL_ALWAYS: /* Always delete the mutex */
|
||||
p_tcb_owner = p_mutex->OwnerTCBPtr; /* Did we had to change the prio of owner? */
|
||||
if ((p_tcb_owner != (OS_TCB *)0) &&
|
||||
(p_tcb_owner->Prio != p_mutex->OwnerOriginalPrio)) {
|
||||
switch (p_tcb_owner->TaskState) { /* yes */
|
||||
case OS_TASK_STATE_RDY:
|
||||
OS_RdyListRemove(p_tcb_owner);
|
||||
p_tcb_owner->Prio = p_mutex->OwnerOriginalPrio; /* Lower owner's prio back */
|
||||
OS_PrioInsert(p_tcb_owner->Prio);
|
||||
OS_RdyListInsertTail(p_tcb_owner); /* Insert owner in ready list at new prio */
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_DLY:
|
||||
case OS_TASK_STATE_SUSPENDED:
|
||||
case OS_TASK_STATE_DLY_SUSPENDED:
|
||||
p_tcb_owner->Prio = p_mutex->OwnerOriginalPrio; /* Not in any pend list, change the prio */
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_PEND:
|
||||
case OS_TASK_STATE_PEND_TIMEOUT:
|
||||
case OS_TASK_STATE_PEND_SUSPENDED:
|
||||
case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
|
||||
OS_PendListChangePrio(p_tcb_owner, /* Owner is pending on another object */
|
||||
p_mutex->OwnerOriginalPrio);
|
||||
break;
|
||||
|
||||
default:
|
||||
OS_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_STATE_INVALID;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
}
|
||||
|
||||
ts = OS_TS_GET(); /* Get timestamp */
|
||||
while (cnt > 0u) { /* Remove all tasks from the pend list */
|
||||
p_pend_data = p_pend_list->HeadPtr;
|
||||
p_tcb = p_pend_data->TCBPtr;
|
||||
OS_PendObjDel((OS_PEND_OBJ *)((void *)p_mutex),
|
||||
p_tcb,
|
||||
ts);
|
||||
cnt--;
|
||||
}
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OS_MutexDbgListRemove(p_mutex);
|
||||
#endif
|
||||
OSMutexQty--;
|
||||
OS_MutexClr(p_mutex);
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
OSSched(); /* Find highest priority task ready to run */
|
||||
*p_err = OS_ERR_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
OS_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
break;
|
||||
}
|
||||
return (nbr_tasks);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* PEND ON MUTEX
|
||||
*
|
||||
* Description: This function waits for a mutex.
|
||||
*
|
||||
* Arguments : p_mutex is a pointer to the 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 (in 'ticks') specified by this argument. If you specify
|
||||
* 0, however, your task will wait forever at the specified mutex or, until the resource
|
||||
* becomes available.
|
||||
*
|
||||
* opt determines whether the user wants to block if the mutex is not available or not:
|
||||
*
|
||||
* OS_OPT_PEND_BLOCKING
|
||||
* OS_OPT_PEND_NON_BLOCKING
|
||||
*
|
||||
* p_ts is a pointer to a variable that will receive the timestamp of when the mutex was posted or
|
||||
* pend aborted or the mutex deleted. If you pass a NULL pointer (i.e. (CPU_TS *)0) then you
|
||||
* will not get the timestamp. In other words, passing a NULL pointer is valid and indicates
|
||||
* that you don't need the timestamp.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE The call was successful and your task owns the resource
|
||||
* OS_ERR_MUTEX_OWNER If calling task already owns the mutex
|
||||
* OS_ERR_OBJ_DEL If 'p_mutex' was deleted
|
||||
* OS_ERR_OBJ_PTR_NULL If 'p_mutex' is a NULL pointer.
|
||||
* OS_ERR_OBJ_TYPE If 'p_mutex' is not pointing at a mutex
|
||||
* OS_ERR_OPT_INVALID If you didn't specify a valid option
|
||||
* OS_ERR_PEND_ABORT If the pend was aborted by another task
|
||||
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
|
||||
* would lead to a suspension.
|
||||
* OS_ERR_PEND_WOULD_BLOCK If you specified non-blocking but the mutex was not
|
||||
* available.
|
||||
* OS_ERR_SCHED_LOCKED If you called this function when the scheduler is locked
|
||||
* OS_ERR_STATE_INVALID If the task is in an invalid state
|
||||
* OS_ERR_STATUS_INVALID If the pend status has an invalid value
|
||||
* OS_ERR_TIMEOUT The mutex was not received within the specified timeout.
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSMutexPend (OS_MUTEX *p_mutex,
|
||||
OS_TICK timeout,
|
||||
OS_OPT opt,
|
||||
CPU_TS *p_ts,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_PEND_DATA pend_data;
|
||||
OS_TCB *p_tcb;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
|
||||
*p_err = OS_ERR_PEND_ISR;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_mutex == (OS_MUTEX *)0) { /* Validate arguments */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return;
|
||||
}
|
||||
switch (opt) { /* Validate 'opt' */
|
||||
case OS_OPT_PEND_BLOCKING:
|
||||
case OS_OPT_PEND_NON_BLOCKING:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_mutex->Type != OS_OBJ_TYPE_MUTEX) { /* Make sure mutex was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = (CPU_TS )0; /* Initialize the returned timestamp */
|
||||
}
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
if (p_mutex->OwnerNestingCtr == (OS_NESTING_CTR)0) { /* Resource available? */
|
||||
p_mutex->OwnerTCBPtr = OSTCBCurPtr; /* Yes, caller may proceed */
|
||||
p_mutex->OwnerOriginalPrio = OSTCBCurPtr->Prio;
|
||||
p_mutex->OwnerNestingCtr = (OS_NESTING_CTR)1;
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = p_mutex->TS;
|
||||
}
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (OSTCBCurPtr == p_mutex->OwnerTCBPtr) { /* See if current task is already the owner of the mutex */
|
||||
p_mutex->OwnerNestingCtr++;
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = p_mutex->TS;
|
||||
}
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_MUTEX_OWNER; /* Indicate that current task already owns the mutex */
|
||||
return;
|
||||
}
|
||||
|
||||
if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
|
||||
return;
|
||||
} else {
|
||||
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend when the scheduler is locked */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_SCHED_LOCKED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Lock the scheduler/re-enable interrupts */
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
p_tcb = p_mutex->OwnerTCBPtr; /* Point to the TCB of the Mutex owner */
|
||||
if (p_tcb->Prio > OSTCBCurPtr->Prio) { /* See if mutex owner has a lower priority than current */
|
||||
switch (p_tcb->TaskState) {
|
||||
case OS_TASK_STATE_RDY:
|
||||
OS_RdyListRemove(p_tcb); /* Remove from ready list at current priority */
|
||||
p_tcb->Prio = OSTCBCurPtr->Prio; /* Raise owner's priority */
|
||||
OS_PrioInsert(p_tcb->Prio);
|
||||
OS_RdyListInsertHead(p_tcb); /* Insert in ready list at new priority */
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_DLY:
|
||||
case OS_TASK_STATE_DLY_SUSPENDED:
|
||||
case OS_TASK_STATE_SUSPENDED:
|
||||
p_tcb->Prio = OSTCBCurPtr->Prio; /* Only need to raise the owner's priority */
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_PEND: /* Change the position of the task in the wait list */
|
||||
case OS_TASK_STATE_PEND_TIMEOUT:
|
||||
case OS_TASK_STATE_PEND_SUSPENDED:
|
||||
case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
|
||||
OS_PendListChangePrio(p_tcb,
|
||||
OSTCBCurPtr->Prio);
|
||||
break;
|
||||
|
||||
default:
|
||||
OS_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_STATE_INVALID;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
OS_Pend(&pend_data, /* Block task pending on Mutex */
|
||||
(OS_PEND_OBJ *)((void *)p_mutex),
|
||||
OS_TASK_PEND_ON_MUTEX,
|
||||
timeout);
|
||||
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
|
||||
OSSched(); /* Find the next highest priority task ready to run */
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
switch (OSTCBCurPtr->PendStatus) {
|
||||
case OS_STATUS_PEND_OK: /* We got the mutex */
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = OSTCBCurPtr->TS;
|
||||
}
|
||||
*p_err = OS_ERR_NONE;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_ABORT: /* Indicate that we aborted */
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = OSTCBCurPtr->TS;
|
||||
}
|
||||
*p_err = OS_ERR_PEND_ABORT;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get mutex within timeout */
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = (CPU_TS )0;
|
||||
}
|
||||
*p_err = OS_ERR_TIMEOUT;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_DEL: /* Indicate that object pended on has been deleted */
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = OSTCBCurPtr->TS;
|
||||
}
|
||||
*p_err = OS_ERR_OBJ_DEL;
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_STATUS_INVALID;
|
||||
break;
|
||||
}
|
||||
CPU_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* ABORT WAITING ON A MUTEX
|
||||
*
|
||||
* Description: This function aborts & readies any tasks currently waiting on a mutex. This function should be used
|
||||
* to fault-abort the wait on the mutex, rather than to normally signal the mutex via OSMutexPost().
|
||||
*
|
||||
* Arguments : p_mutex is a pointer to the mutex
|
||||
*
|
||||
* opt determines the type of ABORT performed:
|
||||
*
|
||||
* OS_OPT_PEND_ABORT_1 ABORT wait for a single task (HPT) waiting on the mutex
|
||||
* OS_OPT_PEND_ABORT_ALL ABORT wait for ALL tasks that are waiting on the mutex
|
||||
* OS_OPT_POST_NO_SCHED Do not call the scheduler
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE At least one task waiting on the mutex was readied and
|
||||
* informed of the aborted wait; check return value for the
|
||||
* number of tasks whose wait on the mutex was aborted.
|
||||
* OS_ERR_OBJ_PTR_NULL If 'p_mutex' is a NULL pointer.
|
||||
* OS_ERR_OBJ_TYPE If 'p_mutex' is not pointing at a mutex
|
||||
* OS_ERR_OPT_INVALID If you specified an invalid option
|
||||
* OS_ERR_PEND_ABORT_ISR If you attempted to call this function from an ISR
|
||||
* OS_ERR_PEND_ABORT_NONE No task were pending
|
||||
*
|
||||
* Returns : == 0 if no tasks were waiting on the mutex, or upon error.
|
||||
* > 0 if one or more tasks waiting on the mutex are now readied and informed.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#if OS_CFG_MUTEX_PEND_ABORT_EN > 0u
|
||||
OS_OBJ_QTY OSMutexPendAbort (OS_MUTEX *p_mutex,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_PEND_LIST *p_pend_list;
|
||||
OS_TCB *p_tcb;
|
||||
CPU_TS ts;
|
||||
OS_OBJ_QTY nbr_tasks;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to Pend Abort from an ISR */
|
||||
*p_err = OS_ERR_PEND_ABORT_ISR;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
switch (opt) { /* Validate 'opt' */
|
||||
case OS_OPT_PEND_ABORT_1:
|
||||
case OS_OPT_PEND_ABORT_ALL:
|
||||
case OS_OPT_PEND_ABORT_1 | OS_OPT_POST_NO_SCHED:
|
||||
case OS_OPT_PEND_ABORT_ALL | OS_OPT_POST_NO_SCHED:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_mutex->Type != OS_OBJ_TYPE_MUTEX) { /* Make sure mutex was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_pend_list = &p_mutex->PendList;
|
||||
if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0u) { /* Any task waiting on mutex? */
|
||||
CPU_CRITICAL_EXIT(); /* No */
|
||||
*p_err = OS_ERR_PEND_ABORT_NONE;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
nbr_tasks = 0u;
|
||||
ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
|
||||
while (p_pend_list->NbrEntries > (OS_OBJ_QTY)0u) {
|
||||
p_tcb = p_pend_list->HeadPtr->TCBPtr;
|
||||
OS_PendAbort((OS_PEND_OBJ *)((void *)p_mutex),
|
||||
p_tcb,
|
||||
ts);
|
||||
nbr_tasks++;
|
||||
if (opt != OS_OPT_PEND_ABORT_ALL) { /* Pend abort all tasks waiting? */
|
||||
break; /* No */
|
||||
}
|
||||
}
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
|
||||
if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0u) {
|
||||
OSSched(); /* Run the scheduler */
|
||||
}
|
||||
|
||||
*p_err = OS_ERR_NONE;
|
||||
return (nbr_tasks);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* POST TO A MUTEX
|
||||
*
|
||||
* Description: This function signals a mutex
|
||||
*
|
||||
* Arguments : p_mutex is a pointer to the mutex
|
||||
*
|
||||
* opt is an option you can specify to alter the behavior of the post. The choices are:
|
||||
*
|
||||
* OS_OPT_POST_NONE No special option selected
|
||||
* OS_OPT_POST_NO_SCHED If you don't want the scheduler to be called after the post.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE The call was successful and the mutex was signaled.
|
||||
* OS_ERR_MUTEX_NESTING Mutex owner nested its use of the mutex
|
||||
* OS_ERR_MUTEX_NOT_OWNER If the task posting is not the Mutex owner
|
||||
* OS_ERR_OBJ_PTR_NULL If 'p_mutex' is a NULL pointer.
|
||||
* OS_ERR_OBJ_TYPE If 'p_mutex' is not pointing at a mutex
|
||||
* OS_ERR_POST_ISR If you attempted to post from an ISR
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSMutexPost (OS_MUTEX *p_mutex,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_PEND_LIST *p_pend_list;
|
||||
OS_TCB *p_tcb;
|
||||
CPU_TS ts;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
|
||||
*p_err = OS_ERR_POST_ISR;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return;
|
||||
}
|
||||
switch (opt) { /* Validate 'opt' */
|
||||
case OS_OPT_POST_NONE:
|
||||
case OS_OPT_POST_NO_SCHED:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_mutex->Type != OS_OBJ_TYPE_MUTEX) { /* Make sure mutex was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
if (OSTCBCurPtr != p_mutex->OwnerTCBPtr) { /* Make sure the mutex owner is releasing the mutex */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_MUTEX_NOT_OWNER;
|
||||
return;
|
||||
}
|
||||
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
ts = OS_TS_GET(); /* Get timestamp */
|
||||
p_mutex->TS = ts;
|
||||
p_mutex->OwnerNestingCtr--; /* Decrement owner's nesting counter */
|
||||
if (p_mutex->OwnerNestingCtr > (OS_NESTING_CTR)0) { /* Are we done with all nestings? */
|
||||
OS_CRITICAL_EXIT(); /* No */
|
||||
*p_err = OS_ERR_MUTEX_NESTING;
|
||||
return;
|
||||
}
|
||||
|
||||
p_pend_list = &p_mutex->PendList;
|
||||
if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0) { /* Any task waiting on mutex? */
|
||||
p_mutex->OwnerTCBPtr = (OS_TCB *)0; /* No */
|
||||
p_mutex->OwnerNestingCtr = (OS_NESTING_CTR)0;
|
||||
OS_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
/* Yes */
|
||||
if (OSTCBCurPtr->Prio != p_mutex->OwnerOriginalPrio) {
|
||||
OS_RdyListRemove(OSTCBCurPtr);
|
||||
OSTCBCurPtr->Prio = p_mutex->OwnerOriginalPrio; /* Lower owner's priority back to its original one */
|
||||
OS_PrioInsert(OSTCBCurPtr->Prio);
|
||||
OS_RdyListInsertTail(OSTCBCurPtr); /* Insert owner in ready list at new priority */
|
||||
OSPrioCur = OSTCBCurPtr->Prio;
|
||||
}
|
||||
/* Get TCB from head of pend list */
|
||||
p_tcb = p_pend_list->HeadPtr->TCBPtr;
|
||||
p_mutex->OwnerTCBPtr = p_tcb; /* Give mutex to new owner */
|
||||
p_mutex->OwnerOriginalPrio = p_tcb->Prio;
|
||||
p_mutex->OwnerNestingCtr = (OS_NESTING_CTR)1;
|
||||
/* Post to mutex */
|
||||
OS_Post((OS_PEND_OBJ *)((void *)p_mutex),
|
||||
(OS_TCB *)p_tcb,
|
||||
(void *)0,
|
||||
(OS_MSG_SIZE )0,
|
||||
(CPU_TS )ts);
|
||||
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
|
||||
if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
|
||||
OSSched(); /* Run the scheduler */
|
||||
}
|
||||
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* CLEAR THE CONTENTS OF A MUTEX
|
||||
*
|
||||
* Description: This function is called by OSMutexDel() to clear the contents of a mutex
|
||||
*
|
||||
|
||||
* Argument(s): p_mutex is a pointer to the mutex to clear
|
||||
* -------
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_MutexClr (OS_MUTEX *p_mutex)
|
||||
{
|
||||
p_mutex->Type = OS_OBJ_TYPE_NONE; /* Mark the data structure as a NONE */
|
||||
p_mutex->NamePtr = (CPU_CHAR *)((void *)"?MUTEX");
|
||||
p_mutex->OwnerTCBPtr = (OS_TCB *)0;
|
||||
p_mutex->OwnerNestingCtr = (OS_NESTING_CTR)0;
|
||||
p_mutex->TS = (CPU_TS )0;
|
||||
p_mutex->OwnerOriginalPrio = OS_CFG_PRIO_MAX;
|
||||
OS_PendListInit(&p_mutex->PendList); /* Initialize the waiting list */
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* ADD/REMOVE MUTEX TO/FROM DEBUG LIST
|
||||
*
|
||||
* Description: These functions are called by uC/OS-III to add or remove a mutex to/from the debug list.
|
||||
*
|
||||
* Arguments : p_mutex is a pointer to the mutex to add/remove
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : These functions are INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
void OS_MutexDbgListAdd (OS_MUTEX *p_mutex)
|
||||
{
|
||||
p_mutex->DbgNamePtr = (CPU_CHAR *)((void *)" ");
|
||||
p_mutex->DbgPrevPtr = (OS_MUTEX *)0;
|
||||
if (OSMutexDbgListPtr == (OS_MUTEX *)0) {
|
||||
p_mutex->DbgNextPtr = (OS_MUTEX *)0;
|
||||
} else {
|
||||
p_mutex->DbgNextPtr = OSMutexDbgListPtr;
|
||||
OSMutexDbgListPtr->DbgPrevPtr = p_mutex;
|
||||
}
|
||||
OSMutexDbgListPtr = p_mutex;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OS_MutexDbgListRemove (OS_MUTEX *p_mutex)
|
||||
{
|
||||
OS_MUTEX *p_mutex_next;
|
||||
OS_MUTEX *p_mutex_prev;
|
||||
|
||||
|
||||
p_mutex_prev = p_mutex->DbgPrevPtr;
|
||||
p_mutex_next = p_mutex->DbgNextPtr;
|
||||
|
||||
if (p_mutex_prev == (OS_MUTEX *)0) {
|
||||
OSMutexDbgListPtr = p_mutex_next;
|
||||
if (p_mutex_next != (OS_MUTEX *)0) {
|
||||
p_mutex_next->DbgPrevPtr = (OS_MUTEX *)0;
|
||||
}
|
||||
p_mutex->DbgNextPtr = (OS_MUTEX *)0;
|
||||
|
||||
} else if (p_mutex_next == (OS_MUTEX *)0) {
|
||||
p_mutex_prev->DbgNextPtr = (OS_MUTEX *)0;
|
||||
p_mutex->DbgPrevPtr = (OS_MUTEX *)0;
|
||||
|
||||
} else {
|
||||
p_mutex_prev->DbgNextPtr = p_mutex_next;
|
||||
p_mutex_next->DbgPrevPtr = p_mutex_prev;
|
||||
p_mutex->DbgNextPtr = (OS_MUTEX *)0;
|
||||
p_mutex->DbgPrevPtr = (OS_MUTEX *)0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* MUTEX INITIALIZATION
|
||||
*
|
||||
* Description: This function is called by OSInit() to initialize the mutex management.
|
||||
*
|
||||
|
||||
* Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE the call was successful
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_MutexInit (OS_ERR *p_err)
|
||||
{
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OSMutexDbgListPtr = (OS_MUTEX *)0;
|
||||
#endif
|
||||
|
||||
OSMutexQty = (OS_OBJ_QTY)0;
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
#endif /* OS_CFG_MUTEX_EN */
|
||||
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* PEND ON MULTIPLE OBJECTS
|
||||
*
|
||||
* File : OS_PEND_MULTI.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_pend_multi__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
|
||||
#if (((OS_CFG_Q_EN > 0u) || (OS_CFG_SEM_EN > 0u)) && (OS_CFG_PEND_MULTI_EN > 0u))
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* PEND ON MULTIPLE OBJECTS
|
||||
*
|
||||
* Description: This function pends on multiple objects. The objects pended on MUST be either semaphores or message
|
||||
* queues. If multiple objects are ready at the start of the pend call, then all available objects that
|
||||
* are ready will be indicated to the caller. If the task must pend on the multiple events then, as soon
|
||||
* as one of the object is either posted, aborted or deleted, the task will be readied.
|
||||
*
|
||||
* This function only allows you to pend on semaphores and/or message queues.
|
||||
*
|
||||
* Arguments : p_pend_data_tbl is a pointer to an array of type OS_PEND_DATA which contains a list of all the
|
||||
* objects we will be waiting on. The caller must declare an array of OS_PEND_DATA
|
||||
* and initialize the .PendObjPtr (see below) with a pointer to the object (semaphore or
|
||||
* message queue) to pend on.
|
||||
*
|
||||
* OS_PEND_DATA MyPendArray[?];
|
||||
*
|
||||
* The OS_PEND_DATA field are as follows:
|
||||
*
|
||||
* OS_PEND_DATA *PrevPtr; Used to link OS_PEND_DATA objects
|
||||
* OS_PEND_DATA *NextPtr; Used to link OS_PEND_DATA objects
|
||||
* OS_TCB *TCBPtr; Pointer to the TCB that is pending on multiple objects
|
||||
* OS_PEND_OBJ *PendObjPtr; USER supplied field which is a pointer to the
|
||||
* semaphore or message queue you want to pend on. When
|
||||
* you call OSPendMulti() you MUST fill this field for
|
||||
* each of the objects you want to pend on.
|
||||
* OS_PEND_OBJ *RdyObjPtr; OSPendMulti() will return the object that was posted,
|
||||
* aborted or deleted in this field.
|
||||
* void *RdyMsgPtr; OSPendMulti() will fill in this field if the object
|
||||
* posted was a message queue. This corresponds to the
|
||||
* message posted.
|
||||
* OS_MSG_SIZE RdyMsgSize; OSPendMulti() will fill in this field if the object
|
||||
* posted was a message queue. This corresponds to the
|
||||
* size of the message posted.
|
||||
* CPU_TS RdyTS; OSPendMulti() will fill in this field if the object
|
||||
* was a message queue. This corresponds to the time
|
||||
* stamp when the message was posted. However, if the
|
||||
* object is a semaphore and the object is already ready
|
||||
* the this field will be set to (CPU_TS)0 because it's
|
||||
* not possible to know when the semaphore was posted.
|
||||
*
|
||||
* tbl_size is the size (in number of elements) of the OS_PEND_DATA array passed to this function. In
|
||||
* other words, if the called needs to pend on 4 separate objects (semaphores and/or queues)
|
||||
* then you would pass 4 to this call.
|
||||
*
|
||||
* timeout is an optional timeout period (in clock ticks). If non-zero, your task will wait any of
|
||||
* the objects up to the amount of time specified by this argument. If you specify 0, however,
|
||||
* your task will wait forever for the specified objects or, until an object is posted,
|
||||
* aborted or deleted.
|
||||
*
|
||||
* opt determines whether the user wants to block if none of the objects are available.
|
||||
*
|
||||
* OS_OPT_PEND_BLOCKING
|
||||
* OS_OPT_PEND_NON_BLOCKING
|
||||
*
|
||||
* p_err is a pointer to where an error message will be deposited. Possible error messages are:
|
||||
*
|
||||
* OS_ERR_NONE The call was successful and your task owns the resources or,
|
||||
* the objects you are waiting for occurred. Check the .RdyObjPtr
|
||||
* fields to know which objects have been posted.
|
||||
* OS_ERR_OBJ_TYPE If any of the .PendPtr is NOT a semaphore or a message queue
|
||||
* OS_ERR_OPT_INVALID If you specified an invalid option for 'opt'
|
||||
* OS_ERR_PEND_ABORT The wait on the events was aborted; check the .RdyObjPtr fields
|
||||
* for which objects were aborted.
|
||||
* OS_ERR_PEND_DEL The wait on the events was aborted; check the .RdyObjPtr fields
|
||||
* for which objects were aborted.
|
||||
* OS_ERR_PEND_ISR If you called this function from an ISR
|
||||
* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked.
|
||||
* OS_ERR_PEND_WOULD_BLOCK If the caller didn't want to block and no object ready
|
||||
* OS_ERR_STATUS_INVALID Invalid pend status
|
||||
* OS_ERR_PTR_INVALID If you passes a NULL pointer of 'p_pend_data_tbl'
|
||||
* OS_ERR_TIMEOUT The objects were not posted within the specified 'timeout'.
|
||||
*
|
||||
* Returns : > 0 the number of objects returned as ready, aborted or deleted
|
||||
* == 0 if no events are returned as ready because of timeout or upon error.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
/*$PAGE*/
|
||||
OS_OBJ_QTY OSPendMulti (OS_PEND_DATA *p_pend_data_tbl,
|
||||
OS_OBJ_QTY tbl_size,
|
||||
OS_TICK timeout,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
CPU_BOOLEAN valid;
|
||||
OS_OBJ_QTY nbr_obj_rdy;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend from an ISR */
|
||||
*p_err = OS_ERR_PEND_ISR;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_pend_data_tbl == (OS_PEND_DATA *)0) { /* Validate 'p_pend_data_tbl' */
|
||||
*p_err = OS_ERR_PTR_INVALID;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
if (tbl_size == (OS_OBJ_QTY)0) { /* Array size must be > 0 */
|
||||
*p_err = OS_ERR_PTR_INVALID;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
switch (opt) {
|
||||
case OS_OPT_PEND_BLOCKING:
|
||||
case OS_OPT_PEND_NON_BLOCKING:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
valid = OS_PendMultiValidate(p_pend_data_tbl, /* -------- Validate objects to be OS_SEM or OS_Q ------- */
|
||||
tbl_size);
|
||||
if (valid == DEF_FALSE) {
|
||||
*p_err = OS_ERR_OBJ_TYPE; /* Invalid, not OS_SEM or OS_Q */
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
CPU_CRITICAL_ENTER();
|
||||
nbr_obj_rdy = OS_PendMultiGetRdy(p_pend_data_tbl, /* --------- SEE IF OBJECT(s) HAVE BEEN POSTED ---------- */
|
||||
tbl_size);
|
||||
if (nbr_obj_rdy > (OS_OBJ_QTY)0) {
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
return ((OS_OBJ_QTY)nbr_obj_rdy);
|
||||
}
|
||||
|
||||
if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
|
||||
return ((OS_OBJ_QTY)0);
|
||||
} else {
|
||||
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend when the scheduler is locked */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_SCHED_LOCKED;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
}
|
||||
/* Lock the scheduler/re-enable interrupts */
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
/* ------ NO OBJECT READY, PEND ON MULTIPLE OBJECTS ----- */
|
||||
OS_PendMultiWait(p_pend_data_tbl, /* Suspend task until object posted or timeout occurs */
|
||||
tbl_size,
|
||||
timeout);
|
||||
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
|
||||
OSSched(); /* Find next highest priority task ready */
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
switch (OSTCBCurPtr->PendStatus) {
|
||||
case OS_STATUS_PEND_OK: /* We got one of the objects posted to */
|
||||
*p_err = OS_ERR_NONE;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_ABORT: /* Indicate that the multi-pend was aborted */
|
||||
*p_err = OS_ERR_PEND_ABORT;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get semaphore within timeout */
|
||||
*p_err = OS_ERR_TIMEOUT;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_DEL: /* Indicate that an object pended on has been deleted */
|
||||
*p_err = OS_ERR_OBJ_DEL;
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_STATUS_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
OSTCBCurPtr->PendStatus = OS_STATUS_PEND_OK;
|
||||
CPU_CRITICAL_EXIT();
|
||||
|
||||
return ((OS_OBJ_QTY)1);
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* GET A LIST OF OBJECTS READY
|
||||
*
|
||||
* Description: This function is called by OSPendMulti() to obtain the list of object that are ready.
|
||||
*
|
||||
* Arguments : p_pend_data_tbl is a pointer to an array of OS_PEND_DATA
|
||||
* ---------------
|
||||
*
|
||||
* tbl_size is the size of the array
|
||||
*
|
||||
* Returns : > 0 the number of objects ready
|
||||
* == 0 if no object ready
|
||||
*
|
||||
* Note : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
OS_OBJ_QTY OS_PendMultiGetRdy (OS_PEND_DATA *p_pend_data_tbl,
|
||||
OS_OBJ_QTY tbl_size)
|
||||
{
|
||||
OS_OBJ_QTY i;
|
||||
OS_OBJ_QTY nbr_obj_rdy;
|
||||
#if OS_CFG_Q_EN > 0u
|
||||
OS_ERR err;
|
||||
OS_MSG_SIZE msg_size;
|
||||
OS_Q *p_q;
|
||||
void *p_void;
|
||||
CPU_TS ts;
|
||||
#endif
|
||||
#if OS_CFG_SEM_EN > 0u
|
||||
OS_SEM *p_sem;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
nbr_obj_rdy = (OS_OBJ_QTY)0;
|
||||
for (i = 0u; i < tbl_size; i++) {
|
||||
p_pend_data_tbl->RdyObjPtr = (OS_PEND_OBJ *)0; /* Clear all fields */
|
||||
p_pend_data_tbl->RdyMsgPtr = (void *)0;
|
||||
p_pend_data_tbl->RdyMsgSize = (OS_MSG_SIZE )0;
|
||||
p_pend_data_tbl->RdyTS = (CPU_TS )0;
|
||||
p_pend_data_tbl->NextPtr = (OS_PEND_DATA *)0;
|
||||
p_pend_data_tbl->PrevPtr = (OS_PEND_DATA *)0;
|
||||
p_pend_data_tbl->TCBPtr = (OS_TCB *)0;
|
||||
#if OS_CFG_Q_EN > 0u
|
||||
p_q = (OS_Q *)((void *)p_pend_data_tbl->PendObjPtr); /* Assume we are pointing to a message queue object */
|
||||
if (p_q->Type == OS_OBJ_TYPE_Q) { /* Is it a message queue? */
|
||||
p_void = OS_MsgQGet(&p_q->MsgQ, /* Yes, Any message waiting in the message queue? */
|
||||
&msg_size,
|
||||
&ts,
|
||||
&err);
|
||||
if (err == OS_ERR_NONE) {
|
||||
p_pend_data_tbl->RdyObjPtr = p_pend_data_tbl->PendObjPtr;
|
||||
p_pend_data_tbl->RdyMsgPtr = p_void; /* Yes, save the message received */
|
||||
p_pend_data_tbl->RdyMsgSize = msg_size;
|
||||
p_pend_data_tbl->RdyTS = ts;
|
||||
nbr_obj_rdy++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_SEM_EN > 0u
|
||||
p_sem = (OS_SEM *)((void *)p_pend_data_tbl->PendObjPtr); /* Assume we are pointing to a semaphore object */
|
||||
if (p_sem->Type == OS_OBJ_TYPE_SEM) { /* Is it a semaphore? */
|
||||
if (p_sem->Ctr > 0u) { /* Yes, Semaphore has been signaled? */
|
||||
p_sem->Ctr--; /* Yes, caller may proceed */
|
||||
p_pend_data_tbl->RdyObjPtr = p_pend_data_tbl->PendObjPtr;
|
||||
p_pend_data_tbl->RdyTS = p_sem->TS;
|
||||
nbr_obj_rdy++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
p_pend_data_tbl++;
|
||||
}
|
||||
return (nbr_obj_rdy);
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* VERIFY THAT OBJECTS PENDED ON ARE EITHER SEMAPHORES or QUEUES
|
||||
*
|
||||
* Description: This function is called by OSPendMulti() to verify that we are multi-pending on either semaphores or
|
||||
* message queues.
|
||||
*
|
||||
* Arguments : p_pend_data_tbl is a pointer to an array of OS_PEND_DATA
|
||||
* ---------------
|
||||
*
|
||||
* tbl_size is the size of the array
|
||||
*
|
||||
* Returns : TRUE if all objects pended on are either semaphores of queues
|
||||
* FALSE if at least one object is not a semaphore or queue.
|
||||
*
|
||||
* Note : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
CPU_BOOLEAN OS_PendMultiValidate (OS_PEND_DATA *p_pend_data_tbl,
|
||||
OS_OBJ_QTY tbl_size)
|
||||
{
|
||||
OS_OBJ_QTY i;
|
||||
OS_OBJ_QTY ctr;
|
||||
#if OS_CFG_SEM_EN > 0u
|
||||
OS_SEM *p_sem;
|
||||
#endif
|
||||
#if OS_CFG_Q_EN > 0u
|
||||
OS_Q *p_q;
|
||||
#endif
|
||||
|
||||
|
||||
for (i = 0u; i < tbl_size; i++) {
|
||||
if (p_pend_data_tbl->PendObjPtr == (OS_PEND_OBJ *)0) { /* All .PendObjPtr in the table MUST be non NULL */
|
||||
return (DEF_FALSE);
|
||||
}
|
||||
|
||||
ctr = 0u;
|
||||
#if OS_CFG_SEM_EN > 0u
|
||||
p_sem = (OS_SEM *)((void *)p_pend_data_tbl->PendObjPtr); /* All objects to pend on must be of type OS_SEM ... */
|
||||
if (p_sem->Type == OS_OBJ_TYPE_SEM) {
|
||||
ctr++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_Q_EN > 0u
|
||||
p_q = (OS_Q *)((void *)p_pend_data_tbl->PendObjPtr); /* ... or of type OS_Q */
|
||||
if (p_q->Type == OS_OBJ_TYPE_Q) {
|
||||
ctr++;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ctr == (OS_OBJ_QTY)0) {
|
||||
return (DEF_FALSE); /* Found at least one invalid object type */
|
||||
}
|
||||
p_pend_data_tbl++;
|
||||
}
|
||||
return (DEF_TRUE);
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* MAKE TASK WAIT FOR ANY OF MULTIPLE EVENTS TO OCCUR
|
||||
*
|
||||
* Description: This function is called by OSPendMulti() to suspend a task because any one of multiple objects that have
|
||||
* not been posted to.
|
||||
*
|
||||
* Arguments : p_pend_data_tbl is a pointer to an array of OS_PEND_DATA
|
||||
* ---------------
|
||||
*
|
||||
* tbl_size is the size of the array
|
||||
*
|
||||
* timeout is the timeout to wait in case none of the objects become ready
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_PendMultiWait (OS_PEND_DATA *p_pend_data_tbl,
|
||||
OS_OBJ_QTY tbl_size,
|
||||
OS_TICK timeout)
|
||||
{
|
||||
OS_OBJ_QTY i;
|
||||
OS_PEND_LIST *p_pend_list;
|
||||
|
||||
#if OS_CFG_Q_EN > 0u
|
||||
OS_Q *p_q;
|
||||
#endif
|
||||
|
||||
#if OS_CFG_SEM_EN > 0u
|
||||
OS_SEM *p_sem;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
OSTCBCurPtr->PendOn = OS_TASK_PEND_ON_MULTI; /* Resource not available, wait until it is */
|
||||
OSTCBCurPtr->PendStatus = OS_STATUS_PEND_OK;
|
||||
OSTCBCurPtr->PendDataTblEntries = tbl_size;
|
||||
OSTCBCurPtr->PendDataTblPtr = p_pend_data_tbl;
|
||||
|
||||
OS_TaskBlock(OSTCBCurPtr, /* Block the task waiting for object to be posted ... */
|
||||
timeout); /* ... but with a timeout if not */
|
||||
|
||||
for (i = 0u; i < tbl_size; i++) {
|
||||
p_pend_data_tbl->TCBPtr = OSTCBCurPtr; /* Every entry points back to the TCB of the task */
|
||||
|
||||
#if OS_CFG_SEM_EN > 0u
|
||||
p_sem = (OS_SEM *)((void *)p_pend_data_tbl->PendObjPtr);
|
||||
if (p_sem->Type == OS_OBJ_TYPE_SEM) {
|
||||
p_pend_list = &p_sem->PendList;
|
||||
OS_PendListInsertPrio(p_pend_list,
|
||||
p_pend_data_tbl);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_Q_EN > 0u
|
||||
p_q = (OS_Q *)((void *)p_pend_data_tbl->PendObjPtr);
|
||||
if (p_q->Type == OS_OBJ_TYPE_Q) {
|
||||
p_pend_list = &p_q->PendList;
|
||||
OS_PendListInsertPrio(p_pend_list,
|
||||
p_pend_data_tbl);
|
||||
}
|
||||
#endif
|
||||
|
||||
p_pend_data_tbl++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
155
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_prio.c
Normal file
155
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_prio.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* PRIORITY MANAGEMENT
|
||||
*
|
||||
* File : OS_PRIO.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_prio__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
|
||||
CPU_DATA OSPrioTbl[OS_PRIO_TBL_SIZE]; /* Declare the array local to this file to allow for ... */
|
||||
/* ... optimization. In other words, this allows the ... */
|
||||
/* ... table to be located in fast memory */
|
||||
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INITIALIZE THE PRIORITY LIST
|
||||
*
|
||||
* Description: This function is called by uC/OS-III to initialize the list of ready priorities.
|
||||
*
|
||||
* Arguments : none
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_PrioInit (void)
|
||||
{
|
||||
CPU_DATA i;
|
||||
|
||||
|
||||
/* Clear the bitmap table ... no task is ready */
|
||||
for (i = 0u; i < OS_PRIO_TBL_SIZE; i++) {
|
||||
OSPrioTbl[i] = (CPU_DATA)0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* GET HIGHEST PRIORITY TASK WAITING
|
||||
*
|
||||
* Description: This function is called by other uC/OS-III services to determine the highest priority task
|
||||
* waiting on the event.
|
||||
*
|
||||
* Arguments : none
|
||||
*
|
||||
* Returns : The priority of the Highest Priority Task (HPT) waiting for the event
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
OS_PRIO OS_PrioGetHighest (void)
|
||||
{
|
||||
CPU_DATA *p_tbl;
|
||||
OS_PRIO prio;
|
||||
|
||||
|
||||
prio = (OS_PRIO)0;
|
||||
p_tbl = &OSPrioTbl[0];
|
||||
while (*p_tbl == (CPU_DATA)0) { /* Search the bitmap table for the highest priority */
|
||||
prio += DEF_INT_CPU_NBR_BITS; /* Compute the step of each CPU_DATA entry */
|
||||
p_tbl++;
|
||||
}
|
||||
prio += (OS_PRIO)CPU_CntLeadZeros(*p_tbl); /* Find the position of the first bit set at the entry */
|
||||
return (prio);
|
||||
}
|
||||
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INSERT PRIORITY
|
||||
*
|
||||
* Description: This function is called to insert a priority in the priority table.
|
||||
*
|
||||
* Arguments : prio is the priority to insert
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_PrioInsert (OS_PRIO prio)
|
||||
{
|
||||
CPU_DATA bit;
|
||||
CPU_DATA bit_nbr;
|
||||
OS_PRIO ix;
|
||||
|
||||
|
||||
ix = prio / DEF_INT_CPU_NBR_BITS;
|
||||
bit_nbr = (CPU_DATA)prio & (DEF_INT_CPU_NBR_BITS - 1u);
|
||||
bit = 1u;
|
||||
bit <<= (DEF_INT_CPU_NBR_BITS - 1u) - bit_nbr;
|
||||
OSPrioTbl[ix] |= bit;
|
||||
}
|
||||
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* REMOVE PRIORITY
|
||||
*
|
||||
* Description: This function is called to remove a priority in the priority table.
|
||||
*
|
||||
* Arguments : prio is the priority to remove
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_PrioRemove (OS_PRIO prio)
|
||||
{
|
||||
CPU_DATA bit;
|
||||
CPU_DATA bit_nbr;
|
||||
OS_PRIO ix;
|
||||
|
||||
|
||||
ix = prio / DEF_INT_CPU_NBR_BITS;
|
||||
bit_nbr = (CPU_DATA)prio & (DEF_INT_CPU_NBR_BITS - 1u);
|
||||
bit = 1u;
|
||||
bit <<= (DEF_INT_CPU_NBR_BITS - 1u) - bit_nbr;
|
||||
OSPrioTbl[ix] &= ~bit;
|
||||
}
|
||||
981
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_q.c
Normal file
981
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_q.c
Normal file
@@ -0,0 +1,981 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* MESSAGE QUEUE MANAGEMENT
|
||||
*
|
||||
* File : OS_Q.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_q__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
|
||||
#if OS_CFG_Q_EN > 0u
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* CREATE A MESSAGE QUEUE
|
||||
*
|
||||
* Description: This function is called by your application to create a message queue. Message queues MUST be created
|
||||
* before they can be used.
|
||||
*
|
||||
* Arguments : p_q is a pointer to the message queue
|
||||
*
|
||||
* p_name is a pointer to an ASCII string that will be used to name the message queue
|
||||
*
|
||||
* max_qty indicates the maximum size of the message queue (must be non-zero). Note that it's also not
|
||||
* possible to have a size higher than the maximum number of OS_MSGs available.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE the call was successful
|
||||
* OS_ERR_CREATE_ISR can't create from an ISR
|
||||
* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the Queue after you called
|
||||
* OSSafetyCriticalStart().
|
||||
* OS_ERR_NAME if 'p_name' is a NULL pointer
|
||||
* OS_ERR_OBJ_CREATED if the message queue has already been created
|
||||
* OS_ERR_OBJ_PTR_NULL if you passed a NULL pointer for 'p_q'
|
||||
* OS_ERR_Q_SIZE if the size you specified is 0
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSQCreate (OS_Q *p_q,
|
||||
CPU_CHAR *p_name,
|
||||
OS_MSG_QTY max_qty,
|
||||
OS_ERR *p_err)
|
||||
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL_IEC61508
|
||||
if (OSSafetyCriticalStartFlag == DEF_TRUE) {
|
||||
*p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to be called from an ISR */
|
||||
*p_err = OS_ERR_CREATE_ISR;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_q == (OS_Q *)0) { /* Validate arguments */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return;
|
||||
}
|
||||
if (max_qty == (OS_MSG_QTY)0) { /* Cannot specify a zero size queue */
|
||||
*p_err = OS_ERR_Q_SIZE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
OS_CRITICAL_ENTER();
|
||||
p_q->Type = OS_OBJ_TYPE_Q; /* Mark the data structure as a message queue */
|
||||
p_q->NamePtr = p_name;
|
||||
OS_MsgQInit(&p_q->MsgQ, /* Initialize the queue */
|
||||
max_qty);
|
||||
OS_PendListInit(&p_q->PendList); /* Initialize the waiting list */
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OS_QDbgListAdd(p_q);
|
||||
#endif
|
||||
OSQQty++; /* One more queue created */
|
||||
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* DELETE A MESSAGE QUEUE
|
||||
*
|
||||
* Description: This function deletes a message queue and readies all tasks pending on the queue.
|
||||
*
|
||||
* Arguments : p_q is a pointer to the message queue you want to delete
|
||||
*
|
||||
* opt determines delete options as follows:
|
||||
*
|
||||
* OS_OPT_DEL_NO_PEND Delete the queue ONLY if no task pending
|
||||
* OS_OPT_DEL_ALWAYS Deletes the queue even if tasks are waiting.
|
||||
* In this case, all the tasks pending will be readied.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* 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_OBJ_PTR_NULL if you pass a NULL pointer for 'p_q'
|
||||
* OS_ERR_OBJ_TYPE if the message queue was not created
|
||||
* OS_ERR_OPT_INVALID An invalid option was specified
|
||||
* OS_ERR_TASK_WAITING One or more tasks were waiting on the queue
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 3) 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#if OS_CFG_Q_DEL_EN > 0u
|
||||
OS_OBJ_QTY OSQDel (OS_Q *p_q,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_OBJ_QTY cnt;
|
||||
OS_OBJ_QTY nbr_tasks;
|
||||
OS_PEND_DATA *p_pend_data;
|
||||
OS_PEND_LIST *p_pend_list;
|
||||
OS_TCB *p_tcb;
|
||||
CPU_TS ts;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't delete a message queue from an ISR */
|
||||
*p_err = OS_ERR_DEL_ISR;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_q == (OS_Q *)0) { /* Validate 'p_q' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
switch (opt) { /* Validate 'opt' */
|
||||
case OS_OPT_DEL_NO_PEND:
|
||||
case OS_OPT_DEL_ALWAYS:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_q->Type != OS_OBJ_TYPE_Q) { /* Make sure message queue was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_pend_list = &p_q->PendList;
|
||||
cnt = p_pend_list->NbrEntries;
|
||||
nbr_tasks = cnt;
|
||||
switch (opt) {
|
||||
case OS_OPT_DEL_NO_PEND: /* Delete message queue only if no task waiting */
|
||||
if (nbr_tasks == (OS_OBJ_QTY)0) {
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OS_QDbgListRemove(p_q);
|
||||
#endif
|
||||
OSQQty--;
|
||||
OS_QClr(p_q);
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
} else {
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_TASK_WAITING;
|
||||
}
|
||||
break;
|
||||
|
||||
case OS_OPT_DEL_ALWAYS: /* Always delete the message queue */
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
|
||||
while (cnt > 0u) { /* Remove all tasks from the pend list */
|
||||
p_pend_data = p_pend_list->HeadPtr;
|
||||
p_tcb = p_pend_data->TCBPtr;
|
||||
OS_PendObjDel((OS_PEND_OBJ *)((void *)p_q),
|
||||
p_tcb,
|
||||
ts);
|
||||
cnt--;
|
||||
}
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OS_QDbgListRemove(p_q);
|
||||
#endif
|
||||
OSQQty--;
|
||||
OS_QClr(p_q);
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
OSSched(); /* Find highest priority task ready to run */
|
||||
*p_err = OS_ERR_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
break;
|
||||
}
|
||||
return (nbr_tasks);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* FLUSH QUEUE
|
||||
*
|
||||
* Description : This function is used to flush the contents of the message queue.
|
||||
*
|
||||
* Arguments : p_q is a pointer to the message queue to flush
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE upon success
|
||||
* OS_ERR_FLUSH_ISR if you called this function from an ISR
|
||||
* OS_ERR_OBJ_PTR_NULL If you passed a NULL pointer for 'p_q'
|
||||
* OS_ERR_OBJ_TYPE If you didn't create the message queue
|
||||
*
|
||||
* Returns : The number of entries freed from the queue
|
||||
*
|
||||
* Note(s) : 1) 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_CFG_Q_FLUSH_EN > 0u
|
||||
OS_MSG_QTY OSQFlush (OS_Q *p_q,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_MSG_QTY entries;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((OS_MSG_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't flush a message queue from an ISR */
|
||||
*p_err = OS_ERR_FLUSH_ISR;
|
||||
return ((OS_MSG_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_q == (OS_Q *)0) { /* Validate arguments */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return ((OS_MSG_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_q->Type != OS_OBJ_TYPE_Q) { /* Make sure message queue was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return ((OS_MSG_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
OS_CRITICAL_ENTER();
|
||||
entries = OS_MsgQFreeAll(&p_q->MsgQ); /* Return all OS_MSGs to the OS_MSG pool */
|
||||
OS_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
return ((OS_MSG_QTY)entries);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* PEND ON A QUEUE FOR A MESSAGE
|
||||
*
|
||||
* Description: This function waits for a message to be sent to a queue
|
||||
*
|
||||
* Arguments : p_q is a pointer to the message 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.
|
||||
*
|
||||
* opt determines whether the user wants to block if the queue is empty or not:
|
||||
*
|
||||
* OS_OPT_PEND_BLOCKING
|
||||
* OS_OPT_PEND_NON_BLOCKING
|
||||
*
|
||||
* p_msg_size is a pointer to a variable that will receive the size of the message
|
||||
*
|
||||
* p_ts is a pointer to a variable that will receive the timestamp of when the message was
|
||||
* received, pend aborted or the message queue deleted, If you pass a NULL pointer (i.e.
|
||||
* (CPU_TS *)0) then you will not get the timestamp. In other words, passing a NULL pointer
|
||||
* is valid and indicates that you don't need the timestamp.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE The call was successful and your task received a message.
|
||||
* OS_ERR_OBJ_PTR_NULL if you pass a NULL pointer for 'p_q'
|
||||
* OS_ERR_OBJ_TYPE if the message queue was not created
|
||||
* OS_ERR_PEND_ABORT the pend was aborted
|
||||
* OS_ERR_PEND_ISR if you called this function from an ISR
|
||||
* OS_ERR_PEND_WOULD_BLOCK If you specified non-blocking but the queue was not empty
|
||||
* OS_ERR_SCHED_LOCKED the scheduler is locked
|
||||
* OS_ERR_TIMEOUT A message was not received within the specified timeout
|
||||
* would lead to a suspension.
|
||||
*
|
||||
* 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 'p_q' is a NULL pointer or,
|
||||
* if you didn't pass a pointer to a queue.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void *OSQPend (OS_Q *p_q,
|
||||
OS_TICK timeout,
|
||||
OS_OPT opt,
|
||||
OS_MSG_SIZE *p_msg_size,
|
||||
CPU_TS *p_ts,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_PEND_DATA pend_data;
|
||||
void *p_void;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((void *)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
|
||||
*p_err = OS_ERR_PEND_ISR;
|
||||
return ((void *)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_q == (OS_Q *)0) { /* Validate arguments */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
if (p_msg_size == (OS_MSG_SIZE *)0) {
|
||||
*p_err = OS_ERR_PTR_INVALID;
|
||||
return ((void *)0);
|
||||
}
|
||||
switch (opt) {
|
||||
case OS_OPT_PEND_BLOCKING:
|
||||
case OS_OPT_PEND_NON_BLOCKING:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return ((void *)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_q->Type != OS_OBJ_TYPE_Q) { /* Make sure message queue was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return ((void *)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = (CPU_TS )0; /* Initialize the returned timestamp */
|
||||
}
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_void = OS_MsgQGet(&p_q->MsgQ, /* Any message waiting in the message queue? */
|
||||
p_msg_size,
|
||||
p_ts,
|
||||
p_err);
|
||||
if (*p_err == OS_ERR_NONE) {
|
||||
CPU_CRITICAL_EXIT();
|
||||
return (p_void); /* Yes, Return message received */
|
||||
}
|
||||
|
||||
if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
|
||||
return ((void *)0);
|
||||
} else {
|
||||
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend when the scheduler is locked */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_SCHED_LOCKED;
|
||||
return ((void *)0);
|
||||
}
|
||||
}
|
||||
/* Lock the scheduler/re-enable interrupts */
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
OS_Pend(&pend_data, /* Block task pending on Message Queue */
|
||||
(OS_PEND_OBJ *)((void *)p_q),
|
||||
OS_TASK_PEND_ON_Q,
|
||||
timeout);
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
|
||||
OSSched(); /* Find the next highest priority task ready to run */
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
switch (OSTCBCurPtr->PendStatus) {
|
||||
case OS_STATUS_PEND_OK: /* Extract message from TCB (Put there by Post) */
|
||||
p_void = OSTCBCurPtr->MsgPtr;
|
||||
*p_msg_size = OSTCBCurPtr->MsgSize;
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = OSTCBCurPtr->TS;
|
||||
}
|
||||
*p_err = OS_ERR_NONE;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_ABORT: /* Indicate that we aborted */
|
||||
p_void = (void *)0;
|
||||
*p_msg_size = (OS_MSG_SIZE)0;
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = OSTCBCurPtr->TS;
|
||||
}
|
||||
*p_err = OS_ERR_PEND_ABORT;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get event within TO */
|
||||
p_void = (void *)0;
|
||||
*p_msg_size = (OS_MSG_SIZE)0;
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = (CPU_TS )0;
|
||||
}
|
||||
*p_err = OS_ERR_TIMEOUT;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_DEL: /* Indicate that object pended on has been deleted */
|
||||
p_void = (void *)0;
|
||||
*p_msg_size = (OS_MSG_SIZE)0;
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = OSTCBCurPtr->TS;
|
||||
}
|
||||
*p_err = OS_ERR_OBJ_DEL;
|
||||
break;
|
||||
|
||||
default:
|
||||
p_void = (void *)0;
|
||||
*p_msg_size = (OS_MSG_SIZE)0;
|
||||
*p_err = OS_ERR_STATUS_INVALID;
|
||||
break;
|
||||
}
|
||||
CPU_CRITICAL_EXIT();
|
||||
return (p_void);
|
||||
}
|
||||
|
||||
|
||||
/*$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().
|
||||
*
|
||||
* Arguments : p_q is a pointer to the message queue
|
||||
*
|
||||
* opt determines the type of ABORT performed:
|
||||
*
|
||||
* OS_OPT_PEND_ABORT_1 ABORT wait for a single task (HPT) waiting on the queue
|
||||
* OS_OPT_PEND_ABORT_ALL ABORT wait for ALL tasks that are waiting on the queue
|
||||
* OS_OPT_POST_NO_SCHED Do not call the scheduler
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE 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_OPT_INVALID if you specified an invalid option
|
||||
* OS_ERR_OBJ_PTR_NULL if you pass a NULL pointer for 'p_q'
|
||||
* OS_ERR_OBJ_TYPE if the message queue was not created
|
||||
* OS_ERR_PEND_ABORT_ISR If this function was called from an ISR
|
||||
* OS_ERR_PEND_ABORT_NONE No task were pending
|
||||
*
|
||||
* 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_CFG_Q_PEND_ABORT_EN > 0u
|
||||
OS_OBJ_QTY OSQPendAbort (OS_Q *p_q,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_PEND_LIST *p_pend_list;
|
||||
OS_TCB *p_tcb;
|
||||
CPU_TS ts;
|
||||
OS_OBJ_QTY nbr_tasks;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to Pend Abort from an ISR */
|
||||
*p_err = OS_ERR_PEND_ABORT_ISR;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_q == (OS_Q *)0) { /* Validate 'p_q' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
switch (opt) { /* Validate 'opt' */
|
||||
case OS_OPT_PEND_ABORT_1:
|
||||
case OS_OPT_PEND_ABORT_ALL:
|
||||
case OS_OPT_PEND_ABORT_1 | OS_OPT_POST_NO_SCHED:
|
||||
case OS_OPT_PEND_ABORT_ALL | OS_OPT_POST_NO_SCHED:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_q->Type != OS_OBJ_TYPE_Q) { /* Make sure queue was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_pend_list = &p_q->PendList;
|
||||
if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0u) { /* Any task waiting on queue? */
|
||||
CPU_CRITICAL_EXIT(); /* No */
|
||||
*p_err = OS_ERR_PEND_ABORT_NONE;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
nbr_tasks = 0u;
|
||||
ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
|
||||
while (p_pend_list->NbrEntries > (OS_OBJ_QTY)0u) {
|
||||
p_tcb = p_pend_list->HeadPtr->TCBPtr;
|
||||
OS_PendAbort((OS_PEND_OBJ *)((void *)p_q),
|
||||
p_tcb,
|
||||
ts);
|
||||
nbr_tasks++;
|
||||
if (opt != OS_OPT_PEND_ABORT_ALL) { /* Pend abort all tasks waiting? */
|
||||
break; /* No */
|
||||
}
|
||||
}
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
|
||||
if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0u) {
|
||||
OSSched(); /* Run the scheduler */
|
||||
}
|
||||
|
||||
*p_err = OS_ERR_NONE;
|
||||
return (nbr_tasks);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* POST MESSAGE TO A QUEUE
|
||||
*
|
||||
* Description: This function sends a message to a queue. With the 'opt' argument, you can specify whether the message
|
||||
* is broadcast to all waiting tasks and/or whether you post the message to the front of the queue (LIFO)
|
||||
* or normally (FIFO) at the end of the queue.
|
||||
*
|
||||
* Arguments : p_q is a pointer to a message queue that must have been created by OSQCreate().
|
||||
*
|
||||
* p_void is a pointer to the message to send.
|
||||
*
|
||||
* msg_size specifies the size of the message (in bytes)
|
||||
*
|
||||
* opt determines the type of POST performed:
|
||||
*
|
||||
* OS_OPT_POST_ALL POST to ALL tasks that are waiting on the queue. This option
|
||||
* can be added to either OS_OPT_POST_FIFO or OS_OPT_POST_LIFO
|
||||
* OS_OPT_POST_FIFO POST message to end of queue (FIFO) and wake up a single
|
||||
* waiting task.
|
||||
* OS_OPT_POST_LIFO POST message to the front of the queue (LIFO) and wake up
|
||||
* a single waiting task.
|
||||
* OS_OPT_POST_NO_SCHED Do not call the scheduler
|
||||
*
|
||||
* Note(s): 1) OS_OPT_POST_NO_SCHED can be added (or OR'd) with one of the other options.
|
||||
* 2) OS_OPT_POST_ALL can be added (or OR'd) with one of the other options.
|
||||
* 3) Possible combination of options are:
|
||||
*
|
||||
* OS_OPT_POST_FIFO
|
||||
* OS_OPT_POST_LIFO
|
||||
* OS_OPT_POST_FIFO + OS_OPT_POST_ALL
|
||||
* OS_OPT_POST_LIFO + OS_OPT_POST_ALL
|
||||
* OS_OPT_POST_FIFO + OS_OPT_POST_NO_SCHED
|
||||
* OS_OPT_POST_LIFO + OS_OPT_POST_NO_SCHED
|
||||
* OS_OPT_POST_FIFO + OS_OPT_POST_ALL + OS_OPT_POST_NO_SCHED
|
||||
* OS_OPT_POST_LIFO + OS_OPT_POST_ALL + OS_OPT_POST_NO_SCHED
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE The call was successful and the message was sent
|
||||
* OS_ERR_MSG_POOL_EMPTY If there are no more OS_MSGs to use to place the message into
|
||||
* OS_ERR_OBJ_PTR_NULL If 'p_q' is a NULL pointer
|
||||
* OS_ERR_OBJ_TYPE If the message queue was not initialized
|
||||
* OS_ERR_Q_MAX If the queue is full
|
||||
*
|
||||
* Returns : None
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSQPost (OS_Q *p_q,
|
||||
void *p_void,
|
||||
OS_MSG_SIZE msg_size,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
CPU_TS ts;
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_q == (OS_Q *)0) { /* Validate 'p_q' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return;
|
||||
}
|
||||
switch (opt) { /* Validate 'opt' */
|
||||
case OS_OPT_POST_FIFO:
|
||||
case OS_OPT_POST_LIFO:
|
||||
case OS_OPT_POST_FIFO | OS_OPT_POST_ALL:
|
||||
case OS_OPT_POST_LIFO | OS_OPT_POST_ALL:
|
||||
case OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED:
|
||||
case OS_OPT_POST_LIFO | OS_OPT_POST_NO_SCHED:
|
||||
case OS_OPT_POST_FIFO | OS_OPT_POST_ALL | OS_OPT_POST_NO_SCHED:
|
||||
case OS_OPT_POST_LIFO | OS_OPT_POST_ALL | OS_OPT_POST_NO_SCHED:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_q->Type != OS_OBJ_TYPE_Q) { /* Make sure message queue was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ts = OS_TS_GET(); /* Get timestamp */
|
||||
|
||||
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) {
|
||||
OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_Q, /* Post to ISR queue */
|
||||
(void *)p_q,
|
||||
(void *)p_void,
|
||||
(OS_MSG_SIZE)msg_size,
|
||||
(OS_FLAGS )0,
|
||||
(OS_OPT )opt,
|
||||
(CPU_TS )ts,
|
||||
(OS_ERR *)p_err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
OS_QPost(p_q,
|
||||
p_void,
|
||||
msg_size,
|
||||
opt,
|
||||
ts,
|
||||
p_err);
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* CLEAR THE CONTENTS OF A MESSAGE QUEUE
|
||||
*
|
||||
* Description: This function is called by OSQDel() to clear the contents of a message queue
|
||||
*
|
||||
|
||||
* Argument(s): p_q is a pointer to the queue to clear
|
||||
* ---
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_QClr (OS_Q *p_q)
|
||||
{
|
||||
(void)OS_MsgQFreeAll(&p_q->MsgQ); /* Return all OS_MSGs to the free list */
|
||||
p_q->Type = OS_OBJ_TYPE_NONE; /* Mark the data structure as a NONE */
|
||||
p_q->NamePtr = (CPU_CHAR *)((void *)"?Q");
|
||||
OS_MsgQInit(&p_q->MsgQ, /* Initialize the list of OS_MSGs */
|
||||
0u);
|
||||
OS_PendListInit(&p_q->PendList); /* Initialize the waiting list */
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* ADD/REMOVE MESSAGE QUEUE TO/FROM DEBUG LIST
|
||||
*
|
||||
* Description: These functions are called by uC/OS-III to add or remove a message queue to/from a message queue debug
|
||||
* list.
|
||||
*
|
||||
* Arguments : p_q is a pointer to the message queue to add/remove
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : These functions are INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
void OS_QDbgListAdd (OS_Q *p_q)
|
||||
{
|
||||
p_q->DbgNamePtr = (CPU_CHAR *)((void *)" ");
|
||||
p_q->DbgPrevPtr = (OS_Q *)0;
|
||||
if (OSQDbgListPtr == (OS_Q *)0) {
|
||||
p_q->DbgNextPtr = (OS_Q *)0;
|
||||
} else {
|
||||
p_q->DbgNextPtr = OSQDbgListPtr;
|
||||
OSQDbgListPtr->DbgPrevPtr = p_q;
|
||||
}
|
||||
OSQDbgListPtr = p_q;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OS_QDbgListRemove (OS_Q *p_q)
|
||||
{
|
||||
OS_Q *p_q_next;
|
||||
OS_Q *p_q_prev;
|
||||
|
||||
|
||||
p_q_prev = p_q->DbgPrevPtr;
|
||||
p_q_next = p_q->DbgNextPtr;
|
||||
|
||||
if (p_q_prev == (OS_Q *)0) {
|
||||
OSQDbgListPtr = p_q_next;
|
||||
if (p_q_next != (OS_Q *)0) {
|
||||
p_q_next->DbgPrevPtr = (OS_Q *)0;
|
||||
}
|
||||
p_q->DbgNextPtr = (OS_Q *)0;
|
||||
|
||||
} else if (p_q_next == (OS_Q *)0) {
|
||||
p_q_prev->DbgNextPtr = (OS_Q *)0;
|
||||
p_q->DbgPrevPtr = (OS_Q *)0;
|
||||
|
||||
} else {
|
||||
p_q_prev->DbgNextPtr = p_q_next;
|
||||
p_q_next->DbgPrevPtr = p_q_prev;
|
||||
p_q->DbgNextPtr = (OS_Q *)0;
|
||||
p_q->DbgPrevPtr = (OS_Q *)0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* MESSAGE QUEUE INITIALIZATION
|
||||
*
|
||||
* Description: This function is called by OSInit() to initialize the message queue management.
|
||||
*
|
||||
|
||||
* Arguments : p_err is a pointer to a variable that will receive an error code.
|
||||
*
|
||||
* OS_ERR_NONE the call was successful
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_QInit (OS_ERR *p_err)
|
||||
{
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OSQDbgListPtr = (OS_Q *)0;
|
||||
#endif
|
||||
|
||||
OSQQty = (OS_OBJ_QTY)0;
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* POST MESSAGE TO A QUEUE
|
||||
*
|
||||
* Description: This function sends a message to a queue. With the 'opt' argument, you can specify whether the message
|
||||
* is broadcast to all waiting tasks and/or whether you post the message to the front of the queue (LIFO)
|
||||
* or normally (FIFO) at the end of the queue.
|
||||
*
|
||||
* Arguments : p_q is a pointer to a message queue that must have been created by OSQCreate().
|
||||
*
|
||||
* p_void is a pointer to the message to send.
|
||||
*
|
||||
* msg_size specifies the size of the message (in bytes)
|
||||
*
|
||||
* opt determines the type of POST performed:
|
||||
*
|
||||
* OS_OPT_POST_ALL POST to ALL tasks that are waiting on the queue
|
||||
*
|
||||
* OS_OPT_POST_FIFO POST as FIFO and wake up single waiting task
|
||||
* OS_OPT_POST_LIFO POST as LIFO and wake up single waiting task
|
||||
*
|
||||
* OS_OPT_POST_NO_SCHED Do not call the scheduler
|
||||
*
|
||||
* ts is the timestamp of the post
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE The call was successful and the message was sent
|
||||
* OS_ERR_MSG_POOL_EMPTY If there are no more OS_MSGs to use to place the message into
|
||||
* OS_ERR_OBJ_PTR_NULL If 'p_q' is a NULL pointer
|
||||
* OS_ERR_OBJ_TYPE If the message queue was not initialized
|
||||
* OS_ERR_Q_MAX If the queue is full
|
||||
*
|
||||
* Returns : None
|
||||
*
|
||||
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_QPost (OS_Q *p_q,
|
||||
void *p_void,
|
||||
OS_MSG_SIZE msg_size,
|
||||
OS_OPT opt,
|
||||
CPU_TS ts,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_OBJ_QTY cnt;
|
||||
OS_OPT post_type;
|
||||
OS_PEND_LIST *p_pend_list;
|
||||
OS_PEND_DATA *p_pend_data;
|
||||
OS_PEND_DATA *p_pend_data_next;
|
||||
OS_TCB *p_tcb;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
OS_CRITICAL_ENTER();
|
||||
p_pend_list = &p_q->PendList;
|
||||
if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0) { /* Any task waiting on message queue? */
|
||||
if ((opt & OS_OPT_POST_LIFO) == (OS_OPT)0) { /* Determine whether we post FIFO or LIFO */
|
||||
post_type = OS_OPT_POST_FIFO;
|
||||
} else {
|
||||
post_type = OS_OPT_POST_LIFO;
|
||||
}
|
||||
OS_MsgQPut(&p_q->MsgQ, /* Place message in the message queue */
|
||||
p_void,
|
||||
msg_size,
|
||||
post_type,
|
||||
ts,
|
||||
p_err);
|
||||
OS_CRITICAL_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((opt & OS_OPT_POST_ALL) != (OS_OPT)0) { /* Post message to all tasks waiting? */
|
||||
cnt = p_pend_list->NbrEntries; /* Yes */
|
||||
} else {
|
||||
cnt = (OS_OBJ_QTY)1; /* No */
|
||||
}
|
||||
p_pend_data = p_pend_list->HeadPtr;
|
||||
while (cnt > 0u) {
|
||||
p_tcb = p_pend_data->TCBPtr;
|
||||
p_pend_data_next = p_pend_data->NextPtr;
|
||||
OS_Post((OS_PEND_OBJ *)((void *)p_q),
|
||||
p_tcb,
|
||||
p_void,
|
||||
msg_size,
|
||||
ts);
|
||||
p_pend_data = p_pend_data_next;
|
||||
cnt--;
|
||||
}
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
|
||||
OSSched(); /* Run the scheduler */
|
||||
}
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
#endif
|
||||
965
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_sem.c
Normal file
965
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_sem.c
Normal file
@@ -0,0 +1,965 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* SEMAPHORE MANAGEMENT
|
||||
*
|
||||
* File : OS_SEM.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_sem__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
|
||||
#if OS_CFG_SEM_EN > 0u
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* CREATE A SEMAPHORE
|
||||
*
|
||||
* Description: This function creates a semaphore.
|
||||
*
|
||||
* Arguments : p_sem is a pointer to the semaphore to initialize. Your application is responsible for
|
||||
* allocating storage for the semaphore.
|
||||
*
|
||||
* p_name is a pointer to the name you would like to give the semaphore.
|
||||
*
|
||||
* cnt is the initial value for the semaphore.
|
||||
* If used to share resources, you should initialize to the number of resources available.
|
||||
* If used to signal the occurrence of event(s) then you should initialize to 0.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE if the call was successful
|
||||
* OS_ERR_CREATE_ISR if you called this function from an ISR
|
||||
* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the semaphore after you
|
||||
* called OSSafetyCriticalStart().
|
||||
* OS_ERR_NAME if 'p_name' is a NULL pointer
|
||||
* OS_ERR_OBJ_CREATED if the semaphore has already been created
|
||||
* OS_ERR_OBJ_PTR_NULL if 'p_sem' is a NULL pointer
|
||||
* OS_ERR_OBJ_TYPE if 'p_sem' has already been initialized to a different
|
||||
* object type
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSSemCreate (OS_SEM *p_sem,
|
||||
CPU_CHAR *p_name,
|
||||
OS_SEM_CTR cnt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL_IEC61508
|
||||
if (OSSafetyCriticalStartFlag == DEF_TRUE) {
|
||||
*p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to be called from an ISR */
|
||||
*p_err = OS_ERR_CREATE_ISR;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
OS_CRITICAL_ENTER();
|
||||
p_sem->Type = OS_OBJ_TYPE_SEM; /* Mark the data structure as a semaphore */
|
||||
p_sem->Ctr = cnt; /* Set semaphore value */
|
||||
p_sem->TS = (CPU_TS)0;
|
||||
p_sem->NamePtr = p_name; /* Save the name of the semaphore */
|
||||
OS_PendListInit(&p_sem->PendList); /* Initialize the waiting list */
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OS_SemDbgListAdd(p_sem);
|
||||
#endif
|
||||
OSSemQty++;
|
||||
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* DELETE A SEMAPHORE
|
||||
*
|
||||
* Description: This function deletes a semaphore.
|
||||
*
|
||||
* Arguments : p_sem is a pointer to the semaphore to delete
|
||||
*
|
||||
* opt determines delete options as follows:
|
||||
*
|
||||
* OS_OPT_DEL_NO_PEND Delete semaphore ONLY if no task pending
|
||||
* OS_OPT_DEL_ALWAYS Deletes the semaphore even if tasks are waiting.
|
||||
* In this case, all the tasks pending will be readied.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* 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_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
|
||||
* OS_ERR_OBJ_TYPE If 'p_sem' is not pointing at a semaphore
|
||||
* OS_ERR_OPT_INVALID An invalid option was specified
|
||||
* OS_ERR_TASK_WAITING One or more tasks were waiting on the semaphore
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
* 3) 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#if OS_CFG_SEM_DEL_EN > 0u
|
||||
OS_OBJ_QTY OSSemDel (OS_SEM *p_sem,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_OBJ_QTY cnt;
|
||||
OS_OBJ_QTY nbr_tasks;
|
||||
OS_PEND_DATA *p_pend_data;
|
||||
OS_PEND_LIST *p_pend_list;
|
||||
OS_TCB *p_tcb;
|
||||
CPU_TS ts;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to delete a semaphore from an ISR */
|
||||
*p_err = OS_ERR_DEL_ISR;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
switch (opt) { /* Validate 'opt' */
|
||||
case OS_OPT_DEL_NO_PEND:
|
||||
case OS_OPT_DEL_ALWAYS:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_sem->Type != OS_OBJ_TYPE_SEM) { /* Make sure semaphore was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return ((OS_OBJ_QTY)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_pend_list = &p_sem->PendList;
|
||||
cnt = p_pend_list->NbrEntries;
|
||||
nbr_tasks = cnt;
|
||||
switch (opt) {
|
||||
case OS_OPT_DEL_NO_PEND: /* Delete semaphore only if no task waiting */
|
||||
if (nbr_tasks == (OS_OBJ_QTY)0) {
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OS_SemDbgListRemove(p_sem);
|
||||
#endif
|
||||
OSSemQty--;
|
||||
OS_SemClr(p_sem);
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
} else {
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_TASK_WAITING;
|
||||
}
|
||||
break;
|
||||
|
||||
case OS_OPT_DEL_ALWAYS: /* Always delete the semaphore */
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
|
||||
while (cnt > 0u) { /* Remove all tasks on the pend list */
|
||||
p_pend_data = p_pend_list->HeadPtr;
|
||||
p_tcb = p_pend_data->TCBPtr;
|
||||
OS_PendObjDel((OS_PEND_OBJ *)((void *)p_sem),
|
||||
p_tcb,
|
||||
ts);
|
||||
cnt--;
|
||||
}
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OS_SemDbgListRemove(p_sem);
|
||||
#endif
|
||||
OSSemQty--;
|
||||
OS_SemClr(p_sem);
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
OSSched(); /* Find highest priority task ready to run */
|
||||
*p_err = OS_ERR_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
break;
|
||||
}
|
||||
return ((OS_OBJ_QTY)nbr_tasks);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* PEND ON SEMAPHORE
|
||||
*
|
||||
* Description: This function waits for a semaphore.
|
||||
*
|
||||
* Arguments : p_sem is a pointer to the 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 (in 'ticks') 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).
|
||||
*
|
||||
* opt determines whether the user wants to block if the semaphore is not available or not:
|
||||
*
|
||||
* OS_OPT_PEND_BLOCKING
|
||||
* OS_OPT_PEND_NON_BLOCKING
|
||||
*
|
||||
* p_ts is a pointer to a variable that will receive the timestamp of when the semaphore was posted
|
||||
* or pend aborted or the semaphore deleted. If you pass a NULL pointer (i.e. (CPU_TS*)0)
|
||||
* then you will not get the timestamp. In other words, passing a NULL pointer is valid
|
||||
* and indicates that you don't need the timestamp.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE The call was successful and your task owns the resource
|
||||
* or, the event you are waiting for occurred.
|
||||
* OS_ERR_OBJ_DEL If 'p_sem' was deleted
|
||||
* OS_ERR_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
|
||||
* OS_ERR_OBJ_TYPE If 'p_sem' is not pointing at a semaphore
|
||||
* OS_ERR_OPT_INVALID If you specified an invalid value for 'opt'
|
||||
* OS_ERR_PEND_ABORT If the pend was aborted by another task
|
||||
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
|
||||
* would lead to a suspension.
|
||||
* OS_ERR_PEND_WOULD_BLOCK If you specified non-blocking but the semaphore was not
|
||||
* available.
|
||||
* OS_ERR_SCHED_LOCKED If you called this function when the scheduler is locked
|
||||
* OS_ERR_STATUS_INVALID Pend status is invalid
|
||||
* OS_ERR_TIMEOUT The semaphore was not received within the specified
|
||||
* timeout.
|
||||
*
|
||||
*
|
||||
* Returns : The current value of the semaphore counter or 0 if not available.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
OS_SEM_CTR OSSemPend (OS_SEM *p_sem,
|
||||
OS_TICK timeout,
|
||||
OS_OPT opt,
|
||||
CPU_TS *p_ts,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_SEM_CTR ctr;
|
||||
OS_PEND_DATA pend_data;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
|
||||
*p_err = OS_ERR_PEND_ISR;
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
switch (opt) { /* Validate 'opt' */
|
||||
case OS_OPT_PEND_BLOCKING:
|
||||
case OS_OPT_PEND_NON_BLOCKING:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_sem->Type != OS_OBJ_TYPE_SEM) { /* Make sure semaphore was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = (CPU_TS)0; /* Initialize the returned timestamp */
|
||||
}
|
||||
CPU_CRITICAL_ENTER();
|
||||
if (p_sem->Ctr > (OS_SEM_CTR)0) { /* Resource available? */
|
||||
p_sem->Ctr--; /* Yes, caller may proceed */
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = p_sem->TS; /* get timestamp of last post */
|
||||
}
|
||||
ctr = p_sem->Ctr;
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
return (ctr);
|
||||
}
|
||||
|
||||
if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
|
||||
ctr = p_sem->Ctr; /* No */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_PEND_WOULD_BLOCK;
|
||||
return (ctr);
|
||||
} else { /* Yes */
|
||||
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend when the scheduler is locked */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_SCHED_LOCKED;
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
}
|
||||
/* Lock the scheduler/re-enable interrupts */
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
OS_Pend(&pend_data, /* Block task pending on Semaphore */
|
||||
(OS_PEND_OBJ *)((void *)p_sem),
|
||||
OS_TASK_PEND_ON_SEM,
|
||||
timeout);
|
||||
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
|
||||
OSSched(); /* Find the next highest priority task ready to run */
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
switch (OSTCBCurPtr->PendStatus) {
|
||||
case OS_STATUS_PEND_OK: /* We got the semaphore */
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = OSTCBCurPtr->TS;
|
||||
}
|
||||
*p_err = OS_ERR_NONE;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_ABORT: /* Indicate that we aborted */
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = OSTCBCurPtr->TS;
|
||||
}
|
||||
*p_err = OS_ERR_PEND_ABORT;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get semaphore within timeout */
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = (CPU_TS )0;
|
||||
}
|
||||
*p_err = OS_ERR_TIMEOUT;
|
||||
break;
|
||||
|
||||
case OS_STATUS_PEND_DEL: /* Indicate that object pended on has been deleted */
|
||||
if (p_ts != (CPU_TS *)0) {
|
||||
*p_ts = OSTCBCurPtr->TS;
|
||||
}
|
||||
*p_err = OS_ERR_OBJ_DEL;
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_STATUS_INVALID;
|
||||
CPU_CRITICAL_EXIT();
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
ctr = p_sem->Ctr;
|
||||
CPU_CRITICAL_EXIT();
|
||||
return (ctr);
|
||||
}
|
||||
|
||||
/*$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 : p_sem is a pointer to the semaphore
|
||||
*
|
||||
* opt determines the type of ABORT performed:
|
||||
*
|
||||
* OS_OPT_PEND_ABORT_1 ABORT wait for a single task (HPT) waiting on the semaphore
|
||||
* OS_OPT_PEND_ABORT_ALL ABORT wait for ALL tasks that are waiting on the semaphore
|
||||
* OS_OPT_POST_NO_SCHED Do not call the scheduler
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE 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_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
|
||||
* OS_ERR_OBJ_TYPE If 'p_sem' is not pointing at a semaphore
|
||||
* OS_ERR_OPT_INVALID If you specified an invalid option
|
||||
* OS_ERR_PEND_ABORT_ISR If you called this function from an ISR
|
||||
* OS_ERR_PEND_ABORT_NONE No task were pending
|
||||
*
|
||||
* 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_CFG_SEM_PEND_ABORT_EN > 0u
|
||||
OS_OBJ_QTY OSSemPendAbort (OS_SEM *p_sem,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_PEND_LIST *p_pend_list;
|
||||
OS_TCB *p_tcb;
|
||||
CPU_TS ts;
|
||||
OS_OBJ_QTY nbr_tasks;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to Pend Abort from an ISR */
|
||||
*p_err = OS_ERR_PEND_ABORT_ISR;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
switch (opt) { /* Validate 'opt' */
|
||||
case OS_OPT_PEND_ABORT_1:
|
||||
case OS_OPT_PEND_ABORT_ALL:
|
||||
case OS_OPT_PEND_ABORT_1 | OS_OPT_POST_NO_SCHED:
|
||||
case OS_OPT_PEND_ABORT_ALL | OS_OPT_POST_NO_SCHED:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_sem->Type != OS_OBJ_TYPE_SEM) { /* Make sure semaphore was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_pend_list = &p_sem->PendList;
|
||||
if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0u) { /* Any task waiting on semaphore? */
|
||||
CPU_CRITICAL_EXIT(); /* No */
|
||||
*p_err = OS_ERR_PEND_ABORT_NONE;
|
||||
return ((OS_OBJ_QTY)0u);
|
||||
}
|
||||
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
nbr_tasks = 0u;
|
||||
ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
|
||||
while (p_pend_list->NbrEntries > (OS_OBJ_QTY)0u) {
|
||||
p_tcb = p_pend_list->HeadPtr->TCBPtr;
|
||||
OS_PendAbort((OS_PEND_OBJ *)((void *)p_sem),
|
||||
p_tcb,
|
||||
ts);
|
||||
nbr_tasks++;
|
||||
if (opt != OS_OPT_PEND_ABORT_ALL) { /* Pend abort all tasks waiting? */
|
||||
break; /* No */
|
||||
}
|
||||
}
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
|
||||
if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0u) {
|
||||
OSSched(); /* Run the scheduler */
|
||||
}
|
||||
|
||||
*p_err = OS_ERR_NONE;
|
||||
return (nbr_tasks);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* POST TO A SEMAPHORE
|
||||
*
|
||||
* Description: This function signals a semaphore
|
||||
*
|
||||
* Arguments : p_sem is a pointer to the semaphore
|
||||
*
|
||||
* opt determines the type of POST performed:
|
||||
*
|
||||
* OS_OPT_POST_1 POST and ready only the highest priority task waiting on semaphore
|
||||
* (if tasks are waiting).
|
||||
* OS_OPT_POST_ALL POST to ALL tasks that are waiting on the semaphore
|
||||
*
|
||||
* OS_OPT_POST_NO_SCHED Do not call the scheduler
|
||||
*
|
||||
* Note(s): 1) OS_OPT_POST_NO_SCHED can be added with one of the other options.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE The call was successful and the semaphore was signaled.
|
||||
* OS_ERR_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
|
||||
* OS_ERR_OBJ_TYPE If 'p_sem' is not pointing at a semaphore
|
||||
* OS_ERR_SEM_OVF If the post would cause the semaphore count to overflow.
|
||||
*
|
||||
* Returns : The current value of the semaphore counter or 0 upon error.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
OS_SEM_CTR OSSemPost (OS_SEM *p_sem,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_SEM_CTR ctr;
|
||||
CPU_TS ts;
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
switch (opt) { /* Validate 'opt' */
|
||||
case OS_OPT_POST_1:
|
||||
case OS_OPT_POST_ALL:
|
||||
case OS_OPT_POST_1 | OS_OPT_POST_NO_SCHED:
|
||||
case OS_OPT_POST_ALL | OS_OPT_POST_NO_SCHED:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return ((OS_SEM_CTR)0u);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_sem->Type != OS_OBJ_TYPE_SEM) { /* Make sure semaphore was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
ts = OS_TS_GET(); /* Get timestamp */
|
||||
|
||||
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from an ISR */
|
||||
OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_SEM, /* Post to ISR queue */
|
||||
(void *)p_sem,
|
||||
(void *)0,
|
||||
(OS_MSG_SIZE)0,
|
||||
(OS_FLAGS )0,
|
||||
(OS_OPT )opt,
|
||||
(CPU_TS )ts,
|
||||
(OS_ERR *)p_err);
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
ctr = OS_SemPost(p_sem, /* Post to semaphore */
|
||||
opt,
|
||||
ts,
|
||||
p_err);
|
||||
|
||||
return (ctr);
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* SET SEMAPHORE
|
||||
*
|
||||
* Description: This function sets the semaphore count to the value specified as an argument. Typically, this value
|
||||
* would be 0 but of course, we can set the semaphore to any value.
|
||||
*
|
||||
* You would typically use this function when a semaphore is used as a signaling mechanism
|
||||
* and, you want to reset the count value.
|
||||
*
|
||||
* Arguments : p_sem is a pointer to the semaphore
|
||||
*
|
||||
* cnt is the new value for the semaphore count. You would pass 0 to reset the semaphore count.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE The call was successful and the semaphore value was set.
|
||||
* OS_ERR_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
|
||||
* OS_ERR_OBJ_TYPE If 'p_sem' is not pointing to a semaphore.
|
||||
* OS_ERR_TASK_WAITING If tasks are waiting on the semaphore.
|
||||
*
|
||||
* Returns : None
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#if OS_CFG_SEM_SET_EN > 0u
|
||||
void OSSemSet (OS_SEM *p_sem,
|
||||
OS_SEM_CTR cnt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_PEND_LIST *p_pend_list;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't call this function from an ISR */
|
||||
*p_err = OS_ERR_SET_ISR;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
|
||||
*p_err = OS_ERR_OBJ_PTR_NULL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
|
||||
if (p_sem->Type != OS_OBJ_TYPE_SEM) { /* Make sure semaphore was created */
|
||||
*p_err = OS_ERR_OBJ_TYPE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
*p_err = OS_ERR_NONE;
|
||||
CPU_CRITICAL_ENTER();
|
||||
if (p_sem->Ctr > (OS_SEM_CTR)0) { /* See if semaphore already has a count */
|
||||
p_sem->Ctr = cnt; /* Yes, set it to the new value specified. */
|
||||
} else {
|
||||
p_pend_list = &p_sem->PendList; /* No */
|
||||
if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0) { /* See if task(s) waiting? */
|
||||
p_sem->Ctr = cnt; /* No, OK to set the value */
|
||||
} else {
|
||||
*p_err = OS_ERR_TASK_WAITING;
|
||||
}
|
||||
}
|
||||
CPU_CRITICAL_EXIT();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* CLEAR THE CONTENTS OF A SEMAPHORE
|
||||
*
|
||||
* Description: This function is called by OSSemDel() to clear the contents of a semaphore
|
||||
*
|
||||
|
||||
* Argument(s): p_sem is a pointer to the semaphore to clear
|
||||
* -----
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_SemClr (OS_SEM *p_sem)
|
||||
{
|
||||
p_sem->Type = OS_OBJ_TYPE_NONE; /* Mark the data structure as a NONE */
|
||||
p_sem->Ctr = (OS_SEM_CTR)0; /* Set semaphore value */
|
||||
p_sem->TS = (CPU_TS )0; /* Clear the time stamp */
|
||||
p_sem->NamePtr = (CPU_CHAR *)((void *)"?SEM");
|
||||
OS_PendListInit(&p_sem->PendList); /* Initialize the waiting list */
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* ADD/REMOVE SEMAPHORE TO/FROM DEBUG LIST
|
||||
*
|
||||
* Description: These functions are called by uC/OS-III to add or remove a semaphore to/from the debug list.
|
||||
*
|
||||
* Arguments : p_sem is a pointer to the semaphore to add/remove
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : These functions are INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
void OS_SemDbgListAdd (OS_SEM *p_sem)
|
||||
{
|
||||
p_sem->DbgNamePtr = (CPU_CHAR *)((void *)" ");
|
||||
p_sem->DbgPrevPtr = (OS_SEM *)0;
|
||||
if (OSSemDbgListPtr == (OS_SEM *)0) {
|
||||
p_sem->DbgNextPtr = (OS_SEM *)0;
|
||||
} else {
|
||||
p_sem->DbgNextPtr = OSSemDbgListPtr;
|
||||
OSSemDbgListPtr->DbgPrevPtr = p_sem;
|
||||
}
|
||||
OSSemDbgListPtr = p_sem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OS_SemDbgListRemove (OS_SEM *p_sem)
|
||||
{
|
||||
OS_SEM *p_sem_next;
|
||||
OS_SEM *p_sem_prev;
|
||||
|
||||
|
||||
p_sem_prev = p_sem->DbgPrevPtr;
|
||||
p_sem_next = p_sem->DbgNextPtr;
|
||||
|
||||
if (p_sem_prev == (OS_SEM *)0) {
|
||||
OSSemDbgListPtr = p_sem_next;
|
||||
if (p_sem_next != (OS_SEM *)0) {
|
||||
p_sem_next->DbgPrevPtr = (OS_SEM *)0;
|
||||
}
|
||||
p_sem->DbgNextPtr = (OS_SEM *)0;
|
||||
|
||||
} else if (p_sem_next == (OS_SEM *)0) {
|
||||
p_sem_prev->DbgNextPtr = (OS_SEM *)0;
|
||||
p_sem->DbgPrevPtr = (OS_SEM *)0;
|
||||
|
||||
} else {
|
||||
p_sem_prev->DbgNextPtr = p_sem_next;
|
||||
p_sem_next->DbgPrevPtr = p_sem_prev;
|
||||
p_sem->DbgNextPtr = (OS_SEM *)0;
|
||||
p_sem->DbgPrevPtr = (OS_SEM *)0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* SEMAPHORE INITIALIZATION
|
||||
*
|
||||
* Description: This function is called by OSInit() to initialize the semaphore management.
|
||||
*
|
||||
|
||||
* Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE the call was successful
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_SemInit (OS_ERR *p_err)
|
||||
{
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
OSSemDbgListPtr = (OS_SEM *)0;
|
||||
#endif
|
||||
|
||||
OSSemQty = (OS_OBJ_QTY)0;
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* POST TO A SEMAPHORE
|
||||
*
|
||||
* Description: This function signals a semaphore
|
||||
*
|
||||
* Arguments : p_sem is a pointer to the semaphore
|
||||
*
|
||||
* opt determines the type of POST performed:
|
||||
*
|
||||
* OS_OPT_POST_1 POST to a single waiting task
|
||||
* OS_OPT_POST_ALL POST to ALL tasks that are waiting on the semaphore
|
||||
*
|
||||
* OS_OPT_POST_NO_SCHED Do not call the scheduler
|
||||
*
|
||||
* Note(s): 1) OS_OPT_POST_NO_SCHED can be added with one of the other options.
|
||||
*
|
||||
* ts is a timestamp indicating when the post occurred.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE The call was successful and the semaphore was signaled.
|
||||
* OS_ERR_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
|
||||
* OS_ERR_OBJ_TYPE If 'p_sem' is not pointing at a semaphore
|
||||
* OS_ERR_SEM_OVF If the post would cause the semaphore count to overflow.
|
||||
*
|
||||
* Returns : The current value of the semaphore counter or 0 upon error.
|
||||
*
|
||||
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
OS_SEM_CTR OS_SemPost (OS_SEM *p_sem,
|
||||
OS_OPT opt,
|
||||
CPU_TS ts,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_OBJ_QTY cnt;
|
||||
OS_SEM_CTR ctr;
|
||||
OS_PEND_LIST *p_pend_list;
|
||||
OS_PEND_DATA *p_pend_data;
|
||||
OS_PEND_DATA *p_pend_data_next;
|
||||
OS_TCB *p_tcb;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_pend_list = &p_sem->PendList;
|
||||
if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0) { /* Any task waiting on semaphore? */
|
||||
switch (sizeof(OS_SEM_CTR)) {
|
||||
case 1u:
|
||||
if (p_sem->Ctr == DEF_INT_08U_MAX_VAL) {
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_SEM_OVF;
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2u:
|
||||
if (p_sem->Ctr == DEF_INT_16U_MAX_VAL) {
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_SEM_OVF;
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4u:
|
||||
if (p_sem->Ctr == DEF_INT_32U_MAX_VAL) {
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_SEM_OVF;
|
||||
return ((OS_SEM_CTR)0);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
p_sem->Ctr++; /* No */
|
||||
ctr = p_sem->Ctr;
|
||||
p_sem->TS = ts; /* Save timestamp in semaphore control block */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
return (ctr);
|
||||
}
|
||||
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
if ((opt & OS_OPT_POST_ALL) != (OS_OPT)0) { /* Post message to all tasks waiting? */
|
||||
cnt = p_pend_list->NbrEntries; /* Yes */
|
||||
} else {
|
||||
cnt = (OS_OBJ_QTY)1; /* No */
|
||||
}
|
||||
p_pend_data = p_pend_list->HeadPtr;
|
||||
while (cnt > 0u) {
|
||||
p_tcb = p_pend_data->TCBPtr;
|
||||
p_pend_data_next = p_pend_data->NextPtr;
|
||||
OS_Post((OS_PEND_OBJ *)((void *)p_sem),
|
||||
p_tcb,
|
||||
(void *)0,
|
||||
(OS_MSG_SIZE)0,
|
||||
ts);
|
||||
p_pend_data = p_pend_data_next;
|
||||
cnt--;
|
||||
}
|
||||
ctr = p_sem->Ctr;
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
|
||||
OSSched(); /* Run the scheduler */
|
||||
}
|
||||
*p_err = OS_ERR_NONE;
|
||||
return (ctr);
|
||||
}
|
||||
|
||||
#endif
|
||||
518
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_stat.c
Normal file
518
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_stat.c
Normal file
@@ -0,0 +1,518 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* STATISTICS MODULE
|
||||
*
|
||||
* File : OS_STAT.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_stat__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
|
||||
#if OS_CFG_STAT_TASK_EN > 0u
|
||||
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* RESET STATISTICS
|
||||
*
|
||||
* Description: This function is called by your application to reset the statistics.
|
||||
*
|
||||
* Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSStatReset (OS_ERR *p_err)
|
||||
{
|
||||
#if (OS_CFG_DBG_EN > 0u)
|
||||
OS_TCB *p_tcb;
|
||||
#if (OS_MSG_EN > 0u)
|
||||
OS_MSG_Q *p_msg_q;
|
||||
#endif
|
||||
#if (OS_CFG_Q_EN > 0u)
|
||||
OS_Q *p_q;
|
||||
#endif
|
||||
#endif
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
|
||||
OSIntQTaskTimeMax = (CPU_TS )0; /* Reset the task execution times */
|
||||
OSIntQNbrEntriesMax = (OS_OBJ_QTY)0; /* Reset the queue maximum number of entries */
|
||||
#endif
|
||||
|
||||
#if OS_CFG_STAT_TASK_EN > 0u
|
||||
OSStatTaskCPUUsageMax = 0u;
|
||||
OSStatTaskTimeMax = (CPU_TS)0;
|
||||
#endif
|
||||
|
||||
OSTickTaskTimeMax = (CPU_TS)0;
|
||||
|
||||
#if OS_CFG_TMR_EN > 0u
|
||||
OSTmrTaskTimeMax = (CPU_TS)0;
|
||||
#endif
|
||||
|
||||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||||
OSIntDisTimeMax = (CPU_TS)0; /* Reset the maximum interrupt disable time */
|
||||
#endif
|
||||
|
||||
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
|
||||
OSSchedLockTimeMax = (CPU_TS)0; /* Reset the maximum scheduler lock time */
|
||||
#endif
|
||||
|
||||
#if OS_MSG_EN > 0u
|
||||
OSMsgPool.NbrUsedMax = 0u;
|
||||
#endif
|
||||
CPU_CRITICAL_EXIT();
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_tcb = OSTaskDbgListPtr;
|
||||
CPU_CRITICAL_EXIT();
|
||||
while (p_tcb != (OS_TCB *)0) { /* Reset per-Task statistics */
|
||||
CPU_CRITICAL_ENTER();
|
||||
|
||||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||||
p_tcb->IntDisTimeMax = (CPU_TS )0;
|
||||
#endif
|
||||
|
||||
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
|
||||
p_tcb->SchedLockTimeMax = (CPU_TS )0;
|
||||
#endif
|
||||
|
||||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||||
#if OS_CFG_TASK_Q_EN > 0u
|
||||
p_tcb->MsgQPendTimeMax = (CPU_TS )0;
|
||||
#endif
|
||||
p_tcb->SemPendTimeMax = (CPU_TS )0;
|
||||
p_tcb->CtxSwCtr = (OS_CTR )0;
|
||||
p_tcb->CPUUsage = (OS_CPU_USAGE)0;
|
||||
p_tcb->CPUUsageMax = (OS_CPU_USAGE)0;
|
||||
p_tcb->CyclesTotal = (OS_CYCLES )0;
|
||||
p_tcb->CyclesTotalPrev = (OS_CYCLES )0;
|
||||
p_tcb->CyclesStart = OS_TS_GET();
|
||||
#endif
|
||||
|
||||
#if OS_CFG_TASK_Q_EN > 0u
|
||||
p_msg_q = &p_tcb->MsgQ;
|
||||
p_msg_q->NbrEntriesMax = (OS_MSG_QTY )0;
|
||||
#endif
|
||||
p_tcb = p_tcb->DbgNextPtr;
|
||||
CPU_CRITICAL_EXIT();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (OS_CFG_Q_EN > 0u) && (OS_CFG_DBG_EN > 0u)
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_q = OSQDbgListPtr;
|
||||
CPU_CRITICAL_EXIT();
|
||||
while (p_q != (OS_Q *)0) { /* Reset message queues statistics */
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_msg_q = &p_q->MsgQ;
|
||||
p_msg_q->NbrEntriesMax = (OS_MSG_QTY)0;
|
||||
p_q = p_q->DbgNextPtr;
|
||||
CPU_CRITICAL_EXIT();
|
||||
}
|
||||
#endif
|
||||
|
||||
OS_TickListResetPeak(); /* Reset tick wheel statistics */
|
||||
|
||||
#if OS_CFG_TMR_EN > 0u
|
||||
OS_TmrResetPeak();
|
||||
#endif
|
||||
|
||||
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* DETERMINE THE CPU CAPACITY
|
||||
*
|
||||
* Description: This function is called by your application to establish CPU usage by first determining how high a 32-bit
|
||||
* counter would count to in 1/10 second if no other tasks were to execute during that time. CPU usage is
|
||||
* then determined by a low priority task which keeps track of this 32-bit counter every second but this
|
||||
* time, with other tasks running. CPU usage is determined by:
|
||||
*
|
||||
* OS_Stat_IdleCtr
|
||||
* CPU Usage (%) = 100 * (1 - ------------------)
|
||||
* OS_Stat_IdleCtrMax
|
||||
*
|
||||
* Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_NONE
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSStatTaskCPUUsageInit (OS_ERR *p_err)
|
||||
{
|
||||
OS_ERR err;
|
||||
OS_TICK dly;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (OS_CFG_TMR_EN > 0u)
|
||||
OSTaskSuspend(&OSTmrTaskTCB, &err);
|
||||
if (err != OS_ERR_NONE) {
|
||||
*p_err = err;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
OSTimeDly((OS_TICK )2, /* Synchronize with clock tick */
|
||||
(OS_OPT )OS_OPT_TIME_DLY,
|
||||
(OS_ERR *)&err);
|
||||
if (err != OS_ERR_NONE) {
|
||||
*p_err = err;
|
||||
return;
|
||||
}
|
||||
CPU_CRITICAL_ENTER();
|
||||
OSStatTaskCtr = (OS_TICK)0; /* Clear idle counter */
|
||||
CPU_CRITICAL_EXIT();
|
||||
|
||||
dly = (OS_TICK)0;
|
||||
if (OSCfg_TickRate_Hz > OSCfg_StatTaskRate_Hz) {
|
||||
dly = (OS_TICK)(OSCfg_TickRate_Hz / OSCfg_StatTaskRate_Hz);
|
||||
}
|
||||
if (dly == (OS_TICK)0) {
|
||||
dly = (OS_TICK)(OSCfg_TickRate_Hz / (OS_RATE_HZ)10);
|
||||
}
|
||||
|
||||
OSTimeDly(dly, /* Determine MAX. idle counter value */
|
||||
OS_OPT_TIME_DLY,
|
||||
&err);
|
||||
|
||||
#if (OS_CFG_TMR_EN > 0u)
|
||||
OSTaskResume(&OSTmrTaskTCB, &err);
|
||||
if (err != OS_ERR_NONE) {
|
||||
*p_err = err;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
OSStatTaskTimeMax = (CPU_TS)0;
|
||||
|
||||
OSStatTaskCtrMax = OSStatTaskCtr; /* Store maximum idle counter count */
|
||||
OSStatTaskRdy = OS_STATE_RDY;
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* STATISTICS TASK
|
||||
*
|
||||
* Description: This task is internal to uC/OS-III and is used to compute some statistics about the multitasking
|
||||
* environment. Specifically, OS_StatTask() computes the CPU usage. CPU usage is determined by:
|
||||
*
|
||||
* OSStatTaskCtr
|
||||
* OSStatTaskCPUUsage = 100 * (1 - ------------------) (units are in %)
|
||||
* OSStatTaskCtrMax
|
||||
*
|
||||
* Arguments : p_arg this pointer is not used at this time.
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This task runs at a priority level higher than the idle task.
|
||||
*
|
||||
* 2) You can disable this task by setting the configuration #define OS_CFG_STAT_TASK_EN to 0.
|
||||
*
|
||||
* 3) You MUST have at least a delay of 2/10 seconds to allow for the system to establish the maximum value
|
||||
* for the idle counter.
|
||||
*
|
||||
* 4) This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_StatTask (void *p_arg)
|
||||
{
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||||
OS_CPU_USAGE usage;
|
||||
OS_CYCLES cycles_total;
|
||||
OS_CYCLES cycles_div;
|
||||
OS_CYCLES cycles_mult;
|
||||
OS_CYCLES cycles_max;
|
||||
#endif
|
||||
OS_TCB *p_tcb;
|
||||
#endif
|
||||
OS_TICK ctr_max;
|
||||
OS_TICK ctr_mult;
|
||||
OS_TICK ctr_div;
|
||||
OS_ERR err;
|
||||
OS_TICK dly;
|
||||
CPU_TS ts_start;
|
||||
CPU_TS ts_end;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */
|
||||
while (OSStatTaskRdy != DEF_TRUE) {
|
||||
OSTimeDly(2u * OSCfg_StatTaskRate_Hz, /* Wait until statistic task is ready */
|
||||
OS_OPT_TIME_DLY,
|
||||
&err);
|
||||
}
|
||||
OSStatReset(&err); /* Reset statistics */
|
||||
|
||||
dly = (OS_TICK)0; /* Compute statistic task sleep delay */
|
||||
if (OSCfg_TickRate_Hz > OSCfg_StatTaskRate_Hz) {
|
||||
dly = (OS_TICK)(OSCfg_TickRate_Hz / OSCfg_StatTaskRate_Hz);
|
||||
}
|
||||
if (dly == (OS_TICK)0) {
|
||||
dly = (OS_TICK)(OSCfg_TickRate_Hz / (OS_RATE_HZ)10);
|
||||
}
|
||||
|
||||
while (DEF_ON) {
|
||||
ts_start = OS_TS_GET();
|
||||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||||
OSIntDisTimeMax = CPU_IntDisMeasMaxGet();
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER(); /* ----------------- OVERALL CPU USAGE ------------------ */
|
||||
OSStatTaskCtrRun = OSStatTaskCtr; /* Obtain the of the stat counter for the past .1 second */
|
||||
OSStatTaskCtr = (OS_TICK)0; /* Reset the stat counter for the next .1 second */
|
||||
CPU_CRITICAL_EXIT();
|
||||
|
||||
if (OSStatTaskCtrMax > OSStatTaskCtrRun) { /* Compute CPU Usage with best resolution */
|
||||
if (OSStatTaskCtrMax < 400000u) { /* 1 to 400,000 */
|
||||
ctr_mult = 10000u;
|
||||
ctr_div = 1u;
|
||||
} else if (OSStatTaskCtrMax < 4000000u) { /* 400,000 to 4,000,000 */
|
||||
ctr_mult = 1000u;
|
||||
ctr_div = 10u;
|
||||
} else if (OSStatTaskCtrMax < 40000000u) { /* 4,000,000 to 40,000,000 */
|
||||
ctr_mult = 100u;
|
||||
ctr_div = 100u;
|
||||
} else if (OSStatTaskCtrMax < 400000000u) { /* 40,000,000 to 400,000,000 */
|
||||
ctr_mult = 10u;
|
||||
ctr_div = 1000u;
|
||||
} else { /* 400,000,000 and up */
|
||||
ctr_mult = 1u;
|
||||
ctr_div = 10000u;
|
||||
}
|
||||
ctr_max = OSStatTaskCtrMax / ctr_div;
|
||||
OSStatTaskCPUUsage = (OS_CPU_USAGE)((OS_TICK)10000u - ctr_mult * OSStatTaskCtrRun / ctr_max);
|
||||
if (OSStatTaskCPUUsageMax < OSStatTaskCPUUsage) {
|
||||
OSStatTaskCPUUsageMax = OSStatTaskCPUUsage;
|
||||
}
|
||||
} else {
|
||||
OSStatTaskCPUUsage = (OS_CPU_USAGE)10000u;
|
||||
}
|
||||
|
||||
OSStatTaskHook(); /* Invoke user definable hook */
|
||||
|
||||
|
||||
#if OS_CFG_DBG_EN > 0u
|
||||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||||
cycles_total = (OS_CYCLES)0;
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_tcb = OSTaskDbgListPtr;
|
||||
CPU_CRITICAL_EXIT();
|
||||
while (p_tcb != (OS_TCB *)0) { /* ----------------- TOTAL CYCLES COUNT ----------------- */
|
||||
OS_CRITICAL_ENTER();
|
||||
p_tcb->CyclesTotalPrev = p_tcb->CyclesTotal; /* Save accumulated # cycles into a temp variable */
|
||||
p_tcb->CyclesTotal = (OS_CYCLES)0; /* Reset total cycles for task for next run */
|
||||
OS_CRITICAL_EXIT();
|
||||
|
||||
cycles_total += p_tcb->CyclesTotalPrev;/* Perform sum of all task # cycles */
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_tcb = p_tcb->DbgNextPtr;
|
||||
CPU_CRITICAL_EXIT();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||||
/* ------------- INDIVIDUAL TASK CPU USAGE -------------- */
|
||||
if (cycles_total > (OS_CYCLES)0u) { /* 'cycles_total' scaling ... */
|
||||
if (cycles_total < 400000u) { /* 1 to 400,000 */
|
||||
cycles_mult = 10000u;
|
||||
cycles_div = 1u;
|
||||
} else if (cycles_total < 4000000u) { /* 400,000 to 4,000,000 */
|
||||
cycles_mult = 1000u;
|
||||
cycles_div = 10u;
|
||||
} else if (cycles_total < 40000000u) { /* 4,000,000 to 40,000,000 */
|
||||
cycles_mult = 100u;
|
||||
cycles_div = 100u;
|
||||
} else if (cycles_total < 400000000u) { /* 40,000,000 to 400,000,000 */
|
||||
cycles_mult = 10u;
|
||||
cycles_div = 1000u;
|
||||
} else { /* 400,000,000 and up */
|
||||
cycles_mult = 1u;
|
||||
cycles_div = 10000u;
|
||||
}
|
||||
cycles_max = cycles_total / cycles_div;
|
||||
} else {
|
||||
cycles_mult = 0u;
|
||||
cycles_max = 1u;
|
||||
}
|
||||
#endif
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_tcb = OSTaskDbgListPtr;
|
||||
CPU_CRITICAL_EXIT();
|
||||
while (p_tcb != (OS_TCB *)0) {
|
||||
#if OS_CFG_TASK_PROFILE_EN > 0u /* Compute execution time of each task */
|
||||
usage = (OS_CPU_USAGE)(cycles_mult * p_tcb->CyclesTotalPrev / cycles_max);
|
||||
if (usage > 10000u) {
|
||||
usage = 10000u;
|
||||
}
|
||||
p_tcb->CPUUsage = usage;
|
||||
if (p_tcb->CPUUsageMax < usage) { /* Detect peak CPU usage */
|
||||
p_tcb->CPUUsageMax = usage;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_STAT_TASK_STK_CHK_EN > 0u
|
||||
OSTaskStkChk( p_tcb, /* Compute stack usage of active tasks only */
|
||||
&p_tcb->StkFree,
|
||||
&p_tcb->StkUsed,
|
||||
&err);
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
p_tcb = p_tcb->DbgNextPtr;
|
||||
CPU_CRITICAL_EXIT();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (OSStatResetFlag == DEF_TRUE) { /* Check if need to reset statistics */
|
||||
OSStatResetFlag = DEF_FALSE;
|
||||
OSStatReset(&err);
|
||||
}
|
||||
|
||||
ts_end = OS_TS_GET() - ts_start; /* Measure execution time of statistic task */
|
||||
if (OSStatTaskTimeMax < ts_end) {
|
||||
OSStatTaskTimeMax = ts_end;
|
||||
}
|
||||
|
||||
OSTimeDly(dly,
|
||||
OS_OPT_TIME_DLY,
|
||||
&err);
|
||||
}
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INITIALIZE THE STATISTICS
|
||||
*
|
||||
* Description: This function is called by OSInit() to initialize the statistic task.
|
||||
*
|
||||
* Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
*
|
||||
* OS_ERR_STK_INVALID If you specified a NULL stack pointer during configuration
|
||||
* OS_ERR_STK_SIZE_INVALID If you didn't specify a large enough stack.
|
||||
* OS_ERR_PRIO_INVALID If you specified a priority for the statistic task equal to or
|
||||
* lower (i.e. higher number) than the idle task.
|
||||
* OS_ERR_xxx An error code returned by OSTaskCreate()
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_StatTaskInit (OS_ERR *p_err)
|
||||
{
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
OSStatTaskCtr = (OS_TICK)0;
|
||||
OSStatTaskCtrRun = (OS_TICK)0;
|
||||
OSStatTaskCtrMax = (OS_TICK)0;
|
||||
OSStatTaskRdy = OS_STATE_NOT_RDY; /* Statistic task is not ready */
|
||||
OSStatResetFlag = DEF_FALSE;
|
||||
|
||||
/* ---------------- CREATE THE STAT TASK ---------------- */
|
||||
if (OSCfg_StatTaskStkBasePtr == (CPU_STK *)0) {
|
||||
*p_err = OS_ERR_STAT_STK_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
if (OSCfg_StatTaskStkSize < OSCfg_StkSizeMin) {
|
||||
*p_err = OS_ERR_STAT_STK_SIZE_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
if (OSCfg_StatTaskPrio >= (OS_CFG_PRIO_MAX - 1u)) {
|
||||
*p_err = OS_ERR_STAT_PRIO_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
OSTaskCreate((OS_TCB *)&OSStatTaskTCB,
|
||||
(CPU_CHAR *)((void *)"uC/OS-III Stat Task"),
|
||||
(OS_TASK_PTR )OS_StatTask,
|
||||
(void *)0,
|
||||
(OS_PRIO )OSCfg_StatTaskPrio,
|
||||
(CPU_STK *)OSCfg_StatTaskStkBasePtr,
|
||||
(CPU_STK_SIZE)OSCfg_StatTaskStkLimit,
|
||||
(CPU_STK_SIZE)OSCfg_StatTaskStkSize,
|
||||
(OS_MSG_QTY )0,
|
||||
(OS_TICK )0,
|
||||
(void *)0,
|
||||
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
|
||||
(OS_ERR *)p_err);
|
||||
}
|
||||
|
||||
#endif
|
||||
2550
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_task.c
Normal file
2550
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_task.c
Normal file
File diff suppressed because it is too large
Load Diff
517
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_tick.c
Normal file
517
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_tick.c
Normal file
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* TICK MANAGEMENT
|
||||
*
|
||||
* File : OS_TICK.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_tick__c = "$Id: $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* LOCAL PROTOTYPES
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* TICK TASK
|
||||
*
|
||||
* Description: This task is internal to uC/OS-III and is triggered by the tick interrupt.
|
||||
*
|
||||
* Arguments : p_arg is an argument passed to the task when the task is created (unused).
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_TickTask (void *p_arg)
|
||||
{
|
||||
OS_ERR err;
|
||||
CPU_TS ts;
|
||||
|
||||
|
||||
p_arg = p_arg; /* Prevent compiler warning */
|
||||
|
||||
while (DEF_ON) {
|
||||
(void)OSTaskSemPend((OS_TICK )0,
|
||||
(OS_OPT )OS_OPT_PEND_BLOCKING,
|
||||
(CPU_TS *)&ts,
|
||||
(OS_ERR *)&err); /* Wait for signal from tick interrupt */
|
||||
if (err == OS_ERR_NONE) {
|
||||
if (OSRunning == OS_STATE_OS_RUNNING) {
|
||||
OS_TickListUpdate(); /* Update all tasks waiting for time */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INITIALIZE TICK TASK
|
||||
*
|
||||
* Description: This function is called by OSInit() to create the tick task.
|
||||
*
|
||||
* Arguments : p_err is a pointer to a variable that will hold the value of an error code:
|
||||
*
|
||||
* OS_ERR_TICK_STK_INVALID if the pointer to the tick task stack is a NULL pointer
|
||||
* OS_ERR_TICK_STK_SIZE indicates that the specified stack size
|
||||
* OS_ERR_PRIO_INVALID if the priority you specified in the configuration is invalid
|
||||
* (There could be only one task at the Idle Task priority)
|
||||
* (Maybe the priority you specified is higher than OS_CFG_PRIO_MAX-1
|
||||
* OS_ERR_?? other error code returned by OSTaskCreate()
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_TickTaskInit (OS_ERR *p_err)
|
||||
{
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
OSTickCtr = (OS_TICK)0u; /* Clear the tick counter */
|
||||
|
||||
OSTickTaskTimeMax = (CPU_TS)0u;
|
||||
|
||||
|
||||
OS_TickListInit(); /* Initialize the tick list data structures */
|
||||
|
||||
/* ---------------- CREATE THE TICK TASK ---------------- */
|
||||
if (OSCfg_TickTaskStkBasePtr == (CPU_STK *)0) {
|
||||
*p_err = OS_ERR_TICK_STK_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
if (OSCfg_TickTaskStkSize < OSCfg_StkSizeMin) {
|
||||
*p_err = OS_ERR_TICK_STK_SIZE_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
if (OSCfg_TickTaskPrio >= (OS_CFG_PRIO_MAX - 1u)) { /* Only one task at the 'Idle Task' priority */
|
||||
*p_err = OS_ERR_TICK_PRIO_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
OSTaskCreate((OS_TCB *)&OSTickTaskTCB,
|
||||
(CPU_CHAR *)((void *)"uC/OS-III Tick Task"),
|
||||
(OS_TASK_PTR )OS_TickTask,
|
||||
(void *)0,
|
||||
(OS_PRIO )OSCfg_TickTaskPrio,
|
||||
(CPU_STK *)OSCfg_TickTaskStkBasePtr,
|
||||
(CPU_STK_SIZE)OSCfg_TickTaskStkLimit,
|
||||
(CPU_STK_SIZE)OSCfg_TickTaskStkSize,
|
||||
(OS_MSG_QTY )0u,
|
||||
(OS_TICK )0u,
|
||||
(void *)0,
|
||||
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR | OS_OPT_TASK_NO_TLS),
|
||||
(OS_ERR *)p_err);
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INITIALIZE THE TICK LIST
|
||||
*
|
||||
* Description: This function initializes the tick handling data structures of uC/OS-III.
|
||||
*
|
||||
* Arguments : none
|
||||
*
|
||||
* Returns : None
|
||||
*
|
||||
* Note(s) : This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_TickListInit (void)
|
||||
{
|
||||
OS_TICK_SPOKE_IX i;
|
||||
OS_TICK_SPOKE *p_spoke;
|
||||
|
||||
|
||||
|
||||
for (i = 0u; i < OSCfg_TickWheelSize; i++) {
|
||||
p_spoke = (OS_TICK_SPOKE *)&OSCfg_TickWheel[i];
|
||||
p_spoke->FirstPtr = (OS_TCB *)0;
|
||||
p_spoke->NbrEntries = (OS_OBJ_QTY )0u;
|
||||
p_spoke->NbrEntriesMax = (OS_OBJ_QTY )0u;
|
||||
}
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* ADD TASK TO TICK LIST
|
||||
*
|
||||
* Description: This function is called to place a task in a list of task waiting for either time to expire or waiting to
|
||||
* timeout on a pend call.
|
||||
*
|
||||
* Arguments : p_tcb is a pointer to the OS_TCB of the task to add to the tick list
|
||||
* -----
|
||||
*
|
||||
* time represents either the 'match' value of OSTickCtr or a relative time from the current
|
||||
* value of OSTickCtr as specified by the 'opt' argument..
|
||||
*
|
||||
* relative when 'opt' is set to OS_OPT_TIME_DLY
|
||||
* relative when 'opt' is set to OS_OPT_TIME_TIMEOUT
|
||||
* match when 'opt' is set to OS_OPT_TIME_MATCH
|
||||
* periodic when 'opt' is set to OS_OPT_TIME_PERIODIC
|
||||
*
|
||||
* opt is an option specifying how to calculate time. The valid values are:
|
||||
* ---
|
||||
* OS_OPT_TIME_DLY
|
||||
* OS_OPT_TIME_TIMEOUT
|
||||
* OS_OPT_TIME_PERIODIC
|
||||
* OS_OPT_TIME_MATCH
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||||
* -----
|
||||
* OS_ERR_NONE the call was successful and the time delay was scheduled.
|
||||
* OS_ERR_TIME_ZERO_DLY if delay is zero or already occurred.
|
||||
*
|
||||
* Returns : None
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
*
|
||||
* 2) This function is assumed to be called with interrupts disabled.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_TickListInsert (OS_TCB *p_tcb,
|
||||
OS_TICK time,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
OS_TICK tick_delta;
|
||||
OS_TICK tick_next;
|
||||
OS_TICK_SPOKE *p_spoke;
|
||||
OS_TCB *p_tcb0;
|
||||
OS_TCB *p_tcb1;
|
||||
OS_TICK_SPOKE_IX spoke;
|
||||
|
||||
|
||||
|
||||
if (opt == OS_OPT_TIME_MATCH) { /* Task time is absolute. */
|
||||
tick_delta = time - OSTickCtr - 1u;
|
||||
if (tick_delta > OS_TICK_TH_RDY) { /* If delay already occurred, ... */
|
||||
p_tcb->TickCtrMatch = (OS_TICK )0u;
|
||||
p_tcb->TickRemain = (OS_TICK )0u;
|
||||
p_tcb->TickSpokePtr = (OS_TICK_SPOKE *)0;
|
||||
*p_err = OS_ERR_TIME_ZERO_DLY; /* ... do NOT delay. */
|
||||
return;
|
||||
}
|
||||
p_tcb->TickCtrMatch = time;
|
||||
p_tcb->TickRemain = tick_delta + 1u;
|
||||
|
||||
} else if (time > (OS_TICK)0u) {
|
||||
if (opt == OS_OPT_TIME_PERIODIC) { /* Task time is periodic. */
|
||||
tick_next = p_tcb->TickCtrPrev + time;
|
||||
tick_delta = tick_next - OSTickCtr - 1u;
|
||||
if (tick_delta < time) { /* If next periodic delay did NOT already occur, ... */
|
||||
p_tcb->TickCtrMatch = tick_next; /* ... set next periodic delay; ... */
|
||||
} else {
|
||||
p_tcb->TickCtrMatch = OSTickCtr + time; /* ... else reset periodic delay. */
|
||||
}
|
||||
p_tcb->TickRemain = p_tcb->TickCtrMatch - OSTickCtr;
|
||||
p_tcb->TickCtrPrev = p_tcb->TickCtrMatch;
|
||||
|
||||
} else { /* Task time is relative to current. */
|
||||
p_tcb->TickCtrMatch = OSTickCtr + time;
|
||||
p_tcb->TickRemain = time;
|
||||
}
|
||||
|
||||
} else { /* Zero time delay; ... */
|
||||
p_tcb->TickCtrMatch = (OS_TICK )0u;
|
||||
p_tcb->TickRemain = (OS_TICK )0u;
|
||||
p_tcb->TickSpokePtr = (OS_TICK_SPOKE *)0;
|
||||
*p_err = OS_ERR_TIME_ZERO_DLY; /* ... do NOT delay. */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
spoke = (OS_TICK_SPOKE_IX)(p_tcb->TickCtrMatch % OSCfg_TickWheelSize);
|
||||
p_spoke = &OSCfg_TickWheel[spoke];
|
||||
|
||||
if (p_spoke->NbrEntries == (OS_OBJ_QTY)0u) { /* First entry in the spoke */
|
||||
p_tcb->TickNextPtr = (OS_TCB *)0;
|
||||
p_tcb->TickPrevPtr = (OS_TCB *)0;
|
||||
p_spoke->FirstPtr = p_tcb;
|
||||
p_spoke->NbrEntries = (OS_OBJ_QTY)1u;
|
||||
} else {
|
||||
p_tcb1 = p_spoke->FirstPtr; /* Point to current first TCB in the list */
|
||||
while (p_tcb1 != (OS_TCB *)0) {
|
||||
p_tcb1->TickRemain = p_tcb1->TickCtrMatch /* Compute time remaining of current TCB in list */
|
||||
- OSTickCtr;
|
||||
if (p_tcb->TickRemain > p_tcb1->TickRemain) { /* Do we need to insert AFTER current TCB in list? */
|
||||
if (p_tcb1->TickNextPtr != (OS_TCB *)0) { /* Yes, are we pointing at the last TCB in the list? */
|
||||
p_tcb1 = p_tcb1->TickNextPtr; /* No, Point to next TCB in the list */
|
||||
} else {
|
||||
p_tcb->TickNextPtr = (OS_TCB *)0;
|
||||
p_tcb->TickPrevPtr = p_tcb1;
|
||||
p_tcb1->TickNextPtr = p_tcb; /* Yes, TCB to add is now new last entry in the list */
|
||||
p_tcb1 = (OS_TCB *)0; /* Break loop */
|
||||
}
|
||||
} else { /* Insert before the current TCB */
|
||||
if (p_tcb1->TickPrevPtr == (OS_TCB *)0) { /* Are we inserting before the first TCB? */
|
||||
p_tcb->TickPrevPtr = (OS_TCB *)0;
|
||||
p_tcb->TickNextPtr = p_tcb1;
|
||||
p_tcb1->TickPrevPtr = p_tcb;
|
||||
p_spoke->FirstPtr = p_tcb;
|
||||
} else { /* Insert in between 2 TCBs already in the list */
|
||||
p_tcb0 = p_tcb1->TickPrevPtr;
|
||||
p_tcb->TickPrevPtr = p_tcb0;
|
||||
p_tcb->TickNextPtr = p_tcb1;
|
||||
p_tcb0->TickNextPtr = p_tcb;
|
||||
p_tcb1->TickPrevPtr = p_tcb;
|
||||
}
|
||||
p_tcb1 = (OS_TCB *)0; /* Break loop */
|
||||
}
|
||||
}
|
||||
p_spoke->NbrEntries++;
|
||||
}
|
||||
if (p_spoke->NbrEntriesMax < p_spoke->NbrEntries) { /* Keep track of maximum # of entries in each spoke */
|
||||
p_spoke->NbrEntriesMax = p_spoke->NbrEntries;
|
||||
}
|
||||
p_tcb->TickSpokePtr = p_spoke; /* Link back to tick spoke */
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* REMOVE A TASK FROM THE TICK LIST
|
||||
*
|
||||
* Description: This function is called to remove a task from the tick list
|
||||
*
|
||||
* Arguments : p_tcb Is a pointer to the OS_TCB to remove.
|
||||
* -----
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
*
|
||||
* 2) This function is assumed to be called with interrupts disabled.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_TickListRemove (OS_TCB *p_tcb)
|
||||
{
|
||||
OS_TICK_SPOKE *p_spoke;
|
||||
OS_TCB *p_tcb1;
|
||||
OS_TCB *p_tcb2;
|
||||
|
||||
|
||||
|
||||
p_spoke = p_tcb->TickSpokePtr;
|
||||
if (p_spoke != (OS_TICK_SPOKE *)0) { /* Confirm that task is in tick list */
|
||||
p_tcb->TickRemain = (OS_TICK)0u;
|
||||
if (p_spoke->FirstPtr == p_tcb) { /* Is timer to remove at the beginning of list? */
|
||||
p_tcb1 = (OS_TCB *)p_tcb->TickNextPtr; /* Yes */
|
||||
p_spoke->FirstPtr = p_tcb1;
|
||||
if (p_tcb1 != (OS_TCB *)0) {
|
||||
p_tcb1->TickPrevPtr = (OS_TCB *)0;
|
||||
}
|
||||
} else {
|
||||
p_tcb1 = p_tcb->TickPrevPtr; /* No, remove timer from somewhere in the list */
|
||||
p_tcb2 = p_tcb->TickNextPtr;
|
||||
p_tcb1->TickNextPtr = p_tcb2;
|
||||
if (p_tcb2 != (OS_TCB *)0) {
|
||||
p_tcb2->TickPrevPtr = p_tcb1;
|
||||
}
|
||||
}
|
||||
p_tcb->TickNextPtr = (OS_TCB *)0;
|
||||
p_tcb->TickPrevPtr = (OS_TCB *)0;
|
||||
p_tcb->TickSpokePtr = (OS_TICK_SPOKE *)0;
|
||||
p_tcb->TickCtrMatch = (OS_TICK )0u;
|
||||
p_spoke->NbrEntries--;
|
||||
}
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* RESET TICK LIST PEAK DETECTOR
|
||||
*
|
||||
* Description: This function is used to reset the peak detector for the number of entries in each spoke.
|
||||
*
|
||||
* Arguments : void
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
void OS_TickListResetPeak (void)
|
||||
{
|
||||
OS_TICK_SPOKE_IX i;
|
||||
OS_TICK_SPOKE *p_spoke;
|
||||
|
||||
|
||||
|
||||
for (i = 0u; i < OSCfg_TickWheelSize; i++) {
|
||||
p_spoke = (OS_TICK_SPOKE *)&OSCfg_TickWheel[i];
|
||||
p_spoke->NbrEntriesMax = (OS_OBJ_QTY )0u;
|
||||
}
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* UPDATE THE TICK LIST
|
||||
*
|
||||
* Description: This function is called when a tick occurs and determines if the timeout waiting for a kernel object has
|
||||
* expired or a delay has expired.
|
||||
*
|
||||
* Arguments : non
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OS_TickListUpdate (void)
|
||||
{
|
||||
CPU_BOOLEAN done;
|
||||
OS_TICK_SPOKE *p_spoke;
|
||||
OS_TCB *p_tcb;
|
||||
OS_TCB *p_tcb_next;
|
||||
OS_TICK_SPOKE_IX spoke;
|
||||
CPU_TS ts_start;
|
||||
CPU_TS ts_end;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
OS_CRITICAL_ENTER();
|
||||
ts_start = OS_TS_GET();
|
||||
OSTickCtr++; /* Keep track of the number of ticks */
|
||||
spoke = (OS_TICK_SPOKE_IX)(OSTickCtr % OSCfg_TickWheelSize);
|
||||
p_spoke = &OSCfg_TickWheel[spoke];
|
||||
p_tcb = p_spoke->FirstPtr;
|
||||
done = DEF_FALSE;
|
||||
while (done == DEF_FALSE) {
|
||||
if (p_tcb != (OS_TCB *)0) {
|
||||
p_tcb_next = p_tcb->TickNextPtr; /* Point to next TCB to update */
|
||||
switch (p_tcb->TaskState) {
|
||||
case OS_TASK_STATE_RDY:
|
||||
case OS_TASK_STATE_PEND:
|
||||
case OS_TASK_STATE_SUSPENDED:
|
||||
case OS_TASK_STATE_PEND_SUSPENDED:
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_DLY:
|
||||
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
|
||||
- OSTickCtr;
|
||||
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
|
||||
p_tcb->TaskState = OS_TASK_STATE_RDY;
|
||||
OS_TaskRdy(p_tcb); /* Make task ready to run */
|
||||
} else {
|
||||
done = DEF_TRUE; /* Don't find a match, we're done! */
|
||||
}
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_PEND_TIMEOUT:
|
||||
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
|
||||
- OSTickCtr;
|
||||
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
|
||||
#if (OS_MSG_EN > 0u)
|
||||
p_tcb->MsgPtr = (void *)0;
|
||||
p_tcb->MsgSize = (OS_MSG_SIZE)0u;
|
||||
#endif
|
||||
p_tcb->TS = OS_TS_GET();
|
||||
OS_PendListRemove(p_tcb); /* Remove from wait list */
|
||||
OS_TaskRdy(p_tcb);
|
||||
p_tcb->TaskState = OS_TASK_STATE_RDY;
|
||||
p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */
|
||||
p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */
|
||||
} else {
|
||||
done = DEF_TRUE; /* Don't find a match, we're done! */
|
||||
}
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_DLY_SUSPENDED:
|
||||
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
|
||||
- OSTickCtr;
|
||||
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
|
||||
p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
|
||||
OS_TickListRemove(p_tcb); /* Remove from current wheel spoke */
|
||||
} else {
|
||||
done = DEF_TRUE; /* Don't find a match, we're done! */
|
||||
}
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
|
||||
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
|
||||
- OSTickCtr;
|
||||
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
|
||||
#if (OS_MSG_EN > 0u)
|
||||
p_tcb->MsgPtr = (void *)0;
|
||||
p_tcb->MsgSize = (OS_MSG_SIZE)0u;
|
||||
#endif
|
||||
p_tcb->TS = OS_TS_GET();
|
||||
OS_PendListRemove(p_tcb); /* Remove from wait list */
|
||||
OS_TickListRemove(p_tcb); /* Remove from current wheel spoke */
|
||||
p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
|
||||
p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */
|
||||
p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */
|
||||
} else {
|
||||
done = DEF_TRUE; /* Don't find a match, we're done! */
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
p_tcb = p_tcb_next;
|
||||
} else {
|
||||
done = DEF_TRUE;
|
||||
}
|
||||
}
|
||||
ts_end = OS_TS_GET() - ts_start; /* Measure execution time of tick task */
|
||||
if (OSTickTaskTimeMax < ts_end) {
|
||||
OSTickTaskTimeMax = ts_end;
|
||||
}
|
||||
OS_CRITICAL_EXIT();
|
||||
}
|
||||
572
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_time.c
Normal file
572
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_time.c
Normal file
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* TIME MANAGEMENT
|
||||
*
|
||||
* File : OS_TIME.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_time__c = "$Id: $";
|
||||
#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 : dly is a value in 'clock ticks' that the task will either delay for or, the target match value
|
||||
* of the tick counter (OSTickCtr). Note that specifying 0 means the task is not to delay.
|
||||
*
|
||||
* depending on the option argument, the task will wake up when OSTickCtr reaches:
|
||||
*
|
||||
* OS_OPT_TIME_DLY : OSTickCtr + dly
|
||||
* OS_OPT_TIME_TIMEOUT : OSTickCtr + dly
|
||||
* OS_OPT_TIME_MATCH : dly
|
||||
* OS_OPT_TIME_PERIODIC : OSTCBCurPtr->TickCtrPrev + dly
|
||||
*
|
||||
* opt specifies whether 'dly' represents absolute or relative time; default option marked with *** :
|
||||
*
|
||||
* *** OS_OPT_TIME_DLY specifies a relative time from the current value of OSTickCtr.
|
||||
* OS_OPT_TIME_TIMEOUT same as OS_OPT_TIME_DLY.
|
||||
* OS_OPT_TIME_MATCH indicates that 'dly' specifies the absolute value that OSTickCtr
|
||||
* must reach before the task will be resumed.
|
||||
* OS_OPT_TIME_PERIODIC indicates that 'dly' specifies the periodic value that OSTickCtr
|
||||
* must reach before the task will be resumed.
|
||||
*
|
||||
* p_err is a pointer to a variable that will contain an error code from this call.
|
||||
*
|
||||
* OS_ERR_NONE the call was successful and the delay occurred.
|
||||
* OS_ERR_OPT_INVALID if you specified an invalid option for this function.
|
||||
* OS_ERR_SCHED_LOCKED can't delay when the scheduler is locked.
|
||||
* OS_ERR_TIME_DLY_ISR if you called this function from an ISR.
|
||||
* OS_ERR_TIME_ZERO_DLY if you specified a delay of zero.
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTimeDly (OS_TICK dly,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to call from an ISR */
|
||||
*p_err = OS_ERR_TIME_DLY_ISR;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u) { /* Can't delay when the scheduler is locked */
|
||||
*p_err = OS_ERR_SCHED_LOCKED;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case OS_OPT_TIME_DLY:
|
||||
case OS_OPT_TIME_TIMEOUT:
|
||||
case OS_OPT_TIME_PERIODIC:
|
||||
if (dly == (OS_TICK)0u) { /* 0 means no delay! */
|
||||
*p_err = OS_ERR_TIME_ZERO_DLY;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case OS_OPT_TIME_MATCH:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
OS_CRITICAL_ENTER();
|
||||
OSTCBCurPtr->TaskState = OS_TASK_STATE_DLY;
|
||||
OS_TickListInsert(OSTCBCurPtr,
|
||||
dly,
|
||||
opt,
|
||||
p_err);
|
||||
if (*p_err != OS_ERR_NONE) {
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
return;
|
||||
}
|
||||
OS_RdyListRemove(OSTCBCurPtr); /* Remove current task from ready list */
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
OSSched(); /* Find next task to run! */
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$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 999 if the tick rate is
|
||||
* 1000 Hz or less otherwise, a higher value would overflow a 32-bit unsigned counter).
|
||||
*
|
||||
* minutes specifies the number of minutes (max. 59 if 'opt' is OS_OPT_TIME_HMSM_STRICT)
|
||||
*
|
||||
* seconds specifies the number of seconds (max. 59 if 'opt' is OS_OPT_TIME_HMSM_STRICT)
|
||||
*
|
||||
* milli specifies the number of milliseconds (max. 999 if 'opt' is OS_OPT_TIME_HMSM_STRICT)
|
||||
*
|
||||
* opt specifies time delay bit-field options logically OR'd; default options marked with *** :
|
||||
*
|
||||
* *** OS_OPT_TIME_DLY specifies a relative time from the current value of OSTickCtr.
|
||||
* OS_OPT_TIME_TIMEOUT same as OS_OPT_TIME_DLY.
|
||||
* OS_OPT_TIME_MATCH indicates that the delay specifies the absolute value that OSTickCtr
|
||||
* must reach before the task will be resumed.
|
||||
* OS_OPT_TIME_PERIODIC indicates that the delay specifies the periodic value that OSTickCtr
|
||||
* must reach before the task will be resumed.
|
||||
*
|
||||
* *** OS_OPT_TIME_HMSM_STRICT strictly allow only hours (0...99)
|
||||
* minutes (0...59)
|
||||
* seconds (0...59)
|
||||
* milliseconds (0...999)
|
||||
* OS_OPT_TIME_HMSM_NON_STRICT allow any value of hours (0...999)
|
||||
* minutes (0...9999)
|
||||
* seconds (0...65535)
|
||||
* milliseconds (0...4294967295)
|
||||
*
|
||||
* p_err is a pointer to a variable that will receive an error code from this call.
|
||||
*
|
||||
* OS_ERR_NONE If the function returns from the desired delay
|
||||
* OS_ERR_OPT_INVALID If you specified an invalid option for 'opt'
|
||||
* OS_ERR_SCHED_LOCKED Can't delay when the scheduler is locked
|
||||
* OS_ERR_TIME_DLY_ISR If called from an ISR
|
||||
* OS_ERR_TIME_INVALID_HOURS If you didn't specify a valid value for 'hours'
|
||||
* OS_ERR_TIME_INVALID_MINUTES If you didn't specify a valid value for 'minutes'
|
||||
* OS_ERR_TIME_INVALID_SECONDS If you didn't specify a valid value for 'seconds'
|
||||
* OS_ERR_TIME_INVALID_MILLISECONDS If you didn't specify a valid value for 'milli'
|
||||
* OS_ERR_TIME_ZERO_DLY If hours, minutes, seconds and milli are all 0
|
||||
*
|
||||
* Returns : none
|
||||
*
|
||||
* Note(s) : 1) 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.
|
||||
*
|
||||
* 2) Although this function allows you to delay a task for many, many hours, it's not recommended to put
|
||||
* a task to sleep for that long.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#if OS_CFG_TIME_DLY_HMSM_EN > 0u
|
||||
void OSTimeDlyHMSM (CPU_INT16U hours,
|
||||
CPU_INT16U minutes,
|
||||
CPU_INT16U seconds,
|
||||
CPU_INT32U milli,
|
||||
OS_OPT opt,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
CPU_BOOLEAN opt_invalid;
|
||||
CPU_BOOLEAN opt_non_strict;
|
||||
#endif
|
||||
OS_OPT opt_time;
|
||||
OS_RATE_HZ tick_rate;
|
||||
OS_TICK ticks;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to call from an ISR */
|
||||
*p_err = OS_ERR_TIME_DLY_ISR;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u) { /* Can't delay when the scheduler is locked */
|
||||
*p_err = OS_ERR_SCHED_LOCKED;
|
||||
return;
|
||||
}
|
||||
|
||||
opt_time = opt & OS_OPT_TIME_MASK; /* Retrieve time options only. */
|
||||
switch (opt_time) {
|
||||
case OS_OPT_TIME_DLY:
|
||||
case OS_OPT_TIME_TIMEOUT:
|
||||
case OS_OPT_TIME_PERIODIC:
|
||||
if (milli == (CPU_INT32U)0u) { /* Make sure we didn't specify a 0 delay */
|
||||
if (seconds == (CPU_INT16U)0u) {
|
||||
if (minutes == (CPU_INT16U)0u) {
|
||||
if (hours == (CPU_INT16U)0u) {
|
||||
*p_err = OS_ERR_TIME_ZERO_DLY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OS_OPT_TIME_MATCH:
|
||||
break;
|
||||
|
||||
default:
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u /* Validate arguments to be within range */
|
||||
opt_invalid = DEF_BIT_IS_SET_ANY(opt, ~OS_OPT_TIME_OPTS_MASK);
|
||||
if (opt_invalid == DEF_YES) {
|
||||
*p_err = OS_ERR_OPT_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
opt_non_strict = DEF_BIT_IS_SET(opt, OS_OPT_TIME_HMSM_NON_STRICT);
|
||||
if (opt_non_strict != DEF_YES) {
|
||||
if (milli > (CPU_INT32U)999u) {
|
||||
*p_err = OS_ERR_TIME_INVALID_MILLISECONDS;
|
||||
return;
|
||||
}
|
||||
if (seconds > (CPU_INT16U)59u) {
|
||||
*p_err = OS_ERR_TIME_INVALID_SECONDS;
|
||||
return;
|
||||
}
|
||||
if (minutes > (CPU_INT16U)59u) {
|
||||
*p_err = OS_ERR_TIME_INVALID_MINUTES;
|
||||
return;
|
||||
}
|
||||
if (hours > (CPU_INT16U)99u) {
|
||||
*p_err = OS_ERR_TIME_INVALID_HOURS;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (minutes > (CPU_INT16U)9999u) {
|
||||
*p_err = OS_ERR_TIME_INVALID_MINUTES;
|
||||
return;
|
||||
}
|
||||
if (hours > (CPU_INT16U)999u) {
|
||||
*p_err = OS_ERR_TIME_INVALID_HOURS;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Compute the total number of clock ticks required.. */
|
||||
/* .. (rounded to the nearest tick) */
|
||||
tick_rate = OSCfg_TickRate_Hz;
|
||||
ticks = ((OS_TICK)hours * (OS_TICK)3600u + (OS_TICK)minutes * (OS_TICK)60u + (OS_TICK)seconds) * tick_rate
|
||||
+ (tick_rate * ((OS_TICK)milli + (OS_TICK)500u / tick_rate)) / (OS_TICK)1000u;
|
||||
|
||||
if (ticks > (OS_TICK)0u) {
|
||||
OS_CRITICAL_ENTER();
|
||||
OSTCBCurPtr->TaskState = OS_TASK_STATE_DLY;
|
||||
OS_TickListInsert(OSTCBCurPtr,
|
||||
ticks,
|
||||
opt_time,
|
||||
p_err);
|
||||
if (*p_err != OS_ERR_NONE) {
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
return;
|
||||
}
|
||||
OS_RdyListRemove(OSTCBCurPtr); /* Remove current task from ready list */
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
OSSched(); /* Find next task to run! */
|
||||
*p_err = OS_ERR_NONE;
|
||||
} else {
|
||||
*p_err = OS_ERR_TIME_ZERO_DLY;
|
||||
}
|
||||
}
|
||||
#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 cannot call this function to resume a task that is waiting for an event
|
||||
* with timeout.
|
||||
*
|
||||
* Arguments : p_tcb is a pointer to the TCB of the task to resume.
|
||||
*
|
||||
* p_err is a pointer to a variable that will receive an error code
|
||||
*
|
||||
* OS_ERR_NONE Task has been resumed
|
||||
* OS_ERR_STATE_INVALID Task is in an invalid state
|
||||
* OS_ERR_TIME_DLY_RESUME_ISR If called from an ISR
|
||||
* OS_ERR_TIME_NOT_DLY Task is not waiting for time to expire
|
||||
* OS_ERR_TASK_SUSPENDED Task cannot be resumed, it was suspended by OSTaskSuspend()
|
||||
*
|
||||
* Note(s) : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#if OS_CFG_TIME_DLY_RESUME_EN > 0u
|
||||
void OSTimeDlyResume (OS_TCB *p_tcb,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
|
||||
if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to call from an ISR */
|
||||
*p_err = OS_ERR_TIME_DLY_RESUME_ISR;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_CFG_ARG_CHK_EN > 0u
|
||||
if (p_tcb == (OS_TCB *)0) { /* Not possible for the running task to be delayed! */
|
||||
*p_err = OS_ERR_TASK_NOT_DLY;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
if (p_tcb == OSTCBCurPtr) { /* Not possible for the running task to be delayed! */
|
||||
*p_err = OS_ERR_TASK_NOT_DLY;
|
||||
CPU_CRITICAL_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (p_tcb->TaskState) {
|
||||
case OS_TASK_STATE_RDY: /* Cannot Abort delay if task is ready */
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_TASK_NOT_DLY;
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_DLY:
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
p_tcb->TaskState = OS_TASK_STATE_RDY;
|
||||
OS_TickListRemove(p_tcb); /* Remove task from tick list */
|
||||
OS_RdyListInsert(p_tcb); /* Add to ready list */
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
*p_err = OS_ERR_NONE;
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_PEND:
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_TASK_NOT_DLY;
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_PEND_TIMEOUT:
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_TASK_NOT_DLY;
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_SUSPENDED:
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_TASK_NOT_DLY;
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_DLY_SUSPENDED:
|
||||
OS_CRITICAL_ENTER_CPU_EXIT();
|
||||
p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
|
||||
OS_TickListRemove(p_tcb); /* Remove task from tick list */
|
||||
OS_CRITICAL_EXIT_NO_SCHED();
|
||||
*p_err = OS_ERR_TASK_SUSPENDED;
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_PEND_SUSPENDED:
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_TASK_NOT_DLY;
|
||||
break;
|
||||
|
||||
case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_TASK_NOT_DLY;
|
||||
break;
|
||||
|
||||
default:
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_STATE_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
OSSched();
|
||||
}
|
||||
#endif
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* GET CURRENT SYSTEM TIME
|
||||
*
|
||||
* Description: This function is used by your application to obtain the current value of the counter which keeps track of
|
||||
* the number of clock ticks.
|
||||
*
|
||||
* Arguments : p_err is a pointer to a variable that will receive an error code
|
||||
*
|
||||
* OS_ERR_NONE If the call was successful
|
||||
*
|
||||
* Returns : The current value of OSTickCtr
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
OS_TICK OSTimeGet (OS_ERR *p_err)
|
||||
{
|
||||
OS_TICK ticks;
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return ((OS_TICK)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
ticks = OSTickCtr;
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
return (ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* SET SYSTEM CLOCK
|
||||
*
|
||||
* Description: This function sets the counter which keeps track of the number of clock ticks.
|
||||
*
|
||||
* Arguments : ticks is the desired tick value
|
||||
*
|
||||
* p_err is a pointer to a variable that will receive an error code
|
||||
*
|
||||
* OS_ERR_NONE If the call was successful
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTimeSet (OS_TICK ticks,
|
||||
OS_ERR *p_err)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
|
||||
|
||||
#ifdef OS_SAFETY_CRITICAL
|
||||
if (p_err == (OS_ERR *)0) {
|
||||
OS_SAFETY_CRITICAL_EXCEPTION();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
OSTickCtr = ticks;
|
||||
CPU_CRITICAL_EXIT();
|
||||
*p_err = OS_ERR_NONE;
|
||||
}
|
||||
|
||||
/*$PAGE*/
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* PROCESS SYSTEM TICK
|
||||
*
|
||||
* Description: This function is used to signal to uC/OS-III the occurrence of a 'system tick' (also known as a
|
||||
* 'clock tick'). This function should be called by the tick ISR.
|
||||
*
|
||||
* Arguments : none
|
||||
*
|
||||
* Returns : none
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
void OSTimeTick (void)
|
||||
{
|
||||
OS_ERR err;
|
||||
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
|
||||
CPU_TS ts;
|
||||
#endif
|
||||
|
||||
|
||||
OSTimeTickHook(); /* Call user definable hook */
|
||||
|
||||
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
|
||||
|
||||
ts = OS_TS_GET(); /* Get timestamp */
|
||||
OS_IntQPost((OS_OBJ_TYPE) OS_OBJ_TYPE_TICK, /* Post to ISR queue */
|
||||
(void *)&OSRdyList[OSPrioCur],
|
||||
(void *) 0,
|
||||
(OS_MSG_SIZE) 0u,
|
||||
(OS_FLAGS ) 0u,
|
||||
(OS_OPT ) 0u,
|
||||
(CPU_TS ) ts,
|
||||
(OS_ERR *)&err);
|
||||
|
||||
#else
|
||||
|
||||
(void)OSTaskSemPost((OS_TCB *)&OSTickTaskTCB, /* Signal tick task */
|
||||
(OS_OPT ) OS_OPT_POST_NONE,
|
||||
(OS_ERR *)&err);
|
||||
|
||||
|
||||
#if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
|
||||
OS_SchedRoundRobin(&OSRdyList[OSPrioCur]);
|
||||
#endif
|
||||
|
||||
#if OS_CFG_TMR_EN > 0u
|
||||
OSTmrUpdateCtr--;
|
||||
if (OSTmrUpdateCtr == (OS_CTR)0u) {
|
||||
OSTmrUpdateCtr = OSTmrUpdateCnt;
|
||||
OSTaskSemPost((OS_TCB *)&OSTmrTaskTCB, /* Signal timer task */
|
||||
(OS_OPT ) OS_OPT_POST_NONE,
|
||||
(OS_ERR *)&err);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
1125
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_tmr.c
Normal file
1125
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_tmr.c
Normal file
File diff suppressed because it is too large
Load Diff
93
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_type.h
Normal file
93
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_type.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* File : OS_TYPE.H
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef OS_TYPE_H
|
||||
#define OS_TYPE_H
|
||||
|
||||
#ifdef VSC_INCLUDE_H_FILE_NAMES
|
||||
const CPU_CHAR *os_type__h = "$Id: $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* INCLUDE HEADER FILES
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
/* Description # Bits */
|
||||
/* <recommended> */
|
||||
/* ----------------------------------------------------------- */
|
||||
|
||||
typedef CPU_INT16U OS_CPU_USAGE; /* CPU Usage 0..10000 <16>/32 */
|
||||
|
||||
typedef CPU_INT32U OS_CTR; /* Counter, 32 */
|
||||
|
||||
typedef CPU_INT32U OS_CTX_SW_CTR; /* Counter of context switches, 32 */
|
||||
|
||||
typedef CPU_INT32U OS_CYCLES; /* CPU clock cycles, <32>/64 */
|
||||
|
||||
typedef CPU_INT32U OS_FLAGS; /* Event flags, 8/16/<32> */
|
||||
|
||||
typedef CPU_INT32U OS_IDLE_CTR; /* Holds the number of times the idle task runs, <32>/64 */
|
||||
|
||||
typedef CPU_INT16U OS_MEM_QTY; /* Number of memory blocks, <16>/32 */
|
||||
typedef CPU_INT16U OS_MEM_SIZE; /* Size in bytes of a memory block, <16>/32 */
|
||||
|
||||
typedef CPU_INT16U OS_MSG_QTY; /* Number of OS_MSGs in the msg pool, <16>/32 */
|
||||
typedef CPU_INT16U OS_MSG_SIZE; /* Size of messages in number of bytes, <16>/32 */
|
||||
|
||||
typedef CPU_INT08U OS_NESTING_CTR; /* Interrupt and scheduler nesting, <8>/16/32 */
|
||||
|
||||
typedef CPU_INT16U OS_OBJ_QTY; /* Number of kernel objects counter, <16>/32 */
|
||||
typedef CPU_INT32U OS_OBJ_TYPE; /* Special flag to determine object type, 32 */
|
||||
|
||||
typedef CPU_INT16U OS_OPT; /* Holds function options <16>/32 */
|
||||
|
||||
typedef CPU_INT08U OS_PRIO; /* Priority of a task, <8>/16/32 */
|
||||
|
||||
typedef CPU_INT16U OS_QTY; /* Quantity <16>/32 */
|
||||
|
||||
typedef CPU_INT32U OS_RATE_HZ; /* Rate in Hertz 32 */
|
||||
|
||||
typedef CPU_INT32U OS_REG; /* Task register 8/16/<32> */
|
||||
typedef CPU_INT08U OS_REG_ID; /* Index to task register <8>/16/32 */
|
||||
|
||||
typedef CPU_INT32U OS_SEM_CTR; /* Semaphore value 16/<32> */
|
||||
|
||||
typedef CPU_INT08U OS_STATE; /* State variable <8>/16/32 */
|
||||
|
||||
typedef CPU_INT08U OS_STATUS; /* Status <8>/16/32 */
|
||||
|
||||
typedef CPU_INT32U OS_TICK; /* Clock tick counter <32>/64 */
|
||||
typedef CPU_INT16U OS_TICK_SPOKE_IX; /* Tick wheel spoke position 8/<16>/32 */
|
||||
|
||||
typedef CPU_INT16U OS_TMR_SPOKE_IX; /* Timer wheel spoke position 8/<16>/32 */
|
||||
|
||||
#endif
|
||||
40
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_var.c
Normal file
40
USER/Ref/bmu-18s-firmware/UCOSIII/uCOS-III/Source/os_var.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
************************************************************************************************************************
|
||||
* uC/OS-III
|
||||
* The Real-Time Kernel
|
||||
*
|
||||
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
|
||||
* All rights reserved. Protected by international copyright laws.
|
||||
*
|
||||
* VARIABLES
|
||||
*
|
||||
* File : OS_VAR.C
|
||||
* By : JJL
|
||||
* Version : V3.03.01
|
||||
*
|
||||
* LICENSING TERMS:
|
||||
* ---------------
|
||||
* uC/OS-III 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-III in a commercial application/
|
||||
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
|
||||
* application/product. We provide ALL the source code for your convenience and to help you
|
||||
* experience uC/OS-III. 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.
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
|
||||
#define OS_GLOBALS
|
||||
|
||||
#define MICRIUM_SOURCE
|
||||
#include <os.h>
|
||||
|
||||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||||
const CPU_CHAR *os_var__c = "$Id: $";
|
||||
#endif
|
||||
Reference in New Issue
Block a user