1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-25 17:25:13 +03:00

First commit CooCox

This commit is contained in:
bsongis 2012-06-10 21:02:43 +00:00
parent a45b03ded3
commit 38d5ca9236
37 changed files with 7559 additions and 56 deletions

View file

@ -0,0 +1,11 @@
CooCox CoOS's source code package includes the following files:
kernel: CooCox CoOS's source code, you can use it without any modification.
portable: CooCox CoOS's port for Cortex M3. It includes the source code for Cortex M3 architecture with three edition : MDK, IAR, GCC. You can choose a suitable one for your application.
config: Configuration files for CooCox CoOS. You can tailor CooCox CoOS for your application with it.
CooCox CoOS's TERMS AND CONDITIONS.pdf: The terms you should obey when using CooCox CoOS's source code.
To develop application based on CooCox CoOS, you should include all the source code files in the kernel folder, and choose an edition in portable folder for the compiler that you are using. You also should amend config.h for tailoring CooCox CoOS, otherwise CooCox CoOS may be too big for your needs.

222
src/CoOS/kernel/CoOS.h Normal file
View file

@ -0,0 +1,222 @@
/**
*******************************************************************************
* @file ccrtos.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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 NULL
#define NULL ((void *)0)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (1)
#endif
/*---------------------------- Error Codes ---------------------------------*/
#define E_CREATE_FAIL (StatusType)-1
#define E_OK (StatusType)0
#define E_INVALID_ID (StatusType)1
#define E_INVALID_PARAMETER (StatusType)2
#define E_CALL (StatusType)3
#define E_TASK_WAITING (StatusType)4
#define E_TIMEOUT (StatusType)5
#define E_SEM_FULL (StatusType)6
#define E_MBOX_FULL (StatusType)7
#define E_QUEUE_FULL (StatusType)8
#define E_SEM_EMPTY (StatusType)9
#define E_MBOX_EMPTY (StatusType)10
#define E_QUEUE_EMPTY (StatusType)11
#define E_FLAG_NOT_READY (StatusType)12
#define E_ALREADY_IN_WAITING (StatusType)13
#define E_TASK_NOT_WAITING (StatusType)14
#define E_TASK_WAIT_OTHER (StatusType)15
#define E_EXCEED_MAX_NUM (StatusType)16
#define E_NOT_IN_DELAY_LIST (StatusType)17
#define E_SEV_REQ_FULL (StatusType)18
#define E_NOT_FREE_ALL (StatusType)19
#define E_PROTECTED_TASK (StatusType)20
#define E_OS_IN_LOCK (StatusType)21
/*---------------------------- Wait Opreation type --------------------------*/
#define OPT_WAIT_ALL 0 /*!< Wait for all flags. */
#define OPT_WAIT_ANY 1 /*!< Wait for any one of flags. */
#define OPT_WAIT_ONE 2 /*!< Waot for one flag. */
/*---------------------------- Delete Opreation type ------------------------*/
#define OPT_DEL_NO_PEND 0 /*!< Delete when no task waitting for */
#define OPT_DEL_ANYWAY 1 /*!< Delete always. */
/*---------------------------- Timer Types ----------------------------------*/
#if CFG_TMR_EN >0
#define TMR_TYPE_ONE_SHOT 0 /*!< Timer counter type: One-shot */
#define TMR_TYPE_PERIODIC 1 /*!< Timer counter type: Periodic */
#endif
/*---------------------------- Event Control ---------------------------------*/
#if CFG_EVENT_EN >0
#define EVENT_SORT_TYPE_FIFO (U8)0x01 /*!< Insert a event by FIFO */
#define EVENT_SORT_TYPE_PRIO (U8)0x02 /*!< Insert a event by prio */
#endif
/*---------------------------- Function declare-------------------------------*/
/* Implement in file "core.c" */
extern void CoInitOS(void); /*!< Initialize OS */
extern void CoStartOS(void); /*!< Start multitask */
extern void CoEnterISR(void); /*!< Enter a ISR */
extern void CoExitISR(void); /*!< Exit a ISR */
extern void CoSchedLock(void);
extern void CoSchedUnlock(void);
extern OS_VER CoGetOSVersion(void); /*!< Get OS version value */
/* Implement in file "task.c" */
#define CoCreateTask(task,argv,prio,stk,stkSz) \
CreateTask(task,argv,(prio)|((stkSz)<<8),stk)
#define CoCreateTaskEx(task,argv,prio,stk,stkSz,timeSlice,isWaitting) \
CreateTask(task,argv,(prio)|((stkSz)<<8)|((timeSlice)<<20)|(isWaitting<<31),stk)
extern void CoExitTask(void);
extern OS_TID CoGetCurTaskID(void);
extern StatusType CoDelTask(OS_TID taskID);
extern StatusType CoActivateTask(OS_TID taskID,void *argv);
extern StatusType CoAwakeTask(OS_TID taskID);
extern StatusType CoSuspendTask(OS_TID taskID);
extern StatusType CoSetPriority(OS_TID taskID,U8 priority);
extern OS_TID CreateTask(FUNCPtr task,void *argv,U32 parameter,OS_STK *stk);
/* Implement in file "time.c" */
extern U64 CoGetOSTime(void);
extern StatusType CoTickDelay(U32 ticks);
extern StatusType CoResetTaskDelayTick(OS_TID taskID,U32 ticks);
extern StatusType CoTimeDelay(U8 hour,U8 minute,U8 sec,U16 millsec);
/* Implement in file "timer.c" */
extern StatusType CoDelTmr(OS_TCID tmrID);
extern StatusType CoStopTmr(OS_TCID tmrID);
extern StatusType CoStartTmr(OS_TCID tmrID);
extern U32 CoGetCurTmrCnt(OS_TCID tmrID,StatusType* perr);
extern StatusType CoSetTmrCnt(OS_TCID tmrID,U32 tmrCnt,U32 tmrReload);
extern OS_TCID CoCreateTmr(U8 tmrType, U32 tmrCnt, U32 tmrReload, vFUNCPtr func);
/* Implement in file "kernelHeap.c"*/
extern void* CoKmalloc(U32 size);
extern void CoKfree(void* memBuf);
/* Implement in file "mm.c" */
extern void* CoGetMemoryBuffer(OS_MMID mmID);
extern StatusType CoDelMemoryPartition(OS_MMID mmID);
extern StatusType CoFreeMemoryBuffer(OS_MMID mmID,void* buf);
extern U32 CoGetFreeBlockNum(OS_MMID mmID,StatusType* perr);
extern OS_MMID CoCreateMemPartition(U8* memBuf,U32 blockSize,U32 blockNum);
/* Implement in file "mutex.c" */
extern OS_MutexID CoCreateMutex(void);
extern StatusType CoEnterMutexSection(OS_MutexID mutexID);
extern StatusType CoLeaveMutexSection(OS_MutexID mutexID);
/* Implement in file "sem.c" */
extern StatusType CoPostSem(OS_EventID id);
extern StatusType CoAcceptSem(OS_EventID id);
extern StatusType isr_PostSem(OS_EventID id);
extern StatusType CoDelSem(OS_EventID id,U8 opt);
extern StatusType CoPendSem(OS_EventID id,U32 timeout);
extern OS_EventID CoCreateSem(U16 initCnt,U16 maxCnt,U8 sortType);
/* Implement in file "mbox.c" */
extern OS_EventID CoCreateMbox(U8 sortType);
extern StatusType CoDelMbox(OS_EventID id,U8 opt);
extern StatusType CoPostMail(OS_EventID id,void* pmail);
extern StatusType isr_PostMail(OS_EventID id,void* pmail);
extern void* CoAcceptMail(OS_EventID id,StatusType* perr);
extern void* CoPendMail(OS_EventID id,U32 timeout,StatusType* perr);
/* Implement in file "queue.c" */
extern StatusType CoDelQueue(OS_EventID id,U8 opt);
extern StatusType CoPostQueueMail(OS_EventID id,void* pmail);
extern StatusType isr_PostQueueMail(OS_EventID id,void* pmail);
extern void* CoAcceptQueueMail(OS_EventID id,StatusType* perr);
extern OS_EventID CoCreateQueue(void **qStart, U16 size ,U8 sortType);
extern void* CoPendQueueMail(OS_EventID id,U32 timeout,StatusType* perr);
/* Implement in file "flag.c" */
extern StatusType CoSetFlag (OS_FlagID id);
extern StatusType CoClearFlag (OS_FlagID id);
extern StatusType isr_SetFlag (OS_FlagID id);
extern StatusType CoDelFlag (OS_FlagID id,U8 opt);
extern StatusType CoAcceptSingleFlag (OS_FlagID id);
extern StatusType CoWaitForSingleFlag (OS_FlagID id,U32 timeout);
extern OS_FlagID CoCreateFlag (BOOL bAutoReset,BOOL bInitialState);
extern U32 CoAcceptMultipleFlags (U32 flags,U8 waitType,StatusType *perr);
extern U32 CoWaitForMultipleFlags (U32 flags,U8 waitType,U32 timeout,StatusType *perr);
/* Implement in file "utility.c" */
extern StatusType CoTimeToTick(U8 hour,U8 minute,U8 sec,U16 millsec,U32* ticks);
extern void CoTickToTime(U32 ticks,U8* hour,U8* minute,U8* sec,U16* millsec);
/* Implement in file "hook.c" */
extern void CoIdleTask(void* pdata);
extern void CoStkOverflowHook(OS_TID taskID);
#endif

