Contiki 2.5
mtarch.c
1 /*
2  * Copyright (c) 2006, Technical University of Munich
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 copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * \file AVR specific implementation of multithreading architecture
32  *
33  * \author Adam Dunkels <adam@sics.se>
34  * \author Simon Barner <barner@in.tum.de>
35  *
36  * @(#)$Id: mtarch.c,v 1.1 2006/12/22 16:55:53 barner Exp $
37  */
38 
39 #include <avr/io.h>
40 #include <avr/interrupt.h>
41 #include <stdio.h>
42 #include "sys/mt.h"
43 #include "dev/rs232.h"
44 
45 /*--------------------------------------------------------------------------*/
46 void
48 {
49 
50 }
51 /*--------------------------------------------------------------------------*/
52 void
53 mtarch_start(struct mtarch_thread *t,
54  void (*function)(void *), void *data)
55 {
56  /* Initialize stack with number sequence (used for
57  * measuring stack usage */
58  uint8_t i;
59 
60  for(i = 0; i < MTARCH_STACKSIZE; ++i) {
61  t->stack[i] = i;
62  }
63 
64  /*
65  * Push pointer to mt_exit and the thread onto our stack:
66  * Caveats:
67  * - The stack is defined as an array of bytes, but pointers are 16 bit wide
68  * - Function pointers are 16-bit addresses in flash ROM, but e.g.
69  * avr-objdump displays byte addresses
70  * - Get the high and low byte of the addresses onto the stack in the
71  * right order
72  */
73 
74  /* Initialize stack. This is done in reverse order ("pushing") the
75  * pre-allocated array */
76 
77  /* mt_exit function that is to be invoked if the thread dies */
78  t->stack[MTARCH_STACKSIZE - 1] = (unsigned char)((unsigned short)mt_exit) & 0xff;
79  t->stack[MTARCH_STACKSIZE - 2] = (unsigned char)((unsigned short)mt_exit >> 8) & 0xff;
80 
81  /* The thread handler. Invoked when RET is called in mtarch_exec */
82  t->stack[MTARCH_STACKSIZE - 3] = (unsigned char)((unsigned short)function) & 0xff;
83  t->stack[MTARCH_STACKSIZE - 4] = (unsigned char)((unsigned short)function >> 8) & 0xff;
84 
85  /* Register r0-r23 in t->stack[MTARCH_STACKSIZE - 5] to
86  * t->stack[MTARCH_STACKSIZE - 28].
87  *
88  * Per calling convention, the argument to the thread handler function
89  * (i.e. the 'data' pointer) is passed via r24-r25.
90  * See http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage) */
91  t->stack[MTARCH_STACKSIZE - 29] = (unsigned char)((unsigned short)data) & 0xff;
92  t->stack[MTARCH_STACKSIZE - 30] = (unsigned char)((unsigned short)data >> 8) & 0xff;
93 
94  /* Initialize stack pointer: Space for 2 2-byte-addresses and 32 registers,
95  * post-decrement POP / pre-increment PUSH scheme */
96  t->sp = &t->stack[MTARCH_STACKSIZE - 1 - 4 - 32];
97 }
98 
99 /*--------------------------------------------------------------------------*/
100 static unsigned char *sptmp;
101 static struct mtarch_thread *running;
102 
103 static void
104 sw(void)
105 {
106  /* Disable interrupts while we perform the context switch */
107  cli ();
108 
109  /* Push 32 general purpuse registers */
110  __asm__("push r0");
111  __asm__("push r1");
112  __asm__("push r2");
113  __asm__("push r3");
114  __asm__("push r4");
115  __asm__("push r5");
116  __asm__("push r6");
117  __asm__("push r7");
118  __asm__("push r8");
119  __asm__("push r9");
120  __asm__("push r10");
121  __asm__("push r11");
122  __asm__("push r12");
123  __asm__("push r13");
124  __asm__("push r14");
125  __asm__("push r15");
126  __asm__("push r16");
127  __asm__("push r17");
128  __asm__("push r18");
129  __asm__("push r19");
130  __asm__("push r20");
131  __asm__("push r21");
132  __asm__("push r22");
133  __asm__("push r23");
134  __asm__("push r24");
135  __asm__("push r25");
136  __asm__("push r26");
137  __asm__("push r27");
138  __asm__("push r28");
139  __asm__("push r29");
140  __asm__("push r30");
141  __asm__("push r31");
142 
143  /* Switch stack pointer */
144  sptmp = running->sp;
145  running->sp = (unsigned char*)SP;
146  SP = (unsigned short)sptmp;
147 
148  /* Pop 32 general purpose registers */
149  __asm__("pop r31");
150  __asm__("pop r30");
151  __asm__("pop r29");
152  __asm__("pop r28");
153  __asm__("pop r27");
154  __asm__("pop r26");
155  __asm__("pop r25");
156  __asm__("pop r24");
157  __asm__("pop r23");
158  __asm__("pop r22");
159  __asm__("pop r21");
160  __asm__("pop r20");
161  __asm__("pop r19");
162  __asm__("pop r18");
163  __asm__("pop r17");
164  __asm__("pop r16");
165  __asm__("pop r15");
166  __asm__("pop r14");
167  __asm__("pop r13");
168  __asm__("pop r12");
169  __asm__("pop r11");
170  __asm__("pop r10");
171  __asm__("pop r9");
172  __asm__("pop r8");
173  __asm__("pop r7");
174  __asm__("pop r6");
175  __asm__("pop r5");
176  __asm__("pop r4");
177  __asm__("pop r3");
178  __asm__("pop r2");
179  __asm__("pop r1");
180  __asm__("pop r0");
181 
182  /* Renable interrupts */
183  sei ();
184 }
185 /*--------------------------------------------------------------------------*/
186 void
187 mtarch_exec(struct mtarch_thread *t)
188 {
189  running = t;
190  sw();
191  running = NULL;
192 }
193 
194 /*--------------------------------------------------------------------------*/
195 void
197 {
198 
199 }
200 /*--------------------------------------------------------------------------*/
201 void
203 {
204  sw();
205 }
206 /*--------------------------------------------------------------------------*/
207 void
208 mtarch_pstop(void)
209 {
210 
211 }
212 /*--------------------------------------------------------------------------*/
213 void
214 mtarch_pstart(void)
215 {
216 
217 }
218 /*--------------------------------------------------------------------------*/
219 int
220 mtarch_stack_usage(struct mt_thread *t)
221 {
222  uint8_t i;
223  for(i = 0; i < MTARCH_STACKSIZE; ++i) {
224  if(t->thread.stack[i] != i) {
225  break;
226  }
227  }
228  return MTARCH_STACKSIZE - i;
229 }
230 /*--------------------------------------------------------------------------*/