/******************************************************************************
 *
 * Copyright:
 *    (C) 2000 - 2005 Embedded Artists AB
 *
 * Description:
 *
 * ESIC:
 *    pre_emptive_os
 *
 * Version:
 *    1.4.0
 *
 * Generate date:
 *    2005-03-15 at 20:27:15
 *
 * NOTE:
 *    DO NOT EDIT THIS FILE. IT IS AUTO GENERATED.
 *    CHANGES TO THIS FILE WILL BE LOST IF THE FILE IS RE-GENERATED
 *
 * Signature:
 *   7072655F656D70746976655F6F73,312E342E302E30,020235
 *   ,35,10104021013134373435363030,07323838,3732,01013
 *   830,0101013138303030303030,3135,33,3135,0232323530
 *   ,01020130,0231343734353539,3238313831,020101100302
 *   103030310010133,0163130,3230,3330,3430,3530,3630,3
 *   730,3830,3930,313030,313130,313230,313330,313430,3
 *   13530,313630,,35,35,35,35,35,35,35,35,35,35,35,35,
 *   35,35,35,35,,,,1001001100011000000000]484152445741
 *   5245,4C5043323130365F32,545538,756E7369676E6564206
 *   3686172,414C49474E4D454E54,34,54424F4F4C,756E73696
 *   76E65642063686172,54553332,756E7369676E656420696E7
 *   4,544D505F46494C4553,2A2E656C663B2A2E6C73743B2A2E6
 *   D61703B2A2E6F3B2A2E6F626A3B2A2E64,454E4449414E,4C4
 *   954544C45,54533332,7369676E656420696E74,545338,736
 *   9676E65642063686172,54553136,756E7369676E656420736
 *   86F7274,54533136,7369676E65642073686F7274,44455343
 *   52495054494F4E,,44454255475F4C4556454C,30,434F4445
 *   5F524F4F54,,47454E5F52554C4553,,4C494E455F5445524D
 *   ,43524C46,4252414345,,43524541544F52,416E646572732
 *   0526F7376616C6C,4352454154494F4E5F44415445,3230303
 *   52D30332D31352032303A31373A3432,524F4F54,433A2F446
 *   F63756D656E747320616E642053657474696E67732F416E646
 *   5727320526F7376616C6C2F4D696E6120646F6B756D656E742
 *   F456D62656464656420417274697374732F50726F647563747
 *   32F4C50433231303620525332333220517569636B537461727
 *   420426F6172642F72746F732F]505245464958,,4445425547
 *   5F4C4556454C,30,555345525F434F4D4D454E54,]64656661
 *   756C74,
 *
 * Checksum:
 *    1673036
 *
 *****************************************************************************/

#ifndef _OSAPI__h
#define _OSAPI__h
/******************************************************************************
 * Includes
 *****************************************************************************/

#include "../api/general.h"

/******************************************************************************
 * Defines, macros, and typedefs
 *****************************************************************************/

#define OS_OK                 0x00
#define OS_ERROR_NULL         0x01
#define OS_ERROR_ISR          0x02
#define OS_ERROR_SEM_OVERRUN  0x03
#define OS_ERROR_PID          0x04
#define OS_ERROR_ALLOCATE     0x05
#define OS_ERROR_STATE        0x06
#define OS_ERROR_QUEUE_FULL   0x07
#define OS_ERROR_TIMEOUT      0x08
#define OS_ERROR_PRIO         0x09

/* signal structure */
typedef struct intSig__
{
  struct intSig__ *pNext;
  tU8 senderId;
}tIntSig;

