/*******************************************************************************
* Project:      Amped'RF Bluetooth
* File name:    OS_Def.h
*
* Copyright (c) 2016 Amped'RF Inc., AR Technology  All rights reserved.
*******************************************************************************/
#ifndef _OS_DEF_H_
#define _OS_DEF_H_

#define SU_RAM_BASE     0x20000000
#define SU_RAM_SIZE     (0x00010000-512)
#define SU_RAM_END      (SU_RAM_BASE + SU_RAM_SIZE)

#define OS_VERSION                01
#define OS_VERSION_VAR            OS_VERSION_VAR_NAME(01)

#define OS_KERNEL_TID             0x0000
#define OS_IDLE_TID               0x0000
#define OS_ISR_TID                0xFFFD // Used for simulations
#define OS_INVALID_TID            0xFFFF
#define OS_INVALID_MID            0xFFFF
#define OS_INVALID_PRIO           0xFFFF
#define OS_INVALID_SIGNAL_NUMBER  0xFFFF

#define OS_HIGH_PRIO              0x40
#define OS_DEFAULT_PRIO           0x80
#define OS_LOW_PRIO               0xC0
#define OS_IDLE_PRIO              0xFF

#define OS_JOB_DONE               (true)
#define OS_JOB_PENDING            (false)

// Genererate a version variable name
#define OS_VERSION_VAR_NAME(ver) \
  BP_Release_ThisObjFileRequiresAReleaseVersionOfBlueOsVer##ver

//#define OS_CHECK_SIGNALS // Check for signal consistency

//------------------------------------------------------------------------------
//  Macros
//------------------------------------------------------------------------------
//#define BP_IS_ISR_MODE()            __READ_IPSR()
//#define BP_ASSERT_ISR_MODE()        assertc((BP_IS_ISR_MODE()), "NotISRmode")

// Get the signal number from the head.
// Note: Please do NOT access the head directly.
#define OS_GetSignalNo(pSignal)      ((pSignal)->Head.SignalNumber)

// Get a pointer to the first byte in the data.
#define OS_GetSignalDataPtr(pSignal) (&((pSignal)->Data.Byte[0]))

// Critical section
#define OS_InitCriticalSection(CS)  (OS_InitMutex(CS))
#define OS_EnterCriticalSection(CS) (OS_LockMutex(CS, true))
#define OS_ExitCriticalSection(CS)  (OS_UnlockMutex(CS))

// Macro for declaring a memory pool
// $$$-JL: Obsolete! To be removed!
#define OS_DECLARE_POOL(Pool, NoOfBlocks, BlockSize) \
  tOS_MemBlockPtr Pool[(sizeof(tOS_Pool) + \
                       NoOfBlocks * (((BlockSize+3)&0xFFFFFFFC) + sizeof(tOS_MemBlock))) / \
                       sizeof(tOS_MemBlockPtr)]
// $$$-JL: Obsolete! To be removed!
#define OS_DECLARE_MEM_POOL(Pool, NoOfBlocks, BlockSize) \
  tOS_MemBlockPtr Pool[(sizeof(tOS_Pool) + \
                       NoOfBlocks * (((BlockSize+3)&0xFFFFFFFC) + sizeof(tOS_MemBlock))) / \
                       sizeof(tOS_MemBlockPtr)]

// Macro for declaring a heap
#define OS_DECLARE_HEAP(Heap, Size)  char Heap[Size]

// Macros for checking execution mode
#ifdef STM32
#define OS_IS_ISR_MODE()            __READ_IPSR()
#else
#define OS_IS_ISR_MODE()            EIC_CurrentPriorityLevelValue()
#endif
#define OS_ASSERT_ISR_MODE()        assertc((OS_IS_ISR_MODE()), "NotISRmode")
#define OS_ASSERT_FISR_MODE()       assertc((OS_IS_ISR_MODE()), "NotFISRmode")
#define OS_ASSERT_USER_MODE()       assertc((!OS_IS_ISR_MODE()),"NotUserMode")

// Macros used for debug purposes
#ifdef MAGIC_DEBUG
#define OS_DECLARE_MAGIC_NUMBER(var)   uint32 var;
#else
#define OS_DECLARE_MAGIC_NUMBER(var)
#endif //MAGIC_DEBUG

// Macro to check the OS version variable is available at link time
#define OS_CHECK_VERSION()          (OS_VERSION_VAR = 0)

// Macro to make sure that users of OS and OS iteself are compiled
// the same way with regards to debug and release
#define OS_RegisterDispatchFunc(MID, DispatchFunc) \
  OS_RegisterDispatchFuncImpl(MID, DispatchFunc); OS_CHECK_VERSION()


