/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
::   Module      :   Kernel Tasks
::   Copyright   :   (C)2004-2009 Woodward
::   Platform(s) :   MPC5xx
::   Limitations :   MPC5xx OS
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*! \file TaskKernel_HAL.h
    \brief The Task Kernel can be exposed with this include file. The Task Kernel exposes the creation of
           tasks and the use of synchornisation objects.
*/

#ifndef __TASKKERNEL_HAL_H
#define __TASKKERNEL_HAL_H

/*----- INCLUDES ------------------------------------------------------------------------------------------*/
#include <typedefn.h>       
#include <NativeError.h>

/*----- DEFINES -------------------------------------------------------------------------------------------*/
#define WAIT_INDEFINITELY -1

#define EVENT_NOT_SET_ON_CREATE  FALSE
#define EVENT_SET_ON_CREATE      TRUE

#define MAX_SEMAPHORE_COUNT      4294967295UL

#define USE_MANUAL_EVENT_CLEAR   Unsupported
#define USE_AUTO_EVENT_CLEAR     FALSE

/*! brief The task stack must be at least this large to safely hold the task's execution context and allow
          the minimalists of stacks for the task to use */
#define MINIMUM_TASK_STACK_SIZE  568

/*----- TYPEDEFS ------------------------------------------------------------------------------------------*/
#pragma pack(1)

typedef void* TaskSyncHandle;
typedef void* MailBoxHandle;

/*! \brief Enumeration describes the set of available task priorities */
typedef enum
{
/*! Low priority tasks execute in preference to idle but are pre-empted by all of ControlCore's events
    including background */
    TASK_PRIORITY_LOW,      
/*! Normal priority tasks execute in preference to idle and low priority tasks. ControlCore background is the highest
    normal priority thread and will thus pre-empt other normal priority tasks as will ControlCore foreground events */
    TASK_PRIORITY_NORMAL,
/*! High priority tasks execute in preference to all other tasks and are only pre-empted by system interrupts */
    TASK_PRIORITY_HIGH,
/*! A priority that sits between \ref TASK_PRIORITY_LOW and \ref TASK_PRIORITY_NORMAL */ 
    TASK_PRIORITY_LOWNORM,
} E_TaskPriority;

/*! \brief Enumeration describes the set of mask definitions that are used to identify the valid task creation
           attributes in the S_TaskCreateAttributes data structure.

Each mask definition applies to a particular member of the data structure.
\code
    ...
    S_TaskCreateAttributes TaskObj;

    TaskObj.uValidAttributesMask = USE_TASK_APP_SUPPLIED_STACK_SIZE;
    TaskObj.uTaskStackSizeInBytes = 2048;
    // The remainder of the data structure can be left undefined since the uValidAttributesMask
    //   indicates that the members are not valid
    ... \endcode */
typedef enum
{
    USE_TASK_PRIORITY = 0x01,                   /*!< Selects S_TaskCreateAttributes::pStack */
    USE_TASK_APP_SUPPLIED_STACK_SIZE = 0x02,    /*!< Selects S_TaskCreateAttributes::uTaskStackSizeInBytes */
    USE_TASK_APP_SUPPLIED_STACK = 0x04,         /*!< Selects S_TaskCreateAttributes::pStack */
    TASK_CREATE_SUSPENDED = 0x08,               /*!< Include this bit mask in the S_TaskCreateAttributes::uValidAttributesMask
                                                     to stop the new task from activating upon creation */
    TASK_DOES_NOT_DELETE = 0x10,                /*!< Include this bit mask in the S_TaskCreateAttributes::uValidAttributesMask
                                                     to stop the task attempting to delete its resources upon termination */
} E_CreateTaskAttributes;

typedef uint1 TaskCreateAttributesMask_U;

/*! \brief This data structure describes all of the Task creation attributes. */
typedef struct
{
/*! Logic-OR the attributes [\ref USE_TASK_PRIORITY, \ref USE_TASK_APP_SUPPLIED_STACK_SIZE, and
    \ref USE_TASK_APP_SUPPLIED_STACK ] that are valid for this this instance of the data structure.

    \code
    ...
    S_TaskCreateAttributes TaskObj;

    // Only going to set the stack size member
    TaskObj.uValidAttributesMask = USE_TASK_APP_SUPPLIED_STACK_SIZE;
    TaskObj.uTaskStackSizeInBytes = 2048;
    // The rest of the data structure can remain uninitialised because the task kernel will ignore it \endcode */    
    TaskCreateAttributesMask_U uValidAttributesMask;
    /*! Defines the search point for identifying a task of the appropriate priority. The kernel will obtain the lowest priority task that meets
        the specified priority conditions and assign it to the task. Task creation will fail if the priority conditions could not be met by the
        available number of tasks supported by the kernel. Select this attribute with the \ref USE_TASK_PRIORITY bit mask. The kernel will select
        the lowest available priority if this attribute is left undefined. */
    E_TaskPriority eRequestedPriority;
    /*! Defines the size of the stack that is to be used by this task. Select this attribute with the \ref USE_TASK_APP_SUPPLIED_STACK_SIZE
        bit mask. The kernel shall create a default stack if this attribute is left undefined. The task should be sized as a multiple
        of 8. */
    uint4 uTaskStackSizeInBytes;
    /*! Defines the memory to be used for the task's stack. Select this attribute with the \ref USE_TASK_APP_SUPPLIED_STACK bit mask. If
        this attribute is left undefined or set to NULL then the kernel shall create a task stack on the free store based upon the
        \ref S_TaskCreateAttributes::uTaskStackSizeInBytes attribute or its kernel supplied default. A stack created on the free store
        by the kernel shall be freed when the task is destroyed. */
    void* pStack;
    /*! Pointer to the function that shall execute when the task activates */
    sint4 (*pfTask)(void*);
    /*! The parameter that the Task Kernel will supply when the task is activated. The task should ignore this
        parameter if it is not initialised when the task is created. */
    void* pTaskParameter;

    /*! The friendly name of the task. This is used within the RTOS debugging environment and does not have any influence on normal
        operation. The string will error if an automatic variable is used to hold the task's name */
    char const* psTaskName;

    /* Always add new members here for legacy protection */

} S_TaskCreateAttributes;