/* process control block */
typedef struct _tOSPCB__
{
  tU8 *pStk;                    /* pointer to top of stack */
  struct _tOSPCB__ *pNextPrioQueueReady; /* next pointer in a prioritized ready queue */
  struct _tOSPCB__ *pPrevPrioQueueReady; /* prev pointer in a prioritized ready queue */
  struct _tOSPCB__ *pNextPrioQueueEvent; /* next pointer in a prioritized event queue */
  struct _tOSPCB__ *pPrevPrioQueueEvent; /* prev pointer in a prioritized event queue */
  struct _tOSPCB__ *pNextTimeQueue; /* next pointer in time queue */
  tU8 pid;                      /* process id */
  tU8 prio;                     /* process priority */
  tU8 flag;                     /* flag (PROC_SEM_WAIT, PROC_SLEEP,...) */
  tU32 sleep;                   /* number of ticks to sleep (relative
                                   other processes in time list) */
  
  tU8 *pStkOrg;  
  tU16 stackSize;

}tOSPCB;

#define NUM_PRIO 5
#define MAX_NUM_PROC 5
#define READY_QUEUE 0
#define EVENT_QUEUE 1

typedef struct _tPrioQueue_
{
  tOSPCB *pPrioList[NUM_PRIO];
  tOSPCB * pPCBs;
}tPrioQueue;

typedef struct _tOSEvent_ 
{
  tPrioQueue waitQ; /* wait queue */
}tOSEvent;

typedef struct _tCntSem_
{
  tOSEvent ev;
  tU16 cnt;

}tCntSem;

/* queue structure */
typedef struct tQueue__
{
  tOSEvent ev;
  void ** pQStart;
  void ** pQEnd;
  void ** pQIn;
  void ** pQOut;
  tU16 queueSize;
  tU16 nEntries;
}tQueue;

/* timer structure */
typedef struct _tTimer__
{
  struct _tTimer__ * next;
  struct _tTimer__ * previous;
  struct _tTimer__ * list;
  void (*callback)(void);
  tU32 delta;
  tU32 time;
  tBool repeat;
}tTimer;

/*****************************************************************************
 *
 * Description:
 *    The three defines below are used to control interrupt state. When
 *    disabling interrupts, the current state is stored in a local variable
 *    named: localSR (of type: tSR), see code example below. When enabling
 *    interrupts again the previously stored state is restored.
 *
 *    void anyFunction(void)
 *    {
 *      volatile tSR localSR;
 *      ...                //other local variables
 *
 *      ...                //some code that execute with enabled IRQ
 *      m_os_dis_int();
 *      ...                //some code that must execute with disabled IRQ
 *      m_os_ena_int();
 *      ...                //some code that execute with enabled IRQ
 *
 *    }
 *
 *    Observe that it is recommended not to enable interrupts in an ISR
 *    (Interrupt Service Routine), in order to create nested interrupts.
 *    Such a structure requires more stack space and can be difficult to
 *    analyze.
 *
 ****************************************************************************/
#define tSR tU32                 /* define the type for status words */
#define m_os_dis_int()  {localSR = halDisableInterrupts_oshal(); asm volatile (" nop");}
#define m_os_ena_int()  {halRestoreInterrupts_oshal(localSR); asm volatile (" nop");}

/******************************************************************************
 * Public functions
 *****************************************************************************/


/*****************************************************************************
 *
 * Description:
 *    This function returns the process identification descriptor for the 
 *    running process. 
 *
 * Params:
 *    [out] pError - The return status of the function. 
 *
 * Returns:
 *    The process identification descriptor of the currently running process. 
 *
 * Error codes:
 *    OS_OK        - The function completed successfully. 
 *    OS_ERROR_ISR - The function was called from an interrupt service 
 *                   routine. 
 *
 ****************************************************************************/
tU8 osPid(tU8* pError);


/*****************************************************************************
 *
 * Description:
 *    This function puts a process to sleep for the specified number of ticks. 
 *
 * Params:
 *    [in] ticks - The number of ticks to put the process to sleep. 
 *
 ****************************************************************************/
void osSleep(tU32 ticks);


/*****************************************************************************
 *
 * Description:
 *    This function must be called before any other call to the operating 
 *    system. 
 *
 ****************************************************************************/
void osInit(void);


