diff --git a/changelog.txt b/changelog.txt index 664594c0..e5cfb1a2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -19,6 +19,10 @@ FEATURE: Increase non-UTF8 font support to 0 to 255 rather than just the true as FEATURE: Added Fb24bpp driver for RGB888 and BGR888 packed framebuffer displays FEATURE: Added UC8173 driver FEATURE: Added complete support for Altera Terasic MAX10 NEEK board +FEATURE: Significantly improved the FreeRTOS port +FEATURE: Added support for operating system initialisation in FreeRTOS +FEATURE: Added GFX_OS_CALL_UGFXMAIN configuration option to allow uGFXMain() to be automatically called +FEATURE: Added GFX_OS_UGFXMAIN_STACKSIZE configuration option to control uGFXMain() stack size *** Release 2.7 *** diff --git a/gfxconf.example.h b/gfxconf.example.h index 4fa31d0c..d4e34a5b 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -56,6 +56,8 @@ // #define GFX_OS_PRE_INIT_FUNCTION myHardwareInitRoutine // #define GFX_OS_EXTRA_INIT_FUNCTION myOSInitRoutine // #define GFX_OS_EXTRA_DEINIT_FUNCTION myOSDeInitRoutine +// #define GFX_OS_CALL_UGFXMAIN FALSE +// #define GFX_OS_UGFXMAIN_STACKSIZE 0 // #define GFX_EMULATE_MALLOC FALSE diff --git a/src/gfx.c b/src/gfx.c index 00d4e563..d13d173c 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -19,6 +19,7 @@ static bool_t gfxInitDone = FALSE; /* These init functions are defined by each module but not published */ extern void _gosInit(void); +extern void _gosPostInit(void); extern void _gosDeinit(void); #ifdef GFX_OS_PRE_INIT_FUNCTION extern void GFX_OS_PRE_INIT_FUNCTION(void); @@ -77,6 +78,9 @@ extern void _gosDeinit(void); extern void _gtransInit(void); extern void _gtransDeinit(void); #endif +#if GFX_OS_CALL_UGFXMAIN + extern threadreturn_t uGFXMain(void *param); +#endif void gfxInit(void) { @@ -130,6 +134,10 @@ void gfxInit(void) #if GFX_USE_GWIN _gwinInit(); #endif + _gosPostInit(); + #if GFX_OS_CALL_UGFXMAIN + uGFXMain(0); + #endif } void gfxDeinit(void) diff --git a/src/gos/gos_arduino.c b/src/gos/gos_arduino.c index 726c57db..2e0e4b53 100644 --- a/src/gos/gos_arduino.c +++ b/src/gos/gos_arduino.c @@ -35,6 +35,10 @@ void _gosInit(void) _gosThreadsInit(); } +void _gosPostInit(void) +{ +} + void _gosDeinit(void) { /* ToDo */ diff --git a/src/gos/gos_chibios.c b/src/gos/gos_chibios.c index fc34b94b..72b91dfc 100644 --- a/src/gos/gos_chibios.c +++ b/src/gos/gos_chibios.c @@ -53,6 +53,10 @@ void _gosInit(void) #endif } +void _gosPostInit(void) +{ +} + void _gosDeinit(void) { /* ToDo */ diff --git a/src/gos/gos_cmsis.c b/src/gos/gos_cmsis.c index 1422fd90..5bb10dbd 100644 --- a/src/gos/gos_cmsis.c +++ b/src/gos/gos_cmsis.c @@ -26,6 +26,10 @@ void _gosInit(void) _gosHeapInit(); } +void _gosPostInit(void) +{ +} + void _gosDeinit(void) { } diff --git a/src/gos/gos_ecos.c b/src/gos/gos_ecos.c index 771ac389..5ca5748f 100644 --- a/src/gos/gos_ecos.c +++ b/src/gos/gos_ecos.c @@ -19,6 +19,10 @@ void _gosInit(void) #endif } +void _gosPostInit(void) +{ +} + void _gosDeinit(void) { /* ToDo */ diff --git a/src/gos/gos_freertos.c b/src/gos/gos_freertos.c index 9708c05f..1f0d8dac 100644 --- a/src/gos/gos_freertos.c +++ b/src/gos/gos_freertos.c @@ -22,18 +22,41 @@ #error "GOS: configUSE_COUNTING_SEMAPHORES must be defined in FreeRTOSConfig.h" #endif +#if !GFX_OS_NO_INIT && INCLUDE_xTaskGetSchedulerState != 1 && configUSE_TIMERS != 1 + #error "GOS: Either INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be defined in FreeRTOSConfig.h" +#endif + +#if !GFX_OS_NO_INIT && !GFX_OS_CALL_UGFXMAIN + #error "GOS: Either GFX_OS_NO_INIT or GFX_OS_CALL_UGFXMAIN must be defined for FreeRTOS" +#endif + void _gosInit(void) { - #if !GFX_OS_NO_INIT - #error "GOS: Operating System initialization for FreeRTOS is not yet implemented in uGFX. Please set GFX_OS_NO_INIT to TRUE in your gfxconf.h" + #if GFX_OS_NO_INIT && !GFX_OS_INIT_NO_WARNING + #warning "GOS: Operating System initialization has been turned off. Make sure you call vTaskStartScheduler()." #endif - #if !GFX_OS_INIT_NO_WARNING - #warning "GOS: Operating System initialization has been turned off. Make sure you call vTaskStartScheduler() before gfxInit() in your application!" +} + +#if !GFX_OS_NO_INIT && GFX_OS_CALL_UGFXMAIN + extern threadreturn_t uGFXMain(void *param); +#endif + +void _gosPostInit(void) +{ + #if !GFX_OS_NO_INIT && GFX_OS_CALL_UGFXMAIN + if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) { + gfxThreadCreate(0, GFX_OS_UGFXMAIN_STACKSIZE, NORMAL_PRIORITY, uGFXMain, 0); + vTaskStartScheduler(); + gfxHalt("Unable to start FreeRTOS scheduler. Out of memory?"); + } #endif } void _gosDeinit(void) { + #if !GFX_OS_NO_INIT + vTaskDelete(0); + #endif } void* gfxRealloc(void *ptr, size_t oldsz, size_t newsz) @@ -131,4 +154,11 @@ gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_ return task; } +#if INCLUDE_eTaskGetState == 1 + threadreturn_t gfxThreadWait(gfxThreadHandle thread) { + while (eTaskGetState(thread) != eDeleted) + gfxYield(); + } +#endif + #endif /* GFX_USE_OS_FREERTOS */ diff --git a/src/gos/gos_freertos.h b/src/gos/gos_freertos.h index 6301a7df..a0f1ed18 100644 --- a/src/gos/gos_freertos.h +++ b/src/gos/gos_freertos.h @@ -60,7 +60,7 @@ typedef portBASE_TYPE threadpriority_t; #define HIGH_PRIORITY configMAX_PRIORITIES-1 /* FreeRTOS will allocate the stack when creating the thread */ -#define DECLARE_THREAD_STACK(name, sz) +#define DECLARE_THREAD_STACK(name, sz) uint8_t name[1] #define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) #define THREAD_RETURN(retval) @@ -103,9 +103,11 @@ 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); -#define gfxThreadWait(thread) {} // never used, not imlpemented -#define gfxThreadMe() {} // never used, not implemented -#define gfxThreadClose(thread) {} +#define gfxThreadMe() xTaskGetCurrentTaskHandle() +#if INCLUDE_eTaskGetState == 1 + threadreturn_t gfxThreadWait(gfxThreadHandle thread); +#endif +#define gfxThreadClose(thread) #ifdef __cplusplus } diff --git a/src/gos/gos_linux.c b/src/gos/gos_linux.c index 1e0675dd..dac3838f 100644 --- a/src/gos/gos_linux.c +++ b/src/gos/gos_linux.c @@ -33,6 +33,10 @@ void _gosInit(void) gfxMutexInit(&SystemMutex); } +void _gosPostInit(void) +{ +} + void _gosDeinit(void) { /* ToDo */ diff --git a/src/gos/gos_nios.c b/src/gos/gos_nios.c index 3a937026..b7709c8c 100644 --- a/src/gos/gos_nios.c +++ b/src/gos/gos_nios.c @@ -25,6 +25,10 @@ void _gosInit(void) _gosThreadsInit(); } +void _gosPostInit(void) +{ +} + void _gosDeinit(void) { } diff --git a/src/gos/gos_options.h b/src/gos/gos_options.h index 2d3b0d29..c78d25ca 100644 --- a/src/gos/gos_options.h +++ b/src/gos/gos_options.h @@ -180,6 +180,32 @@ #ifndef GFX_OS_INIT_NO_WARNING #define GFX_OS_INIT_NO_WARNING FALSE #endif + /** + * @brief Call uGFXMain() after all initialisation + * @details Defaults to FALSE + * @note uGFXMain() is a function defined by the user in their project + * that contains the application main code. This is not expected to return + * and thus gfxInit() will also never return. This is required for some + * operating systems whose main thread never returns after starting the + * scheduler.
+ * Its prototype is:
+ * threadreturn_t uGFXMain(void *param);
+ * @note uGFXMain() will always be called with a NULL paramter. + */ + #ifndef GFX_OS_CALL_UGFXMAIN + #define GFX_OS_CALL_UGFXMAIN FALSE + #endif + /** + * @brief When uGFXMain() is started as a thread, what stack size should be used + * @details Defaults to 0 + * @note uGFXMain() contains the application main code. Some operating systems + * will start this as a thread. eg FreeRTOS. When it is started as a thread + * this defines how many bytes should be used for the thread stack. + * @note 0 means to use the operating systems default stack size. + */ + #ifndef GFX_OS_UGFXMAIN_STACKSIZE + #define GFX_OS_UGFXMAIN_STACKSIZE 0 + #endif /** * @brief Should uGFX stuff be added to the FreeRTOS+Tracer * @details Defaults to FALSE diff --git a/src/gos/gos_osx.c b/src/gos/gos_osx.c index 413ddc62..f06685d7 100644 --- a/src/gos/gos_osx.c +++ b/src/gos/gos_osx.c @@ -30,6 +30,10 @@ void _gosInit(void) gfxMutexInit(&SystemMutex); } +void _gosPostInit(void) +{ +} + void _gosDeinit(void) { /* ToDo */ diff --git a/src/gos/gos_qt.cpp b/src/gos/gos_qt.cpp index e3a0f0ca..422f1535 100644 --- a/src/gos/gos_qt.cpp +++ b/src/gos/gos_qt.cpp @@ -53,6 +53,10 @@ void _gosInit(void) _systickTimer.start(); } +void _gosPostInit(void) +{ +} + void _gosDeinit(void) { } diff --git a/src/gos/gos_raw32.c b/src/gos/gos_raw32.c index 2b482ae2..af9a2442 100644 --- a/src/gos/gos_raw32.c +++ b/src/gos/gos_raw32.c @@ -36,6 +36,10 @@ void _gosInit(void) _gosThreadsInit(); } +void _gosPostInit(void) +{ +} + void _gosDeinit(void) { /* ToDo */ diff --git a/src/gos/gos_rawrtos.c b/src/gos/gos_rawrtos.c index 7c24cd5a..ad646a7d 100644 --- a/src/gos/gos_rawrtos.c +++ b/src/gos/gos_rawrtos.c @@ -32,6 +32,10 @@ void _gosInit(void) #endif } +void _gosPostInit(void) +{ +} + void _gosDeinit(void) { } diff --git a/src/gos/gos_win32.c b/src/gos/gos_win32.c index e9abedd7..5eecca88 100644 --- a/src/gos/gos_win32.c +++ b/src/gos/gos_win32.c @@ -21,6 +21,10 @@ void _gosInit(void) /* No initialization of the operating system itself is needed */ } +void _gosPostInit(void) +{ +} + void _gosDeinit(void) { @@ -102,7 +106,7 @@ gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_ HANDLE thd; if (!(thd = CreateThread(0, stacksz, fn, param, CREATE_SUSPENDED, 0))) - return FALSE; + return 0; SetThreadPriority(thd, prio); ResumeThread(thd);