276
src/CoOS/kernel/OsConfig.h Normal file
View file

@ -0,0 +1,276 @@
/**
*******************************************************************************
* @file config.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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 (72000000)
/*!<
systick frequency (Hz).
*/
#define CFG_SYSTICK_FREQ (100)
/*!<
max systerm api call num in ISR.
*/
#define CFG_MAX_SERVICE_REQUEST (3)
/*!<
Enable(1) or disable(0) order list schedule.
If disable(0),CoOS use Binary-Scheduling Algorithm.
*/
#if (CFG_MAX_USER_TASKS) <15
#define CFG_ORDER_LIST_SCHEDULE_EN (1)
#else
#define CFG_ORDER_LIST_SCHEDULE_EN (0)
#endif
/*!<
Enable(1) or disable(0) Round-Robin Task switching.
*/
#define CFG_ROBIN_EN (1)
/*!<
Default slice of task.
*/
#if CFG_ROBIN_EN > 0
#define CFG_TIME_SLICE (10)
#endif
/*----------------------- Schedule model Config -----------------------------*/
/*!<
Enable(1) or disable(0) all waiting function.
Include sem,mailbox,queue,flag,mutex,delay modules.
If CFG_TASK_WAITTING_EN=0,all these modules are disable.
*/
#define CFG_TASK_WAITTING_EN (1)
/*!<
Dynamic task scheduling(1) or Static Task Scheduling(0) model.
If in Static Task Scheduling model(0),cannot creat task and change task priority
after coocox os start running. In Dynamic Task Scheduling model(1), all these can.
When task terminated, if in Static Task Scheduling model(0),
CoOS do not recovered task resources, and you can activate it again.
But in Dynamic Task Scheduling model(1),task resources will be recovered.
If in Static Task Scheduling model(0),mutex module can not be used, as this model don't
support to change task priority while CoOS running.
*/
#define CFG_TASK_SCHEDULE_EN (1)
/*---------------------- Task Management Config -----------------------------*/
/*!<
Enable(1) or disable(0) CoSetPriority() API.
*/
#if CFG_TASK_SCHEDULE_EN >0
#define CFG_PRIORITY_SET_EN (1)
#endif
/*!<
Enable(1) or disable(0) CoAwakeTask() and CoSuspendTask() API.
*/
#define CFG_TASK_SUSPEND_EN (1)
/*---------------------- Debug Management Config ----------------------------*/
/*!<
Enable(1) or disable(0) parameter checkout .
*/
#define CFG_PAR_CHECKOUT_EN (1)
/*!<
Enable(1) or disable(0) stack overflow checkout .
*/
#define CFG_STK_CHECKOUT_EN (1)
/*---------------------- Memory Management Config ----------------------------*/
/*!<
Enable(1) or disable(0) memory management.
*/
#define CFG_MM_EN (1)
/*!<
Max number of memory.(must be less than 32).
*/
#if CFG_MM_EN >0
#define CFG_MAX_MM (2)
#endif
/*-------------------- Kernel heap Management Config -------------------------*/
/*!<
Enable(1) or disable(0) kernel heap management.
*/
#define CFG_KHEAP_EN (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 (1)
/*!<
Specify max number timer.(must be less than 32)
*/
#if CFG_TMR_EN >0
#define CFG_MAX_TMR (2)
#endif
/*---------------------- Event Management Config ----------------------------*/
/*!<
Enable(1) or disable(0) events management,
events including semaphore,mailbox,queue.
*/
#if CFG_TASK_WAITTING_EN > 0
#define CFG_EVENT_EN (1)
#endif
#if CFG_EVENT_EN > 0
/*!<
Event sort type.(1)FIFO (2)PRI (3)FIFO+PRI
*/
#define CFG_EVENT_SORT (3)
/*!<
Max number of event.(must be less than 255)
Event = semaphore + mailbox + queue;
*/
#define CFG_MAX_EVENT (10)
/*!<
Enable(1) or disable(0) semaphore management.
*/
#define CFG_SEM_EN (1)
/*!<
Enable(1) or disable(0) mailbox management.
*/
#define CFG_MAILBOX_EN (1)
/*!<
Enable(1) or disable(0) queue management.
*/
#define CFG_QUEUE_EN (1)
/*!<
Max number of queue.(less than CFG_MAX_EVENT).
*/
#if CFG_QUEUE_EN >0
#define CFG_MAX_QUEUE (2)
#endif // CFG_QUEUE_EN
#endif // CFG_EVENT_EN
/*----------------------- Flag Management Config ----------------------------*/
/*!<
Enable(1) or disable(0) flag management.
Max number of flag is 32.
*/
#if CFG_TASK_WAITTING_EN > 0
#define CFG_FLAG_EN (1)
#endif
/*---------------------- Mutex Management Config ----------------------------*/
/*!<
Enable(1) or disable(0) mutex management.
*/
#if CFG_TASK_WAITTING_EN > 0
#if CFG_TASK_SCHEDULE_EN > 0
#define CFG_MUTEX_EN (1)
#endif
#endif
/*!<
Max number of mutex.(must be less than 255).
*/
#if CFG_MUTEX_EN >0
#define CFG_MAX_MUTEX (10)
#endif
/*---------------------- Utility Management Config --------------------------*/
/*!<
Enable(1) or disable(0) utility management.
*/
#define CFG_UTILITY_EN (1)
#if CFG_UTILITY_EN >0
/*!<
Enable(1) or disable(0) TickToTime() utility
*/
#define CFG_TICK_TO_TIME_EN (1)
/*!<
Enable(1) or disable(0) TimeToTick() utility
*/
#define CFG_TIME_TO_TICK_EN (1)
#endif
#endif // _CONFIG_H

27
src/CoOS/kernel/OsCore.h Normal file
View file

@ -0,0 +1,27 @@
/**
*******************************************************************************
* @file core.h
* @version V1.12
* @date 2010.03.01
* @brief Header file related to kernel
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; COPYRIGHT 2009 CooCox </center></h2>
*******************************************************************************
*/
#ifndef _CORE_H
#define _CORE_H
#include <CoOS.h>
#define OsSchedLock() OSSchedLock++; /*!< Lock schedule */
extern void OsSchedUnlock(void);
#endif

84
src/CoOS/kernel/OsError.h Normal file
View file

@ -0,0 +1,84 @@
/**
*******************************************************************************
* @file error.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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 */

58
src/CoOS/kernel/OsEvent.h Normal file
View file

@ -0,0 +1,58 @@
/**
*******************************************************************************
* @file event.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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

57
src/CoOS/kernel/OsFlag.h Normal file
View file

@ -0,0 +1,57 @@
/**
*******************************************************************************
* @file flag.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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

View file

@ -0,0 +1,48 @@
/**
*******************************************************************************
* @file kernelHeap.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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 */

41
src/CoOS/kernel/OsMM.h Normal file
View file

@ -0,0 +1,41 @@
/**
*******************************************************************************
* @file mm.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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 */

57
src/CoOS/kernel/OsMutex.h Normal file
View file

@ -0,0 +1,57 @@
/**
*******************************************************************************
* @file mutex.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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 */

39
src/CoOS/kernel/OsQueue.h Normal file
View file

@ -0,0 +1,39 @@
/**
*******************************************************************************
* @file queue.h
* @version V1.12
* @date 2010.03.01
* @brief Queue management header file
* @details This file including some defines and declares about queue management.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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

View file

@ -0,0 +1,51 @@
/**
*******************************************************************************
* @file serviceReq.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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;
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

112
src/CoOS/kernel/OsTask.h Normal file
View file

@ -0,0 +1,112 @@
/**
*******************************************************************************
* @file task.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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 U8 OSIntNesting; /*!< Use to indicate interrupt nesting level. */
extern U8 OSSchedLock; /*!< Schedule is lock(LOCK) or unlock(UN_LOCK). */
extern 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