/*****************************************************************************
 *
 * Description:
 *    This function starts the operating system. There must be at least one 
 *    process created and started before this function is called. A process is 
 *    created by calling osCreateProcess and started by calling 
 *    osStartProcess. osStart, osCreateProcess and osStartProcess are the only 
 *    operating system functions that may be called before the operating 
 *    system is started. If other operating system functions are called before 
 *    the operating system is started the behavior is undefined. The preferred 
 *    way of starting up a multitasking system is to only create and start an 
 *    init process in the main function before osStart is called. The init 
 *    process initializes the system and starts other processes needed. The 
 *    init process can safely initialize other operating system objects like 
 *    semaphores, queues, etc. 
 *
 ****************************************************************************/
void osStart(void);


/*****************************************************************************
 *
 * Description:
 *    This function deletes the currently running process. The process control 
 *    block used by the process will be freed and is therefore available for 
 *    new processes. 
 *
 ****************************************************************************/
void osDeleteProcess(void);


/*****************************************************************************
 *
 * Description:
 *    This function creates a new process. The process is not automatically 
 *    started. To start the process the osStartProcess function must be 
 *    called. A new process can only be created if there is a free process 
 *    control block available. The number of process control blocks is 
 *    specified during operating system configuration (maximum number of 
 *    processes). 
 *
 * Params:
 *    [in]  pProc   - The process entry function. 
 * 
 *              Params (callback):
 *                 arg - This argument can be used to pass arbitrary 
 *                       information to the process entry function when the 
 *                       process is started. 
 *    [in]  pStk    - A pointer to the stack area to use. The stack area must 
 *                    be allocated before the process is created. 
 *    [in]  stkSize - The size of the stack area in bytes. 
 *    [out] pPid    - The returned process identification descriptor (pid). 
 *    [in]  prio    - The priority of the process. The priority is a number 
 *                    between 0 and NUM_PRIO-1, where NUM_PRIO is specified 
 *                    during operating system configuration (maximum number of 
 *                    priorities). 0 is the highest priority level and 
 *                    NUM_PRIO-1 is the lowest priority level. The operating 
 *                    system will always run the process that has the highest 
 *                    priority and is ready to run, i.e. is not sleeping, 
 *                    suspended or waiting for a synchronization primitive. If 
 *                    several processes are run on the same priority level 
 *                    they are scheduled in a round-robin fashion. 
 *    [in]  pParam  - This parameter is passed to the process entry function 
 *                    when the process is started. 
 *    [out] pError  - The return status of the function. 
 *
 * Error codes:
 *    OS_OK             - The function completed successfully. 
 *    OS_ERROR_PRIO     - The supplied priority is not correct. 
 *    OS_ERROR_ALLOCATE - The process could not be created since there are no 
 *                        free process control blocks available. The number of 
 *                        process control blocks is specified during operating 
 *                        system configuration (maximum number of processes). 
 *
 ****************************************************************************/
void osCreateProcess(void  (*pProc) (void* arg),
                     tU8*  pStk,
                     tU16  stkSize,
                     tU8*  pPid,
                     tU8   prio,
                     void* pParam,
                     tU8*  pError);


/*****************************************************************************
 *
 * Description:
 *    This function is used to start a process. The process must previously 
 *    have been created by a call to osCreateProcess. 
 *
 * Params:
 *    [in]  pid    - The process identification descriptor (pid) of the 
 *                   process to start. The pid is returned by osCreateProcess. 
 *    [out] pError - The return status of the function. 
 *
 * Error codes:
 *    OS_OK        - The function completed successfully. 
 *    OS_ERROR_PID - The supplied pid is not correct. 
 *
 ****************************************************************************/
void osStartProcess(tU8  pid,
                    tU8* pError);


/*****************************************************************************
 *
 * Description:
 *    This function suspends the currently running process. Another process 
 *    can resume it by a call to osResume. 
 *
 ****************************************************************************/
void osSuspend(void);


/*****************************************************************************
 *
 * Description:
 *    This function resumes a suspended process. It is valid to do resume on a 
 *    process that has not been suspended. 
 *
 * Params:
 *    [in]  pid    - The process to resume. 
 *    [out] pError - The return status of the function. 
 *
 * Error codes:
 *    OS_OK        - The function completed successfully. 
 *    OS_ERROR_PID - The supplied pid is not correct. 
 *
 ****************************************************************************/