//------------------------------------------------------------------------------
//  Types
//------------------------------------------------------------------------------
typedef uint16 tOS_TaskId;
typedef uint16 tOS_TaskPrio;
typedef uint16 tOS_DataSize;
typedef uint32 tOS_SignalNo;
typedef uint32 tBP_SignalNo;
typedef char*  tOS_TaskName;
typedef char*  tOS_Name;
typedef uint16 tOS_ModuleId;
typedef uint8* tOS_StackPtr;

// Please do not access this data structure from outside.
// It is here because it is needed in the tOS_Signal declaration
typedef struct tOS_SignalHead {
  OS_DECLARE_MAGIC_NUMBER(MagicNumber)
  tOS_SignalNo       SignalNumber;
  tOS_TaskId         SenderTaskId;
  tOS_TaskId         OwnerTaskId;
  tOS_DataSize       DataSize;
#ifdef OS_CHECK_SIGNALS
  uint8              CheckTraverse;
#endif
  struct tOS_Signal *pNextSignal;
} tOS_SignalHead;

typedef struct tOS_Signal {
  tOS_SignalHead Head;
  tOS_SignalData Data;
} tOS_Signal, *tpOS_Signal;

typedef struct tOS_SignalQueue {
  tOS_Signal *pFirst;
  tOS_Signal *pLast;
  uint16     Count;
  uint16     Limit;
} tOS_SignalQueue, *tpOS_SignalQueue;

// Forward declaration
struct tOS_Pool;

// Callback function for mem pool
typedef void (*tOS_PoolNotifyFunc)(struct tOS_Pool*);

// Memory Block Pointer (double pointer)
typedef void *tOS_MemBlockPtr;

// Memory Block Head
typedef struct tOS_MemBlock {
  OS_DECLARE_MAGIC_NUMBER(MagicNumber)
  struct tOS_Pool     *pOwnerPool;
  struct tOS_MemBlock *pNext;
  struct tOS_MemBlock *pMemHeader;
} tOS_MemBlock, *tpOS_MemBlock;

// Memory Pool
typedef struct tOS_Pool {
  char                *Name;
  uint32               NoOfBlocks;
  uint32               BlockSize;
  uint32               BlockUse;
  uint32               BlockUsePeak;
  void *               TopAddress;
  tOS_PoolNotifyFunc   NotifyFunc;
  struct tOS_Pool     *pNextPool;
  tpOS_MemBlock        pFreeBlock;
} tOS_Pool, *tpOS_Pool, tOS_MemPool, *tpOS_MemPool;

// Memory Block Queue
typedef struct tOS_Queue {
  tpOS_MemBlock pFirst;
  tpOS_MemBlock pLast;
  uint16        Count;
  uint16        Limit;
} tOS_Queue, *tpOS_Queue;

// Heap Block Head
typedef struct tOS_HeapBlockHead {
  OS_DECLARE_MAGIC_NUMBER(MagicNumber)
  uint16                Size;
  tOS_TaskId            TaskId;
} tOS_HeapBlockHead, *tpOS_HeapBlockHead;

// Memory Block Head
typedef struct tOS_HeapBlock {
  tOS_HeapBlockHead     Head;
  struct tOS_HeapBlock *pNextBlock;
} tOS_HeapBlock, *tpOS_HeapBlock;

// Memory Pool
typedef struct tOS_Heap {
  char                *Name;
  uint32               Size;
  struct tOS_Heap     *pNextHeap;
  uint16              *pSizeTable;
  tpOS_HeapBlock      *pBlockTable;
  tpOS_HeapBlock       pFreeBlock;
} tOS_Heap, *tpOS_Heap;

// Memory Type
typedef enum {
  eOS_XRam,
  eOS_IRam,
  eOS_BRam,
  eOS_AnyRam
} tOS_MemType, tOS_MemLocation; // $$$-JL: Obsolete! To be removed!

// Memory Allocation Result
// $$$-JL: Obsolete! To be removed!
typedef struct {
  void   *pMem;
  uint32 AlloctedSize;
} tOS_ReqMemInfo;

// Task Context
typedef struct tOS_TaskContext {
  OS_DECLARE_MAGIC_NUMBER(MagicNumber1)
  struct tOS_TaskContext *pNext;
  tOS_TaskId              TaskId;
  uint16                  StackSize;
  tOS_StackPtr            StackPtr;
  OS_DECLARE_MAGIC_NUMBER(MagicNumber2)
} tOS_TaskContext, *tpOS_TaskContext;

// Mutex
typedef struct {
  OS_DECLARE_MAGIC_NUMBER(MagicNumber)
  tpOS_TaskContext  pFirst;
  tpOS_TaskContext  pLast;
  tOS_TaskId        OwnerTaskId;
  uint16            LocksCount;
} tOS_Mutex, *tpOS_Mutex, tOS_CriticalSection, *tpOS_CriticalSection;

