Reduced code size by removing one PT_WAIT_THREAD call site.
[contiki-2.x.git] / cpu / avr / mtarch.c
blobd9bcd35ec578a95f2fa6fc042108ec2700e5ac84
1 /*
2 * Copyright (c) 2006, Technical University of Munich
3 * All rights reserved.
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.
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.
29 * This file is part of the Contiki operating system.
31 * \file AVR specific implementation of multithreading architecture
33 * \author Adam Dunkels <adam@sics.se>
34 * \author Simon Barner <barner@in.tum.de>
36 * @(#)$Id: mtarch.c,v 1.1 2006/12/22 16:55:53 barner Exp $
39 #include <avr/io.h>
40 #include <avr/interrupt.h>
41 #include <stdio.h>
42 #include "sys/mt.h"
43 #include "dev/rs232.h"
45 /*--------------------------------------------------------------------------*/
46 void
47 mtarch_init(void)
51 /*--------------------------------------------------------------------------*/
52 void
53 mtarch_start(struct mtarch_thread *t,
54 void (*function)(void *), void *data)
56 /* Initialize stack with number sequence (used for
57 * measuring stack usage */
58 uint8_t i;
60 for(i = 0; i < MTARCH_STACKSIZE; ++i) {
61 t->stack[i] = i;
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
74 /* Initialize stack. This is done in reverse order ("pushing") the
75 * pre-allocated array */
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;
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;
85 /* Register r0-r23 in t->stack[MTARCH_STACKSIZE - 5] to
86 * t->stack[MTARCH_STACKSIZE - 28].
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;
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];
99 /*--------------------------------------------------------------------------*/
100 static unsigned char *sptmp;
101 static struct mtarch_thread *running;
103 static void
104 sw(void)
106 /* Disable interrupts while we perform the context switch */
107 cli ();
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");
143 /* Switch stack pointer */
144 sptmp = running->sp;
145 running->sp = (unsigned char*)SP;
146 SP = (unsigned short)sptmp;
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");
182 /* Renable interrupts */
183 sei ();
185 /*--------------------------------------------------------------------------*/
186 void
187 mtarch_exec(struct mtarch_thread *t)
189 running = t;
190 sw();
191 running = NULL;
194 /*--------------------------------------------------------------------------*/
195 void
196 mtarch_remove(void)
200 /*--------------------------------------------------------------------------*/
201 void
202 mtarch_yield(void)
204 sw();
206 /*--------------------------------------------------------------------------*/
207 void
208 mtarch_pstop(void)
212 /*--------------------------------------------------------------------------*/
213 void
214 mtarch_pstart(void)
218 /*--------------------------------------------------------------------------*/
220 mtarch_stack_usage(struct mt_thread *t)
222 uint8_t i;
223 for(i = 0; i < MTARCH_STACKSIZE; ++i) {
224 if(t->thread.stack[i] != i) {
225 break;
228 return MTARCH_STACKSIZE - i;
230 /*--------------------------------------------------------------------------*/