void osResume(tU8  pid,
              tU8* pError);


/*****************************************************************************
 *
 * Description:
 *    This function is used to notify the operating system that the 
 *    application has entered an interrupt service routine (ISR). This is 
 *    important if the ISR is using services from the operating system, since 
 *    some services need to know if they are executed from an ISR or not. The 
 *    function osISRExit should be used before the ISR returns to 
 *    notify the operating system about the ISR exit. 
 *
 ****************************************************************************/
void osISREnter(void);


/*****************************************************************************
 *
 * Description:
 *    This function is used to notify the operating system that the currently 
 *    serviced interrupt is about to exit. The function is always used in 
 *    conjunction with the function osISREnter, which should always 
 *    be called before osISRExit. It is important to notify the OS 
 *    about ISRs (Interrupt Service Routines) if they are using services from 
 *    the operating system (since some services need to know if they are 
 *    executed from an ISR or not). 
 *
 ****************************************************************************/
void osISRExit(void);


/*****************************************************************************
 *
 * Description:
 *    This function initializes a counting semaphore and must be called before 
 *    any other function is used on the semaphore. 
 *
 * Params:
 *    [in] pSem    - A pointer to an allocated counting semaphore structure. 
 *    [in] initial - The initial counter value. 
 *
 ****************************************************************************/
void osSemInit(tCntSem* pSem,
               tU16     initial);


/*****************************************************************************
 *
 * Description:
 *    This function takes a counting semaphore, i.e. decreasing the semaphore 
 *    counting. If the semaphore counter is zero the function will block until 
 *    another process or an ISR gives the semaphore or a timeout occurs. 
 *
 * Params:
 *    [in]  pSem    - A pointer to an initialized semaphore structure. 
 *    [in]  timeout - After timeout ticks the operation will timeout. A 
 *                    timeout of zero means no timeout at all. 
 *    [out] pError  - The return status of the function. 
 *
 * Returns:
 *    TRUE if semaphore was taken and FALSE if timeout or error. 
 *
 * Error codes:
 *    OS_OK         - The function completed successfully. 
 *    OS_ERROR_ISR  - The function was called from an interrupt service 
 *                    routine. 
 *    OS_ERROR_NULL - A NULL pointer was supplied to the function where it was 
 *                    not allowed. 
 *
 ****************************************************************************/
tBool osSemTake(tCntSem* pSem,
                tU32     timeout,
                tU8*     pError);


/*****************************************************************************
 *
 * Description:
 *    This function gives a counting semaphore, i.e. increases the semaphore 
 *    counter. If there are one or more processes waiting for the semaphore 
 *    the process with highest priority is made ready to run. 
 *
 * Params:
 *    [in]  pSem   - A pointer to an initialized semaphore structure. 
 *    [out] pError - The return status of the function. 
 *
 * Error codes:
 *    OS_OK         - The function completed successfully. 
 *    OS_ERROR_NULL - A NULL pointer was supplied to the function where it was 
 *                    not allowed. 
 *
 ****************************************************************************/
void osSemGive(tCntSem* pSem,
               tU8*     pError);


/*****************************************************************************
 *
 * Description:
 *    This function tries to take a counting semaphore. If the semaphore 
 *    cannot be taken the function immediately returns instead of blocking. 
 *    This function can be used from an ISR (interrupt service routine). 
 *
 * Params:
 *    [in]  pSem   - A pointer to an initialized semaphore structure. 
 *    [out] pError - The return status of the function. 
 *
 * Returns:
 *    0 if the semaphore was taken, else 1. 
 *
 * Error codes:
 *    OS_OK         - The function completed successfully. 
 *    OS_ERROR_NULL - A NULL pointer was supplied to the function where it was 
 *                    not allowed. 
 *
 ****************************************************************************/
tU8 osSemTryTake(tCntSem* pSem,
                 tU8*     pError);


