1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
/*
* 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 GFXON. 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 GFXON. 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
|