Support for Keil compiler RAW32 CPU specific task switching for Cortex M0,1,3,4,7

ugfx_release_2.7
inmarket 2016-12-06 13:47:33 +10:00
parent c1e2863078
commit ad29f4fee0
5 changed files with 107 additions and 70 deletions

View File

@ -27,6 +27,7 @@ FIX: Fixed strange multi-thread issues in GEVENT
FEATURE: Added ILI9488 driver FEATURE: Added ILI9488 driver
FEATURE: Added the ability to display the detected compiler FEATURE: Added the ability to display the detected compiler
FIX: Fixed an illegal instruction in the Cortex M0 task switcher FIX: Fixed an illegal instruction in the Cortex M0 task switcher
FEATURE: Add support for the Keil compiler for RAW32 task switching for Cortex M0,1,3,4,7
*** Release 2.6 *** *** Release 2.6 ***

View File

@ -186,7 +186,7 @@ typedef struct threadQ {
static threadQ readyQ; // The list of ready threads static threadQ readyQ; // The list of ready threads
static threadQ deadQ; // Where we put threads waiting to be deallocated static threadQ deadQ; // Where we put threads waiting to be deallocated
static thread * current; // The current running thread thread * _gfxCurrentThread; // The current running thread - unfortunately this has to be non-static for the keil compiler
static thread mainthread; // The main thread context static thread mainthread; // The main thread context
#undef GFX_THREADS_DONE #undef GFX_THREADS_DONE
@ -399,7 +399,7 @@ static thread mainthread; // The main thread context
// as we are on a different stack. // as we are on a different stack.
// Run the users function. // Run the users function.
gfxThreadExit(current->fn(current->param)); gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
// We never get here as gfxThreadExit() never returns // We never get here as gfxThreadExit() never returns
} }
@ -451,11 +451,11 @@ void _gosThreadsInit(void) {
_gfxThreadsInit(); _gfxThreadsInit();
current = &mainthread; _gfxCurrentThread = &mainthread;
} }
gfxThreadHandle gfxThreadMe(void) { gfxThreadHandle gfxThreadMe(void) {
return (gfxThreadHandle)current; return (gfxThreadHandle)_gfxCurrentThread;
} }
// Check if there are dead processes to deallocate // Check if there are dead processes to deallocate
@ -476,9 +476,9 @@ void gfxYield(void) {
if (!readyQ.head) if (!readyQ.head)
return; return;
Qadd(&readyQ, me = current); Qadd(&readyQ, me = _gfxCurrentThread);
current = Qpop(&readyQ); _gfxCurrentThread = Qpop(&readyQ);
_gfxTaskSwitch(me, current); _gfxTaskSwitch(me, _gfxCurrentThread);
} }
// This routine is not currently public - but it could be. // This routine is not currently public - but it could be.
@ -486,7 +486,7 @@ void gfxThreadExit(threadreturn_t ret) {
thread *me; thread *me;
// Save the results in case someone is waiting // Save the results in case someone is waiting
me = current; me = _gfxCurrentThread;
me->param = (void *)ret; me->param = (void *)ret;
me->flags |= FLG_THD_DEAD; me->flags |= FLG_THD_DEAD;
@ -496,11 +496,11 @@ void gfxThreadExit(threadreturn_t ret) {
Qadd(&deadQ, me); Qadd(&deadQ, me);
// Set the next thread. Exit if it was the last thread // Set the next thread. Exit if it was the last thread
if (!(current = Qpop(&readyQ))) if (!(_gfxCurrentThread = Qpop(&readyQ)))
gfxExit(); gfxExit();
// Switch to the new thread // Switch to the new thread
_gfxTaskSwitch(me, current); _gfxTaskSwitch(me, _gfxCurrentThread);
// We never get back here as we didn't re-queue ourselves // We never get back here as we didn't re-queue ourselves
} }
@ -530,9 +530,9 @@ gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_
t->param = param; t->param = param;
// Add the current thread to the queue because we are starting a new thread. // Add the current thread to the queue because we are starting a new thread.
me = current; me = _gfxCurrentThread;
Qadd(&readyQ, me); Qadd(&readyQ, me);
current = t; _gfxCurrentThread = t;
_gfxStartThread(me, t); _gfxStartThread(me, t);
@ -544,7 +544,7 @@ threadreturn_t gfxThreadWait(gfxThreadHandle th) {
thread * t; thread * t;
t = th; t = th;
if (t == current) if (t == _gfxCurrentThread)
return -1; return -1;
// Mark that we are waiting // Mark that we are waiting

View File

@ -60,42 +60,54 @@
#elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC #elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC
static /*__arm*/ void _gfxTaskSwitch(thread *oldt, thread *newt) { static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) {
/* push {r4, r5, r6, r7, lr} // Save the old context
push {r4, r5, r6, r7, lr}
mov r4, r8 mov r4, r8
mov r5, r9 mov r5, r9
mov r6, r10 mov r6, r10
mov r7, r11 mov r7, r11
push {r4, r5, r6, r7} push {r4, r5, r6, r7}
str sp, %[oldtcxt] str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
ldr sp, %[newtcxt]
// Load the new context
ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
pop {r4, r5, r6, r7} pop {r4, r5, r6, r7}
mov r8, r4 mov r8, r4
mov r9, r5 mov r9, r5
mov r10, r6 mov r10, r6
mov r11, r7 mov r11, r7
pop {r4, r5, r6, r7, pc} pop {r4, r5, r6, r7, pc}
: [newtcxt] "=m" (newt->cxt) }
: [oldtcxt] "m" (oldt->cxt)
: "memory");
*/ }
static /* __arm */ void _gfxStartThread(thread *oldt, thread *newt) { static __asm void _gfxStartThread(thread *oldt, thread *newt) {
newt->cxt = (char *)newt + newt->size; // Calculate where to generate the new context
/* push {r4, r5, r6, r7, lr} // newt->cxt = (char *)newt + newt->size;
ldr r2,[r1,#__cpp(offsetof(thread,size))]
add r2,r2,r1
str r2,[r1,#__cpp(offsetof(thread,cxt))]
// Save the old context
push {r4, r5, r6, r7, lr}
mov r4, r8 mov r4, r8
mov r5, r9 mov r5, r9
mov r6, r10 mov r6, r10
mov r7, r11 mov r7, r11
push {r4, r5, r6, r7} push {r4, r5, r6, r7}
str sp, %[oldtcxt] str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
ldr sp, %[newtcxt]
: [newtcxt] "=m" (newt->cxt) // Load the new (imcomplete) context
: [oldtcxt] "m" (oldt->cxt) ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
: "memory");
*/ // Run the users function - we save some code because gfxThreadExit() never returns
// Run the users function // gfxThreadExit(current->fn(current->param));
gfxThreadExit(current->fn(current->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 gfxThreadExit
} }
#else #else

View File

@ -46,27 +46,39 @@
#elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC #elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC
static /*__arm*/ void _gfxTaskSwitch(thread *oldt, thread *newt) { static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) {
/* push {r4, r5, r6, r7, r8, r9, r10, r11, lr} // Save the old context
str sp, %[oldtcxt] push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
ldr sp, %[newtcxt] str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
// Load the new context
ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} 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) { static __asm void _gfxStartThread(thread *oldt, thread *newt) {
newt->cxt = (char *)newt + newt->size; // Calculate where to generate the new context
/* push {r4, r5, r6, r7, r8, r9, r10, r11, lr} // newt->cxt = (char *)newt + newt->size;
str sp, %[oldtcxt] ldr r2,[r1,#__cpp(offsetof(thread,size))]
ldr sp, %[newtcxt] add r2,r2,r1
: [newtcxt] "=m" (newt->cxt) str r2,[r1,#__cpp(offsetof(thread,cxt))]
: [oldtcxt] "m" (oldt->cxt)
: "memory"); // Save the old context
*/ push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
// Run the users function str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
gfxThreadExit(current->fn(current->param));
// Load the new (imcomplete) context
ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
// Run the users function - we save some code because gfxThreadExit() never returns
// gfxThreadExit(current->fn(current->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 gfxThreadExit
} }
#else #else

View File

@ -48,30 +48,42 @@
#elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC #elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC
static /*__arm*/ void _gfxTaskSwitch(thread *oldt, thread *newt) { static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) {
/* push {r4, r5, r6, r7, r8, r9, r10, r11, lr} // Save the old context
push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
vpush {s16-s31} vpush {s16-s31}
str sp, %[oldtcxt] str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
ldr sp, %[newtcxt]
// Load the new context
ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
vpop {s16-s31} vpop {s16-s31}
pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} 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) { static __asm void _gfxStartThread(thread *oldt, thread *newt) {
newt->cxt = (char *)newt + newt->size; // Calculate where to generate the new context
/* push {r4, r5, r6, r7, r8, r9, r10, r11, lr} // newt->cxt = (char *)newt + newt->size;
ldr r2,[r1,#__cpp(offsetof(thread,size))]
add r2,r2,r1
str r2,[r1,#__cpp(offsetof(thread,cxt))]
// Save the old context
push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
vpush {s16-s31} vpush {s16-s31}
str sp, %[oldtcxt] str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
ldr sp, %[newtcxt]
: [newtcxt] "=m" (newt->cxt) // Load the new (imcomplete) context
: [oldtcxt] "m" (oldt->cxt) ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
: "memory");
*/ // Run the users function - we save some code because gfxThreadExit() never returns
// Run the users function // gfxThreadExit(current->fn(current->param));
gfxThreadExit(current->fn(current->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 gfxThreadExit
} }
#else #else