/*****************************************************************************
 *
 * Description:
 *    This function initializes a queue structure. 
 *
 * Params:
 *    [in] pQueue     - A pointer to an allocated queue structure. 
 *    [in] pQueueArea - A pointer to the queue area. The user must allocate 
 *                      the memory area used by the queue. The queue area is 
 *                      an array of void pointers. 
 *    [in] size       - The size of the queue area. The size is given in 
 *                      number of void pointers in the area. 
 *
 ****************************************************************************/
void osCreateQueue(tQueue* pQueue,
                   void**  pQueueArea,
                   tU16    size);


/*****************************************************************************
 *
 * Description:
 *    This function retrieves the first message from the queue. The message is 
 *    removed from the queue. If the queue is empty the function will block 
 *    until there is a message to retrieve or a timeout occurs. 
 *
 * Params:
 *    [in]  pQueue  - A pointer to an initialized queue structure. 
 *    [in]  timeout - The number of ticks to wait on a queue before returning. 
 *                    If a timeout of zero is specified the function will 
 *                    never timeout. 
 *    [out] pError  - The return status of the function. 
 *
 * Returns:
 *    The first message in the queue or NULL if timeout or error. 
 *
 * Error codes:
 *    OS_OK         - The function completed successfully. 
 *    OS_ERROR_ISR  - The function was called from an interrupt service 
 *                    routine. 
 *    OS_ERROR_NULL - A NULL pointer was supplied to the function where it was 
 *                    not allowed. 
 *
 ****************************************************************************/
void* osPendQueue(tQueue* pQueue,
                  tU16    timeout,
                  tU8*    pError);


/*****************************************************************************
 *
 * Description:
 *    This function tries to receive the first message from the queue. If the 
 *    queue is empty the function returns immediately. This function can be 
 *    called from within an interrupt service routine (ISR). 
 *
 * Params:
 *    [in]  pQueue - A pointer to an initialized queue structure. 
 *    [out] pError - The return status of the function. 
 *
 * Returns:
 *    The retrieved message or NULL if the queue is empty. 
 *
 * Error codes:
 *    OS_OK         - The function completed successfully. 
 *    OS_ERROR_NULL - A NULL pointer was supplied to the function where it was 
 *                    not allowed. 
 *
 ****************************************************************************/
void* osAcceptQueue(tQueue* pQueue,
                    tU8*    pError);


/*****************************************************************************
 *
 * Description:
 *    This function clears a queue from all messages. 
 *
 * Params:
 *    [in]  pQueue - A pointer to an initialized queue. 
 *    [out] pError - The return status of the function. 
 *
 * Error codes:
 *    OS_OK         - The function completed successfully. 
 *    OS_ERROR_NULL - A NULL pointer was supplied to the function where it was 
 *                    not allowed. 
 *
 ****************************************************************************/
void osFlushQueue(tQueue* pQueue,
                  tU8*    pError);


/*****************************************************************************
 *
 * Description:
 *    This function posts a new message to the end of the queue. 
 *
 * Params:
 *    [in]  pQueue - A pointer to an initialized queue structure. 
 *    [in]  msg    - The message to post. 
 *    [out] pError - The return status of the function. 
 *
 * Error codes:
 *    OS_ERROR_QUEUE_FULL - The queue is full. 
 *    OS_OK               - The function completed successfully. 
 *    OS_ERROR_NULL       - A NULL pointer was supplied to the function where 
 *                          it was not allowed. 
 *
 ****************************************************************************/
void osPostQueue(tQueue* pQueue,
                 void*   msg,
                 tU8*    pError);


/*****************************************************************************
 *
 * Description:
 *    This function posts a new message to the front of the queue. 
 *
 * Params:
 *    [in]  pQueue - 
 *    [in]  msg    - The message to post. 
 *    [out] pError - The return status of the function. 
 *
 * Error codes:
 *    OS_ERROR_QUEUE_FULL - The queue is full. 
 *    OS_OK               - The function completed successfully. 
 *    OS_ERROR_NULL       - A NULL pointer was supplied to the function where 
 *                          it was not allowed. 
 *
 ****************************************************************************/