/*! \brief Enumeration describes the set of mask definitions that are used to identify the valid performance metrics
           in the S_TaskPerformance data structure.

Each mask definition applies to a particular member of the data structure.
\code
    ...
    S_TaskPerformance PerfObj;

    PerfObj.uValidAttributesMask = WANT_TASK_EXEC_PERFORMANCE ;
    // The remainder of the data structure can be left undefined since the uValidAttributesMask
    //   indicates that the members are not valid
    ... \endcode */
typedef enum
{
    WANT_TASK_EXEC_PERFORMANCE = 0x01,  /*!< Selects S_TaskPerformance::u2Execution */
    WANT_TASK_MIN_STACK_FREE = 0x02,    /*!< Selects S_TaskPerformance::uMinBytesStackFree */
} E_TaskPerformanceAttributes;

typedef uint2 TaskPerformanceAttributesMask_U;

/*! \brief Structure describes the available task performance attributes that can be requested with GetAllTaskPerformanceMetrics() */
typedef struct
{
/*! Logic-OR those attributes [\ref WANT_TASK_EXEC_PERFORMANCE, \ref WANT_TASK_MIN_STACK_FREE etc]
    that are to be recovered. */
    TaskPerformanceAttributesMask_U uValidAttributesMask;
/*! Describes the execution performance as a percentage. 0x10000 represents 100% execution */
    uint2 u2Execution;
/*! Describes the minimum number of free bytes that has been observed on the stack since the task began executing. */
    uint4 uMinBytesStackFree;
} S_TaskPerformance;

#pragma pack()

/*----- EXTERNALS -----------------------------------------------------------------------------------------*/

/*----- PROTOTYPES ----------------------------------------------------------------------------------------*/

NativeBool IsThreadPriorityLowerThanISR(void);
uint4 SleepTask(sint4 in_sTimeToSleepInMicroSecs);
uint4 WaitOnSpinTimer(sint4 in_sTimeToWaitInMicroSecs);

NativeError_S WaitOnSyncObject(TaskSyncHandle in_hHandle, sint4 in_sTimeOutInMicroSecs);
NativeError_S DestroySyncHandle(TaskSyncHandle in_hHandle);

NativeError_S ReleaseSemaphore(TaskSyncHandle in_hHandle);
NativeError_S CreateSemaphore(TaskSyncHandle* out_pHandle, uint4 in_uInitCnt, uint4 in_uMaxCnt);

NativeError_S ReleaseMutex(TaskSyncHandle in_hHandle);
NativeError_S CreateMutex(TaskSyncHandle* out_pHandle);

NativeError_S CreateMailBox(MailBoxHandle* out_pHandle, uint4 in_uMaxEntries);
NativeError_S PostToMailBox(MailBoxHandle in_pHandle, void* in_pEntry, sint4 in_sTimeOutInMicroSecs);
NativeError_S FetchFromMailBox(MailBoxHandle in_pHandle, void** out_ppEntry, sint4 in_sTimeOutInMicroSecs);
uint4 GetMailBoxMaxDepth(MailBoxHandle in_pHandle);
NativeError_S DestroyMailBox(MailBoxHandle in_pHandle);

NativeError_S CreateEvent(TaskSyncHandle* out_pHandle, NativeBool in_bIsSetOnCreate, NativeBool in_bUseManualClear);
NativeError_S SetEvent(TaskSyncHandle in_hHandle);

NativeError_S CreateTask(S_TaskCreateAttributes const* in_pTaskAttributes, TaskSyncHandle* out_pHandle);
NativeError_S ActivateTask(TaskSyncHandle);

void* GetTaskLocalStorage(void);
NativeError_S SetTaskLocalStorage(void*);

NativeError_S ExitCriticalSection(void);
NativeError_S EnterCriticalSection(void);

NativeError_S GetTaskReturnValue(TaskSyncHandle, sint4* out_pReturnedValue);

uint2 GetTaskExecPerformanceMetric(TaskSyncHandle in_hHandle);
NativeError_S GetAllTaskPerformanceMetrics(TaskSyncHandle in_hHandle, S_TaskPerformance* out_pTaskPerformance);

/* Will deprecate this function after transition */
NativeVar_U GetTaskIDWithHandle(TaskSyncHandle);

uint2 TaskKernel_GetTaskExecPerf(void);
uint2 TaskKernel_GetAnyTaskExecPerf(TaskSyncHandle in_hHandle);
#endif /* __TASKKERNEL_HAL_H */

/*----- END OF FILE ---------------------------------------------------------------------------------------*/
