Difference between revisions of "GOS"
(→Emulating Malloc) |
(→Emulating Malloc) |
||
Line 325: | Line 325: | ||
To avoid this problem, <code>GFX_EMULATE_MALLOC</code> can be set to <code>TRUE</code> in the [[Configuration|configuration file]]. | To avoid this problem, <code>GFX_EMULATE_MALLOC</code> can be set to <code>TRUE</code> in the [[Configuration|configuration file]]. | ||
When <code>GFX_EMULATE_MALLOC</code> is enabled, the <code>malloc()</code> and <code>free()</code> functions will be defined as wrappers to the corresponding <code>malloc()</code> and <code>free()</code> functions: | When <code>GFX_EMULATE_MALLOC</code> is enabled, the <code>malloc()</code> and <code>free()</code> functions will be defined as wrappers to the corresponding <code>malloc()</code> and <code>free()</code> functions: | ||
− | < | + | <source lang="c"> |
#if GFX_EMULATE_MALLOC | #if GFX_EMULATE_MALLOC | ||
#include <stdlib.h> | #include <stdlib.h> | ||
Line 337: | Line 337: | ||
} | } | ||
#endif | #endif | ||
− | </ | + | </source> |
== Threading == | == Threading == |
Revision as of 06:35, 5 February 2016
GOS is the module which builds the abstraction layer between µGFX and the underlying system. The underlying system can be an RTOS such as ChibiOS or FreeRTOS, or also just a bare metal system. The GOS module allows to write completely platform independent application code.
API reference
The API reference of the GOS module can be found here.
Configuration
There are several configuration options for the GOS module inside the configuration file. Note that none of these configuration settings need to be specified in 99% of the cases as everything comes with a reasonable default implementation/setting.
Compiler
The GFX_COMPILER
configuration setting allows enabling compiler specific optimization code. Please note that this setting usually doesn't have to be set manually by the user as the used compiler will be auto-detected.
Available settings:
Option | Description |
---|---|
GFX_COMPILER_UNKNOWN | Unknown compiler. This is the default and should always work. |
GFX_COMPILER_ACC | ACC Compiler |
GFX_COMPILER_ALTIUM | Altium MicroBlaze C |
GFX_COMPILER_ALTIUMHW | Altium C-to-Hardware |
GFX_COMPILER_AMSTERDAM | Amsterdam Compiler Kit |
GFX_COMPILER_ARMCC | ARM Compiler |
GFX_COMPILER_AZTEC | Aztec C |
GFX_COMPILER_BORLAND | Borland C++ |
GFX_COMPILER_CC65 | CC65 |
GFX_COMPILER_CLANG | CLang (LLVM) compiler |
GFX_COMPILER_COMEAU | Comeau C++ |
GFX_COMPILER_COMPAQ | Compaq C |
GFX_COMPILER_COMPCERT | Compcert Compiler |
GFX_COMPILER_CONVEX | Convex C |
GFX_COMPILER_CRAY | Cray C/C++ |
GFX_COMPILER_CYGWIN | Cygwin (x86) unix emulator compiler for windows |
GFX_COMPILER_DAIB | Diab C/C++ |
GFX_COMPILER_DEC | The older DEC C Compiler |
GFX_COMPILER_DICE | DICE C Compiler |
GFX_COMPILER_DIGNUS | Dignus Systems C++ Compiler |
GFX_COMPILER_DJGPP | DJGPP |
GFX_COMPILER_DMARS | Digital Mars |
GFX_COMPILER_EDG | EDG C++ |
GFX_COMPILER_EKOPATH | EKOPath Compiler |
GFX_COMPILER_FUJITSU | Fujitsu C++ Compiler |
GFX_COMPILER_GCC | Standard GCC/G++ (Also use this when using arm-none-eabi-gcc )
|
GFX_COMPILER_GREENHILL | Green Hill C/C++ |
GFX_COMPILER_HIGHC | Metaware High C/C++ |
GFX_COMPILER_HP | HP C/aC++ |
GFX_COMPILER_IAR | IAR C/C++ |
GFX_COMPILER_IBMXL | IBM XL C/C++ Compiler |
GFX_COMPILER_IMAGECRAFT | ImageCraft C Compiler |
GFX_COMPILER_INTEL | Intel ICC/ICPC Compiler |
GFX_COMPILER_KAI | Kai C++ |
GFX_COMPILER_KEIL | Keil (use this when working with uVision IDE) |
GFX_COMPILER_LCC | LCC |
GFX_COMPILER_METROWORKS | Metroworks |
GFX_COMPILER_MICROTEC | Microtec C/C++ |
GFX_COMPILER_MICROWAY | Microway NDP C |
GFX_COMPILER_MINGW32 | MingW32 (x86) compiler for windows |
GFX_COMPILER_MINGW64 | MingW64 (x64) compiler for windows |
GFX_COMPILER_MIPSPRO | MIPS Pro |
GFX_COMPILER_MIRACLE | Miracle C |
GFX_COMPILER_MPW | MPW C++ |
GFX_COMPILER_NORCROFT | Norcroft ARM |
GFX_COMPILER_NWCC | NWCC |
GFX_COMPILER_OPEN64 | Open64 |
GFX_COMPILER_OSS | Oracle Solaris Studio |
GFX_COMPILER_PACIFIC | Pacific C |
GFX_COMPILER_PALM | Palm C/C++ |
GFX_COMPILER_PELLES | Pelles C |
GFX_COMPILER_PGCC | Portland PGCC/PGCPP |
GFX_COMPILER_RENESAS | Renesas C/C++ |
GFX_COMPILER_SASC | SAS/C |
GFX_COMPILER_SCO | SCO OpenServer |
GFX_COMPILER_SDCC | Small Device C Compiler |
GFX_COMPILER_SN | SN Compiler |
GFX_COMPILER_STRATUS | Stratus VOS C |
GFX_COMPILER_SYMANTEC | Symantec C++ |
GFX_COMPILER_TENDRA | TenDRA C/C++ |
GFX_COMPILER_THINK | Think C |
GFX_COMPILER_TI | Texas Instruments C/C++ |
GFX_COMPILER_TINYC | Tiny C |
GFX_COMPILER_TURBOC | Borland Turbo C |
GFX_COMPILER_ULTIMATE | Ultimate C/C++ |
GFX_COMPILER_USL | USL C |
GFX_COMPILER_VBCC | VBCC |
GFX_COMPILER_VS | Microsoft Visual Studio |
GFX_COMPILER_WATCOM | Watcom |
GFX_COMPILER_ZTC | Zortech C++ |
CPU
The GFX_CPU
configuration setting allows enabling CPU specific optimization code.
Available settings:
Option | Description |
---|---|
GFX_CPU_UNKNOWN | Unknown CPU. This is the default setting. |
GFX_CPU_CORTEX_M0 | Cortex M0 |
GFX_CPU_CORTEX_M1 | Cortex M1 |
GFX_CPU_CORTEX_M2 | Cortex M2 |
GFX_CPU_CORTEX_M3 | Cortex M3 |
GFX_CPU_CORTEX_M4 | Cortex M4 |
GFX_CPU_CORTEX_M4_FP | Cortex M4 with hardware floating point unit |
GFX_CPU_CORTEX_M7 | Cortex M7 |
GFX_CPU_CORTEX_M7_FP | Cortex M7 with hardware floating point unit |
GFX_CPU_X86 | Intel x86 |
GFX_CPU_X64 | Intel x64 |
GFX_CPU_IA64 | Intel Itanium |
GFX_CPU_POWERPC32 | PowerPC 32-Bit |
GFX_CPU_POWERPC64 | PowerPC 64-Bit |
GFX_CPU_SPARC | Sparc |
Endian
The GFX_CPU_ENDIAN
setting enables optimisations that are CPU-endian specific. It does not need to be specified as reasonable defaults and various auto-detection will happen as required.
Option | Description |
---|---|
GFX_CPU_ENDIAN_UNKNOWN | Unknown endianness. This is the default. |
GFX_CPU_ENDIAN_LITTLE | Little endian |
GFX_CPU_ENDIAN_BIG | Big endian |
GFX_CPU_ENDIAN_WBDWL | Words are big endian, DWords are little endian. For example: Honeywell 316 |
GFX_CPU_ENDIAN_WLDWB | Words are little endian, DWords are big endian. For example: PDP-11 |
Inlining
Certain functions of the µGFX library are inlined for performance reasons. Setting GFX_NO_INLINE
to TRUE
will disable the inlining of all functions.
This setting should only be touched in case of there are any compile time errors for unsupported compilers. Disabling inlining will have huge impacts on performance.
Initialization
For code portability reasons the underlying system will be automatically initialized when gosInit()
is called unless GFX_OS_NO_INIT
is set to TRUE
in the configuration file.
Initialization
For code portability reasons the underlying system will be automatically initialized when gosInit()
is called unless GFX_OS_NO_INIT
is set to TRUE
in the configuration file.
Warnings
By default the GOS module will print out a warning during compile time to notify the user that he needs to make sure that his OS has been initialized before calling gfxInit()
. Setting GFX_OS_INIT_NO_WARNING
to TRUE
will suppress this warning.
Note that this warning is only printed out when the GOS module cannot initialize the operating system automatically. This is the case when eg. the RAW32 port is used (see BareMetal).
Extra functions
It is possible to submit code that is executed when µGFX is being initialized and deinitialized through GFX_OS_EXTRA_INIT_FUNCTION
and GFX_OS_EXTRA_DEINIT_FUNCTION
.
Emulating Malloc
An uGFX application should always use gfxAlloc()
and gfxFree()
instead of the corresponding C library functions to ensure portability. However, sometimes external libraries are used within an uGFX applications. External libraries might call malloc()
and free()
which can lead to both compile-time and run-time errors when mixing with the corresponding uGFX functions due to multiple reasons:
- uGFX allows to compile programs without a clib
- On certain platforms uGFX will implements its own heap manager that cannot be used together with the clib one
To avoid this problem, GFX_EMULATE_MALLOC
can be set to TRUE
in the configuration file.
When GFX_EMULATE_MALLOC
is enabled, the malloc()
and free()
functions will be defined as wrappers to the corresponding malloc()
and free()
functions:
#if GFX_EMULATE_MALLOC #include <stdlib.h> void* malloc(size_t size) { return gfxAlloc(size); } void free(void *ptr) { gfxFree(ptr); } #endif
Threading
It is highly recommended to use the uGFX API to create and manage threads. This way the application is fully portable. In most cases these are just 1:1 wrappers to the calls from the underlying operating systems so there is no additional overhead.
Please take a look at the API reference of the GOS module to learn about all the available functions.
The following demos which can be found in the uGFX repository show how to properly use the threading API:
- /demos/modules/gos/threads
- /demos/modules/gos/threads_advanced
Thread priority
The number of different thread priorities is not clearly defined as every underlying operating system implements this feature differently. However, the GOS module ensures that the following three priority levels are defined:
LOW_PRIORITY NORMAL_PRIORITY HIGH_PRIORITY
As thread priorities are usually implemented in form of integer variables, you can increment and decrement these defines in order to further split the thread priorities. For example:
/* Normal priority thread */ NORMAL_PRIORITY /* High priority thread */ HIGH_PRIORITY /* A thread that has a slightly higher priority than the normal priority but with a still smaller priority than the high priroty thread */ NORMAL_PRIORITY + 1
Terminating a thread
The uGFX API does not provide any function to terminate a running thread. This is due to the fact that only very few operating systems provide the feature to terminate a running thread from within another thread. However, it's still possible to tell a thread to terminate itself. This can for example be accomplished by implementing a 'falling over the edge' algorithm where a variable is passed to the custom parameter of the thread function. The thread will frequently check this variable which tells whether the thread should return or not. As the variable is only passed as a pointer it can be modified out of another thread.
The /demos/modules/gos/threads_advanced demo shows how to implement such an algorithm. Basically it looks like this:
threadreturn_t threadFunction(void* param) { /* Cast the paramter into a bool pointer so we can use it */ bool_t* doExit = (bool_t*)param; /* Execute this until we shall be terminated */ while (*doExit == FALSE) { /* Do the actual work... */ } /* Don't return anything (or return something) */ return (threadreturn_t)0; } int main(void) { bool_t exitThread = FALSE; /* Start the thread and pass the variable as a parameter to tell the thread to terminate later */ gfxThreadCreate(NULL, 128, NORMAL_PRIORITY, threadFunction, (void*)&exitThread); /* Tell the thread to return */ exitThread = TRUE; }
Memory management
It is highly recommended to use the uGFX API for memory management. This way the application is fully portable. In most cases these calls are just 1:1 wrappers to the calls from the underlying operating system so there is no additional overhead.
Please take a look at the API reference of the GOS module to learn about all the available functions.
Existing ports
The following ports already exist and are part of the official repository:
- BareMetal (no OS at all)
- ChibiOS/RT
- CMSIS RTOS
- eCos
- FreeRTOS
- Keil RTX
- NIOS-II
- rawrtos
- Arduino
- Teensy
- Linux
- Mac OS X
- Windows
Please have a look at the Using µGFX on... section on the Main Page to find links to the corresponding articles that give information about each of these ports.
BareMetal
It's possible to run µGFX directly on a bare-metal system without any underlying OS using the RAW32 port.
Porting
Porting uGFX to a new underlying system is fairly easy. Only a couple of functions and data types have to be implemented and declared.
Functions
ToDo
void gfxHalt(const char *msg); void gfxExit(void); void* gfxAlloc(size_t sz); void* gfxRealloc(void *p, size_t oldsz, size_t newsz); void gfxFree(void *ptr); void gfxYield(void); void gfxSleepMilliseconds(delaytime_t ms); void gfxSleepMicroseconds(delaytime_t ms); systemticks_t gfxSystemTicks(void); systemticks_t gfxMillisecondsToTicks(delaytime_t ms); void gfxSystemLock(void); void gfxSystemUnlock(void); void gfxMutexInit(gfxMutex *pmutex); void gfxMutexDestroy(gfxMutex *pmutex); void gfxMutexEnter(gfxMutex *pmutex); void gfxMutexExit(gfxMutex *pmutex); void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit); void gfxSemDestroy(gfxSem *psem); bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); void gfxSemSignal(gfxSem *psem); void gfxSemSignalI(gfxSem *psem); semcount_t gfxSemCounter(gfxSem *pSem); semcount_t gfxSemCounterI(gfxSem *pSem); gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); threadreturn_t gfxThreadWait(gfxThreadHandle thread); gfxThreadHandle gfxThreadMe(void) void gfxThreadClose(gfxThreadHandle thread);
Data types
ToDo
Examples
When creating a new port, taking a look at existing ones can help a lot. The existing ports can be found under /src/gos/