123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- /*
- * 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
- #if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
- #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"
- #elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
- COMPILER_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
- #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"
- "mov r4, sp \n\t"
- "str r4, %[oldtcxt] \n\t"
- "ldr r4, %[newtcxt] \n\t"
- "mov sp, r4 \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 = (void *)(((unsigned)newt + newt->size) & ~7);
- __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"
- "mov r4, sp \n\t"
- "str r4, %[oldtcxt] \n\t"
- "ldr r4, %[newtcxt] \n\t"
- "mov sp, r4 \n\t"
- : [newtcxt] "=m" (newt->cxt)
- : [oldtcxt] "m" (oldt->cxt)
- : "memory");
- // Run the users function
- gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
- }
- #elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC
- #define GFX_THREADS_DONE
- #define _gfxThreadsInit()
- static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) {
- PRESERVE8
- // Save the old context
- push {r4, r5, r6, r7, lr}
- mov r4, r8
- mov r5, r9
- mov r6, r10
- mov r7, r11
- push {r4, r5, r6, r7}
- mov r4, sp
- str r4, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
-
- // Load the new context
- ldr r4, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
- mov sp, r4
- pop {r4, r5, r6, r7}
- mov r8, r4
- mov r9, r5
- mov r10, r6
- mov r11, r7
- pop {r4, r5, r6, r7, pc}
- }
- static __asm void _gfxStartThread(thread *oldt, thread *newt) {
- PRESERVE8
- // Calculate where to generate the new context
- // newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
- ldr r2,[r1,#__cpp(offsetof(thread,size))]
- add r2,r2,r1
- and r2, r2, #0xFFFFFFF8
- str r2,[r1,#__cpp(offsetof(thread,cxt))]
-
- // Save the old context
- push {r4, r5, r6, r7, lr}
- mov r4, r8
- mov r5, r9
- mov r6, r10
- mov r7, r11
- push {r4, r5, r6, r7}
- mov r4, sp
- str r4, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
-
- // Load the new (imcomplete) context
- ldr r4, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
- mov sp, r4
-
- // Run the users function - we save some code because gfxThreadExit() never returns
- // gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
- ldr r2,=__cpp(&_gfxCurrentThread)
- ldr r2,[r2,#0]
- ldr r0,[r2,#__cpp(offsetof(thread,param))]
- ldr r1,[r2,#__cpp(offsetof(thread,fn))]
- blx r1
- mov r4,r0
- bl __cpp(gfxThreadExit)
-
- ALIGN
- }
- #else
- #if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
- #warning "GOS Threads: You have specified a specific CPU but your compiler is not supported. Defaulting to CLIB switching"
- #elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
- COMPILER_WARNING("GOS Threads: You have specified a specific CPU but your compiler is not supported. Defaulting to CLIB switching")
- #endif
- #endif
|