28
src/CoOS/kernel/OsTime.h Normal file
View file

@ -0,0 +1,28 @@
/**
*******************************************************************************
* @file task.c
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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

49
src/CoOS/kernel/OsTimer.h Normal file
View file

@ -0,0 +1,49 @@
/**
*******************************************************************************
* @file timer.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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

60
src/CoOS/kernel/coocox.h Normal file
View file

@ -0,0 +1,60 @@
/**
*******************************************************************************
* @file coocox.h
* @version V1.12
* @date 2010.03.01
* @brief Gather for all header file of CooCox CoOS.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; COPYRIGHT 2009 CooCox </center></h2>
*******************************************************************************
*/
#ifndef _COOCOX_H
#define _COOCOX_H
#define OS_VERSION (U16)0x0112 /*!< OS version.(format: Vx.xx),
e.g. value 0x0111 is version V1.12*/
/*---------------------------- 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 */

238
src/CoOS/kernel/core.c Normal file
View file

@ -0,0 +1,238 @@
/**
*******************************************************************************
* @file core.c
* @version V1.12
* @date 2010.03.01
* @brief Core implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; COPYRIGHT 2009 CooCox </center></h2>
*******************************************************************************
*/
/*---------------------------- Include ---------------------------------------*/
#include <coocox.h>
/*---------------------------- Variable Define -------------------------------*/
U8 OSIntNesting = 0; /*!< Use to indicate interrupt nesting level*/
U8 OSSchedLock = 0; /*!< Task Switch lock. */
BOOL TaskSchedReq = FALSE;
/**
*******************************************************************************
* @brief Enter a ISR.
* @param[in] None
* @param[out] None
* @retval None
*
* @par Description
* @details This function is called to notify OS when enter to an ISR.
*
* @note When you call API in ISR,you must call CoEnterISR() before your
* interrupt handler code,and call CoExitISR() after your handler
* code and before exiting from ISR.
*******************************************************************************
*/
void CoEnterISR(void)
{
Inc8(&OSIntNesting); /* OSIntNesting increment */
}
/**
*******************************************************************************
* @brief Exit a ISR.
* @param[in] None
* @param[out] None
* @retval None
*
* @par Description
* @details This function is called when exit from a ISR.
*
* @note
*******************************************************************************
*/
void CoExitISR(void)
{
Dec8(&OSIntNesting); /* OSIntNesting decrease */
if( OSIntNesting == 0) /* Is OSIntNesting == 0? */
{
if(TaskSchedReq == TRUE)
{
OSSchedLock++;
Schedule(); /* Call task schedule */
OSSchedLock--;
}
}
}
/**
*******************************************************************************
* @brief Unlock schedule
* @param[in] None
* @param[out] None
* @retval None
*
* @par Description
* @details This function is called to unlock schedule(i.e.enable schedule again)
*
* @note
*******************************************************************************
*/
void OsSchedUnlock(void)
{
if(OSSchedLock == 1) /* Is OSSchedLock == 0? */
{
#if CFG_TASK_WAITTING_EN > 0
if(IsrReq == TRUE)
{
RespondSRQ(); /* Respond service request */
}
#endif
/* Judge task state change or higher PRI task coming in */
if(TaskSchedReq == TRUE)
{
Schedule(); /* Call task schedule */
}
OSSchedLock = 0;
}
else
{
OSSchedLock--;
}
}
/**
*******************************************************************************
* @brief Lock schedule
* @param[in] None
* @param[out] None
* @retval None
*
* @par Description
* @details This function is called in application code to lock schedule.
*
* @note
*******************************************************************************
*/
void CoSchedLock(void)
{
OsSchedLock(); /* Lock schedule */
}
/**
*******************************************************************************
* @brief Unlock schedule
* @param[in] None
* @param[out] None
* @retval None
*
* @par Description
* @details This function is called in APP to unlock schedule.
*
* @note
*******************************************************************************
*/
void CoSchedUnlock(void)
{
OsSchedUnlock(); /* Unlock schedule */
}
/**
*******************************************************************************
* @brief Initialize OS
* @param[in] None
* @param[out] None
* @retval None
*
* @par Description
* @details This function is called to initialize OS.
*
* @note You must call this function first,before any other OS API function
*
* @code There is a example for useage of this function,as follows:
* e.g.
* ... // Your target initial code.
*
* OsInit(); // Initial OS.
* CreateTask(...); // Create tasks.
* ...
* OsStart(); // Start multitask.
* @endcode
*******************************************************************************
*/
void CoInitOS(void)
{
InitSysTick(); /* Initialize system tick. */
InitInt(); /* Initialize PendSV,SVC,SysTick interrupt */
CreateTCBList(); /* Create TCB list. */
#if CFG_EVENT_EN > 0
CreateEventList(); /* Create event control list. */
#endif
#if CFG_KHEAP_EN > 0
CoCreateKheap(); /* Create kernel heap within user define */
#endif
OsSchedLock(); /* Lock Schedule */
/* Create first task -- IDLE task. */
CoCreateTask( CoIdleTask,
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 */
}

410
src/CoOS/kernel/event.c Normal file
View file

@ -0,0 +1,410 @@
/**
*******************************************************************************
* @file event.c
* @version V1.12
* @date 2010.03.01
* @brief event management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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 = NULL; /*!< 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 = 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 = 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.NULL for other
* event type.
* @param[out] None
* @retval 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 == NULL) /* Is there no free evnet item */
{
OsSchedUnlock(); /* Yes,unlock schedule */
return NULL; /* Return error */
}
pecb = FreeEventList;/* Assign the free event item to this event */
FreeEventList = 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 = NULL;
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 != 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 != 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 = NULL; /* 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-->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 == NULL) /* Is no item in event waiting list?*/
{
pecb->eventTCBList = ptcb; /* Yes,set task as first item */
}
else
{
while(ptcb1->waitNext != 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 == 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 != 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 != NULL)
{
ptcb2->waitPrev = ptcb;
}
}
}
#endif
ptcb->state = TASK_WAITING; /* Set task status to TASK_WAITING state */
TaskSchedReq = TRUE;
OsSchedUnlock(); /* Unlock schedule,and call task schedule */
}
/**
*******************************************************************************
* @brief Move a task from event WAITING list to the DELAY list
* @param[in] pecb Pointer to event control block corresponding to the event.
* @param[out] None
* @retval None
*
* @par Description
* @details This function is called to remove a task from event wait list,and
* then insert it into the READY list.
*******************************************************************************
*/
void EventTaskToRdy(P_ECB pecb)
{
P_OSTCB ptcb;
#if CFG_QUEUE_EN >0
P_QCB pqcb;
#endif
ptcb = pecb->eventTCBList;
if(ptcb == NULL)
return;
pecb->eventTCBList = ptcb->waitNext;/* Get first task in event waiting list*/
if(pecb->eventTCBList != NULL) /* Is no item in event waiting list? */
{
pecb->eventTCBList->waitPrev = NULL; /* No,clear link for first item */
}
ptcb->waitNext = NULL; /* 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 = 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 == NULL) && (ptcb->waitPrev == NULL))
{
pecb->eventTCBList = NULL; /* Yes,set event waiting list as NULL */
}
else if(ptcb->waitPrev == NULL)/* Is the first item in event waiting list?*/
{
/* Yes,remove task from list,and reset event waiting list */
ptcb->waitNext->waitPrev = NULL;
pecb->eventTCBList = ptcb->waitNext;
ptcb->waitNext = NULL;
}
else if(ptcb->waitNext == NULL)/* Is the last item in event waiting list? */
{
ptcb->waitPrev->waitNext = NULL; /* Yes,remove task form list */
ptcb->waitPrev = NULL;
}
else /* No, remove task from list */
{
ptcb->waitPrev->waitNext = ptcb->waitNext;
ptcb->waitNext->waitPrev = ptcb->waitPrev;
ptcb->waitPrev = NULL;
ptcb->waitNext = NULL;
}
ptcb->eventID = INVALID_ID; /* Sign that not to use. */
}
#endif //CFG_EVENT_EN

712
src/CoOS/kernel/flag.c Normal file
View file

