From 8efdd2c51419ad7a38a6594ecabe729c6ab824e4 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Mon, 29 Sep 2014 08:07:43 +0200 Subject: /src/gos/gfx_* -> /src/gos/gos_* --- src/gos/gfx_chibios.c | 168 ----------- src/gos/gfx_chibios.h | 118 -------- src/gos/gfx_ecos.c | 115 -------- src/gos/gfx_ecos.h | 106 ------- src/gos/gfx_freertos.c | 170 ------------ src/gos/gfx_freertos.h | 122 -------- src/gos/gfx_linux.c | 248 ----------------- src/gos/gfx_linux.h | 107 ------- src/gos/gfx_osx.c | 187 ------------- src/gos/gfx_osx.h | 88 ------ src/gos/gfx_raw32.c | 739 ------------------------------------------------- src/gos/gfx_raw32.h | 126 --------- src/gos/gfx_rawrtos.c | 83 ------ src/gos/gfx_rawrtos.h | 77 ------ src/gos/gfx_win32.c | 126 --------- src/gos/gfx_win32.h | 107 ------- src/gos/gos_chibios.c | 168 +++++++++++ src/gos/gos_chibios.h | 118 ++++++++ src/gos/gos_ecos.c | 115 ++++++++ src/gos/gos_ecos.h | 106 +++++++ src/gos/gos_freertos.c | 170 ++++++++++++ src/gos/gos_freertos.h | 122 ++++++++ src/gos/gos_linux.c | 248 +++++++++++++++++ src/gos/gos_linux.h | 107 +++++++ src/gos/gos_osx.c | 187 +++++++++++++ src/gos/gos_osx.h | 88 ++++++ src/gos/gos_raw32.c | 739 +++++++++++++++++++++++++++++++++++++++++++++++++ src/gos/gos_raw32.h | 126 +++++++++ src/gos/gos_rawrtos.c | 83 ++++++ src/gos/gos_rawrtos.h | 77 ++++++ src/gos/gos_win32.c | 126 +++++++++ src/gos/gos_win32.h | 107 +++++++ src/gos/sys_defs.h | 16 +- src/gos/sys_make.mk | 16 +- 34 files changed, 2703 insertions(+), 2703 deletions(-) delete mode 100644 src/gos/gfx_chibios.c delete mode 100644 src/gos/gfx_chibios.h delete mode 100644 src/gos/gfx_ecos.c delete mode 100644 src/gos/gfx_ecos.h delete mode 100644 src/gos/gfx_freertos.c delete mode 100644 src/gos/gfx_freertos.h delete mode 100644 src/gos/gfx_linux.c delete mode 100644 src/gos/gfx_linux.h delete mode 100644 src/gos/gfx_osx.c delete mode 100644 src/gos/gfx_osx.h delete mode 100644 src/gos/gfx_raw32.c delete mode 100644 src/gos/gfx_raw32.h delete mode 100644 src/gos/gfx_rawrtos.c delete mode 100644 src/gos/gfx_rawrtos.h delete mode 100644 src/gos/gfx_win32.c delete mode 100644 src/gos/gfx_win32.h create mode 100644 src/gos/gos_chibios.c create mode 100644 src/gos/gos_chibios.h create mode 100644 src/gos/gos_ecos.c create mode 100644 src/gos/gos_ecos.h create mode 100644 src/gos/gos_freertos.c create mode 100644 src/gos/gos_freertos.h create mode 100644 src/gos/gos_linux.c create mode 100644 src/gos/gos_linux.h create mode 100644 src/gos/gos_osx.c create mode 100644 src/gos/gos_osx.h create mode 100644 src/gos/gos_raw32.c create mode 100644 src/gos/gos_raw32.h create mode 100644 src/gos/gos_rawrtos.c create mode 100644 src/gos/gos_rawrtos.h create mode 100644 src/gos/gos_win32.c create mode 100644 src/gos/gos_win32.h (limited to 'src') diff --git a/src/gos/gfx_chibios.c b/src/gos/gfx_chibios.c deleted file mode 100644 index 9d1a86da..00000000 --- a/src/gos/gfx_chibios.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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 - */ - -#include "gfx.h" - -#if GFX_USE_OS_CHIBIOS - -#include - -#if CH_KERNEL_MAJOR == 2 - - #if !CH_USE_MUTEXES - #error "GOS: CH_USE_MUTEXES must be defined in chconf.h" - #endif - #if !CH_USE_SEMAPHORES - #error "GOS: CH_USE_SEMAPHORES must be defined in chconf.h" - #endif - -#elif CH_KERNEL_MAJOR == 3 - - #if !CH_CFG_USE_MUTEXES - #error "GOS: CH_USE_MUTEXES must be defined in chconf.h" - #endif - #if !CH_CFG_USE_SEMAPHORES - #error "GOS: CH_USE_SEMAPHORES must be defined in chconf.h" - #endif - -#endif - -void _gosInit(void) -{ - #if !GFX_NO_OS_INIT - /* Don't Initialize if the user already has */ - #if CH_KERNEL_MAJOR == 2 - if (!chThdSelf()) { - halInit(); - chSysInit(); - } - #elif CH_KERNEL_MAJOR == 3 - if (!chThdGetSelfX()) { - halInit(); - chSysInit(); - } - #endif - #else - #warning "GOS: Operating System initialization has been turned off. Make sure you call halInit() and chSysInit() before gfxInit() in your application!" - #endif -} - -void _gosDeinit(void) -{ - /* ToDo */ -} - -void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz) -{ - void *np; - - if (newsz <= oldsz) - return ptr; - - np = gfxAlloc(newsz); - if (!np) - return 0; - - if (oldsz) - memcpy(np, ptr, oldsz); - - return np; -} - -void gfxSleepMilliseconds(delaytime_t ms) -{ - switch(ms) { - case TIME_IMMEDIATE: chThdYield(); return; - case TIME_INFINITE: chThdSleep(TIME_INFINITE); return; - default: chThdSleepMilliseconds(ms); return; - } -} - -void gfxSleepMicroseconds(delaytime_t ms) -{ - switch(ms) { - case TIME_IMMEDIATE: return; - case TIME_INFINITE: chThdSleep(TIME_INFINITE); return; - default: chThdSleepMicroseconds(ms); return; - } -} - -void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit) -{ - if (val > limit) - val = limit; - - psem->limit = limit; - - #if CH_KERNEL_MAJOR == 2 - chSemInit(&psem->sem, val); - #elif CH_KERNEL_MAJOR == 3 - chSemObjectInit(&psem->sem, val); - #endif -} - -void gfxSemDestroy(gfxSem *psem) -{ - chSemReset(&psem->sem, 1); -} - -bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) -{ - #if CH_KERNEL_MAJOR == 2 - switch(ms) { - case TIME_IMMEDIATE: return chSemWaitTimeout(&psem->sem, TIME_IMMEDIATE) != RDY_TIMEOUT; - case TIME_INFINITE: chSemWait(&psem->sem); return TRUE; - default: return chSemWaitTimeout(&psem->sem, MS2ST(ms)) != RDY_TIMEOUT; - } - #elif CH_KERNEL_MAJOR == 3 - switch(ms) { - case TIME_IMMEDIATE: return chSemWaitTimeout(&psem->sem, TIME_IMMEDIATE) != MSG_TIMEOUT; - case TIME_INFINITE: chSemWait(&psem->sem); return TRUE; - default: return chSemWaitTimeout(&psem->sem, MS2ST(ms)) != MSG_TIMEOUT; - } - #endif -} - -bool_t gfxSemWaitI(gfxSem *psem) -{ - if (chSemGetCounterI(&psem->sem) <= 0) - return FALSE; - chSemFastWaitI(&psem->sem); - return TRUE; -} - -void gfxSemSignal(gfxSem *psem) -{ - chSysLock(); - - if (gfxSemCounterI(psem) < psem->limit) - chSemSignalI(&psem->sem); - - chSchRescheduleS(); - chSysUnlock(); -} - -void gfxSemSignalI(gfxSem *psem) -{ - if (gfxSemCounterI(psem) < psem->limit) - chSemSignalI(&psem->sem); -} - -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) -{ - if (!stackarea) { - if (!stacksz) stacksz = 256; - return chThdCreateFromHeap(0, stacksz, prio, fn, param); - } - - if (!stacksz) - return 0; - - return chThdCreateStatic(stackarea, stacksz, prio, fn, param); -} - -#endif /* GFX_USE_OS_CHIBIOS */ diff --git a/src/gos/gfx_chibios.h b/src/gos/gfx_chibios.h deleted file mode 100644 index a07c72ab..00000000 --- a/src/gos/gfx_chibios.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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 - */ - -#ifndef _GOS_CHIBIOS_H -#define _GOS_CHIBIOS_H - -#if GFX_USE_OS_CHIBIOS - -#include "ch.h" -#include "hal.h" - -/*===========================================================================*/ -/* Type definitions */ -/*===========================================================================*/ - -/** - * bool_t, - * int8_t, uint8_t, - * int16_t, uint16_t, - * int32_t, uint32_t, - * size_t - * TRUE, FALSE - * TIME_IMMEDIATE, TIME_INFINITE - * are already defined by ChibiOS - */ - -typedef systime_t delaytime_t; -typedef systime_t systemticks_t; -typedef cnt_t semcount_t; -typedef msg_t threadreturn_t; -typedef tprio_t threadpriority_t; - -#define MAX_SEMAPHORE_COUNT ((semcount_t)(((unsigned long)((semcount_t)(-1))) >> 1)) -#define LOW_PRIORITY LOWPRIO -#define NORMAL_PRIORITY NORMALPRIO -#define HIGH_PRIORITY HIGHPRIO - -#define DECLARE_THREAD_STACK(name, sz) WORKING_AREA(name, sz) -#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) - -#if CH_KERNEL_MAJOR == 2 - typedef struct { - Semaphore sem; - semcount_t limit; - } gfxSem; - - typedef Mutex gfxMutex; - typedef Thread* gfxThreadHandle; -#elif CH_KERNEL_MAJOR == 3 - #undef DECLARE_THREAD_STACK - #define DECLARE_THREAD_STACK(a, b) THD_WORKING_AREA(a, b) - - typedef struct { - semaphore_t sem; - semcount_t limit; - } gfxSem; - - typedef mutex_t gfxMutex; - typedef thread_t* gfxThreadHandle; -#endif - - -/*===========================================================================*/ -/* Function declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -// First the kernel version specific ones -#if CH_KERNEL_MAJOR == 2 - #define gfxSystemTicks() chTimeNow() - #define gfxMutexInit(pmutex) chMtxInit(pmutex) - #define gfxMutexExit(pmutex) chMtxUnlock() - #define gfxExit() chSysHalt() -#elif CH_KERNEL_MAJOR == 3 - #define gfxSystemTicks() chVTGetSystemTimeX() - #define gfxMutexInit(pmutex) chMtxObjectInit(pmutex) - #define gfxMutexExit(pmutex) chMtxUnlock(pmutex) - #define gfxExit() osalSysHalt("gfx_exit") -#endif - -#define gfxHalt(msg) { chDbgPanic(msg); chSysHalt(); } -#define gfxAlloc(sz) chHeapAlloc(0, sz) -#define gfxFree(ptr) chHeapFree(ptr) -#define gfxYield() chThdYield() -#define gfxMillisecondsToTicks(ms) MS2ST(ms) -#define gfxSystemLock() chSysLock() -#define gfxSystemUnlock() chSysUnlock() -#define gfxMutexDestroy(pmutex) (void)pmutex -#define gfxMutexEnter(pmutex) chMtxLock(pmutex) -void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz); -void gfxSleepMilliseconds(delaytime_t ms); -void gfxSleepMicroseconds(delaytime_t ms); -void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit); -void gfxSemDestroy(gfxSem *psem); -bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); -bool_t gfxSemWaitI(gfxSem *psem); -void gfxSemSignal(gfxSem *psem); -void gfxSemSignalI(gfxSem *psem); -#define gfxSemCounterI(psem) ((psem)->sem.s_cnt) -#define gfxSemCounter(psem) ((psem)->sem.s_cnt) -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); -#define gfxThreadWait(thread) chThdWait(thread) -#define gfxThreadMe() chThdSelf() -#define gfxThreadClose(thread) (void)thread - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_OS_CHIBIOS */ -#endif /* _GOS_CHIBIOS_H */ diff --git a/src/gos/gfx_ecos.c b/src/gos/gfx_ecos.c deleted file mode 100644 index 16ce821b..00000000 --- a/src/gos/gfx_ecos.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 - */ - -#include "gfx.h" - -#if GFX_USE_OS_ECOS - -void _gosInit(void) -{ - #if !GFX_NO_OS_INIT - #error "GOS: Operating System initialization for eCos is not yet implemented in uGFX. Please set GFX_NO_OS_INIT to TRUE in your gfxconf.h" - #else - #warning "GOS: Operating System initialization has been turned off. Make sure you call cyg_scheduler_start() before gfxInit() in your application!" - #endif -} - -void _gosDeinit(void) -{ - /* ToDo */ -} - -void gfxSleepMilliseconds(delaytime_t ms) -{ - switch(ms) { - case TIME_IMMEDIATE: cyg_thread_yield(); return; - case TIME_INFINITE: cyg_thread_suspend(cyg_thread_self()); return; - default: cyg_thread_delay(gfxMillisecondsToTicks(ms)); return; - } -} - -void gfxSleepMicroseconds(delaytime_t ms) -{ - switch(ms) { - case TIME_IMMEDIATE: return; - case TIME_INFINITE: cyg_thread_suspend(cyg_thread_self()); return; - default: cyg_thread_delay(gfxMillisecondsToTicks(ms/1000)); return; - } -} - -void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit) -{ - if (val > limit) - val = limit; - - psem->limit = limit; - cyg_semaphore_init(&psem->sem, val); -} - -void gfxSemDestroy(gfxSem *psem) -{ - cyg_semaphore_destroy(&psem->sem); -} - -bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) -{ - switch(ms) { - case TIME_IMMEDIATE: return cyg_semaphore_trywait(&psem->sem); - case TIME_INFINITE: return cyg_semaphore_wait(&psem->sem); - default: return cyg_semaphore_timed_wait(&psem->sem, gfxMillisecondsToTicks(ms)+cyg_current_time()); - } -} - -bool_t gfxSemWaitI(gfxSem *psem) -{ - return cyg_semaphore_trywait(&psem->sem); -} - -void gfxSemSignal(gfxSem *psem) -{ - if (psem->limit == MAX_SEMAPHORE_COUNT) - cyg_semaphore_post(&psem->sem); - else { - cyg_scheduler_lock(); - if (gfxSemCounterI(psem) < psem->limit) - cyg_semaphore_post(&psem->sem); - cyg_scheduler_unlock(); - } -} - -void gfxSemSignalI(gfxSem *psem) -{ - if (psem->limit == MAX_SEMAPHORE_COUNT || gfxSemCounterI(psem) < psem->limit) - cyg_semaphore_post(&psem->sem); -} - -semcount_t gfxSemCounterI(gfxSem *psem) { - semcount_t cnt; - - cyg_semaphore_peek(&psem->sem, &cnt); - return cnt; -} - -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) -{ - gfxThreadHandle th; - - if (!stackarea) { - if (!stacksz) stacksz = CYGNUM_HAL_STACK_SIZE_TYPICAL; - if (!(stackarea = gfxAlloc(stacksz+sizeof(cyg_thread)))) - return 0; - } - - if (!stacksz) - return 0; - - cyg_thread_create(prio, fn, param, "uGFX", (((cyg_thread *)stackarea)+1), stacksz, &th, (cyg_thread *)stackarea); - cyg_thread_resume(th); - return th; -} - -#endif /* GFX_USE_OS_ECOS */ diff --git a/src/gos/gfx_ecos.h b/src/gos/gfx_ecos.h deleted file mode 100644 index be9037b6..00000000 --- a/src/gos/gfx_ecos.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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 - */ - -#ifndef _GOS_ECOS_H -#define _GOS_ECOS_H - -#if GFX_USE_OS_ECOS - -#include -#include -#include - -/*===========================================================================*/ -/* Type definitions */ -/*===========================================================================*/ - -typedef cyg_bool_t bool_t; -typedef cyg_int8 int8_t; -typedef cyg_uint8 uint8_t; -typedef cyg_int16 int16_t; -typedef cyg_uint16 uint16_t; -typedef cyg_int32 int32_t; -typedef cyg_uint32 uint32_t; -typedef cyg_uint32 size_t; - -#define TRUE -1 -#define FALSE 0 -#define TIME_IMMEDIATE 0 -#define TIME_INFINITE 0xFFFFFFFF - -typedef cyg_ucount32 delaytime_t; -typedef cyg_tick_count_t systemticks_t; -typedef cyg_count32 semcount_t; -typedef void threadreturn_t; -typedef cyg_addrword_t threadpriority_t; -typedef cyg_handle_t gfxThreadHandle; - -#define MAX_SEMAPHORE_COUNT 0x7FFFFFFF -#define LOW_PRIORITY (CYGNUM_KERNEL_SCHED_PRIORITIES-2) -#define NORMAL_PRIORITY (CYGNUM_KERNEL_SCHED_PRIORITIES/2) -#define HIGH_PRIORITY 0 - -#define DECLARE_THREAD_STACK(name, sz) struct { cyg_thread t; unsigned char stk[sz]; } name[1] -#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(cyg_addrword_t param) - -typedef struct { - cyg_sem_t sem; - semcount_t limit; - } gfxSem; - -typedef cyg_mutex_t gfxMutex; - - -/*===========================================================================*/ -/* Function declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#define gfxSystemTicks() cyg_current_time() -#define gfxExit() exit(0) -#define gfxHalt(msg) exit(-1) -#define gfxYield() cyg_thread_yield() - -#define gfxMillisecondsToTicks(ms) (((ms)*(CYGNUM_HAL_RTC_DENOMINATOR*1000))/(CYGNUM_HAL_RTC_NUMERATOR/1000)) -void gfxSleepMilliseconds(delaytime_t ms); -void gfxSleepMicroseconds(delaytime_t ms); - -#define gfxAlloc(sz) malloc(sz) -#define gfxFree(ptr) free(ptr) -#define gfxRealloc(ptr, oldsz, newsz) realloc(ptr, newsz) - -#define gfxSystemLock() cyg_scheduler_lock() -#define gfxSystemUnlock() cyg_scheduler_unlock() - -#define gfxMutexInit(pmutex) cyg_mutex_init(pmutex) -#define gfxMutexExit(pmutex) cyg_mutex_unlock(pmutex) -#define gfxMutexDestroy(pmutex) cyg_mutex_destroy(pmutex) -#define gfxMutexEnter(pmutex) cyg_mutex_lock(pmutex) - -void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit); -void gfxSemDestroy(gfxSem *psem); -bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); -bool_t gfxSemWaitI(gfxSem *psem); -void gfxSemSignal(gfxSem *psem); -void gfxSemSignalI(gfxSem *psem); -semcount_t gfxSemCounterI(gfxSem *psem); -#define gfxSemCounter(psem) gfxSemCounterI(psem) - -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); -#define gfxThreadWait(thread) NOTIMPLEMENTED_YET -#define gfxThreadMe() cyg_thread_self() -#define gfxThreadClose(thread) (void)thread - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_OS_ECOS */ -#endif /* _GOS_ECOS_H */ diff --git a/src/gos/gfx_freertos.c b/src/gos/gfx_freertos.c deleted file mode 100644 index dbdfd22e..00000000 --- a/src/gos/gfx_freertos.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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 - */ - -#include "gfx.h" -#include - -#if GFX_USE_OS_FREERTOS - -#if INCLUDE_vTaskDelay != 1 - #error "GOS: INCLUDE_vTaskDelay must be defined in FreeRTOSConfig.h" -#endif - -#if configUSE_MUTEXES != 1 - #error "GOS: configUSE_MUTEXES must be defined in FreeRTOSConfig.h" -#endif - -#if configUSE_COUNTING_SEMAPHORES != 1 - #error "GOS: configUSE_COUNTING_SEMAPHORES must be defined in FreeRTOSConfig.h" -#endif - -void _gosInit(void) -{ - #if !GFX_NO_OS_INIT - #error "GOS: Operating System initialization for FreeRTOS is not yet implemented in uGFX. Please set GFX_NO_OS_INIT to TRUE in your gfxconf.h" - #else - #warning "GOS: Operating System initialization has been turned off. Make sure you call vTaskStartScheduler() before gfxInit() in your application!" - #endif -} - -void _gosDeinit(void) -{ -} - -void* gfxRealloc(void *ptr, size_t oldsz, size_t newsz) -{ - void *np; - - if (newsz <= oldsz) - return ptr; - - np = gfxAlloc(newsz); - if (!np) - return 0; - - if (oldsz) { - memcpy(np, ptr, oldsz); - vPortFree(ptr); - } - - return np; -} - -void gfxSleepMilliseconds(delaytime_t ms) -{ - const portTickType ticks = ms / portTICK_PERIOD_MS; - vTaskDelay(ticks); -} - -void gfxSleepMicroseconds(delaytime_t ms) -{ - const portTickType ticks = (ms / 1000) / portTICK_PERIOD_MS; - - // delay milli seconds - vTaskDelay(ticks); - - // microsecond resolution delay is not supported in FreeRTOS - // vUsDelay(ms%1000); -} - -portTickType MS2ST(portTickType ms) -{ - return (ms / portTICK_PERIOD_MS); -} - -void gfxMutexInit(xSemaphoreHandle *s) -{ - *s = xSemaphoreCreateMutex(); - #if GFX_FREERTOS_USE_TRACE - vTraceSetMutexName(*s,"uGFXMutex"); // for FreeRTOS+Trace debug - #endif -} - -void gfxSemInit(gfxSem* psem, semcount_t val, semcount_t limit) -{ - if (val > limit) - val = limit; - - psem->counter = val; - psem->limit = limit; - psem->sem = xSemaphoreCreateCounting(limit,val); - - #if GFX_FREERTOS_USE_TRACE - vTraceSetSemaphoreName(psem->sem, "uGFXSema"); // for FreeRTOS+Trace debug - #endif -} - -void gfxSemDestroy(gfxSem* psem) -{ - vSemaphoreDelete(psem->sem); -} - -bool_t gfxSemWait(gfxSem* psem, delaytime_t ms) -{ - psem->counter--; - - if (xSemaphoreTake(psem->sem, MS2ST(ms)) == pdPASS) - return TRUE; - - psem->counter++; - - return FALSE; -} - -bool_t gfxSemWaitI(gfxSem* psem) -{ - portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; - - psem->counter--; - - if (xSemaphoreTakeFromISR(psem->sem,&xHigherPriorityTaskWoken) == pdTRUE) - return TRUE; - - psem->counter++; - - return FALSE; -} - -void gfxSemSignal(gfxSem* psem) -{ - taskENTER_CRITICAL(); - - if (psem->counter < psem->limit) { - psem->counter++; - xSemaphoreGive(psem->sem); - } - - taskYIELD(); - taskEXIT_CRITICAL(); -} - -void gfxSemSignalI(gfxSem* psem) -{ - portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; - - if (psem->counter < psem->limit) { - psem->counter++; - xSemaphoreGiveFromISR(psem->sem,&xHigherPriorityTaskWoken); - } -} - -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) -{ - xTaskHandle task = NULL; - stacksz = (size_t)stackarea; - - if (stacksz < configMINIMAL_STACK_SIZE) - stacksz = configMINIMAL_STACK_SIZE; - - if (xTaskCreate(fn, "uGFX_TASK", stacksz, param, prio, &task )!= pdPASS) { - for (;;); - } - - return task; -} - -#endif /* GFX_USE_OS_FREERTOS */ diff --git a/src/gos/gfx_freertos.h b/src/gos/gfx_freertos.h deleted file mode 100644 index 57f9b8bd..00000000 --- a/src/gos/gfx_freertos.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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/gfx_freertos.h - * @brief GOS - Operating System Support header file for FreeRTOS. - */ - -#ifndef _GOS_FREERTOS_H -#define _GOS_FREERTOS_H - -#if GFX_USE_OS_FREERTOS - -#include "FreeRTOS.h" -#include "FreeRTOSConfig.h" -#include "semphr.h" -#include "task.h" - -/*===========================================================================*/ -/* Type definitions */ -/*===========================================================================*/ - -/* Additional types are required when FreeRTOS 7.x is used */ -#if !defined(tskKERNEL_VERSION_MAJOR) && !tskKERNEL_VERSION_MAJOR == 8 - typedef signed char int8_t - typedef unsigned char uint8_t - typedef signed int int16_t - typedef unsigned int uint16_t - typedef signed long int int32_t - typedef unsigned long int uint32_t - typedef signed long long int int64_t - typedef unsigned long long int uint64_t -#endif - -/** - * bool_t, - * int8_t, uint8_t, - * int16_t, uint16_t, - * int32_t, uint32_t, - * size_t - * TRUE, FALSE - * are already defined by FreeRTOS - */ -#define TIME_IMMEDIATE 0 -#define TIME_INFINITE ((delaytime_t)-1) -typedef int8_t bool_t; -typedef uint32_t delaytime_t; -typedef portTickType systemticks_t; -typedef int32_t semcount_t; -typedef void threadreturn_t; -typedef portBASE_TYPE threadpriority_t; - -#define MAX_SEMAPHORE_COUNT ((semcount_t)(((unsigned long)((semcount_t)(-1))) >> 1)) -#define LOW_PRIORITY 0 -#define NORMAL_PRIORITY configMAX_PRIORITIES/2 -#define HIGH_PRIORITY configMAX_PRIORITIES-1 - -/* FreeRTOS will allocate the stack when creating the thread, so pass the size instead of a working area */ -#define DECLARE_THREAD_STACK(name, sz) size_t *name = (size_t *)sz -#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) -portTickType MS2ST(portTickType ms); - -typedef struct { - xSemaphoreHandle sem; - semcount_t limit; - semcount_t counter; -} gfxSem; - -typedef xSemaphoreHandle gfxMutex; -typedef xTaskHandle* gfxThreadHandle; - -/*===========================================================================*/ -/* Function declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#define gfxHalt(msg) {} -#define gfxExit() {} -#define gfxAlloc(sz) pvPortMalloc(sz) -#define gfxFree(ptr) vPortFree(ptr) -#define gfxYield() taskYIELD() -#define gfxSystemTicks() xTaskGetTickCount() -#define gfxMillisecondsToTicks(ms) MS2ST(ms) -#define gfxSystemLock() {} -#define gfxSystemUnlock() {} - -void gfxMutexInit(xSemaphoreHandle* s); -#define gfxMutexDestroy(pmutex) vSemaphoreDelete(*pmutex) -#define gfxMutexEnter(pmutex) xSemaphoreTake(*pmutex,portMAX_DELAY) -#define gfxMutexExit(pmutex) xSemaphoreGive(*pmutex) - -void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz); -void gfxSleepMilliseconds(delaytime_t ms); -void gfxSleepMicroseconds(delaytime_t ms); - -void gfxSemInit(gfxSem* psem, semcount_t val, semcount_t limit); -void gfxSemDestroy(gfxSem* psem); -bool_t gfxSemWait(gfxSem* psem, delaytime_t ms); -bool_t gfxSemWaitI(gfxSem* psem); -void gfxSemSignal(gfxSem* psem); -void gfxSemSignalI(gfxSem* psem); -#define gfxSemCounterI(psem) ((psem)->counter) -#define gfxSemCounter(psem) ((psem)->counter) -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); - -#define gfxThreadWait(thread) {} // never used, not imlpemented -#define gfxThreadMe() {} // never used, not implemented -#define gfxThreadClose(thread) {} - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_OS_FREERTOS */ -#endif /* _GOS_CHIBIOS_H */ diff --git a/src/gos/gfx_linux.c b/src/gos/gfx_linux.c deleted file mode 100644 index e6fbe26c..00000000 --- a/src/gos/gfx_linux.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * 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 - */ - -#include "gfx.h" - -#if GFX_USE_OS_LINUX - -// Linux seems to have deprecated pthread_yield() and now says to use sched_yield() -#define USE_SCHED_NOT_PTHREAD_YIELD TRUE - -#include -#include -#include -#if USE_SCHED_NOT_PTHREAD_YIELD - #include - #define linuxyield() sched_yield() -#else - #define linuxyield() pthread_yield() -#endif - -static gfxMutex SystemMutex; - -void _gosInit(void) -{ - /* No initialization of the operating system itself is needed */ - gfxMutexInit(&SystemMutex); -} - -void _gosDeinit(void) -{ - /* ToDo */ -} - -void gfxSystemLock(void) { - gfxMutexEnter(&SystemMutex); -} - -void gfxSystemUnlock(void) { - gfxMutexExit(&SystemMutex); -} - -void gfxYield(void) { - linuxyield(); -} - -void gfxHalt(const char *msg) { - if (msg) - fprintf(stderr, "%s\n", msg); - exit(1); -} - -void gfxSleepMilliseconds(delaytime_t ms) { - struct timespec ts; - - switch(ms) { - case TIME_IMMEDIATE: - linuxyield(); - return; - - case TIME_INFINITE: - while(1) - sleep(60); - return; - - default: - ts.tv_sec = ms / 1000; - ts.tv_nsec = (ms % 1000) * 1000000; - nanosleep(&ts, 0); - return; - } -} - -void gfxSleepMicroseconds(delaytime_t us) { - struct timespec ts; - - switch(us) { - case TIME_IMMEDIATE: - linuxyield(); - return; - - case TIME_INFINITE: - while(1) - sleep(60); - return; - - default: - ts.tv_sec = us / 1000000; - ts.tv_nsec = (us % 1000000) * 1000; - nanosleep(&ts, 0); - return; - } -} - -systemticks_t gfxSystemTicks(void) { - struct timespec ts; - - clock_gettime(CLOCK_MONOTONIC, &ts); - return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; -} - -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { - gfxThreadHandle th; - (void) stackarea; - (void) stacksz; - (void) prio; - - // Implementing priority with pthreads is a rats nest that is also pthreads implementation dependent. - // Only some pthreads schedulers support it, some implementations use the operating system process priority mechanisms. - // Even those that do support it can have different ranges of priority and "normal" priority is an undefined concept. - // Across different UNIX style operating systems things can be very different (let alone OS's such as Windows). - // Even just Linux changes the way priority works with different kernel schedulers and across kernel versions. - // For these reasons we ignore the priority. - - if (pthread_create(&th, 0, fn, param)) - return 0; - - return th; -} - -threadreturn_t gfxThreadWait(gfxThreadHandle thread) { - threadreturn_t retval; - - if (pthread_join(thread, &retval)) - return 0; - - return retval; -} - -#if GFX_USE_POSIX_SEMAPHORES - void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { - pSem->max = limit; - sem_init(&pSem->sem, 0, val); - } - void gfxSemDestroy(gfxSem *pSem) { - sem_destroy(&pSem->sem); - } - bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { - switch (ms) { - case TIME_INFINITE: - return sem_wait(&pSem->sem) ? FALSE : TRUE; - - case TIME_IMMEDIATE: - return sem_trywait(&pSem->sem) ? FALSE : TRUE; - - default: - { - struct timespec tm; - - clock_gettime(CLOCK_REALTIME, &tm); - tm.tv_sec += ms / 1000; - tm.tv_nsec += (ms % 1000) * 1000000; - return sem_timedwait(&pSem->sem, &tm) ? FALSE : TRUE; - } - } - } - void gfxSemSignal(gfxSem *pSem) { - if (gfxSemCounter(pSem) < pSem->max) - sem_post(&pSem->sem); - } - semcount_t gfxSemCounter(gfxSem *pSem) { - int res; - - res = 0; - sem_getvalue(&pSem->sem, &res); - return res; - } -#else - void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { - pthread_mutex_init(&pSem->mtx, 0); - pthread_cond_init(&pSem->cond, 0); - pthread_mutex_lock(&pSem->mtx); - pSem->cnt = val; - pSem->max = limit; - pthread_mutex_unlock(&pSem->mtx); - } - void gfxSemDestroy(gfxSem *pSem) { - pthread_mutex_destroy(&pSem->mtx); - pthread_cond_destroy(&pSem->cond); - } - bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { - pthread_mutex_lock(&pSem->mtx); - - switch (ms) { - case TIME_INFINITE: - while (!pSem->cnt) - pthread_cond_wait(&pSem->cond, &pSem->mtx); - break; - - case TIME_IMMEDIATE: - if (!pSem->cnt) { - pthread_mutex_unlock(&pSem->mtx); - return FALSE; - } - break; - - default: - { - struct timespec tm; - - clock_gettime(CLOCK_REALTIME, &tm); - tm.tv_sec += ms / 1000; - tm.tv_nsec += (ms % 1000) * 1000000; - while (!pSem->cnt) { - // We used to test the return value for ETIMEDOUT. This doesn't - // work in some current pthread libraries which return -1 instead - // and set errno to ETIMEDOUT. So, we will return FALSE on any error - // including a ETIMEDOUT. - if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm)) { - pthread_mutex_unlock(&pSem->mtx); - return FALSE; - } - } - } - break; - } - - pSem->cnt--; - pthread_mutex_unlock(&pSem->mtx); - return TRUE; - } - void gfxSemSignal(gfxSem *pSem) { - pthread_mutex_lock(&pSem->mtx); - - if (pSem->cnt < pSem->max) { - pSem->cnt++; - pthread_cond_signal(&pSem->cond); - } - - pthread_mutex_unlock(&pSem->mtx); - } - semcount_t gfxSemCounter(gfxSem *pSem) { - semcount_t res; - - // The locking is really only required if obtaining the count is a divisible operation - // which it might be on a 8/16 bit processor with a 32 bit semaphore count. - pthread_mutex_lock(&pSem->mtx); - res = pSem->cnt; - pthread_mutex_unlock(&pSem->mtx); - - return res; - } -#endif // GFX_USE_POSIX_SEMAPHORES - -#endif /* GFX_USE_OS_LINUX */ diff --git a/src/gos/gfx_linux.h b/src/gos/gfx_linux.h deleted file mode 100644 index 39cfbc85..00000000 --- a/src/gos/gfx_linux.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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 - */ - -#ifndef _GOS_LINUX_H -#define _GOS_LINUX_H - -#if GFX_USE_OS_LINUX - -// We don't put this in the general sys_options.h as it is Linux specific. -#ifndef GFX_USE_POSIX_SEMAPHORES - #define GFX_USE_POSIX_SEMAPHORES TRUE -#endif - -#include -#include -#include -#include - -#if GFX_USE_POSIX_SEMAPHORES - #include -#endif - -/* Already defined int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, size_t */ - -typedef int8_t bool_t; -typedef unsigned long systemticks_t; -typedef void * threadreturn_t; -typedef unsigned long delaytime_t; -typedef pthread_t gfxThreadHandle; -typedef int threadpriority_t; -typedef uint32_t semcount_t; -typedef pthread_mutex_t gfxMutex; - -#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) -#define DECLARE_THREAD_STACK(name, sz) uint8_t name[0]; - -#define gfxExit() exit(0) -#define gfxAlloc(sz) malloc(sz) -#define gfxRealloc(p,osz,nsz) realloc(p, nsz) -#define gfxFree(ptr) free(ptr) -#define gfxMillisecondsToTicks(ms) (ms) -#define gfxThreadMe() pthread_self() -#define gfxThreadClose(th) (void)th -#define gfxMutexInit(pmtx) pthread_mutex_init(pmtx, 0) -#define gfxMutexDestroy(pmtx) pthread_mutex_destroy(pmtx) -#define gfxMutexEnter(pmtx) pthread_mutex_lock(pmtx) -#define gfxMutexExit(pmtx) pthread_mutex_unlock(pmtx) -#define gfxSemWaitI(psem) gfxSemWait(psem, TIME_IMMEDIATE) -#define gfxSemSignalI(psem) gfxSemSignal(psem) - -#define TIME_IMMEDIATE 0 -#define TIME_INFINITE ((delaytime_t)-1) -#define MAX_SEMAPHORE_COUNT ((semcount_t)-1) -#define LOW_PRIORITY 10 -#define NORMAL_PRIORITY 0 -#define HIGH_PRIORITY -10 - -#if GFX_USE_POSIX_SEMAPHORES - typedef struct gfxSem { - sem_t sem; - semcount_t max; - } gfxSem; - #define gfxSemCounterI(psem) gfxSemCounter(psem) -#else - typedef struct gfxSem { - pthread_mutex_t mtx; - pthread_cond_t cond; - semcount_t cnt; - semcount_t max; - } gfxSem; - #define gfxSemCounterI(psem) ((psem)->cnt) -#endif - -/*===========================================================================*/ -/* Function declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -void gfxYield(void); -void gfxHalt(const char *msg); -void gfxSleepMilliseconds(delaytime_t ms); -void gfxSleepMicroseconds(delaytime_t ms); -systemticks_t gfxSystemTicks(void); -void gfxSystemLock(void); -void gfxSystemUnlock(void); -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); -semcount_t gfxSemCounter(gfxSem *pSem); -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); -threadreturn_t gfxThreadWait(gfxThreadHandle thread); - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_OS_LINUX */ - -#endif /* _GOS_LINUX_H */ diff --git a/src/gos/gfx_osx.c b/src/gos/gfx_osx.c deleted file mode 100644 index f21b8a75..00000000 --- a/src/gos/gfx_osx.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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 - */ - -#include "gfx.h" - -#if GFX_USE_OS_OSX - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static gfxMutex SystemMutex; - -void _gosInit(void) -{ - /* No initialization of the operating system itself is needed */ - gfxMutexInit(&SystemMutex); -} - -void _gosDeinit(void) -{ - /* ToDo */ -} - -void gfxSystemLock(void) { - gfxMutexEnter(&SystemMutex); -} - -void gfxSystemUnlock(void) { - gfxMutexExit(&SystemMutex); -} - -void gfxHalt(const char *msg) { - if (msg) - fprintf(stderr, "%s\n", msg); - exit(1); -} - -void gfxSleepMilliseconds(delaytime_t ms) { - struct timespec ts; - - switch(ms) { - case TIME_IMMEDIATE: gfxYield(); return; - case TIME_INFINITE: while(1) sleep(60); return; - default: - ts.tv_sec = ms / 1000; - ts.tv_nsec = (ms % 1000) * 1000000; - nanosleep(&ts, 0); - return; - } -} - -void gfxSleepMicroseconds(delaytime_t us) { - struct timespec ts; - - switch(us) { - case TIME_IMMEDIATE: gfxYield(); return; - case TIME_INFINITE: while(1) sleep(60); return; - default: - ts.tv_sec = us / 1000000; - ts.tv_nsec = (us % 1000000) * 1000; - nanosleep(&ts, 0); - return; - } -} - -systemticks_t gfxSystemTicks(void) { - mach_timespec_t ts; - clock_serv_t cclock; - - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_time(cclock, &ts); - mach_port_deallocate(mach_task_self(), cclock); - - return ts.tv_sec * 1000UL + ts.tv_nsec / 1000000; -} - -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { - gfxThreadHandle th; - (void) stackarea; - (void) stacksz; - (void) prio; - - // Implementing priority with pthreads is a rats nest that is also pthreads implementation dependent. - // Only some pthreads schedulers support it, some implementations use the operating system process priority mechanisms. - // Even those that do support it can have different ranges of priority and "normal" priority is an undefined concept. - // Across different UNIX style operating systems things can be very different (let alone OS's such as Windows). - // Even just Linux changes the way priority works with different kernel schedulers and across kernel versions. - // For these reasons we ignore the priority. - - if (pthread_create(&th, 0, fn, param)) - return 0; - return th; -} - -threadreturn_t gfxThreadWait(gfxThreadHandle thread) { - threadreturn_t retval; - - if (pthread_join(thread, &retval)) - return 0; - return retval; -} - -void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { - pthread_mutex_init(&pSem->mtx, 0); - pthread_cond_init(&pSem->cond, 0); - pthread_mutex_lock(&pSem->mtx); - pSem->cnt = val; - pSem->max = limit; - pthread_mutex_unlock(&pSem->mtx); -} - -void gfxSemDestroy(gfxSem *pSem) { - pthread_mutex_destroy(&pSem->mtx); - pthread_cond_destroy(&pSem->cond); -} - -bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { - pthread_mutex_lock(&pSem->mtx); - switch (ms) { - case TIME_INFINITE: - while (!pSem->cnt) - pthread_cond_wait(&pSem->cond, &pSem->mtx); - break; - case TIME_IMMEDIATE: - if (!pSem->cnt) { - pthread_mutex_unlock(&pSem->mtx); - return FALSE; - } - break; - default: - { - struct timeval now; - struct timespec tm; - - gettimeofday(&now, 0); - tm.tv_sec = now.tv_sec + ms / 1000; - tm.tv_nsec = now.tv_usec * 1000 + (ms % 1000) * 1000000; - while (!pSem->cnt) { - // We used to test the return value for ETIMEDOUT. This doesn't - // work in some current pthread libraries which return -1 instead - // and set errno to ETIMEDOUT. So, we will return FALSE on any error - // including a ETIMEDOUT. - if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm)) { - pthread_mutex_unlock(&pSem->mtx); - return FALSE; - } - } - } - break; - } - pSem->cnt--; - pthread_mutex_unlock(&pSem->mtx); - return TRUE; -} - -void gfxSemSignal(gfxSem *pSem) { - pthread_mutex_lock(&pSem->mtx); - if (pSem->cnt < pSem->max) { - pSem->cnt++; - pthread_cond_signal(&pSem->cond); - } - pthread_mutex_unlock(&pSem->mtx); -} - -semcount_t gfxSemCounter(gfxSem *pSem) { - semcount_t res; - - // The locking is really only required if obtaining the count is a divisible operation - // which it might be on a 8/16 bit processor with a 32 bit semaphore count. - pthread_mutex_lock(&pSem->mtx); - res = pSem->cnt; - pthread_mutex_unlock(&pSem->mtx); - return res; -} - -#endif /* GFX_USE_OS_OSX */ diff --git a/src/gos/gfx_osx.h b/src/gos/gfx_osx.h deleted file mode 100644 index 635a8934..00000000 --- a/src/gos/gfx_osx.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 - */ - -#ifndef _GOS_OSX_H -#define _GOS_OSX_H - -#if GFX_USE_OS_OSX - -#include -#include -#include - -/* Already defined int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, size_t */ - -typedef int8_t bool_t; -typedef unsigned long systemticks_t; -typedef void * threadreturn_t; -typedef unsigned long delaytime_t; -typedef pthread_t gfxThreadHandle; -typedef int threadpriority_t; -typedef uint32_t semcount_t; -typedef pthread_mutex_t gfxMutex; - -#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) -#define DECLARE_THREAD_STACK(name, sz) uint8_t name[0]; - -#define gfxExit() exit(0) -#define gfxAlloc(sz) malloc(sz) -#define gfxRealloc(p,osz,nsz) realloc(p, nsz) -#define gfxFree(ptr) free(ptr) -#define gfxMillisecondsToTicks(ms) (ms) -#define gfxYield() sched_yield() -#define gfxThreadMe() pthread_self() -#define gfxThreadClose(th) (void)th -#define gfxMutexInit(pmtx) pthread_mutex_init(pmtx, 0) -#define gfxMutexDestroy(pmtx) pthread_mutex_destroy(pmtx) -#define gfxMutexEnter(pmtx) pthread_mutex_lock(pmtx) -#define gfxMutexExit(pmtx) pthread_mutex_unlock(pmtx) -#define gfxSemWaitI(psem) gfxSemWait(psem, TIME_IMMEDIATE) -#define gfxSemSignalI(psem) gfxSemSignal(psem) -#define gfxSemCounterI(pSem) ((pSem)->cnt) - -#define TIME_IMMEDIATE 0 -#define TIME_INFINITE ((delaytime_t)-1) -#define MAX_SEMAPHORE_COUNT ((semcount_t)-1) -#define LOW_PRIORITY 10 -#define NORMAL_PRIORITY 0 -#define HIGH_PRIORITY -10 - -typedef struct gfxSem { - pthread_mutex_t mtx; - pthread_cond_t cond; - semcount_t cnt; - semcount_t max; -} gfxSem; - -/*===========================================================================*/ -/* Function declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -void gfxHalt(const char *msg); -void gfxSleepMilliseconds(delaytime_t ms); -void gfxSleepMicroseconds(delaytime_t ms); -systemticks_t gfxSystemTicks(void); -void gfxSystemLock(void); -void gfxSystemUnlock(void); -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); -semcount_t gfxSemCounter(gfxSem *pSem); -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); -threadreturn_t gfxThreadWait(gfxThreadHandle thread); - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_OS_OSX */ -#endif /* _GOS_OSX_H */ diff --git a/src/gos/gfx_raw32.c b/src/gos/gfx_raw32.c deleted file mode 100644 index 22c753aa..00000000 --- a/src/gos/gfx_raw32.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - * 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 - */ - -#include "gfx.h" - -#if GFX_USE_OS_RAW32 - -#include // Prototype for memcpy() - -#if GOS_RAW_HEAP_SIZE != 0 - static void _gosHeapInit(void); -#else - #define _gosHeapInit() -#endif -static void _gosThreadsInit(void); - -/********************************************************* - * Initialise - *********************************************************/ - -void _gosInit(void) -{ - /* No initialization of the operating system itself is needed as there isn't one. - * On the other hand the C runtime should still already be initialized before - * getting here! - */ - #warning "GOS: Raw32 - Make sure you initialize your hardware and the C runtime before calling gfxInit() in your application!" - - // Set up the heap allocator - _gosHeapInit(); - - // Start the scheduler - _gosThreadsInit(); -} - -void _gosDeinit(void) -{ - /* ToDo */ -} - -/********************************************************* - * For WIn32 emulation - automatically add the tick functions - * the user would normally have to provide for bare metal. - *********************************************************/ - -#if defined(WIN32) - #undef Red - #undef Green - #undef Blue - #define WIN32_LEAN_AND_MEAN - #include - #include - systemticks_t gfxSystemTicks(void) { return GetTickCount(); } - systemticks_t gfxMillisecondsToTicks(delaytime_t ms) { return ms; } -#endif - -/********************************************************* - * Exit everything functions - *********************************************************/ - -void gfxHalt(const char *msg) { - #if defined(WIN32) - fprintf(stderr, "%s\n", msg); - ExitProcess(1); - #else - volatile uint32_t dummy; - (void) msg; - - while(1) - dummy++; - #endif -} - -void gfxExit(void) { - #if defined(WIN32) - ExitProcess(0); - #else - volatile uint32_t dummy; - - while(1) - dummy++; - #endif -} - -/********************************************************* - * Head allocation functions - *********************************************************/ - -#if GOS_RAW_HEAP_SIZE == 0 - #include // Prototype for malloc(), realloc() and free() - - void *gfxAlloc(size_t sz) { - return malloc(sz); - } - - void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz) { - (void) oldsz; - return realloc(ptr, newsz); - } - - void gfxFree(void *ptr) { - free(ptr); - } - -#else - - // Slot structure - user memory follows - typedef struct memslot { - struct memslot *next; // The next memslot - size_t sz; // Includes the size of this memslot. - } memslot; - - // Free Slot - immediately follows the memslot structure - typedef struct freeslot { - memslot *nextfree; // The next free slot - } freeslot; - - #define GetSlotSize(sz) ((((sz) + (sizeof(freeslot) - 1)) & ~(sizeof(freeslot) - 1)) + sizeof(memslot)) - #define NextFree(pslot) ((freeslot *)Slot2Ptr(pslot))->nextfree - #define Ptr2Slot(p) ((memslot *)(p) - 1) - #define Slot2Ptr(pslot) ((pslot)+1) - - static memslot * firstSlot; - static memslot * lastSlot; - static memslot * freeSlots; - static char heap[GOS_RAW_HEAP_SIZE]; - - static void _gosHeapInit(void) { - lastSlot = 0; - gfxAddHeapBlock(heap, GOS_RAW_HEAP_SIZE); - } - - void gfxAddHeapBlock(void *ptr, size_t sz) { - if (sz < sizeof(memslot)+sizeof(freeslot)) - return; - - if (lastSlot) - lastSlot->next = (memslot *)ptr; - else - firstSlot = lastSlot = freeSlots = (memslot *)ptr; - - lastSlot->next = 0; - lastSlot->sz = sz; - NextFree(lastSlot) = 0; - } - - void *gfxAlloc(size_t sz) { - register memslot *prev, *p, *new; - - if (!sz) return 0; - sz = GetSlotSize(sz); - for (prev = 0, p = freeSlots; p != 0; prev = p, p = NextFree(p)) { - // Loop till we have a block big enough - if (p->sz < sz) - continue; - // Can we save some memory by splitting this block? - if (p->sz >= sz + sizeof(memslot)+sizeof(freeslot)) { - new = (memslot *)((char *)p + sz); - new->next = p->next; - p->next = new; - new->sz = p->sz - sz; - p->sz = sz; - if (lastSlot == p) - lastSlot = new; - NextFree(new) = NextFree(p); - NextFree(p) = new; - } - // Remove it from the free list - if (prev) - NextFree(prev) = NextFree(p); - else - freeSlots = NextFree(p); - // Return the result found - return Slot2Ptr(p); - } - // No slots large enough - return 0; - } - - void *gfxRealloc(void *ptr, size_t oldsz, size_t sz) { - register memslot *prev, *p, *new; - (void) oldsz; - - if (!ptr) - return gfxAlloc(sz); - if (!sz) { - gfxFree(ptr); - return 0; - } - - p = Ptr2Slot(ptr); - sz = GetSlotSize(sz); - - // If the next slot is free (and contiguous) merge it into this one - if ((char *)p + p->sz == (char *)p->next) { - for (prev = 0, new = freeSlots; new != 0; prev = new, new = NextFree(new)) { - if (new == p->next) { - p->next = new->next; - p->sz += new->sz; - if (prev) - NextFree(prev) = NextFree(new); - else - freeSlots = NextFree(new); - if (lastSlot == new) - lastSlot = p; - break; - } - } - } - - // If this block is large enough we are nearly done - if (sz < p->sz) { - // Can we save some memory by splitting this block? - if (p->sz >= sz + sizeof(memslot)+sizeof(freeslot)) { - new = (memslot *)((char *)p + sz); - new->next = p->next; - p->next = new; - new->sz = p->sz - sz; - p->sz = sz; - if (lastSlot == p) - lastSlot = new; - NextFree(new) = freeSlots; - freeSlots = new; - } - return Slot2Ptr(p); - } - - // We need to do this the hard way - if ((new = gfxAlloc(sz))) - return 0; - memcpy(new, ptr, p->sz - sizeof(memslot)); - gfxFree(ptr); - return new; - } - - void gfxFree(void *ptr) { - register memslot *prev, *p, *new; - - if (!ptr) - return; - - p = Ptr2Slot(ptr); - - // If the next slot is free (and contiguous) merge it into this one - if ((char *)p + p->sz == (char *)p->next) { - for (prev = 0, new = freeSlots; new != 0; prev = new, new = NextFree(new)) { - if (new == p->next) { - p->next = new->next; - p->sz += new->sz; - if (prev) - NextFree(prev) = NextFree(new); - else - freeSlots = NextFree(new); - if (lastSlot == new) - lastSlot = p; - break; - } - } - } - - // Add it into the free chain - NextFree(p) = freeSlots; - freeSlots = p; - } -#endif - -/********************************************************* - * Semaphores and critical region functions - *********************************************************/ - -#if !defined(INTERRUPTS_OFF) || !defined(INTERRUPTS_ON) - #define INTERRUPTS_OFF() - #define INTERRUPTS_ON() -#endif - -void gfxSystemLock(void) { - INTERRUPTS_OFF(); -} - -void gfxSystemUnlock(void) { - INTERRUPTS_ON(); -} - -void gfxMutexInit(gfxMutex *pmutex) { - pmutex[0] = 0; -} - -void gfxMutexEnter(gfxMutex *pmutex) { - INTERRUPTS_OFF(); - while (pmutex[0]) { - INTERRUPTS_ON(); - gfxYield(); - INTERRUPTS_OFF(); - } - pmutex[0] = 1; - INTERRUPTS_ON(); -} - -void gfxMutexExit(gfxMutex *pmutex) { - pmutex[0] = 0; -} - -void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit) { - psem->cnt = val; - psem->limit = limit; -} - -bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) { - systemticks_t starttm, delay; - - // Convert our delay to ticks - switch (ms) { - case TIME_IMMEDIATE: - delay = TIME_IMMEDIATE; - break; - case TIME_INFINITE: - delay = TIME_INFINITE; - break; - default: - delay = gfxMillisecondsToTicks(ms); - if (!delay) delay = 1; - starttm = gfxSystemTicks(); - } - - INTERRUPTS_OFF(); - while (psem->cnt <= 0) { - INTERRUPTS_ON(); - // Check if we have exceeded the defined delay - switch (delay) { - case TIME_IMMEDIATE: - return FALSE; - case TIME_INFINITE: - break; - default: - if (gfxSystemTicks() - starttm >= delay) - return FALSE; - break; - } - gfxYield(); - INTERRUPTS_OFF(); - } - psem->cnt--; - INTERRUPTS_ON(); - return TRUE; -} - -bool_t gfxSemWaitI(gfxSem *psem) { - if (psem->cnt <= 0) - return FALSE; - psem->cnt--; - return TRUE; -} - -void gfxSemSignal(gfxSem *psem) { - INTERRUPTS_OFF(); - gfxSemSignalI(psem); - INTERRUPTS_ON(); -} - -void gfxSemSignalI(gfxSem *psem) { - if (psem->cnt < psem->limit) - psem->cnt++; -} - -/********************************************************* - * Sleep functions - *********************************************************/ - -void gfxSleepMilliseconds(delaytime_t ms) { - systemticks_t starttm, delay; - - // Safety first - switch (ms) { - case TIME_IMMEDIATE: - return; - case TIME_INFINITE: - while(1) - gfxYield(); - return; - } - - // Convert our delay to ticks - delay = gfxMillisecondsToTicks(ms); - starttm = gfxSystemTicks(); - - do { - gfxYield(); - } while (gfxSystemTicks() - starttm < delay); -} - -void gfxSleepMicroseconds(delaytime_t ms) { - systemticks_t starttm, delay; - - // Safety first - switch (ms) { - case TIME_IMMEDIATE: - return; - case TIME_INFINITE: - while(1) - gfxYield(); - return; - } - - // Convert our delay to ticks - delay = gfxMillisecondsToTicks(ms/1000); - starttm = gfxSystemTicks(); - - do { - gfxYield(); - } while (gfxSystemTicks() - starttm < delay); -} - -/********************************************************* - * Threading functions - *********************************************************/ - -/** - * There are some compilers we know how they store the jmpbuf. For those - * we can use the constant macro definitions. For others we have to "auto-detect". - * Auto-detection is hairy and there is no guarantee it will work on all architectures. - * For those it doesn't - read the compiler manuals and the library source code to - * work out the correct macro values. - * You can use the debugger to work out the values for your compiler and put them here. - * Defining these macros as constant values makes the system behaviour guaranteed but also - * makes your code compiler and cpu architecture dependant. - */ -#if 0 - // Define your compiler constant values here. - // These example values are for mingw32 compiler (x86). - #define AUTO_DETECT_MASK FALSE - #define STACK_DIR_UP FALSE - #define MASK1 0x00000011 - #define MASK2 0x00000000 - #define STACK_BASE 9 -#else - #define AUTO_DETECT_MASK TRUE - #define STACK_DIR_UP stackdirup // TRUE if the stack grow up instead of down - #define MASK1 jmpmask1 // The 1st mask of jmp_buf elements that need relocation - #define MASK2 jmpmask2 // The 2nd mask of jmp_buf elements that need relocation - #define STACK_BASE stackbase // The base of the stack frame relative to the local variables - static bool_t stackdirup; - static uint32_t jmpmask1; - static uint32_t jmpmask2; - static size_t stackbase; -#endif - -#include /* jmp_buf, setjmp(), longjmp() */ - -/** - * Some compilers define a _setjmp() and a setjmp(). - * The difference between them is that setjmp() saves the signal masks. - * That is of no use to us so prefer to use the _setjmp() methods. - * If they don't exist compile them to be the standard setjmp() function. - * Similarly for longjmp(). - */ -#ifndef setjmp - #ifndef _setjmp - #define _setjmp setjmp - #endif -#endif -#ifndef longjmp - #ifndef _longjmp - #define _longjmp longjmp - #endif -#endif - -typedef struct thread { - struct thread * next; // Next thread - int flags; // Flags - #define FLG_THD_ALLOC 0x0001 - #define FLG_THD_MAIN 0x0002 - #define FLG_THD_DEAD 0x0004 - #define FLG_THD_WAIT 0x0008 - size_t size; // Size of the thread stack (including this structure) - threadreturn_t (*fn)(void *param); // Thread function - void * param; // Parameter for the thread function - jmp_buf cxt; // The current thread context. -} thread; - -typedef struct threadQ { - thread *head; - thread *tail; -} threadQ; - -static threadQ readyQ; // The list of ready threads -static threadQ deadQ; // Where we put threads waiting to be deallocated -static thread * current; // The current running thread -static thread mainthread; // The main thread context - -static void Qinit(threadQ * q) { - q->head = q->tail = 0; -} - -static void Qadd(threadQ * q, thread *t) { - t->next = 0; - if (q->head) { - q->tail->next = t; - q->tail = t; - } else - q->head = q->tail = t; -} - -static thread *Qpop(threadQ * q) { - struct thread * t; - - if (!q->head) - return 0; - t = q->head; - q->head = t->next; - return t; -} - -#if AUTO_DETECT_MASK - // The structure for the saved stack frame information - typedef struct saveloc { - char * localptr; - jmp_buf cxt; - } saveloc; - - // A pointer to our auto-detection buffer. - static saveloc *pframeinfo; - - /* These functions are not static to prevent the compiler removing them as functions */ - - void get_stack_state(void) { - char c; - pframeinfo->localptr = (char *)&c; - _setjmp(pframeinfo->cxt); - } - - void get_stack_state_in_fn(void) { - pframeinfo++; - get_stack_state(); - pframeinfo--; - } -#endif - -static void _gosThreadsInit(void) { - Qinit(&readyQ); - current = &mainthread; - current->next = 0; - current->size = sizeof(thread); - current->flags = FLG_THD_MAIN; - current->fn = 0; - current->param = 0; - - #if AUTO_DETECT_MASK - { - uint32_t i; - char ** pout; - char ** pin; - size_t diff; - char * framebase; - - // Allocate a buffer to store our test data - pframeinfo = gfxAlloc(sizeof(saveloc)*2); - - // Get details of the stack frame from within a function - get_stack_state_in_fn(); - - // Get details of the stack frame outside the function - get_stack_state(); - - /* Work out the frame entries to relocate by treating the jump buffer as an array of pointers */ - stackdirup = pframeinfo[1].localptr > pframeinfo[0].localptr; - pout = (char **)pframeinfo[0].cxt; - pin = (char **)pframeinfo[1].cxt; - diff = pframeinfo[0].localptr - pframeinfo[1].localptr; - framebase = pframeinfo[0].localptr; - jmpmask1 = jmpmask2 = 0; - for (i = 0; i < sizeof(jmp_buf)/sizeof(char *); i++, pout++, pin++) { - if ((size_t)(*pout - *pin) == diff) { - if (i < 32) - jmpmask1 |= 1 << i; - else - jmpmask2 |= 1 << (i-32); - - if (stackdirup) { - if (framebase > *pout) - framebase = *pout; - } else { - if (framebase < *pout) - framebase = *pout; - } - } - } - stackbase = stackdirup ? (pframeinfo[0].localptr - framebase) : (framebase - pframeinfo[0].localptr); - - // Clean up - gfxFree(pframeinfo); - } - #endif -} - -gfxThreadHandle gfxThreadMe(void) { - return (gfxThreadHandle)current; -} - -void gfxYield(void) { - if (!_setjmp(current->cxt)) { - // Add us back to the Queue - Qadd(&readyQ, current); - - // Check if there are dead processes to deallocate - while ((current = Qpop(&deadQ))) - gfxFree(current); - - // Run the next process - current = Qpop(&readyQ); - _longjmp(current->cxt, 1); - } -} - -// This routine is not currently public - but it could be. -void gfxThreadExit(threadreturn_t ret) { - // Save the results - current->param = (void *)ret; - current->flags |= FLG_THD_DEAD; - - // Add us to the dead list if we need deallocation as we can't free ourselves. - // If someone is waiting on the thread they will do the cleanup. - if ((current->flags & (FLG_THD_ALLOC|FLG_THD_WAIT)) == FLG_THD_ALLOC) - Qadd(&deadQ, current); - - // Switch to the next task - current = Qpop(&readyQ); - if (!current) - gfxExit(); // Oops - this should never happen! - _longjmp(current->cxt, 1); -} - -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { - thread * t; - (void) prio; - - // Ensure we have a minimum stack size - if (stacksz < sizeof(thread)+64) { - stacksz = sizeof(thread)+64; - stackarea = 0; - } - - if (stackarea) { - t = (thread *)stackarea; - t->flags = 0; - } else { - t = (thread *)gfxAlloc(stacksz); - if (!t) - return 0; - t->flags = FLG_THD_ALLOC; - } - t->size = stacksz; - t->fn = fn; - t->param = param; - if (_setjmp(t->cxt)) { - // This is the new thread - call the function! - gfxThreadExit(current->fn(current->param)); - - // We never get here - return 0; - } - - // Move the stack frame and relocate the context data - { - char ** s; - char * nf; - int diff; - uint32_t i; - - // Copy the stack frame - #if AUTO_DETECT_MASK - if (STACK_DIR_UP) { // Stack grows up - nf = (char *)(t) + sizeof(thread) + stackbase; - memcpy(t+1, (char *)&t - stackbase, stackbase+sizeof(char *)); - } else { // Stack grows down - nf = (char *)(t) + stacksz - (stackbase + sizeof(char *)); - memcpy(nf, &t, stackbase+sizeof(char *)); - } - #elif STACK_DIR_UP - // Stack grows up - nf = (char *)(t) + sizeof(thread) + stackbase; - memcpy(t+1, (char *)&t - stackbase, stackbase+sizeof(char *)); - #else - // Stack grows down - nf = (char *)(t) + size - (stackbase + sizeof(char *)); - memcpy(nf, &t, stackbase+sizeof(char *)); - #endif - - // Relocate the context data - s = (char **)(t->cxt); - diff = nf - (char *)&t; - - // Relocate the elements we know need to be relocated - for (i = 1; i && i < MASK1; i <<= 1, s++) { - if ((MASK1 & i)) - *s += diff; - } - #ifdef MASK2 - for (i = 1; i && i < MASK2; i <<= 1, s++) { - if ((MASK1 & i)) - *s += diff; - } - #endif - } - - // Add this thread to the ready queue - Qadd(&readyQ, t); - return t; -} - -threadreturn_t gfxThreadWait(gfxThreadHandle th) { - thread * t; - - t = th; - if (t == current) - return -1; - - // Mark that we are waiting - t->flags |= FLG_THD_WAIT; - - // Wait for the thread to die - while(!(t->flags & FLG_THD_DEAD)) - gfxYield(); - - // Unmark - t->flags &= ~FLG_THD_WAIT; - - // Clean up resources if needed - if (t->flags & FLG_THD_ALLOC) - gfxFree(t); - - // Return the status left by the dead process - return (threadreturn_t)t->param; -} - -#endif /* GFX_USE_OS_RAW32 */ diff --git a/src/gos/gfx_raw32.h b/src/gos/gfx_raw32.h deleted file mode 100644 index 5a6a2aa7..00000000 --- a/src/gos/gfx_raw32.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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 - */ - -/** - * The raw32 GOS implementation supports any 32 bit processor with or without an - * underlying operating system. It uses cooperative multi-tasking. Be careful - * when writing device drivers not to disturb the assumptions this creates by performing - * call-backs to uGFX code unless you define the INTERRUPTS_OFF() and INTERRUPTS_ON() macros. - * It still requires some C runtime library support... - * enough startup to initialise the stack, interrupts, static data etc and call main(). - * setjmp() and longjmp() - for threading - * memcpy() - for heap and threading - * malloc(), realloc and free() - if GOS_RAW_HEAP_SIZE == 0 - * - * You must also define the following routines in your own code so that timing functions will work... - * systemticks_t gfxSystemTicks(void); - * systemticks_t gfxMillisecondsToTicks(delaytime_t ms); - */ -#ifndef _GOS_RAW32_H -#define _GOS_RAW32_H - -#if GFX_USE_OS_RAW32 - -/*===========================================================================*/ -/* Special Macros just for a Raw implementation */ -/*===========================================================================*/ - -/** - * @brief Set the maximum size of the heap. - * @note If set to 0 then the C runtime library malloc() and free() are used. - */ -#ifndef GOS_RAW_HEAP_SIZE - #define GOS_RAW_HEAP_SIZE 0 -#endif - -/*===========================================================================*/ -/* Type definitions */ -/*===========================================================================*/ - -typedef unsigned char bool_t; - -#ifndef _STDINT_H - typedef char int8_t; - typedef unsigned char uint8_t; - typedef short int16_t; - typedef unsigned short uint16_t; - typedef int int32_t; - typedef unsigned int uint32_t; -#endif - -#if !defined (__need_size_t) && !defined (_STDDEF_H_) - typedef uint32_t size_t; -#endif - -typedef uint32_t delaytime_t; -typedef uint32_t systemticks_t; -typedef short semcount_t; -typedef int threadreturn_t; -typedef int threadpriority_t; - -#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) -#define DECLARE_THREAD_STACK(name, sz) uint8_t name[sz]; - -#define TIME_IMMEDIATE 0 -#define TIME_INFINITE ((delaytime_t)-1) -#define MAX_SEMAPHORE_COUNT 0x7FFF -#define LOW_PRIORITY 0 -#define NORMAL_PRIORITY 1 -#define HIGH_PRIORITY 2 - -typedef struct { - semcount_t cnt; - semcount_t limit; -} gfxSem; - -typedef uint32_t gfxMutex; -typedef void * gfxThreadHandle; - -#define gfxThreadClose(thread) -#define gfxMutexDestroy(pmutex) -#define gfxSemDestroy(psem) -#define gfxSemCounter(psem) ((psem)->cnt) -#define gfxSemCounterI(psem) ((psem)->cnt) - -#ifdef __cplusplus -extern "C" { -#endif - - #if GOS_RAW_HEAP_SIZE != 0 - void gfxAddHeapBlock(void *ptr, size_t sz); - #endif - - void gfxHalt(const char *msg); - void gfxExit(void); - void *gfxAlloc(size_t sz); - void *gfxRealloc(void *ptr, 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 gfxMutexEnter(gfxMutex *pmutex); - void gfxMutexExit(gfxMutex *pmutex); - void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit); - bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); - bool_t gfxSemWaitI(gfxSem *psem); - void gfxSemSignal(gfxSem *psem); - void gfxSemSignalI(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); - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_OS_RAW32 */ -#endif /* _GOS_RAW32_H */ diff --git a/src/gos/gfx_rawrtos.c b/src/gos/gfx_rawrtos.c deleted file mode 100644 index cd684208..00000000 --- a/src/gos/gfx_rawrtos.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "gfx.h" - -#if GFX_USE_OS_RAWRTOS - -#include -#include "raw_api.h" -#include "raw_config.h" - -#if CONFIG_RAW_MUTEX != 1 - #error "GOS: CONFIG_RAW_MUTEX must be defined in raw_config.h" -#endif - -#if CONFIG_RAW_SEMAPHORE != 1 - #error "GOS: CONFIG_RAW_SEMAPHORE must be defined in raw_config.h" -#endif - - -void _gosInit(void) -{ - #if !GFX_NO_OS_INIT - #error "GOS: Operating System initialization for RawRTOS is not yet implemented in uGFX. Please set GFX_NO_OS_INIT to TRUE in your gfxconf.h" - #else - #warning "GOS: Operating System initialization has been turned off. Make sure you call raw_os_start() before gfxInit() in your application!" - #endif -} - -void _gosDeinit(void) -{ -} - - -void gfxSleepMilliseconds(delaytime_t ms) -{ - systemticks_t ticks = ms*RAW_TICKS_PER_SECOND/1000; - if(!ticks)ticks = 1; - raw_sleep(ticks); -} - -void gfxSleepMicroseconds(delaytime_t us) -{ - systemticks_t ticks = (us/1000)*RAW_TICKS_PER_SECOND/1000; - if(!ticks)ticks = 1; - raw_sleep(ticks); -} - -bool_t gfxSemWait(gfxSem* psem, delaytime_t ms) -{ - systemticks_t ticks = ms*RAW_TICKS_PER_SECOND/1000; - if(!ticks)ticks=1; - if(raw_semaphore_get((psem), ticks)==RAW_SUCCESS) - return TRUE; - return FALSE; -} - -bool_t gfxSemWaitI(gfxSem* psem) -{ - if(raw_semaphore_get((psem), TIME_IMMEDIATE)==RAW_SUCCESS) - return TRUE; - return FALSE; -} - -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) -{ - RAW_U16 ret; - gfxThreadHandle taskobj; - - taskobj = gfxAlloc(sizeof(RAW_TASK_OBJ)); - ret = raw_task_create(taskobj, (RAW_U8 *)"uGFX_TASK", param, - prio, 0, stackarea, - stacksz/sizeof(PORT_STACK) , fn, 1); - - if (ret != RAW_SUCCESS) { - for (;;); - } - - return (taskobj); -} - - -#endif - - - diff --git a/src/gos/gfx_rawrtos.h b/src/gos/gfx_rawrtos.h deleted file mode 100644 index eeb5119d..00000000 --- a/src/gos/gfx_rawrtos.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _GOS_RAWRTOS_H -#define _GOS_RAWRTOS_H - -#if GFX_USE_OS_RAWRTOS - -#include "raw_api.h" -#include - -#define TIME_IMMEDIATE (RAW_NO_WAIT) -#define TIME_INFINITE (RAW_WAIT_FOREVER) -typedef int8_t bool_t; -typedef uint32_t delaytime_t; -typedef RAW_TICK_TYPE systemticks_t; -typedef int32_t semcount_t; -typedef uint32_t threadreturn_t; -typedef RAW_U8 threadpriority_t; -typedef uint32_t size_t; - -#define MAX_SEMAPHORE_COUNT RAW_SEMAPHORE_COUNT -#define LOW_PRIORITY (CONFIG_RAW_PRIO_MAX-2) -#define NORMAL_PRIORITY (CONFIG_RAW_PRIO_MAX/2) -#define HIGH_PRIORITY 1 - -typedef RAW_SEMAPHORE gfxSem; -typedef RAW_MUTEX gfxMutex; -typedef RAW_TASK_OBJ* gfxThreadHandle; - -#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) -#define DECLARE_THREAD_STACK(name, sz) PORT_STACK name[sz]; - -#define gfxHalt(msg) for(;;) -#define gfxExit() for(;;) -#define gfxAlloc(sz) raw_malloc(sz) -#define gfxRealloc(p,osz,nsz) raw_calloc(p, nsz) -#define gfxFree(ptr) raw_free(ptr) -#define gfxYield() raw_sleep(0) -#define gfxSystemTicks() raw_system_time_get() -#define gfxMillisecondsToTicks(ms) (ms*RAW_TICKS_PER_SECOND/1000) -#define gfxSystemLock() {} -#define gfxSystemUnlock() {} -#define gfxMutexInit(pmutex) raw_mutex_create(pmutex, (RAW_U8 *)"", RAW_MUTEX_INHERIT_POLICY, 3) -#define gfxMutexDestroy(pmutex) raw_mutex_delete(pmutex) -#define gfxMutexEnter(pmutex) raw_mutex_get(pmutex, TIME_INFINITE) -#define gfxMutexExit(pmutex) raw_mutex_put(pmutex) -#define gfxSemInit(psem, val, limit) raw_semaphore_create(psem, "", val) -#define gfxSemDestroy(psem) raw_semaphore_delete(psem) -#define gfxSemSignal(psem) raw_semaphore_put((psem)) -#define gfxSemSignalI(psem) raw_semaphore_put_all((psem)) -#define gfxSemCounterI(psem) ((psem)->count) -#define gfxThreadMe() {(unsigned int)raw_task_identify()} -#define gfxThreadClose(thread) {} - -extern RAW_VOID *raw_malloc(RAW_U32 size); -extern RAW_VOID raw_free(void *ptr); -extern RAW_VOID *raw_calloc(RAW_U32 nmemb, RAW_U32 size); - -extern RAW_U16 raw_sleep(RAW_TICK_TYPE dly); -extern RAW_TICK_TYPE raw_system_time_get(void); - -extern RAW_U16 raw_mutex_create(RAW_MUTEX *mutex_ptr, RAW_U8 *name_ptr, RAW_U8 policy, RAW_U8 ceiling_prio); -extern RAW_U16 raw_mutex_delete(RAW_MUTEX *mutex_ptr); -extern RAW_U16 raw_mutex_get(RAW_MUTEX *mutex_ptr, RAW_TICK_TYPE wait_option); -extern RAW_U16 raw_mutex_put(RAW_MUTEX *mutex_ptr); -extern RAW_U16 raw_semaphore_create(RAW_SEMAPHORE *semaphore_ptr, RAW_U8 *name_ptr, RAW_U32 initial_count); -extern RAW_U16 raw_semaphore_delete(RAW_SEMAPHORE *semaphore_ptr); -extern RAW_U16 raw_semaphore_get(RAW_SEMAPHORE *semaphore_ptr, RAW_TICK_TYPE wait_option); -extern RAW_U16 raw_semaphore_put(RAW_SEMAPHORE *semaphore_ptr); - -void gfxSleepMilliseconds(delaytime_t ms); -void gfxSleepMicroseconds(delaytime_t us); -bool_t gfxSemWait(gfxSem* psem, delaytime_t ms); -bool_t gfxSemWaitI(gfxSem* psem); -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); - -#endif - -#endif diff --git a/src/gos/gfx_win32.c b/src/gos/gfx_win32.c deleted file mode 100644 index 5d33314f..00000000 --- a/src/gos/gfx_win32.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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/gfx_win32.c - * @brief GOS Win32 Operating System support. - */ -#include "gfx.h" - -#if GFX_USE_OS_WIN32 - -#include - -static HANDLE SystemMutex; - -void _gosInit(void) -{ - /* No initialization of the operating system itself is needed */ -} - -void _gosDeinit(void) -{ - -} - -void gfxHalt(const char *msg) { - if (msg) - fprintf(stderr, "%s\n", msg); - - ExitProcess(1); -} - -void gfxSleepMicroseconds(delaytime_t ms) { - static LARGE_INTEGER pcfreq; - static int initflag; - LARGE_INTEGER t1, t2, tdiff; - - switch(ms) { - case TIME_IMMEDIATE: - return; - - case TIME_INFINITE: - while(1) - Sleep(1000); - return; - } - - if (!initflag) { - QueryPerformanceFrequency(&pcfreq); - initflag++; - } - tdiff.QuadPart = pcfreq.QuadPart * ms / 1000000; - - QueryPerformanceCounter(&t1); - do { - QueryPerformanceCounter(&t2); - } while (t2.QuadPart - t1.QuadPart < tdiff.QuadPart); -} - -void gfxSystemLock(void) { - if (!SystemMutex) - SystemMutex = CreateMutex(0, FALSE, 0); - WaitForSingleObject(SystemMutex, INFINITE); -} - -void gfxSystemUnlock(void) { - ReleaseMutex(SystemMutex); -} - -bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) { - return WaitForSingleObject(*psem, ms) == WAIT_OBJECT_0; -} - -typedef LONG __stdcall (*_NtQuerySemaphore)( - HANDLE SemaphoreHandle, - DWORD SemaphoreInformationClass, /* Would be SEMAPHORE_INFORMATION_CLASS */ - PVOID SemaphoreInformation, /* but this is to much to dump here */ - ULONG SemaphoreInformationLength, - PULONG ReturnLength OPTIONAL -); - -semcount_t gfxSemCounter(gfxSem *pSem) { - static _NtQuerySemaphore NtQuerySemaphore; - struct _SEMAPHORE_BASIC_INFORMATION { - ULONG CurrentCount; - ULONG MaximumCount; - } BasicInfo; - - if (!NtQuerySemaphore) - NtQuerySemaphore = (_NtQuerySemaphore)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySemaphore"); - - NtQuerySemaphore(*pSem, 0, &BasicInfo, sizeof(BasicInfo), 0); - - return BasicInfo.CurrentCount; -} - -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { - (void) stackarea; - HANDLE thd; - - if (!(thd = CreateThread(0, stacksz, fn, param, CREATE_SUSPENDED, 0))) - return FALSE; - - SetThreadPriority(thd, prio); - ResumeThread(thd); - - return thd; -} - -threadreturn_t gfxThreadWait(gfxThreadHandle thread) { - DWORD ret; - - WaitForSingleObject(thread, INFINITE); - GetExitCodeThread(thread, &ret); - CloseHandle(thread); - - return ret; -} - -#endif /* GFX_USE_OS_WIN32 */ -/** @} */ - diff --git a/src/gos/gfx_win32.h b/src/gos/gfx_win32.h deleted file mode 100644 index 5e924a44..00000000 --- a/src/gos/gfx_win32.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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/gfx_win32.h - * @brief GOS - Operating System Support header file for WIN32. - */ - -#ifndef _GOS_WIN32_H -#define _GOS_WIN32_H - -#if GFX_USE_OS_WIN32 - -#ifndef _WIN32_WINNT - #define _WIN32_WINNT 0x0501 // Windows XP and up -#endif - -#define WIN32_LEAN_AND_MEAN -#include -#undef WIN32_LEAN_AND_MEAN - -#include - -/* Stop cygwin from defining these types */ -#define __int8_t_defined - -/** - * size_t - * TRUE, FALSE - * are already defined by Win32 - */ -typedef __int8 bool_t; -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef DWORD delaytime_t; -typedef DWORD systemticks_t; -typedef LONG semcount_t; -typedef DWORD threadreturn_t; -typedef int threadpriority_t; - -#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t WINAPI fnName(void *param) -#define DECLARE_THREAD_STACK(name, sz) uint8_t name[0]; - -#define TIME_IMMEDIATE 0 -#define TIME_INFINITE INFINITE -#define MAX_SEMAPHORE_COUNT ((semcount_t)(((unsigned long)((semcount_t)(-1))) >> 1)) -#define LOW_PRIORITY THREAD_PRIORITY_BELOW_NORMAL -#define NORMAL_PRIORITY THREAD_PRIORITY_NORMAL -#define HIGH_PRIORITY THREAD_PRIORITY_ABOVE_NORMAL - -typedef HANDLE gfxSem; -typedef HANDLE gfxMutex; -typedef HANDLE gfxThreadHandle; - -#define gfxExit() ExitProcess(0) -#define gfxAlloc(sz) malloc(sz) -#define gfxRealloc(p,osz,nsz) realloc(p, nsz) -#define gfxFree(ptr) free(ptr) -#define gfxSleepMilliseconds(ms) Sleep(ms) -#define gfxYield() Sleep(0) -#define gfxSystemTicks() GetTickCount() -#define gfxMillisecondsToTicks(ms) (ms) -#define gfxMutexInit(pmutex) *(pmutex) = CreateMutex(0, FALSE, 0) -#define gfxMutexDestroy(pmutex) CloseHandle(*(pmutex)) -#define gfxMutexEnter(pmutex) WaitForSingleObject(*(pmutex), INFINITE) -#define gfxMutexExit(pmutex) ReleaseMutex(*(pmutex)) -#define gfxSemInit(psem, val, limit) *(psem) = CreateSemaphore(0, val, limit, 0) -#define gfxSemDestroy(psem) CloseHandle(*(psem)) -#define gfxSemWaitI(psem) gfxSemWait((psem), TIME_IMMEDIATE) -#define gfxSemSignal(psem) ReleaseSemaphore(*(psem), 1, 0) -#define gfxSemSignalI(psem) ReleaseSemaphore(*(psem), 1, 0) -#define gfxSemCounterI(psem) gfxSemCounter(psem) -#define gfxThreadMe() GetCurrentThread() -#define gfxThreadClose(thread) CloseHandle(thread) - -/*===========================================================================*/ -/* Function declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -void gfxHalt(const char *msg); -void gfxSleepMicroseconds(delaytime_t ms); -bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); -semcount_t gfxSemCounter(gfxSem *pSem); -void gfxSystemLock(void); -void gfxSystemUnlock(void); -gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); -threadreturn_t gfxThreadWait(gfxThreadHandle thread); - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_OS_WIN32 */ -#endif /* _GOS_WIN32_H */ - diff --git a/src/gos/gos_chibios.c b/src/gos/gos_chibios.c new file mode 100644 index 00000000..9d1a86da --- /dev/null +++ b/src/gos/gos_chibios.c @@ -0,0 +1,168 @@ +/* + * 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 + */ + +#include "gfx.h" + +#if GFX_USE_OS_CHIBIOS + +#include + +#if CH_KERNEL_MAJOR == 2 + + #if !CH_USE_MUTEXES + #error "GOS: CH_USE_MUTEXES must be defined in chconf.h" + #endif + #if !CH_USE_SEMAPHORES + #error "GOS: CH_USE_SEMAPHORES must be defined in chconf.h" + #endif + +#elif CH_KERNEL_MAJOR == 3 + + #if !CH_CFG_USE_MUTEXES + #error "GOS: CH_USE_MUTEXES must be defined in chconf.h" + #endif + #if !CH_CFG_USE_SEMAPHORES + #error "GOS: CH_USE_SEMAPHORES must be defined in chconf.h" + #endif + +#endif + +void _gosInit(void) +{ + #if !GFX_NO_OS_INIT + /* Don't Initialize if the user already has */ + #if CH_KERNEL_MAJOR == 2 + if (!chThdSelf()) { + halInit(); + chSysInit(); + } + #elif CH_KERNEL_MAJOR == 3 + if (!chThdGetSelfX()) { + halInit(); + chSysInit(); + } + #endif + #else + #warning "GOS: Operating System initialization has been turned off. Make sure you call halInit() and chSysInit() before gfxInit() in your application!" + #endif +} + +void _gosDeinit(void) +{ + /* ToDo */ +} + +void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz) +{ + void *np; + + if (newsz <= oldsz) + return ptr; + + np = gfxAlloc(newsz); + if (!np) + return 0; + + if (oldsz) + memcpy(np, ptr, oldsz); + + return np; +} + +void gfxSleepMilliseconds(delaytime_t ms) +{ + switch(ms) { + case TIME_IMMEDIATE: chThdYield(); return; + case TIME_INFINITE: chThdSleep(TIME_INFINITE); return; + default: chThdSleepMilliseconds(ms); return; + } +} + +void gfxSleepMicroseconds(delaytime_t ms) +{ + switch(ms) { + case TIME_IMMEDIATE: return; + case TIME_INFINITE: chThdSleep(TIME_INFINITE); return; + default: chThdSleepMicroseconds(ms); return; + } +} + +void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit) +{ + if (val > limit) + val = limit; + + psem->limit = limit; + + #if CH_KERNEL_MAJOR == 2 + chSemInit(&psem->sem, val); + #elif CH_KERNEL_MAJOR == 3 + chSemObjectInit(&psem->sem, val); + #endif +} + +void gfxSemDestroy(gfxSem *psem) +{ + chSemReset(&psem->sem, 1); +} + +bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) +{ + #if CH_KERNEL_MAJOR == 2 + switch(ms) { + case TIME_IMMEDIATE: return chSemWaitTimeout(&psem->sem, TIME_IMMEDIATE) != RDY_TIMEOUT; + case TIME_INFINITE: chSemWait(&psem->sem); return TRUE; + default: return chSemWaitTimeout(&psem->sem, MS2ST(ms)) != RDY_TIMEOUT; + } + #elif CH_KERNEL_MAJOR == 3 + switch(ms) { + case TIME_IMMEDIATE: return chSemWaitTimeout(&psem->sem, TIME_IMMEDIATE) != MSG_TIMEOUT; + case TIME_INFINITE: chSemWait(&psem->sem); return TRUE; + default: return chSemWaitTimeout(&psem->sem, MS2ST(ms)) != MSG_TIMEOUT; + } + #endif +} + +bool_t gfxSemWaitI(gfxSem *psem) +{ + if (chSemGetCounterI(&psem->sem) <= 0) + return FALSE; + chSemFastWaitI(&psem->sem); + return TRUE; +} + +void gfxSemSignal(gfxSem *psem) +{ + chSysLock(); + + if (gfxSemCounterI(psem) < psem->limit) + chSemSignalI(&psem->sem); + + chSchRescheduleS(); + chSysUnlock(); +} + +void gfxSemSignalI(gfxSem *psem) +{ + if (gfxSemCounterI(psem) < psem->limit) + chSemSignalI(&psem->sem); +} + +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) +{ + if (!stackarea) { + if (!stacksz) stacksz = 256; + return chThdCreateFromHeap(0, stacksz, prio, fn, param); + } + + if (!stacksz) + return 0; + + return chThdCreateStatic(stackarea, stacksz, prio, fn, param); +} + +#endif /* GFX_USE_OS_CHIBIOS */ diff --git a/src/gos/gos_chibios.h b/src/gos/gos_chibios.h new file mode 100644 index 00000000..a07c72ab --- /dev/null +++ b/src/gos/gos_chibios.h @@ -0,0 +1,118 @@ +/* + * 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 + */ + +#ifndef _GOS_CHIBIOS_H +#define _GOS_CHIBIOS_H + +#if GFX_USE_OS_CHIBIOS + +#include "ch.h" +#include "hal.h" + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +/** + * bool_t, + * int8_t, uint8_t, + * int16_t, uint16_t, + * int32_t, uint32_t, + * size_t + * TRUE, FALSE + * TIME_IMMEDIATE, TIME_INFINITE + * are already defined by ChibiOS + */ + +typedef systime_t delaytime_t; +typedef systime_t systemticks_t; +typedef cnt_t semcount_t; +typedef msg_t threadreturn_t; +typedef tprio_t threadpriority_t; + +#define MAX_SEMAPHORE_COUNT ((semcount_t)(((unsigned long)((semcount_t)(-1))) >> 1)) +#define LOW_PRIORITY LOWPRIO +#define NORMAL_PRIORITY NORMALPRIO +#define HIGH_PRIORITY HIGHPRIO + +#define DECLARE_THREAD_STACK(name, sz) WORKING_AREA(name, sz) +#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) + +#if CH_KERNEL_MAJOR == 2 + typedef struct { + Semaphore sem; + semcount_t limit; + } gfxSem; + + typedef Mutex gfxMutex; + typedef Thread* gfxThreadHandle; +#elif CH_KERNEL_MAJOR == 3 + #undef DECLARE_THREAD_STACK + #define DECLARE_THREAD_STACK(a, b) THD_WORKING_AREA(a, b) + + typedef struct { + semaphore_t sem; + semcount_t limit; + } gfxSem; + + typedef mutex_t gfxMutex; + typedef thread_t* gfxThreadHandle; +#endif + + +/*===========================================================================*/ +/* Function declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +// First the kernel version specific ones +#if CH_KERNEL_MAJOR == 2 + #define gfxSystemTicks() chTimeNow() + #define gfxMutexInit(pmutex) chMtxInit(pmutex) + #define gfxMutexExit(pmutex) chMtxUnlock() + #define gfxExit() chSysHalt() +#elif CH_KERNEL_MAJOR == 3 + #define gfxSystemTicks() chVTGetSystemTimeX() + #define gfxMutexInit(pmutex) chMtxObjectInit(pmutex) + #define gfxMutexExit(pmutex) chMtxUnlock(pmutex) + #define gfxExit() osalSysHalt("gfx_exit") +#endif + +#define gfxHalt(msg) { chDbgPanic(msg); chSysHalt(); } +#define gfxAlloc(sz) chHeapAlloc(0, sz) +#define gfxFree(ptr) chHeapFree(ptr) +#define gfxYield() chThdYield() +#define gfxMillisecondsToTicks(ms) MS2ST(ms) +#define gfxSystemLock() chSysLock() +#define gfxSystemUnlock() chSysUnlock() +#define gfxMutexDestroy(pmutex) (void)pmutex +#define gfxMutexEnter(pmutex) chMtxLock(pmutex) +void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz); +void gfxSleepMilliseconds(delaytime_t ms); +void gfxSleepMicroseconds(delaytime_t ms); +void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit); +void gfxSemDestroy(gfxSem *psem); +bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); +bool_t gfxSemWaitI(gfxSem *psem); +void gfxSemSignal(gfxSem *psem); +void gfxSemSignalI(gfxSem *psem); +#define gfxSemCounterI(psem) ((psem)->sem.s_cnt) +#define gfxSemCounter(psem) ((psem)->sem.s_cnt) +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); +#define gfxThreadWait(thread) chThdWait(thread) +#define gfxThreadMe() chThdSelf() +#define gfxThreadClose(thread) (void)thread + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_OS_CHIBIOS */ +#endif /* _GOS_CHIBIOS_H */ diff --git a/src/gos/gos_ecos.c b/src/gos/gos_ecos.c new file mode 100644 index 00000000..16ce821b --- /dev/null +++ b/src/gos/gos_ecos.c @@ -0,0 +1,115 @@ +/* + * 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 + */ + +#include "gfx.h" + +#if GFX_USE_OS_ECOS + +void _gosInit(void) +{ + #if !GFX_NO_OS_INIT + #error "GOS: Operating System initialization for eCos is not yet implemented in uGFX. Please set GFX_NO_OS_INIT to TRUE in your gfxconf.h" + #else + #warning "GOS: Operating System initialization has been turned off. Make sure you call cyg_scheduler_start() before gfxInit() in your application!" + #endif +} + +void _gosDeinit(void) +{ + /* ToDo */ +} + +void gfxSleepMilliseconds(delaytime_t ms) +{ + switch(ms) { + case TIME_IMMEDIATE: cyg_thread_yield(); return; + case TIME_INFINITE: cyg_thread_suspend(cyg_thread_self()); return; + default: cyg_thread_delay(gfxMillisecondsToTicks(ms)); return; + } +} + +void gfxSleepMicroseconds(delaytime_t ms) +{ + switch(ms) { + case TIME_IMMEDIATE: return; + case TIME_INFINITE: cyg_thread_suspend(cyg_thread_self()); return; + default: cyg_thread_delay(gfxMillisecondsToTicks(ms/1000)); return; + } +} + +void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit) +{ + if (val > limit) + val = limit; + + psem->limit = limit; + cyg_semaphore_init(&psem->sem, val); +} + +void gfxSemDestroy(gfxSem *psem) +{ + cyg_semaphore_destroy(&psem->sem); +} + +bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) +{ + switch(ms) { + case TIME_IMMEDIATE: return cyg_semaphore_trywait(&psem->sem); + case TIME_INFINITE: return cyg_semaphore_wait(&psem->sem); + default: return cyg_semaphore_timed_wait(&psem->sem, gfxMillisecondsToTicks(ms)+cyg_current_time()); + } +} + +bool_t gfxSemWaitI(gfxSem *psem) +{ + return cyg_semaphore_trywait(&psem->sem); +} + +void gfxSemSignal(gfxSem *psem) +{ + if (psem->limit == MAX_SEMAPHORE_COUNT) + cyg_semaphore_post(&psem->sem); + else { + cyg_scheduler_lock(); + if (gfxSemCounterI(psem) < psem->limit) + cyg_semaphore_post(&psem->sem); + cyg_scheduler_unlock(); + } +} + +void gfxSemSignalI(gfxSem *psem) +{ + if (psem->limit == MAX_SEMAPHORE_COUNT || gfxSemCounterI(psem) < psem->limit) + cyg_semaphore_post(&psem->sem); +} + +semcount_t gfxSemCounterI(gfxSem *psem) { + semcount_t cnt; + + cyg_semaphore_peek(&psem->sem, &cnt); + return cnt; +} + +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) +{ + gfxThreadHandle th; + + if (!stackarea) { + if (!stacksz) stacksz = CYGNUM_HAL_STACK_SIZE_TYPICAL; + if (!(stackarea = gfxAlloc(stacksz+sizeof(cyg_thread)))) + return 0; + } + + if (!stacksz) + return 0; + + cyg_thread_create(prio, fn, param, "uGFX", (((cyg_thread *)stackarea)+1), stacksz, &th, (cyg_thread *)stackarea); + cyg_thread_resume(th); + return th; +} + +#endif /* GFX_USE_OS_ECOS */ diff --git a/src/gos/gos_ecos.h b/src/gos/gos_ecos.h new file mode 100644 index 00000000..be9037b6 --- /dev/null +++ b/src/gos/gos_ecos.h @@ -0,0 +1,106 @@ +/* + * 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 + */ + +#ifndef _GOS_ECOS_H +#define _GOS_ECOS_H + +#if GFX_USE_OS_ECOS + +#include +#include +#include + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +typedef cyg_bool_t bool_t; +typedef cyg_int8 int8_t; +typedef cyg_uint8 uint8_t; +typedef cyg_int16 int16_t; +typedef cyg_uint16 uint16_t; +typedef cyg_int32 int32_t; +typedef cyg_uint32 uint32_t; +typedef cyg_uint32 size_t; + +#define TRUE -1 +#define FALSE 0 +#define TIME_IMMEDIATE 0 +#define TIME_INFINITE 0xFFFFFFFF + +typedef cyg_ucount32 delaytime_t; +typedef cyg_tick_count_t systemticks_t; +typedef cyg_count32 semcount_t; +typedef void threadreturn_t; +typedef cyg_addrword_t threadpriority_t; +typedef cyg_handle_t gfxThreadHandle; + +#define MAX_SEMAPHORE_COUNT 0x7FFFFFFF +#define LOW_PRIORITY (CYGNUM_KERNEL_SCHED_PRIORITIES-2) +#define NORMAL_PRIORITY (CYGNUM_KERNEL_SCHED_PRIORITIES/2) +#define HIGH_PRIORITY 0 + +#define DECLARE_THREAD_STACK(name, sz) struct { cyg_thread t; unsigned char stk[sz]; } name[1] +#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(cyg_addrword_t param) + +typedef struct { + cyg_sem_t sem; + semcount_t limit; + } gfxSem; + +typedef cyg_mutex_t gfxMutex; + + +/*===========================================================================*/ +/* Function declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#define gfxSystemTicks() cyg_current_time() +#define gfxExit() exit(0) +#define gfxHalt(msg) exit(-1) +#define gfxYield() cyg_thread_yield() + +#define gfxMillisecondsToTicks(ms) (((ms)*(CYGNUM_HAL_RTC_DENOMINATOR*1000))/(CYGNUM_HAL_RTC_NUMERATOR/1000)) +void gfxSleepMilliseconds(delaytime_t ms); +void gfxSleepMicroseconds(delaytime_t ms); + +#define gfxAlloc(sz) malloc(sz) +#define gfxFree(ptr) free(ptr) +#define gfxRealloc(ptr, oldsz, newsz) realloc(ptr, newsz) + +#define gfxSystemLock() cyg_scheduler_lock() +#define gfxSystemUnlock() cyg_scheduler_unlock() + +#define gfxMutexInit(pmutex) cyg_mutex_init(pmutex) +#define gfxMutexExit(pmutex) cyg_mutex_unlock(pmutex) +#define gfxMutexDestroy(pmutex) cyg_mutex_destroy(pmutex) +#define gfxMutexEnter(pmutex) cyg_mutex_lock(pmutex) + +void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit); +void gfxSemDestroy(gfxSem *psem); +bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); +bool_t gfxSemWaitI(gfxSem *psem); +void gfxSemSignal(gfxSem *psem); +void gfxSemSignalI(gfxSem *psem); +semcount_t gfxSemCounterI(gfxSem *psem); +#define gfxSemCounter(psem) gfxSemCounterI(psem) + +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); +#define gfxThreadWait(thread) NOTIMPLEMENTED_YET +#define gfxThreadMe() cyg_thread_self() +#define gfxThreadClose(thread) (void)thread + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_OS_ECOS */ +#endif /* _GOS_ECOS_H */ diff --git a/src/gos/gos_freertos.c b/src/gos/gos_freertos.c new file mode 100644 index 00000000..dbdfd22e --- /dev/null +++ b/src/gos/gos_freertos.c @@ -0,0 +1,170 @@ +/* + * 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 + */ + +#include "gfx.h" +#include + +#if GFX_USE_OS_FREERTOS + +#if INCLUDE_vTaskDelay != 1 + #error "GOS: INCLUDE_vTaskDelay must be defined in FreeRTOSConfig.h" +#endif + +#if configUSE_MUTEXES != 1 + #error "GOS: configUSE_MUTEXES must be defined in FreeRTOSConfig.h" +#endif + +#if configUSE_COUNTING_SEMAPHORES != 1 + #error "GOS: configUSE_COUNTING_SEMAPHORES must be defined in FreeRTOSConfig.h" +#endif + +void _gosInit(void) +{ + #if !GFX_NO_OS_INIT + #error "GOS: Operating System initialization for FreeRTOS is not yet implemented in uGFX. Please set GFX_NO_OS_INIT to TRUE in your gfxconf.h" + #else + #warning "GOS: Operating System initialization has been turned off. Make sure you call vTaskStartScheduler() before gfxInit() in your application!" + #endif +} + +void _gosDeinit(void) +{ +} + +void* gfxRealloc(void *ptr, size_t oldsz, size_t newsz) +{ + void *np; + + if (newsz <= oldsz) + return ptr; + + np = gfxAlloc(newsz); + if (!np) + return 0; + + if (oldsz) { + memcpy(np, ptr, oldsz); + vPortFree(ptr); + } + + return np; +} + +void gfxSleepMilliseconds(delaytime_t ms) +{ + const portTickType ticks = ms / portTICK_PERIOD_MS; + vTaskDelay(ticks); +} + +void gfxSleepMicroseconds(delaytime_t ms) +{ + const portTickType ticks = (ms / 1000) / portTICK_PERIOD_MS; + + // delay milli seconds + vTaskDelay(ticks); + + // microsecond resolution delay is not supported in FreeRTOS + // vUsDelay(ms%1000); +} + +portTickType MS2ST(portTickType ms) +{ + return (ms / portTICK_PERIOD_MS); +} + +void gfxMutexInit(xSemaphoreHandle *s) +{ + *s = xSemaphoreCreateMutex(); + #if GFX_FREERTOS_USE_TRACE + vTraceSetMutexName(*s,"uGFXMutex"); // for FreeRTOS+Trace debug + #endif +} + +void gfxSemInit(gfxSem* psem, semcount_t val, semcount_t limit) +{ + if (val > limit) + val = limit; + + psem->counter = val; + psem->limit = limit; + psem->sem = xSemaphoreCreateCounting(limit,val); + + #if GFX_FREERTOS_USE_TRACE + vTraceSetSemaphoreName(psem->sem, "uGFXSema"); // for FreeRTOS+Trace debug + #endif +} + +void gfxSemDestroy(gfxSem* psem) +{ + vSemaphoreDelete(psem->sem); +} + +bool_t gfxSemWait(gfxSem* psem, delaytime_t ms) +{ + psem->counter--; + + if (xSemaphoreTake(psem->sem, MS2ST(ms)) == pdPASS) + return TRUE; + + psem->counter++; + + return FALSE; +} + +bool_t gfxSemWaitI(gfxSem* psem) +{ + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + psem->counter--; + + if (xSemaphoreTakeFromISR(psem->sem,&xHigherPriorityTaskWoken) == pdTRUE) + return TRUE; + + psem->counter++; + + return FALSE; +} + +void gfxSemSignal(gfxSem* psem) +{ + taskENTER_CRITICAL(); + + if (psem->counter < psem->limit) { + psem->counter++; + xSemaphoreGive(psem->sem); + } + + taskYIELD(); + taskEXIT_CRITICAL(); +} + +void gfxSemSignalI(gfxSem* psem) +{ + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + if (psem->counter < psem->limit) { + psem->counter++; + xSemaphoreGiveFromISR(psem->sem,&xHigherPriorityTaskWoken); + } +} + +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) +{ + xTaskHandle task = NULL; + stacksz = (size_t)stackarea; + + if (stacksz < configMINIMAL_STACK_SIZE) + stacksz = configMINIMAL_STACK_SIZE; + + if (xTaskCreate(fn, "uGFX_TASK", stacksz, param, prio, &task )!= pdPASS) { + for (;;); + } + + return task; +} + +#endif /* GFX_USE_OS_FREERTOS */ diff --git a/src/gos/gos_freertos.h b/src/gos/gos_freertos.h new file mode 100644 index 00000000..57f9b8bd --- /dev/null +++ b/src/gos/gos_freertos.h @@ -0,0 +1,122 @@ +/* + * 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/gfx_freertos.h + * @brief GOS - Operating System Support header file for FreeRTOS. + */ + +#ifndef _GOS_FREERTOS_H +#define _GOS_FREERTOS_H + +#if GFX_USE_OS_FREERTOS + +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "semphr.h" +#include "task.h" + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +/* Additional types are required when FreeRTOS 7.x is used */ +#if !defined(tskKERNEL_VERSION_MAJOR) && !tskKERNEL_VERSION_MAJOR == 8 + typedef signed char int8_t + typedef unsigned char uint8_t + typedef signed int int16_t + typedef unsigned int uint16_t + typedef signed long int int32_t + typedef unsigned long int uint32_t + typedef signed long long int int64_t + typedef unsigned long long int uint64_t +#endif + +/** + * bool_t, + * int8_t, uint8_t, + * int16_t, uint16_t, + * int32_t, uint32_t, + * size_t + * TRUE, FALSE + * are already defined by FreeRTOS + */ +#define TIME_IMMEDIATE 0 +#define TIME_INFINITE ((delaytime_t)-1) +typedef int8_t bool_t; +typedef uint32_t delaytime_t; +typedef portTickType systemticks_t; +typedef int32_t semcount_t; +typedef void threadreturn_t; +typedef portBASE_TYPE threadpriority_t; + +#define MAX_SEMAPHORE_COUNT ((semcount_t)(((unsigned long)((semcount_t)(-1))) >> 1)) +#define LOW_PRIORITY 0 +#define NORMAL_PRIORITY configMAX_PRIORITIES/2 +#define HIGH_PRIORITY configMAX_PRIORITIES-1 + +/* FreeRTOS will allocate the stack when creating the thread, so pass the size instead of a working area */ +#define DECLARE_THREAD_STACK(name, sz) size_t *name = (size_t *)sz +#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) +portTickType MS2ST(portTickType ms); + +typedef struct { + xSemaphoreHandle sem; + semcount_t limit; + semcount_t counter; +} gfxSem; + +typedef xSemaphoreHandle gfxMutex; +typedef xTaskHandle* gfxThreadHandle; + +/*===========================================================================*/ +/* Function declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#define gfxHalt(msg) {} +#define gfxExit() {} +#define gfxAlloc(sz) pvPortMalloc(sz) +#define gfxFree(ptr) vPortFree(ptr) +#define gfxYield() taskYIELD() +#define gfxSystemTicks() xTaskGetTickCount() +#define gfxMillisecondsToTicks(ms) MS2ST(ms) +#define gfxSystemLock() {} +#define gfxSystemUnlock() {} + +void gfxMutexInit(xSemaphoreHandle* s); +#define gfxMutexDestroy(pmutex) vSemaphoreDelete(*pmutex) +#define gfxMutexEnter(pmutex) xSemaphoreTake(*pmutex,portMAX_DELAY) +#define gfxMutexExit(pmutex) xSemaphoreGive(*pmutex) + +void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz); +void gfxSleepMilliseconds(delaytime_t ms); +void gfxSleepMicroseconds(delaytime_t ms); + +void gfxSemInit(gfxSem* psem, semcount_t val, semcount_t limit); +void gfxSemDestroy(gfxSem* psem); +bool_t gfxSemWait(gfxSem* psem, delaytime_t ms); +bool_t gfxSemWaitI(gfxSem* psem); +void gfxSemSignal(gfxSem* psem); +void gfxSemSignalI(gfxSem* psem); +#define gfxSemCounterI(psem) ((psem)->counter) +#define gfxSemCounter(psem) ((psem)->counter) +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); + +#define gfxThreadWait(thread) {} // never used, not imlpemented +#define gfxThreadMe() {} // never used, not implemented +#define gfxThreadClose(thread) {} + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_OS_FREERTOS */ +#endif /* _GOS_CHIBIOS_H */ diff --git a/src/gos/gos_linux.c b/src/gos/gos_linux.c new file mode 100644 index 00000000..e6fbe26c --- /dev/null +++ b/src/gos/gos_linux.c @@ -0,0 +1,248 @@ +/* + * 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 + */ + +#include "gfx.h" + +#if GFX_USE_OS_LINUX + +// Linux seems to have deprecated pthread_yield() and now says to use sched_yield() +#define USE_SCHED_NOT_PTHREAD_YIELD TRUE + +#include +#include +#include +#if USE_SCHED_NOT_PTHREAD_YIELD + #include + #define linuxyield() sched_yield() +#else + #define linuxyield() pthread_yield() +#endif + +static gfxMutex SystemMutex; + +void _gosInit(void) +{ + /* No initialization of the operating system itself is needed */ + gfxMutexInit(&SystemMutex); +} + +void _gosDeinit(void) +{ + /* ToDo */ +} + +void gfxSystemLock(void) { + gfxMutexEnter(&SystemMutex); +} + +void gfxSystemUnlock(void) { + gfxMutexExit(&SystemMutex); +} + +void gfxYield(void) { + linuxyield(); +} + +void gfxHalt(const char *msg) { + if (msg) + fprintf(stderr, "%s\n", msg); + exit(1); +} + +void gfxSleepMilliseconds(delaytime_t ms) { + struct timespec ts; + + switch(ms) { + case TIME_IMMEDIATE: + linuxyield(); + return; + + case TIME_INFINITE: + while(1) + sleep(60); + return; + + default: + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000000; + nanosleep(&ts, 0); + return; + } +} + +void gfxSleepMicroseconds(delaytime_t us) { + struct timespec ts; + + switch(us) { + case TIME_IMMEDIATE: + linuxyield(); + return; + + case TIME_INFINITE: + while(1) + sleep(60); + return; + + default: + ts.tv_sec = us / 1000000; + ts.tv_nsec = (us % 1000000) * 1000; + nanosleep(&ts, 0); + return; + } +} + +systemticks_t gfxSystemTicks(void) { + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; +} + +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { + gfxThreadHandle th; + (void) stackarea; + (void) stacksz; + (void) prio; + + // Implementing priority with pthreads is a rats nest that is also pthreads implementation dependent. + // Only some pthreads schedulers support it, some implementations use the operating system process priority mechanisms. + // Even those that do support it can have different ranges of priority and "normal" priority is an undefined concept. + // Across different UNIX style operating systems things can be very different (let alone OS's such as Windows). + // Even just Linux changes the way priority works with different kernel schedulers and across kernel versions. + // For these reasons we ignore the priority. + + if (pthread_create(&th, 0, fn, param)) + return 0; + + return th; +} + +threadreturn_t gfxThreadWait(gfxThreadHandle thread) { + threadreturn_t retval; + + if (pthread_join(thread, &retval)) + return 0; + + return retval; +} + +#if GFX_USE_POSIX_SEMAPHORES + void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { + pSem->max = limit; + sem_init(&pSem->sem, 0, val); + } + void gfxSemDestroy(gfxSem *pSem) { + sem_destroy(&pSem->sem); + } + bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { + switch (ms) { + case TIME_INFINITE: + return sem_wait(&pSem->sem) ? FALSE : TRUE; + + case TIME_IMMEDIATE: + return sem_trywait(&pSem->sem) ? FALSE : TRUE; + + default: + { + struct timespec tm; + + clock_gettime(CLOCK_REALTIME, &tm); + tm.tv_sec += ms / 1000; + tm.tv_nsec += (ms % 1000) * 1000000; + return sem_timedwait(&pSem->sem, &tm) ? FALSE : TRUE; + } + } + } + void gfxSemSignal(gfxSem *pSem) { + if (gfxSemCounter(pSem) < pSem->max) + sem_post(&pSem->sem); + } + semcount_t gfxSemCounter(gfxSem *pSem) { + int res; + + res = 0; + sem_getvalue(&pSem->sem, &res); + return res; + } +#else + void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { + pthread_mutex_init(&pSem->mtx, 0); + pthread_cond_init(&pSem->cond, 0); + pthread_mutex_lock(&pSem->mtx); + pSem->cnt = val; + pSem->max = limit; + pthread_mutex_unlock(&pSem->mtx); + } + void gfxSemDestroy(gfxSem *pSem) { + pthread_mutex_destroy(&pSem->mtx); + pthread_cond_destroy(&pSem->cond); + } + bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { + pthread_mutex_lock(&pSem->mtx); + + switch (ms) { + case TIME_INFINITE: + while (!pSem->cnt) + pthread_cond_wait(&pSem->cond, &pSem->mtx); + break; + + case TIME_IMMEDIATE: + if (!pSem->cnt) { + pthread_mutex_unlock(&pSem->mtx); + return FALSE; + } + break; + + default: + { + struct timespec tm; + + clock_gettime(CLOCK_REALTIME, &tm); + tm.tv_sec += ms / 1000; + tm.tv_nsec += (ms % 1000) * 1000000; + while (!pSem->cnt) { + // We used to test the return value for ETIMEDOUT. This doesn't + // work in some current pthread libraries which return -1 instead + // and set errno to ETIMEDOUT. So, we will return FALSE on any error + // including a ETIMEDOUT. + if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm)) { + pthread_mutex_unlock(&pSem->mtx); + return FALSE; + } + } + } + break; + } + + pSem->cnt--; + pthread_mutex_unlock(&pSem->mtx); + return TRUE; + } + void gfxSemSignal(gfxSem *pSem) { + pthread_mutex_lock(&pSem->mtx); + + if (pSem->cnt < pSem->max) { + pSem->cnt++; + pthread_cond_signal(&pSem->cond); + } + + pthread_mutex_unlock(&pSem->mtx); + } + semcount_t gfxSemCounter(gfxSem *pSem) { + semcount_t res; + + // The locking is really only required if obtaining the count is a divisible operation + // which it might be on a 8/16 bit processor with a 32 bit semaphore count. + pthread_mutex_lock(&pSem->mtx); + res = pSem->cnt; + pthread_mutex_unlock(&pSem->mtx); + + return res; + } +#endif // GFX_USE_POSIX_SEMAPHORES + +#endif /* GFX_USE_OS_LINUX */ diff --git a/src/gos/gos_linux.h b/src/gos/gos_linux.h new file mode 100644 index 00000000..39cfbc85 --- /dev/null +++ b/src/gos/gos_linux.h @@ -0,0 +1,107 @@ +/* + * 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 + */ + +#ifndef _GOS_LINUX_H +#define _GOS_LINUX_H + +#if GFX_USE_OS_LINUX + +// We don't put this in the general sys_options.h as it is Linux specific. +#ifndef GFX_USE_POSIX_SEMAPHORES + #define GFX_USE_POSIX_SEMAPHORES TRUE +#endif + +#include +#include +#include +#include + +#if GFX_USE_POSIX_SEMAPHORES + #include +#endif + +/* Already defined int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, size_t */ + +typedef int8_t bool_t; +typedef unsigned long systemticks_t; +typedef void * threadreturn_t; +typedef unsigned long delaytime_t; +typedef pthread_t gfxThreadHandle; +typedef int threadpriority_t; +typedef uint32_t semcount_t; +typedef pthread_mutex_t gfxMutex; + +#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) +#define DECLARE_THREAD_STACK(name, sz) uint8_t name[0]; + +#define gfxExit() exit(0) +#define gfxAlloc(sz) malloc(sz) +#define gfxRealloc(p,osz,nsz) realloc(p, nsz) +#define gfxFree(ptr) free(ptr) +#define gfxMillisecondsToTicks(ms) (ms) +#define gfxThreadMe() pthread_self() +#define gfxThreadClose(th) (void)th +#define gfxMutexInit(pmtx) pthread_mutex_init(pmtx, 0) +#define gfxMutexDestroy(pmtx) pthread_mutex_destroy(pmtx) +#define gfxMutexEnter(pmtx) pthread_mutex_lock(pmtx) +#define gfxMutexExit(pmtx) pthread_mutex_unlock(pmtx) +#define gfxSemWaitI(psem) gfxSemWait(psem, TIME_IMMEDIATE) +#define gfxSemSignalI(psem) gfxSemSignal(psem) + +#define TIME_IMMEDIATE 0 +#define TIME_INFINITE ((delaytime_t)-1) +#define MAX_SEMAPHORE_COUNT ((semcount_t)-1) +#define LOW_PRIORITY 10 +#define NORMAL_PRIORITY 0 +#define HIGH_PRIORITY -10 + +#if GFX_USE_POSIX_SEMAPHORES + typedef struct gfxSem { + sem_t sem; + semcount_t max; + } gfxSem; + #define gfxSemCounterI(psem) gfxSemCounter(psem) +#else + typedef struct gfxSem { + pthread_mutex_t mtx; + pthread_cond_t cond; + semcount_t cnt; + semcount_t max; + } gfxSem; + #define gfxSemCounterI(psem) ((psem)->cnt) +#endif + +/*===========================================================================*/ +/* Function declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +void gfxYield(void); +void gfxHalt(const char *msg); +void gfxSleepMilliseconds(delaytime_t ms); +void gfxSleepMicroseconds(delaytime_t ms); +systemticks_t gfxSystemTicks(void); +void gfxSystemLock(void); +void gfxSystemUnlock(void); +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); +semcount_t gfxSemCounter(gfxSem *pSem); +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); +threadreturn_t gfxThreadWait(gfxThreadHandle thread); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_OS_LINUX */ + +#endif /* _GOS_LINUX_H */ diff --git a/src/gos/gos_osx.c b/src/gos/gos_osx.c new file mode 100644 index 00000000..f21b8a75 --- /dev/null +++ b/src/gos/gos_osx.c @@ -0,0 +1,187 @@ +/* + * 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 + */ + +#include "gfx.h" + +#if GFX_USE_OS_OSX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static gfxMutex SystemMutex; + +void _gosInit(void) +{ + /* No initialization of the operating system itself is needed */ + gfxMutexInit(&SystemMutex); +} + +void _gosDeinit(void) +{ + /* ToDo */ +} + +void gfxSystemLock(void) { + gfxMutexEnter(&SystemMutex); +} + +void gfxSystemUnlock(void) { + gfxMutexExit(&SystemMutex); +} + +void gfxHalt(const char *msg) { + if (msg) + fprintf(stderr, "%s\n", msg); + exit(1); +} + +void gfxSleepMilliseconds(delaytime_t ms) { + struct timespec ts; + + switch(ms) { + case TIME_IMMEDIATE: gfxYield(); return; + case TIME_INFINITE: while(1) sleep(60); return; + default: + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000000; + nanosleep(&ts, 0); + return; + } +} + +void gfxSleepMicroseconds(delaytime_t us) { + struct timespec ts; + + switch(us) { + case TIME_IMMEDIATE: gfxYield(); return; + case TIME_INFINITE: while(1) sleep(60); return; + default: + ts.tv_sec = us / 1000000; + ts.tv_nsec = (us % 1000000) * 1000; + nanosleep(&ts, 0); + return; + } +} + +systemticks_t gfxSystemTicks(void) { + mach_timespec_t ts; + clock_serv_t cclock; + + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, &ts); + mach_port_deallocate(mach_task_self(), cclock); + + return ts.tv_sec * 1000UL + ts.tv_nsec / 1000000; +} + +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { + gfxThreadHandle th; + (void) stackarea; + (void) stacksz; + (void) prio; + + // Implementing priority with pthreads is a rats nest that is also pthreads implementation dependent. + // Only some pthreads schedulers support it, some implementations use the operating system process priority mechanisms. + // Even those that do support it can have different ranges of priority and "normal" priority is an undefined concept. + // Across different UNIX style operating systems things can be very different (let alone OS's such as Windows). + // Even just Linux changes the way priority works with different kernel schedulers and across kernel versions. + // For these reasons we ignore the priority. + + if (pthread_create(&th, 0, fn, param)) + return 0; + return th; +} + +threadreturn_t gfxThreadWait(gfxThreadHandle thread) { + threadreturn_t retval; + + if (pthread_join(thread, &retval)) + return 0; + return retval; +} + +void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { + pthread_mutex_init(&pSem->mtx, 0); + pthread_cond_init(&pSem->cond, 0); + pthread_mutex_lock(&pSem->mtx); + pSem->cnt = val; + pSem->max = limit; + pthread_mutex_unlock(&pSem->mtx); +} + +void gfxSemDestroy(gfxSem *pSem) { + pthread_mutex_destroy(&pSem->mtx); + pthread_cond_destroy(&pSem->cond); +} + +bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { + pthread_mutex_lock(&pSem->mtx); + switch (ms) { + case TIME_INFINITE: + while (!pSem->cnt) + pthread_cond_wait(&pSem->cond, &pSem->mtx); + break; + case TIME_IMMEDIATE: + if (!pSem->cnt) { + pthread_mutex_unlock(&pSem->mtx); + return FALSE; + } + break; + default: + { + struct timeval now; + struct timespec tm; + + gettimeofday(&now, 0); + tm.tv_sec = now.tv_sec + ms / 1000; + tm.tv_nsec = now.tv_usec * 1000 + (ms % 1000) * 1000000; + while (!pSem->cnt) { + // We used to test the return value for ETIMEDOUT. This doesn't + // work in some current pthread libraries which return -1 instead + // and set errno to ETIMEDOUT. So, we will return FALSE on any error + // including a ETIMEDOUT. + if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm)) { + pthread_mutex_unlock(&pSem->mtx); + return FALSE; + } + } + } + break; + } + pSem->cnt--; + pthread_mutex_unlock(&pSem->mtx); + return TRUE; +} + +void gfxSemSignal(gfxSem *pSem) { + pthread_mutex_lock(&pSem->mtx); + if (pSem->cnt < pSem->max) { + pSem->cnt++; + pthread_cond_signal(&pSem->cond); + } + pthread_mutex_unlock(&pSem->mtx); +} + +semcount_t gfxSemCounter(gfxSem *pSem) { + semcount_t res; + + // The locking is really only required if obtaining the count is a divisible operation + // which it might be on a 8/16 bit processor with a 32 bit semaphore count. + pthread_mutex_lock(&pSem->mtx); + res = pSem->cnt; + pthread_mutex_unlock(&pSem->mtx); + return res; +} + +#endif /* GFX_USE_OS_OSX */ diff --git a/src/gos/gos_osx.h b/src/gos/gos_osx.h new file mode 100644 index 00000000..635a8934 --- /dev/null +++ b/src/gos/gos_osx.h @@ -0,0 +1,88 @@ +/* + * 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 + */ + +#ifndef _GOS_OSX_H +#define _GOS_OSX_H + +#if GFX_USE_OS_OSX + +#include +#include +#include + +/* Already defined int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, size_t */ + +typedef int8_t bool_t; +typedef unsigned long systemticks_t; +typedef void * threadreturn_t; +typedef unsigned long delaytime_t; +typedef pthread_t gfxThreadHandle; +typedef int threadpriority_t; +typedef uint32_t semcount_t; +typedef pthread_mutex_t gfxMutex; + +#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) +#define DECLARE_THREAD_STACK(name, sz) uint8_t name[0]; + +#define gfxExit() exit(0) +#define gfxAlloc(sz) malloc(sz) +#define gfxRealloc(p,osz,nsz) realloc(p, nsz) +#define gfxFree(ptr) free(ptr) +#define gfxMillisecondsToTicks(ms) (ms) +#define gfxYield() sched_yield() +#define gfxThreadMe() pthread_self() +#define gfxThreadClose(th) (void)th +#define gfxMutexInit(pmtx) pthread_mutex_init(pmtx, 0) +#define gfxMutexDestroy(pmtx) pthread_mutex_destroy(pmtx) +#define gfxMutexEnter(pmtx) pthread_mutex_lock(pmtx) +#define gfxMutexExit(pmtx) pthread_mutex_unlock(pmtx) +#define gfxSemWaitI(psem) gfxSemWait(psem, TIME_IMMEDIATE) +#define gfxSemSignalI(psem) gfxSemSignal(psem) +#define gfxSemCounterI(pSem) ((pSem)->cnt) + +#define TIME_IMMEDIATE 0 +#define TIME_INFINITE ((delaytime_t)-1) +#define MAX_SEMAPHORE_COUNT ((semcount_t)-1) +#define LOW_PRIORITY 10 +#define NORMAL_PRIORITY 0 +#define HIGH_PRIORITY -10 + +typedef struct gfxSem { + pthread_mutex_t mtx; + pthread_cond_t cond; + semcount_t cnt; + semcount_t max; +} gfxSem; + +/*===========================================================================*/ +/* Function declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +void gfxHalt(const char *msg); +void gfxSleepMilliseconds(delaytime_t ms); +void gfxSleepMicroseconds(delaytime_t ms); +systemticks_t gfxSystemTicks(void); +void gfxSystemLock(void); +void gfxSystemUnlock(void); +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); +semcount_t gfxSemCounter(gfxSem *pSem); +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); +threadreturn_t gfxThreadWait(gfxThreadHandle thread); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_OS_OSX */ +#endif /* _GOS_OSX_H */ diff --git a/src/gos/gos_raw32.c b/src/gos/gos_raw32.c new file mode 100644 index 00000000..22c753aa --- /dev/null +++ b/src/gos/gos_raw32.c @@ -0,0 +1,739 @@ +/* + * 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 + */ + +#include "gfx.h" + +#if GFX_USE_OS_RAW32 + +#include // Prototype for memcpy() + +#if GOS_RAW_HEAP_SIZE != 0 + static void _gosHeapInit(void); +#else + #define _gosHeapInit() +#endif +static void _gosThreadsInit(void); + +/********************************************************* + * Initialise + *********************************************************/ + +void _gosInit(void) +{ + /* No initialization of the operating system itself is needed as there isn't one. + * On the other hand the C runtime should still already be initialized before + * getting here! + */ + #warning "GOS: Raw32 - Make sure you initialize your hardware and the C runtime before calling gfxInit() in your application!" + + // Set up the heap allocator + _gosHeapInit(); + + // Start the scheduler + _gosThreadsInit(); +} + +void _gosDeinit(void) +{ + /* ToDo */ +} + +/********************************************************* + * For WIn32 emulation - automatically add the tick functions + * the user would normally have to provide for bare metal. + *********************************************************/ + +#if defined(WIN32) + #undef Red + #undef Green + #undef Blue + #define WIN32_LEAN_AND_MEAN + #include + #include + systemticks_t gfxSystemTicks(void) { return GetTickCount(); } + systemticks_t gfxMillisecondsToTicks(delaytime_t ms) { return ms; } +#endif + +/********************************************************* + * Exit everything functions + *********************************************************/ + +void gfxHalt(const char *msg) { + #if defined(WIN32) + fprintf(stderr, "%s\n", msg); + ExitProcess(1); + #else + volatile uint32_t dummy; + (void) msg; + + while(1) + dummy++; + #endif +} + +void gfxExit(void) { + #if defined(WIN32) + ExitProcess(0); + #else + volatile uint32_t dummy; + + while(1) + dummy++; + #endif +} + +/********************************************************* + * Head allocation functions + *********************************************************/ + +#if GOS_RAW_HEAP_SIZE == 0 + #include // Prototype for malloc(), realloc() and free() + + void *gfxAlloc(size_t sz) { + return malloc(sz); + } + + void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz) { + (void) oldsz; + return realloc(ptr, newsz); + } + + void gfxFree(void *ptr) { + free(ptr); + } + +#else + + // Slot structure - user memory follows + typedef struct memslot { + struct memslot *next; // The next memslot + size_t sz; // Includes the size of this memslot. + } memslot; + + // Free Slot - immediately follows the memslot structure + typedef struct freeslot { + memslot *nextfree; // The next free slot + } freeslot; + + #define GetSlotSize(sz) ((((sz) + (sizeof(freeslot) - 1)) & ~(sizeof(freeslot) - 1)) + sizeof(memslot)) + #define NextFree(pslot) ((freeslot *)Slot2Ptr(pslot))->nextfree + #define Ptr2Slot(p) ((memslot *)(p) - 1) + #define Slot2Ptr(pslot) ((pslot)+1) + + static memslot * firstSlot; + static memslot * lastSlot; + static memslot * freeSlots; + static char heap[GOS_RAW_HEAP_SIZE]; + + static void _gosHeapInit(void) { + lastSlot = 0; + gfxAddHeapBlock(heap, GOS_RAW_HEAP_SIZE); + } + + void gfxAddHeapBlock(void *ptr, size_t sz) { + if (sz < sizeof(memslot)+sizeof(freeslot)) + return; + + if (lastSlot) + lastSlot->next = (memslot *)ptr; + else + firstSlot = lastSlot = freeSlots = (memslot *)ptr; + + lastSlot->next = 0; + lastSlot->sz = sz; + NextFree(lastSlot) = 0; + } + + void *gfxAlloc(size_t sz) { + register memslot *prev, *p, *new; + + if (!sz) return 0; + sz = GetSlotSize(sz); + for (prev = 0, p = freeSlots; p != 0; prev = p, p = NextFree(p)) { + // Loop till we have a block big enough + if (p->sz < sz) + continue; + // Can we save some memory by splitting this block? + if (p->sz >= sz + sizeof(memslot)+sizeof(freeslot)) { + new = (memslot *)((char *)p + sz); + new->next = p->next; + p->next = new; + new->sz = p->sz - sz; + p->sz = sz; + if (lastSlot == p) + lastSlot = new; + NextFree(new) = NextFree(p); + NextFree(p) = new; + } + // Remove it from the free list + if (prev) + NextFree(prev) = NextFree(p); + else + freeSlots = NextFree(p); + // Return the result found + return Slot2Ptr(p); + } + // No slots large enough + return 0; + } + + void *gfxRealloc(void *ptr, size_t oldsz, size_t sz) { + register memslot *prev, *p, *new; + (void) oldsz; + + if (!ptr) + return gfxAlloc(sz); + if (!sz) { + gfxFree(ptr); + return 0; + } + + p = Ptr2Slot(ptr); + sz = GetSlotSize(sz); + + // If the next slot is free (and contiguous) merge it into this one + if ((char *)p + p->sz == (char *)p->next) { + for (prev = 0, new = freeSlots; new != 0; prev = new, new = NextFree(new)) { + if (new == p->next) { + p->next = new->next; + p->sz += new->sz; + if (prev) + NextFree(prev) = NextFree(new); + else + freeSlots = NextFree(new); + if (lastSlot == new) + lastSlot = p; + break; + } + } + } + + // If this block is large enough we are nearly done + if (sz < p->sz) { + // Can we save some memory by splitting this block? + if (p->sz >= sz + sizeof(memslot)+sizeof(freeslot)) { + new = (memslot *)((char *)p + sz); + new->next = p->next; + p->next = new; + new->sz = p->sz - sz; + p->sz = sz; + if (lastSlot == p) + lastSlot = new; + NextFree(new) = freeSlots; + freeSlots = new; + } + return Slot2Ptr(p); + } + + // We need to do this the hard way + if ((new = gfxAlloc(sz))) + return 0; + memcpy(new, ptr, p->sz - sizeof(memslot)); + gfxFree(ptr); + return new; + } + + void gfxFree(void *ptr) { + register memslot *prev, *p, *new; + + if (!ptr) + return; + + p = Ptr2Slot(ptr); + + // If the next slot is free (and contiguous) merge it into this one + if ((char *)p + p->sz == (char *)p->next) { + for (prev = 0, new = freeSlots; new != 0; prev = new, new = NextFree(new)) { + if (new == p->next) { + p->next = new->next; + p->sz += new->sz; + if (prev) + NextFree(prev) = NextFree(new); + else + freeSlots = NextFree(new); + if (lastSlot == new) + lastSlot = p; + break; + } + } + } + + // Add it into the free chain + NextFree(p) = freeSlots; + freeSlots = p; + } +#endif + +/********************************************************* + * Semaphores and critical region functions + *********************************************************/ + +#if !defined(INTERRUPTS_OFF) || !defined(INTERRUPTS_ON) + #define INTERRUPTS_OFF() + #define INTERRUPTS_ON() +#endif + +void gfxSystemLock(void) { + INTERRUPTS_OFF(); +} + +void gfxSystemUnlock(void) { + INTERRUPTS_ON(); +} + +void gfxMutexInit(gfxMutex *pmutex) { + pmutex[0] = 0; +} + +void gfxMutexEnter(gfxMutex *pmutex) { + INTERRUPTS_OFF(); + while (pmutex[0]) { + INTERRUPTS_ON(); + gfxYield(); + INTERRUPTS_OFF(); + } + pmutex[0] = 1; + INTERRUPTS_ON(); +} + +void gfxMutexExit(gfxMutex *pmutex) { + pmutex[0] = 0; +} + +void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit) { + psem->cnt = val; + psem->limit = limit; +} + +bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) { + systemticks_t starttm, delay; + + // Convert our delay to ticks + switch (ms) { + case TIME_IMMEDIATE: + delay = TIME_IMMEDIATE; + break; + case TIME_INFINITE: + delay = TIME_INFINITE; + break; + default: + delay = gfxMillisecondsToTicks(ms); + if (!delay) delay = 1; + starttm = gfxSystemTicks(); + } + + INTERRUPTS_OFF(); + while (psem->cnt <= 0) { + INTERRUPTS_ON(); + // Check if we have exceeded the defined delay + switch (delay) { + case TIME_IMMEDIATE: + return FALSE; + case TIME_INFINITE: + break; + default: + if (gfxSystemTicks() - starttm >= delay) + return FALSE; + break; + } + gfxYield(); + INTERRUPTS_OFF(); + } + psem->cnt--; + INTERRUPTS_ON(); + return TRUE; +} + +bool_t gfxSemWaitI(gfxSem *psem) { + if (psem->cnt <= 0) + return FALSE; + psem->cnt--; + return TRUE; +} + +void gfxSemSignal(gfxSem *psem) { + INTERRUPTS_OFF(); + gfxSemSignalI(psem); + INTERRUPTS_ON(); +} + +void gfxSemSignalI(gfxSem *psem) { + if (psem->cnt < psem->limit) + psem->cnt++; +} + +/********************************************************* + * Sleep functions + *********************************************************/ + +void gfxSleepMilliseconds(delaytime_t ms) { + systemticks_t starttm, delay; + + // Safety first + switch (ms) { + case TIME_IMMEDIATE: + return; + case TIME_INFINITE: + while(1) + gfxYield(); + return; + } + + // Convert our delay to ticks + delay = gfxMillisecondsToTicks(ms); + starttm = gfxSystemTicks(); + + do { + gfxYield(); + } while (gfxSystemTicks() - starttm < delay); +} + +void gfxSleepMicroseconds(delaytime_t ms) { + systemticks_t starttm, delay; + + // Safety first + switch (ms) { + case TIME_IMMEDIATE: + return; + case TIME_INFINITE: + while(1) + gfxYield(); + return; + } + + // Convert our delay to ticks + delay = gfxMillisecondsToTicks(ms/1000); + starttm = gfxSystemTicks(); + + do { + gfxYield(); + } while (gfxSystemTicks() - starttm < delay); +} + +/********************************************************* + * Threading functions + *********************************************************/ + +/** + * There are some compilers we know how they store the jmpbuf. For those + * we can use the constant macro definitions. For others we have to "auto-detect". + * Auto-detection is hairy and there is no guarantee it will work on all architectures. + * For those it doesn't - read the compiler manuals and the library source code to + * work out the correct macro values. + * You can use the debugger to work out the values for your compiler and put them here. + * Defining these macros as constant values makes the system behaviour guaranteed but also + * makes your code compiler and cpu architecture dependant. + */ +#if 0 + // Define your compiler constant values here. + // These example values are for mingw32 compiler (x86). + #define AUTO_DETECT_MASK FALSE + #define STACK_DIR_UP FALSE + #define MASK1 0x00000011 + #define MASK2 0x00000000 + #define STACK_BASE 9 +#else + #define AUTO_DETECT_MASK TRUE + #define STACK_DIR_UP stackdirup // TRUE if the stack grow up instead of down + #define MASK1 jmpmask1 // The 1st mask of jmp_buf elements that need relocation + #define MASK2 jmpmask2 // The 2nd mask of jmp_buf elements that need relocation + #define STACK_BASE stackbase // The base of the stack frame relative to the local variables + static bool_t stackdirup; + static uint32_t jmpmask1; + static uint32_t jmpmask2; + static size_t stackbase; +#endif + +#include /* jmp_buf, setjmp(), longjmp() */ + +/** + * Some compilers define a _setjmp() and a setjmp(). + * The difference between them is that setjmp() saves the signal masks. + * That is of no use to us so prefer to use the _setjmp() methods. + * If they don't exist compile them to be the standard setjmp() function. + * Similarly for longjmp(). + */ +#ifndef setjmp + #ifndef _setjmp + #define _setjmp setjmp + #endif +#endif +#ifndef longjmp + #ifndef _longjmp + #define _longjmp longjmp + #endif +#endif + +typedef struct thread { + struct thread * next; // Next thread + int flags; // Flags + #define FLG_THD_ALLOC 0x0001 + #define FLG_THD_MAIN 0x0002 + #define FLG_THD_DEAD 0x0004 + #define FLG_THD_WAIT 0x0008 + size_t size; // Size of the thread stack (including this structure) + threadreturn_t (*fn)(void *param); // Thread function + void * param; // Parameter for the thread function + jmp_buf cxt; // The current thread context. +} thread; + +typedef struct threadQ { + thread *head; + thread *tail; +} threadQ; + +static threadQ readyQ; // The list of ready threads +static threadQ deadQ; // Where we put threads waiting to be deallocated +static thread * current; // The current running thread +static thread mainthread; // The main thread context + +static void Qinit(threadQ * q) { + q->head = q->tail = 0; +} + +static void Qadd(threadQ * q, thread *t) { + t->next = 0; + if (q->head) { + q->tail->next = t; + q->tail = t; + } else + q->head = q->tail = t; +} + +static thread *Qpop(threadQ * q) { + struct thread * t; + + if (!q->head) + return 0; + t = q->head; + q->head = t->next; + return t; +} + +#if AUTO_DETECT_MASK + // The structure for the saved stack frame information + typedef struct saveloc { + char * localptr; + jmp_buf cxt; + } saveloc; + + // A pointer to our auto-detection buffer. + static saveloc *pframeinfo; + + /* These functions are not static to prevent the compiler removing them as functions */ + + void get_stack_state(void) { + char c; + pframeinfo->localptr = (char *)&c; + _setjmp(pframeinfo->cxt); + } + + void get_stack_state_in_fn(void) { + pframeinfo++; + get_stack_state(); + pframeinfo--; + } +#endif + +static void _gosThreadsInit(void) { + Qinit(&readyQ); + current = &mainthread; + current->next = 0; + current->size = sizeof(thread); + current->flags = FLG_THD_MAIN; + current->fn = 0; + current->param = 0; + + #if AUTO_DETECT_MASK + { + uint32_t i; + char ** pout; + char ** pin; + size_t diff; + char * framebase; + + // Allocate a buffer to store our test data + pframeinfo = gfxAlloc(sizeof(saveloc)*2); + + // Get details of the stack frame from within a function + get_stack_state_in_fn(); + + // Get details of the stack frame outside the function + get_stack_state(); + + /* Work out the frame entries to relocate by treating the jump buffer as an array of pointers */ + stackdirup = pframeinfo[1].localptr > pframeinfo[0].localptr; + pout = (char **)pframeinfo[0].cxt; + pin = (char **)pframeinfo[1].cxt; + diff = pframeinfo[0].localptr - pframeinfo[1].localptr; + framebase = pframeinfo[0].localptr; + jmpmask1 = jmpmask2 = 0; + for (i = 0; i < sizeof(jmp_buf)/sizeof(char *); i++, pout++, pin++) { + if ((size_t)(*pout - *pin) == diff) { + if (i < 32) + jmpmask1 |= 1 << i; + else + jmpmask2 |= 1 << (i-32); + + if (stackdirup) { + if (framebase > *pout) + framebase = *pout; + } else { + if (framebase < *pout) + framebase = *pout; + } + } + } + stackbase = stackdirup ? (pframeinfo[0].localptr - framebase) : (framebase - pframeinfo[0].localptr); + + // Clean up + gfxFree(pframeinfo); + } + #endif +} + +gfxThreadHandle gfxThreadMe(void) { + return (gfxThreadHandle)current; +} + +void gfxYield(void) { + if (!_setjmp(current->cxt)) { + // Add us back to the Queue + Qadd(&readyQ, current); + + // Check if there are dead processes to deallocate + while ((current = Qpop(&deadQ))) + gfxFree(current); + + // Run the next process + current = Qpop(&readyQ); + _longjmp(current->cxt, 1); + } +} + +// This routine is not currently public - but it could be. +void gfxThreadExit(threadreturn_t ret) { + // Save the results + current->param = (void *)ret; + current->flags |= FLG_THD_DEAD; + + // Add us to the dead list if we need deallocation as we can't free ourselves. + // If someone is waiting on the thread they will do the cleanup. + if ((current->flags & (FLG_THD_ALLOC|FLG_THD_WAIT)) == FLG_THD_ALLOC) + Qadd(&deadQ, current); + + // Switch to the next task + current = Qpop(&readyQ); + if (!current) + gfxExit(); // Oops - this should never happen! + _longjmp(current->cxt, 1); +} + +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { + thread * t; + (void) prio; + + // Ensure we have a minimum stack size + if (stacksz < sizeof(thread)+64) { + stacksz = sizeof(thread)+64; + stackarea = 0; + } + + if (stackarea) { + t = (thread *)stackarea; + t->flags = 0; + } else { + t = (thread *)gfxAlloc(stacksz); + if (!t) + return 0; + t->flags = FLG_THD_ALLOC; + } + t->size = stacksz; + t->fn = fn; + t->param = param; + if (_setjmp(t->cxt)) { + // This is the new thread - call the function! + gfxThreadExit(current->fn(current->param)); + + // We never get here + return 0; + } + + // Move the stack frame and relocate the context data + { + char ** s; + char * nf; + int diff; + uint32_t i; + + // Copy the stack frame + #if AUTO_DETECT_MASK + if (STACK_DIR_UP) { // Stack grows up + nf = (char *)(t) + sizeof(thread) + stackbase; + memcpy(t+1, (char *)&t - stackbase, stackbase+sizeof(char *)); + } else { // Stack grows down + nf = (char *)(t) + stacksz - (stackbase + sizeof(char *)); + memcpy(nf, &t, stackbase+sizeof(char *)); + } + #elif STACK_DIR_UP + // Stack grows up + nf = (char *)(t) + sizeof(thread) + stackbase; + memcpy(t+1, (char *)&t - stackbase, stackbase+sizeof(char *)); + #else + // Stack grows down + nf = (char *)(t) + size - (stackbase + sizeof(char *)); + memcpy(nf, &t, stackbase+sizeof(char *)); + #endif + + // Relocate the context data + s = (char **)(t->cxt); + diff = nf - (char *)&t; + + // Relocate the elements we know need to be relocated + for (i = 1; i && i < MASK1; i <<= 1, s++) { + if ((MASK1 & i)) + *s += diff; + } + #ifdef MASK2 + for (i = 1; i && i < MASK2; i <<= 1, s++) { + if ((MASK1 & i)) + *s += diff; + } + #endif + } + + // Add this thread to the ready queue + Qadd(&readyQ, t); + return t; +} + +threadreturn_t gfxThreadWait(gfxThreadHandle th) { + thread * t; + + t = th; + if (t == current) + return -1; + + // Mark that we are waiting + t->flags |= FLG_THD_WAIT; + + // Wait for the thread to die + while(!(t->flags & FLG_THD_DEAD)) + gfxYield(); + + // Unmark + t->flags &= ~FLG_THD_WAIT; + + // Clean up resources if needed + if (t->flags & FLG_THD_ALLOC) + gfxFree(t); + + // Return the status left by the dead process + return (threadreturn_t)t->param; +} + +#endif /* GFX_USE_OS_RAW32 */ diff --git a/src/gos/gos_raw32.h b/src/gos/gos_raw32.h new file mode 100644 index 00000000..5a6a2aa7 --- /dev/null +++ b/src/gos/gos_raw32.h @@ -0,0 +1,126 @@ +/* + * 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 + */ + +/** + * The raw32 GOS implementation supports any 32 bit processor with or without an + * underlying operating system. It uses cooperative multi-tasking. Be careful + * when writing device drivers not to disturb the assumptions this creates by performing + * call-backs to uGFX code unless you define the INTERRUPTS_OFF() and INTERRUPTS_ON() macros. + * It still requires some C runtime library support... + * enough startup to initialise the stack, interrupts, static data etc and call main(). + * setjmp() and longjmp() - for threading + * memcpy() - for heap and threading + * malloc(), realloc and free() - if GOS_RAW_HEAP_SIZE == 0 + * + * You must also define the following routines in your own code so that timing functions will work... + * systemticks_t gfxSystemTicks(void); + * systemticks_t gfxMillisecondsToTicks(delaytime_t ms); + */ +#ifndef _GOS_RAW32_H +#define _GOS_RAW32_H + +#if GFX_USE_OS_RAW32 + +/*===========================================================================*/ +/* Special Macros just for a Raw implementation */ +/*===========================================================================*/ + +/** + * @brief Set the maximum size of the heap. + * @note If set to 0 then the C runtime library malloc() and free() are used. + */ +#ifndef GOS_RAW_HEAP_SIZE + #define GOS_RAW_HEAP_SIZE 0 +#endif + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +typedef unsigned char bool_t; + +#ifndef _STDINT_H + typedef char int8_t; + typedef unsigned char uint8_t; + typedef short int16_t; + typedef unsigned short uint16_t; + typedef int int32_t; + typedef unsigned int uint32_t; +#endif + +#if !defined (__need_size_t) && !defined (_STDDEF_H_) + typedef uint32_t size_t; +#endif + +typedef uint32_t delaytime_t; +typedef uint32_t systemticks_t; +typedef short semcount_t; +typedef int threadreturn_t; +typedef int threadpriority_t; + +#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) +#define DECLARE_THREAD_STACK(name, sz) uint8_t name[sz]; + +#define TIME_IMMEDIATE 0 +#define TIME_INFINITE ((delaytime_t)-1) +#define MAX_SEMAPHORE_COUNT 0x7FFF +#define LOW_PRIORITY 0 +#define NORMAL_PRIORITY 1 +#define HIGH_PRIORITY 2 + +typedef struct { + semcount_t cnt; + semcount_t limit; +} gfxSem; + +typedef uint32_t gfxMutex; +typedef void * gfxThreadHandle; + +#define gfxThreadClose(thread) +#define gfxMutexDestroy(pmutex) +#define gfxSemDestroy(psem) +#define gfxSemCounter(psem) ((psem)->cnt) +#define gfxSemCounterI(psem) ((psem)->cnt) + +#ifdef __cplusplus +extern "C" { +#endif + + #if GOS_RAW_HEAP_SIZE != 0 + void gfxAddHeapBlock(void *ptr, size_t sz); + #endif + + void gfxHalt(const char *msg); + void gfxExit(void); + void *gfxAlloc(size_t sz); + void *gfxRealloc(void *ptr, 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 gfxMutexEnter(gfxMutex *pmutex); + void gfxMutexExit(gfxMutex *pmutex); + void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit); + bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); + bool_t gfxSemWaitI(gfxSem *psem); + void gfxSemSignal(gfxSem *psem); + void gfxSemSignalI(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); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_OS_RAW32 */ +#endif /* _GOS_RAW32_H */ diff --git a/src/gos/gos_rawrtos.c b/src/gos/gos_rawrtos.c new file mode 100644 index 00000000..cd684208 --- /dev/null +++ b/src/gos/gos_rawrtos.c @@ -0,0 +1,83 @@ +#include "gfx.h" + +#if GFX_USE_OS_RAWRTOS + +#include +#include "raw_api.h" +#include "raw_config.h" + +#if CONFIG_RAW_MUTEX != 1 + #error "GOS: CONFIG_RAW_MUTEX must be defined in raw_config.h" +#endif + +#if CONFIG_RAW_SEMAPHORE != 1 + #error "GOS: CONFIG_RAW_SEMAPHORE must be defined in raw_config.h" +#endif + + +void _gosInit(void) +{ + #if !GFX_NO_OS_INIT + #error "GOS: Operating System initialization for RawRTOS is not yet implemented in uGFX. Please set GFX_NO_OS_INIT to TRUE in your gfxconf.h" + #else + #warning "GOS: Operating System initialization has been turned off. Make sure you call raw_os_start() before gfxInit() in your application!" + #endif +} + +void _gosDeinit(void) +{ +} + + +void gfxSleepMilliseconds(delaytime_t ms) +{ + systemticks_t ticks = ms*RAW_TICKS_PER_SECOND/1000; + if(!ticks)ticks = 1; + raw_sleep(ticks); +} + +void gfxSleepMicroseconds(delaytime_t us) +{ + systemticks_t ticks = (us/1000)*RAW_TICKS_PER_SECOND/1000; + if(!ticks)ticks = 1; + raw_sleep(ticks); +} + +bool_t gfxSemWait(gfxSem* psem, delaytime_t ms) +{ + systemticks_t ticks = ms*RAW_TICKS_PER_SECOND/1000; + if(!ticks)ticks=1; + if(raw_semaphore_get((psem), ticks)==RAW_SUCCESS) + return TRUE; + return FALSE; +} + +bool_t gfxSemWaitI(gfxSem* psem) +{ + if(raw_semaphore_get((psem), TIME_IMMEDIATE)==RAW_SUCCESS) + return TRUE; + return FALSE; +} + +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) +{ + RAW_U16 ret; + gfxThreadHandle taskobj; + + taskobj = gfxAlloc(sizeof(RAW_TASK_OBJ)); + ret = raw_task_create(taskobj, (RAW_U8 *)"uGFX_TASK", param, + prio, 0, stackarea, + stacksz/sizeof(PORT_STACK) , fn, 1); + + if (ret != RAW_SUCCESS) { + for (;;); + } + + return (taskobj); +} + + +#endif + + + diff --git a/src/gos/gos_rawrtos.h b/src/gos/gos_rawrtos.h new file mode 100644 index 00000000..eeb5119d --- /dev/null +++ b/src/gos/gos_rawrtos.h @@ -0,0 +1,77 @@ +#ifndef _GOS_RAWRTOS_H +#define _GOS_RAWRTOS_H + +#if GFX_USE_OS_RAWRTOS + +#include "raw_api.h" +#include + +#define TIME_IMMEDIATE (RAW_NO_WAIT) +#define TIME_INFINITE (RAW_WAIT_FOREVER) +typedef int8_t bool_t; +typedef uint32_t delaytime_t; +typedef RAW_TICK_TYPE systemticks_t; +typedef int32_t semcount_t; +typedef uint32_t threadreturn_t; +typedef RAW_U8 threadpriority_t; +typedef uint32_t size_t; + +#define MAX_SEMAPHORE_COUNT RAW_SEMAPHORE_COUNT +#define LOW_PRIORITY (CONFIG_RAW_PRIO_MAX-2) +#define NORMAL_PRIORITY (CONFIG_RAW_PRIO_MAX/2) +#define HIGH_PRIORITY 1 + +typedef RAW_SEMAPHORE gfxSem; +typedef RAW_MUTEX gfxMutex; +typedef RAW_TASK_OBJ* gfxThreadHandle; + +#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) +#define DECLARE_THREAD_STACK(name, sz) PORT_STACK name[sz]; + +#define gfxHalt(msg) for(;;) +#define gfxExit() for(;;) +#define gfxAlloc(sz) raw_malloc(sz) +#define gfxRealloc(p,osz,nsz) raw_calloc(p, nsz) +#define gfxFree(ptr) raw_free(ptr) +#define gfxYield() raw_sleep(0) +#define gfxSystemTicks() raw_system_time_get() +#define gfxMillisecondsToTicks(ms) (ms*RAW_TICKS_PER_SECOND/1000) +#define gfxSystemLock() {} +#define gfxSystemUnlock() {} +#define gfxMutexInit(pmutex) raw_mutex_create(pmutex, (RAW_U8 *)"", RAW_MUTEX_INHERIT_POLICY, 3) +#define gfxMutexDestroy(pmutex) raw_mutex_delete(pmutex) +#define gfxMutexEnter(pmutex) raw_mutex_get(pmutex, TIME_INFINITE) +#define gfxMutexExit(pmutex) raw_mutex_put(pmutex) +#define gfxSemInit(psem, val, limit) raw_semaphore_create(psem, "", val) +#define gfxSemDestroy(psem) raw_semaphore_delete(psem) +#define gfxSemSignal(psem) raw_semaphore_put((psem)) +#define gfxSemSignalI(psem) raw_semaphore_put_all((psem)) +#define gfxSemCounterI(psem) ((psem)->count) +#define gfxThreadMe() {(unsigned int)raw_task_identify()} +#define gfxThreadClose(thread) {} + +extern RAW_VOID *raw_malloc(RAW_U32 size); +extern RAW_VOID raw_free(void *ptr); +extern RAW_VOID *raw_calloc(RAW_U32 nmemb, RAW_U32 size); + +extern RAW_U16 raw_sleep(RAW_TICK_TYPE dly); +extern RAW_TICK_TYPE raw_system_time_get(void); + +extern RAW_U16 raw_mutex_create(RAW_MUTEX *mutex_ptr, RAW_U8 *name_ptr, RAW_U8 policy, RAW_U8 ceiling_prio); +extern RAW_U16 raw_mutex_delete(RAW_MUTEX *mutex_ptr); +extern RAW_U16 raw_mutex_get(RAW_MUTEX *mutex_ptr, RAW_TICK_TYPE wait_option); +extern RAW_U16 raw_mutex_put(RAW_MUTEX *mutex_ptr); +extern RAW_U16 raw_semaphore_create(RAW_SEMAPHORE *semaphore_ptr, RAW_U8 *name_ptr, RAW_U32 initial_count); +extern RAW_U16 raw_semaphore_delete(RAW_SEMAPHORE *semaphore_ptr); +extern RAW_U16 raw_semaphore_get(RAW_SEMAPHORE *semaphore_ptr, RAW_TICK_TYPE wait_option); +extern RAW_U16 raw_semaphore_put(RAW_SEMAPHORE *semaphore_ptr); + +void gfxSleepMilliseconds(delaytime_t ms); +void gfxSleepMicroseconds(delaytime_t us); +bool_t gfxSemWait(gfxSem* psem, delaytime_t ms); +bool_t gfxSemWaitI(gfxSem* psem); +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); + +#endif + +#endif diff --git a/src/gos/gos_win32.c b/src/gos/gos_win32.c new file mode 100644 index 00000000..5d33314f --- /dev/null +++ b/src/gos/gos_win32.c @@ -0,0 +1,126 @@ +/* + * 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/gfx_win32.c + * @brief GOS Win32 Operating System support. + */ +#include "gfx.h" + +#if GFX_USE_OS_WIN32 + +#include + +static HANDLE SystemMutex; + +void _gosInit(void) +{ + /* No initialization of the operating system itself is needed */ +} + +void _gosDeinit(void) +{ + +} + +void gfxHalt(const char *msg) { + if (msg) + fprintf(stderr, "%s\n", msg); + + ExitProcess(1); +} + +void gfxSleepMicroseconds(delaytime_t ms) { + static LARGE_INTEGER pcfreq; + static int initflag; + LARGE_INTEGER t1, t2, tdiff; + + switch(ms) { + case TIME_IMMEDIATE: + return; + + case TIME_INFINITE: + while(1) + Sleep(1000); + return; + } + + if (!initflag) { + QueryPerformanceFrequency(&pcfreq); + initflag++; + } + tdiff.QuadPart = pcfreq.QuadPart * ms / 1000000; + + QueryPerformanceCounter(&t1); + do { + QueryPerformanceCounter(&t2); + } while (t2.QuadPart - t1.QuadPart < tdiff.QuadPart); +} + +void gfxSystemLock(void) { + if (!SystemMutex) + SystemMutex = CreateMutex(0, FALSE, 0); + WaitForSingleObject(SystemMutex, INFINITE); +} + +void gfxSystemUnlock(void) { + ReleaseMutex(SystemMutex); +} + +bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) { + return WaitForSingleObject(*psem, ms) == WAIT_OBJECT_0; +} + +typedef LONG __stdcall (*_NtQuerySemaphore)( + HANDLE SemaphoreHandle, + DWORD SemaphoreInformationClass, /* Would be SEMAPHORE_INFORMATION_CLASS */ + PVOID SemaphoreInformation, /* but this is to much to dump here */ + ULONG SemaphoreInformationLength, + PULONG ReturnLength OPTIONAL +); + +semcount_t gfxSemCounter(gfxSem *pSem) { + static _NtQuerySemaphore NtQuerySemaphore; + struct _SEMAPHORE_BASIC_INFORMATION { + ULONG CurrentCount; + ULONG MaximumCount; + } BasicInfo; + + if (!NtQuerySemaphore) + NtQuerySemaphore = (_NtQuerySemaphore)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySemaphore"); + + NtQuerySemaphore(*pSem, 0, &BasicInfo, sizeof(BasicInfo), 0); + + return BasicInfo.CurrentCount; +} + +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { + (void) stackarea; + HANDLE thd; + + if (!(thd = CreateThread(0, stacksz, fn, param, CREATE_SUSPENDED, 0))) + return FALSE; + + SetThreadPriority(thd, prio); + ResumeThread(thd); + + return thd; +} + +threadreturn_t gfxThreadWait(gfxThreadHandle thread) { + DWORD ret; + + WaitForSingleObject(thread, INFINITE); + GetExitCodeThread(thread, &ret); + CloseHandle(thread); + + return ret; +} + +#endif /* GFX_USE_OS_WIN32 */ +/** @} */ + diff --git a/src/gos/gos_win32.h b/src/gos/gos_win32.h new file mode 100644 index 00000000..5e924a44 --- /dev/null +++ b/src/gos/gos_win32.h @@ -0,0 +1,107 @@ +/* + * 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/gfx_win32.h + * @brief GOS - Operating System Support header file for WIN32. + */ + +#ifndef _GOS_WIN32_H +#define _GOS_WIN32_H + +#if GFX_USE_OS_WIN32 + +#ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0501 // Windows XP and up +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#include + +/* Stop cygwin from defining these types */ +#define __int8_t_defined + +/** + * size_t + * TRUE, FALSE + * are already defined by Win32 + */ +typedef __int8 bool_t; +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef DWORD delaytime_t; +typedef DWORD systemticks_t; +typedef LONG semcount_t; +typedef DWORD threadreturn_t; +typedef int threadpriority_t; + +#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t WINAPI fnName(void *param) +#define DECLARE_THREAD_STACK(name, sz) uint8_t name[0]; + +#define TIME_IMMEDIATE 0 +#define TIME_INFINITE INFINITE +#define MAX_SEMAPHORE_COUNT ((semcount_t)(((unsigned long)((semcount_t)(-1))) >> 1)) +#define LOW_PRIORITY THREAD_PRIORITY_BELOW_NORMAL +#define NORMAL_PRIORITY THREAD_PRIORITY_NORMAL +#define HIGH_PRIORITY THREAD_PRIORITY_ABOVE_NORMAL + +typedef HANDLE gfxSem; +typedef HANDLE gfxMutex; +typedef HANDLE gfxThreadHandle; + +#define gfxExit() ExitProcess(0) +#define gfxAlloc(sz) malloc(sz) +#define gfxRealloc(p,osz,nsz) realloc(p, nsz) +#define gfxFree(ptr) free(ptr) +#define gfxSleepMilliseconds(ms) Sleep(ms) +#define gfxYield() Sleep(0) +#define gfxSystemTicks() GetTickCount() +#define gfxMillisecondsToTicks(ms) (ms) +#define gfxMutexInit(pmutex) *(pmutex) = CreateMutex(0, FALSE, 0) +#define gfxMutexDestroy(pmutex) CloseHandle(*(pmutex)) +#define gfxMutexEnter(pmutex) WaitForSingleObject(*(pmutex), INFINITE) +#define gfxMutexExit(pmutex) ReleaseMutex(*(pmutex)) +#define gfxSemInit(psem, val, limit) *(psem) = CreateSemaphore(0, val, limit, 0) +#define gfxSemDestroy(psem) CloseHandle(*(psem)) +#define gfxSemWaitI(psem) gfxSemWait((psem), TIME_IMMEDIATE) +#define gfxSemSignal(psem) ReleaseSemaphore(*(psem), 1, 0) +#define gfxSemSignalI(psem) ReleaseSemaphore(*(psem), 1, 0) +#define gfxSemCounterI(psem) gfxSemCounter(psem) +#define gfxThreadMe() GetCurrentThread() +#define gfxThreadClose(thread) CloseHandle(thread) + +/*===========================================================================*/ +/* Function declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +void gfxHalt(const char *msg); +void gfxSleepMicroseconds(delaytime_t ms); +bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); +semcount_t gfxSemCounter(gfxSem *pSem); +void gfxSystemLock(void); +void gfxSystemUnlock(void); +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); +threadreturn_t gfxThreadWait(gfxThreadHandle thread); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_OS_WIN32 */ +#endif /* _GOS_WIN32_H */ + diff --git a/src/gos/sys_defs.h b/src/gos/sys_defs.h index d116826f..e4b3ddd2 100644 --- a/src/gos/sys_defs.h +++ b/src/gos/sys_defs.h @@ -440,21 +440,21 @@ * (without any of the documentation overheads) is in the files below. */ #elif GFX_USE_OS_RAWRTOS - #include "src/gos/gfx_rawrtos.h" + #include "src/gos/gos_rawrtos.h" #elif GFX_USE_OS_CHIBIOS - #include "src/gos/gfx_chibios.h" + #include "src/gos/gos_chibios.h" #elif GFX_USE_OS_FREERTOS - #include "src/gos/gfx_freertos.h" + #include "src/gos/gos_freertos.h" #elif GFX_USE_OS_WIN32 - #include "src/gos/gfx_win32.h" + #include "src/gos/gos_win32.h" #elif GFX_USE_OS_LINUX - #include "src/gos/gfx_linux.h" + #include "src/gos/gos_linux.h" #elif GFX_USE_OS_OSX - #include "src/gos/gfx_osx.h" + #include "src/gos/gos_osx.h" #elif GFX_USE_OS_RAW32 - #include "src/gos/gfx_raw32.h" + #include "src/gos/gos_raw32.h" #elif GFX_USE_OS_ECOS - #include "src/gos/gfx_ecos.h" + #include "src/gos/gos_ecos.h" #else #error "Your operating system is not supported yet" #endif diff --git a/src/gos/sys_make.mk b/src/gos/sys_make.mk index 5efa7f80..a7b3dec6 100644 --- a/src/gos/sys_make.mk +++ b/src/gos/sys_make.mk @@ -1,9 +1,9 @@ -GFXSRC += $(GFXLIB)/src/gos/gfx_chibios.c \ - $(GFXLIB)/src/gos/gfx_freertos.c \ - $(GFXLIB)/src/gos/gfx_win32.c \ - $(GFXLIB)/src/gos/gfx_linux.c \ - $(GFXLIB)/src/gos/gfx_osx.c \ - $(GFXLIB)/src/gos/gfx_raw32.c \ - $(GFXLIB)/src/gos/gfx_ecos.c \ - $(GFXLIB)/src/gos/gfx_rawrtos.c +GFXSRC += $(GFXLIB)/src/gos/gos_chibios.c \ + $(GFXLIB)/src/gos/gos_freertos.c \ + $(GFXLIB)/src/gos/gos_win32.c \ + $(GFXLIB)/src/gos/gos_linux.c \ + $(GFXLIB)/src/gos/gos_osx.c \ + $(GFXLIB)/src/gos/gos_raw32.c \ + $(GFXLIB)/src/gos/gos_ecos.c \ + $(GFXLIB)/src/gos/gos_rawrtos.c -- cgit v1.2.3