Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:57690853989a, committed 2010-12-03
- Comitter:
- ericebert
- Date:
- Fri Dec 03 19:45:30 2010 +0000
- Commit message:
- Some basic LED-Flashing works in the CoOS-RTOS using Tasks
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS.h Fri Dec 03 19:45:30 2010 +0000 @@ -0,0 +1,219 @@ +/** + ******************************************************************************* + * @file CoOS.h + * @version V1.1.3 + * @date 2010.04.26 + * @brief API header file of CooCox CoOS. + * @details This file including all API functions's declare of CooCox CoOS. + ******************************************************************************* + * @copy + * + * INTERNAL FILE,DON'T PUBLIC. + * + * <h2><center>© COPYRIGHT 2009 CooCox </center></h2> + ******************************************************************************* + */ + +#ifndef _CCRTOS_H +#define _CCRTOS_H +#include "OsConfig.h" +/*---------------------------- Type Define ----------------------------------*/ +typedef signed char S8; +typedef unsigned char U8; +typedef short S16; +typedef unsigned short U16; +typedef int S32; +typedef unsigned int U32; +typedef long long S64; +typedef unsigned long long U64; +typedef unsigned char BIT; +typedef unsigned char BOOL; +typedef unsigned int OS_STK; +typedef U8 OS_TID; +typedef U8 OS_TCID; +typedef U8 OS_MutexID; +typedef U8 OS_EventID; +typedef U8 OS_FlagID; +typedef U8 OS_MMID; +typedef U8 StatusType; +typedef U16 OS_VER; +typedef void (*FUNCPtr)(void*); +typedef void (*vFUNCPtr)(void); + + +/*---------------------------- Constant Define -------------------------------*/ + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + + +/*---------------------------- Error Codes ---------------------------------*/ +#define E_CREATE_FAIL (StatusType)-1 +#define E_OK (StatusType)0 +#define E_INVALID_ID (StatusType)1 +#define E_INVALID_PARAMETER (StatusType)2 +#define E_CALL (StatusType)3 +#define E_TASK_WAITING (StatusType)4 +#define E_TIMEOUT (StatusType)5 +#define E_SEM_FULL (StatusType)6 +#define E_MBOX_FULL (StatusType)7 +#define E_QUEUE_FULL (StatusType)8 +#define E_SEM_EMPTY (StatusType)9 +#define E_MBOX_EMPTY (StatusType)10 +#define E_QUEUE_EMPTY (StatusType)11 +#define E_FLAG_NOT_READY (StatusType)12 +#define E_ALREADY_IN_WAITING (StatusType)13 +#define E_TASK_NOT_WAITING (StatusType)14 +#define E_TASK_WAIT_OTHER (StatusType)15 +#define E_EXCEED_MAX_NUM (StatusType)16 +#define E_NOT_IN_DELAY_LIST (StatusType)17 +#define E_SEV_REQ_FULL (StatusType)18 +#define E_NOT_FREE_ALL (StatusType)19 +#define E_PROTECTED_TASK (StatusType)20 +#define E_OS_IN_LOCK (StatusType)21 + + +/*---------------------------- Wait Opreation type --------------------------*/ +#define OPT_WAIT_ALL 0 /*!< Wait for all flags. */ +#define OPT_WAIT_ANY 1 /*!< Wait for any one of flags. */ +#define OPT_WAIT_ONE 2 /*!< Waot for one flag. */ + + +/*---------------------------- Delete Opreation type ------------------------*/ +#define OPT_DEL_NO_PEND 0 /*!< Delete when no task waitting for */ +#define OPT_DEL_ANYWAY 1 /*!< Delete always. */ + + +/*---------------------------- Timer Types ----------------------------------*/ +#if CFG_TMR_EN >0 +#define TMR_TYPE_ONE_SHOT 0 /*!< Timer counter type: One-shot */ +#define TMR_TYPE_PERIODIC 1 /*!< Timer counter type: Periodic */ +#endif + + +/*---------------------------- Event Control ---------------------------------*/ +#if CFG_EVENT_EN >0 +#define EVENT_SORT_TYPE_FIFO (U8)0x01 /*!< Insert a event by FIFO */ +#define EVENT_SORT_TYPE_PRIO (U8)0x02 /*!< Insert a event by prio */ +#endif + + +/*---------------------------- Function declare-------------------------------*/ + +/* Implement in file "core.c" */ +extern void CoInitOS(void); /*!< Initialize OS */ +extern void CoStartOS(void); /*!< Start multitask */ +extern void CoEnterISR(void); /*!< Enter a ISR */ +extern void CoExitISR(void); /*!< Exit a ISR */ +extern void CoSchedLock(void); +extern void CoSchedUnlock(void); +extern OS_VER CoGetOSVersion(void); /*!< Get OS version value */ + + +/* Implement in file "task.c" */ +#define CoCreateTask(task,argv,prio,stk,stkSz) \ + CreateTask(task,argv,(prio)|((stkSz)<<8),stk) + + +#define CoCreateTaskEx(task,argv,prio,stk,stkSz,timeSlice,isWaitting) \ + CreateTask(task,argv,(prio)|((stkSz)<<8)|((timeSlice)<<20)|(isWaitting<<31),stk) + +extern void CoExitTask(void); +extern OS_TID CoGetCurTaskID(void); +extern StatusType CoDelTask(OS_TID taskID); +extern StatusType CoActivateTask(OS_TID taskID,void *argv); +extern StatusType CoAwakeTask(OS_TID taskID); +extern StatusType CoSuspendTask(OS_TID taskID); +extern StatusType CoSetPriority(OS_TID taskID,U8 priority); +extern OS_TID CreateTask(FUNCPtr task,void *argv,U32 parameter,OS_STK *stk); + +/* Implement in file "time.c" */ +extern U64 CoGetOSTime(void); +extern StatusType CoTickDelay(U32 ticks); +extern StatusType CoResetTaskDelayTick(OS_TID taskID,U32 ticks); +extern StatusType CoTimeDelay(U8 hour,U8 minute,U8 sec,U16 millsec); + + +/* Implement in file "timer.c" */ +extern StatusType CoDelTmr(OS_TCID tmrID); +extern StatusType CoStopTmr(OS_TCID tmrID); +extern StatusType CoStartTmr(OS_TCID tmrID); +extern U32 CoGetCurTmrCnt(OS_TCID tmrID,StatusType* perr); +extern StatusType CoSetTmrCnt(OS_TCID tmrID,U32 tmrCnt,U32 tmrReload); +extern OS_TCID CoCreateTmr(U8 tmrType, U32 tmrCnt, U32 tmrReload, vFUNCPtr func); + + +/* Implement in file "kernelHeap.c"*/ +extern void* CoKmalloc(U32 size); +extern void CoKfree(void* memBuf); + + +/* Implement in file "mm.c" */ +extern void* CoGetMemoryBuffer(OS_MMID mmID); +extern StatusType CoDelMemoryPartition(OS_MMID mmID); +extern StatusType CoFreeMemoryBuffer(OS_MMID mmID,void* buf); +extern U32 CoGetFreeBlockNum(OS_MMID mmID,StatusType* perr); +extern OS_MMID CoCreateMemPartition(U8* memBuf,U32 blockSize,U32 blockNum); + +/* Implement in file "mutex.c" */ +extern OS_MutexID CoCreateMutex(void); +extern StatusType CoEnterMutexSection(OS_MutexID mutexID); +extern StatusType CoLeaveMutexSection(OS_MutexID mutexID); + + +/* Implement in file "sem.c" */ +extern StatusType CoPostSem(OS_EventID id); +extern StatusType CoAcceptSem(OS_EventID id); +extern StatusType isr_PostSem(OS_EventID id); +extern StatusType CoDelSem(OS_EventID id,U8 opt); +extern StatusType CoPendSem(OS_EventID id,U32 timeout); +extern OS_EventID CoCreateSem(U16 initCnt,U16 maxCnt,U8 sortType); + + +/* Implement in file "mbox.c" */ +extern OS_EventID CoCreateMbox(U8 sortType); +extern StatusType CoDelMbox(OS_EventID id,U8 opt); +extern StatusType CoPostMail(OS_EventID id,void* pmail); +extern StatusType isr_PostMail(OS_EventID id,void* pmail); +extern void* CoAcceptMail(OS_EventID id,StatusType* perr); +extern void* CoPendMail(OS_EventID id,U32 timeout,StatusType* perr); + + +/* Implement in file "queue.c" */ +extern StatusType CoDelQueue(OS_EventID id,U8 opt); +extern StatusType CoPostQueueMail(OS_EventID id,void* pmail); +extern StatusType isr_PostQueueMail(OS_EventID id,void* pmail); +extern void* CoAcceptQueueMail(OS_EventID id,StatusType* perr); +extern OS_EventID CoCreateQueue(void **qStart, U16 size ,U8 sortType); +extern void* CoPendQueueMail(OS_EventID id,U32 timeout,StatusType* perr); + + + +/* Implement in file "flag.c" */ +extern StatusType CoSetFlag (OS_FlagID id); +extern StatusType CoClearFlag (OS_FlagID id); +extern StatusType isr_SetFlag (OS_FlagID id); +extern StatusType CoDelFlag (OS_FlagID id,U8 opt); +extern StatusType CoAcceptSingleFlag (OS_FlagID id); +extern StatusType CoWaitForSingleFlag (OS_FlagID id,U32 timeout); +extern OS_FlagID CoCreateFlag (BOOL bAutoReset,BOOL bInitialState); +extern U32 CoAcceptMultipleFlags (U32 flags,U8 waitType,StatusType *perr); +extern U32 CoWaitForMultipleFlags (U32 flags,U8 waitType,U32 timeout,StatusType *perr); + + +/* Implement in file "utility.c" */ +extern StatusType CoTimeToTick(U8 hour,U8 minute,U8 sec,U16 millsec,U32* ticks); +extern void CoTickToTime(U32 ticks,U8* hour,U8* minute,U8* sec,U16* millsec); + + +/* Implement in file "hook.c" */ +extern void CoIdleTask(void* pdata); +extern void CoStkOverflowHook(OS_TID taskID); + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OsArch.h Fri Dec 03 19:45:30 2010 +0000 @@ -0,0 +1,50 @@ +/** + ******************************************************************************* + * @file OsArch.h + * @version V1.1.3 + * @date 2010.04.26 + * @brief Implement function declare related to Cortex-M3(ARM-v7) + * @details This header file including functions or defines related to + * Cortex-M3(ARM-v7). + ******************************************************************************* + * @copy + * + * INTERNAL FILE,DON'T PUBLIC. + * + * <h2><center>© COPYRIGHT 2009 CooCox </center></h2> + ******************************************************************************* + */ + + +#ifndef _CPU_H +#define _CPU_H + + +#define NVIC_ST_CTRL (*((volatile U32 *)0xE000E010)) +#define NVIC_ST_RELOAD (*((volatile U32 *)0xE000E014)) +#define RELOAD_VAL ((U32)(( (U32)CFG_CPU_FREQ) / (U32)CFG_SYSTICK_FREQ) -1) + +/*!< Initial System tick. */ +#define InitSysTick() NVIC_ST_RELOAD = RELOAD_VAL; \ + NVIC_ST_CTRL = 0x0007 + +#define NVIC_SYS_PRI2 (*((volatile U32 *)0xE000ED1C)) +#define NVIC_SYS_PRI3 (*((volatile U32 *)0xE000ED20)) + +/*!< Initialize PendSV,SVC and SysTick interrupt priority to lowest. */ +#define InitInt() NVIC_SYS_PRI2 |= 0xFF000000;\ + NVIC_SYS_PRI3 |= 0xFFFF0000 + + +/*---------------------------- Variable declare ------------------------------*/ +extern U64 OSTickCnt; /*!< Counter for current system ticks. */ + +/*!< Initial context of task being created */ +extern OS_STK *InitTaskContext(FUNCPtr task,void *param,OS_STK *pstk); +extern void SwitchContext(void); /*!< Switch context */ +extern void SetEnvironment(OS_STK *pstk);/*!< Set environment for run */ +extern U8 Inc8 (volatile U8 *data); +extern U8 Dec8 (volatile U8 *data); +extern void IRQ_ENABLE_RESTORE(void); +extern void IRQ_DISABLE_SAVE(void); +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OsConfig.h Fri Dec 03 19:45:30 2010 +0000 @@ -0,0 +1,276 @@ +/** + ******************************************************************************* + * @file OsConfig.h + * @version V1.1.3 + * @date 2010.04.26 + * @brief This file use by user to configuration CooCox CoOS. + * @note Ensure you have knew every item before modify this file. + ******************************************************************************* + * @copy + * + * INTERNAL FILE,DON'T PUBLIC. + * + * <h2><center>© COPYRIGHT 2009 CooCox </center></h2> + ******************************************************************************* + */ + + +#ifndef _CONFIG_H +#define _CONFIG_H + + +/*!< +Defines chip type,cortex-m3(1),cortex-m0(2) +*/ +#define CFG_CHIP_TYPE (1) + +/*!< +Defines the lowest priority that be assigned. +*/ +#define CFG_LOWEST_PRIO (64) + +/*!< +Max number of tasks that can be running. +*/ +#define CFG_MAX_USER_TASKS (10) + +/*!< +Idle task stack size(word). +*/ +#define CFG_IDLE_STACK_SIZE (25) + +/*!< +System frequency (Hz). +*/ +#define CFG_CPU_FREQ (96000000) + +/*!< +systick frequency (Hz). +*/ +#define CFG_SYSTICK_FREQ (500) + +/*!< +max systerm api call num in ISR. +*/ +#define CFG_MAX_SERVICE_REQUEST (3) + +/*!< +Enable(1) or disable(0) order list schedule. +If disable(0),CoOS use Binary-Scheduling Algorithm. +*/ +#if (CFG_MAX_USER_TASKS) <15 +#define CFG_ORDER_LIST_SCHEDULE_EN (1) +#else +#define CFG_ORDER_LIST_SCHEDULE_EN (0) +#endif + + +/*!< +Enable(1) or disable(0) Round-Robin Task switching. +*/ +#define CFG_ROBIN_EN (1) + +/*!< +Default slice of task. +*/ +#if CFG_ROBIN_EN > 0 +#define CFG_TIME_SLICE (10) +#endif + + +/*----------------------- Schedule model Config -----------------------------*/ +/*!< +Enable(1) or disable(0) all waiting function. +Include sem,mailbox,queue,flag,mutex,delay modules. +If CFG_TASK_WAITTING_EN=0,all these modules are disable. +*/ +#define CFG_TASK_WAITTING_EN (1) + +/*!< +Dynamic task scheduling(1) or Static Task Scheduling(0) model. +If in Static Task Scheduling model(0),cannot creat task and change task priority +after coocox os start running. In Dynamic Task Scheduling model(1), all these can. +When task terminated, if in Static Task Scheduling model(0), +CoOS do not recovered task resources, and you can activate it again. +But in Dynamic Task Scheduling model(1),task resources will be recovered. +If in Static Task Scheduling model(0),mutex module can not be used, as this model don't +support to change task priority while CoOS running. +*/ +#define CFG_TASK_SCHEDULE_EN (1) + + +/*---------------------- Task Management Config -----------------------------*/ +/*!< +Enable(1) or disable(0) CoSetPriority() API. +*/ +#if CFG_TASK_SCHEDULE_EN >0 +#define CFG_PRIORITY_SET_EN (1) +#endif + +/*!< +Enable(1) or disable(0) CoAwakeTask() and CoSuspendTask() API. +*/ +#define CFG_TASK_SUSPEND_EN (1) + + +/*---------------------- Debug Management Config ----------------------------*/ +/*!< +Enable(1) or disable(0) parameter checkout . +*/ +#define CFG_PAR_CHECKOUT_EN (1) + +/*!< +Enable(1) or disable(0) stack overflow checkout . +*/ +#define CFG_STK_CHECKOUT_EN (1) + + + +/*---------------------- Memory Management Config ----------------------------*/ +/*!< +Enable(1) or disable(0) memory management. +*/ +#define CFG_MM_EN (1) + +/*!< +Max number of memory.(must be less than 32). +*/ +#if CFG_MM_EN >0 +#define CFG_MAX_MM (2) +#endif + + + +/*-------------------- Kernel heap Management Config -------------------------*/ +/*!< +Enable(1) or disable(0) kernel heap management. +*/ +#define CFG_KHEAP_EN (1) + +/*!< +Kernel heap size(word). +*/ +#if CFG_KHEAP_EN >0 +#define KHEAP_SIZE (50) +#endif + + + +/*---------------------- Time Management Config -----------------------------*/ +/*!< +Enable(1) or disable(0) TimeDelay() API. +*/ +#if CFG_TASK_WAITTING_EN >0 +#define CFG_TIME_DELAY_EN (1) +#endif + + +/*---------------------- Timer Management Config ----------------------------*/ +/*!< +Enable(1) or disable(0) timer management. +*/ +#define CFG_TMR_EN (1) + +/*!< +Specify max number timer.(must be less than 32) +*/ +#if CFG_TMR_EN >0 +#define CFG_MAX_TMR (2) +#endif + + +/*---------------------- Event Management Config ----------------------------*/ +/*!< +Enable(1) or disable(0) events management, +events including semaphore,mailbox,queue. +*/ +#if CFG_TASK_WAITTING_EN > 0 +#define CFG_EVENT_EN (1) +#endif + +#if CFG_EVENT_EN > 0 +/*!< +Event sort type.(1)FIFO (2)PRI (3)FIFO+PRI +*/ +#define CFG_EVENT_SORT (3) + +/*!< +Max number of event.(must be less than 255) +Event = semaphore + mailbox + queue; +*/ +#define CFG_MAX_EVENT (10) + +/*!< +Enable(1) or disable(0) semaphore management. +*/ +#define CFG_SEM_EN (1) + +/*!< +Enable(1) or disable(0) mailbox management. +*/ +#define CFG_MAILBOX_EN (1) + +/*!< +Enable(1) or disable(0) queue management. +*/ +#define CFG_QUEUE_EN (1) + +/*!< +Max number of queue.(less than CFG_MAX_EVENT). +*/ +#if CFG_QUEUE_EN >0 +#define CFG_MAX_QUEUE (2) +#endif // CFG_QUEUE_EN + +#endif // CFG_EVENT_EN + + + +/*----------------------- Flag Management Config ----------------------------*/ +/*!< +Enable(1) or disable(0) flag management. +Max number of flag is 32. +*/ +#if CFG_TASK_WAITTING_EN > 0 +#define CFG_FLAG_EN (1) +#endif + + +/*---------------------- Mutex Management Config ----------------------------*/ +/*!< +Enable(1) or disable(0) mutex management. +*/ +#if CFG_TASK_WAITTING_EN > 0 +#if CFG_TASK_SCHEDULE_EN > 0 +#define CFG_MUTEX_EN (1) +#endif +#endif + + +/*!< +Max number of mutex.(must be less than 255). +*/ +#if CFG_MUTEX_EN >0 +#define CFG_MAX_MUTEX (10) +#endif + +/*---------------------- Utility Management Config --------------------------*/ +/*!< +Enable(1) or disable(0) utility management. +*/ +#define CFG_UTILITY_EN (1) + +#if CFG_UTILITY_EN >0 + +/*!< +Enable(1) or disable(0) TickToTime() utility +*/ +#define CFG_TICK_TO_TIME_EN (1) +/*!< +Enable(1) or disable(0) TimeToTick() utility +*/ +#define CFG_TIME_TO_TICK_EN (1) +#endif + + +#endif // _CONFIG_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OsCore.h Fri Dec 03 19:45:30 2010 +0000 @@ -0,0 +1,27 @@ +/** + ******************************************************************************* + * @file OsCore.h + * @version V1.1.3 + * @date 2010.04.26 + * @brief Header file related to kernel + ******************************************************************************* + * @copy + * + * INTERNAL FILE,DON'T PUBLIC. + * + * <h2><center>© COPYRIGHT 2009 CooCox </center></h2> + ******************************************************************************* + */ + + +#ifndef _CORE_H +#define _CORE_H + +#include <CoOS.h> + + +#define OsSchedLock() OSSchedLock++; /*!< Lock schedule */ +extern void OsSchedUnlock(void); + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OsError.h Fri Dec 03 19:45:30 2010 +0000 @@ -0,0 +1,84 @@ +/** + ******************************************************************************* + * @file OsError.h + * @version V1.1.3 + * @date 2010.04.26 + * @brief rror dispose header file + * @details This file use to dispose error which from error configure for OS. + ******************************************************************************* + * @copy + * + * INTERNAL FILE,DON'T PUBLIC. + * + * <h2><center>© COPYRIGHT 2009 CooCox </center></h2> + ******************************************************************************* + */ + + +#ifndef _ERROR_H +#define _ERROR_H + +#if (CFG_SYSTICK_FREQ > 1000) ||(CFG_SYSTICK_FREQ < 1) + #error " OsConfig.h System Tick time must between 1ms and 1s!" +#endif + +#if CFG_MAX_USER_TASKS > 253 + #error " OsConfig.h, CFG_MAX_USER_TASKS must be <= 253! " +#endif + +#if CFG_LOWEST_PRIO > 254 + #error " OsConfig.h, CFG_LOWEST_PRIO must be <= 254! " +#endif + +#if CFG_IDLE_STACK_SIZE <25 + #error " OsConfig.h, CFG_IDLE_STACK_SIZE must be >= 25! " +#endif + + +#if CFG_ROBIN_EN > 0 + #if CFG_TIME_SLICE > 4095 + #error " OsConfig.h, CFG_TIME_SLICE must be <= 4095! " + #endif +#endif + +#if CFG_TMR_EN > 0 + #if CFG_MAX_TMR > 32 + #error " OsConfig.h, CFG_MAX_TMR must be <= 32! " + #endif +#endif + + +#if CFG_MM_EN > 0 + #if CFG_MAX_MM > 32 + #error " config.h, CFG_MAX_MM must be <= 32! " + #endif +#endif + + +#if CFG_KHEAP_EN > 0 + #if KHEAP_SIZE < 0x20 + #error " config.h, CFG_MAX_MM must be >= 0x20! " + #endif +#endif + +#if CFG_MUTEX_EN > 0 + #if CFG_MAX_MUTEX > 254 + #error " config.h, CFG_MAX_MUTEX must be <= 254! " + #endif +#endif + + +#if CFG_EVENT_EN > 0 + #if (CFG_MAX_EVENT > 254 || CFG_MAX_EVENT <= 0) + #error " config.h, CFG_MAX_EVENT must be <= 254 && > 0! " + #endif + + + #if CFG_QUEUE_EN > 0 + #if CFG_MAX_QUEUE > CFG_MAX_EVENT + #error " config.h, CFG_MAX_QUEUE must be <= CFG_MAX_EVENT! " + #endif + #endif +#endif /* CFG_EVENT_EN */ + +#endif /* _ERROR_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OsEvent.h Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,58 @@
+/**
+ *******************************************************************************
+ * @file OsEvent.h
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Event management header file
+ * @details This file including some defines and declares related to event
+ * (semaphore,mailbox,queque) management.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+#ifndef _EVENT_H
+#define _EVENT_H
+
+#define EVENT_TYPE_SEM (U8)0x01 /*!< Event type:Semaphore. */
+#define EVENT_TYPE_MBOX (U8)0x02 /*!< Event type:Mailbox. */
+#define EVENT_TYPE_QUEUE (U8)0x03 /*!< Event type:Queue. */
+#define EVENT_TYPE_INVALID (U8)0x04 /*!< Invalid event type. */
+
+
+/**
+ * @struct EventCtrBlk event.h
+ * @brief Event control block
+ * @details This struct is use to manage event,
+ * e.g. semaphore,mailbox,queue.
+ */
+typedef struct EventCtrBlk
+{
+ void* eventPtr; /*!< Point to mailbox or queue struct */
+ U8 id; /*!< ECB id */
+ U8 eventType:4; /*!< Type of event */
+ U8 eventSortType:4; /*!< 0:FIFO 1: Preemptive by prio */
+ U16 eventCounter; /*!< Counter of semaphore. */
+ U16 initialEventCounter; /*!< Initial counter of semaphore. */
+ P_OSTCB eventTCBList; /*!< Task waitting list. */
+}ECB,*P_ECB;
+
+/*---------------------------- Variable declare ------------------------------*/
+extern ECB EventTbl[CFG_MAX_EVENT]; /*!< Table use to save TCB. */
+
+/*---------------------------- Function declare ------------------------------*/
+/*!< Create a event */
+extern P_ECB CreatEvent(U8 eventType,U8 eventSortType,void* eventPtr);
+
+/*!< Remove a task from wait list */
+extern void EventTaskToWait(P_ECB pecb,P_OSTCB ptcb);
+extern StatusType DeleteEvent(P_ECB pecb,U8 opt); /*!< Delete a event. */
+extern void EventTaskToRdy(P_ECB pecb); /*!< Insert a task to ready list*/
+extern void CreateEventList(void); /*!< Create a event list. */
+extern void RemoveEventWaittingList(P_OSTCB ptcb);
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OsFlag.h Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,57 @@
+/**
+ *******************************************************************************
+ * @file OsFlag.h
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Evnet flag management header file
+ * @details This file including some defines and declares about flag management.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+#ifndef _FLAG_H
+#define _FLAG_H
+
+/**
+ * @struct FlagNode flag.h
+ * @brief Flag node struct
+ * @details
+ */
+typedef struct FlagNode
+{
+ struct FlagNode* nextNode; /*!< A pointer to next flag node */
+ struct FlagNode* prevNode; /*!< A pointer to prev flag node */
+ U32 waitFlags; /*!< Flag value */
+ P_OSTCB waitTask; /*!< A pointer to task waitting flag */
+ U8 waitType; /*!< Wait type */
+}FLAG_NODE,*P_FLAG_NODE;
+
+
+/**
+ * @struct Flag flag.h
+ * @brief Flag control block
+ * @details This struct use to mange event flag.
+ */
+typedef struct Flag
+{
+ U32 flagRdy; /*!< Ready flag */
+ U32 resetOpt; /*!< Reset option */
+ U32 flagActive; /*!< Active flag */
+ P_FLAG_NODE headNode; /*!< Head node */
+ P_FLAG_NODE tailNode; /*!< Tail node */
+}FCB,*P_FCB;
+
+
+/*---------------------------- Variable declare ------------------------------*/
+extern FCB FlagCrl;
+
+/*---------------------------- Function declare ------------------------------*/
+extern void RemoveLinkNode(P_FLAG_NODE pnode);
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OsKernelHeap.h Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,48 @@
+/**
+ *******************************************************************************
+ * @file OsKernelHeap.h
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Header file related to memory management
+ * @details This file including some defines and function declare related to
+ * kernel heap management.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+#ifndef _KERNELHEAP_H
+#define _KERNELHEAP_H
+
+
+typedef struct KennelHeap
+{
+ U32 startAddr;
+ U32 endAddr;
+}KHeap,*P_KHeap;
+
+
+typedef struct UsedMemBlk
+{
+ void* nextMB;
+ void* preMB;
+}UMB,*P_UMB;
+
+
+typedef struct FreeMemBlk
+{
+ struct FreeMemBlk* nextFMB;
+ struct UsedMemBlk* nextUMB;
+ struct UsedMemBlk* preUMB;
+}FMB,*P_FMB;
+
+/*---------------------------- Function Declare ------------------------------*/
+extern void CoCreateKheap(void);
+
+#endif /* _KERNELHEAP_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OsMM.h Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,41 @@
+/**
+ *******************************************************************************
+ * @file OsMm.h
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Header file related to memory management
+ * @details This file including some defines and function declare related to
+ * memory management.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+#ifndef _MM_H
+#define _MM_H
+
+
+typedef struct Memory
+{
+ U8* memAddr;
+ U8* freeBlock;
+ U32 blockSize;
+ U32 blockNum;
+}MM,*P_MM;
+
+
+typedef struct MemoryBlock
+{
+ struct MemoryBlock* nextBlock;
+}MemBlk,*P_MemBlk;
+
+
+extern U32 MemoryIDVessel;
+
+#endif /* _MM_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OsMutex.h Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,57 @@
+/**
+ *******************************************************************************
+ * @file OsMutex.h
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Mutex management header file
+ * @details This file including some defines and declare related to mutex
+ * management.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+#ifndef _MUTEX_H
+#define _MUTEX_H
+
+#include <coocox.h>
+
+#if CFG_MUTEX_EN > 0
+
+/*---------------------------- Resource status -------------------------------*/
+#define MUTEX_FREE 0 /*!< Mutex is free */
+#define MUTEX_OCCUPY 1 /*!< Mutex is occupy */
+#define WAITING_MUTEX 0x80
+
+/**
+ * @struct Mutex mutex.h
+ * @brief Mutex control block
+ * @details This struct is use to mutex management.
+ */
+typedef struct Mutex
+{
+ U8 originalPrio; /*!< Mutex priority. */
+ U8 mutexFlag; /*!< Mutex flag. */
+ OS_TID taskID; /*!< Task ID. */
+ OS_TID hipriTaskID; /*!< Mutex ID. */
+ P_OSTCB waittingList; /*!< waitting the Mutex. */
+}MUTEX,*P_MUTEX;
+
+
+/*---------------------------- Variable declare ------------------------------*/
+/*!< Table use to save mutex control block. */
+extern MUTEX MutexTbl[CFG_MAX_MUTEX];
+extern OS_MutexID MutexFreeID; /*!< A pointer to next vliad resource ID. */
+
+
+/*---------------------------- Function declare ------------------------------*/
+extern void RemoveMutexList(P_OSTCB ptcb);
+
+#endif /* CFG_MUTEX_EN */
+
+#endif /* _MUTEX_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OsQueue.h Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,39 @@
+/**
+ *******************************************************************************
+ * @file OsQueue.h
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Queue management header file
+ * @details This file including some defines and declares about queue management.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+#ifndef _QUEUE_H
+#define _QUEUE_H
+
+
+/**
+ * @struct Queue queue.h
+ * @brief Queue struct
+ * @details This struct use to manage queue.
+ *
+ */
+typedef struct Queue
+{
+ void **qStart; /*!< */
+ U8 id; /*!< */
+ U16 head; /*!< The header of queue */
+ U16 tail; /*!< The end of queue */
+ U16 qMaxSize; /*!< The max size of queue */
+ U16 qSize; /*!< Current size of queue */
+}QCB,*P_QCB;
+
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OsServiceReq.h Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,53 @@
+
+/**
+ *******************************************************************************
+ * @file OsServiceReq.h
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Header file related to service request
+ * @details This file including some defines and function declare related to
+ * service request.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+#ifndef _SERVICEREQ_H
+#define _SERVICEREQ_H
+
+#if CFG_MAX_SERVICE_REQUEST > 0
+#define SEM_REQ (U8)0x1
+#define MBOX_REQ (U8)0x2
+#define FLAG_REQ (U8)0x3
+#define QUEUE_REQ (U8)0x4
+
+
+typedef struct ServiceReqCell
+{
+ U8 type;
+ U8 id;
+ void* arg;
+}SQC,*P_SQC;
+
+typedef struct ServiceReqQueue
+{
+ U8 cnt;
+ U8 head;
+ SQC cell[CFG_MAX_SERVICE_REQUEST];
+}SRQ,*P_SRQ;
+
+
+extern SRQ ServiceReq;
+extern BOOL InsertInSRQ(U8 type,U8 id,void* arg);
+#endif
+
+extern void RespondSRQ(void);
+extern BOOL TimeReq;
+extern BOOL TimerReq;
+extern BOOL IsrReq;
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OsTask.h Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,112 @@
+/**
+ *******************************************************************************
+ * @file OsTask.h
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Header file related to task.
+ * @details This file including some defines and function declare related to task.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+#ifndef _TASK_H
+#define _TASK_H
+
+#define SYS_TASK_NUM (1) /*!< System task number. */
+
+/*---------------------------- Task Status -----------------------------------*/
+#define TASK_READY 0 /*!< Ready status of task. */
+#define TASK_RUNNING 1 /*!< Running status of task. */
+#define TASK_WAITING 2 /*!< Waitting status of task. */
+#define TASK_DORMANT 3 /*!< Dormant status of task. */
+
+
+#define INVALID_ID (U8)0xff
+#define INVALID_VALUE (U32)0xffffffff
+#define MAGIC_WORD (U32)0x5a5aa5a5
+
+
+/**
+ * @struct TCB task.h
+ * @brief Task control blcok.
+ * @details This struct use to manage task.
+ */
+typedef struct TCB
+{
+ OS_STK *stkPtr; /*!< The current point of task. */
+ U8 prio; /*!< Task priority. */
+ U8 state; /*!< TaSk status. */
+ OS_TID taskID; /*!< Task ID. */
+
+#if CFG_MUTEX_EN > 0
+ OS_MutexID mutexID; /*!< Mutex ID. */
+#endif
+
+#if CFG_EVENT_EN > 0
+ OS_EventID eventID; /*!< Event ID. */
+#endif
+
+#if CFG_ROBIN_EN >0
+ U16 timeSlice; /*!< Task time slice */
+#endif
+
+#if CFG_STK_CHECKOUT_EN >0
+ OS_STK *stack; /*!< The top point of task. */
+#endif
+
+#if CFG_EVENT_EN > 0
+ void* pmail; /*!< Mail to task. */
+ struct TCB *waitNext; /*!< Point to next TCB in the Event waitting list.*/
+ struct TCB *waitPrev; /*!< Point to prev TCB in the Event waitting list.*/
+#endif
+
+#if CFG_TASK_SCHEDULE_EN == 0
+ FUNCPtr taskFuc;
+ OS_STK *taskStk;
+#endif
+
+
+#if CFG_FLAG_EN > 0
+ void* pnode; /*!< Pointer to node of event flag. */
+#endif
+
+#if CFG_TASK_WAITTING_EN >0
+ U32 delayTick; /*!< The number of ticks which delay. */
+#endif
+ struct TCB *TCBnext; /*!< The pointer to next TCB. */
+ struct TCB *TCBprev; /*!< The pointer to prev TCB. */
+
+}OSTCB,*P_OSTCB;
+
+
+/*---------------------------- Variable declare ------------------------------*/
+// save tcb ptr that created
+extern P_OSTCB FreeTCB; /*!< A pointer to free TCB. */
+extern OSTCB TCBTbl[CFG_MAX_USER_TASKS+SYS_TASK_NUM];
+extern P_OSTCB TCBRdy; /*!< A pointer to TCB that is ready status */
+extern P_OSTCB TCBNext; /*!< A pointer to TCB next be scheduled. */
+extern P_OSTCB TCBRunning; /*!< A pointer to TCB that is running. */
+
+extern U64 OSCheckTime;
+extern volatile U8 OSIntNesting; /*!< Use to indicate interrupt nesting level.*/
+extern volatile U8 OSSchedLock; /*!< Schedule is lock(LOCK) or unlock(UN_LOCK).*/
+extern volatile BOOL TaskSchedReq;
+extern OS_STK idle_stk[CFG_IDLE_STACK_SIZE];
+
+
+void Schedule(void); /*!< Schedule function */
+void IdleTask(void* pdata); /*!< IDLE task code */
+void InsertToTCBRdyList (P_OSTCB tcbInser);
+void RemoveFromTCBRdyList(P_OSTCB ptcb);
+void CreateTCBList(void);
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+void ActiveTaskPri(U8 pri);
+void DeleteTaskPri(U8 pri);
+#endif
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OsTime.h Fri Dec 03 19:45:30 2010 +0000 @@ -0,0 +1,28 @@ +/** + ******************************************************************************* + * @file OsTime.c + * @version V1.1.3 + * @date 2010.04.26 + * @brief Header file related to time management + * @details Thie file including some data declare related to time managment. + ******************************************************************************* + * @copy + * + * INTERNAL FILE,DON'T PUBLIC. + * + * <h2><center>© COPYRIGHT 2009 CooCox </center></h2> + ******************************************************************************* + */ + +#ifndef _TIME_H +#define _TIME_H + +/*---------------------------- Variable declare ------------------------------*/ +extern P_OSTCB DlyList; /*!< A pointer to ther delay list. */ + +/*---------------------------- Function declare ------------------------------*/ +extern void TimeDispose(void); /*!< Time dispose function. */ +extern void isr_TimeDispose(void); +extern void RemoveDelayList(P_OSTCB ptcb); +extern void InsertDelayList(P_OSTCB ptcb,U32 ticks); +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OsTimer.h Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,49 @@
+/**
+ *******************************************************************************
+ * @file OsTimer.h
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Timer manage header file
+ * @details This file including some declares and defines related to timer
+ * management.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+#ifndef _TIMER_H
+#define _TIMER_H
+
+#define TMR_STATE_RUNNING 0 /*!< Timer State: Running */
+#define TMR_STATE_STOPPED 1 /*!< Timer State: Stopped */
+
+/**
+ * @struct tmrCtrl timer.h
+ * @brief Timer control block
+ * @details This struct is use to manage user timer.
+ *
+ */
+typedef struct tmrCtrl /* Timer Control Block Define. */
+{
+ OS_TCID tmrID; /*!< Timer ID. */
+ U8 tmrType; /*!< Timer Type. */
+ U8 tmrState; /*!< Timer State. */
+ U32 tmrCnt; /*!< Timer Counter. */
+ U32 tmrReload; /*!< Timer Reload Counter Value. */
+ vFUNCPtr tmrCallBack; /*!< Call-back Function When Timer overrun. */
+ struct tmrCtrl* tmrNext; /*!< Point to Next Timer Control Block. */
+ struct tmrCtrl* tmrPrev; /*!< Point to Previous Timer Control Block*/
+
+}TmrCtrl,*P_TmrCtrl;
+
+/*---------------------------- Variable declare ------------------------------*/
+extern P_TmrCtrl TmrList; /*!< A pointer to the timer list. */
+extern U32 TmrIDVessel;
+/*---------------------------- Function declare ------------------------------*/
+extern void TmrDispose(void); /*!< Timer counter function. */
+extern void isr_TmrDispose(void);
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arch.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,96 @@
+/**
+ *******************************************************************************
+ * @file arch.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief This file provides InitTaskContext() and SysTick_Handler().
+ *******************************************************************************
+ * @copy
+ * WRITE COPY INFORMATION USE CAPITAL LETTER
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+U64 OSTickCnt = 0; /*!< Current system tick counter */
+
+/**
+ ******************************************************************************
+ * @brief Initial task context
+ * @param[in] task Entry point of task.
+ * @param[in] param The parameter pass to task.
+ * @param[in] pstk The pointer to stack top.
+ * @param[out] None
+ * @retval Returns location of new stack top.
+ *
+ * @par Description
+ * @details This function is called to initialize the stack frame of the
+ * task being created.
+ ******************************************************************************
+ */
+OS_STK *InitTaskContext(FUNCPtr task,void *param,OS_STK *pstk)
+{
+ OS_STK *context;
+ context = pstk;
+ *(context--) = (U32)0x01000000L; /* xPSR */
+ *(context--) = (U32)task; /* Entry point of task. */
+ *(context) = (U32)0xFFFFFFFEL;
+ context = context - 5;
+ *(context) = (U32)param; /* R0: argument */
+ context = context - 8;
+
+ return (context); /* Returns location of new stack top. */
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief System tick interrupt handler.
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This is system tick interrupt headler.
+ * @note CoOS may schedule when exiting this ISR.
+ *******************************************************************************
+ */
+extern "C" void SysTick_Handler(void)
+{
+ OSSchedLock++; /* Lock scheduler. */
+ OSTickCnt++; /* Increment systerm time. */
+#if CFG_TASK_WAITTING_EN >0
+ if(DlyList != 0) /* Have task in delay list? */
+ {
+ if(DlyList->delayTick > 1) /* Delay time > 1? */
+ {
+ DlyList->delayTick--; /* Decrease delay time of the list head. */
+ }
+ else
+ {
+ DlyList->delayTick = 0;
+ isr_TimeDispose(); /* Call hander for delay time list */
+ }
+ }
+#endif
+
+#if CFG_TMR_EN > 0
+ if(TmrList != 0) /* Have timer in working? */
+ {
+ if(TmrList->tmrCnt > 1) /* Timer time > 1? */
+ {
+ TmrList->tmrCnt--; /* Decrease timer time of the list head. */
+ }
+ else
+ {
+ TmrList->tmrCnt = 0;
+ isr_TmrDispose(); /* Call hander for timer list */
+ }
+ }
+#endif
+ TaskSchedReq = TRUE;
+ OsSchedUnlock();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coocox.h Fri Dec 03 19:45:30 2010 +0000 @@ -0,0 +1,60 @@ +/** + ******************************************************************************* + * @file coocox.h + * @version V1.1.3 + * @date 2010.04.26 + * @brief Gather for all header file of CooCox CoOS. + ******************************************************************************* + * @copy + * + * INTERNAL FILE,DON'T PUBLIC. + * + * <h2><center>© COPYRIGHT 2009 CooCox </center></h2> + ******************************************************************************* + */ + + +#ifndef _COOCOX_H +#define _COOCOX_H + +#define OS_VERSION (U16)0x0113 /*!< OS version.(format: Vx.xx), + e.g. value 0x0113 is version V1.13*/ +/*---------------------------- Include ---------------------------------------*/ +#include "CoOS.h" +#include "OsArch.h" +#include "OsCore.h" +#include "OsTask.h" +#include "OsServiceReq.h" +#include "OsError.h" +#include "OsTime.h" + + +#if CFG_TMR_EN > 0 + #include "OsTimer.h" +#endif + +#if CFG_KHEAP_EN > 0 + #include "OsKernelHeap.h" +#endif + +#if CFG_MM_EN >0 + #include "OsMM.h" +#endif + +#if CFG_EVENT_EN > 0 + #include "OsEvent.h" +#endif + +#if CFG_MUTEX_EN > 0 + #include "OsMutex.h" +#endif + +#if CFG_QUEUE_EN > 0 + #include "OsQueue.h" +#endif + +#if CFG_FLAG_EN > 0 + #include "OsFlag.h" +#endif + +#endif /* _COOCOX_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,238 @@
+ /**
+ *******************************************************************************
+ * @file core.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Core implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+/*---------------------------- Variable Define -------------------------------*/
+volatile U8 OSIntNesting = 0; /*!< Use to indicate interrupt nesting level*/
+volatile U8 OSSchedLock = 0; /*!< Task Switch lock. */
+volatile BOOL TaskSchedReq = FALSE;
+
+
+/**
+ *******************************************************************************
+ * @brief Enter a ISR.
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to notify OS when enter to an ISR.
+ *
+ * @note When you call API in ISR,you must call CoEnterISR() before your
+ * interrupt handler code,and call CoExitISR() after your handler
+ * code and before exiting from ISR.
+ *******************************************************************************
+ */
+void CoEnterISR(void)
+{
+ Inc8(&OSIntNesting); /* OSIntNesting increment */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Exit a ISR.
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called when exit from a ISR.
+ *
+ * @note
+ *******************************************************************************
+ */
+void CoExitISR(void)
+{
+ Dec8(&OSIntNesting); /* OSIntNesting decrease */
+ if( OSIntNesting == 0) /* Is OSIntNesting == 0? */
+ {
+ if(TaskSchedReq == TRUE)
+ {
+ OSSchedLock++;
+ Schedule(); /* Call task schedule */
+ OSSchedLock--;
+ }
+ }
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Unlock schedule
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to unlock schedule(i.e.enable schedule again)
+ *
+ * @note
+ *******************************************************************************
+ */
+void OsSchedUnlock(void)
+{
+ if(OSSchedLock == 1) /* Is OSSchedLock == 0? */
+ {
+#if CFG_TASK_WAITTING_EN > 0
+ if(IsrReq == TRUE)
+ {
+ RespondSRQ(); /* Respond service request */
+ }
+#endif
+ /* Judge task state change or higher PRI task coming in */
+ if(TaskSchedReq == TRUE)
+ {
+ Schedule(); /* Call task schedule */
+ }
+ OSSchedLock = 0;
+ }
+ else
+ {
+ OSSchedLock--;
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Lock schedule
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called in application code to lock schedule.
+ *
+ * @note
+ *******************************************************************************
+ */
+void CoSchedLock(void)
+{
+ OsSchedLock(); /* Lock schedule */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Unlock schedule
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called in APP to unlock schedule.
+ *
+ * @note
+ *******************************************************************************
+ */
+void CoSchedUnlock(void)
+{
+ OsSchedUnlock(); /* Unlock schedule */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Initialize OS
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to initialize OS.
+ *
+ * @note You must call this function first,before any other OS API function
+ *
+ * @code There is a example for useage of this function,as follows:
+ * e.g.
+ * ... // Your target initial code.
+ *
+ * OsInit(); // Initial OS.
+ * CreateTask(...); // Create tasks.
+ * ...
+ * OsStart(); // Start multitask.
+ * @endcode
+ *******************************************************************************
+ */
+void CoInitOS(void)
+{
+ InitSysTick(); /* Initialize system tick. */
+ InitInt(); /* Initialize PendSV,SVC,SysTick interrupt */
+ CreateTCBList(); /* Create TCB list. */
+#if CFG_EVENT_EN > 0
+ CreateEventList(); /* Create event control list. */
+#endif
+#if CFG_KHEAP_EN > 0
+ CoCreateKheap(); /* Create kernel heap within user define */
+#endif
+ OsSchedLock(); /* Lock Schedule */
+ /* Create first task -- IDLE task. */
+ CoCreateTask( CoIdleTask,
+ 0,
+ CFG_LOWEST_PRIO,
+ &idle_stk[CFG_IDLE_STACK_SIZE-1],
+ CFG_IDLE_STACK_SIZE
+ );
+ /* Set PSP for CoIdleTask coming in */
+ SetEnvironment(&idle_stk[CFG_IDLE_STACK_SIZE-1]);
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Start multitask
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to start multitask.After it is called,
+ * OS start schedule task by priority or/and time slice.
+ * @note This function must be called to start OS when you use CoOS,and must
+ * call after CoOsInit().
+ *******************************************************************************
+ */
+void CoStartOS(void)
+{
+ TCBRunning = &TCBTbl[0]; /* Get running task */
+ TCBNext = TCBRunning; /* Set next scheduled task as running task */
+ TCBRunning->state = TASK_RUNNING; /* Set running task status to RUNNING */
+ RemoveFromTCBRdyList(TCBRunning); /* Remove running task from READY list */
+ OsSchedUnlock(); /* Enable Schedule,call task schedule */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Get OS version
+ * @param[in] None
+ * @param[out] None
+ * @retval The value is version of OS mutipled by 100.
+ *
+ * @par Description
+ * @details This function is used to return the version number of CooCox OS.
+ * the return value corresponds to CooCox's version number multiplied
+ * by 100. In other words, version 1.02 would be returned as 102.
+ *******************************************************************************
+ */
+OS_VER CoGetOSVersion(void)
+{
+ return OS_VERSION; /* Get CooCox CoOS version */
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/event.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,410 @@
+/**
+ *******************************************************************************
+ * @file event.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief event management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+
+/*---------------------------- Variable Define -------------------------------*/
+#if CFG_EVENT_EN > 0
+
+ECB EventTbl[CFG_MAX_EVENT]= {{0}};/*!< Table which save event control block.*/
+P_ECB FreeEventList = 0; /*!< Pointer to free event control block. */
+
+
+/**
+ *******************************************************************************
+ * @brief Create a empty list of event control block
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called by OSInit() API to create a ECB list,supply
+ * a pointer to next event control block that not used.
+ *******************************************************************************
+ */
+void CreateEventList(void)
+{
+ U8 i;
+ P_ECB pecb1;
+#if CFG_MAX_EVENT > 1
+ P_ECB pecb2;
+#endif
+ i=0;
+ pecb1 = &EventTbl[0]; /* Get first item */
+#if CFG_MAX_EVENT == 1 /* Build event list for only one item */
+ pecb1->eventPtr = 0;
+ pecb1->id = i; /* Assign ID. */
+ pecb1->eventType = EVENT_TYPE_INVALID; /* Sign that not to use. */
+#endif
+
+#if CFG_MAX_EVENT > 1 /* Build event list for more than one item */
+ pecb2 = &EventTbl[1];
+ for(;i< (CFG_MAX_EVENT-1);i++ )
+ {
+ pecb1->eventPtr = (void*)pecb2; /* Set link for list */
+ pecb1->id = i; /* Assign ID. */
+ pecb1->eventType = EVENT_TYPE_INVALID;/* Sign that not to use. */
+ pecb1++; /* Get next item */
+ pecb2++;
+ }
+ pecb1->eventType = EVENT_TYPE_INVALID; /* Sign that not to use. */
+ pecb1->eventPtr = 0; /* Set link for last item */
+ pecb1->id = i;
+#endif
+
+ FreeEventList = &EventTbl[0]; /* Set free event item */
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Release a ECB
+ * @param[in] pecb A pointer to event control block which be released.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to release a event control block when a
+ * event be deleted.
+ *******************************************************************************
+ */
+static void ReleaseECB(P_ECB pecb)
+{
+ pecb->eventType = EVENT_TYPE_INVALID; /* Sign that not to use. */
+ OsSchedLock(); /* Lock schedule */
+ pecb->eventPtr = FreeEventList; /* Release ECB that event hold */
+ FreeEventList = pecb; /* Reset free event item */
+ OsSchedUnlock(); /* Unlock schedule */
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Create a event
+ * @param[in] eventType The type of event which being created.
+ * @param[in] eventSortType Event sort type.
+ * @param[in] eventCounter Event counter,ONLY for EVENT_TYPE_SEM.
+ * @param[in] eventPtr Event struct pointer,ONLY for Queue.0 for other
+ * event type.
+ * @param[out] None
+ * @retval 0 Invalid pointer,create event fail.
+ * @retval others Pointer to event control block which had assigned right now.
+ *
+ * @par Description
+ * @details This function is called by CreateSem(),...
+ * to get a event control block and initial the event content.
+ *
+ * @note This is a internal function of CooCox CoOS,User can't call.
+ *******************************************************************************
+ */
+P_ECB CreatEvent(U8 eventType,U8 eventSortType,void* eventPtr)
+{
+ P_ECB pecb;
+
+ OsSchedLock(); /* Lock schedule */
+ if(FreeEventList == 0) /* Is there no free evnet item */
+ {
+ OsSchedUnlock(); /* Yes,unlock schedule */
+ return 0; /* Return error */
+ }
+ pecb = FreeEventList;/* Assign the free event item to this event */
+ FreeEventList = (P_ECB)FreeEventList->eventPtr; /* Reset free event item */
+ OsSchedUnlock(); /* Unlock schedul */
+
+ pecb->eventType = eventType; /* Initialize event item as user set */
+ pecb->eventSortType = eventSortType;
+ pecb->eventPtr = eventPtr;
+ pecb->eventTCBList = 0;
+ return pecb; /* Return event item pointer */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Delete a event
+ * @param[in] pecb Pointer to event control block which will be deleted.
+ * @param[in] opt Delete option.
+ * @arg == OPT_DEL_ANYWAY Delete event always
+ * @arg == OPT_DEL_NO_PEND Delete event only when no task pending on.
+ * @param[out] None
+ * @retval E_INVALID_PARAMETER Parameter passed is invalid,deleted fail.
+ * @retval E_TASK_WAITTING These are one more tasks waitting event.
+ * @retval E_OK Delete event control block successful.
+ *
+ * @par Description
+ * @details This function is called to delete a event from the event wait list
+ * use specify option.
+ *
+ * @note This is a internal function of Coocox CoOS,user can't call.
+ *******************************************************************************
+ */
+StatusType DeleteEvent(P_ECB pecb,U8 opt)
+{
+ P_OSTCB ptcb;
+ if(opt == OPT_DEL_NO_PEND) /* Do delete event when no task pend? */
+ {
+ if(pecb->eventTCBList != 0) /* Yes,is there task pend this event? */
+ {
+ return E_TASK_WAITING; /* Yes,error return */
+ }
+ else
+ {
+ ReleaseECB(pecb); /* No,release resource that event hold*/
+ }
+ }
+ else if(opt == OPT_DEL_ANYWAY) /* Do delete event anyway? */
+ {
+ OsSchedLock(); /* Lock schedule */
+ while(pecb->eventTCBList != 0) /* Is there task pend this event? */
+ { /* Yes,remove it */
+ ptcb = pecb->eventTCBList;/* Get first task in event waiting list */
+ if(ptcb->delayTick != INVALID_VALUE) /* Is task in delay list? */
+ {
+ RemoveDelayList(ptcb); /* Yes,remove task from delay list */
+ }
+
+ /* Set next item as event waiting list head */
+ pecb->eventTCBList = ptcb->waitNext;
+ ptcb->waitNext = 0; /* Clear link for event waiting list */
+ ptcb->eventID = INVALID_ID; /* Sign that not to use. */
+
+ InsertToTCBRdyList(ptcb); /* Insert task into ready list */
+ }
+ OsSchedUnlock(); /* Unlock schedule */
+ ReleaseECB(pecb); /* Release resource that event hold */
+ }
+ return E_OK; /* Return OK */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Insert a task to event wait list
+ * @param[in] pecb Pointer to event control block corresponding to the event.
+ * @param[in] ptcb Pointer to task that will be insert to event wait list.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to insert a task by fllowing manner:
+ * opt == EVENT_SORT_TYPE_FIFO By FIFO.
+ * opt == EVENT_SORT_TYPE_PRIO By priority order,hghest priority
+ * as head,lowest priority as end.
+ * (Highest-->...-->Lowest-->0)
+ *******************************************************************************
+ */
+void EventTaskToWait(P_ECB pecb,P_OSTCB ptcb)
+{
+ P_OSTCB ptcb1;
+#if (CFG_EVENT_SORT == 2) || (CFG_EVENT_SORT == 3)
+ P_OSTCB ptcb2;
+#endif
+
+ OsSchedLock(); /* Lock schedule */
+ ptcb1 = pecb->eventTCBList; /* Get first task in event waiting list */
+ ptcb->eventID = pecb->id; /* Set event ID for task */
+
+#if CFG_EVENT_SORT == 3 /* Does event waiting list sort as FIFO? */
+
+ if(pecb->eventSortType == EVENT_SORT_TYPE_FIFO)
+#endif
+
+#if (CFG_EVENT_SORT == 1) || (CFG_EVENT_SORT == 3)
+ {
+ if(ptcb1 == 0) /* Is no item in event waiting list?*/
+ {
+ pecb->eventTCBList = ptcb; /* Yes,set task as first item */
+ }
+ else
+ {
+ while(ptcb1->waitNext != 0)/* No,insert task in last */
+ {
+ ptcb1 = ptcb1->waitNext;
+ }
+ ptcb1->waitNext = ptcb; /* Set link for list */
+ ptcb->waitPrev = ptcb1;
+ }
+ }
+#endif
+
+#if CFG_EVENT_SORT ==3 /* Does event waiting list sort as preemptive priority?*/
+ else if(pecb->eventSortType == EVENT_SORT_TYPE_PRIO)
+#endif
+#if (CFG_EVENT_SORT == 2) || (CFG_EVENT_SORT == 3)
+ {
+ if(ptcb1 == 0) /* Is no item in event waiting list? */
+ {
+ pecb->eventTCBList = ptcb; /* Yes,set task as first item */
+ }
+ /* Is PRI of task higher than list first item? */
+ else if(ptcb1->prio > ptcb->prio)
+ {
+ pecb->eventTCBList = ptcb; /* Reset task as first item */
+ ptcb->waitNext = ptcb1; /* Set link for list */
+ ptcb1->waitPrev = ptcb;
+ }
+ else /* No,find correct place to insert */
+ {
+ ptcb2 = ptcb1->waitNext;
+ while(ptcb2 != 0) /* Is last item? */
+ {
+ if(ptcb2->prio > ptcb->prio) /* No,is correct place? */
+ {
+ break; /* Yes,break Circulation */
+ }
+ ptcb1 = ptcb2; /* Save current item */
+ ptcb2 = ptcb2->waitNext; /* Get next item */
+ }
+ ptcb1->waitNext = ptcb; /* Set link for list */
+ ptcb->waitPrev = ptcb1;
+ ptcb->waitNext = ptcb2;
+ if(ptcb2 != 0)
+ {
+ ptcb2->waitPrev = ptcb;
+ }
+ }
+ }
+#endif
+ ptcb->state = TASK_WAITING; /* Set task status to TASK_WAITING state */
+ TaskSchedReq = TRUE;
+ OsSchedUnlock(); /* Unlock schedule,and call task schedule */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Move a task from event WAITING list to the DELAY list
+ * @param[in] pecb Pointer to event control block corresponding to the event.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to remove a task from event wait list,and
+ * then insert it into the READY list.
+ *******************************************************************************
+ */
+void EventTaskToRdy(P_ECB pecb)
+{
+ P_OSTCB ptcb;
+#if CFG_QUEUE_EN >0
+ P_QCB pqcb;
+#endif
+ ptcb = pecb->eventTCBList;
+ if(ptcb == 0)
+ return;
+
+ pecb->eventTCBList = ptcb->waitNext;/* Get first task in event waiting list*/
+ if(pecb->eventTCBList != 0) /* Is no item in event waiting list? */
+ {
+ pecb->eventTCBList->waitPrev = 0; /* No,clear link for first item */
+ }
+
+ ptcb->waitNext = 0; /* Clear event waiting link for task*/
+ ptcb->eventID = INVALID_ID; /* Sign that not to use. */
+
+ if(ptcb->delayTick != INVALID_VALUE) /* Is task in delay list? */
+ {
+ RemoveDelayList(ptcb); /* Yes,remove task from DELAY list */
+ }
+ if(pecb->eventType == EVENT_TYPE_MBOX)/* Is it a mailbox event? */
+ {
+ ptcb->pmail = pecb->eventPtr; /* Yes,send mail to task */
+ pecb->eventPtr = 0; /* Clear event sign */
+ pecb->eventCounter--;
+ }
+#if CFG_QUEUE_EN >0
+ else if(pecb->eventType == EVENT_TYPE_QUEUE) /* Is it a queue event? */
+ {
+ pqcb = (P_QCB)pecb->eventPtr; /* Yes,get queue pointer */
+ ptcb->pmail = *(pqcb->qStart + pqcb->head); /* Send mail to task */
+ pqcb->head++; /* Clear event sign */
+ pqcb->qSize--;
+ if(pqcb->head == pqcb->qMaxSize)
+ {
+ pqcb->head = 0;
+ }
+ }
+#endif
+
+#if CFG_MAILBOX_EN >0
+ else if(pecb->eventType == EVENT_TYPE_SEM)/* Is it a semaphore event? */
+ {
+ pecb->eventCounter--; /* Yes,clear event sign */
+ ptcb->pmail = (void*)0xffffffff; /* Indicate task woke by event */
+ }
+#endif
+ if(ptcb == TCBRunning)
+ {
+ ptcb->state = TASK_RUNNING;
+ }
+ else
+ {
+ InsertToTCBRdyList(ptcb); /* Insert task into ready list */
+ }
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Move a task from event wait list to the ready list
+ * @param[in] pecb Pointer to event control block corresponding to the event.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to remove a task from event wait list,and
+ * then insert it to the ready list.
+ *******************************************************************************
+ */
+void RemoveEventWaittingList(P_OSTCB ptcb)
+{
+ P_ECB pecb;
+ pecb = &EventTbl[ptcb->eventID]; /* Get event control block */
+
+ /* Is there only one item in event waiting list? */
+ if((ptcb->waitNext == 0) && (ptcb->waitPrev == 0))
+ {
+ pecb->eventTCBList = 0; /* Yes,set event waiting list as 0 */
+ }
+ else if(ptcb->waitPrev == 0)/* Is the first item in event waiting list?*/
+ {
+ /* Yes,remove task from list,and reset event waiting list */
+ ptcb->waitNext->waitPrev = 0;
+ pecb->eventTCBList = ptcb->waitNext;
+ ptcb->waitNext = 0;
+ }
+ else if(ptcb->waitNext == 0)/* Is the last item in event waiting list? */
+ {
+ ptcb->waitPrev->waitNext = 0; /* Yes,remove task form list */
+ ptcb->waitPrev = 0;
+ }
+ else /* No, remove task from list */
+ {
+ ptcb->waitPrev->waitNext = ptcb->waitNext;
+ ptcb->waitNext->waitPrev = ptcb->waitPrev;
+ ptcb->waitPrev = 0;
+ ptcb->waitNext = 0;
+ }
+ ptcb->eventID = INVALID_ID; /* Sign that not to use. */
+}
+
+#endif //CFG_EVENT_EN
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/flag.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,712 @@
+/**
+ *******************************************************************************
+ * @file flag.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Flag management implementation code of coocox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+#if CFG_FLAG_EN > 0
+/*---------------------------- Variable Define -------------------------------*/
+#define FLAG_MAX_NUM 32 /*!< Define max flag number. */
+FCB FlagCrl = {0}; /*!< Flags list struct */
+
+
+/*---------------------------- Function Declare ------------------------------*/
+static void FlagBlock(P_FLAG_NODE pnode,U32 flags,U8 waitType);
+static P_FLAG_NODE RemoveFromLink(P_FLAG_NODE pnode);
+
+/**
+ *******************************************************************************
+ * @brief Create a flag
+ * @param[in] bAutoReset Reset mode,TRUE(Auto Reset) FLASE(Manual Reset).
+ * @param[in] bInitialState Initial state.
+ * @param[out] None
+ * @retval E_CREATE_FAIL Create flag fail.
+ * @retval others Create flag successful.
+ *
+ * @par Description
+ * @details This function use to create a event flag.
+ * @note
+ *******************************************************************************
+ */
+OS_FlagID CoCreateFlag(BOOL bAutoReset,BOOL bInitialState)
+{
+ U8 i;
+ OsSchedLock();
+
+ for(i=0;i<FLAG_MAX_NUM;i++)
+ {
+ /* Assign a free flag control block */
+ if((FlagCrl.flagActive&(1<<i)) == 0 )
+ {
+ FlagCrl.flagActive |= (1<<i); /* Initialize active flag */
+ FlagCrl.flagRdy |= (bInitialState<<i);/* Initialize ready flag */
+ FlagCrl.resetOpt |= (bAutoReset<<i);/* Initialize reset option */
+ OsSchedUnlock();
+ return i ; /* Return Flag ID */
+ }
+ }
+ OsSchedUnlock();
+
+ return E_CREATE_FAIL; /* There is no free flag control block*/
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Delete a flag
+ * @param[in] id Flag ID.
+ * @param[in] opt Delete option.
+ * @param[out] None
+ * @retval E_CALL Error call in ISR.
+ * @retval E_INVALID_ID Invalid event ID.
+ * @retval E_TASK_WAITTING Tasks waitting for the event,delete fail.
+ * @retval E_OK Event deleted successful.
+ *
+ * @par Description
+ * @details This function is called to delete a event flag.
+ * @note
+ *******************************************************************************
+ */
+StatusType CoDelFlag(OS_FlagID id,U8 opt)
+{
+ P_FLAG_NODE pnode;
+ P_FCB pfcb;
+ pfcb = &FlagCrl;
+ if(OSIntNesting > 0) /* If be called from ISR */
+ {
+ return E_CALL;
+ }
+#if CFG_PAR_CHECKOUT_EN >0
+ if((pfcb->flagActive&(1<<id)) == 0) /* Flag is valid or not */
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ OsSchedLock();
+ pnode = pfcb->headNode;
+
+ while(pnode != 0) /* Ready all tasks waiting for flags */
+ {
+ if((pnode->waitFlags&(1<<id)) != 0) /* If no task is waiting on flags */
+ {
+ if(opt == OPT_DEL_NO_PEND) /* Delete flag if no task waiting */
+ {
+ OsSchedUnlock();
+ return E_TASK_WAITING;
+ }
+ else if (opt == OPT_DEL_ANYWAY) /* Always delete the flag */
+ {
+ if(pnode->waitType == OPT_WAIT_ALL)
+ {
+ /* If the flag is only required by NODE */
+ if( pnode->waitFlags == (1<<id) )
+ {
+ /* Remove the NODE from waiting list */
+ pnode = RemoveFromLink(pnode);
+ continue;
+ }
+ else
+ {
+ pnode->waitFlags &= ~(1<<id); /* Update waitflags */
+ }
+ }
+ else
+ {
+ pnode = RemoveFromLink(pnode);
+ continue;
+ }
+ }
+ }
+ pnode = pnode->nextNode;
+ }
+
+ /* Remove the flag from the flags list */
+ pfcb->flagActive &= ~(1<<id);
+ pfcb->flagRdy &= ~(1<<id);
+ pfcb->resetOpt &= ~(1<<id);
+ OsSchedUnlock();
+ return E_OK;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief AcceptSingleFlag
+ * @param[in] id Flag ID.
+ * @param[out] None
+ * @retval E_INVALID_ID Invalid event ID.
+ * @retval E_FLAG_NOT_READY Flag is not in ready state.
+ * @retval E_OK The call was successful and your task owns the Flag.
+ *
+ * @par Description
+ * @details This fucntion is called to accept single flag
+ * @note
+ *******************************************************************************
+ */
+StatusType CoAcceptSingleFlag(OS_FlagID id)
+{
+ P_FCB pfcb;
+ pfcb = &FlagCrl;
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= FLAG_MAX_NUM)
+ {
+ return E_INVALID_ID; /* Invalid 'id',return error */
+ }
+ if((pfcb->flagActive&(1<<id)) == 0)
+ {
+ return E_INVALID_ID; /* Flag is deactive,return error */
+ }
+#endif
+ if((pfcb->flagRdy&(1<<id)) != 0) /* If the required flag is set */
+ {
+ OsSchedLock()
+ pfcb->flagRdy &= ~((FlagCrl.resetOpt)&(1<<id)); /* Clear the flag */
+ OsSchedUnlock();
+ return E_OK;
+ }
+ else /* If the required flag is not set */
+ {
+ return E_FLAG_NOT_READY;
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief AcceptMultipleFlags
+ * @param[in] flags Flags that waiting to active task.
+ * @param[in] waitType Flags wait type.
+ * @param[out] perr A pointer to error code.
+ * @retval 0
+ * @retval springFlag
+ *
+ * @par Description
+ * @details This fucntion is called to accept multiple flags.
+ * @note
+ *******************************************************************************
+ */
+U32 CoAcceptMultipleFlags(U32 flags,U8 waitType,StatusType *perr)
+{
+ U32 springFlag;
+ P_FCB pfcb;
+ pfcb = &FlagCrl;
+
+#if CFG_PAR_CHECKOUT_EN >0
+ if((flags&pfcb->flagActive) != flags ) /* Judge flag is active or not? */
+ {
+ *perr = E_INVALID_PARAMETER; /* Invalid flags */
+ return 0;
+ }
+#endif
+
+ springFlag = flags & pfcb->flagRdy;
+
+ OsSchedLock();
+ /* If any required flags are set */
+ if( (springFlag != 0) && (waitType == OPT_WAIT_ANY) )
+ {
+
+ pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt); /* Clear the flags */
+ OsSchedUnlock();
+ *perr = E_OK;
+ return springFlag;
+ }
+
+ /* If all required flags are set */
+ if((springFlag == flags) && (waitType == OPT_WAIT_ALL))
+ {
+ pfcb->flagRdy &= ~(springFlag&pfcb->resetOpt); /* Clear the flags */
+ OsSchedUnlock();
+ *perr = E_OK;
+ return springFlag;
+ }
+ OsSchedUnlock();
+ *perr = E_FLAG_NOT_READY;
+ return 0;
+}
+
+
+
+
+/**
+ *******************************************************************************
+ * @brief WaitForSingleFlag
+ * @param[in] id Flag ID.
+ * @param[in] timeout The longest time for writting flag.
+ * @param[out] None
+ * @retval E_CALL Error call in ISR.
+ * @retval E_INVALID_ID Invalid event ID.
+ * @retval E_TIMEOUT Flag wasn't received within 'timeout' time.
+ * @retval E_OK The call was successful and your task owns the Flag,
+ * or the event you are waiting for occurred.
+ *
+ * @par Description
+ * @details This function is called to wait for only one flag,
+ * (1) if parameter "timeout" == 0,waiting until flag be set;
+ * (2) when "timeout" != 0,if flag was set or wasn't set but timeout
+ * occured,the task will exit the waiting list,convert to READY
+ * or RUNNING state.
+ * @note
+ *******************************************************************************
+ */
+StatusType CoWaitForSingleFlag(OS_FlagID id,U32 timeout)
+{
+ FLAG_NODE flagNode;
+ P_FCB pfcb;
+ P_OSTCB curTCB;
+
+ if(OSIntNesting > 0) /* See if the caller is ISR */
+ {
+ return E_CALL;
+ }
+ if(OSSchedLock != 0) /* Schedule is lock? */
+ {
+ return E_OS_IN_LOCK; /* Yes,error return */
+ }
+
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= FLAG_MAX_NUM) /* Judge id is valid or not? */
+ {
+ return E_INVALID_ID; /* Invalid 'id' */
+ }
+ if((FlagCrl.flagActive&(1<<id)) == 0 )/* Judge flag is active or not? */
+ {
+ return E_INVALID_ID; /* Flag is deactive ,return error */
+ }
+#endif
+
+ OsSchedLock();
+ pfcb = &FlagCrl;
+ /* See if the required flag is set */
+ if((pfcb->flagRdy&(1<<id)) != 0) /* If the required flag is set */
+ {
+ pfcb->flagRdy &= ~((pfcb->resetOpt&(1<<id))); /* Clear the flag */
+ OsSchedUnlock();
+ }
+ else /* If the required flag is not set */
+ {
+ curTCB = TCBRunning;
+ if(timeout == 0) /* If time-out is not configured */
+ {
+ /* Block task until the required flag is set */
+ FlagBlock (&flagNode,(1<<id),OPT_WAIT_ONE);
+ curTCB->state = TASK_WAITING;
+ TaskSchedReq = TRUE;
+ OsSchedUnlock();
+
+ /* The required flag is set and the task is in running state */
+ curTCB->pnode = 0;
+ OsSchedLock();
+
+ /* Clear the required flag or not */
+ pfcb->flagRdy &= ~((1<<id)&(pfcb->resetOpt));
+ OsSchedUnlock();
+ }
+ else /* If time-out is configured */
+ {
+ /* Block task until the required flag is set or time-out occurs */
+ FlagBlock(&flagNode,(1<<id),OPT_WAIT_ONE);
+ InsertDelayList(curTCB,timeout);
+
+ OsSchedUnlock();
+ if(curTCB->pnode == 0) /* If time-out occurred */
+ {
+ return E_TIMEOUT;
+ }
+ else /* If flag is set */
+ {
+ curTCB->pnode = 0;
+ OsSchedLock();
+
+ /* Clear the required flag or not */
+ pfcb->flagRdy &= ~((1<<id)&(pfcb->resetOpt));
+ OsSchedUnlock();
+ }
+ }
+ }
+ return E_OK;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief WaitForMultipleFlags
+ * @param[in] flags Flags that waiting to active task.
+ * @param[in] waitType Flags wait type.
+ * @param[in] timeout The longest time for writting flag.
+ * @param[out] perr A pointer to error code.
+ * @retval 0
+ * @retval springFlag
+ *
+ * @par Description
+ * @details This function is called to pend a task for waitting multiple flag.
+ * @note
+ *******************************************************************************
+ */
+U32 CoWaitForMultipleFlags(U32 flags,U8 waitType,U32 timeout,StatusType *perr)
+{
+ U32 springFlag;
+ P_FCB pfcb;
+ FLAG_NODE flagNode;
+ P_OSTCB curTCB;
+
+
+ if(OSIntNesting > 0) /* If the caller is ISR */
+ {
+ *perr = E_CALL;
+ return 0;
+ }
+ if(OSSchedLock != 0) /* Schedule is lock? */
+ {
+ *perr = E_OS_IN_LOCK;
+ return 0; /* Yes,error return */
+ }
+#if CFG_PAR_CHECKOUT_EN >0
+ if( (flags&FlagCrl.flagActive) != flags )
+ {
+ *perr = E_INVALID_PARAMETER; /* Invalid 'flags' */
+ return 0;
+ }
+#endif
+ OsSchedLock();
+ pfcb = &FlagCrl;
+ springFlag = flags & pfcb->flagRdy;
+
+ /* If any required flags are set */
+ if((springFlag != 0) && (waitType == OPT_WAIT_ANY))
+ {
+ pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt); /* Clear the flag */
+ OsSchedUnlock();
+ *perr = E_OK;
+ return springFlag;
+ }
+
+ /* If all required flags are set */
+ if( (springFlag == flags) && (waitType == OPT_WAIT_ALL) )
+ {
+ pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt); /* Clear the flags */
+ OsSchedUnlock();
+ *perr = E_OK;
+ return springFlag;
+ }
+
+ curTCB = TCBRunning;
+ if(timeout == 0) /* If time-out is not configured */
+ {
+ /* Block task until the required flag are set */
+ FlagBlock(&flagNode,flags,waitType);
+ curTCB->state = TASK_WAITING;
+ TaskSchedReq = TRUE;
+ OsSchedUnlock();
+
+ curTCB->pnode = 0;
+ OsSchedLock();
+ springFlag = flags & pfcb->flagRdy;
+ pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt);/* Clear the flags */
+ OsSchedUnlock();
+ *perr = E_OK;
+ return springFlag;
+ }
+ else /* If time-out is configured */
+ {
+ /* Block task until the required flag are set or time-out occurred */
+ FlagBlock(&flagNode,flags,waitType);
+ InsertDelayList(curTCB,timeout);
+
+ OsSchedUnlock();
+ if(curTCB->pnode == 0) /* If time-out occurred */
+ {
+ *perr = E_TIMEOUT;
+ return 0;
+ }
+ else /* If the required flags are set */
+ {
+ curTCB->pnode = 0;
+ OsSchedLock();
+ springFlag = flags & FlagCrl.flagRdy;
+
+ /* Clear the required ready flags or not */
+ pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt);
+ OsSchedUnlock();
+ *perr = E_OK;
+ return springFlag;
+ }
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Clear a Flag
+ * @param[in] id Flag ID.
+ * @param[out] None
+ * @retval E_OK Event deleted successful.
+ * @retval E_INVALID_ID Invalid event ID.
+ *
+ * @par Description
+ * @details This function is called to clear a flag.
+ *
+ * @note
+ *******************************************************************************
+ */
+StatusType CoClearFlag(OS_FlagID id)
+{
+ P_FCB pfcb;
+ pfcb = &FlagCrl;
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= FLAG_MAX_NUM)
+ {
+ return E_INVALID_ID; /* Invalid id */
+ }
+ if((pfcb->flagActive&(1<<id)) == 0)
+ {
+ return E_INVALID_ID; /* Invalid flag */
+ }
+#endif
+
+ pfcb->flagRdy &= ~(1<<id); /* Clear the flag */
+ return E_OK;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Set a flag
+ * @param[in] id Flag ID.
+ * @param[out] None
+ * @retval E_INVALID_ID Invalid event ID.
+ * @retval E_OK Event deleted successful.
+ *
+ * @par Description
+ * @details This function is called to set a flag.
+ * @note
+ *******************************************************************************
+ */
+StatusType CoSetFlag(OS_FlagID id)
+{
+ P_FLAG_NODE pnode;
+ P_FCB pfcb;
+ pfcb = &FlagCrl;
+
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= FLAG_MAX_NUM) /* Flag is valid or not */
+ {
+ return E_INVALID_ID; /* Invalid flag id */
+ }
+ if((pfcb->flagActive&(1<<id)) == 0)
+ {
+ return E_INVALID_ID; /* Flag is not exist */
+ }
+#endif
+
+ if((pfcb->flagRdy&(1<<id)) != 0) /* Flag had already been set */
+ {
+ return E_OK;
+ }
+
+ pfcb->flagRdy |= (1<<id); /* Update the flags ready list */
+
+ OsSchedLock();
+ pnode = pfcb->headNode;
+ while(pnode != 0)
+ {
+ if(pnode->waitType == OPT_WAIT_ALL) /* Extract all the bits we want */
+ {
+ if((pnode->waitFlags&pfcb->flagRdy) == pnode->waitFlags)
+ {
+ /* Remove the flag node from the wait list */
+ pnode = RemoveFromLink(pnode);
+ if((pfcb->resetOpt&(1<<id)) != 0)/* If the flags is auto-reset*/
+ {
+ break;
+ }
+ continue;
+ }
+ }
+ else /* Extract only the bits we want */
+ {
+ if( (pnode->waitFlags & pfcb->flagRdy) != 0)
+ {
+ /* Remove the flag node from the wait list */
+ pnode = RemoveFromLink(pnode);
+ if((pfcb->resetOpt&(1<<id)) != 0)
+ {
+ break; /* The flags is auto-reset */
+ }
+ continue;
+ }
+ }
+ pnode = pnode->nextNode;
+ }
+ OsSchedUnlock();
+ return E_OK;
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Set a flag in ISR
+ * @param[in] id Flag ID.
+ * @param[out] None
+ * @retval E_INVALID_ID Invalid event ID.
+ * @retval E_OK Event deleted successful.
+ *
+ * @par Description
+ * @details This function is called in ISR to set a flag.
+ * @note
+ *******************************************************************************
+ */
+#if CFG_MAX_SERVICE_REQUEST > 0
+StatusType isr_SetFlag(OS_FlagID id)
+{
+ if(OSSchedLock > 0) /* If scheduler is locked,(the caller is ISR) */
+ {
+ /* Insert the request into service request queue */
+ if(InsertInSRQ(FLAG_REQ,id,0) == FALSE)
+ {
+ return E_SEV_REQ_FULL; /* The service requst queue is full */
+ }
+ else
+ {
+ return E_OK;
+ }
+ }
+ else
+ {
+ return(CoSetFlag(id)); /* The caller is not ISR, set the flag*/
+ }
+}
+#endif
+
+/**
+ *******************************************************************************
+ * @brief Block a task to wait a flag event
+ * @param[in] pnode A node that will link into flag waiting list.
+ * @param[in] flags Flag(s) that the node waiting for.
+ * @param[in] waitType Waiting type of the node.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to block a task to wait a flag event.
+ * @note
+ *******************************************************************************
+ */
+static void FlagBlock(P_FLAG_NODE pnode,U32 flags,U8 waitType)
+{
+ P_FCB pfcb;
+ pfcb = &FlagCrl;
+
+ TCBRunning->pnode = pnode;
+ pnode->waitTask = TCBRunning;
+ pnode->waitFlags = flags; /* Save the flags that we need to wait for*/
+ pnode->waitType = waitType; /* Save the type of wait */
+
+ if(pfcb->tailNode == 0) /* If this is the first NODE to insert? */
+ {
+ pnode->nextNode = 0;
+ pnode->prevNode = 0;
+ pfcb->headNode = pnode; /* Insert the NODE to the head */
+ }
+ else /* If it is not the first NODE to insert? */
+ {
+ pfcb->tailNode->nextNode = pnode; /* Insert the NODE to the tail */
+ pnode->prevNode = pfcb->tailNode;
+ pnode->nextNode = 0;
+ }
+ pfcb->tailNode = pnode;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Remove a flag node from list
+ * @param[in] pnode A node that will remove from flag waiting list.
+ * @param[out] None
+ * @retval pnode Next node of the node that have removed out.
+ *
+ * @par Description
+ * @details This function is called to remove a flag node from the wait list.
+ * @note
+ *******************************************************************************
+ */
+static P_FLAG_NODE RemoveFromLink(P_FLAG_NODE pnode)
+{
+ P_OSTCB ptcb;
+
+ RemoveLinkNode(pnode); /* Remove the flag node from wait list. */
+ ptcb = pnode->waitTask;
+
+ /* The task in the delay list */
+ if(ptcb->delayTick != INVALID_VALUE)/* If the task is in tick delay list */
+ {
+ RemoveDelayList(ptcb); /* Remove the task from tick delay list */
+ }
+
+ ptcb->pnode = (void*)0xffffffff;
+
+ if(ptcb == TCBRunning)
+ {
+ ptcb->state = TASK_RUNNING;
+ }
+ else
+ {
+ InsertToTCBRdyList(ptcb); /* Insert the task to ready list */
+ }
+ return (pnode->nextNode);
+}
+
+/**
+ *******************************************************************************
+ * @brief Remove a flag node from list
+ * @param[in] pnode A node that will remove from flag waiting list.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to remove a flag node from the wait list.
+ * @note
+ *******************************************************************************
+ */
+void RemoveLinkNode(P_FLAG_NODE pnode)
+{
+ /* If only one NODE in the list*/
+ if((pnode->nextNode == 0) && (pnode->prevNode == 0))
+ {
+ FlagCrl.headNode = 0;
+ FlagCrl.tailNode = 0;
+ }
+ else if(pnode->nextNode == 0) /* If the NODE is tail */
+ {
+ FlagCrl.tailNode = pnode->prevNode;
+ pnode->prevNode->nextNode = 0;
+ }
+ else if(pnode->prevNode == 0) /* If the NODE is head */
+ {
+ FlagCrl.headNode = pnode->nextNode;
+ pnode->nextNode->prevNode = 0;
+ }
+ else /* The NODE is in the middle */
+ {
+ pnode->nextNode->prevNode = pnode->prevNode;
+ pnode->prevNode->nextNode = pnode->nextNode;
+ }
+ pnode->waitTask->pnode = 0;
+}
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hook.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,65 @@
+/**
+ *******************************************************************************
+ * @file hook.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief hook management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+/*---------------------------- Inlcude --------------------------------------*/
+#include <coocox.h>
+
+/**
+ *******************************************************************************
+ * @brief IDLE task of OS
+ * @param[in] pdata The parameter passed to IDLE task.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is system IDLE task code.
+ *******************************************************************************
+ */
+void CoIdleTask(void* pdata)
+{
+ /* Add your codes here */
+ for(; ;)
+ {
+ /* Add your codes here */
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Hook for stack overflow
+ * @param[in] taskID Piont to the task which lead to stack overflow.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is a hook for stack overflow.
+ *******************************************************************************
+ */
+void CoStkOverflowHook(OS_TID taskID)
+{
+ /* Process stack overflow here */
+ for(; ;)
+ {
+
+ }
+}
+
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernelHeap.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,409 @@
+/**
+ *******************************************************************************
+ * @file kernelHeap.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief kernel heap management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+
+#if CFG_KHEAP_EN >0
+/*---------------------------- Variable Define -------------------------------*/
+U32 KernelHeap[KHEAP_SIZE] = {0}; /*!< Kernel heap */
+P_FMB FMBlist = 0; /*!< Free memory block list */
+KHeap Kheap = {0}; /*!< Kernel heap control */
+
+
+/*---------------------------- Function Declare ------------------------------*/
+static P_FMB GetPreFMB(P_UMB usedMB);
+/**
+ *******************************************************************************
+ * @brief Create kernel heap
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to create kernel heap.
+ *******************************************************************************
+ */
+void CoCreateKheap(void)
+{
+ Kheap.startAddr = (U32)(KernelHeap); /* Initialize kernel heap control */
+ Kheap.endAddr = (U32)(KernelHeap) + KHEAP_SIZE*4;
+ FMBlist = (P_FMB)KernelHeap; /* Initialize free memory block list*/
+ FMBlist->nextFMB = 0;
+ FMBlist->nextUMB = 0;
+ FMBlist->preUMB = 0;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Allocation size bytes of memory block from kernel heap.
+ * @param[in] size Length of menory block.
+ * @param[out] None
+ * @retval 0 Allocate fail.
+ * @retval others Pointer to memory block.
+ *
+ * @par Description
+ * @details This function is called to allocation size bytes of memory block.
+ *******************************************************************************
+ */
+void* CoKmalloc(U32 size)
+{
+ P_FMB freeMB,newFMB,preFMB;
+ P_UMB usedMB,tmpUMB;
+ U8* memAddr;
+ U32 freeSize;
+ U32 kheapAddr;
+
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if( size == 0 )
+ {
+ return 0;
+ }
+#endif
+
+ /* Word alignment,and add used memory head size */
+ size = (((size+3)>>2)<<2) + 8;
+ kheapAddr = Kheap.endAddr; /* Get the end address of kernel heap */
+ OsSchedLock(); /* Lock schedule */
+ freeMB = FMBlist; /* Get first item of free memory list */
+ preFMB = 0;
+ while(freeMB != 0 ) /* Is out of free memory list? */
+ { /* No */
+ if(freeMB->nextUMB == 0) /* Is last item of free memory list? */
+ { /* Yes,get size for this free item */
+ freeSize = kheapAddr - (U32)(freeMB);
+ }
+ else /* No,get size for this free item */
+ {
+ freeSize = (U32)(freeMB->nextUMB) -1 - (U32)(freeMB);
+ }
+ if(freeSize >= size) /* If the size equal or greater than need */
+ { /* Yes,assign in this free memory */
+ usedMB=(P_UMB)freeMB;/* Get the address for used memory block head*/
+
+ /* Get the address for used memory block */
+ memAddr = (U8*)((U32)(usedMB) + 8);
+
+ /* Is left size of free memory smaller than 12? */
+ if((freeSize-size) < 12)
+ {
+ /* Yes,malloc together(12 is the size of the header information
+ of free memory block ). */
+ if(preFMB != 0)/* Is first item of free memory block list? */
+ { /* No,set the link for list */
+ preFMB->nextFMB = freeMB->nextFMB;
+ }
+ else /* Yes,reset the first item */
+ {
+ FMBlist = freeMB->nextFMB;
+ }
+
+ if(freeMB->nextUMB != 0) /* Is last item? */
+ { /* No,set the link for list */
+ tmpUMB = (P_UMB)((U32)(freeMB->nextUMB)-1);
+ tmpUMB->preMB = (void*)((U32)usedMB|0x1);
+ }
+
+ usedMB->nextMB = freeMB->nextUMB;/* Set used memory block link*/
+ usedMB->preMB = freeMB->preUMB;
+ }
+ else /* No,the left size more than 12 */
+ {
+ /* Get new free memory block address */
+ newFMB = (P_FMB)((U32)(freeMB) + size);
+
+ if(preFMB != 0)/* Is first item of free memory block list? */
+ {
+ preFMB->nextFMB = newFMB; /* No,set the link for list */
+ }
+ else
+ {
+ FMBlist = newFMB; /* Yes,reset the first item */
+ }
+
+ /* Set link for new free memory block */
+ newFMB->preUMB = (P_UMB)((U32)usedMB|0x1);
+ newFMB->nextUMB = freeMB->nextUMB;
+ newFMB->nextFMB = freeMB->nextFMB;
+
+ if(freeMB->nextUMB != 0) /* Is last item? */
+ { /* No,set the link for list */
+ tmpUMB = (P_UMB)((U32)(freeMB->nextUMB)-1);
+ tmpUMB->preMB = newFMB;
+ }
+
+ usedMB->nextMB = newFMB; /* Set used memory block link */
+ usedMB->preMB = freeMB->preUMB;
+ }
+
+ if(freeMB->preUMB != 0) /* Is first item? */
+ { /* No,set the link for list */
+ tmpUMB = (P_UMB)((U32)(freeMB->preUMB)-1);
+ tmpUMB->nextMB = (void*)((U32)usedMB|0x1);
+ }
+
+ OsSchedUnlock(); /* Unlock schedule */
+ return memAddr; /* Return used memory block address */
+ }
+ preFMB = freeMB; /* Save current free memory block as previous */
+ freeMB = freeMB->nextFMB; /* Get the next item as current item*/
+ }
+ OsSchedUnlock(); /* Unlock schedule */
+ return 0; /* Error return */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Release memory block to kernel heap.
+ * @param[in] memBuf Pointer to memory block.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to release memory block.
+ *******************************************************************************
+ */
+void CoKfree(void* memBuf)
+{
+ P_FMB curFMB,nextFMB,preFMB;
+ P_UMB usedMB,nextUMB,preUMB;
+
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(memBuf == 0)
+ {
+ return;
+ }
+#endif
+
+ usedMB = (P_UMB)((U32)(memBuf)-8);
+
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if((U32)(memBuf) < Kheap.startAddr)
+ {
+ return;
+ }
+ if((U32)(memBuf) > Kheap.endAddr)
+ {
+ return;
+ }
+#endif
+
+
+ OsSchedLock(); /* Lock schedule */
+
+#if CFG_PAR_CHECKOUT_EN >0 /* Check UMB in list */
+ if((U32)(usedMB) < (U32)(FMBlist))
+ {
+ preUMB = (P_UMB)((U32)(FMBlist->preUMB)-1);
+ while(preUMB != usedMB)
+ {
+ if(preUMB == 0)
+ {
+ OsSchedUnlock();
+ return;
+ }
+ preUMB = (P_UMB)((U32)(preUMB->preMB)-1);
+ }
+ }
+ else
+ {
+ if(FMBlist == 0)
+ {
+ nextUMB = (P_UMB)(Kheap.startAddr);
+ }
+ else
+ {
+ if(FMBlist->nextUMB != 0)
+ {
+ nextUMB = (P_UMB)((U32)(FMBlist->nextUMB)-1);
+ }
+ else
+ {
+ nextUMB = 0;
+ }
+ }
+
+ while(nextUMB != usedMB)
+ {
+ if(nextUMB == 0)
+ {
+ OsSchedUnlock();
+ return;
+ }
+ if(((U32)(nextUMB->nextMB)&0x1) == 0)
+ {
+ nextFMB = (P_FMB)(nextUMB->nextMB);
+ nextUMB = (P_UMB)((U32)(nextFMB->nextUMB)-1);
+ }
+ else
+ {
+ nextUMB = (P_UMB)((U32)(nextUMB->nextMB)-1);
+ }
+ }
+ }
+#endif
+
+
+ /* Is between two free memory block? */
+ if( (((U32)(usedMB->nextMB)&0x1) == 0) && (((U32)(usedMB->preMB)&0x1)==0) )
+ { /* Yes,is the only one item in kernel heap? */
+ if((usedMB->nextMB == 0) && (usedMB->preMB == 0))
+ {
+ curFMB = (P_FMB)usedMB; /* Yes,release this item */
+ curFMB->nextFMB = 0;
+ curFMB->nextUMB = 0;
+ curFMB->preUMB = 0;
+ FMBlist = curFMB;
+ }
+ else if(usedMB->preMB == 0) /* Is the first item in kernel heap */
+ {
+ /* Yes,release this item,and set link for list */
+ curFMB = (P_FMB)usedMB;
+ nextFMB = (P_FMB)usedMB->nextMB;
+
+ curFMB->nextFMB = nextFMB->nextFMB;
+ curFMB->nextUMB = nextFMB->nextUMB;
+ curFMB->preUMB = 0;
+ FMBlist = curFMB;
+ }
+ else if(usedMB->nextMB == 0) /* Is the last item in kernel heap */
+ { /* Yes,release this item,and set link for list */
+ curFMB = (P_FMB)(usedMB->preMB);
+ curFMB->nextFMB = 0;
+ curFMB->nextUMB = 0;
+ }
+ else /* All no,show this item between two normal FMB */
+ {
+ /* release this item,and set link for list */
+ nextFMB = (P_FMB)usedMB->nextMB;
+ curFMB = (P_FMB)(usedMB->preMB);
+
+ curFMB->nextFMB = nextFMB->nextFMB;
+ curFMB->nextUMB = nextFMB->nextUMB;
+ }
+ }
+ else if(((U32)(usedMB->preMB)&0x1) == 0) /* Is between FMB and UMB? */
+ {
+ if(usedMB->preMB == 0) /* Yes,is the first item in kernel heap? */
+ {
+ /* Yes,release this item,and set link for list */
+ curFMB = (P_FMB)usedMB;
+ nextUMB = (P_UMB)usedMB->nextMB;
+ curFMB->nextUMB = nextUMB;
+ curFMB->preUMB = 0;
+ curFMB->nextFMB = FMBlist;
+ FMBlist = curFMB;
+ }
+ else /* No,release this item,and set link for list */
+ {
+ curFMB = (P_FMB)usedMB->preMB;
+ nextUMB = (P_UMB)usedMB->nextMB;
+ curFMB->nextUMB = nextUMB;
+ }
+
+ }
+ else if(((U32)(usedMB->nextMB)&0x1) == 0) /* Is between UMB and FMB? */
+ { /* Yes */
+ preUMB = (P_UMB)(usedMB->preMB); /* Get previous UMB */
+ curFMB = (P_FMB)(usedMB); /* new FMB */
+ preFMB = GetPreFMB(usedMB); /* Get previous FMB */
+ if(preFMB == 0) /* Is previous FMB==0? */
+ {
+ nextFMB = FMBlist; /* Yes,get next FMB */
+ FMBlist = curFMB; /* Reset new FMB as the first item of FMB list*/
+ }
+ else
+ {
+ nextFMB = preFMB->nextFMB; /* No,get next FMB */
+ preFMB->nextFMB = curFMB; /* Set link for FMB list */
+ }
+
+ if(nextFMB == 0) /* Is new FMB as last item of FMB list? */
+ {
+ curFMB->preUMB = preUMB; /* Yes,set link for list */
+ curFMB->nextUMB = 0;
+ curFMB->nextFMB = 0;
+ }
+ else
+ {
+ curFMB->preUMB = preUMB; /* No,set link for list */
+ curFMB->nextUMB = nextFMB->nextUMB;
+ curFMB->nextFMB = nextFMB->nextFMB;
+ }
+ }
+ else /* All no,show UMB between two UMB*/
+ {
+ curFMB = (P_FMB)(usedMB); /* new FMB */
+ preFMB = GetPreFMB(usedMB); /* Get previous FMB */
+ preUMB = (P_UMB)(usedMB->preMB); /* Get previous UMB */
+ nextUMB = (P_UMB)(usedMB->nextMB); /* Get next UMB */
+
+ if(preFMB == 0 ) /* Is previous FMB==0? */
+ {
+ nextFMB = FMBlist; /* Yes,get next FMB */
+ FMBlist = curFMB; /* Reset new FMB as the first item of FMB list */
+ }
+ else
+ {
+ nextFMB = preFMB->nextFMB; /* No,get next FMB */
+ preFMB->nextFMB = curFMB; /* Set link for FMB list */
+ }
+
+ curFMB->preUMB = preUMB; /* Set current FMB link for list */
+ curFMB->nextUMB = nextUMB;
+ curFMB->nextFMB = nextFMB;
+ }
+
+ if(curFMB->preUMB != 0)/* Is current FMB as first item in kernel heap? */
+ { /* No,set link for list */
+ preUMB = (P_UMB)((U32)(curFMB->preUMB)-1);
+ preUMB->nextMB = (void*)curFMB;
+ }
+ if(curFMB->nextUMB != 0)/* Is current FMB as last item in kernel heap? */
+ { /* No,set link for list */
+ nextUMB = (P_UMB)((U32)(curFMB->nextUMB)-1);
+ nextUMB->preMB = (void*)curFMB;
+ }
+ OsSchedUnlock(); /* Unlock schedule */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Get previous free memory block pointer.
+ * @param[in] usedMB Current used memory block.
+ * @param[out] None
+ * @retval Previous free memory block pointer.
+ *
+ * @par Description
+ * @details This function is called to get previous free memory block pointer.
+ *******************************************************************************
+ */
+static P_FMB GetPreFMB(P_UMB usedMB)
+{
+ P_UMB preUMB;
+ preUMB = usedMB;
+ while(((U32)(preUMB->preMB)&0x1)) /* Is previous MB as FMB? */
+ { /* No,get previous MB */
+ preUMB = (P_UMB)((U32)(preUMB->preMB)-1);
+ }
+ return (P_FMB)(preUMB->preMB); /* Yes,return previous MB */
+}
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,190 @@
+#include "mbed.h"
+#include <CoOS.h>
+
+Serial pc(USBTX, USBRX);
+
+/*---------------------------------- Define ---------------------------------*/
+#define STK_SIZE 128 /*!< Stack size. */
+#define INIT_TASK_PRIO 11 /*!< Priority of "init_task" task. */
+#define A_TASK_PRIO 10 /*!< Priority of "A" task. */
+#define B_TASK_PRIO 10 /*!< Priority of "B" task. */
+#define CLK_TASK_PRIO 10 /*!< Priority of "clock" task. */
+
+/*---------------------------------- Variable Define -------------------------*/
+OS_STK init_task_stk[STK_SIZE]; /*!< The stack of "init_task" task. */
+OS_STK a_task_stk[STK_SIZE]; /*!< The stack of "a" task. */
+OS_STK b_task_stk[STK_SIZE]; /*!< The stack of "b" task. */
+OS_STK clk_task_stk[STK_SIZE]; /*!< The stack of "clcok" task. */
+
+OS_MutexID mut_LED; /*!< Mutex id related to LED. */
+
+OS_FlagID a_flg;
+OS_FlagID b_flg;
+U8 errInfo[32]; /*!< Save error code. */
+
+
+DigitalOut myled(LED1);
+
+/**
+ *******************************************************************************
+ * @brief Switch on LED
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ * @par Description
+ * @details This function use to Switch on specify led in LCD.
+ *******************************************************************************
+ */
+void LED_On ()
+{
+ CoEnterMutexSection(mut_LED);
+ myled =1;
+ CoLeaveMutexSection(mut_LED);
+}
+
+/**
+ *******************************************************************************
+ * @brief Switch off LED
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ * @par Description
+ * @details This function use to Switch off specify led in LCD.
+ *******************************************************************************
+ */
+void LED_Off () {
+
+ CoEnterMutexSection(mut_LED);
+ myled = 0;
+ CoLeaveMutexSection(mut_LED);
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Function 'signal_func' called from multiple tasks
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ * @par Description
+ * @details This function use to Set flag for multiple tasks.
+ *******************************************************************************
+ */
+void signal_func (const char* fromString)
+{
+
+ pc.printf(fromString);
+ CoSetFlag(b_flg);
+ CoTickDelay(50);
+ CoSetFlag(b_flg);
+ CoTickDelay(50);
+ CoSetFlag(a_flg);
+ CoTickDelay(50);
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Task 1 'phaseA': Phase A output
+ * @param[in] pdata A pointer to parameter passed to task.
+ * @param[out] None
+ * @retval None
+ *******************************************************************************
+ */
+void taskA (void *pdata) {
+ for (;;) {
+ CoWaitForSingleFlag(a_flg,0);
+ LED_On();
+ signal_func("\r\nSignal from Task A"); /*!< call common signal function */
+ LED_Off();
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Task 2 'phaseB': Phase B output
+ * @param[in] pdata A pointer to parameter passed to task.
+ * @param[out] None
+ * @retval None
+ *******************************************************************************
+ */
+void taskB (void *pdata) {
+ for (;;) {
+ CoWaitForSingleFlag(a_flg,0);
+ LED_On ();
+ signal_func("\r\nSignal from Task B"); /*!< call common signal function */
+ LED_Off();
+ }
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Task 5 'clock': Signal Clock
+ * @param[in] pdata A pointer to parameter passed to task.
+ * @param[out] None
+ * @retval None
+ *******************************************************************************
+ */
+void clock (void *pdata) {
+ for (;;) {
+ CoWaitForSingleFlag(b_flg,0);
+ LED_On ();
+ CoTickDelay(10);
+ LED_Off();
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief "init_task" task code
+ * @param[in] pdata A pointer to parameter passed to task.
+ * @param[out] None
+ * @retval None
+ * @par Description
+ * @details This task use to create other tasks, all mutexs and flags,and so on.
+ *******************************************************************************
+ */
+void init_task (void *pdata)
+{
+ pdata = pdata;
+
+ mut_LED = CoCreateMutex();
+ a_flg = CoCreateFlag(TRUE,0);
+ b_flg = CoCreateFlag(TRUE,0);
+
+ CoCreateTask(taskA,0,A_TASK_PRIO,&a_task_stk[STK_SIZE-1],STK_SIZE);
+ CoCreateTask(taskB,0,B_TASK_PRIO,&b_task_stk[STK_SIZE-1],STK_SIZE);
+ CoCreateTask(clock,0,CLK_TASK_PRIO,&clk_task_stk[STK_SIZE-1],STK_SIZE);
+ CoSetFlag(a_flg);
+ CoExitTask(); /*!< Delete "init_task" task. */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief main function
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *******************************************************************************
+ */
+int main()
+{
+ //SystemInit(); /*!< Initialize the MCU clocks */
+
+ pc.printf ("\r\n");
+ pc.printf ("\r\nCooCox RTOS Demo\n");
+ CoInitOS(); /*!< Initial CooCox RTOS. */
+ pc.printf ("\r\n CoInitOS done.");
+ CoCreateTask( init_task,0,INIT_TASK_PRIO,&init_task_stk[STK_SIZE-1],STK_SIZE);
+ pc.printf ("\r\n CoCreateTask init_task done.");
+ CoStartOS();
+ pc.printf ("\r\n CoStartOS done.");
+
+ while (1);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Dec 03 19:45:30 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbox.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,322 @@
+/**
+ *******************************************************************************
+ * @file mbox.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Mailbox management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+
+#if CFG_MAILBOX_EN > 0
+
+
+/**
+ *******************************************************************************
+ * @brief Create a mailbox
+ * @param[in] sortType Mail box waiting list sort type.
+ * @param[out] None
+ * @retval E_CREATE_FAIL Create mailbox fail.
+ * @retval others Create mailbox successful.
+ *
+ * @par Description
+ * @details This function is called to create a mailbox.
+ * @note
+ *******************************************************************************
+ */
+OS_EventID CoCreateMbox(U8 sortType)
+{
+ P_ECB pecb;
+
+ /* Create a mailbox type event control block */
+ pecb = CreatEvent(EVENT_TYPE_MBOX,sortType,0);
+ if(pecb == 0) /* If failed to create event block */
+ {
+ return E_CREATE_FAIL;
+ }
+ pecb->eventCounter = 0;
+ return (pecb->id); /* Create a mailbox successfully, return event ID */
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Delete a mailbox
+ * @param[in] id Event ID.
+ * @param[in] opt Delete option.
+ * @param[out] None
+ * @retval E_INVALID_ID Invalid event ID.
+ * @retval E_INVALID_PARAMETER Invalid parameter.
+ * @retval E_TASK_WAITTING Tasks waitting for the event,delete fail.
+ * @retval E_OK Event deleted successful.
+ *
+ * @par Description
+ * @details This function is called to delete a mailbox.
+ * @note
+ *******************************************************************************
+ */
+StatusType CoDelMbox(OS_EventID id,U8 opt)
+{
+ P_ECB pecb;
+
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT) /* Judge id is valid or not? */
+ {
+ return E_INVALID_ID; /* Id is invalid ,return error */
+ }
+#endif
+ pecb = &EventTbl[id];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(pecb->eventType != EVENT_TYPE_MBOX)/* Validate event control block type*/
+ {
+ return E_INVALID_ID; /* The event is not mailbox */
+ }
+#endif
+ return (DeleteEvent(pecb,opt)); /* Delete the mailbox event control block */
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Accept a mailbox
+ * @param[in] id Event ID.
+ * @param[out] perr A pointer to error code.
+ * @retval 0
+ * @retval A pointer to mailbox accepted.
+ *
+ * @par Description
+ * @details This function is called to accept a mailbox.
+ * @note
+ *******************************************************************************
+ */
+void* CoAcceptMail(OS_EventID id,StatusType* perr)
+{
+ P_ECB pecb;
+ void* pmail;
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT)
+ {
+ *perr = E_INVALID_ID; /* Invalid 'id' */
+ return 0;
+ }
+#endif
+ pecb = &EventTbl[id];
+
+#if CFG_PAR_CHECKOUT_EN >0
+ if(pecb->eventType != EVENT_TYPE_MBOX)/* Invalid event control block type */
+ {
+ *perr = E_INVALID_ID;
+ return 0;
+ }
+#endif
+ OsSchedLock();
+ if(pecb->eventCounter == 1) /* If there is already a message */
+ {
+ *perr = E_OK;
+ pmail = pecb->eventPtr; /* Get the message */
+ pecb->eventPtr = 0; /* Clear the mailbox */
+ pecb->eventCounter = 0;
+ OsSchedUnlock();
+ return pmail; /* Return the message received */
+ }
+ else /* If the mailbox is empty */
+ {
+ OsSchedUnlock();
+ *perr = E_MBOX_EMPTY; /* Mailbox is empty,return 0 */
+ return 0;
+ }
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Wait for a mailbox
+ * @param[in] id Event ID.
+ * @param[in] timeout The longest time for writting mail.
+ * @param[out] perr A pointer to error code.
+ * @retval 0
+ * @retval A pointer to mailbox accept.
+ *
+ * @par Description
+ * @details This function is called to wait a mailbox.
+ * @note
+ *******************************************************************************
+ */
+void* CoPendMail(OS_EventID id,U32 timeout,StatusType* perr)
+{
+ P_ECB pecb;
+ void* pmail;
+ P_OSTCB curTCB;
+
+ if(OSIntNesting > 0) /* If the caller is ISR */
+ {
+ *perr = E_CALL;
+ return 0;
+ }
+
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT)
+ {
+ *perr = E_INVALID_ID; /* Invalid 'id',retrun error */
+ return 0;
+ }
+#endif
+
+ pecb = &EventTbl[id];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(pecb->eventType != EVENT_TYPE_MBOX)
+ {
+ *perr = E_INVALID_ID; /* Invalid event type,not EVENT_TYPE_MBOX */
+ return 0;
+ }
+#endif
+
+ if(OSSchedLock != 0) /* Judge schedule is locked or not? */
+ {
+ *perr = E_OS_IN_LOCK; /* Schedule is locked */
+ return 0; /* return 0 */
+ }
+ if( pecb->eventCounter == 1) /* If there is already a message */
+ {
+ *perr = E_OK;
+ pmail = pecb->eventPtr; /* Get the message */
+ pecb->eventPtr = 0; /* Clear the mailbox */
+ pecb->eventCounter = 0;
+ return pmail; /* Return the message received */
+ }
+ else /* If message is not available, task will pend */
+ {
+ curTCB = TCBRunning;
+ if(timeout == 0) /* If time-out is not configured */
+ {
+ EventTaskToWait(pecb,curTCB); /* Block task until event occurs */
+ *perr = E_OK;
+
+ /* Have recived a message or the mailbox have been deleted */
+ pmail = curTCB->pmail;
+ curTCB->pmail = 0;
+ return pmail; /* Return received message or 0 */
+ }
+ else /* If time-out is configured */
+ {
+ OsSchedLock();
+
+ /* Block task until event or timeout occurs */
+ EventTaskToWait(pecb,curTCB);
+ InsertDelayList(curTCB,timeout);
+ OsSchedUnlock();
+ if( curTCB->pmail == 0) /* Time-out occurred */
+ {
+ *perr = E_TIMEOUT;
+ return 0;
+ }
+ else /* Have recived a message or the mailbox have been deleted*/
+ {
+ *perr = E_OK;
+ pmail = curTCB->pmail;
+ curTCB->pmail = 0;
+ return pmail; /* Return received message or 0 */
+ }
+ }
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Post a mailbox
+ * @param[in] id Event ID.
+ * @param[in] pmail Pointer to mail that want to send.
+ * @param[out] None
+ * @retval E_INVALID_ID
+ * @retval E_OK
+ *
+ * @par Description
+ * @details This function is called to post a mail.
+ * @note
+ *******************************************************************************
+ */
+StatusType CoPostMail(OS_EventID id,void* pmail)
+{
+ P_ECB pecb;
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT)
+ {
+ return E_INVALID_ID; /* Invalid id,return error */
+ }
+#endif
+
+ pecb = &EventTbl[id];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(pecb->eventType != EVENT_TYPE_MBOX)/* Validate event control block type*/
+ {
+ return E_INVALID_ID; /* Event is not mailbox,return error*/
+ }
+#endif
+
+ if(pecb->eventCounter == 0) /* If mailbox doesn't already have a message*/
+ {
+ OsSchedLock();
+ pecb->eventPtr = pmail; /* Place message in mailbox */
+ pecb->eventCounter = 1;
+ EventTaskToRdy(pecb); /* Check waiting list */
+ OsSchedUnlock();
+ return E_OK;
+ }
+ else /* If there is already a message in mailbox */
+ {
+ return E_MBOX_FULL; /* Mailbox is full,and return "E_MBOX_FULL" */
+ }
+}
+
+/**
+ *******************************************************************************
+ * @brief Post a mailbox in ISR
+ * @param[in] id Event ID.
+ * @param[in] pmail Pointer to mail that want to send.
+ * @param[out] None
+ * @retval E_INVALID_ID
+ * @retval E_OK
+ *
+ * @par Description
+ * @details This function is called to post a mail in ISR.
+ * @note
+ *******************************************************************************
+ */
+#if CFG_MAX_SERVICE_REQUEST > 0
+StatusType isr_PostMail(OS_EventID id,void* pmail)
+{
+ if(OSSchedLock > 0) /* If scheduler is locked,(the caller is ISR) */
+ {
+ /* Insert the request into service request queue */
+ if(InsertInSRQ(MBOX_REQ,id,pmail) == FALSE)
+ {
+ return E_SEV_REQ_FULL; /* If service request queue is full */
+ }
+ else /* Operate successfully */
+ {
+ return E_OK;
+ }
+ }
+ else
+ {
+ return(CoPostMail(id,pmail)); /* Sends the message to the mailbox */
+ }
+}
+#endif
+
+#endif
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mm.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,275 @@
+/**
+ *******************************************************************************
+ * @file mm.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief memory management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+
+#if CFG_MM_EN > 0
+/*---------------------------- Variable Define -------------------------------*/
+MM MemoryTbl[CFG_MAX_MM] = {{0}};/*!< Table which save memory control block. */
+U32 MemoryIDVessel = 0; /*!< Memory ID container. */
+
+/**
+ *******************************************************************************
+ * @brief Create a memory partition
+ * @param[in] memBuf Specify memory partition head address.
+ * @param[in] blockSize Specify memory block size.
+ * @param[in] blockNum Specify memory block number.
+ * @param[out] None
+ * @retval E_CREATE_FAIL Create memory partition fail.
+ * @retval others Create memory partition successful.
+ *
+ * @par Description
+ * @details This function is called to create a memory partition.
+ *******************************************************************************
+ */
+OS_MMID CoCreateMemPartition(U8* memBuf,U32 blockSize,U32 blockNum)
+{
+ U8 i,j;
+ U8 *memory;
+ P_MemBlk memBlk;
+ memory = memBuf;
+
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(memBuf == 0)
+ {
+ return E_CREATE_FAIL;
+ }
+ if(blockSize == 0)
+ {
+ return E_CREATE_FAIL;
+ }
+ if((blockSize&0x3) != 0)
+ {
+ return E_CREATE_FAIL;
+ }
+ if(blockNum<=1)
+ {
+ return E_CREATE_FAIL;
+ }
+#endif
+
+ OsSchedLock(); /* Lock schedule */
+ for(i = 0; i < CFG_MAX_MM; i++)
+ {
+ if((MemoryIDVessel & (1 << i)) == 0) /* Is free memory ID? */
+ {
+ MemoryIDVessel |= (1<<i); /* Yes,assign ID to this memory block */
+ OsSchedUnlock(); /* Unlock schedule */
+ MemoryTbl[i].memAddr = memory;/* Initialize memory control block*/
+ MemoryTbl[i].freeBlock = memory;
+ MemoryTbl[i].blockSize = blockSize;
+ MemoryTbl[i].blockNum = blockNum;
+ memBlk = (P_MemBlk)memory; /* Bulid list in this memory block*/
+ for(j=0;j<blockNum-1;j++)
+ {
+ memory = memory+blockSize;
+ memBlk->nextBlock = (P_MemBlk)memory;
+ memBlk = memBlk->nextBlock;
+ }
+ memBlk->nextBlock = 0;
+ return i; /* Return memory block ID */
+ }
+ }
+ OsSchedUnlock(); /* Unlock schedule */
+ return E_CREATE_FAIL; /* Error return */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Delete a memory partition
+ * @param[in] mmID Specify memory partition that want to delete.
+ * @param[out] None
+ * @retval E_INVALID_ID The memory partition id passed was invalid,delete fail.
+ * @retval E_OK Delete successful.
+ *
+ * @par Description
+ * @details This function is called to Delete a memory partition.
+ *******************************************************************************
+ */
+StatusType CoDelMemoryPartition(OS_MMID mmID)
+{
+ P_MM memCtl;
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(mmID >= CFG_MAX_MM)
+ {
+ return E_INVALID_ID;
+ }
+ if( ((1<<mmID)&MemoryIDVessel) == 0)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ OsSchedLock(); /* Lock schedule */
+ memCtl = &MemoryTbl[mmID]; /* Release memory control block */
+ MemoryIDVessel &= ~(1<<mmID);
+ OsSchedUnlock(); /* Unlock schedule */
+
+ memCtl->memAddr = 0;
+ memCtl->freeBlock = 0;
+ memCtl->blockSize = 0;
+ memCtl->blockNum = 0;
+ return E_OK; /* Return OK */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Get free block number in a memory partition
+ * @param[in] mmID Specify memory partition.
+ *
+ * @param[out] E_INVALID_ID Invalid ID was passed and get counter failure.
+ * @param[out] E_OK Get current counter successful.
+ * @retval fbNum The number of free block.
+ *
+ * @par Description
+ * @details This function is called to get free block number in a memory
+ * partition.
+ *******************************************************************************
+ */
+U32 CoGetFreeBlockNum(OS_MMID mmID,StatusType* perr)
+{
+ U32 fbNum;
+ P_MM memCtl;
+ P_MemBlk memBlk;
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(mmID >= CFG_MAX_MM)
+ {
+ *perr = E_INVALID_ID;
+ return 0;
+ }
+ if( ((1<<mmID)&MemoryIDVessel) == 0)
+ {
+ *perr = E_INVALID_ID; /* Invalid memory id,return 0 */
+ return 0;
+ }
+#endif
+ memCtl = &MemoryTbl[mmID];
+ OsSchedLock(); /* Lock schedule */
+ memBlk = (P_MemBlk)(memCtl->freeBlock);/* Get the free item in memory list*/
+ fbNum = 0;
+ while(memBlk != 0) /* Get counter of free item */
+ {
+ fbNum++;
+ memBlk = memBlk->nextBlock; /* Get next free iterm */
+ }
+ OsSchedUnlock(); /* Unlock schedul */
+ *perr = E_OK;
+ return fbNum; /* Return the counter of free item */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Get a memory buffer from memory partition
+ * @param[in] mmID Specify memory partition that want to assign buffer.
+ * @param[out] None
+ * @retval 0 Assign buffer fail.
+ * @retval others Assign buffer successful,and return the buffer pointer.
+ *
+ * @par Description
+ * @details This function is called to Delete a memory partition.
+ *******************************************************************************
+ */
+void* CoGetMemoryBuffer(OS_MMID mmID)
+{
+ P_MM memCtl;
+ P_MemBlk memBlk;
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(mmID >= CFG_MAX_MM)
+ {
+ return 0;
+ }
+ if( ((1<<mmID)&MemoryIDVessel) == 0)
+ {
+ return 0;
+ }
+#endif
+ memCtl = &MemoryTbl[mmID];
+ OsSchedLock(); /* Lock schedule */
+ if(memCtl->freeBlock == 0 ) /* Is there no free item in memory list */
+ {
+ OsSchedUnlock(); /* Unlock schedule */
+ return 0; /* Yes,error return */
+ }
+ memBlk = (P_MemBlk)memCtl->freeBlock; /* Get free memory block */
+ memCtl->freeBlock = (U8*)memBlk->nextBlock; /* Reset the first free item */
+ OsSchedUnlock(); /* Unlock schedule */
+ return memBlk; /* Return free memory block address */
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Free a memory buffer to memory partition
+ * @param[in] mmID Specify memory partition.
+ * @param[in] buf Specify memory buffer that want to free.
+ * @param[out] None
+ * @retval E_INVALID_ID The memory partition id passed was invalid.
+ * @retval E_INVALID_PARAMETER The parameter passed was invalid.
+ * @retval E_OK Free successful.
+ *
+ * @par Description
+ * @details This function is called to Delete a memory partition.
+ *******************************************************************************
+ */
+StatusType CoFreeMemoryBuffer(OS_MMID mmID,void* buf)
+{
+ P_MM memCtl;
+ P_MemBlk memBlk;
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(mmID >= CFG_MAX_MM)
+ {
+ return E_INVALID_ID;
+ }
+ if( ((1<<mmID)&MemoryIDVessel) == 0)
+ {
+ return E_INVALID_ID;
+ }
+ if(buf == 0)
+ {
+ return E_INVALID_PARAMETER;
+ }
+#endif
+
+ memCtl = &MemoryTbl[mmID];
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if((U32)buf < (U32)(memCtl->memAddr))
+ {
+ return E_INVALID_PARAMETER;
+ }
+ if((U32)buf > (U32)(memCtl->memAddr + memCtl->blockSize*memCtl->blockNum))
+ {
+ return E_INVALID_PARAMETER;
+ }
+ if(((U32)buf - (U32)(memCtl->memAddr))%(memCtl->blockSize) != 0)
+ {
+ return E_INVALID_PARAMETER;
+ }
+#endif
+ memBlk = (P_MemBlk)buf; /* Reset the first free item */
+ OsSchedLock();
+ memBlk->nextBlock = (P_MemBlk)memCtl->freeBlock;
+ memCtl->freeBlock = (U8 *) buf;
+ OsSchedUnlock();
+ return E_OK; /* Return OK */
+}
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mutex.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,349 @@
+/**
+ *******************************************************************************
+ * @file mutex.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Mutex management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+
+/*---------------------------- Variable Define -------------------------------*/
+#if CFG_MUTEX_EN > 0
+
+OS_MutexID MutexFreeID = 0; /*!< Point to next vliad mutex ID. */
+MUTEX MutexTbl[CFG_MAX_MUTEX] = {{0}}; /*!< Mutex struct array */
+
+
+
+/**
+ *******************************************************************************
+ * @brief Create a mutex
+ * @param[in] None
+ * @param[out] None
+ * @retval E_CREATE_FAIL Create mutex fail.
+ * @retval others Create mutex successful.
+ *
+ * @par Description
+ * @details This function is called to create a mutex.
+ * @note
+ *******************************************************************************
+ */
+OS_MutexID CoCreateMutex(void)
+{
+ OS_MutexID id;
+ P_MUTEX pMutex;
+ OsSchedLock();
+
+ /* Assign a free mutex control block */
+ if(MutexFreeID < CFG_MAX_MUTEX )
+ {
+ id = MutexFreeID++;
+ OsSchedUnlock();
+ pMutex = &MutexTbl[id];
+ pMutex->hipriTaskID = INVALID_ID;
+ pMutex->originalPrio = 0xff;
+ pMutex->mutexFlag = MUTEX_FREE; /* Mutex is free,not was occupied */
+ pMutex->taskID = INVALID_ID;
+ pMutex->waittingList = 0;
+ return id; /* Return mutex ID */
+ }
+
+ OsSchedUnlock();
+ return E_CREATE_FAIL; /* No free mutex control block */
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Enter a critical area
+ * @param[in] mutexID Specify mutex.
+ * @param[out] None
+ * @retval E_INVALID_ID Invalid mutex id.
+ * @retval E_CALL Error call in ISR.
+ * @retval E_OK Enter critical area successful.
+ *
+ * @par Description
+ * @details This function is called when entering a critical area.
+ * @note
+ *******************************************************************************
+ */
+StatusType CoEnterMutexSection(OS_MutexID mutexID)
+{
+ P_OSTCB ptcb,pCurTcb;
+ P_MUTEX pMutex;
+
+#if CFG_EVENT_EN >0
+ P_ECB pecb;
+#endif
+
+ if(OSIntNesting > 0) /* If the caller is ISR */
+ {
+ return E_CALL;
+ }
+ if(OSSchedLock != 0) /* Is OS lock? */
+ {
+ return E_OS_IN_LOCK; /* Yes,error return */
+ }
+
+#if CFG_PAR_CHECKOUT_EN >0
+ if(mutexID >= MutexFreeID) /* Invalid 'mutexID' */
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ OsSchedLock();
+ pCurTcb = TCBRunning;
+ pMutex = &MutexTbl[mutexID];
+
+ pCurTcb->mutexID = mutexID;
+ if(pMutex->mutexFlag == MUTEX_FREE) /* If mutex is available */
+ {
+ pMutex->originalPrio = pCurTcb->prio; /* Save priority of owning task */
+ pMutex->taskID = pCurTcb->taskID; /* Acquire the resource */
+ pMutex->hipriTaskID = pCurTcb->taskID;
+ pMutex->mutexFlag = MUTEX_OCCUPY; /* Occupy the mutex resource*/
+ }
+ /* If the mutex resource had been occupied */
+ else if(pMutex->mutexFlag == MUTEX_OCCUPY)
+ {
+ ptcb = &TCBTbl[pMutex->taskID];
+ if(ptcb->prio > pCurTcb->prio) /* Need to promote priority of owner? */
+ {
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ DeleteTaskPri(ptcb->prio);
+ ActiveTaskPri(pCurTcb->prio);
+#endif
+ ptcb->prio = pCurTcb->prio; /* Promote prio of owner */
+
+ /* Upgarde the highest priority about the mutex */
+ pMutex->hipriTaskID = pCurTcb->taskID;
+ if(ptcb->state == TASK_READY) /* If the task is ready to run */
+ {
+ RemoveFromTCBRdyList(ptcb); /* Remove the task from READY list*/
+ InsertToTCBRdyList(ptcb); /* Insert the task into READY list*/
+ }
+#if CFG_EVENT_EN >0
+ /* If the task is waiting on a event */
+ else if(ptcb->eventID != INVALID_ID)
+ {
+ pecb = &EventTbl[ptcb->eventID];
+
+ /* If the event waiting type is preemptive Priority */
+ if(pecb->eventSortType == EVENT_SORT_TYPE_PRIO)
+ {
+ /* Remove the task from event waiting list */
+ RemoveEventWaittingList(ptcb);
+
+ /* Insert the task into event waiting list */
+ EventTaskToWait(pecb,ptcb);
+ }
+ }
+#endif
+ }
+
+ pCurTcb->state = TASK_WAITING; /* Block current task */
+ TaskSchedReq = TRUE;
+ pCurTcb->TCBnext = 0;
+ pCurTcb->TCBprev = 0;
+
+ ptcb = pMutex->waittingList;
+ if(ptcb == 0) /* If the event waiting list is empty */
+ {
+ pMutex->waittingList = pCurTcb; /* Insert the task to head */
+ }
+ else /* If the event waiting list is not empty */
+ {
+ while(ptcb->TCBnext != 0) /* Insert the task to tail */
+ {
+ ptcb = ptcb->TCBnext;
+ }
+ ptcb->TCBnext = pCurTcb;
+ pCurTcb->TCBprev = ptcb;
+ pCurTcb->TCBnext = 0;
+ }
+ }
+ OsSchedUnlock();
+ return E_OK;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Leave from a critical area
+ * @param[in] mutexID Specify mutex id.
+ * @param[out] None
+ * @retval E_INVALID_ID Invalid mutex id.
+ * @retval E_CALL Error call in ISR.
+ * @retval E_OK Exit a critical area successful.
+ *
+ * @par Description
+ * @details This function must be called when exiting from a critical area.
+ * @note
+ *******************************************************************************
+ */
+StatusType CoLeaveMutexSection(OS_MutexID mutexID)
+{
+ P_OSTCB ptcb;
+ P_MUTEX pMutex;
+ U8 prio;
+ U8 taskID;
+
+ if(OSIntNesting > 0) /* If the caller is ISR */
+ {
+ return E_CALL;
+ }
+
+#if CFG_PAR_CHECKOUT_EN >0
+ if(mutexID >= MutexFreeID)
+ {
+ return E_INVALID_ID; /* Invalid mutex id, return error */
+ }
+#endif
+ OsSchedLock();
+ pMutex = &MutexTbl[mutexID]; /* Obtain point of mutex control block*/
+ ptcb = &TCBTbl[pMutex->taskID];
+ ptcb->mutexID = INVALID_ID;
+ if(pMutex->waittingList == 0) /* If the mutex waiting list is empty */
+ {
+ pMutex->mutexFlag = MUTEX_FREE; /* The mutex resource is available */
+ pMutex->taskID = INVALID_ID;
+ OsSchedUnlock();
+ }
+ else /* If there is at least one task waitting for the mutex */
+ {
+ taskID = pMutex->taskID; /* Get task ID of mutex owner */
+
+ /* we havn't promoted current task's priority */
+ if(pMutex->hipriTaskID == taskID)
+ {
+ ptcb = pMutex->waittingList;/* Point to mutex first waiting task */
+ prio = ptcb->prio;
+ while(ptcb != 0) /* Find the highest priority task */
+ {
+ if(ptcb->prio < prio)
+ {
+ prio = ptcb->prio;
+ pMutex->hipriTaskID = ptcb->taskID;
+ }
+ ptcb = ptcb->TCBnext;
+ }
+ }
+ else /* we have promoted current task's priority */
+ {
+ prio = TCBTbl[taskID].prio;
+ }
+
+ /* Reset the task priority */
+ pMutex->taskID = INVALID_ID;
+ CoSetPriority(taskID,pMutex->originalPrio);
+
+ /* Find first task in waiting list ready to run */
+ ptcb = pMutex->waittingList;
+ pMutex->waittingList = ptcb->TCBnext;
+ pMutex->originalPrio = ptcb->prio;
+ pMutex->taskID = ptcb->taskID;
+
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ if(prio != ptcb->prio)
+ {
+ DeleteTaskPri(ptcb->prio);
+ ActiveTaskPri(prio);
+ }
+#endif
+
+ ptcb->prio = prio; /* Raise the task's priority */
+
+ /* Insert the task which acquire the mutex into ready list. */
+ ptcb->TCBnext = 0;
+ ptcb->TCBprev = 0;
+
+ InsertToTCBRdyList(ptcb); /* Insert the task into the READY list */
+ OsSchedUnlock();
+ }
+ return E_OK;
+}
+
+/**
+ *******************************************************************************
+ * @brief Remove a task from mutex waiting list
+ * @param[in] ptcb TCB which will remove out.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function be called when delete a task.
+ * @note
+ *******************************************************************************
+ */
+void RemoveMutexList(P_OSTCB ptcb)
+{
+ U8 prio;
+ OS_TID taskID;
+ P_MUTEX pMutex;
+ pMutex = &MutexTbl[ptcb->mutexID];
+
+ /* If only one task waiting on mutex */
+ if((ptcb->TCBnext ==0) && (ptcb->TCBprev == 0))
+ {
+ pMutex->waittingList = 0; /* Waiting list is empty */
+ }
+ else if(ptcb->TCBnext == 0) /* If the task is the last of waiting list*/
+ {
+ /* Remove task from mutex waiting list */
+ ptcb->TCBprev->TCBnext = 0;
+ ptcb->TCBprev = 0;
+ }
+ else if(ptcb->TCBprev == 0)/* If the task is the first of waiting list*/
+ {
+ /* Remove task from waiting list */
+ ptcb->TCBnext->TCBprev = 0;
+ ptcb->TCBnext = 0;
+ }
+ else /* If the task is in the middle of waiting list */
+ {
+ /* Remove task from wait list */
+ ptcb->TCBnext->TCBprev = ptcb->TCBprev;
+ ptcb->TCBprev->TCBnext = ptcb->TCBnext;
+ ptcb->TCBprev = 0;
+ ptcb->TCBnext = 0;
+ }
+
+ ptcb->mutexID = INVALID_ID;
+
+ /* If the task have highest priority in mutex waiting list */
+ if(pMutex->hipriTaskID == ptcb->taskID)
+ {
+ ptcb = pMutex->waittingList;
+ prio = pMutex->originalPrio;
+ pMutex->hipriTaskID = pMutex->taskID;
+ while(ptcb != 0) /* Find task ID of highest priority task*/
+ {
+ if(ptcb->prio < prio)
+ {
+ prio = ptcb->prio;
+ pMutex->hipriTaskID = ptcb->taskID;
+ }
+ ptcb = ptcb->TCBnext;
+ }
+ taskID = pMutex->taskID;
+ pMutex->taskID = INVALID_ID;
+ CoSetPriority(taskID,prio); /* Reset the mutex ower priority */
+ pMutex->taskID = taskID;
+ }
+}
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/port.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,248 @@
+/**
+ *******************************************************************************
+ * @file prot.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Compiler adapter for CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2010 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+
+/**
+ ******************************************************************************
+ * @brief Plus a byte integers and Saved into memory cell
+ * @param[in] data byte integers.
+ * @param[out] None
+ * @retval Returns Original value.
+ *
+ * @par Description
+ * @details This function is called to Plus a byte integers
+ * and Saved into memory cell.
+ ******************************************************************************
+ */
+__asm U8 Inc8 (volatile U8 *data)
+{
+ PUSH {R1}
+ CPSID I
+ LDRB R1,[R0]
+ ADDS R1,#1
+ STRB R1,[R0]
+ CPSIE I
+ SUBS R1,#1
+ MOVS R0,R1
+ POP {R1}
+ BX LR
+ ALIGN
+}
+
+
+/**
+ ******************************************************************************
+ * @brief Decrease a byte integers and Saved into memory cell
+ * @param[in] data byte integers.
+ * @param[out] None
+ * @retval Returns Original value.
+ *
+ * @par Description
+ * @details This function is called to Decrease a byte integers
+ * and Saved into memory cell.
+ ******************************************************************************
+ */
+__asm U8 Dec8 (volatile U8 *data)
+{
+ PUSH {R1}
+ CPSID I
+ LDRB R1,[R0]
+ SUBS R1,#1
+ STRB R1,[R0]
+ CPSIE I
+ MOVS R0,R1
+ POP {R1}
+ BX LR
+ ALIGN
+}
+
+/**
+ ******************************************************************************
+ * @brief ENABLE Interrupt
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to ENABLE Interrupt.
+ ******************************************************************************
+ */
+__asm void IRQ_ENABLE_RESTORE(void)
+{ CPSIE I
+ BX LR
+}
+
+/**
+ ******************************************************************************
+ * @brief Close Interrupt
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to close Interrupt.
+ ******************************************************************************
+ */
+__asm void IRQ_DISABLE_SAVE(void)
+{ CPSID I
+ BX LR
+}
+
+/**
+ ******************************************************************************
+ * @brief Set environment for Coocox OS running
+ * @param[in] pstk stack pointer
+ * @param[out] None
+ * @retval None.
+ *
+ * @par Description
+ * @details This function is called to Set environment
+ * for Coocox OS running.
+ ******************************************************************************
+ */
+__asm void SetEnvironment(OS_STK *pstk)
+{
+ SUBS R0,#28
+ MSR PSP, R0 ; Mov new stack point to PSP
+ BX LR
+ ALIGN
+}
+
+
+/**
+ ******************************************************************************
+ * @brief Do ready work to Switch Context for task change
+ * @param[in] None
+ * @param[out] None
+ * @retval None.
+ *
+ * @par Description
+ * @details This function is called to Do ready work to
+ * Switch Context for task change
+ ******************************************************************************
+ */
+__asm void SwitchContext(void)
+{
+ LDR R0, =0xE000ED04 ; Trigger the PendSV exception (causes context switch)
+ LDR R1, =0x10000000
+ STR R1, [R0]
+ BX LR
+ ALIGN
+}
+
+
+/**
+ ******************************************************************************
+ * @brief Switch Context for task change
+ * @param[in] None
+ * @param[out] None
+ * @retval None.
+ *
+ * @par Description
+ * @details This function is called to Switch Context for task change.
+ ******************************************************************************
+ */
+#if CFG_CHIP_TYPE == 2
+extern "C" __asm void PendSV_Handler()
+{
+ IMPORT TCBRunning
+ IMPORT TCBNext
+ IMPORT OSSchedLock
+ LDR R3,=TCBRunning
+ LDR R1,[R3] ; R1 == running tcb
+ LDR R2,=TCBNext
+ LDR R2,[R2] ; R2 == next tcb
+
+ CMP R1,R2
+ BEQ exitPendSV
+ MRS R0, PSP ; Get PSP point (can not use PUSH,in ISR,SP is MSP )
+
+ SUBS R0,R0,#32
+ STR R0,[R1] ; Save orig PSP
+ ; Store r4-r11,r0 -= regCnt * 4,r0 is new stack
+ ; top point (addr h->l r11,r10,...,r5,r4)
+ STMIA R0!,{R4-R7} ; Save old context (R4-R7)
+ MOV R4,R8
+ MOV R5,R9
+ MOV R6,R10
+ MOV R7,R11
+ STMIA R0!,{R4-R7} ; Save old context (R8-R11)
+
+
+popStk
+ STR R2, [R3] ; TCBRunning = TCBNext;
+ LDR R0, [R2] ; Get SP of task that be switch into.
+
+ ADDS R0, R0,#16
+ LDMIA R0!,{R4-R7} ; Restore new Context (R8-R11)
+ MOV R8,R4
+ MOV R9,R5
+ MOV R10,R6
+ MOV R11,R7
+ SUBS R0,R0,#32
+ LDMIA R0!,{R4-R7} ; Restore new Context (R4-R7)
+ ADDS R0, R0,#16
+ MSR PSP, R0 ; Mov new stack point to PSP
+
+exitPendSV
+ LDR R3,=OSSchedLock
+ MOVS R0, #0x0
+ STRB R0, [R3]
+ MOVS R0,#4
+ RSBS R0,#0 ; =0xFFFFFFFC,Ensure exception return uses process stack
+ BX R0 ; Exit interrupt
+ ALIGN
+}
+#endif
+
+
+#if CFG_CHIP_TYPE == 1
+extern "C" __asm void PendSV_Handler()
+{
+ IMPORT TCBRunning
+ IMPORT TCBNext
+ IMPORT OSSchedLock
+ LDR R3,=TCBRunning
+ LDR R1,[R3] ; R1 == running tcb
+ LDR R2,=TCBNext
+ LDR R2,[R2] ; R2 == next tcb
+
+ CMP R1,R2
+ BEQ exitPendSV
+ MRS R0, PSP ; Get PSP point (can not use PUSH,in ISR,SP is MSP )
+ STMDB R0!,{R4-R11} ; Store r4-r11,r0 -= regCnt * 4,r0 is new stack
+ ; top point (addr h->l r11,r10,...,r5,r4)
+ STR R0,[R1] ; Save orig PSP
+popStk
+ STR R2, [R3] ; TCBRunning = TCBNext;
+ LDR R0, [R2] ; Get SP of task that be switch into.
+ LDMIA R0!,{R4-R11} ; POP (R4-R11),R0 += regCnt * 4
+ MSR PSP, R0 ; Mov new stack point to PSP
+
+exitPendSV
+ LDR R3,=OSSchedLock
+ MOVS R0, #0x0
+ STRB R0, [R3]
+ ORR LR, LR, #0x04 ; Ensure exception return uses process stack
+ BX LR ; Exit interrupt
+
+ ALIGN
+}
+#endif
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/queue.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,391 @@
+/**
+ *******************************************************************************
+ * @file queue.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Queue management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+
+#if CFG_QUEUE_EN > 0
+/*---------------------------- Variable Define -------------------------------*/
+QCB QueueTbl[CFG_MAX_QUEUE] = {{0}}; /*!< Queue control block table */
+U32 QueueIDVessel = 0; /*!< Queue list mask */
+
+
+
+/**
+ *******************************************************************************
+ * @brief Create a queue
+ * @param[in] qStart Pointer to mail pointer buffer.
+ * @param[in] size The length of queue.
+ * @param[in] sortType Mail queue waiting list sort type.
+ * @param[out] None
+ * @retval E_CREATE_FAIL Create queue fail.
+ * @retval others Create queue successful.
+ *
+ * @par Description
+ * @details This function is called to create a queue.
+ * @note
+ *******************************************************************************
+ */
+OS_EventID CoCreateQueue(void **qStart, U16 size ,U8 sortType)
+{
+ U8 i;
+ P_ECB pecb;
+
+#if CFG_PAR_CHECKOUT_EN >0
+ if((qStart == 0) || (size == 0))
+ {
+ return E_CREATE_FAIL;
+ }
+#endif
+
+ OsSchedLock();
+ for(i = 0; i < CFG_MAX_QUEUE; i++)
+ {
+ /* Assign a free QUEUE control block */
+ if((QueueIDVessel & (1 << i)) == 0)
+ {
+ QueueIDVessel |= (1<<i);
+ OsSchedUnlock();
+
+ QueueTbl[i].qStart = qStart; /* Initialize the queue */
+ QueueTbl[i].id = i;
+ QueueTbl[i].head = 0;
+ QueueTbl[i].tail = 0;
+ QueueTbl[i].qMaxSize = size;
+ QueueTbl[i].qSize = 0;
+
+ /* Get a event control block and initial the event content */
+ pecb = CreatEvent(EVENT_TYPE_QUEUE,sortType,&QueueTbl[i]);
+
+ if(pecb == 0 ) /* If there is no free EVENT control block*/
+ {
+ return E_CREATE_FAIL;
+ }
+ return (pecb->id);
+ }
+ }
+
+ OsSchedUnlock();
+ return E_CREATE_FAIL; /* There is no free QUEUE control block */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Delete a queue
+ * @param[in] id Event ID.
+ * @param[in] opt Delete option.
+ * @param[out] None
+ * @retval E_INVALID_ID Invalid event ID.
+ * @retval E_INVALID_PARAMETER Invalid parameter.
+ * @retval E_TASK_WAITTING Tasks waitting for the event,delete fail.
+ * @retval E_OK Event deleted successful.
+ *
+ * @par Description
+ * @details This function is called to delete a queue.
+ * @note
+ *******************************************************************************
+ */
+StatusType CoDelQueue(OS_EventID id,U8 opt)
+{
+ P_ECB pecb;
+ P_QCB pqcb;
+ StatusType err;
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT)
+ {
+ return E_INVALID_ID; /* Invalid id,return error */
+ }
+#endif
+
+ pecb = &EventTbl[id];
+#if CFG_PAR_CHECKOUT_EN >0
+ if( pecb->eventType != EVENT_TYPE_QUEUE)
+ {
+ return E_INVALID_ID; /* The event is not queue,return error*/
+ }
+#endif
+ pqcb = (P_QCB)pecb->eventPtr; /* Point at queue control block */
+ err = DeleteEvent(pecb,opt); /* Delete the event control block */
+ if(err == E_OK) /* If the event block have been deleted */
+ {
+ QueueIDVessel &= ~((U32)(1<<(pqcb->id))); /* Update free queue list */
+ pqcb->qStart = 0;
+ pqcb->id = 0;
+ pqcb->head = 0;
+ pqcb->tail = 0;
+ pqcb->qMaxSize = 0;
+ pqcb->qSize = 0;
+ }
+ return err;
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Accept a mail from queue
+ * @param[in] id Event ID.
+ * @param[out] perr A pointer to error code.
+ * @retval 0
+ * @retval A pointer to mail accepted.
+ *
+ * @par Description
+ * @details This function is called to accept a mail from queue.
+ * @note
+ *******************************************************************************
+ */
+void* CoAcceptQueueMail(OS_EventID id,StatusType* perr)
+{
+ P_ECB pecb;
+ P_QCB pqcb;
+ void* pmail;
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT)
+ {
+ *perr = E_INVALID_ID; /* Invalid id,return error */
+ return 0;
+ }
+#endif
+
+ pecb = &EventTbl[id];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(pecb->eventType != EVENT_TYPE_QUEUE)/* Invalid event control block type*/
+ {
+ *perr = E_INVALID_ID;
+ return 0;
+ }
+#endif
+ pqcb = (P_QCB)pecb->eventPtr; /* Point at queue control block */
+ OsSchedLock();
+ if(pqcb->qSize != 0) /* If there are any messages in the queue */
+ {
+ /* Extract oldest message from the queue */
+ pmail = *(pqcb->qStart + pqcb->head);
+ pqcb->head++; /* Update the queue head */
+ pqcb->qSize--; /* Update the number of messages in the queue */
+ if(pqcb->head == pqcb->qMaxSize)
+ {
+ pqcb->head = 0;
+ }
+ OsSchedUnlock();
+ *perr = E_OK;
+ return pmail; /* Return message received */
+ }
+ else /* If there is no message in the queue*/
+ {
+ OsSchedUnlock();
+ *perr = E_QUEUE_EMPTY;
+ return 0; /* Return 0 */
+ }
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Pend for a mail
+ * @param[in] id Event ID.
+ * @param[in] timeout The longest time for writting mail.
+ * @param[out] perr A pointer to error code.
+ * @retval 0
+ * @retval A pointer to mail accept.
+ *
+ * @par Description
+ * @details This function is called to wait for a mail.
+ * @note
+ *******************************************************************************
+ */
+void* CoPendQueueMail(OS_EventID id,U32 timeout,StatusType* perr)
+{
+ P_ECB pecb;
+ P_QCB pqcb;
+ P_OSTCB curTCB;
+ void* pmail;
+ if(OSIntNesting > 0) /* If the caller is ISR */
+ {
+ *perr = E_CALL;
+ return 0;
+ }
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT)
+ {
+ *perr = E_INVALID_ID; /* Invalid event id,return error */
+ return 0;
+ }
+#endif
+
+ pecb = &EventTbl[id];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(pecb->eventType != EVENT_TYPE_QUEUE) /* The event type is not queue */
+ {
+ *perr = E_INVALID_ID;
+ return 0;
+ }
+#endif
+ if(OSSchedLock != 0) /* Judge schedule is locked or not? */
+ {
+ *perr = E_OS_IN_LOCK; /* Schedule is locked,return error */
+ return 0;
+ }
+ pqcb = (P_QCB)pecb->eventPtr; /* Point at queue control block */
+
+ if(pqcb->qSize != 0) /* If there are any messages in the queue */
+ {
+ /* Extract oldest message from the queue */
+ pmail = *(pqcb->qStart + pqcb->head);
+ pqcb->head++; /* Update the queue head */
+ pqcb->qSize--; /* Update the number of messages in the queue */
+ if(pqcb->head == pqcb->qMaxSize)/* Check queue head */
+ {
+ pqcb->head = 0;
+ }
+ *perr = E_OK;
+ return pmail; /* Return message received */
+ }
+ else /* If there is no message in the queue*/
+ {
+ curTCB = TCBRunning;
+ if(timeout == 0) /* If time-out is not configured */
+ {
+ /* Block current task until the event occur */
+ EventTaskToWait(pecb,curTCB);
+
+ /* Have recived message or the queue have been deleted */
+ pmail = curTCB->pmail;
+ curTCB->pmail = 0;
+ *perr = E_OK;
+ return pmail; /* Return message received or 0 */
+ }
+ else /* If time-out is configured */
+ {
+ OsSchedLock();
+
+ /* Block current task until event or timeout occurs */
+ EventTaskToWait(pecb,curTCB);
+ InsertDelayList(curTCB,timeout);
+ OsSchedUnlock();
+ if(curTCB->pmail == 0) /* If time-out occurred */
+ {
+ *perr = E_TIMEOUT;
+ return 0;
+ }
+ else /* If event occured */
+ {
+ pmail = curTCB->pmail;
+ curTCB->pmail = 0;
+ *perr = E_OK;
+ return pmail; /* Return message received or 0 */
+ }
+ }
+ }
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Post a mail to queue
+ * @param[in] id Event ID.
+ * @param[in] pmail Pointer to mail that want to send.
+ * @param[out] None
+ * @retval E_OK
+ * @retval E_INVALID_ID
+ * @retval E_QUEUE_FULL
+ *
+ * @par Description
+ * @details This function is called to post a mail to queue.
+ * @note
+ *******************************************************************************
+ */
+StatusType CoPostQueueMail(OS_EventID id,void* pmail)
+{
+ P_ECB pecb;
+ P_QCB pqcb;
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ pecb = &EventTbl[id];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(pecb->eventType != EVENT_TYPE_QUEUE)
+ {
+ return E_INVALID_ID; /* The event type isn't queue,return */
+ }
+#endif
+ pqcb = (P_QCB)pecb->eventPtr;
+ if(pqcb->qSize == pqcb->qMaxSize) /* If queue is full */
+ {
+ return E_QUEUE_FULL;
+ }
+ else /* If queue is not full */
+ {
+ OsSchedLock();
+ *(pqcb->qStart + pqcb->tail) = pmail; /* Insert message into queue */
+ pqcb->tail++; /* Update queue tail */
+ pqcb->qSize++; /* Update the number of messages in the queue */
+ if(pqcb->tail == pqcb->qMaxSize) /* Check queue tail */
+ {
+ pqcb->tail = 0;
+ }
+ EventTaskToRdy(pecb); /* Check the event waiting list */
+ OsSchedUnlock();
+ return E_OK;
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Post a mail to queue in ISR
+ * @param[in] id Event ID.
+ * @param[in] pmail Pointer to mail that want to send.
+ * @param[out] None
+ * @retval E_OK
+ * @retval E_INVALID_ID
+ * @retval E_QUEUE_FULL
+ *
+ * @par Description
+ * @details This function is called in ISR to post a mail to queue.
+ * @note
+ *******************************************************************************
+ */
+#if CFG_MAX_SERVICE_REQUEST > 0
+StatusType isr_PostQueueMail(OS_EventID id,void* pmail)
+{
+ if(OSSchedLock > 0) /* If scheduler is locked,(the caller is ISR) */
+ {
+ /* Insert the request into service request queue */
+ if(InsertInSRQ(QUEUE_REQ,id,pmail) == FALSE)
+ {
+ return E_SEV_REQ_FULL; /* If service request queue is full */
+ }
+ else /* If the request have been inserted into service request queue */
+ {
+ return E_OK;
+ }
+ }
+ else /* The scheduler is unlocked */
+ {
+ return(CoPostQueueMail(id,pmail)); /* Send the message to the queue*/
+ }
+}
+#endif
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sem.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,319 @@
+/**
+ *******************************************************************************
+ * @file sem.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Semaphore management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+#if CFG_SEM_EN >0
+
+/**
+ *******************************************************************************
+ * @brief Create a semaphore
+ * @param[in] initCnt Semaphore valid counter.
+ * @param[in] maxCnt Semaphore max initialize counter.
+ * @param[in] sortType Semaphore sort type.
+ * @param[out] None
+ * @retval E_CREATE_FAIL Create semaphore fail.
+ * @retval others Create semaphore successful.
+ *
+ * @par Description
+ * @details This function is called to create a semaphore.
+ *******************************************************************************
+ */
+OS_EventID CoCreateSem(U16 initCnt,U16 maxCnt,U8 sortType)
+{
+ P_ECB pecb;
+#if CFG_PAR_CHECKOUT_EN >0
+ if(initCnt > maxCnt)
+ {
+ return E_CREATE_FAIL; /* Invalid 'initCnt' or 'maxCnt' */
+ }
+
+ if ((sortType != EVENT_SORT_TYPE_FIFO) && (sortType != EVENT_SORT_TYPE_PRIO))
+ {
+ return E_CREATE_FAIL; /* Illegal sort type,return error */
+ }
+#endif
+
+ /* Create a semaphore type event control block */
+ pecb = CreatEvent(EVENT_TYPE_SEM,sortType,0);
+ if(pecb == 0) /* If failed to create event block */
+ {
+ return E_CREATE_FAIL;
+ }
+ pecb->eventCounter = initCnt;/* Initialize event block */
+ pecb->initialEventCounter = maxCnt;
+ return (pecb->id); /* Return event id */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Delete a semaphore
+ * @param[in] id Event ID which to be deleted.
+ * @param[in] opt Delete option.
+ * @arg == OPT_DEL_ANYWAY Delete semaphore always
+ * @arg == OPT_DEL_NO_PEND Delete semaphore only when no task pending on.
+ * @param[out] None
+ * @retval E_INVALID_ID Invalid event ID.
+ * @retval E_INVALID_PARAMETER Invalid parameter.
+ * @retval E_TASK_WAITTING Tasks waitting for the event,delete fail.
+ * @retval E_OK Event deleted successful.
+ *
+ * @par Description
+ * @details This function is called to delete a semaphore.
+ *
+ * @note
+ *******************************************************************************
+ */
+StatusType CoDelSem(OS_EventID id,U8 opt)
+{
+ P_ECB pecb;
+
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ pecb = &EventTbl[id];
+
+#if CFG_PAR_CHECKOUT_EN >0
+ if(pecb->eventType != EVENT_TYPE_SEM)
+ {
+ return E_INVALID_ID; /* The event type is not semaphore */
+ }
+#endif
+
+ return (DeleteEvent(pecb,opt));/* Delete the semaphore event control block*/
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Accept a semaphore without waitting
+ * @param[in] id Event ID
+ * @param[out] None
+ * @retval E_INVALID_ID Invalid event ID.
+ * @retval E_SEM_EMPTY No semaphore exist.
+ * @retval E_OK Get semaphore successful.
+ *
+ * @par Description
+ * @details This function is called accept a semaphore without waitting.
+ *******************************************************************************
+ */
+StatusType CoAcceptSem(OS_EventID id)
+{
+ P_ECB pecb;
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ pecb = &EventTbl[id];
+#if CFG_PAR_CHECKOUT_EN >0
+ if( pecb->eventType != EVENT_TYPE_SEM)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ OsSchedLock();
+ if(pecb->eventCounter > 0) /* If semaphore is positive,resource available */
+ {
+ OsSchedUnlock();
+ pecb->eventCounter--; /* Decrement semaphore only if positive */
+ return E_OK;
+ }
+ else /* Resource is not available */
+ {
+ OsSchedUnlock();
+ return E_SEM_EMPTY;
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief wait for a semaphore
+ * @param[in] id Event ID.
+ * @param[in] timeout The longest time for writting semaphore.
+ * @para 0
+ * @para 0x1~0xff
+ * @param[out] None
+ * @retval E_CALL Error call in ISR.
+ * @retval E_INVALID_ID Invalid event ID.
+ * @retval E_TIMEOUT Semaphore was not received within the specified
+ * 'timeout' time.
+ * @retval E_OK The call was successful and your task owns the
+ * resource,or the event you are waiting for occurred.
+ *
+ * @par Description
+ * @details This function is called to waits for a semaphore.
+ * @note IF this function is called in ISR,nothing to do and return immediately.
+ *******************************************************************************
+ */
+StatusType CoPendSem(OS_EventID id,U32 timeout)
+{
+ P_ECB pecb;
+ P_OSTCB curTCB;
+ if(OSIntNesting > 0) /* If the caller is ISR */
+ {
+ return E_CALL;
+ }
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ pecb = &EventTbl[id];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(pecb->eventType != EVENT_TYPE_SEM)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ if(OSSchedLock != 0) /* Schdule is locked? */
+ {
+ return E_OS_IN_LOCK; /* Yes,error return */
+ }
+ if(pecb->eventCounter > 0) /* If semaphore is positive,resource available */
+ {
+ pecb->eventCounter--; /* Decrement semaphore only if positive */
+ return E_OK;
+ }
+ else /* Resource is not available */
+ {
+ curTCB = TCBRunning;
+ if(timeout == 0) /* If time-out is not configured */
+ {
+ EventTaskToWait(pecb,curTCB); /* Block task until event occurs */
+ curTCB->pmail = 0;
+ return E_OK;
+ }
+ else /* If time-out is configured */
+ {
+ OsSchedLock();
+
+ /* Block task until event or timeout occurs */
+ EventTaskToWait(pecb,curTCB);
+ InsertDelayList(curTCB,timeout);
+
+ OsSchedUnlock();
+ if (curTCB->pmail == 0) /* If pmail is 0, time-out occurred*/
+ {
+ return E_TIMEOUT;
+ }
+ else /* Event occurred or event have been deleted*/
+ {
+ curTCB->pmail = 0;
+ return E_OK;
+ }
+ }
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Post a semaphore
+ * @param[in] id id of event control block associated with the desired semaphore.
+ * @param[out] None
+ * @retval E_INVALID_ID Parameter id passed was invalid event ID.
+ * @retval E_SEM_FULL Semaphore full.
+ * @retval E_OK Semaphore had post successful.
+ *
+ * @par Description
+ * @details This function is called to post a semaphore to corresponding event.
+ *
+ * @note
+ *******************************************************************************
+ */
+StatusType CoPostSem(OS_EventID id)
+{
+ P_ECB pecb;
+#if CFG_PAR_CHECKOUT_EN >0
+ if(id >= CFG_MAX_EVENT)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ pecb = &EventTbl[id];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(pecb->eventType != EVENT_TYPE_SEM) /* Invalid event control block type */
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ /* Make sure semaphore will not overflow */
+ if(pecb->eventCounter == pecb->initialEventCounter)
+ {
+ return E_SEM_FULL; /* The counter of Semaphore reach the max number*/
+ }
+ OsSchedLock();
+ pecb->eventCounter++; /* Increment semaphore count to register event */
+ EventTaskToRdy(pecb); /* Check semaphore event waiting list */
+ OsSchedUnlock();
+ return E_OK;
+
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Post a semaphore in ISR
+ * @param[in] id identifier of event control block associated with the
+ * desired semaphore.
+ * @param[out] None
+ * @retval E_INVALID_ID Parameter id passed was invalid event ID.
+ * @retval E_NO_TASK_WAITTING There are one more tasks waitting for the event.
+ * @retval E_OK Semaphore had signaled successful.
+ *
+ * @par Description
+ * @details This function is called in ISR to post a semaphore to corresponding
+ * event.
+ * @note
+ *******************************************************************************
+ */
+#if CFG_MAX_SERVICE_REQUEST > 0
+StatusType isr_PostSem(OS_EventID id)
+{
+ if(OSSchedLock > 0) /* If scheduler is locked,(the caller is ISR) */
+ {
+ /* Initiate a post service handling request */
+ if(InsertInSRQ(SEM_REQ,id,0) == FALSE)
+ {
+ return E_SEV_REQ_FULL; /* If service request queue is full */
+ }
+ else /* Operate successfully */
+ {
+ return E_OK;
+ }
+ }
+ else
+ {
+ return(CoPostSem(id)); /* Post semaphore */
+ }
+}
+#endif
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/serviceReq.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,165 @@
+/**
+ *******************************************************************************
+ * @file serviceReq.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief servive request management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+#if (CFG_TASK_WAITTING_EN > 0) || (CFG_TMR_EN >0)
+
+#if CFG_MAX_SERVICE_REQUEST > 0
+/*---------------------------- Variable Define -------------------------------*/
+SRQ ServiceReq = {0,0}; /*!< ISR server request queue */
+#endif
+BOOL IsrReq = FALSE;
+#if (CFG_TASK_WAITTING_EN > 0)
+BOOL TimeReq = FALSE; /*!< Time delay dispose request */
+#endif
+
+#if CFG_TMR_EN > 0
+BOOL TimerReq = FALSE; /*!< Timer dispose request */
+#endif
+
+/**
+ *******************************************************************************
+ * @brief Insert into service requst queue
+ * @param[in] type Service request type.
+ * @param[in] id Service request event id,event id/flag id.
+ * @param[in] arg Service request argument.
+ * @param[out] None
+ *
+ * @retval FALSE Successfully insert into service request queue.
+ * @retval TRUE Failure to insert into service request queue.
+ *
+ * @par Description
+ * @details This function be called to insert a requst into service request
+ * queue.
+ * @note
+ *******************************************************************************
+ */
+#if (CFG_MAX_SERVICE_REQUEST > 0)
+BOOL InsertInSRQ(U8 type,U8 id,void* arg)
+{
+ P_SQC pcell;
+ U8 cnt;
+ U8 heed;
+ IRQ_DISABLE_SAVE();
+ if (ServiceReq.cnt >= CFG_MAX_SERVICE_REQUEST)
+ {
+ IRQ_ENABLE_RESTORE ();
+
+ return FALSE; /* Error return */
+ }
+ cnt = Inc8(&ServiceReq.cnt);
+ heed = ServiceReq.head;
+ IsrReq = TRUE;
+ pcell = &ServiceReq.cell[((cnt+heed)%CFG_MAX_SERVICE_REQUEST)];/*the tail */
+ pcell->type = type; /* Save service request type, */
+ pcell->id = id; /* event id */
+ pcell->arg = arg; /* and parameter */
+ IRQ_ENABLE_RESTORE ();
+
+ return TRUE; /* Return OK */
+}
+#endif
+
+
+
+/**
+ *******************************************************************************
+ * @brief Respond the request in the service request queue.
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function be called to respond the request in the service
+ * request queue.
+ * @note
+ *******************************************************************************
+ */
+void RespondSRQ(void)
+{
+
+#if CFG_MAX_SERVICE_REQUEST > 0
+ SQC cell;
+
+#endif
+
+#if (CFG_TASK_WAITTING_EN > 0)
+ if(TimeReq == TRUE) /* Time delay request? */
+ {
+ TimeDispose(); /* Yes,call handler */
+ TimeReq = FALSE; /* Reset time delay request false */
+ }
+#endif
+#if CFG_TMR_EN > 0
+ if(TimerReq == TRUE) /* Timer request? */
+ {
+ TmrDispose(); /* Yes,call handler */
+ TimerReq = FALSE; /* Reset timer request false */
+ }
+#endif
+
+#if CFG_MAX_SERVICE_REQUEST > 0
+
+ while (ServiceReq.cnt != 0)
+ {
+ IRQ_DISABLE_SAVE (); /* need to protect the following */
+ cell = ServiceReq.cell[ServiceReq.head]; /* extract one cell */
+ ServiceReq.head = (ServiceReq.head + 1) % /* move head (pop) */
+ CFG_MAX_SERVICE_REQUEST;
+ ServiceReq.cnt--;
+ IRQ_ENABLE_RESTORE (); /* now use the cell copy */
+
+ switch(cell.type) /* Judge service request type */
+ {
+#if CFG_SEM_EN > 0
+ case SEM_REQ: /* Semaphore post request,call handler*/
+ CoPostSem(cell.id);
+ break;
+#endif
+#if CFG_MAILBOX_EN > 0
+ case MBOX_REQ: /* Mailbox post request,call handler */
+ CoPostMail(cell.id, cell.arg);
+ break;
+#endif
+#if CFG_FLAG_EN > 0
+ case FLAG_REQ: /* Flag set request,call handler */
+ CoSetFlag(cell.id);
+ break;
+#endif
+#if CFG_QUEUE_EN > 0
+ case QUEUE_REQ: /* Queue post request,call handler */
+ CoPostQueueMail(cell.id, cell.arg);
+ break;
+#endif
+ default: /* Others,break */
+ break;
+ }
+ }
+#endif
+ IRQ_DISABLE_SAVE (); /* need to protect the following */
+
+ if (ServiceReq.cnt == 0) /* another item in the queue already? */
+ {
+ IsrReq = FALSE; /* queue still empty here */
+ }
+ IRQ_ENABLE_RESTORE (); /* now it is done and return */
+}
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/task.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,1260 @@
+/**
+ *******************************************************************************
+ * @file task.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief task management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+/*---------------------------- Variable Define -------------------------------*/
+
+/*!< Table use to save TCB pointer. */
+OSTCB TCBTbl[CFG_MAX_USER_TASKS+SYS_TASK_NUM] = {{0}};
+
+/*!< The stack of IDLE task. */
+OS_STK idle_stk[CFG_IDLE_STACK_SIZE] = {0};
+
+P_OSTCB FreeTCB = 0; /*!< pointer to free TCB */
+P_OSTCB TCBRdy = 0; /*!< Pointer to the READY list. */
+P_OSTCB TCBNext = 0; /*!< Poniter to task that next scheduled by OS */
+P_OSTCB TCBRunning = 0; /*!< Pointer to TCB that current running task. */
+U64 OSCheckTime = 0; /*!< The counter of system tick. */
+
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+OS_TID PriNum;
+U8 ActivePri[CFG_MAX_USER_TASKS+SYS_TASK_NUM];
+U8 TaskNumPerPri[CFG_MAX_USER_TASKS+SYS_TASK_NUM];
+OS_TID RdyTaskPri[CFG_MAX_USER_TASKS+SYS_TASK_NUM] = {0};
+U32 RdyTaskPriInfo[(CFG_MAX_USER_TASKS+SYS_TASK_NUM+31)/32];
+#endif
+
+
+/**
+ *******************************************************************************
+ * @brief Create a TCB list.
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called by CoOSInit() to initial the empty list
+ * of OS_TCBS,supply a pointer to free TCB.
+ *******************************************************************************
+ */
+void CreateTCBList(void)
+{
+ U8 i;
+ P_OSTCB ptcb1,ptcb2;
+
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ PriNum = 0;
+#endif
+
+ ptcb1 = &TCBTbl[0]; /* Build the free TCB list */
+ ptcb2 = &TCBTbl[1];
+ for(i=0;i< (CFG_MAX_USER_TASKS+SYS_TASK_NUM-1);i++ )
+ {
+ ptcb1->taskID = i;
+ ptcb1->state = TASK_DORMANT;
+ ptcb1->TCBnext = ptcb2;
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ RdyTaskPri[i] = INVALID_ID;
+ ActivePri[i] = INVALID_ID;
+#endif
+ ptcb1++;
+ ptcb2++;
+ }
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ ActivePri[i] = INVALID_ID;
+#endif
+
+ ptcb1->taskID = i;
+ ptcb1->TCBnext = 0;
+ FreeTCB = &TCBTbl[0]; /* Initialize FreeTCB as head item of list */
+}
+
+
+
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+
+/**
+ *******************************************************************************
+ * @brief Get sequence number for Assign priority
+ * @param[in] pri Assign priority
+ * @param[out] SequenceNum priority number
+ * @retval TRUE Assign priority in priority queue.
+ * FALSE Assign priority not in priority queue.
+ *
+ * @par Description
+ * @details This function is called in Binary-Scheduling Algorithm
+ * to get sequence number for Assign priority.
+ *******************************************************************************
+ */
+static BOOL GetPriSeqNum(U8 pri,OS_TID* SequenceNum)
+{
+ OS_TID seqNum;
+ OS_TID num,tmpNum;
+ num = 0;
+ seqNum = PriNum;
+ while(num != seqNum)
+ {
+ tmpNum = num;
+ num = (num+seqNum)/2;
+ if(pri == ActivePri[num])
+ {
+ *SequenceNum = num;
+ return TRUE;
+ }
+ else if (pri < ActivePri[num])
+ {
+ seqNum = num;
+ num = tmpNum;
+ }
+ else
+ {
+ num++;
+ }
+ }
+ *SequenceNum = num;
+ return FALSE;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Get the nearest ready priority sequence number for Assign number
+ * @param[in] seqNum Assign sequence number
+ * @param[out] None
+ * @retval INVALID_ID Cannot find higher ready priority.
+ * Others Nearest ready priority sequence number
+ *
+ * @par Description
+ * @details This function is called in Binary-Scheduling Algorithm
+ * to get the nearest ready priority sequence number.
+ *******************************************************************************
+ */
+static U8 GetRdyPriSeqNum(U8 seqNum)
+{
+ U32 tmp;
+ U8 i,j,num;
+ S8 cnt;
+ i = seqNum/32;
+ j = seqNum%32;
+
+ do
+ {
+ tmp = RdyTaskPriInfo[i];
+ if(tmp != 0)
+ {
+ num = j/8;
+ do
+ {
+ if((tmp&(0xff<<(num*8))) !=0 )
+ {
+ if((tmp&(0xf0<<(num*8))) !=0)
+ {
+ for(cnt=j; cnt >=(num*8+4); cnt--)
+ {
+ if( (tmp&(1<<cnt)) !=0)
+ {
+ return (32*i+cnt);
+ }
+ }
+ }
+
+ if((j&0x4)==4)
+ j = (j|0x3) -4;
+
+ for(cnt=j; cnt >=num*8; cnt--)
+ {
+ if( (tmp&(1<<cnt)) !=0)
+ {
+ return (32*i+cnt);
+ }
+ }
+ }
+ j = num*8 -1;
+ }while((num--)!=0);
+ }
+ j=31;
+ }while((i--)!=0);
+ return INVALID_ID;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Remap the ready status of priority queue from Assign sequence number
+ * @param[in] seqNum Assign sequence number
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called in Binary-Scheduling Algorithm
+ * to Remap the ready status for priority queue.
+ *******************************************************************************
+ */
+static void PrioRemap(OS_TID seqNum)
+{
+ U8 i,j;
+ U32 tmp;
+ tmp = j = 0;
+ j = seqNum/32;
+ for(i=0;i<seqNum%32;i++)
+ {
+ tmp |= 1<<i;
+ }
+ tmp &= RdyTaskPriInfo[j];
+
+ for(i=seqNum; i<PriNum; i++)
+ {
+ if((i%32==0)&&(i!=seqNum))
+ {
+ RdyTaskPriInfo[j++] = tmp;
+ tmp = 0;
+ }
+ if(RdyTaskPri[i] != INVALID_ID)
+ {
+ tmp = tmp | (1<<(i%32));
+ }
+ }
+ RdyTaskPriInfo[j++] = tmp;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Get the ready status for assign sequence number
+ * @param[in] seqNum Assign sequence number
+ * @param[out] None
+ * @retval TRUE This priority has ready task
+ * FALSE This priority doesn't have ready task
+ *
+ * @par Description
+ * @details This function is called in Binary-Scheduling Algorithm
+ * to get the ready status for assign sequence number.
+ *******************************************************************************
+ */
+static BOOL GetPrioSeqNumStatus(U8 seqNum)
+{
+ if( (RdyTaskPriInfo[seqNum/32] & (1<<(seqNum%32))) == 0)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Set the ready status for assign sequence number
+ * @param[in] seqNum Assign sequence number
+ * @param[in] isRdy Ready statues for assign sequence number
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called in Binary-Scheduling Algorithm
+ * to set the ready status for assign sequence number.
+ *******************************************************************************
+ */
+static void SetPrioSeqNumStatus(U8 seqNum, BOOL isRdy)
+{
+ U32 tmp;
+ tmp = RdyTaskPriInfo[seqNum/32];
+ tmp &= ~(1<<(seqNum%32));
+ tmp |= isRdy<<(seqNum%32);
+ RdyTaskPriInfo[seqNum/32] = tmp;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Active priority in queue
+ * @param[in] pri Task priority
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called in Binary-Scheduling Algorithm
+ * to active priority in queue, if this priority had been in activation,
+ * increate the task num for this priority.
+ *******************************************************************************
+ */
+void ActiveTaskPri(U8 pri)
+{
+ OS_TID seqNum,num;
+ if(GetPriSeqNum(pri,&seqNum) == FALSE)
+ {
+ for(num=PriNum;num>seqNum;num--)
+ {
+ ActivePri[num] = ActivePri[num-1];
+ TaskNumPerPri[num] = TaskNumPerPri[num-1];
+ RdyTaskPri[num] = RdyTaskPri[num-1];
+ }
+ ActivePri[seqNum] = pri;
+ TaskNumPerPri[seqNum] = 1;
+ RdyTaskPri[seqNum] = INVALID_ID;
+ PriNum++;
+ PrioRemap(seqNum);
+ }
+ else
+ {
+ TaskNumPerPri[seqNum]++;
+ }
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Delete priority in queue
+ * @param[in] pri Task priority
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called in Binary-Scheduling Algorithm
+ * to decrease the task num for this priority, if the num goto 0,
+ * remove the priority for queue.
+ *******************************************************************************
+ */
+void DeleteTaskPri(U8 pri)
+{
+ OS_TID seqNum,num;
+
+ GetPriSeqNum(pri,&seqNum);
+ TaskNumPerPri[seqNum]--;
+ if(TaskNumPerPri[seqNum]==0)
+ {
+ for(num=seqNum; num<(PriNum-1); num++)
+ {
+ ActivePri[num] = ActivePri[num+1];
+ TaskNumPerPri[num] = TaskNumPerPri[num+1];
+ RdyTaskPri[num] = RdyTaskPri[num+1];
+ }
+ PriNum--;
+ PrioRemap(seqNum);
+ }
+}
+
+#endif
+
+
+/**
+ *******************************************************************************
+ * @brief Insert a task to the ready list
+ * @param[in] tcbInsert A pointer to task will be inserted.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to insert a task to the READY list.
+ *******************************************************************************
+ */
+void InsertToTCBRdyList(P_OSTCB tcbInsert)
+{
+ P_OSTCB ptcbNext,ptcb;
+ U8 prio;
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ U8 seqNum;
+ U8 RdyTaskSeqNum;
+#endif
+
+ prio = tcbInsert->prio; /* Get PRI of inserted task */
+ tcbInsert->state = TASK_READY; /* Set task as TASK_READY */
+
+#if CFG_ROBIN_EN >0
+ ptcb = TCBRunning;
+ /* Set schedule time for the same PRI task as TCBRunning. */
+ if(prio == ptcb->prio) /* Is PRI of inserted task equal to running task? */
+ {
+ if(ptcb != tcbInsert) /* Yes,is inserted task equal to running task? */
+ {
+ if(ptcb != 0) /* No,TCBRunning == 0? */
+ { /* N0,OSCheckTime < OSTickCnt? */
+ if(OSCheckTime < OSTickCnt)
+ { /* Yes,set OSCheckTime for task robin */
+ OSCheckTime = OSTickCnt + ptcb->timeSlice;
+ }
+ }
+ }
+ }
+#endif
+
+
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ GetPriSeqNum(prio,&seqNum);
+ if(GetPrioSeqNumStatus(seqNum) == TRUE)
+ {
+ ptcb = &TCBTbl[RdyTaskPri[seqNum]];
+ RdyTaskPri[seqNum] = tcbInsert->taskID;
+ }
+ else
+ {
+ RdyTaskPri[seqNum] = tcbInsert->taskID;
+ RdyTaskSeqNum = GetRdyPriSeqNum(seqNum);
+ SetPrioSeqNumStatus(seqNum, 1);
+ if(RdyTaskSeqNum == INVALID_ID)
+ {
+ ptcb = TCBRdy;
+ TaskSchedReq = TRUE;
+ if(ptcb == 0)
+ {
+ TCBRdy = tcbInsert;
+ }
+ else
+ {
+ tcbInsert->TCBnext = ptcb; /* Yes,set tcbInsert as head item of list */
+ ptcb->TCBprev = tcbInsert;
+ TCBRdy = tcbInsert;
+ }
+ return;
+ }
+ else
+ {
+ ptcb = &TCBTbl[RdyTaskPri[RdyTaskSeqNum]];
+ }
+ }
+
+ ptcbNext = ptcb->TCBnext;
+ tcbInsert->TCBnext = ptcbNext; /* Set link for list */
+ ptcb->TCBnext = tcbInsert;
+ tcbInsert->TCBprev = ptcb;
+ if(ptcbNext != 0)
+ {
+ ptcbNext->TCBprev = tcbInsert;
+ }
+
+
+#else
+ ptcb = TCBRdy;
+ if (ptcb == 0) /* Is ready list 0? */
+ {
+ TaskSchedReq = TRUE;
+ TCBRdy = tcbInsert; /* Yse,set tcbInsert as head item of list */
+ }
+ else if (prio < ptcb->prio)/* Is PRI of inserted task higher than TCBRdy? */
+ {
+ TaskSchedReq = TRUE;
+ tcbInsert->TCBnext = ptcb; /* Yes,set tcbInsert as head item of list */
+ ptcb->TCBprev = tcbInsert;
+ TCBRdy = tcbInsert;
+ }
+ else /* No,find correct place */
+ {
+ ptcbNext = ptcb->TCBnext; /* Get next item */
+ while(ptcbNext != 0) /* Is last item in ready list? */
+ { /* No,find correct place */
+ if(prio < ptcbNext->prio) /* Is correct place? */
+ break; /* Yes,break circulation */
+ ptcb = ptcbNext; /* Save current item */
+ ptcbNext = ptcbNext->TCBnext; /* Get next item */
+ }
+ tcbInsert->TCBnext = ptcbNext; /* Set link for list */
+ ptcb->TCBnext = tcbInsert;
+ tcbInsert->TCBprev = ptcb;
+ if(ptcbNext != 0)
+ {
+ ptcbNext->TCBprev = tcbInsert;
+ }
+ }
+#endif
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Remove a task from the READY list
+ * @param[in] ptcb A pointer to task which be removed.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to remove a task from the READY list.
+ *******************************************************************************
+ */
+void RemoveFromTCBRdyList(P_OSTCB ptcb)
+{
+
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ U8 prio;
+ U8 seqNum;
+ BOOL isChange;
+ isChange = FALSE;
+ prio = ptcb->prio;
+ GetPriSeqNum(prio,&seqNum);
+#endif
+
+ /* Is there only one item in READY list? */
+ if((ptcb->TCBnext == 0) && (ptcb->TCBprev == 0) )
+ {
+ TCBRdy = 0; /* Yes,set READY list as 0 */
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ isChange = TRUE;
+#endif
+ }
+ else if(ptcb->TCBprev == 0) /* Is the first item in READY list? */
+ {
+ /* Yes,remove task from the list,and reset the head of READY list */
+ TCBRdy = ptcb->TCBnext;
+ ptcb->TCBnext = 0;
+ TCBRdy->TCBprev = 0;
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ if(TCBRdy->prio != prio)
+ isChange = TRUE;
+
+#endif
+ }
+ else if( ptcb->TCBnext == 0) /* Is the last item in READY list? */
+ { /* Yes,remove task from list */
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ if(ptcb->TCBprev->prio != prio)
+ isChange = TRUE;
+ else
+ RdyTaskPri[seqNum] = ptcb->TCBprev->taskID;
+#endif
+ ptcb->TCBprev->TCBnext = 0;
+ ptcb->TCBprev = 0;
+ }
+ else /* No, remove task from list */
+ {
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ if((ptcb->TCBprev->prio != prio) && (ptcb->TCBnext->prio != prio))
+ isChange = TRUE;
+ else if((ptcb->TCBprev->prio == prio) && (ptcb->TCBnext->prio != prio))
+ RdyTaskPri[seqNum] = ptcb->TCBprev->taskID;
+#endif
+ ptcb->TCBprev->TCBnext = ptcb->TCBnext;
+ ptcb->TCBnext->TCBprev = ptcb->TCBprev;
+ ptcb->TCBnext = 0;
+ ptcb->TCBprev = 0;
+ }
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ if(isChange == TRUE)
+ {
+ RdyTaskPri[seqNum] = INVALID_ID;
+ SetPrioSeqNumStatus(seqNum, 0);
+ }
+#endif
+}
+
+
+#if CFG_MUTEX_EN > 0
+#define CFG_PRIORITY_SET_EN (1)
+#endif
+#if CFG_PRIORITY_SET_EN >0
+/**
+ *******************************************************************************
+ * @brief Change task priority
+ * @param[in] taskID Specify task id.
+ * @param[in] priority New priority.
+ * @param[out] None
+ * @retval E_OK Change priority successful.
+ * @retval E_INVALID_ID Invalid id,change priority fail.
+ * @retval E_PROTECTED_TASK Can't change idle task priority.
+ *
+ * @par Description
+ * @details This function is called to change priority for a specify task.
+ *******************************************************************************
+ */
+StatusType CoSetPriority(OS_TID taskID,U8 priority)
+{
+ P_OSTCB ptcb;
+#if CFG_MUTEX_EN >0
+ U8 prio;
+ P_MUTEX pMutex;
+#endif
+#if CFG_EVENT_EN >0
+ P_ECB pecb;
+#endif
+
+ if(taskID == 0) /* Is idle task? */
+ {
+ return E_PROTECTED_TASK; /* Yes,error return */
+ }
+
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ ptcb = &TCBTbl[taskID]; /* Get TCB of task ID */
+#if CFG_PAR_CHECKOUT_EN >0
+ if(ptcb->state == TASK_DORMANT)
+ {
+ return E_INVALID_ID;
+ }
+ if(priority > CFG_LOWEST_PRIO)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ if(ptcb->prio != priority) /* Is PRI equal to original PRI? */
+ { /* No */
+#if CFG_MUTEX_EN >0
+ if(ptcb->mutexID != INVALID_ID)
+ {
+ pMutex = &MutexTbl[ptcb->mutexID];
+ if(pMutex->taskID == ptcb->taskID) /* Task hold mutex? */
+ {
+ pMutex->originalPrio= priority;/* Yes,change original PRI in mutex*/
+ if(ptcb->prio < priority) /* Is task priority higher than set?*/
+ {
+ return E_OK; /* Yes,do nothing,return OK */
+ }
+ }
+ }
+
+#endif
+
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ DeleteTaskPri(ptcb->prio);
+ ActiveTaskPri(priority);
+#endif
+
+ ptcb->prio = priority; /* Change task PRI */
+ if(ptcb->state == TASK_READY) /* Is task in READY list? */
+ {
+ OsSchedLock(); /* Yes,reorder task in READY list */
+ RemoveFromTCBRdyList(ptcb);
+ InsertToTCBRdyList(ptcb);
+ OsSchedUnlock();
+ }
+ else if(ptcb->state == TASK_RUNNING)/* Is task running? */
+ {
+ if(ptcb->prio > TCBRdy->prio) /* Yes,Is PRI higher than TCBRdy? */
+ {
+ OsSchedLock(); /* Yes,reorder task in READY list */
+ TaskSchedReq = TRUE;
+ OsSchedUnlock();
+ }
+ }
+ else
+ { /* No,task in WAITING list */
+#if CFG_MUTEX_EN >0
+ if(ptcb->mutexID != INVALID_ID) /* Is task in mutex WAITING list? */
+ {
+ /* Yes,reset the highest PRI in the list */
+ OsSchedLock();
+ pMutex = &MutexTbl[ptcb->mutexID];
+ ptcb = pMutex->waittingList;
+ prio = pMutex->originalPrio;
+ pMutex->hipriTaskID = pMutex->taskID;
+ while(ptcb != 0)
+ {
+ if(ptcb->prio < prio)
+ {
+ prio = ptcb->prio;
+ pMutex->hipriTaskID = ptcb->taskID;
+ }
+ ptcb = ptcb->TCBnext;
+ }
+ OsSchedUnlock();
+ if(pMutex->originalPrio != prio)
+ {
+ CoSetPriority(pMutex->taskID,prio);
+ }
+ }
+#endif
+
+#if CFG_EVENT_EN >0
+ ptcb = &TCBTbl[taskID];
+ if(ptcb->eventID != INVALID_ID) /* Is task in event WAITING list? */
+ {
+ pecb = &EventTbl[ptcb->eventID];
+
+ /* Yes,is event sort type as preemptive PRI? */
+ if(pecb->eventSortType == EVENT_SORT_TYPE_PRIO)
+ {
+ /* Yes,reorder task in the list */
+ RemoveEventWaittingList(ptcb);
+ EventTaskToWait(pecb,ptcb);
+ }
+ }
+#endif
+ }
+ }
+ return E_OK;
+}
+#endif
+
+/**
+ *******************************************************************************
+ * @brief Schedule function
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called by every where need to switch context,
+ * It is schedule function of OS kernel.
+ *******************************************************************************
+ */
+void Schedule(void)
+{
+ U8 RunPrio,RdyPrio;
+ P_OSTCB pRdyTcb,pCurTcb;
+
+
+ pCurTcb = TCBRunning;
+ pRdyTcb = TCBRdy;
+
+ if((pRdyTcb==0) || (pCurTcb != TCBNext) || (OSSchedLock >1) || (OSIntNesting >0))
+ {
+ return;
+ }
+
+ TaskSchedReq = FALSE;
+ RunPrio = pCurTcb->prio;
+ RdyPrio = pRdyTcb->prio;
+
+ /* Is Running task status was changed? */
+ if(pCurTcb->state != TASK_RUNNING)
+ {
+ TCBNext = pRdyTcb; /* Yes,set TCBNext and reorder READY list */
+ pRdyTcb->state = TASK_RUNNING;
+ RemoveFromTCBRdyList(pRdyTcb);
+ }
+
+ else if(RdyPrio < RunPrio ) /* Is higher PRI task coming in? */
+ {
+ TCBNext = pRdyTcb; /* Yes,set TCBNext and reorder READY list */
+ InsertToTCBRdyList(pCurTcb);
+ RemoveFromTCBRdyList(pRdyTcb);
+ pRdyTcb->state = TASK_RUNNING;
+ }
+
+#if CFG_ROBIN_EN >0 /* Is time for robinning */
+ else if((RunPrio == RdyPrio) && (OSCheckTime == OSTickCnt))
+ {
+ TCBNext = pRdyTcb; /* Yes,set TCBNext and reorder READY list */
+ InsertToTCBRdyList(pCurTcb);
+ RemoveFromTCBRdyList(pRdyTcb);
+ pRdyTcb->state = TASK_RUNNING;
+ }
+#endif
+ else
+ {
+ return;
+ }
+
+#if CFG_ROBIN_EN >0
+ if(TCBNext->prio == TCBRdy->prio) /* Reset OSCheckTime for task robinnig */
+ OSCheckTime = OSTickCnt + TCBNext->timeSlice;
+#endif
+
+
+#if CFG_STK_CHECKOUT_EN > 0 /* Is stack overflow? */
+ if((pCurTcb->stkPtr < pCurTcb->stack)||(*(U32*)(pCurTcb->stack) != MAGIC_WORD))
+ {
+ CoStkOverflowHook(pCurTcb->taskID); /* Yes,call handler */
+ }
+#endif
+
+ SwitchContext(); /* Call task context switch */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Assign a TCB to task being created
+ * @param[in] None
+ * @param[out] None
+ *
+ * @retval XXXX
+ *
+ * @par Description
+ * @details This function is called to assign a task control block for task
+ * being created.
+ *******************************************************************************
+ */
+static P_OSTCB AssignTCB(void)
+{
+ P_OSTCB ptcb;
+
+ OsSchedLock(); /* Lock schedule */
+ if(FreeTCB == 0) /* Is there no free TCB */
+ {
+ OsSchedUnlock(); /* Yes,unlock schedule */
+ return 0; /* Error return */
+ }
+ ptcb = FreeTCB; /* Yes,assgin free TCB for this task */
+ /* Set next item as the head of free TCB list */
+ FreeTCB = FreeTCB->TCBnext;
+ OsSchedUnlock();
+ return ptcb;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Create a task
+ * @param[in] task Task code entry.
+ * @param[in] argv The parameter passed to task.
+ * @param[in] parameter Task priority + stack size + time slice + isWaitting.
+ * @param[in] stk Pointer to stack top of task.
+ * @param[out] None
+ * @retval E_CREATE_FAIL Fail to create a task .
+ * @retval others Valid task id.
+ *
+ * @par Description
+ * @details This function is called by application to create a task,return a id
+ * to mark this task.
+ *******************************************************************************
+ */
+OS_TID CreateTask(FUNCPtr task,void *argv,U32 parameter,OS_STK *stk)
+{
+ OS_STK* stkTopPtr;
+ P_OSTCB ptcb;
+ U8 prio;
+#if CFG_ROBIN_EN >0
+ U16 timeSlice;
+#endif
+
+#if CFG_STK_CHECKOUT_EN >0 /* Check validity of parameter */
+ U16 sktSz;
+ sktSz = (parameter&0xfff00)>>8;
+#endif
+ prio = parameter&0xff;
+
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(task == 0)
+ {
+ return E_CREATE_FAIL;
+ }
+ if(stk == 0)
+ {
+ return E_CREATE_FAIL;
+ }
+ if(prio > CFG_LOWEST_PRIO)
+ {
+ return E_CREATE_FAIL;
+ }
+#if CFG_STK_CHECKOUT_EN >0
+ if(sktSz < 20)
+ {
+ return E_CREATE_FAIL;
+ }
+#endif // CFG_STK_CHECKOUT_EN
+#endif // CFG_PAR_CHECKOUT_EN
+
+#if CFG_TASK_SCHEDULE_EN == 0
+ if(TCBRunning != 0)
+ return E_CREATE_FAIL;
+#endif
+
+ stkTopPtr = InitTaskContext(task,argv,stk); /* Initialize task context. */
+
+ ptcb = AssignTCB(); /* Get free TCB to use */
+
+ if(ptcb == 0) /* Is free TCB equal to 0? */
+ {
+ return E_CREATE_FAIL; /* Yes,error return */
+ }
+
+ ptcb->stkPtr = stkTopPtr; /* Initialize TCB as user set */
+ ptcb->prio = prio;
+#if CFG_STK_CHECKOUT_EN >0
+ ptcb->stack = stk+1 - sktSz; /* Set bottom stack for stack overflow check */
+ *(U32*)(ptcb->stack) = MAGIC_WORD;
+#endif
+
+#if CFG_TASK_WAITTING_EN >0
+ ptcb->delayTick = INVALID_VALUE;
+#endif
+
+#if CFG_TASK_SCHEDULE_EN == 0
+ ptcb->taskFuc = task;
+ ptcb->taskStk = stk;
+#endif
+ ptcb->TCBnext = 0; /* Initialize TCB link in READY list */
+ ptcb->TCBprev = 0;
+
+#if CFG_ROBIN_EN >0 /* Set task time slice for task robin */
+ timeSlice = (parameter&0x7fff0000)>>20;
+ if(timeSlice == 0)
+ {
+ timeSlice = CFG_TIME_SLICE;
+ }
+ ptcb->timeSlice = timeSlice;
+#endif
+
+#if CFG_FLAG_EN > 0
+ ptcb->pnode = 0; /* Initialize task as no flag waiting */
+#endif
+
+#if CFG_EVENT_EN > 0
+ ptcb->eventID = INVALID_ID; /* Initialize task as no event waiting*/
+ ptcb->pmail = 0;
+ ptcb->waitNext = 0;
+ ptcb->waitPrev = 0;
+#endif
+
+#if CFG_MUTEX_EN > 0
+ /* Initialize task as no mutex holding or waiting */
+ ptcb->mutexID = INVALID_ID;
+#endif
+
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ ActiveTaskPri(prio);
+#endif
+
+ if((parameter>>31) == 0) /* Is task in waitting state? */
+ { /* No,set it into ready list */
+ OsSchedLock(); /* Lock schedule */
+ InsertToTCBRdyList(ptcb); /* Insert into the READY list */
+ OsSchedUnlock(); /* Unlock schedule */
+ }
+ else
+ { /* Yes,Set task status as TASK_WAITING*/
+ ptcb->state = TASK_WAITING;
+ }
+ return ptcb->taskID; /* Return task ID */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Delete Task
+ * @param[in] taskID Task ID
+ * @param[out] None
+ * @retval E_INVALID_ID Invalid task ID.
+ * @retval E_PROTECTED_TASK Protected task in OS.
+ * @retval E_OK Delete successful.
+ *
+ * @par Description
+ * @details This function is called to delete assign task.
+ *******************************************************************************
+ */
+StatusType CoDelTask(OS_TID taskID)
+{
+ P_OSTCB ptcb;
+
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ ptcb = &TCBTbl[taskID];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(ptcb->state == TASK_DORMANT)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ if(taskID == 0) /* Is idle task? */
+ {
+ return E_PROTECTED_TASK; /* Yes,error return */
+ }
+
+ if(ptcb->state == TASK_RUNNING) /* Is task running? */
+ {
+ if(OSSchedLock != 0) /* Yes,is OS lock? */
+ {
+ return E_OS_IN_LOCK; /* Yes,error return */
+ }
+ }
+
+#if CFG_MUTEX_EN >0 /* Do task hold mutex? */
+ if(ptcb->mutexID != INVALID_ID)
+ {
+ if(MutexTbl[ptcb->mutexID].taskID == ptcb->taskID)
+ { /* Yes,leave the mutex */
+ CoLeaveMutexSection(ptcb->mutexID);
+ }
+ }
+
+#endif
+
+ OsSchedLock(); /* Lock schedule */
+
+ if(ptcb->state == TASK_READY) /* Is task in READY list? */
+ {
+ RemoveFromTCBRdyList(ptcb); /* Yes,remove task from the READY list*/
+ }
+
+#if CFG_TASK_WAITTING_EN > 0
+ else if(ptcb->state == TASK_WAITING)/* Is task in the WAITING list? */
+ {
+ /* Yes,Is task in delay list? */
+ if(ptcb->delayTick != INVALID_VALUE)
+ {
+ RemoveDelayList(ptcb); /* Yes,remove task from READY list */
+ }
+
+#if CFG_EVENT_EN > 0
+ if(ptcb->eventID != INVALID_ID) /* Is task in event waiting list? */
+ {
+ /* Yes,remove task from event waiting list */
+ RemoveEventWaittingList(ptcb);
+ }
+#endif
+
+#if CFG_FLAG_EN > 0
+ if(ptcb->pnode != 0) /* Is task in flag waiting list? */
+ {
+ /* Yes,remove task from flag waiting list */
+ RemoveLinkNode((P_FLAG_NODE)ptcb->pnode);
+ }
+#endif
+
+#if CFG_MUTEX_EN >0
+ if(ptcb->mutexID != INVALID_ID) /* Is task in mutex waiting list? */
+ {
+ RemoveMutexList(ptcb); /* Yes,remove task from mutex waiting list*/
+ }
+#endif
+ }
+#endif
+ ptcb->state = TASK_DORMANT; /* Release TCB */
+ TaskSchedReq = TRUE;
+
+#if CFG_ORDER_LIST_SCHEDULE_EN ==0
+ DeleteTaskPri(ptcb->prio);
+#endif
+
+#if CFG_TASK_SCHEDULE_EN >0
+ ptcb->TCBnext = FreeTCB;
+ FreeTCB = ptcb;
+#endif
+ OsSchedUnlock(); /* Unlock schedule */
+ return E_OK; /* return OK */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Exit Task
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to exit current task.
+ *******************************************************************************
+ */
+void CoExitTask(void)
+{
+ CoDelTask(TCBRunning->taskID); /* Call task delete function */
+}
+
+
+#if CFG_TASK_SCHEDULE_EN ==0
+/**
+ *******************************************************************************
+ * @brief Activate Task
+ * @param[in] taskID Task ID
+ * @param[in] argv Task argv
+ * @param[out] None
+ * @retval E_INVALID_ID Invalid task ID.
+ * @retval E_OK Activate task successful.
+ *
+ * @par Description
+ * @details This function is called to activate current task.
+ *******************************************************************************
+ */
+StatusType CoActivateTask(OS_TID taskID,void *argv)
+{
+ P_OSTCB ptcb;
+ OS_STK* stkTopPtr;
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ ptcb = &TCBTbl[taskID];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(ptcb->stkPtr == 0)
+ return E_INVALID_ID;
+#endif
+ if(ptcb->state != TASK_DORMANT)
+ return E_OK;
+
+
+ /* Initialize task context. */
+ stkTopPtr = InitTaskContext(ptcb->taskFuc,argv,ptcb->taskStk);
+
+ ptcb->stkPtr = stkTopPtr; /* Initialize TCB as user set */
+ OsSchedLock(); /* Lock schedule */
+ InsertToTCBRdyList(ptcb); /* Insert into the READY list */
+ OsSchedUnlock(); /* Unlock schedule */
+ return E_OK;
+}
+#endif
+
+
+/**
+ *******************************************************************************
+ * @brief Get current task id
+ * @param[in] None
+ * @param[out] None
+ * @retval ID of the current task.
+ *
+ * @par Description
+ * @details This function is called to get current task id.
+ *******************************************************************************
+ */
+OS_TID CoGetCurTaskID(void)
+{
+ return (TCBRunning->taskID); /* Return running task ID */
+}
+
+#if CFG_TASK_SUSPEND_EN >0
+/**
+ *******************************************************************************
+ * @brief Suspend Task
+ * @param[in] taskID ID of task that want to suspend.
+ * @param[out] None
+ * @retval E_OK Task suspend successful.
+ * @retval E_INVALID_ID Invalid event ID.
+ * @retval E_PROTECTED_TASK Can't suspend idle task.
+ * @retval E_ALREADY_IN_WAITING Task now in waiting state.
+
+ *
+ * @par Description
+ * @details This function is called to exit current task.
+ *******************************************************************************
+ */
+StatusType CoSuspendTask(OS_TID taskID)
+{
+ P_OSTCB ptcb;
+
+ if(taskID == 0) /* Is idle task? */
+ {
+ return E_PROTECTED_TASK; /* Yes,error return */
+ }
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ ptcb = &TCBTbl[taskID];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(ptcb->state == TASK_DORMANT)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ if(OSSchedLock != 0)
+ {
+ return E_OS_IN_LOCK;
+ }
+ if(ptcb->state == TASK_WAITING) /* Is task in WAITING list? */
+ {
+ return E_ALREADY_IN_WAITING; /* Yes,error return */
+ }
+
+ OsSchedLock();
+ if(ptcb != TCBRunning) /* Is runing task? */
+ {
+ RemoveFromTCBRdyList(ptcb); /* No,Remove task from READY list */
+ }
+ else
+ {
+ TaskSchedReq = TRUE;
+ }
+
+ ptcb->state = TASK_WAITING; /* Set task status as TASK_WAITING */
+ OsSchedUnlock(); /* Call task schedule */
+ return E_OK; /* Return OK */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Awake Task
+ * @param[in] taskID ID of task that will been awaked.
+ * @param[out] None
+ * @retval E_OK Task awake successful.
+ * @retval E_INVALID_ID Invalid task ID.
+ * @retval E_TASK_NOT_WAITING Task now not in waiting state.
+ * @retval E_TASK_WAIT_OTHER Task now waiting other awake event.
+ * @retval E_PROTECTED_TASK Idle task mustn't be awaked.
+ *
+ * @par Description
+ * @details This function is called to awake current task.
+ *******************************************************************************
+ */
+StatusType CoAwakeTask(OS_TID taskID)
+{
+ P_OSTCB ptcb;
+
+ if(taskID == 0) /* Is idle task? */
+ {
+ return E_PROTECTED_TASK; /* Yes,error return */
+ }
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ ptcb = &TCBTbl[taskID];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(ptcb->state == TASK_DORMANT)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ if(ptcb->state != TASK_WAITING) /* Is task in WAITING list */
+ {
+ return E_TASK_NOT_WAITING; /* No,error return */
+ }
+
+#if CFG_TASK_WAITTING_EN > 0
+ if(ptcb->delayTick != INVALID_VALUE)/* Is task in READY list */
+ {
+ return E_TASK_WAIT_OTHER; /* Yes,error return */
+ }
+
+#if CFG_FLAG_EN > 0
+ if(ptcb->pnode != 0) /* Is task in flag waiting list */
+ {
+ return E_TASK_WAIT_OTHER; /* Yes,error return */
+ }
+#endif
+
+#if CFG_EVENT_EN>0
+ if(ptcb->eventID != INVALID_ID) /* Is task in event waiting list */
+ {
+ return E_TASK_WAIT_OTHER; /* Yes,error return */
+ }
+#endif
+
+#if CFG_MUTEX_EN > 0
+ if(ptcb->mutexID != INVALID_ID) /* Is task in mutex waiting list */
+ {
+ return E_TASK_WAIT_OTHER; /* Yes,error return */
+ }
+#endif
+
+#endif //CFG_TASK_WAITTING_EN
+
+ /* All no,so WAITING state was set by CoSuspendTask() */
+ OsSchedLock(); /* Lock schedule */
+ InsertToTCBRdyList(ptcb); /* Insert the task into the READY list*/
+ OsSchedUnlock(); /* Unlock schedule */
+ return E_OK; /* return OK */
+}
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/time.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,376 @@
+/**
+ *******************************************************************************
+ * @file time.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief time management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+#if CFG_TASK_WAITTING_EN > 0
+
+/*---------------------------- Variable Define -------------------------------*/
+P_OSTCB DlyList = 0; /*!< Header pointer to the DELAY list.*/
+
+
+/**
+ *******************************************************************************
+ * @brief Insert into DELAY list
+ *
+ * @param[in] ptcb Task that want to insert into DELAY list.
+ * @param[in] ticks Delay system ticks.
+ * @param[out] None
+ * @retval None.
+ *
+ * @par Description
+ * @details This function is called to insert task into DELAY list.
+ *******************************************************************************
+ */
+void InsertDelayList(P_OSTCB ptcb,U32 ticks)
+{
+ S32 deltaTicks;
+ P_OSTCB dlyNext;
+
+ if(ticks == 0) /* Is delay tick == 0? */
+ return; /* Yes,do nothing,return */
+ if(DlyList == 0) /* Is no item in DELAY list? */
+ {
+ ptcb->delayTick = ticks; /* Yes,set this as first item */
+ DlyList = ptcb;
+ }
+ else
+ {
+ /* No,find correct place ,and insert the task */
+ dlyNext = DlyList;
+ deltaTicks = ticks; /* Get task delay ticks */
+
+ /* Find correct place */
+ while(dlyNext != 0)
+ {
+ /* Get delta ticks with previous item */
+ deltaTicks -= dlyNext->delayTick;
+ if(deltaTicks < 0) /* Is delta ticks<0? */
+ {
+ /* Yes,get correct place */
+ if(dlyNext->TCBprev != 0) /* Is head item of DELAY list? */
+ {
+ dlyNext->TCBprev->TCBnext = ptcb; /* No,insert into */
+ ptcb->TCBprev = dlyNext->TCBprev;
+ ptcb->TCBnext = dlyNext;
+ dlyNext->TCBprev = ptcb;
+ }
+ else /* Yes,set task as first item */
+ {
+ ptcb->TCBnext = DlyList;
+ DlyList->TCBprev = ptcb;
+ DlyList = ptcb;
+ }
+ ptcb->delayTick = ptcb->TCBnext->delayTick+deltaTicks;
+ ptcb->TCBnext->delayTick -= ptcb->delayTick;
+ break;
+ }
+ /* Is last item in DELAY list? */
+ else if((deltaTicks >= 0) && (dlyNext->TCBnext == 0) )
+ {
+ ptcb->TCBprev = dlyNext; /* Yes,insert into */
+ dlyNext->TCBnext = ptcb;
+ ptcb->delayTick = deltaTicks;
+ break;
+ }
+ dlyNext = dlyNext->TCBnext; /* Get the next item in DELAY list */
+ }
+ }
+
+ ptcb->state = TASK_WAITING; /* Set task status as TASK_WAITING */
+ TaskSchedReq = TRUE;
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Remove from the DELAY list
+ * @param[in] ptcb Task that want to remove from the DELAY list.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to remove task from the DELAY list.
+ *******************************************************************************
+ */
+void RemoveDelayList(P_OSTCB ptcb)
+{
+
+ /* Is there only one item in the DELAY list? */
+ if((ptcb->TCBprev == 0) && ( ptcb->TCBnext == 0))
+ {
+ DlyList = 0; /* Yes,set DELAY list as 0 */
+ }
+ else if(ptcb->TCBprev == 0) /* Is the first item in DELAY list? */
+ {
+ /* Yes,remove task from the DELAY list,and reset the list */
+ DlyList = ptcb->TCBnext;
+ ptcb->TCBnext->delayTick += ptcb->delayTick;
+ ptcb->TCBnext->TCBprev = 0;
+ ptcb->TCBnext = 0;
+
+ }
+ else if(ptcb->TCBnext == 0) /* Is the last item in DELAY list? */
+ {
+ ptcb->TCBprev->TCBnext = 0; /* Yes,remove task form DELAY list */
+ ptcb->TCBprev = 0;
+ }
+ else /* No, remove task from DELAY list */
+ {
+ ptcb->TCBprev->TCBnext = ptcb->TCBnext;
+ ptcb->TCBnext->TCBprev = ptcb->TCBprev;
+ ptcb->TCBnext->delayTick += ptcb->delayTick;
+ ptcb->TCBnext = 0;
+ ptcb->TCBprev = 0;
+ }
+ ptcb->delayTick = INVALID_VALUE; /* Set task delay tick value as invalid */
+}
+
+/**
+ *******************************************************************************
+ * @brief Get current ticks
+ * @param[in] None
+ * @param[out] None
+ * @retval Return current system tick counter.
+ *
+ * @par Description
+ * @details This function is called to obtain current system tick counter.
+ *******************************************************************************
+ */
+U64 CoGetOSTime(void)
+{
+ return OSTickCnt; /* Get system time(tick) */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Delay current task for specify ticks number
+ * @param[in] ticks Specify system tick number which will delay.
+ * @param[out] None
+ * @retval E_CALL Error call in ISR.
+ * @retval E_OK The current task was insert to DELAY list successful,it
+ * will delay specify time.
+ * @par Description
+ * @details This function delay specify ticks for current task.
+ *
+ * @note This function be called in ISR,do nothing and return immediately.
+ *******************************************************************************
+ */
+StatusType CoTickDelay(U32 ticks)
+{
+ if(OSIntNesting >0) /* Is call in ISR? */
+ {
+ return E_CALL; /* Yes,error return */
+ }
+
+ if(ticks == INVALID_VALUE) /* Is tick==INVALID_VALUE? */
+ {
+ return E_INVALID_PARAMETER; /* Yes,error return */
+ }
+ if(ticks == 0) /* Is tick==0? */
+ {
+ return E_OK; /* Yes,do nothing ,return OK */
+ }
+ if(OSSchedLock != 0) /* Is OS lock? */
+ {
+ return E_OS_IN_LOCK; /* Yes,error return */
+ }
+ OsSchedLock(); /* Lock schedule */
+ InsertDelayList(TCBRunning,ticks); /* Insert task in DELAY list */
+ OsSchedUnlock(); /* Unlock schedule,and call task schedule */
+ return E_OK; /* Return OK */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Reset task delay ticks
+ * @param[in] ptcb Task that want to insert into DELAY list.
+ * @param[in] ticks Specify system tick number which will delay .
+ * @param[out] None
+ * @retval E_CALL Error call in ISR.
+ * @retval E_INVALID_ID Invalid task id.
+ * @retval E_NOT_IN_DELAY_LIST Task not in delay list.
+ * @retval E_OK The current task was inserted to DELAY list
+ * successful,it will delay for specify time.
+ * @par Description
+ * @details This function delay specify ticks for current task.
+ *******************************************************************************
+ */
+StatusType CoResetTaskDelayTick(OS_TID taskID,U32 ticks)
+{
+ P_OSTCB ptcb;
+
+
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ ptcb = &TCBTbl[taskID];
+#if CFG_PAR_CHECKOUT_EN >0
+ if(ptcb->stkPtr == 0)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ if(ptcb->delayTick == INVALID_VALUE) /* Is tick==INVALID_VALUE? */
+ {
+ return E_NOT_IN_DELAY_LIST; /* Yes,error return */
+ }
+ OsSchedLock(); /* Lock schedule */
+ RemoveDelayList(ptcb); /* Remove task from the DELAY list */
+
+ if(ticks == 0) /* Is delay tick==0? */
+ {
+ InsertToTCBRdyList(ptcb); /* Insert task into the DELAY list */
+ }
+ else
+ {
+ InsertDelayList(ptcb,ticks); /* No,insert task into DELAY list */
+ }
+ OsSchedUnlock(); /* Unlock schedule,and call task schedule */
+ return E_OK; /* Return OK */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Delay current task for detail time
+ * @param[in] hour Specify the number of hours.
+ * @param[in] minute Specify the number of minutes.
+ * @param[in] sec Specify the number of seconds.
+ * @param[in] millsec Specify the number of millseconds.
+ * @param[out] None
+ * @retval E_CALL Error call in ISR.
+ * @retval E_INVALID_PARAMETER Parameter passed was invalid,delay fail.
+ * @retval E_OK The current task was inserted to DELAY list
+ * successful,it will delay for specify time.
+ * @par Description
+ * @details This function delay specify time for current task.
+ *
+ * @note If this function called in ISR,do nothing and return immediately.
+ *******************************************************************************
+ */
+#if CFG_TIME_DELAY_EN >0
+StatusType CoTimeDelay(U8 hour,U8 minute,U8 sec,U16 millsec)
+{
+ U32 ticks;
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(OSIntNesting > 0)
+ {
+ return E_CALL;
+ }
+ if((minute > 59)||(sec > 59)||(millsec > 999))
+ return E_INVALID_PARAMETER;
+#endif
+ if(OSSchedLock != 0) /* Is OS lock? */
+ {
+ return E_OS_IN_LOCK; /* Yes,error return */
+ }
+
+ /* Get tick counter from time */
+ ticks = ((hour*3600) + (minute*60) + (sec)) * (CFG_SYSTICK_FREQ)\
+ + (millsec*CFG_SYSTICK_FREQ + 500)/1000;
+
+ CoTickDelay(ticks); /* Call tick delay */
+ return E_OK; /* Return OK */
+}
+#endif
+
+
+
+
+/**
+ *******************************************************************************
+ * @brief Dispose time delay
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to dispose time delay of all task.
+ *******************************************************************************
+ */
+void TimeDispose(void)
+{
+ P_OSTCB dlyList;
+
+ dlyList = DlyList; /* Get first item of DELAY list */
+ while((dlyList != 0) && (dlyList->delayTick == 0) )
+ {
+
+#if CFG_EVENT_EN > 0
+ if(dlyList->eventID != INVALID_ID) /* Is task in event waiting list? */
+ {
+ RemoveEventWaittingList(dlyList); /* Yes,remove task from list */
+ }
+#endif
+
+#if CFG_FLAG_EN > 0
+ if(dlyList->pnode != 0) /* Is task in flag waiting list? */
+ {
+ RemoveLinkNode((P_FLAG_NODE)dlyList->pnode); /* Yes,remove task from list */
+ }
+#endif
+ dlyList->delayTick = INVALID_VALUE; /* Set delay tick value as invalid*/
+ DlyList = dlyList->TCBnext; /* Get next item as the head of DELAY list*/
+ dlyList->TCBnext = 0;
+
+ InsertToTCBRdyList(dlyList); /* Insert task into READY list */
+
+ dlyList = DlyList; /* Get the first item of DELAY list */
+ if(dlyList != 0) /* Is DELAY list as 0? */
+ {
+ dlyList->TCBprev = 0; /* No,initialize the first item */
+ }
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Dispose time delay in ISR
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called in systick interrupt to dispose time delay
+ * of all task.
+ *******************************************************************************
+ */
+void isr_TimeDispose(void)
+{
+ if(OSSchedLock > 1) /* Is schedule lock? */
+ {
+ IsrReq = TRUE;
+ TimeReq = TRUE; /* Yes,set time request true */
+ }
+ else
+ {
+ TimeDispose(); /* No,call handler */
+ }
+}
+
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/timer.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,447 @@
+/**
+ *******************************************************************************
+ * @file timer.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief timer management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+/*---------------------------- Variable Define -------------------------------*/
+#if CFG_TMR_EN > 0
+
+TmrCtrl TmrTbl[CFG_MAX_TMR]= {{0}};/*!< Table which save timer control block.*/
+P_TmrCtrl TmrList = 0; /*!< The header of the TmrCtrl list. */
+U32 TmrIDVessel = 0; /*!< Timer ID container. */
+
+
+/**
+ *******************************************************************************
+ * @brief Insert a timer into the timer list
+ * @param[in] tmrID Specify timer ID which insertted.
+ * @param[out] None
+ * @retval E_INVALID_ID Timer ID passed was invalid,insert fail.
+ * @retval E_OK Insert successful.
+ *
+ * @par Description
+ * @details This function is called to insert a timer into the timer list.
+ *******************************************************************************
+ */
+static void InsertTmrList(OS_TCID tmrID)
+{
+ P_TmrCtrl pTmr;
+ S32 deltaTicks;
+ U32 tmrCnt;
+ tmrCnt = TmrTbl[tmrID].tmrCnt; /* Get timer time */
+
+ if(tmrCnt == 0) /* Is timer time==0? */
+ {
+ return; /* Do nothing,return */
+ }
+
+ OsSchedLock(); /* Lock schedule */
+ if(TmrList == 0) /* Is no item in timer list? */
+ {
+ TmrList = &TmrTbl[tmrID]; /* Yes,set this as first item */
+ }
+ else /* No,find correct place ,and insert inserted timer */
+ {
+ pTmr = TmrList;
+ deltaTicks = tmrCnt; /* Get timer tick */
+
+ /* find correct place */
+ while(pTmr != 0)
+ {
+ deltaTicks -= pTmr->tmrCnt; /* Get ticks with previous item */
+ if(deltaTicks < 0) /* Is delta ticks<0? */
+ {
+ /* Yes,get correct place */
+ if(pTmr->tmrPrev!= 0)/* Is head item of timer list? */
+ {
+ /* No,insert into */
+ pTmr->tmrPrev->tmrNext = &TmrTbl[tmrID];
+ TmrTbl[tmrID].tmrPrev = pTmr->tmrPrev;
+ TmrTbl[tmrID].tmrNext = pTmr;
+ pTmr->tmrPrev = &TmrTbl[tmrID];
+ }
+ else /* Yes,set task as first item */
+ {
+ TmrTbl[tmrID].tmrNext = TmrList;
+ TmrList->tmrPrev = &TmrTbl[tmrID];
+ TmrList = &TmrTbl[tmrID];
+ }
+ TmrTbl[tmrID].tmrCnt = TmrTbl[tmrID].tmrNext->tmrCnt+deltaTicks;
+ TmrTbl[tmrID].tmrNext->tmrCnt -= TmrTbl[tmrID].tmrCnt;
+ break;
+ }
+ /* Is last item in list? */
+ else if((deltaTicks >= 0) && (pTmr->tmrNext == 0))
+ {
+ /* Yes,insert into */
+ TmrTbl[tmrID].tmrPrev = pTmr;
+ pTmr->tmrNext = &TmrTbl[tmrID];
+ TmrTbl[tmrID].tmrCnt = deltaTicks;
+ break;
+ }
+ pTmr = pTmr->tmrNext; /* Get the next item in timer list */
+ }
+ }
+ OsSchedUnlock(); /* Unlock schedule */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Remove a timer from the timer list
+ * @param[in] tmrID Specify ID for a timer which removed form timer list.
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to remove a timer from the timer list.
+ *******************************************************************************
+ */
+static void RemoveTmrList(OS_TCID tmrID)
+{
+ P_TmrCtrl pTmr;
+
+ pTmr = &TmrTbl[tmrID];
+
+ OsSchedLock(); /* Lock schedule */
+
+ /* Is there only one item in timer list? */
+ if((pTmr->tmrPrev == 0) && (pTmr->tmrNext == 0))
+ {
+ TmrList = 0; /* Yes,set timer list as 0 */
+ }
+ else if(pTmr->tmrPrev == 0) /* Is the first item in timer list? */
+ { /* Yes,remove timer from list,and reset timer list */
+ TmrList = pTmr->tmrNext;
+ TmrList->tmrPrev = 0;
+ pTmr->tmrNext->tmrCnt += pTmr->tmrCnt;
+ pTmr->tmrNext = 0;
+ }
+ else if(pTmr->tmrNext == 0) /* Is the last item in timer list? */
+ {
+ /* Yes,remove timer form list */
+ pTmr->tmrPrev->tmrNext = 0;
+ pTmr->tmrPrev = 0;
+ }
+ else /* No, remove timer from list */
+ {
+ pTmr->tmrPrev->tmrNext = pTmr->tmrNext;
+ pTmr->tmrNext->tmrPrev = pTmr->tmrPrev;
+ pTmr->tmrNext->tmrCnt += pTmr->tmrCnt;
+ pTmr->tmrNext = 0;
+ pTmr->tmrPrev = 0;
+ }
+ OsSchedUnlock(); /* Unlock schedule */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Create a timer
+ * @param[in] tmrType Specify timer's type.
+ * @param[in] tmrCnt Specify timer initial counter value.
+ * @param[in] tmrReload Specify timer reload value.
+ * @param[in] func Specify timer callback function entry.
+ * @param[out] None
+ * @retval E_CREATE_FAIL Create timer fail.
+ * @retval others Create timer successful.
+ *
+ * @par Description
+ * @details This function is called to create a timer.
+ *******************************************************************************
+ */
+OS_TCID CoCreateTmr(U8 tmrType, U32 tmrCnt, U32 tmrReload, vFUNCPtr func)
+{
+ U8 i;
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if((tmrType != TMR_TYPE_ONE_SHOT) && (tmrType != TMR_TYPE_PERIODIC))
+ {
+ return E_CREATE_FAIL;
+ }
+ if(func == 0)
+ {
+ return E_CREATE_FAIL;
+ }
+#endif
+ OsSchedLock(); /* Lock schedule */
+ for(i = 0; i < CFG_MAX_TMR; i++)
+ {
+ if((TmrIDVessel & (1 << i)) == 0) /* Is free timer ID? */
+ {
+ TmrIDVessel |= (1<<i); /* Yes,assign ID to this timer */
+ OsSchedUnlock(); /* Unlock schedule */
+ TmrTbl[i].tmrID = i; /* Initialize timer as user set */
+ TmrTbl[i].tmrType = tmrType;
+ TmrTbl[i].tmrState = TMR_STATE_STOPPED;
+ TmrTbl[i].tmrCnt = tmrCnt;
+ TmrTbl[i].tmrReload = tmrReload;
+ TmrTbl[i].tmrCallBack = func;
+ TmrTbl[i].tmrPrev = 0;
+ TmrTbl[i].tmrNext = 0;
+ return i; /* Return timer ID */
+ }
+ }
+ OsSchedUnlock(); /* Unlock schedule */
+ return E_CREATE_FAIL; /* Error return */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Start counter
+ * @param[in] tmrID Specify a timer which startted.
+ * @param[out] None
+ * @retval E_INVALID_ID The timer id passed was invalid,can't start timer
+ * @retval E_OK Insert a timer to timer list and start it successful.
+ *
+ * @par Description
+ * @details This function is called to make a timer start countering.
+ *******************************************************************************
+ */
+StatusType CoStartTmr(OS_TCID tmrID)
+{
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(tmrID >= CFG_MAX_TMR)
+ {
+ return E_INVALID_ID;
+ }
+ if( (TmrIDVessel & (1<<tmrID)) == 0)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ if(TmrTbl[tmrID].tmrState == TMR_STATE_RUNNING) /* Is timer running? */
+ {
+ return E_OK; /* Yes,do nothing,return OK */
+ }
+
+ /* No,set timer status as TMR_STATE_RUNNING */
+ TmrTbl[tmrID].tmrState = TMR_STATE_RUNNING;
+ InsertTmrList(tmrID); /* Insert this timer into timer list */
+ return E_OK; /* Return OK */
+}
+
+
+
+/**
+ *******************************************************************************
+ * @brief Stop countering for a spcify timer
+ * @param[in] tmrID Specify a timer which stopped.
+ * @param[out] None
+ * @retval E_INVALID_ID The timer id passed was invalid, stop failure.
+ * @retval E_OK Stop a timer countering successful.
+ *
+ * @par Description
+ * @details This function is called to stop a timer from counting.
+ *******************************************************************************
+ */
+StatusType CoStopTmr(OS_TCID tmrID)
+{
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(tmrID >= CFG_MAX_TMR)
+ {
+ return E_INVALID_ID;
+ }
+ if((TmrIDVessel & (1<<tmrID)) == 0)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+
+ if(TmrTbl[tmrID].tmrState == TMR_STATE_STOPPED)/* Does timer stop running?*/
+ {
+ return E_OK; /* Yes,do nothing,return OK */
+ }
+ RemoveTmrList(tmrID); /* No,remove this timer from timer list */
+
+ /* Set timer status as TMR_STATE_STOPPED */
+ TmrTbl[tmrID].tmrState = TMR_STATE_STOPPED;
+ return E_OK; /* Return OK */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Delete a timer
+ * @param[in] tmrID Specify a timer which deleted.
+ * @param[out] None
+ * @retval E_INVALID_ID The timer id passed was invalid,deleted failure.
+ * @retval E_OK Delete a timer successful.
+ *
+ * @par Description
+ * @details This function is called to delete a timer which created before.
+ *******************************************************************************
+ */
+StatusType CoDelTmr(OS_TCID tmrID)
+{
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(tmrID >= CFG_MAX_TMR)
+ {
+ return E_INVALID_ID;
+ }
+ if( (TmrIDVessel & (1<<tmrID)) == 0)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+
+ if(TmrTbl[tmrID].tmrState == TMR_STATE_RUNNING) /* Is timer running? */
+ {
+ RemoveTmrList(tmrID); /* Yes,remove this timer from timer list*/
+ }
+ TmrIDVessel &=~(1<<tmrID); /* Release resource that this timer hold*/
+ return E_OK; /* Return OK */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Get current counter of specify timer
+ * @param[in] tmrID Specify timer by ID.
+ * @param[out] E_INVALID_ID Invalid ID was passed and get counter failure.
+ * @param[out] E_OK Get current counter successful.
+ * @retval Current counter of a timer which specify by id.
+ *
+ * @par Description
+ * @details This function is called to obtain current counter of specify timer.
+ *******************************************************************************
+ */
+U32 CoGetCurTmrCnt(OS_TCID tmrID,StatusType* perr)
+{
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(tmrID >= CFG_MAX_TMR)
+ {
+ *perr = E_INVALID_ID;
+ return 0;
+ }
+ if((TmrIDVessel & (1<<tmrID)) == 0)
+ {
+ *perr = E_INVALID_ID;
+ return 0;
+ }
+#endif
+ *perr = E_OK;
+ return TmrTbl[tmrID].tmrCnt; /* Return timer counter */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Setting for a specify timer
+ * @param[in] tmrID Specify timer by ID.
+ * @param[in] tmrCnt Specify timer counter which need to be set.
+ * @param[in] tmrReload Specify timer reload value which need to be set.
+ * @param[out] None
+ * @retval E_INVALID_ID The ID passed was invalid,set fail.
+ * @retval E_OK Set timer counter successful.
+ *
+ * @par Description
+ * @details This function is called to set timer counter and reload value.
+ *******************************************************************************
+ */
+StatusType CoSetTmrCnt(OS_TCID tmrID,U32 tmrCnt,U32 tmrReload)
+{
+#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
+ if(tmrID >= CFG_MAX_TMR)
+ {
+ return E_INVALID_ID;
+ }
+ if( (TmrIDVessel & (1<<tmrID)) == 0)
+ {
+ return E_INVALID_ID;
+ }
+#endif
+ TmrTbl[tmrID].tmrCnt = tmrCnt; /* Reset timer counter and reload value */
+ TmrTbl[tmrID].tmrReload = tmrReload;
+
+ if(TmrTbl[tmrID].tmrState == TMR_STATE_RUNNING) /* Is timer running? */
+ {
+ RemoveTmrList(tmrID); /* Yes,reorder timer in timer list */
+ InsertTmrList(tmrID);
+ }
+ return E_OK; /* Return OK */
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Timer counter dispose
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to dispose timer counter.
+ *******************************************************************************
+ */
+void TmrDispose(void)
+{
+ P_TmrCtrl pTmr;
+
+ pTmr = TmrList; /* Get first item of timer list */
+ while((pTmr != 0) && (pTmr->tmrCnt == 0) )
+ {
+ if(pTmr->tmrType == TMR_TYPE_ONE_SHOT) /* Is a One-shot timer? */
+ {
+ /* Yes,remove this timer from timer list */
+ RemoveTmrList(pTmr->tmrID);
+
+ /* Set timer status as TMR_STATE_STOPPED */
+ pTmr->tmrState = TMR_STATE_STOPPED;
+ (pTmr->tmrCallBack)(); /* Call timer callback function */
+ }
+ else if(pTmr->tmrType == TMR_TYPE_PERIODIC) /* Is a periodic timer? */
+ {
+ /* Yes,remove this timer from timer list */
+ RemoveTmrList(pTmr->tmrID);
+ pTmr->tmrCnt = pTmr->tmrReload; /* Reset timer tick */
+ InsertTmrList(pTmr->tmrID); /* Insert timer into timer list */
+ (pTmr->tmrCallBack)(); /* Call timer callback function */
+ }
+ pTmr = TmrList; /* Get first item of timer list */
+ }
+}
+
+
+/**
+ *******************************************************************************
+ * @brief Timer counter dispose in ISR
+ * @param[in] None
+ * @param[out] None
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to dispose timer counter.
+ *******************************************************************************
+ */
+void isr_TmrDispose(void)
+{
+ if(OSSchedLock > 1) /* Is schedule lock? */
+ {
+ IsrReq = TRUE;
+ TimerReq = TRUE; /* Yes,set timer request true */
+ }
+ else
+ {
+ TmrDispose(); /* No,call handler */
+ }
+}
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/utility.c Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,86 @@
+/**
+ *******************************************************************************
+ * @file utility.c
+ * @version V1.1.3
+ * @date 2010.04.26
+ * @brief Utility management implementation code of CooCox CoOS kernel.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+/*---------------------------- Include ---------------------------------------*/
+#include <coocox.h>
+
+#if CFG_UTILITY_EN > 0
+
+
+/**
+ *******************************************************************************
+ * @brief Convert tick number to time
+ * @param[in] ticks Specifies the systerm tick numbers that will be converted.
+ * @param[out] hour Hours which converted.
+ * @param[out] minute minutes which converted.
+ * @param[out] sec seconds which converted.
+ * @param[out] millsec millseconds which converted.
+ * @retval None
+ *
+ * @par Description
+ * @details This function is called to convert specify ticks to time format.
+ *******************************************************************************
+ */
+#if CFG_TICK_TO_TIME_EN > 0
+void CoTickToTime(U32 ticks,U8* hour,U8* minute,U8* sec,U16* millsec)
+{
+ U32 totalTime;
+
+ /* Convert ticks to time*/
+ totalTime = ticks * (1000/CFG_SYSTICK_FREQ);
+ *millsec = totalTime%1000;
+ totalTime = totalTime/1000;
+ *sec = totalTime%60;
+ totalTime = totalTime/60;
+ *minute = totalTime%60;
+ totalTime = totalTime/60;
+ *hour = totalTime;
+}
+#endif /* CFG_TICK_TO_TIME_EN */
+
+
+/**
+ *******************************************************************************
+ * @brief Convert time to tick
+ * @param[in] hour Specifies the number of hours.
+ * @param[in] minute Specifies the number of minutes.
+ * @param[in] sec Specifies the number of seconds.
+ * @param[in] millsec Specifies the number of millseconds.
+ * @param[out] ticks Tick numbers that converted.
+ * @retval E_INVALID_PARAMETER Invalid parameter be passed and convert fail.
+ * @retval E_OK Convert successful.
+ *
+ * @par Description
+ * @details This function is called to convert specify time to tick number.
+ *******************************************************************************
+ */
+#if CFG_TIME_TO_TICK_EN > 0
+StatusType CoTimeToTick(U8 hour,U8 minute,U8 sec,U16 millsec,U32* ticks)
+{
+#if CFG_PAR_CHECKOUT_EN >0
+ /* Validate arguments to be within range */
+ if((minute > 59)||(sec > 59)||(millsec > 999))
+ return E_INVALID_PARAMETER;
+#endif
+
+ /* Convert time to ticks */
+ *ticks = ((hour*3600) + (minute*60) + (sec)) * (CFG_SYSTICK_FREQ)\
+ + (millsec*CFG_SYSTICK_FREQ + 500)/1000;
+ return E_OK;
+}
+#endif /* CFG_TIME_TO_TICK_EN */
+
+#endif /* CFG_UTILITY_EN */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/utility.h Fri Dec 03 19:45:30 2010 +0000
@@ -0,0 +1,39 @@
+/**
+ *******************************************************************************
+ * @file utility.h
+ * @version V1.1.3 Initial version
+ * @date 2010.04.26
+ * @brief Utility function header file
+ * @details This file including some defines and declares related to utility
+ * function.
+ *******************************************************************************
+ * @copy
+ *
+ * INTERNAL FILE,DON'T PUBLIC.
+ *
+ * <h2><center>© COPYRIGHT 2009 CooCox </center></h2>
+ *******************************************************************************
+ */
+
+
+#ifndef _UTILITY_H
+#define _UTILITY_H
+
+
+/**
+ * @struct Time struct utility.h
+ * @brief Time struct
+ * @details This struct use to manage time
+ */
+typedef struct SysTime
+{
+ U8 sec; /*!< Second */
+ U8 min; /*!< Minute */
+ U8 hour; /*!< Hour */
+ U8 date; /*!< Date */
+ U8 month; /*!< Month */
+ U16 year; /*!< Year */
+}TIME;
+
+#endif
+