@ -0,0 +1,712 @@
/**
*******************************************************************************
* @file flag.c
* @version V1.12
* @date 2010.03.01
* @brief Flag management implementation code of coocox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; COPYRIGHT 2009 CooCox </center></h2>
*******************************************************************************
*/
/*---------------------------- Include ---------------------------------------*/
#include <coocox.h>
#if CFG_FLAG_EN > 0
/*---------------------------- Variable Define -------------------------------*/
#define FLAG_MAX_NUM 32 /*!< Define max flag number. */
FCB FlagCrl = {0}; /*!< Flags list struct */
/*---------------------------- Function Declare ------------------------------*/
static void FlagBlock(P_FLAG_NODE pnode,U32 flags,U8 waitType);
static P_FLAG_NODE RemoveFromLink(P_FLAG_NODE pnode);
/**
*******************************************************************************
* @brief Create a flag
* @param[in] bAutoReset Reset mode,TRUE(Auto Reset) FLASE(Manual Reset).
* @param[in] bInitialState Initial state.
* @param[out] None
* @retval E_CREATE_FAIL Create flag fail.
* @retval others Create flag successful.
*
* @par Description
* @details This function use to create a event flag.
* @note
*******************************************************************************
*/
OS_FlagID CoCreateFlag(BOOL bAutoReset,BOOL bInitialState)
{
U8 i;
OsSchedLock();
for(i=0;i<FLAG_MAX_NUM;i++)
{
/* Assign a free flag control block */
if((FlagCrl.flagActive&(1<<i)) == 0 )
{
FlagCrl.flagActive |= (1<<i); /* Initialize active flag */
FlagCrl.flagRdy |= (bInitialState<<i);/* Initialize ready flag */
FlagCrl.resetOpt |= (bAutoReset<<i);/* Initialize reset option */
OsSchedUnlock();
return i ; /* Return Flag ID */
}
}
OsSchedUnlock();
return E_CREATE_FAIL; /* There is no free flag control block*/
}
/**
*******************************************************************************
* @brief Delete a flag
* @param[in] id Flag ID.
* @param[in] opt Delete option.
* @param[out] None
* @retval E_CALL Error call in ISR.
* @retval E_INVALID_ID Invalid event ID.
* @retval E_TASK_WAITTING Tasks waitting for the event,delete fail.
* @retval E_OK Event deleted successful.
*
* @par Description
* @details This function is called to delete a event flag.
* @note
*******************************************************************************
*/
StatusType CoDelFlag(OS_FlagID id,U8 opt)
{
P_FLAG_NODE pnode;
P_FCB pfcb;
pfcb = &FlagCrl;
if(OSIntNesting > 0) /* If be called from ISR */
{
return E_CALL;
}
#if CFG_PAR_CHECKOUT_EN >0
if((pfcb->flagActive&(1<<id)) == 0) /* Flag is valid or not */
{
return E_INVALID_ID;
}
#endif
OsSchedLock();
pnode = pfcb->headNode;
while(pnode != 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 = TRUE;
OsSchedUnlock();
/* The required flag is set and the task is in running state */
curTCB->pnode = 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 == NULL) /* If time-out occurred */
{
return E_TIMEOUT;
}
else /* If flag is set */
{
curTCB->pnode = 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 = TRUE;
OsSchedUnlock();
curTCB->pnode = 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 == NULL) /* If time-out occurred */
{
*perr = E_TIMEOUT;
return 0;
}
else /* If the required flags are set */
{
curTCB->pnode = 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 != 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,NULL) == 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 == NULL) /* If this is the first NODE to insert? */
{
pnode->nextNode = NULL;
pnode->prevNode = NULL;
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 = NULL;
}
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 == NULL) && (pnode->prevNode == NULL))
{
FlagCrl.headNode = NULL;
FlagCrl.tailNode = NULL;
}
else if(pnode->nextNode == NULL) /* If the NODE is tail */
{
FlagCrl.tailNode = pnode->prevNode;
pnode->prevNode->nextNode = NULL;
}
else if(pnode->prevNode == NULL) /* If the NODE is head */
{
FlagCrl.headNode = pnode->nextNode;
pnode->nextNode->prevNode = NULL;
}
else /* The NODE is in the middle */
{
pnode->nextNode->prevNode = pnode->prevNode;
pnode->prevNode->nextNode = pnode->nextNode;
}
pnode->waitTask->pnode = NULL;
}
#endif

65
src/CoOS/kernel/hook.c Normal file
View file