// Semaphore
typedef struct {
  OS_DECLARE_MAGIC_NUMBER(MagicNumber)
  tpOS_TaskContext  pFirst;
  tpOS_TaskContext  pLast;
  uint16            Count;
} tOS_Semaphore, *tpOS_Semaphore;

// Callback function type definition for Module Init
typedef void (*tOS_InitFunc)(void);
typedef tOS_TaskId (*tOS_DispatchFunc)(tOS_SignalNo);

// Module Info
typedef struct tOS_ModuleInfo {
  uint16  MajorVersion;
  uint16  MinorVersion;
  char   *Description;
} tOS_ModuleInfo, *tpOS_ModuleInfo;

// Module Init Item to go in the init array
typedef struct tOS_ModuleInitItem {
  tOS_ModuleId    *pModuleId;
  tOS_InitFunc     InitFunc;
  char            *Name;
  tpOS_ModuleInfo  pInfo;
} tOS_ModuleInitItem, *tpOS_ModuleInitItem;

typedef struct tOS_MCBItem {
  tOS_DispatchFunc DispatchFunc;
} tOS_MCBItem;

// Event
typedef struct {
  OS_DECLARE_MAGIC_NUMBER(MagicNumber)
  tpOS_TaskContext  pTasks;
} tOS_Event, *tpOS_Event;

// External declarations of variables for each module id.
/*
#define OS_BEGIN_MODULE_DECLARATION
#define OS_DECLARE_MODULE_INFO(m)   extern tOS_ModuleId BP_##m;
#define OS_DECLARE_MODULE(m)        extern tOS_ModuleId BP_##m;
#define OS_END_MODULE_DECLARATION
#include "Modules.h"
#undef OS_BEGIN_MODULE_DECLARATION
#undef OS_DECLARE_MODULE_INFO
#undef OS_DECLARE_MODULE
#undef OS_END_MODULE_DECLARATION
*/

// Build info
typedef const struct {
  const uint32 BuildNumber;
  const char  *pBuildComment;
  const char  *pBuildTime;
  const char  *pCopyright;
} tOS_BuildInfo, *tpOS_BuildInfo;

// Callback function type definitions
typedef void       (*tOS_ReceiveFunc)(tOS_Signal*);
typedef void       (*tOS_IdleFunc)(void);
typedef void       (*tOS_InterceptFunc)(tOS_Signal*);
typedef void       (*tOS_FatalFunc)(uint32 Reason, char *pFileName, uint16 LineNo);
typedef void       (*tOS_ShutdownFunc)(uint32 Reason);
typedef bool       (*tOS_BackgroundJobFunc)(uint32 Argument);

#define OS_ASSERT(Exp, Comment)     assertc((Exp), "BP:" Comment)
#define OS_ASSERT_SIG_NUMBER(No)    OS_ASSERT(((No) != OS_INVALID_SIGNAL_NUMBER),"BadSigNo")
#define OS_ASSERT_INVALID_PTR(Ptr)  OS_ASSERT(((Ptr) == OS_INVALID_PTR),"BadPtr")
#define OS_ASSERT_VALID_PTR(Ptr)    OS_ASSERT(((Ptr) != OS_INVALID_PTR),"BadPtr")
#define OS_ASSERT_EXEC_TID(Tid)     OS_ASSERT(((Tid) == OS_Data.ExecutingTaskId),"BadOwner")
#define OS_ASSERT_TID(Tid)          OS_ASSERT(((Tid) != OS_INVALID_TID),"BadTId")

//------------------------------------------------------------------------------
//
//  External Variables
//
//------------------------------------------------------------------------------

extern tOS_BuildInfo OS_BuildInfo; // Build info

// Variable used for check link version, debug or release
extern uint8 OS_VERSION_VAR;

// For accessing module Initilaization items by OS and to know
// number of modules - See OS_Modules.c for the definitions.
extern const tOS_ModuleInitItem OS_MIT[];
extern const uint8 OS_NModules;
extern tOS_MCBItem OS_MCB[];

//------------------------------------------------------------------------------
//  Functions declarations
//------------------------------------------------------------------------------

// Initiate the back plane and all the modules.
void OS_Init(void);

//------------------------------------------------------------------------------

// Get information about a module
void OS_GetModuleInfo(tOS_ModuleId ModuleId, char **pName,
                      tpOS_ModuleInfo *ppModuleInfo);

//------------------------------------------------------------------------------

// Enumerate all modules. Start with ModuleId = BP_INVALID_MID. Ends with
// returning BP_INVALID_MID.

