Contiki 2.5
mtarch.c
1 /*
2  * Copyright (c) 2007, Takahide Matsutsuka.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following
12  * disclaimer in the documentation and/or other materials provided
13  * with the distribution.
14  * 3. The name of the author may not be used to endorse or promote
15  * products derived from this software without specific prior
16  * written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  */
31  /*
32  * \file
33  * Z80 machine-specific implementation for supporting multithread.
34  * \author
35  * Takahide Matsutsuka <markn@markn.org>
36  */
37 #include "sys/mt.h"
38 #include "mtarch.h"
39 
40 /*--------------------------------------------------------------------------*/
41 void
43 {
44 }
45 /*--------------------------------------------------------------------------*/
46 void
47 mtarch_start(struct mtarch_thread *t,
48  void (*function)(void *), void *data)
49 {
50  u16_t i;
51 
52  for(i = 0; i < MTARCH_STACKSIZE; i++) {
53  t->stack[i] = i;
54  }
55 
56  t->sp = &t->stack[MTARCH_STACKSIZE - 1];
57 
58 
59  /* A parameter for method for thread function. */
60  *t->sp = (u16_t)data;
61  --t->sp;
62 
63  /* This will be a return address of thread function. */
64  *t->sp = (u16_t)mt_exit;
65  --t->sp;
66 
67  /* The thread function, is used as a return address of mtarch_switch. */
68  *t->sp = (u16_t)function;
69  --t->sp;
70 
71  /*
72  * Space for registers.
73  * af, bc, de, hl, ix, iy, af', bc', de', hl'
74  */
75  /*
76  * Z80 stack basis:
77  * push stores the data AFTER decrementing sp.
78  * pop reads the data BEFORE incrementing sp.
79  */
80 
81  t->sp = t->sp - 9;
82 }
83 /*--------------------------------------------------------------------------*/
84 static struct mtarch_thread *running_thread;
85 static u16_t *sptmp;
86 static void
87 mtarch_switch()
88 {
89  __asm
90  di ; disable interrupt
91  ; normal registers
92  push af
93  push bc
94  push de
95  push hl
96  push ix
97  push iy
98 
99  ; back registers
100  ex af,af'
101  push af
102  exx
103  push bc
104  push de
105  push hl
106 
107  ; swap between running_thread->sp and SP reg
108  ; _running_thread in asembler below points running_thread->sp
109  ; sptmp = sp;
110  ld (_sptmp),sp
111 
112  ; sp = *(running_thread->sp);
113  ld ix,(_running_thread)
114  ld l,0(ix)
115  ld h,1(ix)
116  ld sp,hl
117 
118  ; running_thread->sp = sptmp;
119  ld hl,(_sptmp)
120  ld 0(ix),l
121  ld 1(ix),h
122 
123  ; back registers
124  pop hl
125  pop de
126  pop bc
127  exx
128  pop af
129  ex af,af'
130 
131  ; normal registers
132  pop iy
133  pop ix
134  pop hl
135  pop de
136  pop bc
137  pop af
138  ei ; enable interrupt
139  __endasm;
140  // here sp indicates the address that point the function
141 }
142 /*--------------------------------------------------------------------------*/
143 void
144 mtarch_exec(struct mtarch_thread *t)
145 {
146  running_thread = t;
147  mtarch_switch();
148  running_thread = NULL;
149 }
150 /*--------------------------------------------------------------------------*/
151 void
153 {
154 }
155 /*--------------------------------------------------------------------------*/
156 void
158 {
159  if (running_thread == NULL) {
160  /* ERROR! we have no runnning thread. */
161  return;
162  }
163  mtarch_switch();
164 }
165 /*--------------------------------------------------------------------------*/
166 void mtarch_stop(struct mtarch_thread *thread)
167 {
168 }
169 /*--------------------------------------------------------------------------*/
170 void
171 mtarch_pstop()
172 {
173 }
174 /*--------------------------------------------------------------------------*/
175 void
176 mtarch_pstart()
177 {
178 }
179 /*--------------------------------------------------------------------------*/
180 int
181 mtarch_stack_usage(struct mtarch_thread *t)
182 {
183  u16_t i;
184  for (i = 0; i < MTARCH_STACKSIZE; i++) {
185  if (t->stack[i] != i) {
186  return MTARCH_STACKSIZE - i;
187  }
188  }
189 
190  return 0;
191 }
192 /*--------------------------------------------------------------------------*/