diff --git a/docs/releases.txt b/docs/releases.txt index b471ca8e..567c711e 100644 --- a/docs/releases.txt +++ b/docs/releases.txt @@ -25,6 +25,8 @@ FEATURE: Added gdispAddFont() for adding a dynamic font to the permanent font li FEATURE: Added gmiscHittestPoly() for checking whether a point is inside of a polygon FIX: Fixed strange multi-thread issues in GEVENT FEATURE: Added ILI9488 driver +FEATURE: Added the ability to display the detected compiler +FIX: Fixed an illegal instruction in the Cortex M0 task switcher *** Release 2.6 *** diff --git a/src/gos/gos_x_threads.c b/src/gos/gos_x_threads.c index d2cb6113..6f4a9ee7 100644 --- a/src/gos/gos_x_threads.c +++ b/src/gos/gos_x_threads.c @@ -189,118 +189,19 @@ 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 +#undef GFX_THREADS_DONE + #if GFX_CPU == GFX_CPU_CORTEX_M0 || GFX_CPU == GFX_CPU_CORTEX_M1 - - // Use the EABI calling standard (ARM's AAPCS) - Save r4 - r11 - // The context is saved at the current stack location and a pointer is maintained in the thread structure. - - #define _gfxThreadsInit() - - static __attribute__((pcs("aapcs"),naked)) void _gfxTaskSwitch(thread *oldt, thread *newt) { - __asm__ volatile ( "push {r4, r5, r6, r7, lr} \n\t" - "mov r4, r8 \n\t" - "mov r5, r9 \n\t" - "mov r6, r10 \n\t" - "mov r7, r11 \n\t" - "push {r4, r5, r6, r7} \n\t" - "str sp, %[oldtcxt] \n\t" - "ldr sp, %[newtcxt] \n\t" - "pop {r4, r5, r6, r7} \n\t" - "mov r8, r4 \n\t" - "mov r9, r5 \n\t" - "mov r10, r6 \n\t" - "mov r11, r7 \n\t" - "pop {r4, r5, r6, r7, pc} \n\t" - : [newtcxt] "=m" (newt->cxt) - : [oldtcxt] "m" (oldt->cxt) - : "memory"); - } - - static __attribute__((pcs("aapcs"),naked)) void _gfxStartThread(thread *oldt, thread *newt) { - newt->cxt = (char *)newt + newt->size; - __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t" // save current context - "str sp, %[oldtcxt] \n\t" // save context pointer - "ldr sp, %[newtcxt] \n\t" // load new context pointer - : [newtcxt] "=m" (newt->cxt) - : [oldtcxt] "m" (oldt->cxt) - : "memory"); - - // Run the users function - gfxThreadExit(current->fn(current->param)); - } - + #include "gos_x_threads_cortexm01.h" #elif GFX_CPU == GFX_CPU_CORTEX_M3 || GFX_CPU == GFX_CPU_CORTEX_M4 || GFX_CPU == GFX_CPU_CORTEX_M7 - - // Use the EABI calling standard (ARM's AAPCS) - Save r4 - r11 - // The context is saved at the current stack location and a pointer is maintained in the thread structure. - - #if CORTEX_USE_FPU - #warning "GOS Threads: You have specified GFX_CPU=GFX_CPU_CORTX_M? with no hardware floating point support but CORTEX_USE_FPU is TRUE. Try using GFX_CPU_GFX_CPU_CORTEX_M?_FP instead" - #endif - - #define _gfxThreadsInit() - - static __attribute__((pcs("aapcs"),naked)) void _gfxTaskSwitch(thread *oldt, thread *newt) { - __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t" - "str sp, %[oldtcxt] \n\t" - "ldr sp, %[newtcxt] \n\t" - "pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} \n\t" - : [newtcxt] "=m" (newt->cxt) - : [oldtcxt] "m" (oldt->cxt) - : "memory"); - } - - static __attribute__((pcs("aapcs"),naked)) void _gfxStartThread(thread *oldt, thread *newt) { - newt->cxt = (char *)newt + newt->size; - __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t" - "str sp, %[oldtcxt] \n\t" - "ldr sp, %[newtcxt] \n\t" - : [newtcxt] "=m" (newt->cxt) - : [oldtcxt] "m" (oldt->cxt) - : "memory"); - - // Run the users function - gfxThreadExit(current->fn(current->param)); - } - + #include "gos_x_threads_cortexm347.h" #elif GFX_CPU == GFX_CPU_CORTEX_M4_FP || GFX_CPU == GFX_CPU_CORTEX_M7_FP + #include "gos_x_threads_cortexm47fp.h" +#endif - // Use the EABI calling standard (ARM's AAPCS) - Save r4 - r11 and floating point - // The context is saved at the current stack location and a pointer is maintained in the thread structure. +#ifndef GFX_THREADS_DONE + #define GFX_THREADS_DONE - #if !CORTEX_USE_FPU - #warning "GOS Threads: You have specified GFX_CPU=GFX_CPU_CORTX_M?_FP with hardware floating point support but CORTEX_USE_FPU is FALSE. Try using GFX_CPU_GFX_CPU_CORTEX_M? instead" - #endif - - #define _gfxThreadsInit() - - static __attribute__((pcs("aapcs-vfp"),naked)) void _gfxTaskSwitch(thread *oldt, thread *newt) { - __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t" - "vpush {s16-s31} \n\t" - "str sp, %[oldtcxt] \n\t" - "ldr sp, %[newtcxt] \n\t" - "vpop {s16-s31} \n\t" - "pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} \n\t" - : [newtcxt] "=m" (newt->cxt) - : [oldtcxt] "m" (oldt->cxt) - : "memory"); - } - - static __attribute__((pcs("aapcs-vfp"),naked)) void _gfxStartThread(thread *oldt, thread *newt) { - newt->cxt = (char *)newt + newt->size; - __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t" - "vpush {s16-s31} \n\t" - "str sp, %[oldtcxt] \n\t" - "ldr sp, %[newtcxt] \n\t" - : [newtcxt] "=m" (newt->cxt) - : [oldtcxt] "m" (oldt->cxt) - : "memory"); - - // Run the users function - gfxThreadExit(current->fn(current->param)); - } - -#else #include // Prototype for memcpy() #include @@ -514,6 +415,7 @@ static thread mainthread; // The main thread context #define _gfxTaskSwitch(oldt, newt) _gfxXSwitch(oldt, newt, FALSE) #define _gfxStartThread(oldt, newt) _gfxXSwitch(oldt, newt, TRUE) #endif +#undef GFX_THREADS_DONE static void Qinit(threadQ * q) { q->head = q->tail = 0; diff --git a/src/gos/gos_x_threads_cortexm01.h b/src/gos/gos_x_threads_cortexm01.h new file mode 100644 index 00000000..df2d1f78 --- /dev/null +++ b/src/gos/gos_x_threads_cortexm01.h @@ -0,0 +1,103 @@ +/* + * 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 + */ + +/** + * Thread Switching Functions for the Cortex M0 & M1 + * + * Use the EABI calling standard (ARM's AAPCS) - Save r4 - r11 + * The context is saved at the current stack location and a pointer is maintained in the thread structure. + */ + +#if CORTEX_USE_FPU + #warning "GOS Threads: You have specified GFX_CPU=GFX_CPU_CORTX_M? with no hardware floating point support but CORTEX_USE_FPU is TRUE. Try using GFX_CPU_GFX_CPU_CORTEX_M?_FP instead" +#endif + +#if GFX_COMPILER == GFX_COMPILER_GCC || GFX_COMPILER == GFX_COMPILER_CYGWIN || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64 + #define GFX_THREADS_DONE + #define _gfxThreadsInit() + + static __attribute__((pcs("aapcs"),naked)) void _gfxTaskSwitch(thread *oldt, thread *newt) { + __asm__ volatile ( "push {r4, r5, r6, r7, lr} \n\t" + "mov r4, r8 \n\t" + "mov r5, r9 \n\t" + "mov r6, r10 \n\t" + "mov r7, r11 \n\t" + "push {r4, r5, r6, r7} \n\t" + "str sp, %[oldtcxt] \n\t" + "ldr sp, %[newtcxt] \n\t" + "pop {r4, r5, r6, r7} \n\t" + "mov r8, r4 \n\t" + "mov r9, r5 \n\t" + "mov r10, r6 \n\t" + "mov r11, r7 \n\t" + "pop {r4, r5, r6, r7, pc} \n\t" + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); + } + + static __attribute__((pcs("aapcs"),naked)) void _gfxStartThread(thread *oldt, thread *newt) { + newt->cxt = (char *)newt + newt->size; + __asm__ volatile ( "push {r4, r5, r6, r7, lr} \n\t" + "mov r4, r8 \n\t" + "mov r5, r9 \n\t" + "mov r6, r10 \n\t" + "mov r7, r11 \n\t" + "push {r4, r5, r6, r7} \n\t" + "str sp, %[oldtcxt] \n\t" + "ldr sp, %[newtcxt] \n\t" + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); + + // Run the users function + gfxThreadExit(current->fn(current->param)); + } + +#elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC + + static /*__arm*/ void _gfxTaskSwitch(thread *oldt, thread *newt) { +/* push {r4, r5, r6, r7, lr} + mov r4, r8 + mov r5, r9 + mov r6, r10 + mov r7, r11 + push {r4, r5, r6, r7} + str sp, %[oldtcxt] + ldr sp, %[newtcxt] + pop {r4, r5, r6, r7} + mov r8, r4 + mov r9, r5 + mov r10, r6 + mov r11, r7 + pop {r4, r5, r6, r7, pc} + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); +*/ } + + static /* __arm */ void _gfxStartThread(thread *oldt, thread *newt) { + newt->cxt = (char *)newt + newt->size; +/* push {r4, r5, r6, r7, lr} + mov r4, r8 + mov r5, r9 + mov r6, r10 + mov r7, r11 + push {r4, r5, r6, r7} + str sp, %[oldtcxt] + ldr sp, %[newtcxt] + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); +*/ + // Run the users function + gfxThreadExit(current->fn(current->param)); + } + +#else + #warning "GOS: Threads: You have specified a specific CPU but your compiler is not supported. Defaulting to CLIB switching" +#endif diff --git a/src/gos/gos_x_threads_cortexm347.h b/src/gos/gos_x_threads_cortexm347.h new file mode 100644 index 00000000..0392e674 --- /dev/null +++ b/src/gos/gos_x_threads_cortexm347.h @@ -0,0 +1,74 @@ +/* + * 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 + */ + +/** + * Thread Switching Functions for the Cortex M3, M4 & M7 without hardware floating point + * + * Use the EABI calling standard (ARM's AAPCS) - Save r4 - r11 + * The context is saved at the current stack location and a pointer is maintained in the thread structure. + */ + + +#if CORTEX_USE_FPU + #warning "GOS Threads: You have specified GFX_CPU=GFX_CPU_CORTX_M? with no hardware floating point support but CORTEX_USE_FPU is TRUE. Try using GFX_CPU_GFX_CPU_CORTEX_M?_FP instead" +#endif + +#if GFX_COMPILER == GFX_COMPILER_GCC || GFX_COMPILER == GFX_COMPILER_CYGWIN || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64 + #define GFX_THREADS_DONE + #define _gfxThreadsInit() + + static __attribute__((pcs("aapcs"),naked)) void _gfxTaskSwitch(thread *oldt, thread *newt) { + __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t" + "str sp, %[oldtcxt] \n\t" + "ldr sp, %[newtcxt] \n\t" + "pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} \n\t" + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); + } + + static __attribute__((pcs("aapcs"),naked)) void _gfxStartThread(thread *oldt, thread *newt) { + newt->cxt = (char *)newt + newt->size; + __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t" + "str sp, %[oldtcxt] \n\t" + "ldr sp, %[newtcxt] \n\t" + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); + + // Run the users function + gfxThreadExit(current->fn(current->param)); + } + +#elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC + + static /*__arm*/ void _gfxTaskSwitch(thread *oldt, thread *newt) { +/* push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + str sp, %[oldtcxt] + ldr sp, %[newtcxt] + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); +*/ } + + static /* __arm */ void _gfxStartThread(thread *oldt, thread *newt) { + newt->cxt = (char *)newt + newt->size; +/* push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + str sp, %[oldtcxt] + ldr sp, %[newtcxt] + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); +*/ + // Run the users function + gfxThreadExit(current->fn(current->param)); + } + +#else + #warning "GOS: Threads: You have specified a specific CPU but your compiler is not supported. Defaulting to CLIB switching" +#endif diff --git a/src/gos/gos_x_threads_cortexm47fp.h b/src/gos/gos_x_threads_cortexm47fp.h new file mode 100644 index 00000000..0d4d0d89 --- /dev/null +++ b/src/gos/gos_x_threads_cortexm47fp.h @@ -0,0 +1,79 @@ +/* + * 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 + */ + +/** + * Thread Switching Functions for the Cortex M4 & M7 with hardware floating point + * + * Use the EABI calling standard (ARM's AAPCS) - Save r4 - r11 and floating point + * The context is saved at the current stack location and a pointer is maintained in the thread structure. + */ + +#if !CORTEX_USE_FPU + #warning "GOS Threads: You have specified GFX_CPU=GFX_CPU_CORTX_M?_FP with hardware floating point support but CORTEX_USE_FPU is FALSE. Try using GFX_CPU_GFX_CPU_CORTEX_M? instead" +#endif + +#if GFX_COMPILER == GFX_COMPILER_GCC || GFX_COMPILER == GFX_COMPILER_CYGWIN || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64 + #define GFX_THREADS_DONE + #define _gfxThreadsInit() + + static __attribute__((pcs("aapcs-vfp"),naked)) void _gfxTaskSwitch(thread *oldt, thread *newt) { + __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t" + "vpush {s16-s31} \n\t" + "str sp, %[oldtcxt] \n\t" + "ldr sp, %[newtcxt] \n\t" + "vpop {s16-s31} \n\t" + "pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} \n\t" + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); + } + + static __attribute__((pcs("aapcs-vfp"),naked)) void _gfxStartThread(thread *oldt, thread *newt) { + newt->cxt = (char *)newt + newt->size; + __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t" + "vpush {s16-s31} \n\t" + "str sp, %[oldtcxt] \n\t" + "ldr sp, %[newtcxt] \n\t" + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); + + // Run the users function + gfxThreadExit(current->fn(current->param)); + } + +#elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC + + static /*__arm*/ void _gfxTaskSwitch(thread *oldt, thread *newt) { +/* push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + vpush {s16-s31} + str sp, %[oldtcxt] + ldr sp, %[newtcxt] + vpop {s16-s31} + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); +*/ } + + static /* __arm */ void _gfxStartThread(thread *oldt, thread *newt) { + newt->cxt = (char *)newt + newt->size; +/* push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + vpush {s16-s31} + str sp, %[oldtcxt] + ldr sp, %[newtcxt] + : [newtcxt] "=m" (newt->cxt) + : [oldtcxt] "m" (oldt->cxt) + : "memory"); +*/ + // Run the users function + gfxThreadExit(current->fn(current->param)); + } + +#else + #warning "GOS: Threads: You have specified a specific CPU but your compiler is not supported. Defaulting to CLIB switching" +#endif