electronix79
/
CoOS_mbed
CooCox 1.1.4 on mbed with simple blinky example
Revision 0:7f6d87f66362, committed 2011-07-29
- Comitter:
- electronix79
- Date:
- Fri Jul 29 03:01:03 2011 +0000
- Commit message:
- CooCox 1.1.4
Changed in this revision
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/CoOS.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/CoOS.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,222 @@ +/** + ******************************************************************************* + * @file CoOS.h + * @version V1.1.4 + * @date 2011.04.20 + * @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 Co_NULL +#define Co_NULL ((void *)0) +#endif + +#ifndef Co_FALSE +#define Co_FALSE (0) +#endif + +#ifndef Co_TRUE +#define Co_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) &0x000FFF00 ),stk) + + +#define CoCreateTaskEx(task,argv,prio,stk,stkSz,timeSlice,isWaitting) \ + CreateTask(task,argv,(prio)|(((stkSz)<<8)&0x000FFF00)|(((timeSlice)<<20)&0x7FF00000)|((isWaitting<<31)&0x80000000),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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsConfig.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsConfig.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,276 @@ +/** + ******************************************************************************* + * @file config.h + * @version V1.1.4 + * @date 2011.04.20 + * @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 (5) + +/*!< +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 (1000) + +/*!< +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 (0) + +/*!< +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 (0) +#endif + +/*!< +Enable(1) or disable(0) CoAwakeTask() and CoSuspendTask() API. +*/ +#define CFG_TASK_SUSPEND_EN (0) + + +/*---------------------- Debug Management Config ----------------------------*/ +/*!< +Enable(1) or disable(0) parameter checkout . +*/ +#define CFG_PAR_CHECKOUT_EN (0) + +/*!< +Enable(1) or disable(0) stack overflow checkout . +*/ +#define CFG_STK_CHECKOUT_EN (0) + + + +/*---------------------- Memory Management Config ----------------------------*/ +/*!< +Enable(1) or disable(0) memory management. +*/ +#define CFG_MM_EN (0) + +/*!< +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 (0) + +/*!< +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 (0) + +/*!< +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 (5) + +/*!< +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 (0) + +/*!< +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 (0) + +#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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsCore.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsCore.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,27 @@ +/** + ******************************************************************************* + * @file OsCore.h + * @version V1.1.4 + * @date 2011.04.20 + * @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 +
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsError.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsError.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,84 @@ +/** + ******************************************************************************* + * @file OsError.h + * @version V1.1.4 + * @date 2011.04.20 + * @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 */
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsEvent.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsEvent.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,58 @@ +/** + ******************************************************************************* + * @file OsEvent.h + * @version V1.1.4 + * @date 2011.04.20 + * @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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsFlag.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsFlag.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,57 @@ +/** + ******************************************************************************* + * @file OsFlag.h + * @version V1.1.4 + * @date 2011.04.20 + * @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 +
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsKernelHeap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsKernelHeap.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,48 @@ +/** + ******************************************************************************* + * @file OsKernelHeap.h + * @version V1.1.4 + * @date 2011.04.20 + * @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 */ +
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsMM.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsMM.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,41 @@ +/** + ******************************************************************************* + * @file OsMm.h + * @version V1.1.4 + * @date 2011.04.20 + * @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 */ +
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsMutex.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsMutex.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,57 @@ +/** + ******************************************************************************* + * @file OsMutex.h + * @version V1.1.4 + * @date 2011.04.20 + * @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 */
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsQueue.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsQueue.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,39 @@ +/** + ******************************************************************************* + * @file OsQueue.h + * @version V1.1.4 + * @date 2011.04.20 + * @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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsServiceReq.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsServiceReq.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,53 @@ + +/** + ******************************************************************************* + * @file OsServiceReq.h + * @version V1.1.4 + * @date 2011.04.20 + * @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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsTask.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsTask.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,112 @@ +/** + ******************************************************************************* + * @file OsTask.h + * @version V1.1.4 + * @date 2011.04.20 + * @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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsTime.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsTime.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,28 @@ +/** + ******************************************************************************* + * @file OsTime.c + * @version V1.1.4 + * @date 2011.04.20 + * @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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/OsTimer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/OsTimer.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,49 @@ +/** + ******************************************************************************* + * @file OsTimer.h + * @version V1.1.4 + * @date 2011.04.20 + * @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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/coocox.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/coocox.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,60 @@ +/** + ******************************************************************************* + * @file coocox.h + * @version V1.1.4 + * @date 2011.04.20 + * @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)0x0114 /*!< OS version.(format: Vx.xx), + e.g. value 0x0114 is version V1.14*/ +/*---------------------------- 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 */
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/core.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/core.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,238 @@ + /** + ******************************************************************************* + * @file core.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 = Co_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 == Co_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 == Co_TRUE) + { + RespondSRQ(); /* Respond service request */ + } +#endif + /* Judge task state change or higher PRI task coming in */ + if(TaskSchedReq == Co_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, + Co_NULL, + 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 */ +} +
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/event.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/event.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,410 @@ +/** + ******************************************************************************* + * @file event.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 = Co_NULL; + 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 = Co_NULL; /* 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.Co_NULL for other + * event type. + * @param[out] None + * @retval Co_NULL 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 == Co_NULL) /* 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 != Co_NULL) /* 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 != Co_NULL) /* 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-->Co_NULL) + ******************************************************************************* + */ +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 == Co_NULL) /* Is no item in event waiting list?*/ + { + pecb->eventTCBList = ptcb; /* Yes,set task as first item */ + } + else + { + while(ptcb1->waitNext != Co_NULL)/* 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 == Co_NULL) /* 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 != Co_NULL) /* 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 != Co_NULL) + { + ptcb2->waitPrev = ptcb; + } + } + } +#endif + ptcb->state = TASK_WAITING; /* Set task status to TASK_WAITING state */ + TaskSchedReq = Co_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 != Co_NULL) /* 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 = Co_NULL; /* 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 Co_NULL */ + } + 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 +
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/flag.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/flag.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,712 @@ +/** + ******************************************************************************* + * @file flag.c + * @version V1.1.4 + * @date 2011.04.20 + * @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,Co_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 != Co_NULL) /* 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 = Co_TRUE; + OsSchedUnlock(); + + /* The required flag is set and the task is in running state */ + curTCB->pnode = Co_NULL; + 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 == Co_NULL) /* If time-out occurred */ + { + return E_TIMEOUT; + } + else /* If flag is set */ + { + curTCB->pnode = Co_NULL; + 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 = Co_TRUE; + OsSchedUnlock(); + + curTCB->pnode = Co_NULL; + 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 == Co_NULL) /* If time-out occurred */ + { + *perr = E_TIMEOUT; + return 0; + } + else /* If the required flags are set */ + { + curTCB->pnode = Co_NULL; + 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 != Co_NULL) + { + 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,Co_NULL) == Co_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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/hook.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/hook.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,65 @@ +/** + ******************************************************************************* + * @file hook.c + * @version V1.1.4 + * @date 2011.04.20 + * @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(; ;) + { + + } +} + + + + + +
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/kernelHeap.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/kernelHeap.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,409 @@ +/** + ******************************************************************************* + * @file kernelHeap.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 = Co_NULL; /*!< 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 = Co_NULL; + FMBlist->nextUMB = Co_NULL; + FMBlist->preUMB = Co_NULL; +} + + +/** + ******************************************************************************* + * @brief Allocation size bytes of memory block from kernel heap. + * @param[in] size Length of menory block. + * @param[out] None + * @retval Co_NULL 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 Co_NULL; + } +#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 = Co_NULL; + while(freeMB != Co_NULL ) /* Is out of free memory list? */ + { /* No */ + if(freeMB->nextUMB == Co_NULL) /* 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 != Co_NULL)/* 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 != Co_NULL) /* 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 != Co_NULL)/* 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 != Co_NULL) /* 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 != Co_NULL) /* 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 Co_NULL; /* 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 == Co_NULL) + { + 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 == Co_NULL) + { + OsSchedUnlock(); + return; + } + preUMB = (P_UMB)((U32)(preUMB->preMB)-1); + } + } + else + { + if(FMBlist == Co_NULL) + { + nextUMB = (P_UMB)(Kheap.startAddr); + } + else + { + if(FMBlist->nextUMB != Co_NULL) + { + nextUMB = (P_UMB)((U32)(FMBlist->nextUMB)-1); + } + else + { + nextUMB = Co_NULL; + } + } + + while(nextUMB != usedMB) + { + if(nextUMB == Co_NULL) + { + 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 == Co_NULL) && (usedMB->preMB == Co_NULL)) + { + curFMB = (P_FMB)usedMB; /* Yes,release this item */ + curFMB->nextFMB = Co_NULL; + curFMB->nextUMB = Co_NULL; + curFMB->preUMB = Co_NULL; + FMBlist = curFMB; + } + else if(usedMB->preMB == Co_NULL) /* 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 = Co_NULL; + FMBlist = curFMB; + } + else if(usedMB->nextMB == Co_NULL) /* Is the last item in kernel heap */ + { /* Yes,release this item,and set link for list */ + curFMB = (P_FMB)(usedMB->preMB); + curFMB->nextFMB = Co_NULL; + curFMB->nextUMB = Co_NULL; + } + 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 == Co_NULL) /* 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 = Co_NULL; + 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 == Co_NULL) /* Is previous FMB==Co_NULL? */ + { + 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 == Co_NULL) /* Is new FMB as last item of FMB list? */ + { + curFMB->preUMB = preUMB; /* Yes,set link for list */ + curFMB->nextUMB = Co_NULL; + curFMB->nextFMB = Co_NULL; + } + 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 == Co_NULL ) /* Is previous FMB==Co_NULL? */ + { + 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 != Co_NULL)/* 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 != Co_NULL)/* 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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/mbox.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/mbox.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,325 @@ +/** + ******************************************************************************* + * @file mbox.c + * @version V1.1.4 + * @date 2011.04.20 + * @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,Co_NULL); + if(pecb == Co_NULL) /* 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 Co_NULL + * @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 Co_NULL; + } +#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 Co_NULL; + } +#endif + OsSchedLock(); + if(pecb->eventCounter == 1) /* If there is already a message */ + { + *perr = E_OK; + pmail = pecb->eventPtr; /* Get the message */ + pecb->eventPtr = Co_NULL; /* 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 Co_NULL */ + return Co_NULL; + } +} + + + +/** + ******************************************************************************* + * @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 Co_NULL + * @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 Co_NULL; + } + +#if CFG_PAR_CHECKOUT_EN >0 + if(id >= CFG_MAX_EVENT) + { + *perr = E_INVALID_ID; /* Invalid 'id',retrun error */ + return Co_NULL; + } +#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 Co_NULL; + } +#endif + + if(OSSchedLock != 0) /* Judge schedule is locked or not? */ + { + *perr = E_OS_IN_LOCK; /* Schedule is locked */ + return Co_NULL; /* return Co_NULL */ + } + OsSchedLock(); + if( pecb->eventCounter == 1) /* If there is already a message */ + { + *perr = E_OK; + pmail = pecb->eventPtr; /* Get the message */ + pecb->eventPtr = Co_NULL; /* Clear the mailbox */ + pecb->eventCounter = 0; + OsSchedUnlock(); + return pmail; /* Return the message received */ + } + else /* If message is not available, task will pend */ + { + OsSchedUnlock(); + 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 = Co_NULL; + return pmail; /* Return received message or Co_NULL */ + } + else /* If time-out is configured */ + { + OsSchedLock(); + + /* Block task until event or timeout occurs */ + EventTaskToWait(pecb,curTCB); + InsertDelayList(curTCB,timeout); + OsSchedUnlock(); + if( curTCB->pmail == Co_NULL) /* Time-out occurred */ + { + *perr = E_TIMEOUT; + return Co_NULL; + } + else /* Have recived a message or the mailbox have been deleted*/ + { + *perr = E_OK; + pmail = curTCB->pmail; + curTCB->pmail = Co_NULL; + return pmail; /* Return received message or Co_NULL */ + } + } + } +} + + +/** + ******************************************************************************* + * @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) == Co_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 + +
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/mm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/mm.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,275 @@ +/** + ******************************************************************************* + * @file mm.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 == Co_NULL) + { + 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 = Co_NULL; + 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 = Co_NULL; + memCtl->freeBlock = Co_NULL; + 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 != Co_NULL) /* 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 Co_NULL 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 Co_NULL; + } + if( ((1<<mmID)&MemoryIDVessel) == 0) + { + return Co_NULL; + } +#endif + memCtl = &MemoryTbl[mmID]; + OsSchedLock(); /* Lock schedule */ + if(memCtl->freeBlock == Co_NULL ) /* Is there no free item in memory list */ + { + OsSchedUnlock(); /* Unlock schedule */ + return Co_NULL; /* 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 == Co_NULL) + { + 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 = buf; + OsSchedUnlock(); + return E_OK; /* Return OK */ +} + +#endif +
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/mutex.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/mutex.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,349 @@ +/** + ******************************************************************************* + * @file mutex.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 = Co_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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/queue.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/queue.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,393 @@ +/** + ******************************************************************************* + * @file queue.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 == Co_NULL) || (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 == Co_NULL ) /* 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 = Co_NULL; + 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 Co_NULL + * @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 Co_NULL; + } +#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 Co_NULL; + } +#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 Co_NULL; /* Return Co_NULL */ + } +} + + + +/** + ******************************************************************************* + * @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 Co_NULL + * @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 Co_NULL; + } +#if CFG_PAR_CHECKOUT_EN >0 + if(id >= CFG_MAX_EVENT) + { + *perr = E_INVALID_ID; /* Invalid event id,return error */ + return Co_NULL; + } +#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 Co_NULL; + } +#endif + if(OSSchedLock != 0) /* Judge schedule is locked or not? */ + { + *perr = E_OS_IN_LOCK; /* Schedule is locked,return error */ + return Co_NULL; + } + 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)/* Check queue head */ + { + pqcb->head = 0; + } + OsSchedUnlock(); + *perr = E_OK; + return pmail; /* Return message received */ + } + else /* If there is no message in the queue*/ + { + OsSchedUnlock(); + 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 = Co_NULL; + *perr = E_OK; + return pmail; /* Return message received or Co_NULL */ + } + 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 == Co_NULL) /* If time-out occurred */ + { + *perr = E_TIMEOUT; + return Co_NULL; + } + else /* If event occured */ + { + pmail = curTCB->pmail; + curTCB->pmail = Co_NULL; + *perr = E_OK; + return pmail; /* Return message received or Co_NULL */ + } + } + } +} + + + +/** + ******************************************************************************* + * @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) == Co_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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/sem.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/sem.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,322 @@ +/** + ******************************************************************************* + * @file sem.c + * @version V1.1.4 + * @date 2011.04.20 + * @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,Co_NULL); + if(pecb == Co_NULL) /* 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 */ + } + OsSchedLock(); + if(pecb->eventCounter > 0) /* If semaphore is positive,resource available */ + { + pecb->eventCounter--; /* Decrement semaphore only if positive */ + OsSchedUnlock(); + return E_OK; + } + else /* Resource is not available */ + { + OsSchedUnlock(); + curTCB = TCBRunning; + if(timeout == 0) /* If time-out is not configured */ + { + EventTaskToWait(pecb,curTCB); /* Block task until event occurs */ + curTCB->pmail = Co_NULL; + 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 == Co_NULL) /* If pmail is Co_NULL, time-out occurred*/ + { + return E_TIMEOUT; + } + else /* Event occurred or event have been deleted*/ + { + curTCB->pmail = Co_NULL; + 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,Co_NULL) == Co_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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/serviceReq.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/serviceReq.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,165 @@ +/** + ******************************************************************************* + * @file serviceReq.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 = Co_FALSE; +#if (CFG_TASK_WAITTING_EN > 0) +BOOL TimeReq = Co_FALSE; /*!< Time delay dispose request */ +#endif + +#if CFG_TMR_EN > 0 +BOOL TimerReq = Co_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 Co_FALSE Successfully insert into service request queue. + * @retval Co_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 Co_FALSE; /* Error return */ + } + cnt = Inc8(&ServiceReq.cnt); + heed = ServiceReq.head; + IsrReq = Co_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 Co_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 == Co_TRUE) /* Time delay request? */ + { + TimeDispose(); /* Yes,call handler */ + TimeReq = Co_FALSE; /* Reset time delay request Co_FALSE */ + } +#endif +#if CFG_TMR_EN > 0 + if(TimerReq == Co_TRUE) /* Timer request? */ + { + TmrDispose(); /* Yes,call handler */ + TimerReq = Co_FALSE; /* Reset timer request Co_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 = Co_FALSE; /* queue still empty here */ + } + IRQ_ENABLE_RESTORE (); /* now it is done and return */ +} + +#endif +
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/task.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/task.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,1260 @@ +/** + ******************************************************************************* + * @file task.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 Co_TRUE Assign priority in priority queue. + * Co_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 Co_TRUE; + } + else if (pri < ActivePri[num]) + { + seqNum = num; + num = tmpNum; + } + else + { + num++; + } + } + *SequenceNum = num; + return Co_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 Co_TRUE This priority has ready task + * Co_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 Co_FALSE; + } + return Co_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) == Co_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 != Co_NULL) /* No,TCBRunning == Co_NULL? */ + { /* 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) == Co_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 = Co_TRUE; + if(ptcb == Co_NULL) + { + 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 != Co_NULL) + { + ptcbNext->TCBprev = tcbInsert; + } + + +#else + ptcb = TCBRdy; + if (ptcb == Co_NULL) /* Is ready list Co_NULL? */ + { + TaskSchedReq = Co_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 = Co_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 != Co_NULL) /* 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 != Co_NULL) + { + 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 = Co_FALSE; + prio = ptcb->prio; + GetPriSeqNum(prio,&seqNum); +#endif + + /* Is there only one item in READY list? */ + if((ptcb->TCBnext == Co_NULL) && (ptcb->TCBprev == Co_NULL) ) + { + TCBRdy = 0; /* Yes,set READY list as Co_NULL */ +#if CFG_ORDER_LIST_SCHEDULE_EN ==0 + isChange = Co_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 = Co_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 = Co_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 = Co_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 == Co_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 = Co_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 != Co_NULL) + { + 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==Co_NULL) || (pCurTcb != TCBNext) || (OSSchedLock >1) || (OSIntNesting >0)) + { + return; + } + + TaskSchedReq = Co_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 Co_NULL? */ + { + 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 = Co_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 == Co_NULL) + 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 = Co_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 != Co_NULL) /* 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
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/time.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/time.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,376 @@ +/** + ******************************************************************************* + * @file time.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 = Co_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 Co_NULL */ + } + 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 == Co_NULL) + { + 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 Co_NULL? */ + { + 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 = Co_TRUE; + TimeReq = Co_TRUE; /* Yes,set time request Co_TRUE */ + } + else + { + TimeDispose(); /* No,call handler */ + } +} + + +#endif
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/timer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/timer.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,447 @@ +/** + ******************************************************************************* + * @file timer.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 = Co_NULL; /*!< 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 == Co_NULL) /* 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 != Co_NULL) + { + deltaTicks -= pTmr->tmrCnt; /* Get ticks with previous item */ + if(deltaTicks < 0) /* Is delta ticks<0? */ + { + /* Yes,get correct place */ + if(pTmr->tmrPrev!= Co_NULL)/* 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 == Co_NULL)) + { + /* 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 == Co_NULL) && (pTmr->tmrNext == Co_NULL)) + { + TmrList = Co_NULL; /* Yes,set timer list as Co_NULL */ + } + else if(pTmr->tmrPrev == Co_NULL) /* Is the first item in timer list? */ + { /* Yes,remove timer from list,and reset timer list */ + TmrList = pTmr->tmrNext; + TmrList->tmrPrev = Co_NULL; + pTmr->tmrNext->tmrCnt += pTmr->tmrCnt; + pTmr->tmrNext = Co_NULL; + } + else if(pTmr->tmrNext == Co_NULL) /* Is the last item in timer list? */ + { + /* Yes,remove timer form list */ + pTmr->tmrPrev->tmrNext = Co_NULL; + pTmr->tmrPrev = Co_NULL; + } + else /* No, remove timer from list */ + { + pTmr->tmrPrev->tmrNext = pTmr->tmrNext; + pTmr->tmrNext->tmrPrev = pTmr->tmrPrev; + pTmr->tmrNext->tmrCnt += pTmr->tmrCnt; + pTmr->tmrNext = Co_NULL; + pTmr->tmrPrev = Co_NULL; + } + 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 == Co_NULL) + { + 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 = Co_NULL; + TmrTbl[i].tmrNext = Co_NULL; + 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 != Co_NULL) && (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 = Co_TRUE; + TimerReq = Co_TRUE; /* Yes,set timer request true */ + } + else + { + TmrDispose(); /* No,call handler */ + } +} + +#endif
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/utility.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/utility.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,86 @@ +/** + ******************************************************************************* + * @file utility.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 */
diff -r 000000000000 -r 7f6d87f66362 CoOS/kernel/utility.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/utility.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,39 @@ +/** + ******************************************************************************* + * @file utility.h + * @version V1.1.4 + * @date 2011.04.20 + * @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 +
diff -r 000000000000 -r 7f6d87f66362 CoOS/portable/Keil/port.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/portable/Keil/port.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,248 @@ +/** + ******************************************************************************* + * @file port.c + * @version V1.14 + * @date 2011.04.20 + * @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 + +
diff -r 000000000000 -r 7f6d87f66362 CoOS/portable/OsArch.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/portable/OsArch.h Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,50 @@ +/** + ******************************************************************************* + * @file OsArch.h + * @version V1.1.4 + * @date 2011.04.20 + * @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
diff -r 000000000000 -r 7f6d87f66362 CoOS/portable/arch.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/portable/arch.c Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,96 @@ +/** + ******************************************************************************* + * @file arch.c + * @version V1.1.4 + * @date 2011.04.20 + * @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 != Co_NULL) /* 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 != Co_NULL) /* 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 = Co_TRUE; + OsSchedUnlock(); +}
diff -r 000000000000 -r 7f6d87f66362 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,83 @@ +// CooCox RTOS v1.1.4 with simple example +// Two LEDs will blink with 250ms and 500ms interval based on two seperate tasks +// by electronix79, 29/July/2011 +// +// Comments: Nice work by Eric Ebert which used CooCox RTOS v1.1.3 but all files of CoOS were in one main folder, +// so I create new project with the same structure as in CooCox design and of cause I use the updated version 1.1.4 + +#include "mbed.h" + +#include <CoOS.h> + +DigitalOut led1(LED1), led4(LED4); + +#define TASK_STACK_SIZE 128 /*!< Define task size */ + +#define PRIORITY_TASK1 1 /* Priority of task 1 */ +#define PRIORITY_TASK2 2 /* Priority of task 2 */ +#define PRIORITY_TASK3 3 /* Priority of task 3 */ + +OS_STK task1_stk[TASK_STACK_SIZE]; /*!< Define "task1" task stack */ +OS_STK task2_stk[TASK_STACK_SIZE]; /*!< Define "task2" task stack */ +OS_STK task3_stk[TASK_STACK_SIZE]; /*!< Define "task3" task stack */ + +OS_TID task1_id; /*!< Task ID of 'task1'. */ +OS_TID task2_id; /*!< Task ID of 'task2'. */ +OS_TID task3_id; /*!< Task ID of 'task3'. */ + +OS_MutexID mut_1; /*!< Save id of mutex. */ + +void task1(void *); +void task2(void *); +void task3(void *); + +void task1(void* pdata) +{ + mut_1 = CoCreateMutex(); /* Create a mutex */ + + task2_id = CoCreateTask(task2, (void *)0, PRIORITY_TASK2, &task2_stk[TASK_STACK_SIZE-1], TASK_STACK_SIZE); + task3_id = CoCreateTask(task3, (void *)0, PRIORITY_TASK3, &task3_stk[TASK_STACK_SIZE-1], TASK_STACK_SIZE); + + CoExitTask(); /* Delete 'task1' task. */ +} + +void task2(void* pdata) +{ + for(;;) + { + CoEnterMutexSection(mut_1); /* Enter critical region */ + led1 = 1; /* Turn On Led */ + CoLeaveMutexSection(mut_1); /* Exit critical region */ + CoTickDelay(250); /* Delay 250ms */ + CoEnterMutexSection(mut_1); /* Enter critical region */ + led1 = 0; /* Turn Off Led */ + CoLeaveMutexSection(mut_1); /* Exit critical region */ + CoTickDelay(250); /* Delay 250ms */ + } +} + +void task3(void* pdata) +{ + for(;;) + { + CoEnterMutexSection(mut_1); /* Enter critical region */ + led4 = 1; /* Turn On Led */ + CoLeaveMutexSection(mut_1); /* Exit critical region */ + CoTickDelay(500); /* Delay 500ms */ + CoEnterMutexSection(mut_1); /* Enter critical region */ + led4 = 0; /* Turn Off Led */ + CoLeaveMutexSection(mut_1); /* Exit critical region */ + CoTickDelay(500); /* Delay 500ms */ + } +} + +int main() +{ + CoInitOS(); /*!< Initial CooCox CoOS */ + + task1_id = CoCreateTask(task1, (void *)0, PRIORITY_TASK1, &task1_stk[TASK_STACK_SIZE-1], TASK_STACK_SIZE); + + CoStartOS(); /*!< Start multitask */ + + while (1); /*!< The code don't reach here */ +}
diff -r 000000000000 -r 7f6d87f66362 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Jul 29 03:01:03 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912