Difference between revisions of "GOS"

From uGFX Wiki
Jump to: navigation, search
(Initialization)
(Existing ports)
Line 410: Line 410:
 
* CMSIS RTOS
 
* CMSIS RTOS
 
* eCos
 
* eCos
 +
* Zephyr
 
* FreeRTOS
 
* FreeRTOS
 
* Keil RTX
 
* Keil RTX

Revision as of 17:52, 20 September 2017

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. If GFX_SHOW_COMPILER is set to TRUE a compiler warning will be generated showing the name of the compiler that was manually set or automatically detected.

Available values for GFX_COMPILER are:

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.

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) or when GFX_OS_NO_INIT has been set to TRUE to prevent gfxInit() from initializing the underlying systems automatically.

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. The functions have to have no parameters and void as return type.

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 gfxAlloc() and gfxFree() 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. Have a look at Emulating Malloc in case of you have to use external libraries that use malloc() and free().

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
  • Zephyr
  • FreeRTOS
  • Keil RTX
  • NIOS-II
  • rawrtos
  • Arduino
  • Teensy
  • SylixOS
  • Linux
  • Mac OS X
  • Windows
  • And most likely more because we forgot to update this list.

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

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);

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/