@ -0,0 +1,65 @@
/**
*******************************************************************************
* @file hook.c
* @version V1.12
* @date 2010.03.01
* @brief hook management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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(; ;)
{
}
}

View file

@ -0,0 +1,409 @@
/**
*******************************************************************************
* @file kernelHeap.c
* @version V1.12
* @date 2010.03.01
* @brief kernel heap management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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 = 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 = NULL;
FMBlist->nextUMB = NULL;
FMBlist->preUMB = NULL;
}
/**
*******************************************************************************
* @brief Allocation size bytes of memory block from kernel heap.
* @param[in] size Length of menory block.
* @param[out] None
* @retval 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 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 = NULL;
while(freeMB != NULL ) /* Is out of free memory list? */
{ /* No */
if(freeMB->nextUMB == 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 != 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 != 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 != 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 != 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 != 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 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 == 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 == NULL)
{
OsSchedUnlock();
return;
}
preUMB = (P_UMB)((U32)(preUMB->preMB)-1);
}
}
else
{
if(FMBlist == NULL)
{
nextUMB = (P_UMB)(Kheap.startAddr);
}
else
{
if(FMBlist->nextUMB != NULL)
{
nextUMB = (P_UMB)((U32)(FMBlist->nextUMB)-1);
}
else
{
nextUMB = NULL;
}
}
while(nextUMB != usedMB)
{
if(nextUMB == 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 == NULL) && (usedMB->preMB == NULL))
{
curFMB = (P_FMB)usedMB; /* Yes,release this item */
curFMB->nextFMB = NULL;
curFMB->nextUMB = NULL;
curFMB->preUMB = NULL;
FMBlist = curFMB;
}
else if(usedMB->preMB == 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 = NULL;
FMBlist = curFMB;
}
else if(usedMB->nextMB == NULL) /* Is the last item in kernel heap */
{ /* Yes,release this item,and set link for list */
curFMB = (P_FMB)(usedMB->preMB);
curFMB->nextFMB = NULL;
curFMB->nextUMB = 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 == 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 = 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 == NULL) /* Is previous FMB==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 == NULL) /* Is new FMB as last item of FMB list? */
{
curFMB->preUMB = preUMB; /* Yes,set link for list */
curFMB->nextUMB = NULL;
curFMB->nextFMB = 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 == NULL ) /* Is previous FMB==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 != 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 != 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

322
src/CoOS/kernel/mbox.c Normal file
View file

@ -0,0 +1,322 @@
/**
*******************************************************************************
* @file mbox.c
* @version V1.12
* @date 2010.03.01
* @brief Mailbox management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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,NULL);
if(pecb == 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 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 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 NULL;
}
#endif
OsSchedLock();
if(pecb->eventCounter == 1) /* If there is already a message */
{
*perr = E_OK;
pmail = pecb->eventPtr; /* Get the message */
pecb->eventPtr = 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 NULL */
return 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 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 NULL;
}
#if CFG_PAR_CHECKOUT_EN >0
if(id >= CFG_MAX_EVENT)
{
*perr = E_INVALID_ID; /* Invalid 'id',retrun error */
return 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 NULL;
}
#endif
if(OSSchedLock != 0) /* Judge schedule is locked or not? */
{
*perr = E_OS_IN_LOCK; /* Schedule is locked */
return NULL; /* return NULL */
}
if( pecb->eventCounter == 1) /* If there is already a message */
{
*perr = E_OK;
pmail = pecb->eventPtr; /* Get the message */
pecb->eventPtr = NULL; /* Clear the mailbox */
pecb->eventCounter = 0;
return pmail; /* Return the message received */
}
else /* If message is not available, task will pend */
{
curTCB = TCBRunning;
if(timeout == 0) /* If time-out is not configured */
{
EventTaskToWait(pecb,curTCB); /* Block task until event occurs */
*perr = E_OK;
/* Have recived a message or the mailbox have been deleted */
pmail = curTCB->pmail;
curTCB->pmail = NULL;
return pmail; /* Return received message or 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 == NULL) /* Time-out occurred */
{
*perr = E_TIMEOUT;
return NULL;
}
else /* Have recived a message or the mailbox have been deleted*/
{
*perr = E_OK;
pmail = curTCB->pmail;
curTCB->pmail = NULL;
return pmail; /* Return received message or 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) == 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

275
src/CoOS/kernel/mm.c Normal file
View file

@ -0,0 +1,275 @@
/**
*******************************************************************************
* @file mm.c
* @version V1.12
* @date 2010.03.01
* @brief memory management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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 == 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 = 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 = NULL;
memCtl->freeBlock = 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 != 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 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 NULL;
}
if( ((1<<mmID)&MemoryIDVessel) == 0)
{
return NULL;
}
#endif
memCtl = &MemoryTbl[mmID];
OsSchedLock(); /* Lock schedule */
if(memCtl->freeBlock == NULL ) /* Is there no free item in memory list */
{
OsSchedUnlock(); /* Unlock schedule */
return 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 == 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

349
src/CoOS/kernel/mutex.c Normal file
View file

@ -0,0 +1,349 @@
/**
*******************************************************************************
* @file mutex.c
* @version V1.12
* @date 2010.03.01
* @brief Mutex management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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 = NULL;
return id; /* Return mutex ID */
}
OsSchedUnlock();
return E_CREATE_FAIL; /* No free mutex control block */
}
/**
*******************************************************************************
* @brief Enter a critical area
* @param[in] mutexID Specify mutex.
* @param[out] None
* @retval E_INVALID_ID Invalid mutex id.
* @retval E_CALL Error call in ISR.
* @retval E_OK Enter critical area successful.
*
* @par Description
* @details This function is called when entering a critical area.
* @note
*******************************************************************************
*/
StatusType CoEnterMutexSection(OS_MutexID mutexID)
{
P_OSTCB ptcb,pCurTcb;
P_MUTEX pMutex;
#if CFG_EVENT_EN >0
P_ECB pecb;
#endif
if(OSIntNesting > 0) /* If the caller is ISR */
{
return E_CALL;
}
if(OSSchedLock != 0) /* Is OS lock? */
{
return E_OS_IN_LOCK; /* Yes,error return */
}
#if CFG_PAR_CHECKOUT_EN >0
if(mutexID >= MutexFreeID) /* Invalid 'mutexID' */
{
return E_INVALID_ID;
}
#endif
OsSchedLock();
pCurTcb = TCBRunning;
pMutex = &MutexTbl[mutexID];
pCurTcb->mutexID = mutexID;
if(pMutex->mutexFlag == MUTEX_FREE) /* If mutex is available */
{
pMutex->originalPrio = pCurTcb->prio; /* Save priority of owning task */
pMutex->taskID = pCurTcb->taskID; /* Acquire the resource */
pMutex->hipriTaskID = pCurTcb->taskID;
pMutex->mutexFlag = MUTEX_OCCUPY; /* Occupy the mutex resource*/
}
/* If the mutex resource had been occupied */
else if(pMutex->mutexFlag == MUTEX_OCCUPY)
{
ptcb = &TCBTbl[pMutex->taskID];
if(ptcb->prio > pCurTcb->prio) /* Need to promote priority of owner? */
{
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
DeleteTaskPri(ptcb->prio);
ActiveTaskPri(pCurTcb->prio);
#endif
ptcb->prio = pCurTcb->prio; /* Promote prio of owner */
/* Upgarde the highest priority about the mutex */
pMutex->hipriTaskID = pCurTcb->taskID;
if(ptcb->state == TASK_READY) /* If the task is ready to run */
{
RemoveFromTCBRdyList(ptcb); /* Remove the task from READY list*/
InsertToTCBRdyList(ptcb); /* Insert the task into READY list*/
}
#if CFG_EVENT_EN >0
/* If the task is waiting on a event */
else if(ptcb->eventID != INVALID_ID)
{
pecb = &EventTbl[ptcb->eventID];
/* If the event waiting type is preemptive Priority */
if(pecb->eventSortType == EVENT_SORT_TYPE_PRIO)
{
/* Remove the task from event waiting list */
RemoveEventWaittingList(ptcb);
/* Insert the task into event waiting list */
EventTaskToWait(pecb,ptcb);
}
}
#endif
}
pCurTcb->state = TASK_WAITING; /* Block current task */
TaskSchedReq = TRUE;
pCurTcb->TCBnext = NULL;
pCurTcb->TCBprev = NULL;
ptcb = pMutex->waittingList;
if(ptcb == NULL) /* 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 != NULL) /* Insert the task to tail */
{
ptcb = ptcb->TCBnext;
}
ptcb->TCBnext = pCurTcb;
pCurTcb->TCBprev = ptcb;
pCurTcb->TCBnext = NULL;
}
}
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 == NULL) /* 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 != NULL) /* 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 = NULL;
ptcb->TCBprev = NULL;
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 ==NULL) && (ptcb->TCBprev == NULL))
{
pMutex->waittingList = NULL; /* Waiting list is empty */
}
else if(ptcb->TCBnext == NULL) /* If the task is the last of waiting list*/
{
/* Remove task from mutex waiting list */
ptcb->TCBprev->TCBnext = NULL;
ptcb->TCBprev = NULL;
}
else if(ptcb->TCBprev == NULL)/* If the task is the first of waiting list*/
{
/* Remove task from waiting list */
ptcb->TCBnext->TCBprev = NULL;
ptcb->TCBnext = NULL;
}
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 = NULL;
ptcb->TCBnext = NULL;
}
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 != NULL) /* 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

391
src/CoOS/kernel/queue.c Normal file
View file

@ -0,0 +1,391 @@
/**
*******************************************************************************
* @file queue.c
* @version V1.12
* @date 2010.03.01
* @brief Queue management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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 == 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 == 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 = 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 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 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 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 NULL; /* Return 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 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 NULL;
}
#if CFG_PAR_CHECKOUT_EN >0
if(id >= CFG_MAX_EVENT)
{
*perr = E_INVALID_ID; /* Invalid event id,return error */
return 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 NULL;
}
#endif
if(OSSchedLock != 0) /* Judge schedule is locked or not? */
{
*perr = E_OS_IN_LOCK; /* Schedule is locked,return error */
return NULL;
}
pqcb = (P_QCB)pecb->eventPtr; /* Point at queue control block */
if(pqcb->qSize != 0) /* If there are any messages in the queue */
{
/* Extract oldest message from the queue */
pmail = *(pqcb->qStart + pqcb->head);
pqcb->head++; /* Update the queue head */
pqcb->qSize--; /* Update the number of messages in the queue */
if(pqcb->head == pqcb->qMaxSize)/* Check queue head */
{
pqcb->head = 0;
}
*perr = E_OK;
return pmail; /* Return message received */
}
else /* If there is no message in the queue*/
{
curTCB = TCBRunning;
if(timeout == 0) /* If time-out is not configured */
{
/* Block current task until the event occur */
EventTaskToWait(pecb,curTCB);
/* Have recived message or the queue have been deleted */
pmail = curTCB->pmail;
curTCB->pmail = NULL;
*perr = E_OK;
return pmail; /* Return message received or 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 == NULL) /* If time-out occurred */
{
*perr = E_TIMEOUT;
return NULL;
}
else /* If event occured */
{
pmail = curTCB->pmail;
curTCB->pmail = NULL;
*perr = E_OK;
return pmail; /* Return message received or 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) == 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

319
src/CoOS/kernel/sem.c Normal file
View file

@ -0,0 +1,319 @@
/**
*******************************************************************************
* @file sem.c
* @version V1.12
* @date 2010.03.01
* @brief Semaphore management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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,NULL);
if(pecb == 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 */
}
if(pecb->eventCounter > 0) /* If semaphore is positive,resource available */
{
pecb->eventCounter--; /* Decrement semaphore only if positive */
return E_OK;
}
else /* Resource is not available */
{
curTCB = TCBRunning;
if(timeout == 0) /* If time-out is not configured */
{
EventTaskToWait(pecb,curTCB); /* Block task until event occurs */
curTCB->pmail = 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 == NULL) /* If pmail is NULL, time-out occurred*/
{
return E_TIMEOUT;
}
else /* Event occurred or event have been deleted*/
{
curTCB->pmail = 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,NULL) == 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

View file

@ -0,0 +1,147 @@
/**
*******************************************************************************
* @file serviceReq.c
* @version V1.12
* @date 2010.03.01
* @brief servive request management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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}; /*!< ISR server request queue */
#endif
BOOL IsrReq = FALSE;
#if (CFG_TASK_WAITTING_EN > 0)
BOOL TimeReq = FALSE; /*!< Time delay dispose request */
#endif
#if CFG_TMR_EN > 0
BOOL TimerReq = FALSE; /*!< Timer dispose request */
#endif
/**
*******************************************************************************
* @brief Insert into service requst queue
* @param[in] type Service request type.
* @param[in] id Service request event id,event id/flag id.
* @param[in] arg Service request argument.
* @param[out] None
*
* @retval FALSE Successfully insert into service request queue.
* @retval TRUE Failure to insert into service request queue.
*
* @par Description
* @details This function be called to insert a requst into service request
* queue.
* @note
*******************************************************************************
*/
#if CFG_MAX_SERVICE_REQUEST > 0
BOOL InsertInSRQ(U8 type,U8 id,void* arg)
{
U16 cnt;
P_SQC pcell;
cnt = Inc8(&ServiceReq.cnt); /* Service request counter decrease */
if(cnt >= CFG_MAX_SERVICE_REQUEST) /* If counter exceed max */
{
return FALSE; /* Error return */
}
IsrReq = TRUE;
pcell = &ServiceReq.cell[cnt]; /* Save service request type and parameter */
pcell->type = type;
pcell->id = id;
pcell->arg = arg;
return TRUE; /* Return OK */
}
#endif
/**
*******************************************************************************
* @brief Respond the request in the service request queue.
* @param[in] None
* @param[out] None
* @retval None
*
* @par Description
* @details This function be called to respond the request in the service
* request queue.
* @note
*******************************************************************************
*/
void RespondSRQ(void)
{
#if CFG_MAX_SERVICE_REQUEST > 0
U16 i;
P_SQC pcell;
#endif
#if (CFG_TASK_WAITTING_EN > 0)
if(TimeReq == TRUE) /* Time delay request? */
{
TimeDispose(); /* Yes,call handler */
TimeReq = FALSE; /* Reset time delay request false */
}
#endif
#if CFG_TMR_EN > 0
if(TimerReq == TRUE) /* Timer request? */
{
TmrDispose(); /* Yes,call handler */
TimerReq = FALSE; /* Reset timer request false */
}
#endif
#if CFG_MAX_SERVICE_REQUEST > 0
pcell = &ServiceReq.cell[0]; /* Get the head item of service request list*/
for(i=0;i<ServiceReq.cnt;i++,pcell++)
{
switch(pcell->type) /* Judge service request type */
{
#if CFG_SEM_EN > 0
case SEM_REQ: /* Semaphore post request,call handler*/
CoPostSem(pcell->id);
break;
#endif
#if CFG_MAILBOX_EN > 0
case MBOX_REQ: /* Mailbox post request,call handler */
CoPostMail(pcell->id,pcell->arg);
break;
#endif
#if CFG_FLAG_EN > 0
case FLAG_REQ: /* Flag set request,call handler */
CoSetFlag(pcell->id);
break;
#endif
#if CFG_QUEUE_EN > 0
case QUEUE_REQ: /* Queue post request,call handler */
CoPostQueueMail(pcell->id,pcell->arg);
break;
#endif
default: /* Others,break */
break;
}
pcell->type = 0; /* Initialize the service request cell*/
pcell->id = 0;
pcell->arg = 0;
}
ServiceReq.cnt = 0; /* Initialize the service request queue */
#endif
IsrReq = FALSE;
}
#endif

1260
src/CoOS/kernel/task.c Normal file

File diff suppressed because it is too large Load diff

376
src/CoOS/kernel/time.c Normal file
View file

@ -0,0 +1,376 @@
/**
*******************************************************************************
* @file time.c
* @version V1.12
* @date 2010.03.01
* @brief time management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; COPYRIGHT 2009 CooCox </center></h2>
*******************************************************************************
*/
/*---------------------------- Include ---------------------------------------*/
#include <coocox.h>
#if CFG_TASK_WAITTING_EN > 0
/*---------------------------- Variable Define -------------------------------*/
P_OSTCB DlyList = NULL; /*!< 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 == NULL) /* 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 != NULL)
{
/* Get delta ticks with previous item */
deltaTicks -= dlyNext->delayTick;
if(deltaTicks < 0) /* Is delta ticks<0? */
{
/* Yes,get correct place */
if(dlyNext->TCBprev != NULL) /* 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 == NULL) )
{
ptcb->TCBprev = dlyNext; /* Yes,insert into */
dlyNext->TCBnext = ptcb;
ptcb->delayTick = deltaTicks;
break;
}
dlyNext = dlyNext->TCBnext; /* Get the next item in DELAY list */
}
}
ptcb->state = TASK_WAITING; /* Set task status as TASK_WAITING */
TaskSchedReq = TRUE;
}
/**
*******************************************************************************
* @brief Remove from the DELAY list
* @param[in] ptcb Task that want to remove from the DELAY list.
* @param[out] None
* @retval None
*
* @par Description
* @details This function is called to remove task from the DELAY list.
*******************************************************************************
*/
void RemoveDelayList(P_OSTCB ptcb)
{
/* Is there only one item in the DELAY list? */
if((ptcb->TCBprev == NULL) && ( ptcb->TCBnext == NULL))
{
DlyList = NULL; /* Yes,set DELAY list as NULL */
}
else if(ptcb->TCBprev == NULL) /* 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 = NULL;
ptcb->TCBnext = NULL;
}
else if(ptcb->TCBnext == NULL) /* Is the last item in DELAY list? */
{
ptcb->TCBprev->TCBnext = NULL; /* Yes,remove task form DELAY list */
ptcb->TCBprev = NULL;
}
else /* No, remove task from DELAY list */
{
ptcb->TCBprev->TCBnext = ptcb->TCBnext;
ptcb->TCBnext->TCBprev = ptcb->TCBprev;
ptcb->TCBnext->delayTick += ptcb->delayTick;
ptcb->TCBnext = NULL;
ptcb->TCBprev = NULL;
}
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 == 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 != NULL) && (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 != NULL) /* Is task in flag waiting list? */
{
RemoveLinkNode(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 = NULL;
InsertToTCBRdyList(dlyList); /* Insert task into READY list */
dlyList = DlyList; /* Get the first item of DELAY list */
if(dlyList != NULL) /* Is DELAY list as NULL? */
{
dlyList->TCBprev = NULL; /* No,initialize the first item */
}
}
}
/**
*******************************************************************************
* @brief Dispose time delay in ISR
* @param[in] None
* @param[out] None
* @retval None
*
* @par Description
* @details This function is called in systick interrupt to dispose time delay
* of all task.
*******************************************************************************
*/
void isr_TimeDispose(void)
{
if(OSSchedLock > 1) /* Is schedule lock? */
{
IsrReq = TRUE;
TimeReq = TRUE; /* Yes,set time request true */
}
else
{
TimeDispose(); /* No,call handler */
}
}
#endif

