ugfx/src/gos/gos.h

508 lines
14 KiB
C

/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
/**
* @file src/gos/gos.h
* @brief GOS - Operating System Support header file
*
* @addtogroup GOS
*
* @brief Module to build a uniform abstraction layer between uGFX and the underlying system
*
* @note Some of the routines specified below may be implemented simply as
* a macro to the real operating system call.
* @{
*/
#ifndef _GOS_H
#define _GOS_H
#if defined(__DOXYGEN__)
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
/**
* @name Various integer sizes
* @note Your platform may use slightly different definitions to these
* @{
*/
typedef unsigned char bool_t;
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef long int32_t;
typedef unsigned long uint32_t;
/** @} */
/**
* @name Various platform (and operating system) dependent types
* @note Your platform may use slightly different definitions to these
* @{
*/
typedef unsigned long size_t;
typedef unsigned long delaytime_t;
typedef unsigned long systemticks_t;
typedef short semcount_t;
typedef int threadreturn_t;
typedef int threadpriority_t;
/** @} */
/**
* @brief Declare a thread function
*
* @param[in] fnName The name of the function
* @param[in] param A custom parameter that is passed to the function
*/
#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param)
/**
* @brief Declare a thread stack
*
* @param[in] name The name of the stack
* @param[in] sz The size of the stack
*/
#define DECLARE_THREAD_STACK(name, sz) uint8_t name[sz];
/*
* @brief Return from a thread
*
* @details Some underlying operating systems allow to return a value from a thread while others don't.
* For systems that don't allow to return a value from a thread function this call is simply ignored.
*
* @param[in] reval The value which should be returned
*/
#define THREAD_RETURN(retval) return retval
/**
* @name Various platform (and operating system) constants
* @note Your platform may use slightly different definitions to these
* @{
*/
#define FALSE 0
#define TRUE 1
#define TIME_IMMEDIATE 0
#define TIME_INFINITE ((delaytime_t)-1)
#define MAX_SEMAPHORE_COUNT ((semcount_t)(((unsigned long)((semcount_t)(-1))) >> 1))
#define LOW_PRIORITY 0
#define NORMAL_PRIORITY 1
#define HIGH_PRIORITY 2
/** @} */
/**
* @brief A semaphore
* @note Your operating system will have a proper definition for this structure
*/
typedef struct {} gfxSem;
/**
* @brief A mutex
* @note Your operating system will have a proper definition for this structure
*/
typedef struct {} gfxMutex;
/**
* @brief A thread handle
* @note Your operating system will have a proper definition for this.
*/
typedef void * gfxThreadHandle;
/*===========================================================================*/
/* Function declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Halt the GFX application due to an error.
*
* @param[in] msg An optional debug message to show (Can be NULL)
*
* @api
*/
void gfxHalt(const char *msg);
/**
* @brief Exit the GFX application.
*
* @api
*/
void gfxExit(void);
/**
* @brief Allocate memory
* @return A pointer to the memory allocated or NULL if there is no more memory available
*
* @param[in] sz The size in bytes of the area to allocate
*
* @api
*/
void *gfxAlloc(size_t sz);
/**
* @brief Re-allocate memory
* @return A pointer to the new memory area or NULL if there is no more memory available
*
* @param[in] ptr The old memory area to be increased/decreased in size
* @param[in] oldsz The size in bytes of the old memory area
* @param[in] newsz The size in bytes of the new memory area
*
* @note Some operating systems don't use the oldsz parameter as they implicitly know the size of
* old memory area. The parameter must always be supplied however for API compatibility.
* @note gfxRealloc() can make the area smaller or larger but may have to return a different pointer.
* If this occurs the new area contains a copy of the data from the old area. The old memory
* pointer should not be used after this routine as the original area may have been freed.
* @note If there is insufficient memory to create the new memory region, NULL is returned and the
* old memory area is left unchanged.
*
* @api
*/
void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz);
/**
* @brief Free memory
*
* @param[in] ptr The memory to free
*
* @api
*/
void gfxFree(void *ptr);
/**
* @brief Use gfxAlloc and gfxFree to implement malloc() and free()
*
* @note Sometimes your application will include functions that
* want to internally use malloc() and free(). As the default
* implementations of these in your C library are almost
* invariably incorrect for an embedded platform, this option
* allows you to emulate those calls with gfxAlloc() and gfxFree().
* An example is the C library routine rand() which on many
* implementations internally uses malloc().
*
* @api
*/
#ifndef GFX_EMULATE_MALLOC
#define GFX_EMULATE_MALLOC FALSE
#endif
/**
* @brief Yield the current thread
* @details Give up the rest of the current time slice for this thread in order to give other threads
* a chance to run.
*
* @api
*/
void gfxYield(void);
/**
* @brief Put the current thread to sleep for the specified period in milliseconds
*
* @param[in] ms The number milliseconds to sleep
*
* @note Specifying TIME_IMMEDIATE will yield the current thread but return
* on the next time slice.
* @note Specifying TIME_INFINITE will sleep forever.
*
* @api
*/
void gfxSleepMilliseconds(delaytime_t ms);
/**
* @brief Put the current thread to sleep for the specified period in microseconds
*
* @param[in] us The number microseconds to sleep
*
* @note Specifying TIME_IMMEDIATE will return immediately (no sleeping)
* @note Specifying TIME_INFINITE will sleep forever.
*
* @api
*/
void gfxSleepMicroseconds(delaytime_t us);
/**
* @brief Get the current operating system tick time
* @return The current tick time
*
* @note A "tick" is an arbitrary period of time that the operating
* system uses to mark time.
* @note The absolute value of this call is relatively meaningless. Its usefulness
* is in calculating periods between two calls to this function.
* @note As the value from this function can wrap it is important that any periods are calculated
* as t2 - t1 and then compared to the desired period rather than comparing
* t1 + period to t2
*
* @api
*/
systemticks_t gfxSystemTicks(void);
/**
* @brief Convert a given number of millseconds to a number of operating system ticks
* @return The period in system ticks.
*
* @note A "tick" is an arbitrary period of time that the operating
* system uses to mark time.
*
* @param[in] ms The number of millseconds
*
* @api
*/
systemticks_t gfxMillisecondsToTicks(delaytime_t ms);
/**
* @brief Lock the operating system to protect a sequence of code
*
* @note Calling this will lock out all other threads from executing even at interrupt level
* within the GFX system. On hardware this may be implemented as a disabling of interrupts,
* however in an operating system which hides real interrupt level code it may simply use a
* mutex lock.
* @note The thread MUST NOT block whilst the system is locked. It must execute in this state for
* as short a period as possible as this can seriously affect interrupt latency on some
* platforms.
* @note While locked only interrupt level (iclass) GFX routines may be called.
*
* @api
*/
void gfxSystemLock(void);
/**
* @brief Unlock the operating system previous locked by gfxSystemLock()
*
* @api
*/
void gfxSystemUnlock(void);
/**
* @brief Initialise a mutex to protect a region of code from other threads.
*
* @param[in] pmutex A pointer to the mutex
*
* @note Whilst a counting semaphore with a limit of 1 can be used for similiar purposes
* on many operating systems using a seperate mutex structure is more efficient.
*
* @api
*/
void gfxMutexInit(gfxMutex *pmutex);
/**
* @brief Destroy a Mutex.
*
* @param[in] pmutex A pointer to the mutex
*
* @api
*/
void gfxMutexDestroy(gfxMutex *pmutex);
/**
* @brief Enter the critical code region protected by the mutex.
* @details Blocks until there is no other thread in the critical region.
*
* @param[in] pmutex A pointer to the mutex
*
* @api
*/
void gfxMutexEnter(gfxMutex *pmutex);
/**
* @brief Exit the critical code region protected by the mutex.
* @details May cause another thread waiting on the mutex to now be placed into the run queue.
*
* @param[in] pmutex A pointer to the mutex
*
* @api
*/
void gfxMutexExit(gfxMutex *pmutex);
/**
* @brief Initialise a Counted Semaphore
*
* @param[in] psem A pointer to the semaphore
* @param[in] val The initial value of the semaphore
* @param[in] limit The maxmimum value of the semaphore
*
* @note Operations defined for counted semaphores:
* Signal: The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
* Wait: The semaphore counter is decreased and if the result becomes negative the thread is queued
* in the semaphore and suspended.
*
* @api
*/
void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit);
/**
* @brief Destroy a Counted Semaphore
*
* @param[in] psem A pointer to the semaphore
*
* @note Any threads waiting on the semaphore will be released
*
* @api
*/
void gfxSemDestroy(gfxSem *psem);
/**
* @brief Wait on a semaphore
* @details The semaphore counter is decreased and if the result becomes negative the thread waits for it to become
* non-negative again
* @return FALSE if the wait timeout occurred otherwise TRUE
*
* @param[in] psem A pointer to the semaphore
* @param[in] ms The maximum time to wait for the semaphore
*
* @api
*/
bool_t gfxSemWait(gfxSem *psem, delaytime_t ms);
/**
* @brief Test if a wait on a semaphore can be satisfied immediately
* @details Equivalent to @p gfxSemWait(psem, TIME_IMMEDIATE) except it can be called at interrupt level
* @return FALSE if the wait would occur occurred otherwise TRUE
*
* @param[in] psem A pointer to the semaphore
*
* @iclass
* @api
*/
bool_t gfxSemWaitI(gfxSem *psem);
/**
* @brief Signal a semaphore
* @details The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
*
* @param[in] psem A pointer to the semaphore
*
* @api
*/
void gfxSemSignal(gfxSem *psem);
/**
* @brief Signal a semaphore
* @details The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
*
* @param[in] psem A pointer to the semaphore
*
* @iclass
* @api
*/
void gfxSemSignalI(gfxSem *psem);
/**
* @brief Get the current semaphore count
* @return The current semaphore count
*
* @param[in] psem A pointer to the semaphore
*
* @api
*/
semcount_t gfxSemCounter(gfxSem *psem);
/**
* @brief Get the current semaphore count
* @return The current semaphore count
*
* @param[in] psem A pointer to the semaphore
*
* @iclass
* @api
*/
semcount_t gfxSemCounterI(gfxSem *psem);
/**
* @brief Start a new thread.
* @return Returns a thread handle if the thread was started, NULL on an error
*
* @param[in] stackarea A pointer to the area for the new threads stack or NULL to dynamically allocate it
* @param[in] stacksz The size of the thread stack. 0 means the default operating system size although this
* is only valid when stackarea is dynamically allocated.
* @param[in] prio The priority of the new thread
* @param[in] fn The function the new thread will run
* @param[in] param A parameter to pass the thread function.
*
* @api
*/
gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param);
/**
* @brief Wait for a thread to finish.
* @return Returns the thread exit code.
*
* @param[in] thread The Thread Handle
*
* @note This will also close the thread handle as it is no longer useful
* once the thread has ended.
* @api
*/
threadreturn_t gfxThreadWait(gfxThreadHandle thread);
/**
* @brief Get the current thread handle.
* @return A thread handle
*
* @api
*/
gfxThreadHandle gfxThreadMe(void);
/**
* @brief Close the thread handle.
*
* @param[in] thread The Thread Handle
*
* @note This does not affect the thread, it just closes our handle to the thread.
*
* @api
*/
void gfxThreadClose(gfxThreadHandle thread);
#ifdef __cplusplus
}
#endif
/**
* All the above was just for the doxygen documentation. All the implementation of the above
* (without any of the documentation overheads) is in the files below.
*/
#elif GFX_USE_OS_RAWRTOS
#include "gos_rawrtos.h"
#elif GFX_USE_OS_CHIBIOS
#include "gos_chibios.h"
#elif GFX_USE_OS_FREERTOS
#include "gos_freertos.h"
#elif GFX_USE_OS_WIN32
#include "gos_win32.h"
#elif GFX_USE_OS_LINUX
#include "gos_linux.h"
#elif GFX_USE_OS_OSX
#include "gos_osx.h"
#elif GFX_USE_OS_RAW32
#include "gos_raw32.h"
#elif GFX_USE_OS_ECOS
#include "gos_ecos.h"
#elif GFX_USE_OS_ARDUINO
#include "gos_arduino.h"
#elif GFX_USE_OS_CMSIS
#include "gos_cmsis.h"
#elif GFX_USE_OS_KEIL
#include "gos_keil.h"
#elif GFX_USE_OS_NIOS
#include "gos_nios.h"
#elif GFX_USE_OS_QT
#include "gos_qt.h"
#else
#error "Your operating system is not supported yet"
#endif
#endif /* _GOS_H */
/** @} */