tOS_ModuleId OS_GetNextModule(tOS_ModuleId ModuleId);

//------------------------------------------------------------------------------

// Return current ModuleId.

tOS_ModuleId OS_GetCurrentModule(void);

//------------------------------------------------------------------------------

// Create a task. This is normally done in the module init routine.

tOS_TaskId OS_CreateTask(tOS_TaskName TaskName, tOS_InitFunc InitFunc,
                         tOS_ReceiveFunc ReceiveFunc, tOS_TaskPrio Prio);

//------------------------------------------------------------------------------

// Create a task with it's own stack. This enables the task to use blocking
// routines like OS_ObtainSemaphore. The caller needs to allocate the stack
// and provide a pointer and stack size. pStack should point to the lowest
// address of the stack. Both pStack and StackSize should to be 4 byte aligned.

tOS_TaskId OS_CreateTaskWithStack(tOS_TaskName TaskName, tOS_InitFunc InitFunc,
                                  tOS_ReceiveFunc ReceiveFunc, tOS_TaskPrio Prio,
                                  uint8 *pStack, uint16 StackSize);

//------------------------------------------------------------------------------

// Delete the task with TaskId. Returns true if task was successfully deleted.
// Returns false if trying to delete self.

bool OS_DeleteTask(tOS_TaskId TaskId);

//------------------------------------------------------------------------------

// Transform a task with its own stack to a task without a stack.

bool OS_ReleaseTaskStack(tOS_TaskId TaskId);

//------------------------------------------------------------------------------

// Check if a task with higher priority needs to run. If so, suspend the
// current executing task and schedule the task with higher priority.
// It is requires that the current executing task has a stack for a switch to
// happen.

void OS_RescheduleTask(void);

//------------------------------------------------------------------------------

// Get a pointer to the name of the task

tOS_TaskName OS_GetTaskName(tOS_TaskId TaskId);

//------------------------------------------------------------------------------

// Get the priority of a task

tOS_TaskPrio OS_GetTaskPrio(tOS_TaskId TaskId);

//------------------------------------------------------------------------------

// Search the task names of all the tasks

tOS_TaskId OS_FindTaskId(tOS_TaskName TaskName);

//------------------------------------------------------------------------------

// Enumerate all tasks. Start with TaskId = BP_INVALID_TID. Ends with returning
// BP_INVALID_TID.

tOS_TaskId OS_GetNextTaskId(tOS_TaskId TaskId);

//------------------------------------------------------------------------------

// Register a dispatch function for the module. This is normally done in the
// module init routine.
// Note: Please use the macro BP_RegisterDispatchFunc instead calling this
///      function

void OS_RegisterDispatchFuncImpl(tOS_ModuleId MID, tOS_DispatchFunc DispatchFunc);

//------------------------------------------------------------------------------

// To be used by interrupt routines to find the task once and for all

tOS_TaskId OS_IsrFindTask(tOS_ModuleId MId, tOS_SignalNo SignalNo);

//------------------------------------------------------------------------------

// Send a signal to a specific module