447
src/CoOS/kernel/timer.c Normal file
View file

@ -0,0 +1,447 @@
/**
*******************************************************************************
* @file timer.c
* @version V1.12
* @date 2010.03.01
* @brief timer management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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 = 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 == 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 != NULL)
{
deltaTicks -= pTmr->tmrCnt; /* Get ticks with previous item */
if(deltaTicks < 0) /* Is delta ticks<0? */
{
/* Yes,get correct place */
if(pTmr->tmrPrev!= 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 == 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 == NULL) && (pTmr->tmrNext == NULL))
{
TmrList = NULL; /* Yes,set timer list as NULL */
}
else if(pTmr->tmrPrev == NULL) /* Is the first item in timer list? */
{ /* Yes,remove timer from list,and reset timer list */
TmrList = pTmr->tmrNext;
TmrList->tmrPrev = NULL;
pTmr->tmrNext->tmrCnt += pTmr->tmrCnt;
pTmr->tmrNext = NULL;
}
else if(pTmr->tmrNext == NULL) /* Is the last item in timer list? */
{
/* Yes,remove timer form list */
pTmr->tmrPrev->tmrNext = NULL;
pTmr->tmrPrev = NULL;
}
else /* No, remove timer from list */
{
pTmr->tmrPrev->tmrNext = pTmr->tmrNext;
pTmr->tmrNext->tmrPrev = pTmr->tmrPrev;
pTmr->tmrNext->tmrCnt += pTmr->tmrCnt;
pTmr->tmrNext = NULL;
pTmr->tmrPrev = 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 == 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 = NULL;
TmrTbl[i].tmrNext = 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 != 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 = TRUE;
TimerReq = TRUE; /* Yes,set timer request true */
}
else
{
TmrDispose(); /* No,call handler */
}
}
#endif

86
src/CoOS/kernel/utility.c Normal file
View file

@ -0,0 +1,86 @@
/**
*******************************************************************************
* @file utility.c
* @version V1.12
* @date 2010.03.01
* @brief Utility management implementation code of CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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 */