void osPostFrontQueue(tQueue* pQueue,
                      void*   msg,
                      tU8*    pError);


/*****************************************************************************
 *
 * Description:
 *    This function initializes a timer. A timer is initialized with a timer 
 *    value, specified in timer ticks. When the specified time has elapsed the 
 *    timer is said to fire. When a timer fire the callback function of the 
 *    timer is executed. A timer can be set to be repeatable. A repeatable 
 *    timer is reactivated once the callback function has returned. The timer 
 *    structure must be allocated, statically or dynamically, by the user 
 *    before this function is used. osCreateTimer does not allocate the 
 *    structure, it initializes and queues the timer. 
 *
 * Params:
 *    [in] pTimer   - A pointer to an allocated timer structure. 
 *    [in] callback - The callback to be used when the timer fires. 
 *    [in] repeat   - If TRUE the timer will be reactivated as soon as the 
 *                    callback function has returned. 
 *    [in] time     - The initial timer value, specified in system ticks. 
 *
 ****************************************************************************/
void osCreateTimer(tTimer* pTimer,
                   void    (*callback) (void),
                   tBool   repeat,
                   tU32    time);


/*****************************************************************************
 *
 * Description:
 *    This function deletes a timer. The timer structure is not de-allocated, 
 *    only removed from the timer queue. If the timer has already fired and is 
 *    not repeatable there is no need to call this function. It is only 
 *    meaningful to call this function on a timer that is armed but not fired. 
 *
 * Params:
 *    [in]  pTimer - A pointer to the timer to delete. 
 *    [out] pError - The return status of the function. 
 *
 * Error codes:
 *    OS_OK         - The function completed successfully. 
 *    OS_ERROR_NULL - A NULL pointer was supplied to the function where it was 
 *                    not allowed. 
 *
 ****************************************************************************/
void osDeleteTimer(tTimer* pTimer,
                   tU8*    pError);


/*****************************************************************************
 *
 * Description:
 *    This function initializes the timer process. The timer process runs on 
 *    the highest priority, i.e. 0, and executes the timer callback function 
 *    when a timer expires. No other process should be run on this priority. 
 *
 * Params:
 *    [out] pError - The return status of the function. 
 *
 * Error codes:
 *    OS_OK             - The function completed successfully. 
 *    OS_ERROR_ALLOCATE - The timer process could not be created since there 
 *                        was no free process control blocks available. The 
 *                        number of process control blocks is specified during 
 *                        operating system configuration (maximum number of 
 *                        processes). 
 *
 ****************************************************************************/
void osInitTimers(tU8* pError);


/*****************************************************************************
 *
 * Description:
 *    This function returns the stack usage. The stack usage is based on the 
 *    maximum size used so far, i.e. from the application start to the point 
 *    where this function is called. 
 *
 * Params:
 *    [in] pid - The pid of the process to check. 
 *
 * Returns:
 *    The used fraction of the stack area specified in percent. 
 *
 ****************************************************************************/
tU8 osStackUsage(tU8 pid);

/*
 * The following functions should only be called from a hardware
 * abstraction layer.
 */


/*****************************************************************************
 *
 * Description:
 *    This function must be called periodically, usually from a timer 
 *    interrupt, to generate a system tick. It is essential to the operating 
 *    system to receive a periodic tick to work at all. All times in the 
 *    operating system is measured in system ticks, i.e. the time between two 
 *    system ticks. 
 *
 ****************************************************************************/
void osTick(void);


/*****************************************************************************
 *
 * Description:
 *    This function implements the scheduling policy and modifies the 
 *    pNxtToRun pointer to point to the process that should run according to 
 *    the policy. The policy is to always run the process with the highest 
 *    priority that is ready to run. If there is more than one process with 
 *    the highest priority, the processes are scheduled in a round-robin 
 *    fashion. 
 *
 ****************************************************************************/
void osGetHighPrioProc(void);

#endif
