/*
 * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o 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.
 *
 * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
 */
#if defined (FSL_RTOS_UCOSII)

#include <assert.h>
#include "fsl_os_abstraction.h"
#include "fsl_interrupt_manager.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*! @brief Converts milliseconds to ticks*/
#define MSEC_TO_TICK(msec)      (((INT32U)(msec)+500uL/OS_TICKS_PER_SEC)*OS_TICKS_PER_SEC/1000uL)
#define TICKS_TO_MSEC(tick)      ((tick)*1000uL/OS_TICKS_PER_SEC)

/*******************************************************************************
 * Code
 ******************************************************************************/

/*FUNCTION**********************************************************************
 *
 * Function Name : __task_create
 * Description   : This function is used by the macro task_create. Return
 * kSuccess if the task is created successfully, kError if failed.
 *
 *END**************************************************************************/
fsl_rtos_status __task_create(task_t          task,
                              uint8_t        *name,
                              uint16_t        stackSize,
                              task_stack_t   *stackMem,
                              uint16_t        priority,
                              void           *param,
                              bool            usesFloat,
                              task_handler_t *handler)
{
    INT8U err;
    uint32_t stackSizeLocal = stackSize/sizeof(task_stack_t);

    *handler = priority;    /*!< Priority is required to destroy the task.*/
    err = OSTaskCreateExt(task,       /*!< Task pointer*/
                          param,      /*!< Task input parameter*/
                          &stackMem[stackSizeLocal - 1],   /*!< Pointer to top of stack*/
                          priority,   /*!< Task priority*/
                          priority,   /*!< Task id. should be the same as priority*/
                          stackMem,   /*!< Pointer to the bottom of the stack*/
                          stackSizeLocal,  /*!< Size of the stack*/
                          (void*)0,   /*!< TCB extension not supported by this abstraction*/
                          usesFloat ? OS_TASK_OPT_SAVE_FP : OS_TASK_OPT_NONE
                          );
    if (OS_ERR_NONE != err)
    {
        return kError;
    }
#if OS_TASK_NAME_EN > 0u
    OSTaskNameSet (priority, name, &err);
    if (OS_ERR_NONE != err)
    {
        return kError;
    }
#else
    name = name;
#endif
    return kSuccess;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : task_destroy
 * Description   : This function destroy a task. Return kSuccess if the task
 * is destroied, or return kError.
 *
 *END**************************************************************************/
fsl_rtos_status task_destroy(task_handler_t handler)
{
    INT8U err = OSTaskDel(handler);

    if (OS_ERR_NONE == err)
    {
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : sync_create
 * Description   : This function is used to create a sync object.
 * Return kSuccess if create successfully, otherwise return kError.
 *
 *END**************************************************************************/
fsl_rtos_status sync_create(sync_object_t *obj, uint8_t initValue)
{
    *obj = OSSemCreate(initValue);

    if (*obj)
    {
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : sync_wait
 * Description   : This function checks the sync object's counting value, if it
 * is positive, decreases it and returns kSuccess, otherwise, timeout will be
 * used for wait. Pass the #kSyncWaitForever constant to wait indefinitely,
 * timeout should not be 0.
 * Return kSuccess if the sync object is signaled before the timeout is exhausted,
 * return kTimeout if the sync object has not been signaled before the timeout
 * is exhausted, return kError if the parameter is invalid.
 *
 *END**************************************************************************/
fsl_rtos_status sync_wait(sync_object_t *obj, uint32_t timeout)
{
    INT8U err;

    if (!timeout)  /* timeout should not be 0. */
    {
        return kError;
    }

    if (kSyncWaitForever == timeout)   /* Wait forever. */
    {
        timeout = 0U;
    }
    else
    {
        timeout = MSEC_TO_TICK(timeout); /* Change timeout to tick. */
        /*
         * If timeout is too short that changed to 0 tick, reset it to 1 tick
         * in case of infinitely wait.
         */
        if (!timeout)
        {
            timeout = 1U;
        }
    }

    OSSemPend(*obj, timeout, &err);

    if (OS_ERR_NONE == err)
    {
        return kSuccess;
    }
    else if (OS_ERR_TIMEOUT == err)
    {
        return kTimeout;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : sync_poll
 * Description   : This function is used to poll a sync object's status.
 * If the sync object's counting value is positive, decrease it and return
 * kSuccess. If the object's counting value is 0 or the parameter is invalid,
 * the function will return kError immediately.
 *
 *END**************************************************************************/
fsl_rtos_status sync_poll(sync_object_t *obj)
{

    INT16U ret = OSSemAccept(*obj);

    if (ret > 0)
    {
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : sync_signal
 * Description   : This function is used to signal a sync object.
 * Return kSuccess if the sync object is signaled successfully, otherwise
 * return kError.
 * This function should not be called from isr.
 *
 *END**************************************************************************/
fsl_rtos_status sync_signal(sync_object_t *obj)
{
    if (OS_ERR_NONE == OSSemPost(*obj))
    {
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : sync_signal_from_isr
 * Description   : This function is used to signal a sync object.
 * Return kSuccess if the sync object is signaled successfully, otherwise
 * return kError.
 * This function should be called from isr only.
 *
 *END**************************************************************************/
fsl_rtos_status sync_signal_from_isr(sync_object_t *obj)
{
    return sync_signal(obj);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : sync_destroy
 * Description   : This function is used to destroy a sync object.
 * Return kSuccess if the sync object is destroyed successfully, otherwise
 * return kError.
 *
 *END**************************************************************************/
fsl_rtos_status sync_destroy(sync_object_t* obj)
{
    INT8U err;

    OSSemDel(*obj, OS_DEL_ALWAYS, &err);

    if (OS_ERR_NONE == err)
    {
        *obj = (sync_object_t)0;
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : lock_create
 * Description   : This function is used to create a lock object.
 * Return kSuccess if create successfully, otherwise return kError.
 *
 *END**************************************************************************/
fsl_rtos_status lock_create(lock_object_t *obj)
{
    INT8U err;

    /* NOTE: uCOS-ii does not support priority inherit but only priority protect */
    *obj = OSMutexCreate(OS_PRIO_MUTEX_CEIL_DIS, &err);

    if (OS_ERR_NONE == err)
    {
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : lock_wait
 * Description   : This function is used to wait to obtain a lock object.
 * Pass the #kSyncWaitForever constant to wait indefinitely for someone to
 * unlock the object. 0 should not be passed to this function.
 * Return kSuccess if the lock object is obtained before the timeout is exhausted,
 * return kTimeout if has not obtained the lock object before the timeout
 * is exhausted, return kError if the parameter is invalid.
 *
 *END**************************************************************************/
fsl_rtos_status lock_wait(lock_object_t *obj, uint32_t timeout)
{
    INT8U err;

    /*!< Avoid to get the mutex current task has already got*/
    if ((*obj)->OSEventPtr == (void *)OSTCBCur)
    {
        return kError;
    }

    if (kSyncWaitForever == timeout)   /* Wait forever. */
    {
        timeout = 0U;
    }
    else
    {
        timeout = MSEC_TO_TICK(timeout); /* Change timeout to tick. */
        /*
         * If timeout is too short that changed to 0 tick, reset it to 1 tick
         * in case of infinitely wait.
         */
        if (!timeout)
        {
            timeout = 1U;
        }
    }

    OSMutexPend(*obj, timeout, &err);

    if (OS_ERR_NONE == err)
    {
        return kSuccess;
    }
    else if (OS_ERR_TIMEOUT == err)
    {
        return kTimeout;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : lock_poll
 * Description   : This function is used to poll a lock object's status.
 * If the lock object is unlocked, this function will return kSuccess and lock
 * the object. If the lock object has been locked, return kIdle immediately.
 * If parameter is invalid return kError.
 *
 *END**************************************************************************/
fsl_rtos_status lock_poll(lock_object_t *obj)
{
    INT8U err;
    BOOLEAN pollResult;

    pollResult = OSMutexAccept(*obj, &err);

    if (OS_ERR_NONE == err)
    {
        if (OS_TRUE == pollResult)
        {
            return kSuccess;
        }
        else
        {
            return kIdle;
        }
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : lock_release
 * Description   : This function is used to unlock a lock object.
 * Return kSuccess if the lock object is unlocked successfully, otherwise
 * return kError.
 *
 *END**************************************************************************/
fsl_rtos_status lock_release(lock_object_t *obj)
{
    if (OS_ERR_NONE == OSMutexPost(*obj))
    {
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : lock_destroy
 * Description   : This function is used to destroy a lock object.
 * Return kSuccess if the lock object is destroyed successfully, otherwise
 * return kError.
 *
 *END**************************************************************************/
fsl_rtos_status lock_destroy(lock_object_t *obj)
{
    INT8U err;

    OSMutexDel(*obj, OS_DEL_ALWAYS, &err);

    if (OS_ERR_NONE == err)
    {
        *obj = (lock_object_t)0;
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : event_create
 * Description   : This function is used to create a event object. The event can
 * be auto clear or manual clear.
 * Return kSuccess if create successfully, otherwise return kError.
 *
 *END**************************************************************************/
fsl_rtos_status event_create(event_object_t  *obj,
                             event_clear_type clearType)
{
    INT8U err;
    obj->pGrp = OSFlagCreate(0u, &err);
    if (OS_ERR_NONE == err)
    {
        obj->clearType = clearType;
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : event_wait
 * Description   : This function is used to wait a event.
 * Pass the #kSyncWaitForever constant to wait indefinitely. 0 should not be
 * passed to this function. Return kSuccess if any flag bit of the event object is
 * set before the timeout is exhausted, return kTimeout if no flag is set before
 * the timeout is exhausted, return kError if the parameter is invalid. If setFlags
 * is not NULL, the flags that have been set will be get by setFlags.
 *
 *END**************************************************************************/
fsl_rtos_status event_wait(event_object_t *obj,
                           uint32_t        timeout,
                           event_group_t  *setFlags)
{
    INT8U err, opt;
    event_group_t saveFlags;

    if (0U == timeout)
    {
        return kError;                                /*!< timeout should not be 0*/
    }

    if (kSyncWaitForever == timeout)                  /*!< Wait forever*/
    {
        timeout = 0U;
    }
    else
    {
        timeout = MSEC_TO_TICK(timeout); /* Change timeout to tick. */
        /*
         * If timeout is too short that changed to 0 tick, reset it to 1 tick
         * in case of infinitely wait.
         */
        if (!timeout)
        {
            timeout = 1U;
        }
    }

    opt = OS_FLAG_WAIT_SET_ANY;

    if (kEventAutoClr == obj->clearType)
    {
        opt |= OS_FLAG_CONSUME;
    }
    saveFlags = OSFlagPend(obj->pGrp, (OS_FLAGS)~0, opt,
                           timeout, &err);

    if (setFlags)
    {
        *setFlags = saveFlags;
    }

    if (OS_ERR_NONE == err)
    {
        return kSuccess;
    }
    else if (OS_ERR_TIMEOUT == err)
    {
        return kTimeout;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : event_set
 * Description   : Set one or more event flags of an event object.
 * Return kSuccess if set successfully, kError if failed.
 * This function should not be called from an ISR.
 *
 *END**************************************************************************/
fsl_rtos_status event_set(event_object_t *obj, event_group_t flags)
{
    INT8U err;

    OSFlagPost(obj->pGrp, flags, OS_FLAG_SET, &err);

    if (OS_ERR_NONE == err)
    {
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : event_set_from_isr
 * Description   : Set one or more event flags of an event object.
 * Return kSuccess if set successfully, kError if failed.
 * This function should only be called from an ISR.
 *
 *END**************************************************************************/
fsl_rtos_status event_set_from_isr(event_object_t *obj, event_group_t flags)
{
    return event_set(obj, flags);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : event_clear
 * Description   : Clear one or more event flags of an event object.
 * Return kSuccess if clear successfully, kError if failed.
 *
 *END**************************************************************************/
fsl_rtos_status event_clear(event_object_t *obj, event_group_t flags)
{
    INT8U err;

    OSFlagPost(obj->pGrp, flags, OS_FLAG_CLR, &err);

    if (OS_ERR_NONE == err)
    {
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : event_check_flags
 * Description   : Check the specific event flags are set or not.
 * Return kFlagSet if any flags are set, otherwise return kFlagNotSet.
 *
 *END**************************************************************************/
event_status event_check_flags(event_object_t *obj,
                               event_group_t   flag)
{
    INT8U err;
    OS_FLAGS flagsSet = OSFlagQuery(obj->pGrp, &err);
    
    if (OS_ERR_NONE != err)
    {
        return kFlagNotSet;
    }

    if (flag & flagsSet)
    {
        return kFlagSet;
    }
    else
    {
        return kFlagNotSet;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : event_destroy
 * Description   : This function is used to destroy a event object.
 * Return kSuccess if the event object is destroyed successfully, otherwise
 * return kError.
 *
 *END**************************************************************************/
fsl_rtos_status event_destroy(event_object_t* obj)
{
    INT8U err;

    OSFlagDel(obj->pGrp, OS_DEL_ALWAYS, &err);

    if (OS_ERR_NONE == err)
    {
        obj->pGrp = (OS_FLAG_GRP*)0;
        return kSuccess;
    }
    else
    {
        return kError;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : msg_queue_create
 * Description   : This function is used to create a message queue.
 * If OSA is configured to copy messages to internal memory, OSMEM is used to
 * manage the internal memory.
 * Return the handle to the message queue if create successfully, other wise
 * return 0.
 *
 *END**************************************************************************/
msg_queue_handler_t msg_queue_create(msg_queue_t *queue, uint16_t number, uint16_t size)
{
#if (__FSL_RTOS_MSGQ_COPY_MSG__)
    INT8U  err;

    queue->pq = OSQCreate(queue->msgTbl, number);
    if (!queue->pq)
    {
        return (msg_queue_handler_t)0;
    }

    /* Use OS_MEM to manage the memory which is used to save messages*/
    queue->pmem = OSMemCreate(queue->msgs, number, size*sizeof(int32_t), &err);
    if (!queue->pmem)
    {
        OSQDel(queue->pq, OS_DEL_ALWAYS, &err);
        return (msg_queue_handler_t)0;
    }

    queue->size = size;
    return (msg_queue_handler_t)queue;
    
#else
    size = size;
    queue->pq = OSQCreate(queue->msgTbl, number);
    if (!queue->pq)
    {
        return (msg_queue_handler_t)0;
    }
    return (msg_queue_handler_t)queue;
#endif
}

/*FUNCTION**********************************************************************
 *
 * Function Name : msg_queue_put
 * Description   : This function is used to put a message to a message queue.
 * If OSA is configured to copy messages to internal memory, OSMEM will provide
 * a memory block and the message is copied to the memory block.
 * Return kSuccess if the message is put successfully, other wise return kError.
 *
 *END**************************************************************************/
fsl_rtos_status msg_queue_put(msg_queue_handler_t handler, msg_queue_item_t item)
{
#if (__FSL_RTOS_MSGQ_COPY_MSG__)
    INT8U err;
    void  *localMsg;
    int32_t  *from_ptr, *to_ptr;
    uint32_t msg_size = handler->size;

    localMsg = OSMemGet(handler->pmem, &err);
    if (!localMsg)
    {
        return kError;
    }

    /*!< copy msg to localMsg */
    from_ptr = (int32_t*)item;
    to_ptr   = (int32_t*)localMsg;
    while (msg_size--)
    {
        *to_ptr++ = *from_ptr++;
    }

    if (OS_ERR_NONE != OSQPost(handler->pq, localMsg))
    {
        OSMemPut(handler->pmem, localMsg);
        return kError;
    }

    return kSuccess;
#else
    /* In this case, the message is passed by reference, so passing the pointer is ok. */
    if (OS_ERR_NONE == OSQPost(handler->pq, item))
    {
        return kSuccess;
    }
    else
    {
        return kError;
    }
#endif
}

/*FUNCTION**********************************************************************
 *
 * Function Name : msg_queue_get
 * Description   : This function is used to get a message from a message queue.
 * If the message queue is empty, set timeout to 0 to return immediately, set
 * timeout to #kSyncWaitForever to wait indefinitely.
 * Return kSuccess if the message is get before the timeout is exhausted, return
 * kTimeout if no message is get before the timeout is exhausted, return kError
 * if the parameter is invalid.
 * The unit of timeout is millisecond.
 *
 *END**************************************************************************/
fsl_rtos_status msg_queue_get(msg_queue_handler_t handler,
                              msg_queue_item_t   *item,
                              uint32_t            timeout)
{
    INT8U err;
#if (__FSL_RTOS_MSGQ_COPY_MSG__)
    void* localMsg;
    int32_t  *from_ptr, *to_ptr;
    uint16_t msg_size = handler->size;

    if (0U != timeout)
    {
        if (kSyncWaitForever == timeout)   /* Wait forever. */
        {
            timeout = 0U;
        }
        else
        {
            timeout = MSEC_TO_TICK(timeout); /* Change timeout to tick. */
            /*
             * If timeout is too short that changed to 0 tick, reset it to 1 tick
             * in case of infinitely wait.
             */
            if (!timeout)
            {
                timeout = 1U;
            }
        }

        localMsg = OSQPend(handler->pq, timeout, &err);
    }
    else
    {
        localMsg = OSQAccept(handler->pq, &err);
    }

    switch (err)
    {
        case OS_ERR_NONE:
            break;
        case OS_ERR_Q_EMPTY:
            return kIdle;
            break; /* For misra 15.2 */
        case OS_ERR_TIMEOUT:
            return kTimeout;
            break; /* For misra 15.2 */
        default:
            return kError;
    }

    /* copy localMsg to msg*/
    to_ptr   = (int32_t*)(*item);
    from_ptr = (int32_t*)localMsg;
    while (msg_size--)
    {
        *to_ptr++ = *from_ptr++;
    }
    
    if (OS_ERR_NONE != OSMemPut(handler->pmem, localMsg))
    {
        return kError;
    }

    return kSuccess;
#else
    if (0U == timeout)
    {
        *item = OSQAccept(handler->pq, &err);
    }
    else
    {
        if (kSyncWaitForever == timeout)   /* Wait forever. */
        {
            timeout = 0U;
        }
        else
        {
            timeout = MSEC_TO_TICK(timeout); /* Change timeout to tick. */
            /*
             * If timeout is too short that changed to 0 tick, reset it to 1 tick
             * in case of infinitely wait.
             */
            if (!timeout)
            {
                timeout = 1U;
            }
        }
        *item = OSQPend(handler->pq, timeout, &err);
    }

    switch (err)
    {
        case OS_ERR_NONE:
            return kSuccess;
        case OS_ERR_Q_EMPTY:
            return kIdle;
            break; /* For misra 15.2 */
        case OS_ERR_TIMEOUT:
            return kTimeout;
            break; /* For misra 15.2 */
        default:
            return kError;
    }
#endif
}

/*FUNCTION**********************************************************************
 *
 * Function Name : msg_queue_flush
 * Description   : This function is used to flush the message queue.
 * If OSA is configured to copy messages to internal memory, the memory blocks
 * that save the message will be return to OSMEM.
 * Return kSuccess if the message queue is flushed successfully, other wise
 * return kError.
 *
 *END**************************************************************************/
fsl_rtos_status msg_queue_flush(msg_queue_handler_t handler)
{
/*!< If last status indicates the queue is empty, then the operation succeeded.*/
/*!< Return erro otherwise.*/
#if (__FSL_RTOS_MSGQ_COPY_MSG__)
    INT8U err = OS_ERR_NONE;
    void *msg;

    while (1)
    {
        msg = OSQAccept(handler->pq, &err);
        if (OS_ERR_Q_EMPTY == err)
        {
            return kSuccess; /* The message queue is emptied. */
        }
        else if (OS_ERR_NONE != err)
        {
            return kError;
        }
        err = OSMemPut(handler->pmem, msg);

        if (OS_ERR_NONE != err)
        {
            return kError;
        }
    }
#else
    if (OS_ERR_NONE == OSQFlush(handler->pq))
    {
        return kSuccess;
    }
    else
    {
        return kError;
    }
#endif
}

/*FUNCTION**********************************************************************
 *
 * Function Name : msg_queue_destroy
 * Description   : This function is used to destroy the message queue.
 * Return kSuccess if the message queue is destroied successfully, other wise
 * return kError.
 *
 *END**************************************************************************/
#if (__FSL_RTOS_MSGQ_COPY_MSG__)
fsl_rtos_status msg_queue_destroy(msg_queue_handler_t handler)
{
#if OS_CRITICAL_METHOD == 3u
    OS_CPU_SR  cpu_sr = 0u;
#endif
    INT8U err;
    OS_MEM* pmem;

    OSQDel(handler->pq, OS_DEL_ALWAYS, &err);

    if (OS_ERR_NONE != err)
    {
        return kError;
    }
    
    /*<! return OS_MEM to OS*/
    OS_ENTER_CRITICAL();
    pmem = handler->pmem;
    pmem->OSMemFreeList = OSMemFreeList;
    OSMemFreeList = pmem;
    OS_EXIT_CRITICAL();

    handler->pmem = (OS_MEM   *)0;
    handler->pq   = (OS_EVENT *)0;

    return kSuccess;
}
#else
fsl_rtos_status msg_queue_destroy(msg_queue_handler_t handler)
{
    INT8U err;

    OSQDel(handler->pq, OS_DEL_ALWAYS, &err);

    if (OS_ERR_NONE != err)
    {
        return kError;
    }
    else
    {
        return kSuccess;
    }
}
#endif

/*FUNCTION**********************************************************************
 *
 * Function Name : mem_allocate
 * Description   : This function is used to allocate amount of memory in bytes.
 * Return the pointer to the memory if success, otherwise return NULL;
 *
 *END**************************************************************************/
void * mem_allocate(size_t size)
{
    return malloc(size);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : mem_allocate_zero
 * Description   : This function is used to allocate amount of memory in bytes
 * and initializes it to 0.
 * Return the pointer to the memory if success, otherwise return NULL;
 *
 *END**************************************************************************/
void * mem_allocate_zero(size_t size)
{
    return calloc(1, size);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : mem_free
 * Description   : This function is used to free the memory previously allocated.
 *
 *END**************************************************************************/
fsl_rtos_status mem_free(void *ptr)
{
    free(ptr);
    return kSuccess;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : time_delay
 * Description   : This function is used to delay for a number of milliseconds.
 *
 *END**************************************************************************/
void time_delay(uint32_t delay)
{
    delay = MSEC_TO_TICK(delay);
    /*
     * If delay is too short that changed to 0 tick, reset it to 1 tick
     * in case of no delay.
     */
    if (!delay)
    {
        delay = 1U;
    }
    OSTimeDly(delay);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : interrupt_handler_register
 * Description   : This function is used to install interrupt handler.
 * For uCOS-II, this function will always return kSuccess.
 *
 *END**************************************************************************/
fsl_rtos_status interrupt_handler_register(int32_t irqNumber, void (*handler)(void))
{
    interrupt_register_handler((IRQn_Type)irqNumber, handler);

    return kSuccess;
}

#endif
/*******************************************************************************
 * EOF
 ******************************************************************************/