39
src/CoOS/kernel/utility.h Normal file
View file

@ -0,0 +1,39 @@
/**
*******************************************************************************
* @file utility.h
* @version V1.00 Initial version
* @date 2009.06.26
* @brief Utility function header file
* @details This file including some defines and declares related to utility
* function.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; 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

View file

@ -0,0 +1,251 @@
/**
*******************************************************************************
* @file prot.c
* @version V1.12
* @date 2010.03.01
* @brief Compiler adapter for CooCox CoOS kernel.
*******************************************************************************
* @copy
*
* INTERNAL FILE,DON'T PUBLIC.
*
* <h2><center>&copy; COPYRIGHT 2010 CooCox </center></h2>
*******************************************************************************
*/
/*---------------------------- Include ---------------------------------------*/
#include "coocox.h"
//******************************************************************************
// EQUATES
//******************************************************************************
U32 NVIC_INT_CTRL = 0xE000ED04; // Interrupt control state register
U32 NVIC_PENDSVSET = 0x10000000; // Value to trigger PendSV exception
U32 INT_EXIT = 0xFFFFFFFC;
//******************************************************************************
// PUBLIC FUNCTIONS
//******************************************************************************
extern U8 Inc8(U8 *data) ;
extern U8 Dec8(U8 *data) ;
extern void SetEnvironment(OS_STK *pstk) __attribute__ ((naked));
extern void SwitchContext(void) __attribute__ ((naked));
extern void PendSV_Handler(void) __attribute__ ((naked));
/**
******************************************************************************
* @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.
******************************************************************************
*/
U8 Inc8 (U8 *data)
{
register U8 result = 0;
__asm volatile
(
" PUSH {R1} \n"
" CPSID I \n"
" LDRB R1,[%1] \n"
" ADD R1,#1 \n"
" STRB R1,[%1] \n"
" CPSIE I \n"
" SUB R1,#0x1 \n"
" MOVS %0,R1 \n"
" POP {R1} \n"
:"=r"(result)
:"r"(data)
);
return (result);
}
/**
******************************************************************************
* @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.
******************************************************************************
*/
U8 Dec8 (U8 *data)
{
register U8 result = 0;
__asm volatile
(
" PUSH {R1} \n"
" CPSID I \n"
" LDRB R1,[%1] \n"
" SUB R1,#1 \n"
" STRB R1,[%1] \n"
" CPSIE I \n"
" MOVS %0,R1 \n"
" POP {R1} \n"
:"=r"(result)
:"r"(data)
);
return (result);
}
/**
******************************************************************************
* @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.
******************************************************************************
*/
void SetEnvironment (OS_STK *pstk)
{
__asm volatile
(
" SUB R0,#28 \n"
" MSR PSP,R0 \n"
" BX LR \n"
);
}
/**
******************************************************************************
* @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
******************************************************************************
*/
void SwitchContext(void)
{
__asm volatile
(
" LDR R3,=NVIC_INT_CTRL \n"
" LDR R3,[R3] \n"
" LDR R2,=NVIC_PENDSVSET \n"
" LDR R1,[R2] \n"
" STR R1, [R3] \n"
" BX LR \n"
);
}
/**
******************************************************************************
* @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
void PendSV_Handler(void)
{
__asm volatile
(
" LDR R3,=TCBRunning \n"
" LDR R1,[R3] \n" // R1 == running tcb
" LDR R2,=TCBNext \n"
" LDR R2,[R2] \n" // R2 == next tcb
" CMP R1,R2 \n"
" BEQ exitPendSV \n"
" MRS R0, PSP \n" // Get PSP point (can not use PUSH,in ISR,SP is MSP )
" SUB R0,R0,#32 \n"
" STR R0,[R1] \n" // 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} \n" // Save old context (R4-R7)
" MOV R4,R8 \n"
" MOV R5,R9 \n"
" MOV R6,R10 \n"
" MOV R7,R11 \n"
" STMIA R0!,{R4-R7} \n" // Save old context (R8-R11)
" popStk: \n"
" STR R2, [R3] \n" // TCBRunning = TCBNext;
" LDR R0, [R2] \n" // Get SP of task that be switch into.
" ADD R0,R0,#16 \n"
" LDMIA R0!,{R4-R7} \n" // Restore new Context (R8-R11)
" MOV R8,R4 \n"
" MOV R9,R5 \n"
" MOV R10,R6 \n"
" MOV R11,R7 \n"
" SUB R0,R0,#32 \n"
" LDMIA R0!,{R4-R7} \n" // Restore new Context (R4-R7)
" ADD R0,R0,#16 \n"
" MSR PSP, R0 \n" // Mov new stack point to PSP
" exitPendSV: \n"
" LDR R3,=OSSchedLock \n"
" MOV R0, #0x0 \n"
" STRB R0, [R3] \n"
" LDR R3,=INT_EXIT \n"
" LDR R0, [R3] \n"
" BX R0 \n" // Exit interrupt
);
}
#endif
#if CFG_CHIP_TYPE == 1
void PendSV_Handler(void)
{
////////debug block /////////////////////////
__asm volatile
(
" LDR R3,=TCBRunning \n"
" LDR R1,[R3] \n" // R1 == running tcb
" LDR R2,=TCBNext \n"
" LDR R2,[R2] \n" // R2 == next tcb
" CMP R1,R2 \n"
" BEQ exitPendSV \n"
" MRS R0, PSP \n" // Get PSP point (can not use PUSH,in ISR,SP is MSP )
" STMDB R0!,{R4-R11} \n" // Store r4-r11,r0 -= regCnt * 4,r0 is new stack
// top point (addr h->l r11,r10,...,r5,r4)
" STR R0,[R1] \n" // Save orig PSP
" STR R2, [R3] \n" // TCBRunning = TCBNext;
" LDR R0, [R2] \n" // Get SP of task that be switch into.
" LDMIA R0!,{R4-R11} \n" // POP {R4-R11},R0 += regCnt * 4
" MSR PSP, R0 \n" // Mov new stack point to PSP
" exitPendSV: \n"
" LDR R3,=OSSchedLock\n"
" MOVS R0, #0x0 \n"
" STRB R0, [R3] \n"
" ORR LR,LR,#0x04 \n" // Ensure exception return uses process stack
" BX LR \n" // Exit interrupt
);
}
#endif

View file

@ -0,0 +1,48 @@
/**
*******************************************************************************
* @file cpu.h
* @version V1.12
* @date 2010.03.01
* @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>&copy; 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 (U8 *data);
extern U8 Dec8 (U8 *data);
#endif

96
src/CoOS/portable/arch.c Normal file
View file

@ -0,0 +1,96 @@
/**
*******************************************************************************
* @file cpu.c
* @version V1.12
* @date 2010.03.01
* @brief This file provides InitTaskContext() and SysTick_Handler().
*******************************************************************************
* @copy
* WRITE COPY INFORMATION USE CAPITAL LETTER
*
* <h2><center>&copy; 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.
*******************************************************************************
*/
void SysTick_Handler(void)
{
OSSchedLock++; /* Lock scheduler. */
OSTickCnt++; /* Increment systerm time. */
#if CFG_TASK_WAITTING_EN >0
if(DlyList != 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 != 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 = TRUE;
OsSchedUnlock();
}

View file

@ -172,6 +172,7 @@ ifeq ($(PCB), ARM)
endif endif
CC = $(TRGT)gcc CC = $(TRGT)gcc
AS = $(TRGT)as
OBJCOPY = $(TRGT)objcopy OBJCOPY = $(TRGT)objcopy
OBJDUMP = $(TRGT)objdump OBJDUMP = $(TRGT)objdump
SIZE = $(TRGT)size SIZE = $(TRGT)size
@ -321,7 +322,7 @@ ifeq ($(PCB), ARM)
# V4 ARM, so ... # V4 ARM, so ...
OPT = 2 OPT = 2
CPPDEFS += -DPCBARM -DAUDIO -DHAPTIC -DPXX -DDSM2 -DDSM2_PPM CPPDEFS += -DPCBARM -DAUDIO -DHAPTIC -DPXX -DDSM2 -DDSM2_PPM
EXTRAINCDIRS += ersky9x FreeRTOSV7.1.1/Source/include FreeRTOSV7.1.1/Source/portable/IAR/ARM_CM3 EXTRAINCDIRS += ersky9x CoOS/kernel CoOS/portable # FreeRTOSV7.1.1/Source/include FreeRTOSV7.1.1/Source/portable/GCC/ARM_CM3
BOARDSRC = board_ersky9x.cpp BOARDSRC = board_ersky9x.cpp
EXTRABOARDSRC = ersky9x/core_cm3.c ersky9x/board_lowlevel.c ersky9x/crt.c ersky9x/vectors_sam3s.c EXTRABOARDSRC = ersky9x/core_cm3.c ersky9x/board_lowlevel.c ersky9x/crt.c ersky9x/vectors_sam3s.c
CPPSRC += ersky9x/ff.cpp ersky9x/diskio.cpp ersky9x/gtime.cpp CPPSRC += ersky9x/ff.cpp ersky9x/diskio.cpp ersky9x/gtime.cpp
@ -680,9 +681,29 @@ ifeq ($(PCB), ARM)
#$(CC) $(ALL_CPPFLAGS) FreeRTOSV7.1.1/Source/queue.c -o queue.o #$(CC) $(ALL_CPPFLAGS) FreeRTOSV7.1.1/Source/queue.c -o queue.o
#$(CC) $(ALL_CPPFLAGS) FreeRTOSV7.1.1/Source/tasks.c -o tasks.o #$(CC) $(ALL_CPPFLAGS) FreeRTOSV7.1.1/Source/tasks.c -o tasks.o
#$(CC) $(ALL_CPPFLAGS) FreeRTOSV7.1.1/Source/timers.c -o timers.o #$(CC) $(ALL_CPPFLAGS) FreeRTOSV7.1.1/Source/timers.c -o timers.o
#$(CC) $(ALL_CPPFLAGS) FreeRTOSV7.1.1/Source/portable/GCC/ARM_CM3_MPU/port.c -o port.o #$(CC) $(ALL_CPPFLAGS) FreeRTOSV7.1.1/Source/portable/GCC/ARM_CM3/port.c -o port.o
#$(CC) $(ALL_CPPFLAGS) FreeRTOSV7.1.1/Source/portable/IAR/ARM_CM3/port.c -o port.o
#$(AS) FreeRTOSV7.1.1/Source/portable/IAR/ARM_CM3/portasm.s -o portasm.o
#$(CC) $(ALL_CPPFLAGS) FreeRTOSV7.1.1/Source/portable/MemMang/heap_2.c -o heap.o
#$(CC) $(ALL_CPPFLAGS) syscalls.c -o syscalls.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/core.c -o core.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/hook.c -o hook.o
#$(CC) $(ALL_CPPFLAGS) CoOS/kernel/kernelHeap.c -o kernelHeap.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/task.c -o task.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/mutex.c -o mutex.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/sem.c -o sem.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/queue.c -o queue.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/mbox.c -o mbox.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/flag.c -o flag.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/event.c -o event.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/time.c -o time.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/timer.c -o timer.o
$(CC) $(ALL_CPPFLAGS) CoOS/kernel/serviceReq.c -o serviceReq.o
$(CC) $(ALL_CPPFLAGS) CoOS/portable/GCC/port.c -o port.o
$(CC) $(ALL_CPPFLAGS) CoOS/portable/arch.c -o arch.o
$(CC) $(ALL_CPPFLAGS) $< -o allsrc.o $(CC) $(ALL_CPPFLAGS) $< -o allsrc.o
$(CC) allsrc.o -mcpu=cortex-m3 -mthumb -nostartfiles -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref,--no-warn-mismatch -o $@ #$(CC) allsrc.o list.o queue.o tasks.o timers.o port.o heap.o syscalls.o -mcpu=cortex-m3 -mthumb -nostartfiles -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref,--no-warn-mismatch -o $@
$(CC) allsrc.o core.o hook.o task.o mutex.o sem.o queue.o mbox.o flag.o event.o time.o timer.o serviceReq.o port.o arch.o -mcpu=cortex-m3 -mthumb -nostartfiles -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref,--no-warn-mismatch -o $@
else else
%.elf: allsrc.cpp %.elf: allsrc.cpp
@echo @echo

View file

@ -31,6 +31,9 @@
* *
*/ */
extern "C" {
#include <CoOS.h>
}
#include "open9x.h" #include "open9x.h"
#if defined(SPLASH) #if defined(SPLASH)
@ -2653,6 +2656,66 @@ uint16_t stack_free()
#endif #endif
OS_STK uartprintf_stk[1024];
extern "C" {
void vMainTask(void *) {
alert("START", "START");
while(1) {
#if defined(PCBARM)
uint16_t t0 = getTmr2MHz();
#else
uint16_t t0 = getTmr16KHz();
#endif
if (g_eeGeneral.filterInput == e_adc_filtered) {
getADC_filt() ;
}
else if ( g_eeGeneral.filterInput == e_adc_osmp) {
getADC_osmp() ;
}
else {
getADC_single() ;
}
#if defined(PCBARM) && defined(REVB)
Current_analogue = ( Current_analogue * 31 + s_anaFilt[8] ) >> 5 ;
#elif defined(PCBV4)
// For PCB V4, use our own 1.2V, external reference (connected to ADC3)
ADCSRB &= ~(1<<MUX5);
ADMUX = 0x03|ADC_VREF_TYPE; // Switch MUX to internal reference
#elif defined(PCBSTD)
ADMUX = 0x1E|ADC_VREF_TYPE; // Switch MUX to internal reference
#endif
perMain();
// Bandgap has had plenty of time to settle...
#if not defined(PCBARM)
getADC_bandgap();
#endif
if(heartbeat == 0x3)
{
wdt_reset();
heartbeat = 0;
}
#if defined(PCBARM)
t0 = getTmr2MHz() - t0;
#else
t0 = getTmr16KHz() - t0;
#endif
if (t0 > g_timeMain) g_timeMain = t0 ;
}
}
}
OS_TID uartprintfTask;
int main(void) int main(void)
{ {
// The WDT remains active after a WDT reset -- at maximum clock speed. So it's // The WDT remains active after a WDT reset -- at maximum clock speed. So it's
@ -2786,7 +2849,7 @@ int main(void)
startPulses(); startPulses();
if (check_soft_power() <= e_power_trainer) { if (check_soft_power() <= e_power_trainer) {
wdt_enable(WDTO_500MS); // wdt_enable(WDTO_500MS);
} }
#if defined(PCBARM) #if defined(PCBARM)
@ -2794,58 +2857,17 @@ int main(void)
#elif defined(PCBV4) #elif defined(PCBV4)
uint8_t shutdown_state = 0; uint8_t shutdown_state = 0;
#endif #endif
if ((shutdown_state=check_soft_power()) <= e_power_trainer) {
while(1) { alert("COOS", "START");
#if defined(PCBARM) || defined(PCBV4) CoInitOS();
if ((shutdown_state=check_soft_power()) > e_power_trainer) alert("COOS", "INIT");
break; //xTaskHandle taskHandle;
#endif //xTaskCreate ((pdTASK_CODE)&vMainTask, (const signed portCHAR * const) "Main", 2048, NULL, (tskIDLE_PRIORITY + 1), &taskHandle);
//vTaskStartScheduler ();
#if defined(PCBARM) uartprintfTask = CoCreateTask(vMainTask,NULL,0,&uartprintf_stk[1023],100);
uint16_t t0 = getTmr2MHz(); alert("COOS", "TASK");
#else CoStartOS();
uint16_t t0 = getTmr16KHz(); alert("COOS", "FIN");
#endif
if (g_eeGeneral.filterInput == e_adc_filtered) {
getADC_filt() ;
}
else if ( g_eeGeneral.filterInput == e_adc_osmp) {
getADC_osmp() ;
}
else {
getADC_single() ;
}
#if defined(PCBARM) && defined(REVB)
Current_analogue = ( Current_analogue * 31 + s_anaFilt[8] ) >> 5 ;
#elif defined(PCBV4)
// For PCB V4, use our own 1.2V, external reference (connected to ADC3)
ADCSRB &= ~(1<<MUX5);
ADMUX = 0x03|ADC_VREF_TYPE; // Switch MUX to internal reference
#elif defined(PCBSTD)
ADMUX = 0x1E|ADC_VREF_TYPE; // Switch MUX to internal reference
#endif
perMain();
// Bandgap has had plenty of time to settle...
#if not defined(PCBARM)
getADC_bandgap();
#endif
if(heartbeat == 0x3)
{
wdt_reset();
heartbeat = 0;
}
#if defined(PCBARM)
t0 = getTmr2MHz() - t0;
#else
t0 = getTmr16KHz() - t0;
#endif
if (t0 > g_timeMain) g_timeMain = t0 ;
} }
#if defined(PCBARM) || defined(PCBV4) #if defined(PCBARM) || defined(PCBV4)