summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/thread.c45
2 files changed, 45 insertions, 1 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 10aecf3a43..82d32fb8ad 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1,6 +1,7 @@
1#ifdef IRIVER_H100 1#ifdef IRIVER_H100
2crt0.S 2crt0.S
3backlight.c 3backlight.c
4thread.c
4#else 5#else
5backlight.c 6backlight.c
6buffer.c 7buffer.c
diff --git a/firmware/thread.c b/firmware/thread.c
index e44db5706d..ea8d650f15 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -16,18 +16,28 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include "config.h"
19#include <stdbool.h> 20#include <stdbool.h>
20#include "thread.h" 21#include "thread.h"
21#include "panic.h" 22#include "panic.h"
22#include "kernel.h" 23#include "kernel.h"
23#include "sh7034.h" 24#include "cpu.h"
24 25
26#if CONFIG_CPU == MCF5249
27struct regs
28{
29 unsigned int d[6]; /* d2-d7 */
30 unsigned int a[5]; /* a2-a6 */
31 void *sp; /* Stack pointer (a7) */
32};
33#elif CONFIG_CPU == SH7034
25struct regs 34struct regs
26{ 35{
27 unsigned int r[7]; /* Registers r8 thru r14 */ 36 unsigned int r[7]; /* Registers r8 thru r14 */
28 void *sp; /* Stack pointer (r15) */ 37 void *sp; /* Stack pointer (r15) */
29 void* pr; /* Procedure register */ 38 void* pr; /* Procedure register */
30}; 39};
40#endif
31 41
32int num_threads; 42int num_threads;
33static volatile int num_sleepers; 43static volatile int num_sleepers;
@@ -43,6 +53,26 @@ extern int stackend[];
43 53
44void switch_thread(void) __attribute__ ((section(".icode"))); 54void switch_thread(void) __attribute__ ((section(".icode")));
45 55
56#if CONFIG_CPU == MCF5249
57/*---------------------------------------------------------------------------
58 * Store non-volatile context.
59 *---------------------------------------------------------------------------
60 */
61static inline void store_context(void* addr)
62{
63 asm volatile ("movem.l %%d2-%%d7/%%a2-%%a7,(%0)\n\t" : : "a" (addr));
64}
65
66/*---------------------------------------------------------------------------
67 * Load non-volatile context.
68 *---------------------------------------------------------------------------
69 */
70static inline void load_context(const void* addr)
71{
72 asm volatile ("movem.l (%0),%%d2-%%d7/%%a2-%%a7\n\t" : : "a" (addr));
73}
74
75#elif CONFIG_CPU == SH7034
46/*--------------------------------------------------------------------------- 76/*---------------------------------------------------------------------------
47 * Store non-volatile context. 77 * Store non-volatile context.
48 *--------------------------------------------------------------------------- 78 *---------------------------------------------------------------------------
@@ -79,6 +109,7 @@ static inline void load_context(const void* addr)
79 "lds %0,pr\n\t" 109 "lds %0,pr\n\t"
80 "mov.l %0, @(0, r15)" : "+r" (addr)); 110 "mov.l %0, @(0, r15)" : "+r" (addr));
81} 111}
112#endif
82 113
83/*--------------------------------------------------------------------------- 114/*---------------------------------------------------------------------------
84 * Switch thread in round robin fashion. 115 * Switch thread in round robin fashion.
@@ -97,8 +128,12 @@ void switch_thread(void)
97 while (num_sleepers == num_threads) 128 while (num_sleepers == num_threads)
98 { 129 {
99 /* Enter sleep mode, woken up on interrupt */ 130 /* Enter sleep mode, woken up on interrupt */
131#if CONFIG_CPU == MCF5249
132 asm volatile ("stop #0x2000");
133#else
100 SBYCR &= 0x7F; 134 SBYCR &= 0x7F;
101 asm volatile ("sleep"); 135 asm volatile ("sleep");
136#endif
102 } 137 }
103 138
104#endif 139#endif
@@ -111,8 +146,10 @@ void switch_thread(void)
111 146
112 /* Check if the current thread stack is overflown */ 147 /* Check if the current thread stack is overflown */
113 stackptr = thread_stack[current]; 148 stackptr = thread_stack[current];
149#ifndef IRIVER_H100
114 if(stackptr[0] != 0xdeadbeef) 150 if(stackptr[0] != 0xdeadbeef)
115 panicf("Stkov %s", thread_name[current]); 151 panicf("Stkov %s", thread_name[current]);
152#endif
116 153
117 load_context(&thread_contexts[next]); 154 load_context(&thread_contexts[next]);
118} 155}
@@ -158,10 +195,16 @@ int create_thread(void* function, void* stack, int stack_size,
158 thread_stack_size[num_threads] = stack_size; 195 thread_stack_size[num_threads] = stack_size;
159 regs = &thread_contexts[num_threads]; 196 regs = &thread_contexts[num_threads];
160 store_context(regs); 197 store_context(regs);
198#if CONFIG_CPU == MCF5249
199 regs->sp = (void*)(((unsigned int)stack + stack_size - 4) & ~3);
200 /* Put the return address on the stack */
201 *(unsigned long *)(regs->sp) = (int)function;
202#elif CONFIG_CPU == SH7034
161 /* Subtract 4 to leave room for the PR push in load_context() 203 /* Subtract 4 to leave room for the PR push in load_context()
162 Align it on an even 32 bit boundary */ 204 Align it on an even 32 bit boundary */
163 regs->sp = (void*)(((unsigned int)stack + stack_size - 4) & ~3); 205 regs->sp = (void*)(((unsigned int)stack + stack_size - 4) & ~3);
164 regs->pr = function; 206 regs->pr = function;
207#endif
165 208
166 wake_up_thread(); 209 wake_up_thread();
167 return num_threads++; /* return the current ID, e.g for remove_thread() */ 210 return num_threads++; /* return the current ID, e.g for remove_thread() */