Merge pull request #59 from victorpv/RTOS
CoOS 1.12 and 1.1.6 (latest), and FreeRTOS 8.2.1
This commit is contained in:
commit
526bd42318
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file OsTime.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Header file related to time management
|
||||||
|
* @details Thie file including some data declare related to time managment.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 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
|
|
@ -0,0 +1,72 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file OsTimer.h
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Timer manage header file
|
||||||
|
* @details This file including some declares and defines related to timer
|
||||||
|
* management.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 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
|
|
@ -0,0 +1,126 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file arch.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief This file provides InitTaskContext() and SysTick_Handler().
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 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;
|
||||||
|
#if CFG_CHIP_TYPE == 3
|
||||||
|
context = context - 18;
|
||||||
|
#endif
|
||||||
|
*(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;
|
||||||
|
#if CFG_CHIP_TYPE == 3
|
||||||
|
context = context - 16;
|
||||||
|
#endif
|
||||||
|
// *(--context) = 0xfffffffd; /* LR */
|
||||||
|
|
||||||
|
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 CoSysTick_Handler(void)
|
||||||
|
{
|
||||||
|
OSSchedLock++; /* Lock scheduler. */
|
||||||
|
OSTickCnt++; /* Increment systerm time. */
|
||||||
|
#if CFG_TASK_WAITTING_EN >0
|
||||||
|
if(DlyList != Co_NULL) /* Have task in delay list? */
|
||||||
|
{
|
||||||
|
if(DlyList->delayTick > 1) /* Delay time > 1? */
|
||||||
|
{
|
||||||
|
DlyList->delayTick--; /* Decrease delay time of the list head. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DlyList->delayTick = 0;
|
||||||
|
isr_TimeDispose(); /* Call hander for delay time list */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TMR_EN > 0
|
||||||
|
if(TmrList != Co_NULL) /* Have timer in working? */
|
||||||
|
{
|
||||||
|
if(TmrList->tmrCnt > 1) /* Timer time > 1? */
|
||||||
|
{
|
||||||
|
TmrList->tmrCnt--; /* Decrease timer time of the list head. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TmrList->tmrCnt = 0;
|
||||||
|
isr_TmrDispose(); /* Call hander for timer list */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
TaskSchedReq = Co_TRUE;
|
||||||
|
OsSchedUnlock();
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file coocox.h
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Gather for all header file of CooCox CoOS.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _COOCOX_H
|
||||||
|
#define _COOCOX_H
|
||||||
|
|
||||||
|
#define OS_VERSION (U16)0x0114 /*!< OS version.(format: Vx.xx),
|
||||||
|
e.g. value 0x0114 is version V1.14*/
|
||||||
|
/*---------------------------- Include ---------------------------------------*/
|
||||||
|
#include "CoOS.h"
|
||||||
|
#include "OsArch.h"
|
||||||
|
#include "OsCore.h"
|
||||||
|
#include "OsTask.h"
|
||||||
|
#include "OsServiceReq.h"
|
||||||
|
#include "OsError.h"
|
||||||
|
#include "OsTime.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if CFG_TMR_EN > 0
|
||||||
|
#include "OsTimer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_KHEAP_EN > 0
|
||||||
|
#include "OsKernelHeap.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_MM_EN >0
|
||||||
|
#include "OsMM.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_EVENT_EN > 0
|
||||||
|
#include "OsEvent.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_MUTEX_EN > 0
|
||||||
|
#include "OsMutex.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_QUEUE_EN > 0
|
||||||
|
#include "OsQueue.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_FLAG_EN > 0
|
||||||
|
#include "OsFlag.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _COOCOX_H */
|
|
@ -0,0 +1,262 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file core.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Core implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*---------------------------- Include ---------------------------------------*/
|
||||||
|
#include <coocox.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------- Variable Define -------------------------------*/
|
||||||
|
volatile U8 OSIntNesting = 0; /*!< Use to indicate interrupt nesting level*/
|
||||||
|
volatile U8 OSSchedLock = 0; /*!< Task Switch lock. */
|
||||||
|
volatile BOOL TaskSchedReq = Co_FALSE;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Enter a ISR.
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to notify OS when enter to an ISR.
|
||||||
|
*
|
||||||
|
* @note When you call API in ISR,you must call CoEnterISR() before your
|
||||||
|
* interrupt handler code,and call CoExitISR() after your handler
|
||||||
|
* code and before exiting from ISR.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void CoEnterISR(void)
|
||||||
|
{
|
||||||
|
Inc8(&OSIntNesting); /* OSIntNesting increment */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Exit a ISR.
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called when exit from a ISR.
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void CoExitISR(void)
|
||||||
|
{
|
||||||
|
Dec8(&OSIntNesting); /* OSIntNesting decrease */
|
||||||
|
if( OSIntNesting == 0) /* Is OSIntNesting == 0? */
|
||||||
|
{
|
||||||
|
if(TaskSchedReq == Co_TRUE)
|
||||||
|
{
|
||||||
|
OSSchedLock++;
|
||||||
|
Schedule(); /* Call task schedule */
|
||||||
|
OSSchedLock--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Unlock schedule
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to unlock schedule(i.e.enable schedule again)
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void OsSchedUnlock(void)
|
||||||
|
{
|
||||||
|
if(OSSchedLock == 1) /* Is OSSchedLock == 0? */
|
||||||
|
{
|
||||||
|
#if CFG_TASK_WAITTING_EN > 0
|
||||||
|
if(IsrReq == Co_TRUE)
|
||||||
|
{
|
||||||
|
RespondSRQ(); /* Respond service request */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* Judge task state change or higher PRI task coming in */
|
||||||
|
if(TaskSchedReq == Co_TRUE)
|
||||||
|
{
|
||||||
|
Schedule(); /* Call task schedule */
|
||||||
|
}
|
||||||
|
OSSchedLock = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OSSchedLock--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Lock schedule
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called in application code to lock schedule.
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void CoSchedLock(void)
|
||||||
|
{
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Unlock schedule
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called in APP to unlock schedule.
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void CoSchedUnlock(void)
|
||||||
|
{
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Initialize OS
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to initialize OS.
|
||||||
|
*
|
||||||
|
* @note You must call this function first,before any other OS API function
|
||||||
|
*
|
||||||
|
* @code There is a example for useage of this function,as follows:
|
||||||
|
* e.g.
|
||||||
|
* ... // Your target initial code.
|
||||||
|
*
|
||||||
|
* OsInit(); // Initial OS.
|
||||||
|
* CreateTask(...); // Create tasks.
|
||||||
|
* ...
|
||||||
|
* OsStart(); // Start multitask.
|
||||||
|
* @endcode
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void CoInitOS(void)
|
||||||
|
{
|
||||||
|
InitSysTick(); /* Initialize system tick. */
|
||||||
|
InitInt(); /* Initialize PendSV,SVC,SysTick interrupt */
|
||||||
|
CreateTCBList(); /* Create TCB list. */
|
||||||
|
#if CFG_EVENT_EN > 0
|
||||||
|
CreateEventList(); /* Create event control list. */
|
||||||
|
#endif
|
||||||
|
#if CFG_KHEAP_EN > 0
|
||||||
|
CoCreateKheap(); /* Create kernel heap within user define */
|
||||||
|
#endif
|
||||||
|
OsSchedLock(); /* Lock Schedule */
|
||||||
|
/* Create first task -- IDLE task. */
|
||||||
|
CoCreateTask( CoIdleTask,
|
||||||
|
Co_NULL,
|
||||||
|
CFG_LOWEST_PRIO,
|
||||||
|
&idle_stk[CFG_IDLE_STACK_SIZE-1],
|
||||||
|
CFG_IDLE_STACK_SIZE
|
||||||
|
);
|
||||||
|
/* Set PSP for CoIdleTask coming in */
|
||||||
|
SetEnvironment(&idle_stk[CFG_IDLE_STACK_SIZE-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Start multitask
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to start multitask.After it is called,
|
||||||
|
* OS start schedule task by priority or/and time slice.
|
||||||
|
* @note This function must be called to start OS when you use CoOS,and must
|
||||||
|
* call after CoOsInit().
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void CoStartOS(void)
|
||||||
|
{
|
||||||
|
TCBRunning = &TCBTbl[0]; /* Get running task */
|
||||||
|
TCBNext = TCBRunning; /* Set next scheduled task as running task */
|
||||||
|
TCBRunning->state = TASK_RUNNING; /* Set running task status to RUNNING */
|
||||||
|
RemoveFromTCBRdyList(TCBRunning); /* Remove running task from READY list */
|
||||||
|
OsSchedUnlock(); /* Enable Schedule,call task schedule */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Get OS version
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval The value is version of OS mutipled by 100.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is used to return the version number of CooCox OS.
|
||||||
|
* the return value corresponds to CooCox's version number multiplied
|
||||||
|
* by 100. In other words, version 1.02 would be returned as 102.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
OS_VER CoGetOSVersion(void)
|
||||||
|
{
|
||||||
|
return OS_VERSION; /* Get CooCox CoOS version */
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,435 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file event.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief event management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 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 = Co_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 = Co_NULL;
|
||||||
|
pecb1->id = i; /* Assign ID. */
|
||||||
|
pecb1->eventType = EVENT_TYPE_INVALID; /* Sign that not to use. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_MAX_EVENT > 1 /* Build event list for more than one item */
|
||||||
|
pecb2 = &EventTbl[1];
|
||||||
|
for(;i< (CFG_MAX_EVENT-1);i++ )
|
||||||
|
{
|
||||||
|
pecb1->eventPtr = (void*)pecb2; /* Set link for list */
|
||||||
|
pecb1->id = i; /* Assign ID. */
|
||||||
|
pecb1->eventType = EVENT_TYPE_INVALID;/* Sign that not to use. */
|
||||||
|
pecb1++; /* Get next item */
|
||||||
|
pecb2++;
|
||||||
|
}
|
||||||
|
pecb1->eventType = EVENT_TYPE_INVALID; /* Sign that not to use. */
|
||||||
|
pecb1->eventPtr = Co_NULL; /* Set link for last item */
|
||||||
|
pecb1->id = i;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FreeEventList = &EventTbl[0]; /* Set free event item */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Release a ECB
|
||||||
|
* @param[in] pecb A pointer to event control block which be released.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to release a event control block when a
|
||||||
|
* event be deleted.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
static void ReleaseECB(P_ECB pecb)
|
||||||
|
{
|
||||||
|
pecb->eventType = EVENT_TYPE_INVALID; /* Sign that not to use. */
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
pecb->eventPtr = FreeEventList; /* Release ECB that event hold */
|
||||||
|
FreeEventList = pecb; /* Reset free event item */
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Create a event
|
||||||
|
* @param[in] eventType The type of event which being created.
|
||||||
|
* @param[in] eventSortType Event sort type.
|
||||||
|
* @param[in] eventCounter Event counter,ONLY for EVENT_TYPE_SEM.
|
||||||
|
* @param[in] eventPtr Event struct pointer,ONLY for Queue.Co_NULL for other
|
||||||
|
* event type.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval Co_NULL Invalid pointer,create event fail.
|
||||||
|
* @retval others Pointer to event control block which had assigned right now.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called by CreateSem(),...
|
||||||
|
* to get a event control block and initial the event content.
|
||||||
|
*
|
||||||
|
* @note This is a internal function of CooCox CoOS,User can't call.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
P_ECB CreatEvent(U8 eventType,U8 eventSortType,void* eventPtr)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
if(FreeEventList == Co_NULL) /* Is there no free evnet item */
|
||||||
|
{
|
||||||
|
OsSchedUnlock(); /* Yes,unlock schedule */
|
||||||
|
return Co_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 = Co_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 != Co_NULL) /* Yes,is there task pend this event? */
|
||||||
|
{
|
||||||
|
return E_TASK_WAITING; /* Yes,error return */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReleaseECB(pecb); /* No,release resource that event hold*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(opt == OPT_DEL_ANYWAY) /* Do delete event anyway? */
|
||||||
|
{
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
while(pecb->eventTCBList != Co_NULL) /* Is there task pend this event? */
|
||||||
|
{ /* Yes,remove it */
|
||||||
|
ptcb = pecb->eventTCBList;/* Get first task in event waiting list */
|
||||||
|
if(ptcb->delayTick != INVALID_VALUE) /* Is task in delay list? */
|
||||||
|
{
|
||||||
|
RemoveDelayList(ptcb); /* Yes,remove task from delay list */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set next item as event waiting list head */
|
||||||
|
pecb->eventTCBList = ptcb->waitNext;
|
||||||
|
ptcb->waitNext = Co_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-->Co_NULL)
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void EventTaskToWait(P_ECB pecb,P_OSTCB ptcb)
|
||||||
|
{
|
||||||
|
P_OSTCB ptcb1;
|
||||||
|
#if (CFG_EVENT_SORT == 2) || (CFG_EVENT_SORT == 3)
|
||||||
|
P_OSTCB ptcb2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
ptcb1 = pecb->eventTCBList; /* Get first task in event waiting list */
|
||||||
|
ptcb->eventID = pecb->id; /* Set event ID for task */
|
||||||
|
|
||||||
|
#if CFG_EVENT_SORT == 3 /* Does event waiting list sort as FIFO? */
|
||||||
|
|
||||||
|
if(pecb->eventSortType == EVENT_SORT_TYPE_FIFO)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (CFG_EVENT_SORT == 1) || (CFG_EVENT_SORT == 3)
|
||||||
|
{
|
||||||
|
if(ptcb1 == Co_NULL) /* Is no item in event waiting list?*/
|
||||||
|
{
|
||||||
|
pecb->eventTCBList = ptcb; /* Yes,set task as first item */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while(ptcb1->waitNext != Co_NULL)/* No,insert task in last */
|
||||||
|
{
|
||||||
|
ptcb1 = ptcb1->waitNext;
|
||||||
|
}
|
||||||
|
ptcb1->waitNext = ptcb; /* Set link for list */
|
||||||
|
ptcb->waitPrev = ptcb1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_EVENT_SORT ==3 /* Does event waiting list sort as preemptive priority?*/
|
||||||
|
else if(pecb->eventSortType == EVENT_SORT_TYPE_PRIO)
|
||||||
|
#endif
|
||||||
|
#if (CFG_EVENT_SORT == 2) || (CFG_EVENT_SORT == 3)
|
||||||
|
{
|
||||||
|
if(ptcb1 == Co_NULL) /* Is no item in event waiting list? */
|
||||||
|
{
|
||||||
|
pecb->eventTCBList = ptcb; /* Yes,set task as first item */
|
||||||
|
}
|
||||||
|
/* Is PRI of task higher than list first item? */
|
||||||
|
else if(ptcb1->prio > ptcb->prio)
|
||||||
|
{
|
||||||
|
pecb->eventTCBList = ptcb; /* Reset task as first item */
|
||||||
|
ptcb->waitNext = ptcb1; /* Set link for list */
|
||||||
|
ptcb1->waitPrev = ptcb;
|
||||||
|
}
|
||||||
|
else /* No,find correct place to insert */
|
||||||
|
{
|
||||||
|
ptcb2 = ptcb1->waitNext;
|
||||||
|
while(ptcb2 != Co_NULL) /* Is last item? */
|
||||||
|
{
|
||||||
|
if(ptcb2->prio > ptcb->prio) /* No,is correct place? */
|
||||||
|
{
|
||||||
|
break; /* Yes,break Circulation */
|
||||||
|
}
|
||||||
|
ptcb1 = ptcb2; /* Save current item */
|
||||||
|
ptcb2 = ptcb2->waitNext; /* Get next item */
|
||||||
|
}
|
||||||
|
ptcb1->waitNext = ptcb; /* Set link for list */
|
||||||
|
ptcb->waitPrev = ptcb1;
|
||||||
|
ptcb->waitNext = ptcb2;
|
||||||
|
if(ptcb2 != Co_NULL)
|
||||||
|
{
|
||||||
|
ptcb2->waitPrev = ptcb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ptcb->state = TASK_WAITING; /* Set task status to TASK_WAITING state */
|
||||||
|
TaskSchedReq = Co_TRUE;
|
||||||
|
OsSchedUnlock(); /* Unlock schedule,and call task schedule */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Move a task from event WAITING list to the DELAY list
|
||||||
|
* @param[in] pecb Pointer to event control block corresponding to the event.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to remove a task from event wait list,and
|
||||||
|
* then insert it into the READY list.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void EventTaskToRdy(P_ECB pecb)
|
||||||
|
{
|
||||||
|
P_OSTCB ptcb;
|
||||||
|
#if CFG_QUEUE_EN >0
|
||||||
|
P_QCB pqcb;
|
||||||
|
#endif
|
||||||
|
ptcb = pecb->eventTCBList;
|
||||||
|
if(ptcb == Co_NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pecb->eventTCBList = ptcb->waitNext;/* Get first task in event waiting list*/
|
||||||
|
if(pecb->eventTCBList != Co_NULL) /* Is no item in event waiting list? */
|
||||||
|
{
|
||||||
|
pecb->eventTCBList->waitPrev = Co_NULL; /* No,clear link for first item */
|
||||||
|
}
|
||||||
|
|
||||||
|
ptcb->waitNext = Co_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 CFG_MAILBOX_EN >0
|
||||||
|
if(pecb->eventType == EVENT_TYPE_MBOX)/* Is it a mailbox event? */
|
||||||
|
{
|
||||||
|
ptcb->pmail = pecb->eventPtr; /* Yes,send mail to task */
|
||||||
|
pecb->eventPtr = Co_NULL; /* Clear event sign */
|
||||||
|
//pecb->eventCounter--;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#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_SEM_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 == Co_NULL) && (ptcb->waitPrev == Co_NULL))
|
||||||
|
{
|
||||||
|
pecb->eventTCBList = Co_NULL; /* Yes,set event waiting list as Co_NULL */
|
||||||
|
}
|
||||||
|
else if(ptcb->waitPrev == Co_NULL)/* Is the first item in event waiting list?*/
|
||||||
|
{
|
||||||
|
/* Yes,remove task from list,and reset event waiting list */
|
||||||
|
ptcb->waitNext->waitPrev = Co_NULL;
|
||||||
|
pecb->eventTCBList = ptcb->waitNext;
|
||||||
|
ptcb->waitNext = Co_NULL;
|
||||||
|
}
|
||||||
|
else if(ptcb->waitNext == Co_NULL)/* Is the last item in event waiting list? */
|
||||||
|
{
|
||||||
|
ptcb->waitPrev->waitNext = Co_NULL; /* Yes,remove task form list */
|
||||||
|
ptcb->waitPrev = Co_NULL;
|
||||||
|
}
|
||||||
|
else /* No, remove task from list */
|
||||||
|
{
|
||||||
|
ptcb->waitPrev->waitNext = ptcb->waitNext;
|
||||||
|
ptcb->waitNext->waitPrev = ptcb->waitPrev;
|
||||||
|
ptcb->waitPrev = Co_NULL;
|
||||||
|
ptcb->waitNext = Co_NULL;
|
||||||
|
}
|
||||||
|
ptcb->eventID = INVALID_ID; /* Sign that not to use. */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //CFG_EVENT_EN
|
||||||
|
|
|
@ -0,0 +1,735 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file flag.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Flag management implementation code of coocox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------- Include ---------------------------------------*/
|
||||||
|
#include <coocox.h>
|
||||||
|
|
||||||
|
#if CFG_FLAG_EN > 0
|
||||||
|
/*---------------------------- Variable Define -------------------------------*/
|
||||||
|
#define FLAG_MAX_NUM 32 /*!< Define max flag number. */
|
||||||
|
FCB FlagCrl = {0}; /*!< Flags list struct */
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------- Function Declare ------------------------------*/
|
||||||
|
static void FlagBlock(P_FLAG_NODE pnode,U32 flags,U8 waitType);
|
||||||
|
static P_FLAG_NODE RemoveFromLink(P_FLAG_NODE pnode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Create a flag
|
||||||
|
* @param[in] bAutoReset Reset mode,Co_TRUE(Auto Reset) FLASE(Manual Reset).
|
||||||
|
* @param[in] bInitialState Initial state.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_CREATE_FAIL Create flag fail.
|
||||||
|
* @retval others Create flag successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function use to create a event flag.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
OS_FlagID CoCreateFlag(BOOL bAutoReset,BOOL bInitialState)
|
||||||
|
{
|
||||||
|
U8 i;
|
||||||
|
OsSchedLock();
|
||||||
|
|
||||||
|
for(i=0;i<FLAG_MAX_NUM;i++)
|
||||||
|
{
|
||||||
|
/* Assign a free flag control block */
|
||||||
|
if((FlagCrl.flagActive&(1<<i)) == 0 )
|
||||||
|
{
|
||||||
|
FlagCrl.flagActive |= (1<<i); /* Initialize active flag */
|
||||||
|
FlagCrl.flagRdy |= (bInitialState<<i);/* Initialize ready flag */
|
||||||
|
FlagCrl.resetOpt |= (bAutoReset<<i);/* Initialize reset option */
|
||||||
|
OsSchedUnlock();
|
||||||
|
return i ; /* Return Flag ID */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OsSchedUnlock();
|
||||||
|
|
||||||
|
return E_CREATE_FAIL; /* There is no free flag control block*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Delete a flag
|
||||||
|
* @param[in] id Flag ID.
|
||||||
|
* @param[in] opt Delete option.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_CALL Error call in ISR.
|
||||||
|
* @retval E_INVALID_ID Invalid event ID.
|
||||||
|
* @retval E_TASK_WAITTING Tasks waitting for the event,delete fail.
|
||||||
|
* @retval E_OK Event deleted successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to delete a event flag.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoDelFlag(OS_FlagID id,U8 opt)
|
||||||
|
{
|
||||||
|
P_FLAG_NODE pnode;
|
||||||
|
P_FCB pfcb;
|
||||||
|
pfcb = &FlagCrl;
|
||||||
|
if(OSIntNesting > 0) /* If be called from ISR */
|
||||||
|
{
|
||||||
|
return E_CALL;
|
||||||
|
}
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if((pfcb->flagActive&(1<<id)) == 0) /* Flag is valid or not */
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
OsSchedLock();
|
||||||
|
pnode = pfcb->headNode;
|
||||||
|
|
||||||
|
while(pnode != Co_NULL) /* Ready all tasks waiting for flags */
|
||||||
|
{
|
||||||
|
if((pnode->waitFlags&(1<<id)) != 0) /* If no task is waiting on flags */
|
||||||
|
{
|
||||||
|
if(opt == OPT_DEL_NO_PEND) /* Delete flag if no task waiting */
|
||||||
|
{
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_TASK_WAITING;
|
||||||
|
}
|
||||||
|
else if (opt == OPT_DEL_ANYWAY) /* Always delete the flag */
|
||||||
|
{
|
||||||
|
if(pnode->waitType == OPT_WAIT_ALL)
|
||||||
|
{
|
||||||
|
/* If the flag is only required by NODE */
|
||||||
|
if( pnode->waitFlags == (1<<id) )
|
||||||
|
{
|
||||||
|
/* Remove the NODE from waiting list */
|
||||||
|
pnode = RemoveFromLink(pnode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pnode->waitFlags &= ~(1<<id); /* Update waitflags */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pnode = RemoveFromLink(pnode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pnode = pnode->nextNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the flag from the flags list */
|
||||||
|
pfcb->flagActive &= ~(1<<id);
|
||||||
|
pfcb->flagRdy &= ~(1<<id);
|
||||||
|
pfcb->resetOpt &= ~(1<<id);
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief AcceptSingleFlag
|
||||||
|
* @param[in] id Flag ID.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID Invalid event ID.
|
||||||
|
* @retval E_FLAG_NOT_READY Flag is not in ready state.
|
||||||
|
* @retval E_OK The call was successful and your task owns the Flag.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This fucntion is called to accept single flag
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoAcceptSingleFlag(OS_FlagID id)
|
||||||
|
{
|
||||||
|
P_FCB pfcb;
|
||||||
|
pfcb = &FlagCrl;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= FLAG_MAX_NUM)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Invalid 'id',return error */
|
||||||
|
}
|
||||||
|
if((pfcb->flagActive&(1<<id)) == 0)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Flag is deactive,return error */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if((pfcb->flagRdy&(1<<id)) != 0) /* If the required flag is set */
|
||||||
|
{
|
||||||
|
OsSchedLock()
|
||||||
|
pfcb->flagRdy &= ~((FlagCrl.resetOpt)&(1<<id)); /* Clear the flag */
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
else /* If the required flag is not set */
|
||||||
|
{
|
||||||
|
return E_FLAG_NOT_READY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief AcceptMultipleFlags
|
||||||
|
* @param[in] flags Flags that waiting to active task.
|
||||||
|
* @param[in] waitType Flags wait type.
|
||||||
|
* @param[out] perr A pointer to error code.
|
||||||
|
* @retval 0
|
||||||
|
* @retval springFlag
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This fucntion is called to accept multiple flags.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
U32 CoAcceptMultipleFlags(U32 flags,U8 waitType,StatusType *perr)
|
||||||
|
{
|
||||||
|
U32 springFlag;
|
||||||
|
P_FCB pfcb;
|
||||||
|
pfcb = &FlagCrl;
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if((flags&pfcb->flagActive) != flags ) /* Judge flag is active or not? */
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_PARAMETER; /* Invalid flags */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
springFlag = flags & pfcb->flagRdy;
|
||||||
|
|
||||||
|
OsSchedLock();
|
||||||
|
/* If any required flags are set */
|
||||||
|
if( (springFlag != 0) && (waitType == OPT_WAIT_ANY) )
|
||||||
|
{
|
||||||
|
|
||||||
|
pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt); /* Clear the flags */
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_OK;
|
||||||
|
return springFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If all required flags are set */
|
||||||
|
if((springFlag == flags) && (waitType == OPT_WAIT_ALL))
|
||||||
|
{
|
||||||
|
pfcb->flagRdy &= ~(springFlag&pfcb->resetOpt); /* Clear the flags */
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_OK;
|
||||||
|
return springFlag;
|
||||||
|
}
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_FLAG_NOT_READY;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief WaitForSingleFlag
|
||||||
|
* @param[in] id Flag ID.
|
||||||
|
* @param[in] timeout The longest time for writting flag.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_CALL Error call in ISR.
|
||||||
|
* @retval E_INVALID_ID Invalid event ID.
|
||||||
|
* @retval E_TIMEOUT Flag wasn't received within 'timeout' time.
|
||||||
|
* @retval E_OK The call was successful and your task owns the Flag,
|
||||||
|
* or the event you are waiting for occurred.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to wait for only one flag,
|
||||||
|
* (1) if parameter "timeout" == 0,waiting until flag be set;
|
||||||
|
* (2) when "timeout" != 0,if flag was set or wasn't set but timeout
|
||||||
|
* occured,the task will exit the waiting list,convert to READY
|
||||||
|
* or RUNNING state.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoWaitForSingleFlag(OS_FlagID id,U32 timeout)
|
||||||
|
{
|
||||||
|
FLAG_NODE flagNode;
|
||||||
|
P_FCB pfcb;
|
||||||
|
P_OSTCB curTCB;
|
||||||
|
|
||||||
|
if(OSIntNesting > 0) /* See if the caller is ISR */
|
||||||
|
{
|
||||||
|
return E_CALL;
|
||||||
|
}
|
||||||
|
if(OSSchedLock != 0) /* Schedule is lock? */
|
||||||
|
{
|
||||||
|
return E_OS_IN_LOCK; /* Yes,error return */
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= FLAG_MAX_NUM) /* Judge id is valid or not? */
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Invalid 'id' */
|
||||||
|
}
|
||||||
|
if((FlagCrl.flagActive&(1<<id)) == 0 )/* Judge flag is active or not? */
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Flag is deactive ,return error */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OsSchedLock();
|
||||||
|
pfcb = &FlagCrl;
|
||||||
|
/* See if the required flag is set */
|
||||||
|
if((pfcb->flagRdy&(1<<id)) != 0) /* If the required flag is set */
|
||||||
|
{
|
||||||
|
pfcb->flagRdy &= ~((pfcb->resetOpt&(1<<id))); /* Clear the flag */
|
||||||
|
OsSchedUnlock();
|
||||||
|
}
|
||||||
|
else /* If the required flag is not set */
|
||||||
|
{
|
||||||
|
curTCB = TCBRunning;
|
||||||
|
if(timeout == 0) /* If time-out is not configured */
|
||||||
|
{
|
||||||
|
/* Block task until the required flag is set */
|
||||||
|
FlagBlock (&flagNode,(1<<id),OPT_WAIT_ONE);
|
||||||
|
curTCB->state = TASK_WAITING;
|
||||||
|
TaskSchedReq = Co_TRUE;
|
||||||
|
OsSchedUnlock();
|
||||||
|
|
||||||
|
/* The required flag is set and the task is in running state */
|
||||||
|
curTCB->pnode = Co_NULL;
|
||||||
|
OsSchedLock();
|
||||||
|
|
||||||
|
/* Clear the required flag or not */
|
||||||
|
pfcb->flagRdy &= ~((1<<id)&(pfcb->resetOpt));
|
||||||
|
OsSchedUnlock();
|
||||||
|
}
|
||||||
|
else /* If time-out is configured */
|
||||||
|
{
|
||||||
|
/* Block task until the required flag is set or time-out occurs */
|
||||||
|
FlagBlock(&flagNode,(1<<id),OPT_WAIT_ONE);
|
||||||
|
InsertDelayList(curTCB,timeout);
|
||||||
|
|
||||||
|
OsSchedUnlock();
|
||||||
|
if(curTCB->pnode == Co_NULL) /* If time-out occurred */
|
||||||
|
{
|
||||||
|
return E_TIMEOUT;
|
||||||
|
}
|
||||||
|
else /* If flag is set */
|
||||||
|
{
|
||||||
|
curTCB->pnode = Co_NULL;
|
||||||
|
OsSchedLock();
|
||||||
|
|
||||||
|
/* Clear the required flag or not */
|
||||||
|
pfcb->flagRdy &= ~((1<<id)&(pfcb->resetOpt));
|
||||||
|
OsSchedUnlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief WaitForMultipleFlags
|
||||||
|
* @param[in] flags Flags that waiting to active task.
|
||||||
|
* @param[in] waitType Flags wait type.
|
||||||
|
* @param[in] timeout The longest time for writting flag.
|
||||||
|
* @param[out] perr A pointer to error code.
|
||||||
|
* @retval 0
|
||||||
|
* @retval springFlag
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to pend a task for waitting multiple flag.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
U32 CoWaitForMultipleFlags(U32 flags,U8 waitType,U32 timeout,StatusType *perr)
|
||||||
|
{
|
||||||
|
U32 springFlag;
|
||||||
|
P_FCB pfcb;
|
||||||
|
FLAG_NODE flagNode;
|
||||||
|
P_OSTCB curTCB;
|
||||||
|
|
||||||
|
|
||||||
|
if(OSIntNesting > 0) /* If the caller is ISR */
|
||||||
|
{
|
||||||
|
*perr = E_CALL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(OSSchedLock != 0) /* Schedule is lock? */
|
||||||
|
{
|
||||||
|
*perr = E_OS_IN_LOCK;
|
||||||
|
return 0; /* Yes,error return */
|
||||||
|
}
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if( (flags&FlagCrl.flagActive) != flags )
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_PARAMETER; /* Invalid 'flags' */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
OsSchedLock();
|
||||||
|
pfcb = &FlagCrl;
|
||||||
|
springFlag = flags & pfcb->flagRdy;
|
||||||
|
|
||||||
|
/* If any required flags are set */
|
||||||
|
if((springFlag != 0) && (waitType == OPT_WAIT_ANY))
|
||||||
|
{
|
||||||
|
pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt); /* Clear the flag */
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_OK;
|
||||||
|
return springFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If all required flags are set */
|
||||||
|
if( (springFlag == flags) && (waitType == OPT_WAIT_ALL) )
|
||||||
|
{
|
||||||
|
pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt); /* Clear the flags */
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_OK;
|
||||||
|
return springFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
curTCB = TCBRunning;
|
||||||
|
if(timeout == 0) /* If time-out is not configured */
|
||||||
|
{
|
||||||
|
/* Block task until the required flag are set */
|
||||||
|
FlagBlock(&flagNode,flags,waitType);
|
||||||
|
curTCB->state = TASK_WAITING;
|
||||||
|
TaskSchedReq = Co_TRUE;
|
||||||
|
OsSchedUnlock();
|
||||||
|
|
||||||
|
curTCB->pnode = Co_NULL;
|
||||||
|
OsSchedLock();
|
||||||
|
springFlag = flags & pfcb->flagRdy;
|
||||||
|
pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt);/* Clear the flags */
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_OK;
|
||||||
|
return springFlag;
|
||||||
|
}
|
||||||
|
else /* If time-out is configured */
|
||||||
|
{
|
||||||
|
/* Block task until the required flag are set or time-out occurred */
|
||||||
|
FlagBlock(&flagNode,flags,waitType);
|
||||||
|
InsertDelayList(curTCB,timeout);
|
||||||
|
|
||||||
|
OsSchedUnlock();
|
||||||
|
if(curTCB->pnode == Co_NULL) /* If time-out occurred */
|
||||||
|
{
|
||||||
|
*perr = E_TIMEOUT;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else /* If the required flags are set */
|
||||||
|
{
|
||||||
|
curTCB->pnode = Co_NULL;
|
||||||
|
OsSchedLock();
|
||||||
|
springFlag = flags & FlagCrl.flagRdy;
|
||||||
|
|
||||||
|
/* Clear the required ready flags or not */
|
||||||
|
pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt);
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_OK;
|
||||||
|
return springFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Clear a Flag
|
||||||
|
* @param[in] id Flag ID.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_OK Event deleted successful.
|
||||||
|
* @retval E_INVALID_ID Invalid event ID.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to clear a flag.
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoClearFlag(OS_FlagID id)
|
||||||
|
{
|
||||||
|
P_FCB pfcb;
|
||||||
|
pfcb = &FlagCrl;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= FLAG_MAX_NUM)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Invalid id */
|
||||||
|
}
|
||||||
|
if((pfcb->flagActive&(1<<id)) == 0)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Invalid flag */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pfcb->flagRdy &= ~(1<<id); /* Clear the flag */
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Set a flag
|
||||||
|
* @param[in] id Flag ID.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID Invalid event ID.
|
||||||
|
* @retval E_OK Event deleted successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to set a flag.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoSetFlag(OS_FlagID id)
|
||||||
|
{
|
||||||
|
P_FLAG_NODE pnode;
|
||||||
|
P_FCB pfcb;
|
||||||
|
pfcb = &FlagCrl;
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= FLAG_MAX_NUM) /* Flag is valid or not */
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Invalid flag id */
|
||||||
|
}
|
||||||
|
if((pfcb->flagActive&(1<<id)) == 0)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Flag is not exist */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if((pfcb->flagRdy&(1<<id)) != 0) /* Flag had already been set */
|
||||||
|
{
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
pfcb->flagRdy |= (1<<id); /* Update the flags ready list */
|
||||||
|
|
||||||
|
OsSchedLock();
|
||||||
|
pnode = pfcb->headNode;
|
||||||
|
while(pnode != Co_NULL)
|
||||||
|
{
|
||||||
|
if(pnode->waitType == OPT_WAIT_ALL) /* Extract all the bits we want */
|
||||||
|
{
|
||||||
|
if((pnode->waitFlags&pfcb->flagRdy) == pnode->waitFlags)
|
||||||
|
{
|
||||||
|
/* Remove the flag node from the wait list */
|
||||||
|
pnode = RemoveFromLink(pnode);
|
||||||
|
if((pfcb->resetOpt&(1<<id)) != 0)/* If the flags is auto-reset*/
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* Extract only the bits we want */
|
||||||
|
{
|
||||||
|
if( (pnode->waitFlags & pfcb->flagRdy) != 0)
|
||||||
|
{
|
||||||
|
/* Remove the flag node from the wait list */
|
||||||
|
pnode = RemoveFromLink(pnode);
|
||||||
|
if((pfcb->resetOpt&(1<<id)) != 0)
|
||||||
|
{
|
||||||
|
break; /* The flags is auto-reset */
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pnode = pnode->nextNode;
|
||||||
|
}
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Set a flag in ISR
|
||||||
|
* @param[in] id Flag ID.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID Invalid event ID.
|
||||||
|
* @retval E_OK Event deleted successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called in ISR to set a flag.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
#if CFG_MAX_SERVICE_REQUEST > 0
|
||||||
|
StatusType isr_SetFlag(OS_FlagID id)
|
||||||
|
{
|
||||||
|
if(OSSchedLock > 0) /* If scheduler is locked,(the caller is ISR) */
|
||||||
|
{
|
||||||
|
/* Insert the request into service request queue */
|
||||||
|
if(InsertInSRQ(FLAG_REQ,id,Co_NULL) == Co_FALSE)
|
||||||
|
{
|
||||||
|
return E_SEV_REQ_FULL; /* The service requst queue is full */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return(CoSetFlag(id)); /* The caller is not ISR, set the flag*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Block a task to wait a flag event
|
||||||
|
* @param[in] pnode A node that will link into flag waiting list.
|
||||||
|
* @param[in] flags Flag(s) that the node waiting for.
|
||||||
|
* @param[in] waitType Waiting type of the node.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to block a task to wait a flag event.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
static void FlagBlock(P_FLAG_NODE pnode,U32 flags,U8 waitType)
|
||||||
|
{
|
||||||
|
P_FCB pfcb;
|
||||||
|
pfcb = &FlagCrl;
|
||||||
|
|
||||||
|
TCBRunning->pnode = pnode;
|
||||||
|
pnode->waitTask = TCBRunning;
|
||||||
|
pnode->waitFlags = flags; /* Save the flags that we need to wait for*/
|
||||||
|
pnode->waitType = waitType; /* Save the type of wait */
|
||||||
|
|
||||||
|
if(pfcb->tailNode == Co_NULL) /* If this is the first NODE to insert? */
|
||||||
|
{
|
||||||
|
pnode->nextNode = Co_NULL;
|
||||||
|
pnode->prevNode = Co_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 = Co_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 == Co_NULL) && (pnode->prevNode == Co_NULL))
|
||||||
|
{
|
||||||
|
FlagCrl.headNode = Co_NULL;
|
||||||
|
FlagCrl.tailNode = Co_NULL;
|
||||||
|
}
|
||||||
|
else if(pnode->nextNode == Co_NULL) /* If the NODE is tail */
|
||||||
|
{
|
||||||
|
FlagCrl.tailNode = pnode->prevNode;
|
||||||
|
pnode->prevNode->nextNode = Co_NULL;
|
||||||
|
}
|
||||||
|
else if(pnode->prevNode == Co_NULL) /* If the NODE is head */
|
||||||
|
{
|
||||||
|
FlagCrl.headNode = pnode->nextNode;
|
||||||
|
pnode->nextNode->prevNode = Co_NULL;
|
||||||
|
}
|
||||||
|
else /* The NODE is in the middle */
|
||||||
|
{
|
||||||
|
pnode->nextNode->prevNode = pnode->prevNode;
|
||||||
|
pnode->prevNode->nextNode = pnode->nextNode;
|
||||||
|
}
|
||||||
|
pnode->waitTask->pnode = Co_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,88 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file hook.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief hook management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 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(; ;)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,432 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file kernelHeap.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief kernel heap management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------- Include ---------------------------------------*/
|
||||||
|
#include <coocox.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if CFG_KHEAP_EN >0
|
||||||
|
/*---------------------------- Variable Define -------------------------------*/
|
||||||
|
U32 KernelHeap[KHEAP_SIZE] = {0}; /*!< Kernel heap */
|
||||||
|
P_FMB FMBlist = Co_NULL; /*!< Free memory block list */
|
||||||
|
KHeap Kheap = {0}; /*!< Kernel heap control */
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------- Function Declare ------------------------------*/
|
||||||
|
static P_FMB GetPreFMB(P_UMB usedMB);
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Create kernel heap
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to create kernel heap.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void CoCreateKheap(void)
|
||||||
|
{
|
||||||
|
Kheap.startAddr = (U32)(KernelHeap); /* Initialize kernel heap control */
|
||||||
|
Kheap.endAddr = (U32)(KernelHeap) + KHEAP_SIZE*4;
|
||||||
|
FMBlist = (P_FMB)KernelHeap; /* Initialize free memory block list*/
|
||||||
|
FMBlist->nextFMB = Co_NULL;
|
||||||
|
FMBlist->nextUMB = Co_NULL;
|
||||||
|
FMBlist->preUMB = Co_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Allocation size bytes of memory block from kernel heap.
|
||||||
|
* @param[in] size Length of menory block.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval Co_NULL Allocate fail.
|
||||||
|
* @retval others Pointer to memory block.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to allocation size bytes of memory block.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void* CoKmalloc(U32 size)
|
||||||
|
{
|
||||||
|
P_FMB freeMB,newFMB,preFMB;
|
||||||
|
P_UMB usedMB,tmpUMB;
|
||||||
|
U8* memAddr;
|
||||||
|
U32 freeSize;
|
||||||
|
U32 kheapAddr;
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if( size == 0 )
|
||||||
|
{
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Word alignment,and add used memory head size */
|
||||||
|
size = (((size+3)>>2)<<2) + 8;
|
||||||
|
kheapAddr = Kheap.endAddr; /* Get the end address of kernel heap */
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
freeMB = FMBlist; /* Get first item of free memory list */
|
||||||
|
preFMB = Co_NULL;
|
||||||
|
while(freeMB != Co_NULL ) /* Is out of free memory list? */
|
||||||
|
{ /* No */
|
||||||
|
if(freeMB->nextUMB == Co_NULL) /* Is last item of free memory list? */
|
||||||
|
{ /* Yes,get size for this free item */
|
||||||
|
freeSize = kheapAddr - (U32)(freeMB);
|
||||||
|
}
|
||||||
|
else /* No,get size for this free item */
|
||||||
|
{
|
||||||
|
freeSize = (U32)(freeMB->nextUMB) -1 - (U32)(freeMB);
|
||||||
|
}
|
||||||
|
if(freeSize >= size) /* If the size equal or greater than need */
|
||||||
|
{ /* Yes,assign in this free memory */
|
||||||
|
usedMB=(P_UMB)freeMB;/* Get the address for used memory block head*/
|
||||||
|
|
||||||
|
/* Get the address for used memory block */
|
||||||
|
memAddr = (U8*)((U32)(usedMB) + 8);
|
||||||
|
|
||||||
|
/* Is left size of free memory smaller than 12? */
|
||||||
|
if((freeSize-size) < 12)
|
||||||
|
{
|
||||||
|
/* Yes,malloc together(12 is the size of the header information
|
||||||
|
of free memory block ). */
|
||||||
|
if(preFMB != Co_NULL)/* Is first item of free memory block list? */
|
||||||
|
{ /* No,set the link for list */
|
||||||
|
preFMB->nextFMB = freeMB->nextFMB;
|
||||||
|
}
|
||||||
|
else /* Yes,reset the first item */
|
||||||
|
{
|
||||||
|
FMBlist = freeMB->nextFMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(freeMB->nextUMB != Co_NULL) /* Is last item? */
|
||||||
|
{ /* No,set the link for list */
|
||||||
|
tmpUMB = (P_UMB)((U32)(freeMB->nextUMB)-1);
|
||||||
|
tmpUMB->preMB = (void*)((U32)usedMB|0x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
usedMB->nextMB = freeMB->nextUMB;/* Set used memory block link*/
|
||||||
|
usedMB->preMB = freeMB->preUMB;
|
||||||
|
}
|
||||||
|
else /* No,the left size more than 12 */
|
||||||
|
{
|
||||||
|
/* Get new free memory block address */
|
||||||
|
newFMB = (P_FMB)((U32)(freeMB) + size);
|
||||||
|
|
||||||
|
if(preFMB != Co_NULL)/* Is first item of free memory block list? */
|
||||||
|
{
|
||||||
|
preFMB->nextFMB = newFMB; /* No,set the link for list */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FMBlist = newFMB; /* Yes,reset the first item */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set link for new free memory block */
|
||||||
|
newFMB->preUMB = (P_UMB)((U32)usedMB|0x1);
|
||||||
|
newFMB->nextUMB = freeMB->nextUMB;
|
||||||
|
newFMB->nextFMB = freeMB->nextFMB;
|
||||||
|
|
||||||
|
if(freeMB->nextUMB != Co_NULL) /* Is last item? */
|
||||||
|
{ /* No,set the link for list */
|
||||||
|
tmpUMB = (P_UMB)((U32)(freeMB->nextUMB)-1);
|
||||||
|
tmpUMB->preMB = newFMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
usedMB->nextMB = newFMB; /* Set used memory block link */
|
||||||
|
usedMB->preMB = freeMB->preUMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(freeMB->preUMB != Co_NULL) /* Is first item? */
|
||||||
|
{ /* No,set the link for list */
|
||||||
|
tmpUMB = (P_UMB)((U32)(freeMB->preUMB)-1);
|
||||||
|
tmpUMB->nextMB = (void*)((U32)usedMB|0x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
return memAddr; /* Return used memory block address */
|
||||||
|
}
|
||||||
|
preFMB = freeMB; /* Save current free memory block as previous */
|
||||||
|
freeMB = freeMB->nextFMB; /* Get the next item as current item*/
|
||||||
|
}
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
return Co_NULL; /* Error return */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Release memory block to kernel heap.
|
||||||
|
* @param[in] memBuf Pointer to memory block.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to release memory block.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void CoKfree(void* memBuf)
|
||||||
|
{
|
||||||
|
P_FMB curFMB,nextFMB,preFMB;
|
||||||
|
P_UMB usedMB,nextUMB,preUMB;
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(memBuf == Co_NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
usedMB = (P_UMB)((U32)(memBuf)-8);
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if((U32)(memBuf) < Kheap.startAddr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if((U32)(memBuf) > Kheap.endAddr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check UMB in list */
|
||||||
|
if((U32)(usedMB) < (U32)(FMBlist))
|
||||||
|
{
|
||||||
|
preUMB = (P_UMB)((U32)(FMBlist->preUMB)-1);
|
||||||
|
while(preUMB != usedMB)
|
||||||
|
{
|
||||||
|
if(preUMB == Co_NULL)
|
||||||
|
{
|
||||||
|
OsSchedUnlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
preUMB = (P_UMB)((U32)(preUMB->preMB)-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(FMBlist == Co_NULL)
|
||||||
|
{
|
||||||
|
nextUMB = (P_UMB)(Kheap.startAddr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(FMBlist->nextUMB != Co_NULL)
|
||||||
|
{
|
||||||
|
nextUMB = (P_UMB)((U32)(FMBlist->nextUMB)-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nextUMB = Co_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while(nextUMB != usedMB)
|
||||||
|
{
|
||||||
|
if(nextUMB == Co_NULL)
|
||||||
|
{
|
||||||
|
OsSchedUnlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(((U32)(nextUMB->nextMB)&0x1) == 0)
|
||||||
|
{
|
||||||
|
nextFMB = (P_FMB)(nextUMB->nextMB);
|
||||||
|
nextUMB = (P_UMB)((U32)(nextFMB->nextUMB)-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nextUMB = (P_UMB)((U32)(nextUMB->nextMB)-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Is between two free memory block? */
|
||||||
|
if( (((U32)(usedMB->nextMB)&0x1) == 0) && (((U32)(usedMB->preMB)&0x1)==0) )
|
||||||
|
{ /* Yes,is the only one item in kernel heap? */
|
||||||
|
if((usedMB->nextMB == Co_NULL) && (usedMB->preMB == Co_NULL))
|
||||||
|
{
|
||||||
|
curFMB = (P_FMB)usedMB; /* Yes,release this item */
|
||||||
|
curFMB->nextFMB = Co_NULL;
|
||||||
|
curFMB->nextUMB = Co_NULL;
|
||||||
|
curFMB->preUMB = Co_NULL;
|
||||||
|
FMBlist = curFMB;
|
||||||
|
}
|
||||||
|
else if(usedMB->preMB == Co_NULL) /* Is the first item in kernel heap */
|
||||||
|
{
|
||||||
|
/* Yes,release this item,and set link for list */
|
||||||
|
curFMB = (P_FMB)usedMB;
|
||||||
|
nextFMB = (P_FMB)usedMB->nextMB;
|
||||||
|
|
||||||
|
curFMB->nextFMB = nextFMB->nextFMB;
|
||||||
|
curFMB->nextUMB = nextFMB->nextUMB;
|
||||||
|
curFMB->preUMB = Co_NULL;
|
||||||
|
FMBlist = curFMB;
|
||||||
|
}
|
||||||
|
else if(usedMB->nextMB == Co_NULL) /* Is the last item in kernel heap */
|
||||||
|
{ /* Yes,release this item,and set link for list */
|
||||||
|
curFMB = (P_FMB)(usedMB->preMB);
|
||||||
|
curFMB->nextFMB = Co_NULL;
|
||||||
|
curFMB->nextUMB = Co_NULL;
|
||||||
|
}
|
||||||
|
else /* All no,show this item between two normal FMB */
|
||||||
|
{
|
||||||
|
/* release this item,and set link for list */
|
||||||
|
nextFMB = (P_FMB)usedMB->nextMB;
|
||||||
|
curFMB = (P_FMB)(usedMB->preMB);
|
||||||
|
|
||||||
|
curFMB->nextFMB = nextFMB->nextFMB;
|
||||||
|
curFMB->nextUMB = nextFMB->nextUMB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(((U32)(usedMB->preMB)&0x1) == 0) /* Is between FMB and UMB? */
|
||||||
|
{
|
||||||
|
if(usedMB->preMB == Co_NULL) /* Yes,is the first item in kernel heap? */
|
||||||
|
{
|
||||||
|
/* Yes,release this item,and set link for list */
|
||||||
|
curFMB = (P_FMB)usedMB;
|
||||||
|
nextUMB = (P_UMB)usedMB->nextMB;
|
||||||
|
curFMB->nextUMB = nextUMB;
|
||||||
|
curFMB->preUMB = Co_NULL;
|
||||||
|
curFMB->nextFMB = FMBlist;
|
||||||
|
FMBlist = curFMB;
|
||||||
|
}
|
||||||
|
else /* No,release this item,and set link for list */
|
||||||
|
{
|
||||||
|
curFMB = (P_FMB)usedMB->preMB;
|
||||||
|
nextUMB = (P_UMB)usedMB->nextMB;
|
||||||
|
curFMB->nextUMB = nextUMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(((U32)(usedMB->nextMB)&0x1) == 0) /* Is between UMB and FMB? */
|
||||||
|
{ /* Yes */
|
||||||
|
preUMB = (P_UMB)(usedMB->preMB); /* Get previous UMB */
|
||||||
|
curFMB = (P_FMB)(usedMB); /* new FMB */
|
||||||
|
preFMB = GetPreFMB(usedMB); /* Get previous FMB */
|
||||||
|
if(preFMB == Co_NULL) /* Is previous FMB==Co_NULL? */
|
||||||
|
{
|
||||||
|
nextFMB = FMBlist; /* Yes,get next FMB */
|
||||||
|
FMBlist = curFMB; /* Reset new FMB as the first item of FMB list*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nextFMB = preFMB->nextFMB; /* No,get next FMB */
|
||||||
|
preFMB->nextFMB = curFMB; /* Set link for FMB list */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nextFMB == Co_NULL) /* Is new FMB as last item of FMB list? */
|
||||||
|
{
|
||||||
|
curFMB->preUMB = preUMB; /* Yes,set link for list */
|
||||||
|
curFMB->nextUMB = Co_NULL;
|
||||||
|
curFMB->nextFMB = Co_NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curFMB->preUMB = preUMB; /* No,set link for list */
|
||||||
|
curFMB->nextUMB = nextFMB->nextUMB;
|
||||||
|
curFMB->nextFMB = nextFMB->nextFMB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* All no,show UMB between two UMB*/
|
||||||
|
{
|
||||||
|
curFMB = (P_FMB)(usedMB); /* new FMB */
|
||||||
|
preFMB = GetPreFMB(usedMB); /* Get previous FMB */
|
||||||
|
preUMB = (P_UMB)(usedMB->preMB); /* Get previous UMB */
|
||||||
|
nextUMB = (P_UMB)(usedMB->nextMB); /* Get next UMB */
|
||||||
|
|
||||||
|
if(preFMB == Co_NULL ) /* Is previous FMB==Co_NULL? */
|
||||||
|
{
|
||||||
|
nextFMB = FMBlist; /* Yes,get next FMB */
|
||||||
|
FMBlist = curFMB; /* Reset new FMB as the first item of FMB list */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nextFMB = preFMB->nextFMB; /* No,get next FMB */
|
||||||
|
preFMB->nextFMB = curFMB; /* Set link for FMB list */
|
||||||
|
}
|
||||||
|
|
||||||
|
curFMB->preUMB = preUMB; /* Set current FMB link for list */
|
||||||
|
curFMB->nextUMB = nextUMB;
|
||||||
|
curFMB->nextFMB = nextFMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(curFMB->preUMB != Co_NULL)/* Is current FMB as first item in kernel heap? */
|
||||||
|
{ /* No,set link for list */
|
||||||
|
preUMB = (P_UMB)((U32)(curFMB->preUMB)-1);
|
||||||
|
preUMB->nextMB = (void*)curFMB;
|
||||||
|
}
|
||||||
|
if(curFMB->nextUMB != Co_NULL)/* Is current FMB as last item in kernel heap? */
|
||||||
|
{ /* No,set link for list */
|
||||||
|
nextUMB = (P_UMB)((U32)(curFMB->nextUMB)-1);
|
||||||
|
nextUMB->preMB = (void*)curFMB;
|
||||||
|
}
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Get previous free memory block pointer.
|
||||||
|
* @param[in] usedMB Current used memory block.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval Previous free memory block pointer.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to get previous free memory block pointer.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
static P_FMB GetPreFMB(P_UMB usedMB)
|
||||||
|
{
|
||||||
|
P_UMB preUMB;
|
||||||
|
preUMB = usedMB;
|
||||||
|
while(((U32)(preUMB->preMB)&0x1)) /* Is previous MB as FMB? */
|
||||||
|
{ /* No,get previous MB */
|
||||||
|
preUMB = (P_UMB)((U32)(preUMB->preMB)-1);
|
||||||
|
}
|
||||||
|
return (P_FMB)(preUMB->preMB); /* Yes,return previous MB */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,356 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file mbox.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Mailbox management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*---------------------------- Include ---------------------------------------*/
|
||||||
|
#include <coocox.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if CFG_MAILBOX_EN > 0
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Create a mailbox
|
||||||
|
* @param[in] sortType Mail box waiting list sort type.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_CREATE_FAIL Create mailbox fail.
|
||||||
|
* @retval others Create mailbox successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to create a mailbox.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
OS_EventID CoCreateMbox(U8 sortType)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
|
||||||
|
/* Create a mailbox type event control block */
|
||||||
|
pecb = CreatEvent(EVENT_TYPE_MBOX,sortType,Co_NULL);
|
||||||
|
if(pecb == Co_NULL) /* If failed to create event block */
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL;
|
||||||
|
}
|
||||||
|
pecb->eventCounter = 0;
|
||||||
|
return (pecb->id); /* Create a mailbox successfully, return event ID */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Delete a mailbox
|
||||||
|
* @param[in] id Event ID.
|
||||||
|
* @param[in] opt Delete option.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID Invalid event ID.
|
||||||
|
* @retval E_INVALID_PARAMETER Invalid parameter.
|
||||||
|
* @retval E_TASK_WAITTING Tasks waitting for the event,delete fail.
|
||||||
|
* @retval E_OK Event deleted successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to delete a mailbox.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoDelMbox(OS_EventID id,U8 opt)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT) /* Judge id is valid or not? */
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Id is invalid ,return error */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(pecb->eventType != EVENT_TYPE_MBOX)/* Validate event control block type*/
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* The event is not mailbox */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return (DeleteEvent(pecb,opt)); /* Delete the mailbox event control block */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Accept a mailbox
|
||||||
|
* @param[in] id Event ID.
|
||||||
|
* @param[out] perr A pointer to error code.
|
||||||
|
* @retval Co_NULL
|
||||||
|
* @retval A pointer to mailbox accepted.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to accept a mailbox.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void* CoAcceptMail(OS_EventID id,StatusType* perr)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
void* pmail;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT)
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID; /* Invalid 'id' */
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(pecb->eventType != EVENT_TYPE_MBOX)/* Invalid event control block type */
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID;
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
OsSchedLock();
|
||||||
|
if(pecb->eventCounter == 1) /* If there is already a message */
|
||||||
|
{
|
||||||
|
*perr = E_OK;
|
||||||
|
pmail = pecb->eventPtr; /* Get the message */
|
||||||
|
pecb->eventPtr = Co_NULL; /* Clear the mailbox */
|
||||||
|
pecb->eventCounter = 0;
|
||||||
|
OsSchedUnlock();
|
||||||
|
return pmail; /* Return the message received */
|
||||||
|
}
|
||||||
|
else /* If the mailbox is empty */
|
||||||
|
{
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_MBOX_EMPTY; /* Mailbox is empty,return Co_NULL */
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Wait for a mailbox
|
||||||
|
* @param[in] id Event ID.
|
||||||
|
* @param[in] timeout The longest time for writting mail.
|
||||||
|
* @param[out] perr A pointer to error code.
|
||||||
|
* @retval Co_NULL
|
||||||
|
* @retval A pointer to mailbox accept.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to wait a mailbox.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void* CoPendMail(OS_EventID id,U32 timeout,StatusType* perr)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
void* pmail;
|
||||||
|
P_OSTCB curTCB;
|
||||||
|
|
||||||
|
if(OSIntNesting > 0) /* If the caller is ISR */
|
||||||
|
{
|
||||||
|
*perr = E_CALL;
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT)
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID; /* Invalid 'id',retrun error */
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(pecb->eventType != EVENT_TYPE_MBOX)
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID; /* Invalid event type,not EVENT_TYPE_MBOX */
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(OSSchedLock != 0) /* Judge schedule is locked or not? */
|
||||||
|
{
|
||||||
|
*perr = E_OS_IN_LOCK; /* Schedule is locked */
|
||||||
|
return Co_NULL; /* return Co_NULL */
|
||||||
|
}
|
||||||
|
OsSchedLock();
|
||||||
|
if( pecb->eventCounter == 1) /* If there is already a message */
|
||||||
|
{
|
||||||
|
*perr = E_OK;
|
||||||
|
pmail = pecb->eventPtr; /* Get the message */
|
||||||
|
pecb->eventPtr = Co_NULL; /* Clear the mailbox */
|
||||||
|
pecb->eventCounter = 0;
|
||||||
|
OsSchedUnlock();
|
||||||
|
return pmail; /* Return the message received */
|
||||||
|
}
|
||||||
|
else /* If message is not available, task will pend */
|
||||||
|
{
|
||||||
|
OsSchedUnlock();
|
||||||
|
curTCB = TCBRunning;
|
||||||
|
if(timeout == 0) /* If time-out is not configured */
|
||||||
|
{
|
||||||
|
EventTaskToWait(pecb,curTCB); /* Block task until event occurs */
|
||||||
|
*perr = E_OK;
|
||||||
|
|
||||||
|
/* Have recived a message or the mailbox have been deleted */
|
||||||
|
OsSchedLock();
|
||||||
|
pmail = curTCB->pmail;
|
||||||
|
pecb->eventCounter = 0;
|
||||||
|
curTCB->pmail = Co_NULL;
|
||||||
|
OsSchedUnlock();
|
||||||
|
return pmail; /* Return received message or Co_NULL */
|
||||||
|
}
|
||||||
|
else /* If time-out is configured */
|
||||||
|
{
|
||||||
|
OsSchedLock();
|
||||||
|
|
||||||
|
/* Block task until event or timeout occurs */
|
||||||
|
EventTaskToWait(pecb,curTCB);
|
||||||
|
InsertDelayList(curTCB,timeout);
|
||||||
|
OsSchedUnlock();
|
||||||
|
if( curTCB->pmail == Co_NULL) /* Time-out occurred */
|
||||||
|
{
|
||||||
|
*perr = E_TIMEOUT;
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
else /* Have recived a message or the mailbox have been deleted*/
|
||||||
|
{
|
||||||
|
*perr = E_OK;
|
||||||
|
|
||||||
|
OsSchedLock();
|
||||||
|
pmail = curTCB->pmail;
|
||||||
|
pecb->eventCounter = 0;
|
||||||
|
curTCB->pmail = Co_NULL;
|
||||||
|
OsSchedUnlock();
|
||||||
|
|
||||||
|
return pmail; /* Return received message or Co_NULL */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Post a mailbox
|
||||||
|
* @param[in] id Event ID.
|
||||||
|
* @param[in] pmail Pointer to mail that want to send.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID
|
||||||
|
* @retval E_OK
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to post a mail.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoPostMail(OS_EventID id,void* pmail)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Invalid id,return error */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(pecb->eventType != EVENT_TYPE_MBOX)/* Validate event control block type*/
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Event is not mailbox,return error*/
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(pecb->eventCounter == 0) /* If mailbox doesn't already have a message*/
|
||||||
|
{
|
||||||
|
OsSchedLock();
|
||||||
|
pecb->eventPtr = pmail; /* Place message in mailbox */
|
||||||
|
pecb->eventCounter = 1;
|
||||||
|
EventTaskToRdy(pecb); /* Check waiting list */
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
else /* If there is already a message in mailbox */
|
||||||
|
{
|
||||||
|
return E_MBOX_FULL; /* Mailbox is full,and return "E_MBOX_FULL" */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Post a mailbox in ISR
|
||||||
|
* @param[in] id Event ID.
|
||||||
|
* @param[in] pmail Pointer to mail that want to send.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID
|
||||||
|
* @retval E_OK
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to post a mail in ISR.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
#if CFG_MAX_SERVICE_REQUEST > 0
|
||||||
|
StatusType isr_PostMail(OS_EventID id,void* pmail)
|
||||||
|
{
|
||||||
|
if(OSSchedLock > 0) /* If scheduler is locked,(the caller is ISR) */
|
||||||
|
{
|
||||||
|
/* Insert the request into service request queue */
|
||||||
|
if(InsertInSRQ(MBOX_REQ,id,pmail) == Co_FALSE)
|
||||||
|
{
|
||||||
|
return E_SEV_REQ_FULL; /* If service request queue is full */
|
||||||
|
}
|
||||||
|
else /* Operate successfully */
|
||||||
|
{
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return(CoPostMail(id,pmail)); /* Sends the message to the mailbox */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,298 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file mm.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief memory management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------- Include ---------------------------------------*/
|
||||||
|
#include <coocox.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if CFG_MM_EN > 0
|
||||||
|
/*---------------------------- Variable Define -------------------------------*/
|
||||||
|
MM MemoryTbl[CFG_MAX_MM] = {{0}};/*!< Table which save memory control block. */
|
||||||
|
U32 MemoryIDVessel = 0; /*!< Memory ID container. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Create a memory partition
|
||||||
|
* @param[in] memBuf Specify memory partition head address.
|
||||||
|
* @param[in] blockSize Specify memory block size.
|
||||||
|
* @param[in] blockNum Specify memory block number.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_CREATE_FAIL Create memory partition fail.
|
||||||
|
* @retval others Create memory partition successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to create a memory partition.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
OS_MMID CoCreateMemPartition(U8* memBuf,U32 blockSize,U32 blockNum)
|
||||||
|
{
|
||||||
|
U8 i,j;
|
||||||
|
U8 *memory;
|
||||||
|
P_MemBlk memBlk;
|
||||||
|
memory = memBuf;
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(memBuf == Co_NULL)
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL;
|
||||||
|
}
|
||||||
|
if(blockSize == 0)
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL;
|
||||||
|
}
|
||||||
|
if((blockSize&0x3) != 0)
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL;
|
||||||
|
}
|
||||||
|
if(blockNum<=1)
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
for(i = 0; i < CFG_MAX_MM; i++)
|
||||||
|
{
|
||||||
|
if((MemoryIDVessel & (1 << i)) == 0) /* Is free memory ID? */
|
||||||
|
{
|
||||||
|
MemoryIDVessel |= (1<<i); /* Yes,assign ID to this memory block */
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
MemoryTbl[i].memAddr = memory;/* Initialize memory control block*/
|
||||||
|
MemoryTbl[i].freeBlock = memory;
|
||||||
|
MemoryTbl[i].blockSize = blockSize;
|
||||||
|
MemoryTbl[i].blockNum = blockNum;
|
||||||
|
memBlk = (P_MemBlk)memory; /* Bulid list in this memory block*/
|
||||||
|
for(j=0;j<blockNum-1;j++)
|
||||||
|
{
|
||||||
|
memory = memory+blockSize;
|
||||||
|
memBlk->nextBlock = (P_MemBlk)memory;
|
||||||
|
memBlk = memBlk->nextBlock;
|
||||||
|
}
|
||||||
|
memBlk->nextBlock = Co_NULL;
|
||||||
|
return i; /* Return memory block ID */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
return E_CREATE_FAIL; /* Error return */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Delete a memory partition
|
||||||
|
* @param[in] mmID Specify memory partition that want to delete.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID The memory partition id passed was invalid,delete fail.
|
||||||
|
* @retval E_OK Delete successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to Delete a memory partition.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoDelMemoryPartition(OS_MMID mmID)
|
||||||
|
{
|
||||||
|
P_MM memCtl;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(mmID >= CFG_MAX_MM)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
if( ((1<<mmID)&MemoryIDVessel) == 0)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
memCtl = &MemoryTbl[mmID]; /* Release memory control block */
|
||||||
|
MemoryIDVessel &= ~(1<<mmID);
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
|
||||||
|
memCtl->memAddr = Co_NULL;
|
||||||
|
memCtl->freeBlock = Co_NULL;
|
||||||
|
memCtl->blockSize = 0;
|
||||||
|
memCtl->blockNum = 0;
|
||||||
|
return E_OK; /* Return OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Get free block number in a memory partition
|
||||||
|
* @param[in] mmID Specify memory partition.
|
||||||
|
*
|
||||||
|
* @param[out] E_INVALID_ID Invalid ID was passed and get counter failure.
|
||||||
|
* @param[out] E_OK Get current counter successful.
|
||||||
|
* @retval fbNum The number of free block.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to get free block number in a memory
|
||||||
|
* partition.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
U32 CoGetFreeBlockNum(OS_MMID mmID,StatusType* perr)
|
||||||
|
{
|
||||||
|
U32 fbNum;
|
||||||
|
P_MM memCtl;
|
||||||
|
P_MemBlk memBlk;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(mmID >= CFG_MAX_MM)
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if( ((1<<mmID)&MemoryIDVessel) == 0)
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID; /* Invalid memory id,return 0 */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
memCtl = &MemoryTbl[mmID];
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
memBlk = (P_MemBlk)(memCtl->freeBlock);/* Get the free item in memory list*/
|
||||||
|
fbNum = 0;
|
||||||
|
while(memBlk != Co_NULL) /* Get counter of free item */
|
||||||
|
{
|
||||||
|
fbNum++;
|
||||||
|
memBlk = memBlk->nextBlock; /* Get next free iterm */
|
||||||
|
}
|
||||||
|
OsSchedUnlock(); /* Unlock schedul */
|
||||||
|
*perr = E_OK;
|
||||||
|
return fbNum; /* Return the counter of free item */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Get a memory buffer from memory partition
|
||||||
|
* @param[in] mmID Specify memory partition that want to assign buffer.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval Co_NULL Assign buffer fail.
|
||||||
|
* @retval others Assign buffer successful,and return the buffer pointer.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to Delete a memory partition.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void* CoGetMemoryBuffer(OS_MMID mmID)
|
||||||
|
{
|
||||||
|
P_MM memCtl;
|
||||||
|
P_MemBlk memBlk;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(mmID >= CFG_MAX_MM)
|
||||||
|
{
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
if( ((1<<mmID)&MemoryIDVessel) == 0)
|
||||||
|
{
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
memCtl = &MemoryTbl[mmID];
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
if(memCtl->freeBlock == Co_NULL ) /* Is there no free item in memory list */
|
||||||
|
{
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
return Co_NULL; /* Yes,error return */
|
||||||
|
}
|
||||||
|
memBlk = (P_MemBlk)memCtl->freeBlock; /* Get free memory block */
|
||||||
|
memCtl->freeBlock = (U8*)memBlk->nextBlock; /* Reset the first free item */
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
return memBlk; /* Return free memory block address */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Free a memory buffer to memory partition
|
||||||
|
* @param[in] mmID Specify memory partition.
|
||||||
|
* @param[in] buf Specify memory buffer that want to free.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID The memory partition id passed was invalid.
|
||||||
|
* @retval E_INVALID_PARAMETER The parameter passed was invalid.
|
||||||
|
* @retval E_OK Free successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to Delete a memory partition.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoFreeMemoryBuffer(OS_MMID mmID,void* buf)
|
||||||
|
{
|
||||||
|
P_MM memCtl;
|
||||||
|
P_MemBlk memBlk;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(mmID >= CFG_MAX_MM)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
if( ((1<<mmID)&MemoryIDVessel) == 0)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
if(buf == Co_NULL)
|
||||||
|
{
|
||||||
|
return E_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memCtl = &MemoryTbl[mmID];
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if((U32)buf < (U32)(memCtl->memAddr))
|
||||||
|
{
|
||||||
|
return E_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
if((U32)buf > (U32)(memCtl->memAddr + memCtl->blockSize*memCtl->blockNum))
|
||||||
|
{
|
||||||
|
return E_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
if(((U32)buf - (U32)(memCtl->memAddr))%(memCtl->blockSize) != 0)
|
||||||
|
{
|
||||||
|
return E_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
memBlk = (P_MemBlk)buf; /* Reset the first free item */
|
||||||
|
OsSchedLock();
|
||||||
|
memBlk->nextBlock = (P_MemBlk)memCtl->freeBlock;
|
||||||
|
memCtl->freeBlock = buf;
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_OK; /* Return OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,372 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file mutex.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Mutex management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 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 = Co_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 = Co_TRUE;
|
||||||
|
pCurTcb->TCBnext = Co_NULL;
|
||||||
|
pCurTcb->TCBprev = Co_NULL;
|
||||||
|
|
||||||
|
ptcb = pMutex->waittingList;
|
||||||
|
if(ptcb == Co_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 != Co_NULL) /* Insert the task to tail */
|
||||||
|
{
|
||||||
|
ptcb = ptcb->TCBnext;
|
||||||
|
}
|
||||||
|
ptcb->TCBnext = pCurTcb;
|
||||||
|
pCurTcb->TCBprev = ptcb;
|
||||||
|
pCurTcb->TCBnext = Co_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 == Co_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 != Co_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 = Co_NULL;
|
||||||
|
ptcb->TCBprev = Co_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 ==Co_NULL) && (ptcb->TCBprev == Co_NULL))
|
||||||
|
{
|
||||||
|
pMutex->waittingList = Co_NULL; /* Waiting list is empty */
|
||||||
|
}
|
||||||
|
else if(ptcb->TCBnext == Co_NULL) /* If the task is the last of waiting list*/
|
||||||
|
{
|
||||||
|
/* Remove task from mutex waiting list */
|
||||||
|
ptcb->TCBprev->TCBnext = Co_NULL;
|
||||||
|
ptcb->TCBprev = Co_NULL;
|
||||||
|
}
|
||||||
|
else if(ptcb->TCBprev == Co_NULL)/* If the task is the first of waiting list*/
|
||||||
|
{
|
||||||
|
/* Remove task from waiting list */
|
||||||
|
ptcb->TCBnext->TCBprev = Co_NULL;
|
||||||
|
ptcb->TCBnext = Co_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 = Co_NULL;
|
||||||
|
ptcb->TCBnext = Co_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 != Co_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
|
|
@ -0,0 +1,334 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file prot.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Compiler adapter for CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 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(volatile U8 *data) ;
|
||||||
|
extern U8 Dec8(volatile U8 *data) ;
|
||||||
|
extern void IRQ_ENABLE_RESTORE(void);
|
||||||
|
extern void IRQ_DISABLE_SAVE(void);
|
||||||
|
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 (volatile 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 (volatile 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 ENABLE Interrupt
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to ENABLE Interrupt.
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
void IRQ_ENABLE_RESTORE(void)
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" CPSIE I \n"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @brief Close Interrupt
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to close Interrupt.
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
void IRQ_DISABLE_SAVE(void)
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" CPSID I \n"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @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
|
||||||
|
(
|
||||||
|
#if CFG_CHIP_TYPE == 3
|
||||||
|
" SUB R0,#100 \n"
|
||||||
|
#else
|
||||||
|
" SUB R0,#28 \n"
|
||||||
|
#endif
|
||||||
|
" 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
|
||||||
|
// Maple
|
||||||
|
void __exc_pendsv(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 || 3 == CFG_CHIP_TYPE
|
||||||
|
// Maple
|
||||||
|
void __exc_pendsv(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)
|
||||||
|
#if CFG_CHIP_TYPE == 3
|
||||||
|
" VSTMDB R0!, {S16-S31} \n" // store remaining FPU registers
|
||||||
|
#endif // CFG_FPU_ENABLE
|
||||||
|
|
||||||
|
" 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.
|
||||||
|
|
||||||
|
#if CFG_CHIP_TYPE == 3
|
||||||
|
" VLDMIA R0!, {S16-S31} \n" // load remaining FPU registers
|
||||||
|
#endif // CFG_FPU_ENABLE
|
||||||
|
|
||||||
|
" 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
|
||||||
|
#if CFG_CHIP_TYPE == 3
|
||||||
|
" LDR LR,=0xFFFFFFED \n"
|
||||||
|
#endif
|
||||||
|
" BX LR \n" // Exit interrupt
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,432 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file queue.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Queue management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*---------------------------- Include ---------------------------------------*/
|
||||||
|
#include <coocox.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if CFG_QUEUE_EN > 0
|
||||||
|
/*---------------------------- Variable Define -------------------------------*/
|
||||||
|
QCB QueueTbl[CFG_MAX_QUEUE] = {{0}}; /*!< Queue control block table */
|
||||||
|
U32 QueueIDVessel = 0; /*!< Queue list mask */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Create a queue
|
||||||
|
* @param[in] qStart Pointer to mail pointer buffer.
|
||||||
|
* @param[in] size The length of queue.
|
||||||
|
* @param[in] sortType Mail queue waiting list sort type.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_CREATE_FAIL Create queue fail.
|
||||||
|
* @retval others Create queue successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to create a queue.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
OS_EventID CoCreateQueue(void **qStart, U16 size ,U8 sortType)
|
||||||
|
{
|
||||||
|
U8 i;
|
||||||
|
P_ECB pecb;
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if((qStart == Co_NULL) || (size == 0))
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OsSchedLock();
|
||||||
|
for(i = 0; i < CFG_MAX_QUEUE; i++)
|
||||||
|
{
|
||||||
|
/* Assign a free QUEUE control block */
|
||||||
|
if((QueueIDVessel & (1 << i)) == 0)
|
||||||
|
{
|
||||||
|
QueueIDVessel |= (1<<i);
|
||||||
|
OsSchedUnlock();
|
||||||
|
|
||||||
|
QueueTbl[i].qStart = qStart; /* Initialize the queue */
|
||||||
|
QueueTbl[i].id = i;
|
||||||
|
QueueTbl[i].head = 0;
|
||||||
|
QueueTbl[i].tail = 0;
|
||||||
|
QueueTbl[i].qMaxSize = size;
|
||||||
|
QueueTbl[i].qSize = 0;
|
||||||
|
|
||||||
|
/* Get a event control block and initial the event content */
|
||||||
|
pecb = CreatEvent(EVENT_TYPE_QUEUE,sortType,&QueueTbl[i]);
|
||||||
|
|
||||||
|
if(pecb == Co_NULL ) /* If there is no free EVENT control block*/
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL;
|
||||||
|
}
|
||||||
|
return (pecb->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_CREATE_FAIL; /* There is no free QUEUE control block */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Delete a queue
|
||||||
|
* @param[in] id Event ID.
|
||||||
|
* @param[in] opt Delete option.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID Invalid event ID.
|
||||||
|
* @retval E_INVALID_PARAMETER Invalid parameter.
|
||||||
|
* @retval E_TASK_WAITTING Tasks waitting for the event,delete fail.
|
||||||
|
* @retval E_OK Event deleted successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to delete a queue.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoDelQueue(OS_EventID id,U8 opt)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
P_QCB pqcb;
|
||||||
|
StatusType err;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* Invalid id,return error */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if( pecb->eventType != EVENT_TYPE_QUEUE)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* The event is not queue,return error*/
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
pqcb = (P_QCB)pecb->eventPtr; /* Point at queue control block */
|
||||||
|
err = DeleteEvent(pecb,opt); /* Delete the event control block */
|
||||||
|
if(err == E_OK) /* If the event block have been deleted */
|
||||||
|
{
|
||||||
|
QueueIDVessel &= ~((U32)(1<<(pqcb->id))); /* Update free queue list */
|
||||||
|
pqcb->qStart = Co_NULL;
|
||||||
|
pqcb->id = 0;
|
||||||
|
pqcb->head = 0;
|
||||||
|
pqcb->tail = 0;
|
||||||
|
pqcb->qMaxSize = 0;
|
||||||
|
pqcb->qSize = 0;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Accept a mail from queue
|
||||||
|
* @param[in] id Event ID.
|
||||||
|
* @param[out] perr A pointer to error code.
|
||||||
|
* @retval Co_NULL
|
||||||
|
* @retval A pointer to mail accepted.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to accept a mail from queue.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void* CoAcceptQueueMail(OS_EventID id,StatusType* perr)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
P_QCB pqcb;
|
||||||
|
void* pmail;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT)
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID; /* Invalid id,return error */
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(pecb->eventType != EVENT_TYPE_QUEUE)/* Invalid event control block type*/
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID;
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
pqcb = (P_QCB)pecb->eventPtr; /* Point at queue control block */
|
||||||
|
OsSchedLock();
|
||||||
|
if(pqcb->qSize != 0) /* If there are any messages in the queue */
|
||||||
|
{
|
||||||
|
/* Extract oldest message from the queue */
|
||||||
|
pmail = *(pqcb->qStart + pqcb->head);
|
||||||
|
pqcb->head++; /* Update the queue head */
|
||||||
|
pqcb->qSize--; /* Update the number of messages in the queue */
|
||||||
|
if(pqcb->head == pqcb->qMaxSize)
|
||||||
|
{
|
||||||
|
pqcb->head = 0;
|
||||||
|
}
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_OK;
|
||||||
|
return pmail; /* Return message received */
|
||||||
|
}
|
||||||
|
else /* If there is no message in the queue*/
|
||||||
|
{
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_QUEUE_EMPTY;
|
||||||
|
return Co_NULL; /* Return Co_NULL */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Pend for a mail
|
||||||
|
* @param[in] id Event ID.
|
||||||
|
* @param[in] timeout The longest time for writting mail.
|
||||||
|
* @param[out] perr A pointer to error code.
|
||||||
|
* @retval Co_NULL
|
||||||
|
* @retval A pointer to mail accept.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to wait for a mail.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void* CoPendQueueMail(OS_EventID id,U32 timeout,StatusType* perr)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
P_QCB pqcb;
|
||||||
|
P_OSTCB curTCB;
|
||||||
|
void* pmail;
|
||||||
|
if(OSIntNesting > 0) /* If the caller is ISR */
|
||||||
|
{
|
||||||
|
*perr = E_CALL;
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT)
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID; /* Invalid event id,return error */
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(pecb->eventType != EVENT_TYPE_QUEUE) /* The event type is not queue */
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID;
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if(OSSchedLock != 0) /* Judge schedule is locked or not? */
|
||||||
|
{
|
||||||
|
*perr = E_OS_IN_LOCK; /* Schedule is locked,return error */
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
pqcb = (P_QCB)pecb->eventPtr; /* Point at queue control block */
|
||||||
|
OsSchedLock();
|
||||||
|
if(pqcb->qSize != 0) /* If there are any messages in the queue */
|
||||||
|
{
|
||||||
|
/* Extract oldest message from the queue */
|
||||||
|
pmail = *(pqcb->qStart + pqcb->head);
|
||||||
|
pqcb->head++; /* Update the queue head */
|
||||||
|
pqcb->qSize--; /* Update the number of messages in the queue */
|
||||||
|
if(pqcb->head == pqcb->qMaxSize)/* Check queue head */
|
||||||
|
{
|
||||||
|
pqcb->head = 0;
|
||||||
|
}
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_OK;
|
||||||
|
return pmail; /* Return message received */
|
||||||
|
}
|
||||||
|
else /* If there is no message in the queue*/
|
||||||
|
{
|
||||||
|
OsSchedUnlock();
|
||||||
|
curTCB = TCBRunning;
|
||||||
|
if(timeout == 0) /* If time-out is not configured */
|
||||||
|
{
|
||||||
|
/* Block current task until the event occur */
|
||||||
|
EventTaskToWait(pecb,curTCB);
|
||||||
|
|
||||||
|
/* Have recived message or the queue have been deleted */
|
||||||
|
OsSchedLock();
|
||||||
|
pmail = curTCB->pmail;
|
||||||
|
curTCB->pmail = Co_NULL;
|
||||||
|
pqcb->head++; /* Clear event sign */
|
||||||
|
pqcb->qSize--;
|
||||||
|
if(pqcb->head == pqcb->qMaxSize)
|
||||||
|
{
|
||||||
|
pqcb->head = 0;
|
||||||
|
}
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_OK;
|
||||||
|
return pmail; /* Return message received or Co_NULL */
|
||||||
|
}
|
||||||
|
else /* If time-out is configured */
|
||||||
|
{
|
||||||
|
OsSchedLock();
|
||||||
|
|
||||||
|
/* Block current task until event or timeout occurs */
|
||||||
|
EventTaskToWait(pecb,curTCB);
|
||||||
|
InsertDelayList(curTCB,timeout);
|
||||||
|
OsSchedUnlock();
|
||||||
|
if(curTCB->pmail == Co_NULL) /* If time-out occurred */
|
||||||
|
{
|
||||||
|
*perr = E_TIMEOUT;
|
||||||
|
return Co_NULL;
|
||||||
|
}
|
||||||
|
else /* If event occured */
|
||||||
|
{
|
||||||
|
OsSchedLock();
|
||||||
|
pmail = curTCB->pmail;
|
||||||
|
curTCB->pmail = Co_NULL;
|
||||||
|
pqcb->head++; /* Clear event sign */
|
||||||
|
pqcb->qSize--;
|
||||||
|
if(pqcb->head == pqcb->qMaxSize)
|
||||||
|
{
|
||||||
|
pqcb->head = 0;
|
||||||
|
}
|
||||||
|
OsSchedUnlock();
|
||||||
|
*perr = E_OK;
|
||||||
|
return pmail; /* Return message received or Co_NULL */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Post a mail to queue
|
||||||
|
* @param[in] id Event ID.
|
||||||
|
* @param[in] pmail Pointer to mail that want to send.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_OK
|
||||||
|
* @retval E_INVALID_ID
|
||||||
|
* @retval E_QUEUE_FULL
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to post a mail to queue.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoPostQueueMail(OS_EventID id,void* pmail)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
P_QCB pqcb;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(pecb->eventType != EVENT_TYPE_QUEUE)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* The event type isn't queue,return */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
pqcb = (P_QCB)pecb->eventPtr;
|
||||||
|
if(pqcb->qSize == pqcb->qMaxSize) /* If queue is full */
|
||||||
|
{
|
||||||
|
return E_QUEUE_FULL;
|
||||||
|
}
|
||||||
|
else /* If queue is not full */
|
||||||
|
{
|
||||||
|
OsSchedLock();
|
||||||
|
*(pqcb->qStart + pqcb->tail) = pmail; /* Insert message into queue */
|
||||||
|
pqcb->tail++; /* Update queue tail */
|
||||||
|
pqcb->qSize++; /* Update the number of messages in the queue */
|
||||||
|
if(pqcb->tail == pqcb->qMaxSize) /* Check queue tail */
|
||||||
|
{
|
||||||
|
pqcb->tail = 0;
|
||||||
|
}
|
||||||
|
EventTaskToRdy(pecb); /* Check the event waiting list */
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Post a mail to queue in ISR
|
||||||
|
* @param[in] id Event ID.
|
||||||
|
* @param[in] pmail Pointer to mail that want to send.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_OK
|
||||||
|
* @retval E_INVALID_ID
|
||||||
|
* @retval E_QUEUE_FULL
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called in ISR to post a mail to queue.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
#if CFG_MAX_SERVICE_REQUEST > 0
|
||||||
|
StatusType isr_PostQueueMail(OS_EventID id,void* pmail)
|
||||||
|
{
|
||||||
|
if(OSSchedLock > 0) /* If scheduler is locked,(the caller is ISR) */
|
||||||
|
{
|
||||||
|
/* Insert the request into service request queue */
|
||||||
|
if(InsertInSRQ(QUEUE_REQ,id,pmail) == Co_FALSE)
|
||||||
|
{
|
||||||
|
return E_SEV_REQ_FULL; /* If service request queue is full */
|
||||||
|
}
|
||||||
|
else /* If the request have been inserted into service request queue */
|
||||||
|
{
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* The scheduler is unlocked */
|
||||||
|
{
|
||||||
|
return(CoPostQueueMail(id,pmail)); /* Send the message to the queue*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,347 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file sem.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Semaphore management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------- Include ---------------------------------------*/
|
||||||
|
#include <coocox.h>
|
||||||
|
|
||||||
|
#if CFG_SEM_EN >0
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Create a semaphore
|
||||||
|
* @param[in] initCnt Semaphore valid counter.
|
||||||
|
* @param[in] maxCnt Semaphore max initialize counter.
|
||||||
|
* @param[in] sortType Semaphore sort type.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_CREATE_FAIL Create semaphore fail.
|
||||||
|
* @retval others Create semaphore successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to create a semaphore.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
OS_EventID CoCreateSem(U16 initCnt,U16 maxCnt,U8 sortType)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(initCnt > maxCnt)
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL; /* Invalid 'initCnt' or 'maxCnt' */
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sortType != EVENT_SORT_TYPE_FIFO) && (sortType != EVENT_SORT_TYPE_PRIO))
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL; /* Illegal sort type,return error */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Create a semaphore type event control block */
|
||||||
|
pecb = CreatEvent(EVENT_TYPE_SEM,sortType,Co_NULL);
|
||||||
|
if(pecb == Co_NULL) /* If failed to create event block */
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL;
|
||||||
|
}
|
||||||
|
pecb->eventCounter = initCnt;/* Initialize event block */
|
||||||
|
pecb->initialEventCounter = maxCnt;
|
||||||
|
return (pecb->id); /* Return event id */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Delete a semaphore
|
||||||
|
* @param[in] id Event ID which to be deleted.
|
||||||
|
* @param[in] opt Delete option.
|
||||||
|
* @arg == OPT_DEL_ANYWAY Delete semaphore always
|
||||||
|
* @arg == OPT_DEL_NO_PEND Delete semaphore only when no task pending on.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID Invalid event ID.
|
||||||
|
* @retval E_INVALID_PARAMETER Invalid parameter.
|
||||||
|
* @retval E_TASK_WAITTING Tasks waitting for the event,delete fail.
|
||||||
|
* @retval E_OK Event deleted successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to delete a semaphore.
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoDelSem(OS_EventID id,U8 opt)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(pecb->eventType != EVENT_TYPE_SEM)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID; /* The event type is not semaphore */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (DeleteEvent(pecb,opt));/* Delete the semaphore event control block*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Accept a semaphore without waitting
|
||||||
|
* @param[in] id Event ID
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID Invalid event ID.
|
||||||
|
* @retval E_SEM_EMPTY No semaphore exist.
|
||||||
|
* @retval E_OK Get semaphore successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called accept a semaphore without waitting.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoAcceptSem(OS_EventID id)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if( pecb->eventType != EVENT_TYPE_SEM)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
OsSchedLock();
|
||||||
|
if(pecb->eventCounter > 0) /* If semaphore is positive,resource available */
|
||||||
|
{
|
||||||
|
pecb->eventCounter--; /* Decrement semaphore only if positive */
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
else /* Resource is not available */
|
||||||
|
{
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_SEM_EMPTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief wait for a semaphore
|
||||||
|
* @param[in] id Event ID.
|
||||||
|
* @param[in] timeout The longest time for writting semaphore.
|
||||||
|
* @para 0
|
||||||
|
* @para 0x1~0xff
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_CALL Error call in ISR.
|
||||||
|
* @retval E_INVALID_ID Invalid event ID.
|
||||||
|
* @retval E_TIMEOUT Semaphore was not received within the specified
|
||||||
|
* 'timeout' time.
|
||||||
|
* @retval E_OK The call was successful and your task owns the
|
||||||
|
* resource,or the event you are waiting for occurred.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to waits for a semaphore.
|
||||||
|
* @note IF this function is called in ISR,nothing to do and return immediately.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoPendSem(OS_EventID id,U32 timeout)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
P_OSTCB curTCB;
|
||||||
|
if(OSIntNesting > 0) /* If the caller is ISR */
|
||||||
|
{
|
||||||
|
return E_CALL;
|
||||||
|
}
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(pecb->eventType != EVENT_TYPE_SEM)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if(OSSchedLock != 0) /* Schdule is locked? */
|
||||||
|
{
|
||||||
|
return E_OS_IN_LOCK; /* Yes,error return */
|
||||||
|
}
|
||||||
|
OsSchedLock();
|
||||||
|
if(pecb->eventCounter > 0) /* If semaphore is positive,resource available */
|
||||||
|
{
|
||||||
|
pecb->eventCounter--; /* Decrement semaphore only if positive */
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
else /* Resource is not available */
|
||||||
|
{
|
||||||
|
curTCB = TCBRunning;
|
||||||
|
if(timeout == 0) /* If time-out is not configured */
|
||||||
|
{
|
||||||
|
EventTaskToWait(pecb,curTCB); /* Block task until event occurs */
|
||||||
|
pecb->eventCounter--;
|
||||||
|
curTCB->pmail = Co_NULL;
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
else /* If time-out is configured */
|
||||||
|
{
|
||||||
|
/* Block task until event or timeout occurs */
|
||||||
|
EventTaskToWait(pecb,curTCB);
|
||||||
|
InsertDelayList(curTCB,timeout);
|
||||||
|
|
||||||
|
OsSchedUnlock();
|
||||||
|
if (curTCB->pmail == Co_NULL) /* If pmail is Co_NULL, time-out occurred*/
|
||||||
|
{
|
||||||
|
return E_TIMEOUT;
|
||||||
|
}
|
||||||
|
else /* Event occurred or event have been deleted*/
|
||||||
|
{
|
||||||
|
OsSchedLock();
|
||||||
|
curTCB->pmail = Co_NULL;
|
||||||
|
pecb->eventCounter--;
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Post a semaphore
|
||||||
|
* @param[in] id id of event control block associated with the desired semaphore.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID Parameter id passed was invalid event ID.
|
||||||
|
* @retval E_SEM_FULL Semaphore full.
|
||||||
|
* @retval E_OK Semaphore had post successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to post a semaphore to corresponding event.
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoPostSem(OS_EventID id)
|
||||||
|
{
|
||||||
|
P_ECB pecb;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(id >= CFG_MAX_EVENT)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pecb = &EventTbl[id];
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0
|
||||||
|
if(pecb->eventType != EVENT_TYPE_SEM) /* Invalid event control block type */
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Make sure semaphore will not overflow */
|
||||||
|
if(pecb->eventCounter == pecb->initialEventCounter)
|
||||||
|
{
|
||||||
|
return E_SEM_FULL; /* The counter of Semaphore reach the max number*/
|
||||||
|
}
|
||||||
|
OsSchedLock();
|
||||||
|
pecb->eventCounter++; /* Increment semaphore count to register event */
|
||||||
|
EventTaskToRdy(pecb); /* Check semaphore event waiting list */
|
||||||
|
OsSchedUnlock();
|
||||||
|
return E_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Post a semaphore in ISR
|
||||||
|
* @param[in] id identifier of event control block associated with the
|
||||||
|
* desired semaphore.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID Parameter id passed was invalid event ID.
|
||||||
|
* @retval E_NO_TASK_WAITTING There are one more tasks waitting for the event.
|
||||||
|
* @retval E_OK Semaphore had signaled successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called in ISR to post a semaphore to corresponding
|
||||||
|
* event.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
#if CFG_MAX_SERVICE_REQUEST > 0
|
||||||
|
StatusType isr_PostSem(OS_EventID id)
|
||||||
|
{
|
||||||
|
if(OSSchedLock > 0) /* If scheduler is locked,(the caller is ISR) */
|
||||||
|
{
|
||||||
|
/* Initiate a post service handling request */
|
||||||
|
if(InsertInSRQ(SEM_REQ,id,Co_NULL) == Co_FALSE)
|
||||||
|
{
|
||||||
|
return E_SEV_REQ_FULL; /* If service request queue is full */
|
||||||
|
}
|
||||||
|
else /* Operate successfully */
|
||||||
|
{
|
||||||
|
return E_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return(CoPostSem(id)); /* Post semaphore */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,188 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file serviceReq.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief servive request management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------- Include ---------------------------------------*/
|
||||||
|
#include <coocox.h>
|
||||||
|
|
||||||
|
#if (CFG_TASK_WAITTING_EN > 0) || (CFG_TMR_EN >0)
|
||||||
|
|
||||||
|
#if CFG_MAX_SERVICE_REQUEST > 0
|
||||||
|
/*---------------------------- Variable Define -------------------------------*/
|
||||||
|
SRQ ServiceReq = {0,0}; /*!< ISR server request queue */
|
||||||
|
#endif
|
||||||
|
BOOL IsrReq = Co_FALSE;
|
||||||
|
#if (CFG_TASK_WAITTING_EN > 0)
|
||||||
|
BOOL TimeReq = Co_FALSE; /*!< Time delay dispose request */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TMR_EN > 0
|
||||||
|
BOOL TimerReq = Co_FALSE; /*!< Timer dispose request */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Insert into service requst queue
|
||||||
|
* @param[in] type Service request type.
|
||||||
|
* @param[in] id Service request event id,event id/flag id.
|
||||||
|
* @param[in] arg Service request argument.
|
||||||
|
* @param[out] None
|
||||||
|
*
|
||||||
|
* @retval Co_FALSE Successfully insert into service request queue.
|
||||||
|
* @retval Co_TRUE Failure to insert into service request queue.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function be called to insert a requst into service request
|
||||||
|
* queue.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
#if (CFG_MAX_SERVICE_REQUEST > 0)
|
||||||
|
BOOL InsertInSRQ(U8 type,U8 id,void* arg)
|
||||||
|
{
|
||||||
|
P_SQC pcell;
|
||||||
|
U8 cnt;
|
||||||
|
U8 heed;
|
||||||
|
IRQ_DISABLE_SAVE();
|
||||||
|
if (ServiceReq.cnt >= CFG_MAX_SERVICE_REQUEST)
|
||||||
|
{
|
||||||
|
IRQ_ENABLE_RESTORE ();
|
||||||
|
|
||||||
|
return Co_FALSE; /* Error return */
|
||||||
|
}
|
||||||
|
cnt = Inc8(&ServiceReq.cnt);
|
||||||
|
heed = ServiceReq.head;
|
||||||
|
IsrReq = Co_TRUE;
|
||||||
|
pcell = &ServiceReq.cell[((cnt+heed)%CFG_MAX_SERVICE_REQUEST)];/*the tail */
|
||||||
|
pcell->type = type; /* Save service request type, */
|
||||||
|
pcell->id = id; /* event id */
|
||||||
|
pcell->arg = arg; /* and parameter */
|
||||||
|
IRQ_ENABLE_RESTORE ();
|
||||||
|
|
||||||
|
return Co_TRUE; /* Return OK */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Respond the request in the service request queue.
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function be called to respond the request in the service
|
||||||
|
* request queue.
|
||||||
|
* @note
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void RespondSRQ(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if CFG_MAX_SERVICE_REQUEST > 0
|
||||||
|
SQC cell;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (CFG_TASK_WAITTING_EN > 0)
|
||||||
|
if(TimeReq == Co_TRUE) /* Time delay request? */
|
||||||
|
{
|
||||||
|
TimeDispose(); /* Yes,call handler */
|
||||||
|
TimeReq = Co_FALSE; /* Reset time delay request Co_FALSE */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if CFG_TMR_EN > 0
|
||||||
|
if(TimerReq == Co_TRUE) /* Timer request? */
|
||||||
|
{
|
||||||
|
TmrDispose(); /* Yes,call handler */
|
||||||
|
TimerReq = Co_FALSE; /* Reset timer request Co_FALSE */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_MAX_SERVICE_REQUEST > 0
|
||||||
|
|
||||||
|
while (ServiceReq.cnt != 0)
|
||||||
|
{
|
||||||
|
IRQ_DISABLE_SAVE (); /* need to protect the following */
|
||||||
|
cell = ServiceReq.cell[ServiceReq.head]; /* extract one cell */
|
||||||
|
ServiceReq.head = (ServiceReq.head + 1) % /* move head (pop) */
|
||||||
|
CFG_MAX_SERVICE_REQUEST;
|
||||||
|
ServiceReq.cnt--;
|
||||||
|
IRQ_ENABLE_RESTORE (); /* now use the cell copy */
|
||||||
|
|
||||||
|
switch(cell.type) /* Judge service request type */
|
||||||
|
{
|
||||||
|
#if CFG_SEM_EN > 0
|
||||||
|
case SEM_REQ: /* Semaphore post request,call handler*/
|
||||||
|
CoPostSem(cell.id);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if CFG_MAILBOX_EN > 0
|
||||||
|
case MBOX_REQ: /* Mailbox post request,call handler */
|
||||||
|
CoPostMail(cell.id, cell.arg);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if CFG_FLAG_EN > 0
|
||||||
|
case FLAG_REQ: /* Flag set request,call handler */
|
||||||
|
CoSetFlag(cell.id);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if CFG_QUEUE_EN > 0
|
||||||
|
case QUEUE_REQ: /* Queue post request,call handler */
|
||||||
|
CoPostQueueMail(cell.id, cell.arg);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default: /* Others,break */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
IRQ_DISABLE_SAVE (); /* need to protect the following */
|
||||||
|
|
||||||
|
if (ServiceReq.cnt == 0) /* another item in the queue already? */
|
||||||
|
{
|
||||||
|
IsrReq = Co_FALSE; /* queue still empty here */
|
||||||
|
}
|
||||||
|
IRQ_ENABLE_RESTORE (); /* now it is done and return */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,399 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file time.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief time management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------- Include ---------------------------------------*/
|
||||||
|
#include <coocox.h>
|
||||||
|
|
||||||
|
#if CFG_TASK_WAITTING_EN > 0
|
||||||
|
|
||||||
|
/*---------------------------- Variable Define -------------------------------*/
|
||||||
|
P_OSTCB DlyList = Co_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 == Co_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 != Co_NULL)
|
||||||
|
{
|
||||||
|
/* Get delta ticks with previous item */
|
||||||
|
deltaTicks -= dlyNext->delayTick;
|
||||||
|
if(deltaTicks < 0) /* Is delta ticks<0? */
|
||||||
|
{
|
||||||
|
/* Yes,get correct place */
|
||||||
|
if(dlyNext->TCBprev != Co_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 == Co_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 = Co_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Remove from the DELAY list
|
||||||
|
* @param[in] ptcb Task that want to remove from the DELAY list.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to remove task from the DELAY list.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void RemoveDelayList(P_OSTCB ptcb)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Is there only one item in the DELAY list? */
|
||||||
|
if((ptcb->TCBprev == Co_NULL) && ( ptcb->TCBnext == Co_NULL))
|
||||||
|
{
|
||||||
|
DlyList = Co_NULL; /* Yes,set DELAY list as Co_NULL */
|
||||||
|
}
|
||||||
|
else if(ptcb->TCBprev == Co_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 = Co_NULL;
|
||||||
|
ptcb->TCBnext = Co_NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(ptcb->TCBnext == Co_NULL) /* Is the last item in DELAY list? */
|
||||||
|
{
|
||||||
|
ptcb->TCBprev->TCBnext = Co_NULL; /* Yes,remove task form DELAY list */
|
||||||
|
ptcb->TCBprev = Co_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 = Co_NULL;
|
||||||
|
ptcb->TCBprev = Co_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 == Co_NULL)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(ptcb->delayTick == INVALID_VALUE) /* Is tick==INVALID_VALUE? */
|
||||||
|
{
|
||||||
|
return E_NOT_IN_DELAY_LIST; /* Yes,error return */
|
||||||
|
}
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
RemoveDelayList(ptcb); /* Remove task from the DELAY list */
|
||||||
|
|
||||||
|
if(ticks == 0) /* Is delay tick==0? */
|
||||||
|
{
|
||||||
|
InsertToTCBRdyList(ptcb); /* Insert task into the DELAY list */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InsertDelayList(ptcb,ticks); /* No,insert task into DELAY list */
|
||||||
|
}
|
||||||
|
OsSchedUnlock(); /* Unlock schedule,and call task schedule */
|
||||||
|
return E_OK; /* Return OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Delay current task for detail time
|
||||||
|
* @param[in] hour Specify the number of hours.
|
||||||
|
* @param[in] minute Specify the number of minutes.
|
||||||
|
* @param[in] sec Specify the number of seconds.
|
||||||
|
* @param[in] millsec Specify the number of millseconds.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_CALL Error call in ISR.
|
||||||
|
* @retval E_INVALID_PARAMETER Parameter passed was invalid,delay fail.
|
||||||
|
* @retval E_OK The current task was inserted to DELAY list
|
||||||
|
* successful,it will delay for specify time.
|
||||||
|
* @par Description
|
||||||
|
* @details This function delay specify time for current task.
|
||||||
|
*
|
||||||
|
* @note If this function called in ISR,do nothing and return immediately.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
#if CFG_TIME_DELAY_EN >0
|
||||||
|
StatusType CoTimeDelay(U8 hour,U8 minute,U8 sec,U16 millsec)
|
||||||
|
{
|
||||||
|
U32 ticks;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(OSIntNesting > 0)
|
||||||
|
{
|
||||||
|
return E_CALL;
|
||||||
|
}
|
||||||
|
if((minute > 59)||(sec > 59)||(millsec > 999))
|
||||||
|
return E_INVALID_PARAMETER;
|
||||||
|
#endif
|
||||||
|
if(OSSchedLock != 0) /* Is OS lock? */
|
||||||
|
{
|
||||||
|
return E_OS_IN_LOCK; /* Yes,error return */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get tick counter from time */
|
||||||
|
ticks = ((hour*3600) + (minute*60) + (sec)) * (CFG_SYSTICK_FREQ)\
|
||||||
|
+ (millsec*CFG_SYSTICK_FREQ + 500)/1000;
|
||||||
|
|
||||||
|
CoTickDelay(ticks); /* Call tick delay */
|
||||||
|
return E_OK; /* Return OK */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Dispose time delay
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to dispose time delay of all task.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void TimeDispose(void)
|
||||||
|
{
|
||||||
|
P_OSTCB dlyList;
|
||||||
|
|
||||||
|
dlyList = DlyList; /* Get first item of DELAY list */
|
||||||
|
while((dlyList != Co_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 != Co_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 = Co_NULL;
|
||||||
|
|
||||||
|
InsertToTCBRdyList(dlyList); /* Insert task into READY list */
|
||||||
|
|
||||||
|
dlyList = DlyList; /* Get the first item of DELAY list */
|
||||||
|
if(dlyList != Co_NULL) /* Is DELAY list as Co_NULL? */
|
||||||
|
{
|
||||||
|
dlyList->TCBprev = Co_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 = Co_TRUE;
|
||||||
|
TimeReq = Co_TRUE; /* Yes,set time request Co_TRUE */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TimeDispose(); /* No,call handler */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,470 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file timer.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief timer management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 CooCox </center></h2>
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------- Include ---------------------------------------*/
|
||||||
|
#include <coocox.h>
|
||||||
|
|
||||||
|
/*---------------------------- Variable Define -------------------------------*/
|
||||||
|
#if CFG_TMR_EN > 0
|
||||||
|
|
||||||
|
TmrCtrl TmrTbl[CFG_MAX_TMR]= {{0}};/*!< Table which save timer control block.*/
|
||||||
|
P_TmrCtrl TmrList = Co_NULL; /*!< The header of the TmrCtrl list. */
|
||||||
|
U32 TmrIDVessel = 0; /*!< Timer ID container. */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Insert a timer into the timer list
|
||||||
|
* @param[in] tmrID Specify timer ID which insertted.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID Timer ID passed was invalid,insert fail.
|
||||||
|
* @retval E_OK Insert successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to insert a timer into the timer list.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
static void InsertTmrList(OS_TCID tmrID)
|
||||||
|
{
|
||||||
|
P_TmrCtrl pTmr;
|
||||||
|
S32 deltaTicks;
|
||||||
|
U32 tmrCnt;
|
||||||
|
tmrCnt = TmrTbl[tmrID].tmrCnt; /* Get timer time */
|
||||||
|
|
||||||
|
if(tmrCnt == 0) /* Is timer time==0? */
|
||||||
|
{
|
||||||
|
return; /* Do nothing,return */
|
||||||
|
}
|
||||||
|
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
if(TmrList == Co_NULL) /* Is no item in timer list? */
|
||||||
|
{
|
||||||
|
TmrList = &TmrTbl[tmrID]; /* Yes,set this as first item */
|
||||||
|
}
|
||||||
|
else /* No,find correct place ,and insert inserted timer */
|
||||||
|
{
|
||||||
|
pTmr = TmrList;
|
||||||
|
deltaTicks = tmrCnt; /* Get timer tick */
|
||||||
|
|
||||||
|
/* find correct place */
|
||||||
|
while(pTmr != Co_NULL)
|
||||||
|
{
|
||||||
|
deltaTicks -= pTmr->tmrCnt; /* Get ticks with previous item */
|
||||||
|
if(deltaTicks < 0) /* Is delta ticks<0? */
|
||||||
|
{
|
||||||
|
/* Yes,get correct place */
|
||||||
|
if(pTmr->tmrPrev!= Co_NULL)/* Is head item of timer list? */
|
||||||
|
{
|
||||||
|
/* No,insert into */
|
||||||
|
pTmr->tmrPrev->tmrNext = &TmrTbl[tmrID];
|
||||||
|
TmrTbl[tmrID].tmrPrev = pTmr->tmrPrev;
|
||||||
|
TmrTbl[tmrID].tmrNext = pTmr;
|
||||||
|
pTmr->tmrPrev = &TmrTbl[tmrID];
|
||||||
|
}
|
||||||
|
else /* Yes,set task as first item */
|
||||||
|
{
|
||||||
|
TmrTbl[tmrID].tmrNext = TmrList;
|
||||||
|
TmrList->tmrPrev = &TmrTbl[tmrID];
|
||||||
|
TmrList = &TmrTbl[tmrID];
|
||||||
|
}
|
||||||
|
TmrTbl[tmrID].tmrCnt = TmrTbl[tmrID].tmrNext->tmrCnt+deltaTicks;
|
||||||
|
TmrTbl[tmrID].tmrNext->tmrCnt -= TmrTbl[tmrID].tmrCnt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Is last item in list? */
|
||||||
|
else if((deltaTicks >= 0) && (pTmr->tmrNext == Co_NULL))
|
||||||
|
{
|
||||||
|
/* Yes,insert into */
|
||||||
|
TmrTbl[tmrID].tmrPrev = pTmr;
|
||||||
|
pTmr->tmrNext = &TmrTbl[tmrID];
|
||||||
|
TmrTbl[tmrID].tmrCnt = deltaTicks;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pTmr = pTmr->tmrNext; /* Get the next item in timer list */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Remove a timer from the timer list
|
||||||
|
* @param[in] tmrID Specify ID for a timer which removed form timer list.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to remove a timer from the timer list.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
static void RemoveTmrList(OS_TCID tmrID)
|
||||||
|
{
|
||||||
|
P_TmrCtrl pTmr;
|
||||||
|
|
||||||
|
pTmr = &TmrTbl[tmrID];
|
||||||
|
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
|
||||||
|
/* Is there only one item in timer list? */
|
||||||
|
if((pTmr->tmrPrev == Co_NULL) && (pTmr->tmrNext == Co_NULL))
|
||||||
|
{
|
||||||
|
TmrList = Co_NULL; /* Yes,set timer list as Co_NULL */
|
||||||
|
}
|
||||||
|
else if(pTmr->tmrPrev == Co_NULL) /* Is the first item in timer list? */
|
||||||
|
{ /* Yes,remove timer from list,and reset timer list */
|
||||||
|
TmrList = pTmr->tmrNext;
|
||||||
|
TmrList->tmrPrev = Co_NULL;
|
||||||
|
pTmr->tmrNext->tmrCnt += pTmr->tmrCnt;
|
||||||
|
pTmr->tmrNext = Co_NULL;
|
||||||
|
}
|
||||||
|
else if(pTmr->tmrNext == Co_NULL) /* Is the last item in timer list? */
|
||||||
|
{
|
||||||
|
/* Yes,remove timer form list */
|
||||||
|
pTmr->tmrPrev->tmrNext = Co_NULL;
|
||||||
|
pTmr->tmrPrev = Co_NULL;
|
||||||
|
}
|
||||||
|
else /* No, remove timer from list */
|
||||||
|
{
|
||||||
|
pTmr->tmrPrev->tmrNext = pTmr->tmrNext;
|
||||||
|
pTmr->tmrNext->tmrPrev = pTmr->tmrPrev;
|
||||||
|
pTmr->tmrNext->tmrCnt += pTmr->tmrCnt;
|
||||||
|
pTmr->tmrNext = Co_NULL;
|
||||||
|
pTmr->tmrPrev = Co_NULL;
|
||||||
|
}
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Create a timer
|
||||||
|
* @param[in] tmrType Specify timer's type.
|
||||||
|
* @param[in] tmrCnt Specify timer initial counter value.
|
||||||
|
* @param[in] tmrReload Specify timer reload value.
|
||||||
|
* @param[in] func Specify timer callback function entry.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_CREATE_FAIL Create timer fail.
|
||||||
|
* @retval others Create timer successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to create a timer.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
OS_TCID CoCreateTmr(U8 tmrType, U32 tmrCnt, U32 tmrReload, vFUNCPtr func)
|
||||||
|
{
|
||||||
|
U8 i;
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if((tmrType != TMR_TYPE_ONE_SHOT) && (tmrType != TMR_TYPE_PERIODIC))
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL;
|
||||||
|
}
|
||||||
|
if(func == Co_NULL)
|
||||||
|
{
|
||||||
|
return E_CREATE_FAIL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
OsSchedLock(); /* Lock schedule */
|
||||||
|
for(i = 0; i < CFG_MAX_TMR; i++)
|
||||||
|
{
|
||||||
|
if((TmrIDVessel & (1 << i)) == 0) /* Is free timer ID? */
|
||||||
|
{
|
||||||
|
TmrIDVessel |= (1<<i); /* Yes,assign ID to this timer */
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
TmrTbl[i].tmrID = i; /* Initialize timer as user set */
|
||||||
|
TmrTbl[i].tmrType = tmrType;
|
||||||
|
TmrTbl[i].tmrState = TMR_STATE_STOPPED;
|
||||||
|
TmrTbl[i].tmrCnt = tmrCnt;
|
||||||
|
TmrTbl[i].tmrReload = tmrReload;
|
||||||
|
TmrTbl[i].tmrCallBack = func;
|
||||||
|
TmrTbl[i].tmrPrev = Co_NULL;
|
||||||
|
TmrTbl[i].tmrNext = Co_NULL;
|
||||||
|
return i; /* Return timer ID */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OsSchedUnlock(); /* Unlock schedule */
|
||||||
|
return E_CREATE_FAIL; /* Error return */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Start counter
|
||||||
|
* @param[in] tmrID Specify a timer which startted.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID The timer id passed was invalid,can't start timer
|
||||||
|
* @retval E_OK Insert a timer to timer list and start it successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to make a timer start countering.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoStartTmr(OS_TCID tmrID)
|
||||||
|
{
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(tmrID >= CFG_MAX_TMR)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
if( (TmrIDVessel & (1<<tmrID)) == 0)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(TmrTbl[tmrID].tmrState == TMR_STATE_RUNNING) /* Is timer running? */
|
||||||
|
{
|
||||||
|
return E_OK; /* Yes,do nothing,return OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No,set timer status as TMR_STATE_RUNNING */
|
||||||
|
TmrTbl[tmrID].tmrState = TMR_STATE_RUNNING;
|
||||||
|
InsertTmrList(tmrID); /* Insert this timer into timer list */
|
||||||
|
return E_OK; /* Return OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Stop countering for a spcify timer
|
||||||
|
* @param[in] tmrID Specify a timer which stopped.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID The timer id passed was invalid, stop failure.
|
||||||
|
* @retval E_OK Stop a timer countering successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to stop a timer from counting.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoStopTmr(OS_TCID tmrID)
|
||||||
|
{
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(tmrID >= CFG_MAX_TMR)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
if((TmrIDVessel & (1<<tmrID)) == 0)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
if(TmrTbl[tmrID].tmrState == TMR_STATE_STOPPED)/* Does timer stop running?*/
|
||||||
|
{
|
||||||
|
return E_OK; /* Yes,do nothing,return OK */
|
||||||
|
}
|
||||||
|
RemoveTmrList(tmrID); /* No,remove this timer from timer list */
|
||||||
|
|
||||||
|
/* Set timer status as TMR_STATE_STOPPED */
|
||||||
|
TmrTbl[tmrID].tmrState = TMR_STATE_STOPPED;
|
||||||
|
return E_OK; /* Return OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Delete a timer
|
||||||
|
* @param[in] tmrID Specify a timer which deleted.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID The timer id passed was invalid,deleted failure.
|
||||||
|
* @retval E_OK Delete a timer successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to delete a timer which created before.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoDelTmr(OS_TCID tmrID)
|
||||||
|
{
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(tmrID >= CFG_MAX_TMR)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
if( (TmrIDVessel & (1<<tmrID)) == 0)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(TmrTbl[tmrID].tmrState == TMR_STATE_RUNNING) /* Is timer running? */
|
||||||
|
{
|
||||||
|
RemoveTmrList(tmrID); /* Yes,remove this timer from timer list*/
|
||||||
|
}
|
||||||
|
TmrIDVessel &=~(1<<tmrID); /* Release resource that this timer hold*/
|
||||||
|
return E_OK; /* Return OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Get current counter of specify timer
|
||||||
|
* @param[in] tmrID Specify timer by ID.
|
||||||
|
* @param[out] E_INVALID_ID Invalid ID was passed and get counter failure.
|
||||||
|
* @param[out] E_OK Get current counter successful.
|
||||||
|
* @retval Current counter of a timer which specify by id.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to obtain current counter of specify timer.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
U32 CoGetCurTmrCnt(OS_TCID tmrID,StatusType* perr)
|
||||||
|
{
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(tmrID >= CFG_MAX_TMR)
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if((TmrIDVessel & (1<<tmrID)) == 0)
|
||||||
|
{
|
||||||
|
*perr = E_INVALID_ID;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
*perr = E_OK;
|
||||||
|
return TmrTbl[tmrID].tmrCnt; /* Return timer counter */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Setting for a specify timer
|
||||||
|
* @param[in] tmrID Specify timer by ID.
|
||||||
|
* @param[in] tmrCnt Specify timer counter which need to be set.
|
||||||
|
* @param[in] tmrReload Specify timer reload value which need to be set.
|
||||||
|
* @param[out] None
|
||||||
|
* @retval E_INVALID_ID The ID passed was invalid,set fail.
|
||||||
|
* @retval E_OK Set timer counter successful.
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to set timer counter and reload value.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
StatusType CoSetTmrCnt(OS_TCID tmrID,U32 tmrCnt,U32 tmrReload)
|
||||||
|
{
|
||||||
|
#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */
|
||||||
|
if(tmrID >= CFG_MAX_TMR)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
if( (TmrIDVessel & (1<<tmrID)) == 0)
|
||||||
|
{
|
||||||
|
return E_INVALID_ID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
TmrTbl[tmrID].tmrCnt = tmrCnt; /* Reset timer counter and reload value */
|
||||||
|
TmrTbl[tmrID].tmrReload = tmrReload;
|
||||||
|
|
||||||
|
if(TmrTbl[tmrID].tmrState == TMR_STATE_RUNNING) /* Is timer running? */
|
||||||
|
{
|
||||||
|
RemoveTmrList(tmrID); /* Yes,reorder timer in timer list */
|
||||||
|
InsertTmrList(tmrID);
|
||||||
|
}
|
||||||
|
return E_OK; /* Return OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Timer counter dispose
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to dispose timer counter.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void TmrDispose(void)
|
||||||
|
{
|
||||||
|
P_TmrCtrl pTmr;
|
||||||
|
|
||||||
|
pTmr = TmrList; /* Get first item of timer list */
|
||||||
|
while((pTmr != Co_NULL) && (pTmr->tmrCnt == 0) )
|
||||||
|
{
|
||||||
|
if(pTmr->tmrType == TMR_TYPE_ONE_SHOT) /* Is a One-shot timer? */
|
||||||
|
{
|
||||||
|
/* Yes,remove this timer from timer list */
|
||||||
|
RemoveTmrList(pTmr->tmrID);
|
||||||
|
|
||||||
|
/* Set timer status as TMR_STATE_STOPPED */
|
||||||
|
pTmr->tmrState = TMR_STATE_STOPPED;
|
||||||
|
(pTmr->tmrCallBack)(); /* Call timer callback function */
|
||||||
|
}
|
||||||
|
else if(pTmr->tmrType == TMR_TYPE_PERIODIC) /* Is a periodic timer? */
|
||||||
|
{
|
||||||
|
/* Yes,remove this timer from timer list */
|
||||||
|
RemoveTmrList(pTmr->tmrID);
|
||||||
|
pTmr->tmrCnt = pTmr->tmrReload; /* Reset timer tick */
|
||||||
|
InsertTmrList(pTmr->tmrID); /* Insert timer into timer list */
|
||||||
|
(pTmr->tmrCallBack)(); /* Call timer callback function */
|
||||||
|
}
|
||||||
|
pTmr = TmrList; /* Get first item of timer list */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @brief Timer counter dispose in ISR
|
||||||
|
* @param[in] None
|
||||||
|
* @param[out] None
|
||||||
|
* @retval None
|
||||||
|
*
|
||||||
|
* @par Description
|
||||||
|
* @details This function is called to dispose timer counter.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
void isr_TmrDispose(void)
|
||||||
|
{
|
||||||
|
if(OSSchedLock > 1) /* Is schedule lock? */
|
||||||
|
{
|
||||||
|
IsrReq = Co_TRUE;
|
||||||
|
TimerReq = Co_TRUE; /* Yes,set timer request true */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TmrDispose(); /* No,call handler */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,109 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file utility.c
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Utility management implementation code of CooCox CoOS kernel.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 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 */
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file utility.h
|
||||||
|
* @version V1.1.6
|
||||||
|
* @date 2014.05.23
|
||||||
|
* @brief Utility function header file
|
||||||
|
* @details This file including some defines and declares related to utility
|
||||||
|
* function.
|
||||||
|
*******************************************************************************
|
||||||
|
* @copy
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2014 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
|
||||||
|
|
Loading…
Reference in New Issue