void OS_Send(tOS_ModuleId MID, tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Send a signal to a specific task

void OS_SendToTask(tOS_TaskId TId,tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Send a signal to a specific module from a interrupt service routine.
// Note: Should only be used by interrupt service routines!

void OS_IsrSend(tOS_ModuleId MId, tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Send a signal to a specific task from a interrupt service routine.
// Note: Should only be used by interrupt service routines!

void OS_IsrSendToTask(tOS_TaskId TId,tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Send a signal to a specific module from a fast interrupt service routine.
// Note: Should only be used by fast interrupt service routines! (FIQ)

void OS_FisrSend(tOS_ModuleId MId, tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Send a signal to a specific task from a interrupt service routine.
// Note: Should only be used by fast interrupt service routines! (FIQ)

void OS_FisrSendToTask(tOS_TaskId TId,tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Send a signal to a specific task and fake the sending task.
// Note: Should only be used by simulator or equivalent!

void OS_SendWithExplicitSender(tOS_ModuleId MId, tOS_Signal *pSignal,
                               tOS_TaskId TaskId);

//------------------------------------------------------------------------------

// Resend a signal that has been intercepted by the registered intercept function

void OS_ResendIntercepted(tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Save a signal in the special saved queue. There is one saved queue for
// every task.

void OS_SaveSignal(tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Move the signals in the saved queue to the incomming signal queue.
// The signals will be received later on by the task. The will be placed
// last in the signal queue.

void OS_ReceiveSavedSignals(void);

//------------------------------------------------------------------------------

// Enable automatically call to OS_ReceiveSavedSignals whenever a signal is
// received. This will preserve the order of your saved signals with relation
// to new signals.

void OS_SetAutoReceiveSavedSignals(bool On);

//------------------------------------------------------------------------------

// Check if any signals are pending for any task. This routine is called
// when about to go to sleep. All interrupts should be disabled before
// calling this routine.

bool OS_IsSignalPending(void);

//------------------------------------------------------------------------------

// Start the signal pump in the Back Plane. This never returns unless someone
// calles the OS_Stop() function. This function is called after system
// init.

void OS_Start(void);

//------------------------------------------------------------------------------

// Stop the signal pump in the BackPlane. See OS_Start() for more info.

void OS_Stop(void);

//------------------------------------------------------------------------------

// Register a function that will be called when no signals are queued

void OS_RegisterIdleFunc(tOS_IdleFunc IdleFunc);

//------------------------------------------------------------------------------

// Deregister the idle function

void BP_DeregisterIdleFunc(tOS_IdleFunc IdleFunc);

//------------------------------------------------------------------------------

// Register a function that will be called for every signal sent. The signal
// will be bassed to this function instead of the real receiver. The intercept
// function can look at sender and receiver with the functions below.
// Use OS_ResendIntercepted to pass the signal on to the real receiver.

void OS_RegisterInterceptFunc(tOS_InterceptFunc InterceptFunc);

//------------------------------------------------------------------------------

// Deregister the idle function

void OS_DeregisterInterceptFunc(tOS_InterceptFunc InterceptFunc);

//------------------------------------------------------------------------------

// Register a function that will be called if a fatal event occures

void OS_RegisterFatalFunc(tOS_FatalFunc FatalFunc);

//------------------------------------------------------------------------------

// Deregister the fatal function

void OS_DeregisterFatalFunc(tOS_FatalFunc FatalFunc);

//------------------------------------------------------------------------------

// Register a function that will be called to shut down the system

void OS_RegisterShutdownFunc(tOS_ShutdownFunc ShutdownFunc);

//------------------------------------------------------------------------------

// Deregister the shut down function

void OS_DeregisterShutdownFunc(tOS_ShutdownFunc ShutdownFunc);

//------------------------------------------------------------------------------

// Alocate a signal with a certain signal number and a specific size in
// the normal memory pool.
#ifdef DEBUG
#define OS_AllocSignal(a, b)        BP_AllocSignalDbg(a, b, __FILE__, __LINE__)
tOS_Signal* BP_AllocSignalDbg(tOS_SignalNo SignalNo, tOS_DataSize DataSize,
                            char * file, int  line);
#else
tOS_Signal* OS_AllocSignal(tOS_SignalNo SignalNo, tOS_DataSize DataSize);
#endif
//------------------------------------------------------------------------------

// Alocate a signal with a certain signal number and a specific size in
// the normal memory pool.
// Note: Should only be used by interrupt service routines!

#ifdef DEBUG
#define OS_IsrAllocSignal(a, b)     BP_IsrAllocSignalDbg(a, b, __FILE__, __LINE__)
tOS_Signal* BP_IsrAllocSignalDbg(tOS_SignalNo SignalNo, tOS_DataSize DataSize,
                               char * file, int  line);
#else
tOS_Signal* OS_IsrAllocSignal(tOS_SignalNo SignalNo, tOS_DataSize DataSize);
#endif

//------------------------------------------------------------------------------

// Alocate a signal with a certain signal number and a specific size in
// the normal memory pool.
// Note: Should only be used by fast interrupt service routines! (FIQ)

tOS_Signal* OS_FisrAllocSignal(tOS_SignalNo SignalNo, tOS_DataSize DataSize);

//------------------------------------------------------------------------------

// Alocate a signal with a certain signal number and a specific size in
// the memory pool accessable by DMA

tOS_Signal* OS_AllocSignalInBuffer(tOS_SignalNo SignalNo, tOS_DataSize DataSize);

//------------------------------------------------------------------------------

// Alocate a signal with a certain signal number and a specific size in
// the memory pool accessable by DMA
// Note: Should only be used by interrupt service routines!

tOS_Signal* OS_IsrAllocSignalInBuffer(tOS_SignalNo SignalNo, tOS_DataSize DataSize);

//------------------------------------------------------------------------------

// Alocate a signal with a certain signal number and a specific size in
// the memory pool accessable by DMA
// Note: Should only be used by fast interrupt service routines! (FIQ)

tOS_Signal* OS_FisrAllocSignalInBuffer(tOS_SignalNo SignalNo, tOS_DataSize DataSize);

//------------------------------------------------------------------------------

// Release a signal.

#ifdef DEBUG
#define OS_ReleaseSignal(a)     BP_ReleaseSignalDbg(a, __FILE__, __LINE__)
void BP_ReleaseSignalDbg(tOS_Signal *pSignal, char * file, int  line);
#else
void OS_ReleaseSignal(tOS_Signal *pSignal);
#endif

//------------------------------------------------------------------------------

// Release a signal from an interrupt service routine.
// Note: Should only be used by interrupt service routines!


#ifdef DEBUG
#define OS_IsrReleaseSignal(a)     BP_IsrReleaseSignalDbg(a, __FILE__, __LINE__)
void BP_IsrReleaseSignalDbg(tOS_Signal *pSignal, char * file, int  line);
#else
void OS_IsrReleaseSignal(tOS_Signal *pSignal);
#endif

//------------------------------------------------------------------------------

// Check if we have signals free to allocate.
// Returns false if we are out of any signals.

bool OS_FreeSignalsExists(void);

//------------------------------------------------------------------------------

// Read the sender in the signal header.

tOS_TaskId OS_GetSignalSender(tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Read the receiver in the signal header.

tOS_TaskId OS_GetSignalReceiver(tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Read the owner in the signal header.

tOS_TaskId OS_GetSignalOwner(tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Set the executing task as owner of signal.

void OS_TakeOwnershipOfSignal(tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Set the executing task as owner of signal.
// Note: Should only be used by interrupt service routines!

void OS_IsrTakeOwnershipOfSignal(tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Read the data size in the signal header.

tOS_DataSize OS_GetDataSize(tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Initialize a signal queue.
// Should only be done once when the queue is allocated

void OS_InitSignalQueue(tOS_SignalQueue *pSignalQueue);

//------------------------------------------------------------------------------

// Add a signal to the end of a signal queue

void OS_AddToSignalQueue(tOS_SignalQueue *pSignalQueue, tOS_Signal *pSignal);

//------------------------------------------------------------------------------

// Take out the first signal in the signal queue. Returns NULL if queue is empty.

tOS_Signal* OS_GetFirstInSignalQueue(tOS_SignalQueue *pSignalQueue);

//------------------------------------------------------------------------------

// Counts the number of signals in a signal queue.
// Note: It loops through the queue when it counts

uint32 OS_GetSizeOfSignalQueue(tOS_SignalQueue *pSignalQueue);

//------------------------------------------------------------------------------

// Get the TaskId of the current executing task.
// Note: Should not be called from an ISR.

tOS_TaskId OS_GetExecutingTaskId(void);

//------------------------------------------------------------------------------

// Allocate a block of memory. Returns NULL if no memory available.

void* OS_AllocMemory(tOS_DataSize DataSize);

//------------------------------------------------------------------------------

// Allocates a block of memory in Buffer RAM

void* OS_AllocMemoryInBuffer(tOS_DataSize DataSize);

//------------------------------------------------------------------------------

// Release a block of memory.

void OS_ReleaseMemory(void* pMemory);

//------------------------------------------------------------------------------

// Request a controlled system shutdown. This function will return.

void OS_RequestSystemShutdown(uint32 Reason);

//------------------------------------------------------------------------------

// Report to BackPlane that a task has done shutdown.
// After a SIG_SHUTDOWN signal has been received by a task, it should
// report back when the shutdown of this task has been done.

void OS_ReportTaskShutdownDone(void);

//------------------------------------------------------------------------------

// Create a bacground job. The Background job function will be called whenever
// the backplane is in idle until the function returns BP_JOB_DONE. When
// the function returns BP_JOB_PENDING it will be called again. The parameter
// Argument is passed to the background job function when it is called.

void OS_CreateBackgroundJob(tOS_BackgroundJobFunc BackgoundJobFunc, uint32 Argument);

//------------------------------------------------------------------------------

// Request a immidiate system shutdown. This function will NOT return.

void OS_SystemFatal(uint32 Reason,char *pFileName, uint16 LineNo);
//------------------------------------------------------------------------------

// Get a pointer to the tBP_BuildInfo data structure

tpOS_BuildInfo OS_GetBuildInfoPtr(void);

//------------------------------------------------------------------------------

// Execute as another task. The context will be set to TaskId and the old
// task context will be return.
// Please note: Only to be used by power users who know what they are doing!

tOS_TaskId OS_ExecuteAsTask(tOS_TaskId TaskId);

//------------------------------------------------------------------------------

// Returns true if we are executing in IRQ or FIQ mode.

bool OS_IsIsrMode(void);

//------------------------------------------------------------------------------

// Force ISR mode in the simulator
// Note: Should only be called in the simulator

tOS_TaskId OS_SimulatorForceIsrMode(void);

//------------------------------------------------------------------------------

// Force user mode in the simulator
// Note: Should only be called in the simulator
void OS_SimulatorForceUserMode(tOS_TaskId TaskId);

//------------------------------------------------------------------------------
//
//  Mutex Management
//
//------------------------------------------------------------------------------

void OS_InitMutex(tpOS_Mutex pMutex);


//------------------------------------------------------------------------------

bool OS_LockMutex(tpOS_Mutex pMutex, bool Suspend);

//------------------------------------------------------------------------------

void OS_UnlockMutex(tpOS_Mutex pMutex);

//------------------------------------------------------------------------------

void OS_DeleteMutex(tpOS_Mutex pMutex);

//------------------------------------------------------------------------------
//
//  Semaphore Management
//
//------------------------------------------------------------------------------

// Initiates a semaphore. The caller needs to allocate the space for the
// semaphore, i.e. declare a variable of type tBP_Semaphore. The initial
// count of the semaphore is set to the value of the count parameter.

void OS_InitSemaphore(tpOS_Semaphore pSemaphore, uint16 Count);

//------------------------------------------------------------------------------

// Get a semaphore. Returns true if a semaphore was a obtained. The task will
// be suspended if the parameter Supend is true and no semaphore is available.

bool OS_ObtainSemaphore(tpOS_Semaphore pSemaphore, bool Suspend);

//------------------------------------------------------------------------------

// Release a semaphore. The executing task will be suspended if a task with
// higher priority is waiting for the sempahore.

void OS_ReleaseSemaphore(tpOS_Semaphore pSemaphore);

//------------------------------------------------------------------------------

// Release a semaphore from IRQ or FIQ context.

void OS_IsrReleaseSempaphore(tpOS_Semaphore pSemaphore);

//------------------------------------------------------------------------------

// Delete a semapore. All pending tasks will wake-up. The executing task will
// be suspended if a task with higher priority is waiting for the sempahore.

void OS_DeleteSemaphore(tpOS_Semaphore pSemaphore);


//------------------------------------------------------------------------------
//
//  Event Management
//
//------------------------------------------------------------------------------

// Initiates an event. The caller needs to allocate the space for the
// event, i.e. declare a variable of type tBP_Event.

void OS_InitEvent(tpOS_Event pEvent);

//------------------------------------------------------------------------------

// Wait for an event to pulse. Returns true if an event was pulsed. A return
// value of false indicates that the task can't be blocked, i.e. does not have
// a stack.

bool OS_WaitForEvent(tpOS_Event pEvent);

//------------------------------------------------------------------------------

// Pulse an event. All tasks waiting for this event will wake-up.

void OS_PulseEvent(tpOS_Event pEvent);

//------------------------------------------------------------------------------

// Pulse an event from ISR or FIQ contect. All tasks waiting for this event will
// be woken up.

void OS_IsrPulseEvent(tpOS_Event pEvent);

//------------------------------------------------------------------------------

// Pulse an event. Only ONE task waiting for this event will wake-up.

void OS_PulseEventOneTaskOnly(tpOS_Event pEvent);

//------------------------------------------------------------------------------

// Pulse an event from ISR or FIQ contect. Only ONE task waiting for this event
// will wake-up.

void OS_IsrPulseEventOneTaskOnly(tpOS_Event pEvent);

//------------------------------------------------------------------------------

// Delete an event. All pending tasks will wake-up. The executing task will
// be suspended if a task with higher priority is waiting for the sempahore.

void OS_DeleteEvent(tpOS_Event pEvent);

//------------------------------------------------------------------------------
//
//  Memory Managment
//
//------------------------------------------------------------------------------

// Reserve a chunk (Size) of memory of a certain memory type (MemType)
uint8* OS_ReserveMemory(uint32 Size);

//------------------------------------------------------------------------------

// Reserve a chunk of memory of a certain memory type (MemType) for a pool
uint8* OS_ReservePoolMemory(uint32 NoOfBlocks, uint32 BlockSize);

//------------------------------------------------------------------------------


// This function will return the largest free memory space size

uint32 OS_GetLargestFreeMemorySize(void);

//------------------------------------------------------------------------------

// This function will return the IRAM free memory size

uint32 OS_GetFreeIramMemorySize(void);

//------------------------------------------------------------------------------

// This function will return the BRAM free memory space size

uint32 OS_GetFreeBramMemorySize(void);

//------------------------------------------------------------------------------

// This function will return the XRAM free memory space size

uint32 OS_GetFreeXramMemorySize(void);

//------------------------------------------------------------------------------
//
//  Pool Management
//
//------------------------------------------------------------------------------

// Create a pool in memory category. A pool consists of a number of
// blocks (NoOfBlocks), each of a certain size (BlockSize). When a block is
// returned to the pool with OS_ReturnToPool, the pool creator will be notified
// with a call back to PoolNotifyFunc when a pool goes from empty (optional).
// Please note: The notify callback executes in the context of who calls
// BP_Return to pool.

tpOS_MemPool OS_CreatePool(char *Name, uint8 *pMem, uint32 NoOfBlocks,
                          uint32 BlockSize, tOS_PoolNotifyFunc PoolNotifyFunc);

//------------------------------------------------------------------------------

// Reset a pool to its create state.

void OS_ResetPool(tpOS_Pool pPool);

//------------------------------------------------------------------------------

// Get a memory block from a pool (pMemPool). Returns NULL if the pool is empty.

void* OS_GetFromPool(tpOS_MemPool pMemPool);

//------------------------------------------------------------------------------

// Return a block to the pool.

void OS_ReturnToPool(void *p);

//------------------------------------------------------------------------------
//
//  Heap Management
//
//------------------------------------------------------------------------------

// Create a heap at address pointed to by pMem and with a size of MemSize bytes.
// Note: OS_CreateHeap does not allocate the memory, it only initializes the
// memory. Use BP_DECLARE_HEAP to allocate memory.

tpOS_Heap OS_CreateHeap(char *Name, char *pMem, uint32 MemSize,
                        uint16 *pSizeTable);

//------------------------------------------------------------------------------

// Allocate a heap block from a heap (pHeap) with a specific size (Size)

void* OS_GetFromHeap(tpOS_Heap pHeap, uint32 Size);

//------------------------------------------------------------------------------

// Return a heap block (p) to a heap (pHeap)

void OS_ReturnToHeap(tpOS_Heap pHeap, void *p);

//------------------------------------------------------------------------------

// Return all fixed size pools to the heap

void OS_PurgeHeap(tpOS_Heap pHeap);

//------------------------------------------------------------------------------

// Go through all heaps and purge them one by one.

void OS_PurgeAllHeaps(void);

//------------------------------------------------------------------------------

// Return a heap block (p) to any heap.
// Note: Will result in a search in memory for the right heap.

bool OS_ReturnToAnyHeap(void *p);

//------------------------------------------------------------------------------

// Return a heap block refered to by a pointer (p) into the heap block. The
// pointer (p) does not have to point to the start of the heap block.
// Note: Will result in a search in memory for the right heap and heap block.

bool OS_TryReturnToHeap(void *p);

//------------------------------------------------------------------------------

// Queue up a delayed call to OS_TryReturnToHeap. The heap block (p) will be
// returned when the idle state is reached.
// Note: Nice to call from ISR and FISR mode.

void OS_ReturnToHeapLater(void *p);

//------------------------------------------------------------------------------

// Read the owner task of the heap block.

tOS_TaskId OS_GetOwnerOfHeapBlock(void *p);

//------------------------------------------------------------------------------

// Set the owner task to the executing task.

void OS_TakeOwnershipOfHeapBlock(void *p);

//------------------------------------------------------------------------------

// Print a heap (pHeap) structure

void OS_DumpHeap(tpOS_Heap pHeap);

//------------------------------------------------------------------------------

// Generic release. The argument could be a signal, a memory block in a pool or
// a heap object.

void OS_Release(void *p);

//------------------------------------------------------------------------------

// Initialize a memory queue.
// Should only be done once when the queue is allocated

void OS_InitQueue(tOS_Queue *pQueue);

//------------------------------------------------------------------------------

// Set the size limit for the queue. Queue items will be returned to pool when
// when the limit is exceeded starting from the front.
// The size limit can be turned of by setting limit to 0 (zero).

void OS_SetQueueLimit(tOS_Queue *pQueue, uint16 Limit);

//------------------------------------------------------------------------------

// Add a buffer to the end of a queue

void OS_Queue(tOS_Queue *pQueue, void *pMem);

//------------------------------------------------------------------------------

// Add a buffer in the front of a queue

void OS_QueueInFront(tOS_Queue *pQueue, void *pMem);

//------------------------------------------------------------------------------

// Take out the buffer from a queue. Returns NULL if queue is empty.

void* OS_GetFromQueue(tOS_Queue *pQueue);

//------------------------------------------------------------------------------

// Dump all signals and their content to the log

void OS_DumpSignalsToLog(bool DumpUnusedAsWell);

//------------------------------------------------------------------------------

// Prints all memory categories, pools and blocks

void OS_DumpPools(void);

//------------------------------------------------------------------------------

// Prints content of all Tasks Signal queues

void OS_DumpQueues(void);

//------------------------------------------------------------------------------

// Gets the shutdown reason

uint32 OS_GetShutdownReason(void);




#endif //BACKPLANE_H

//------------------------------------------------------------------------------
// End of BackPlane.h
