diff options
-rw-r--r-- | firmware/thread.c | 83 |
1 files changed, 76 insertions, 7 deletions
diff --git a/firmware/thread.c b/firmware/thread.c index ea8d650f15..537a1f0700 100644 --- a/firmware/thread.c +++ b/firmware/thread.c | |||
@@ -37,8 +37,19 @@ struct regs | |||
37 | void *sp; /* Stack pointer (r15) */ | 37 | void *sp; /* Stack pointer (r15) */ |
38 | void* pr; /* Procedure register */ | 38 | void* pr; /* Procedure register */ |
39 | }; | 39 | }; |
40 | |||
41 | #elif CONFIG_CPU == TCC730 | ||
42 | struct regs | ||
43 | { | ||
44 | void *sp; /* Stack pointer (a15) */ | ||
45 | void *start; /* Thread start address */ | ||
46 | int started; /* 0 when not started */ | ||
47 | }; | ||
40 | #endif | 48 | #endif |
41 | 49 | ||
50 | #define DEADBEEF ((int)0xdeadbeef) | ||
51 | |||
52 | |||
42 | int num_threads; | 53 | int num_threads; |
43 | static volatile int num_sleepers; | 54 | static volatile int num_sleepers; |
44 | static int current_thread; | 55 | static int current_thread; |
@@ -109,6 +120,51 @@ static inline void load_context(const void* addr) | |||
109 | "lds %0,pr\n\t" | 120 | "lds %0,pr\n\t" |
110 | "mov.l %0, @(0, r15)" : "+r" (addr)); | 121 | "mov.l %0, @(0, r15)" : "+r" (addr)); |
111 | } | 122 | } |
123 | #elif CONFIG_CPU == TCC730 | ||
124 | /*--------------------------------------------------------------------------- | ||
125 | * Store non-volatile context. | ||
126 | *--------------------------------------------------------------------------- | ||
127 | */ | ||
128 | #define store_context(addr) \ | ||
129 | __asm__ volatile ( \ | ||
130 | "push r0,r1\n\t" \ | ||
131 | "push r2,r3\n\t" \ | ||
132 | "push r4,r5\n\t" \ | ||
133 | "push r6,r7\n\t" \ | ||
134 | "push a8,a9\n\t" \ | ||
135 | "push a10,a11\n\t" \ | ||
136 | "push a12,a13\n\t" \ | ||
137 | "push a14\n\t" \ | ||
138 | "ldw @[%0+0], a15\n\t" : : "a" (addr) ); | ||
139 | |||
140 | /*--------------------------------------------------------------------------- | ||
141 | * Load non-volatile context. | ||
142 | *--------------------------------------------------------------------------- | ||
143 | */ | ||
144 | #define load_context(addr) \ | ||
145 | { \ | ||
146 | if (!(addr)->started) { \ | ||
147 | (addr)->started = 1; \ | ||
148 | __asm__ volatile ( \ | ||
149 | "ldw a15, @[%0+0]\n\t" \ | ||
150 | "ldw a14, @[%0+4]\n\t" \ | ||
151 | "jmp a14\n\t" : : "a" (addr) \ | ||
152 | ); \ | ||
153 | } else \ | ||
154 | __asm__ volatile ( \ | ||
155 | "ldw a15, @[%0+0]\n\t" \ | ||
156 | "pop a14\n\t" \ | ||
157 | "pop a13,a12\n\t" \ | ||
158 | "pop a11,a10\n\t" \ | ||
159 | "pop a9,a8\n\t" \ | ||
160 | "pop r7,r6\n\t" \ | ||
161 | "pop r5,r4\n\t" \ | ||
162 | "pop r3,r2\n\t" \ | ||
163 | "pop r1,r0\n\t" : : "a" (addr) \ | ||
164 | ); \ | ||
165 | \ | ||
166 | } | ||
167 | |||
112 | #endif | 168 | #endif |
113 | 169 | ||
114 | /*--------------------------------------------------------------------------- | 170 | /*--------------------------------------------------------------------------- |
@@ -130,6 +186,10 @@ void switch_thread(void) | |||
130 | /* Enter sleep mode, woken up on interrupt */ | 186 | /* Enter sleep mode, woken up on interrupt */ |
131 | #if CONFIG_CPU == MCF5249 | 187 | #if CONFIG_CPU == MCF5249 |
132 | asm volatile ("stop #0x2000"); | 188 | asm volatile ("stop #0x2000"); |
189 | #elif CONFIG_CPU == TCC730 | ||
190 | /* No sleep instr on the CalmRisc. (?) | ||
191 | * TODO: investigate the SYS instruction | ||
192 | */ | ||
133 | #else | 193 | #else |
134 | SBYCR &= 0x7F; | 194 | SBYCR &= 0x7F; |
135 | asm volatile ("sleep"); | 195 | asm volatile ("sleep"); |
@@ -145,9 +205,9 @@ void switch_thread(void) | |||
145 | store_context(&thread_contexts[current]); | 205 | store_context(&thread_contexts[current]); |
146 | 206 | ||
147 | /* Check if the current thread stack is overflown */ | 207 | /* Check if the current thread stack is overflown */ |
148 | stackptr = thread_stack[current]; | 208 | stackptr = thread_stack[current]; |
149 | #ifndef IRIVER_H100 | 209 | #if ! (defined(IRIVER_H100) || defined (ARCHOS_GMINI120)) |
150 | if(stackptr[0] != 0xdeadbeef) | 210 | if(stackptr[0] != DEADBEEF) |
151 | panicf("Stkov %s", thread_name[current]); | 211 | panicf("Stkov %s", thread_name[current]); |
152 | #endif | 212 | #endif |
153 | 213 | ||
@@ -182,11 +242,11 @@ int create_thread(void* function, void* stack, int stack_size, | |||
182 | return -1; | 242 | return -1; |
183 | 243 | ||
184 | /* Munge the stack to make it easy to spot stack overflows */ | 244 | /* Munge the stack to make it easy to spot stack overflows */ |
185 | stacklen = stack_size / 4; | 245 | stacklen = stack_size / sizeof(int); |
186 | stackptr = stack; | 246 | stackptr = stack; |
187 | for(i = 0;i < stacklen;i++) | 247 | for(i = 0;i < stacklen;i++) |
188 | { | 248 | { |
189 | stackptr[i] = 0xdeadbeef; | 249 | stackptr[i] = DEADBEEF; |
190 | } | 250 | } |
191 | 251 | ||
192 | /* Store interesting information */ | 252 | /* Store interesting information */ |
@@ -194,16 +254,22 @@ int create_thread(void* function, void* stack, int stack_size, | |||
194 | thread_stack[num_threads] = stack; | 254 | thread_stack[num_threads] = stack; |
195 | thread_stack_size[num_threads] = stack_size; | 255 | thread_stack_size[num_threads] = stack_size; |
196 | regs = &thread_contexts[num_threads]; | 256 | regs = &thread_contexts[num_threads]; |
197 | store_context(regs); | ||
198 | #if CONFIG_CPU == MCF5249 | 257 | #if CONFIG_CPU == MCF5249 |
258 | store_context(regs); | ||
199 | regs->sp = (void*)(((unsigned int)stack + stack_size - 4) & ~3); | 259 | regs->sp = (void*)(((unsigned int)stack + stack_size - 4) & ~3); |
200 | /* Put the return address on the stack */ | 260 | /* Put the return address on the stack */ |
201 | *(unsigned long *)(regs->sp) = (int)function; | 261 | *(unsigned long *)(regs->sp) = (int)function; |
202 | #elif CONFIG_CPU == SH7034 | 262 | #elif CONFIG_CPU == SH7034 |
263 | store_context(regs); | ||
203 | /* Subtract 4 to leave room for the PR push in load_context() | 264 | /* Subtract 4 to leave room for the PR push in load_context() |
204 | Align it on an even 32 bit boundary */ | 265 | Align it on an even 32 bit boundary */ |
205 | regs->sp = (void*)(((unsigned int)stack + stack_size - 4) & ~3); | 266 | regs->sp = (void*)(((unsigned int)stack + stack_size - 4) & ~3); |
206 | regs->pr = function; | 267 | regs->pr = function; |
268 | #elif CONFIG_CPU == TCC730 | ||
269 | /* Align stack on word boundary */ | ||
270 | regs->sp = (void*)(((unsigned int)stack + stack_size - 2) & ~1); | ||
271 | regs->start = (void*)function; | ||
272 | regs->started = 0; | ||
207 | #endif | 273 | #endif |
208 | 274 | ||
209 | wake_up_thread(); | 275 | wake_up_thread(); |
@@ -244,6 +310,9 @@ void init_threads(void) | |||
244 | thread_name[0] = main_thread_name; | 310 | thread_name[0] = main_thread_name; |
245 | thread_stack[0] = stackbegin; | 311 | thread_stack[0] = stackbegin; |
246 | thread_stack_size[0] = (int)stackend - (int)stackbegin; | 312 | thread_stack_size[0] = (int)stackend - (int)stackbegin; |
313 | #if CONFIG_CPU == TCC730 | ||
314 | thread_contexts[0].started = 1; | ||
315 | #endif | ||
247 | num_sleepers = 0; | 316 | num_sleepers = 0; |
248 | } | 317 | } |
249 | 318 | ||
@@ -257,7 +326,7 @@ int thread_stack_usage(int threadnum) | |||
257 | 326 | ||
258 | for(i = 0;i < thread_stack_size[threadnum]/sizeof(int);i++) | 327 | for(i = 0;i < thread_stack_size[threadnum]/sizeof(int);i++) |
259 | { | 328 | { |
260 | if(stackptr[i] != 0xdeadbeef) | 329 | if(stackptr[i] != DEADBEEF) |
261 | break; | 330 | break; |
262 | } | 331 | } |
263 | 332 | ||