Contiki 3.x
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  */
37 
38 #include <avr/io.h>
39 #include <avr/interrupt.h>
40 #include <stdio.h>
41 #include "sys/mt.h"
42 #include "dev/rs232.h"
43 
44 /*--------------------------------------------------------------------------*/
45 void
47 {
48 
49 }
50 /*--------------------------------------------------------------------------*/
51 void
52 mtarch_start(struct mtarch_thread *t,
53  void (*function)(void *), void *data)
54 {
55  /* Initialize stack with number sequence (used for
56  * measuring stack usage */
57  uint8_t i;
58 
59  for(i = 0; i < MTARCH_STACKSIZE; ++i) {
60  t->stack[i] = i;
61  }
62 
63  /*
64  * Push pointer to mt_exit and the thread onto our stack:
65  * Caveats:
66  * - The stack is defined as an array of bytes, but pointers are 16 bit wide
67  * - Function pointers are 16-bit addresses in flash ROM, but e.g.
68  * avr-objdump displays byte addresses
69  * - Get the high and low byte of the addresses onto the stack in the
70  * right order
71  */
72 
73  /* Initialize stack. This is done in reverse order ("pushing") the
74  * pre-allocated array */
75 
76  /* mt_exit function that is to be invoked if the thread dies */
77  t->stack[MTARCH_STACKSIZE - 1] = (unsigned char)((unsigned short)mt_exit) & 0xff;
78  t->stack[MTARCH_STACKSIZE - 2] = (unsigned char)((unsigned short)mt_exit >> 8) & 0xff;
79 
80  /* The thread handler. Invoked when RET is called in mtarch_exec */
81  t->stack[MTARCH_STACKSIZE - 3] = (unsigned char)((unsigned short)function) & 0xff;
82  t->stack[MTARCH_STACKSIZE - 4] = (unsigned char)((unsigned short)function >> 8) & 0xff;
83 
84  /* Register r0-r23 in t->stack[MTARCH_STACKSIZE - 5] to
85  * t->stack[MTARCH_STACKSIZE - 28].
86  *
87  * Per calling convention, the argument to the thread handler function
88  * (i.e. the 'data' pointer) is passed via r24-r25.
89  * See http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage) */
90  t->stack[MTARCH_STACKSIZE - 29] = (unsigned char)((unsigned short)data) & 0xff;
91  t->stack[MTARCH_STACKSIZE - 30] = (unsigned char)((unsigned short)data >> 8) & 0xff;
92 
93  /* Initialize stack pointer: Space for 2 2-byte-addresses and 32 registers,
94  * post-decrement POP / pre-increment PUSH scheme */
95  t->sp = &t->stack[MTARCH_STACKSIZE - 1 - 4 - 32];
96 }
97 
98 /*--------------------------------------------------------------------------*/
99 static unsigned char *sptmp;
100 static struct mtarch_thread *running;
101 
102 static void
103 sw(void)
104 {
105  /* Disable interrupts while we perform the context switch */
106  cli ();
107 
108  /* Push 32 general purpuse registers */
109  __asm__("push r0");
110  __asm__("push r1");
111  __asm__("push r2");
112  __asm__("push r3");
113  __asm__("push r4");
114  __asm__("push r5");
115  __asm__("push r6");
116  __asm__("push r7");
117  __asm__("push r8");
118  __asm__("push r9");
119  __asm__("push r10");
120  __asm__("push r11");
121  __asm__("push r12");
122  __asm__("push r13");
123  __asm__("push r14");
124  __asm__("push r15");
125  __asm__("push r16");
126  __asm__("push r17");
127  __asm__("push r18");
128  __asm__("push r19");
129  __asm__("push r20");
130  __asm__("push r21");
131  __asm__("push r22");
132  __asm__("push r23");
133  __asm__("push r24");
134  __asm__("push r25");
135  __asm__("push r26");
136  __asm__("push r27");
137  __asm__("push r28");
138  __asm__("push r29");
139  __asm__("push r30");
140  __asm__("push r31");
141 
142  /* Switch stack pointer */
143  sptmp = running->sp;
144  running->sp = (unsigned char*)SP;
145  SP = (unsigned short)sptmp;
146 
147  /* Pop 32 general purpose registers */
148  __asm__("pop r31");
149  __asm__("pop r30");
150  __asm__("pop r29");
151  __asm__("pop r28");
152  __asm__("pop r27");
153  __asm__("pop r26");
154  __asm__("pop r25");
155  __asm__("pop r24");
156  __asm__("pop r23");
157  __asm__("pop r22");
158  __asm__("pop r21");
159  __asm__("pop r20");
160  __asm__("pop r19");
161  __asm__("pop r18");
162  __asm__("pop r17");
163  __asm__("pop r16");
164  __asm__("pop r15");
165  __asm__("pop r14");
166  __asm__("pop r13");
167  __asm__("pop r12");
168  __asm__("pop r11");
169  __asm__("pop r10");
170  __asm__("pop r9");
171  __asm__("pop r8");
172  __asm__("pop r7");
173  __asm__("pop r6");
174  __asm__("pop r5");
175  __asm__("pop r4");
176  __asm__("pop r3");
177  __asm__("pop r2");
178  __asm__("pop r1");
179  __asm__("pop r0");
180 
181  /* Renable interrupts */
182  sei ();
183 }
184 /*--------------------------------------------------------------------------*/
185 void
187 {
188  running = t;
189  sw();
190  running = NULL;
191 }
192 
193 /*--------------------------------------------------------------------------*/
194 void
196 {
197 
198 }
199 /*--------------------------------------------------------------------------*/
200 void
202 {
203  sw();
204 }
205 /*--------------------------------------------------------------------------*/
206 void
207 mtarch_pstop(void)
208 {
209 
210 }
211 /*--------------------------------------------------------------------------*/
212 void
213 mtarch_pstart(void)
214 {
215 
216 }
217 /*--------------------------------------------------------------------------*/
218 void
220 {
221 
222 }
223 /*--------------------------------------------------------------------------*/
224 int
225 mtarch_stack_usage(struct mt_thread *t)
226 {
227  uint8_t i;
228  for(i = 0; i < MTARCH_STACKSIZE; ++i) {
229  if(t->thread.stack[i] != i) {
230  break;
231  }
232  }
233  return MTARCH_STACKSIZE - i;
234 }
235 /*--------------------------------------------------------------------------*/
void mtarch_init(void)
Initialize the architecture specific support functions for the multi-thread library.
Definition: mtarch.c:49
void mtarch_yield(void)
Yield the processor.
Definition: mtarch.c:89
Header file for the preemptive multitasking library for Contiki.
void mtarch_remove(void)
Uninstall library and clean up.
Definition: mtarch.c:54
void mtarch_start(struct mtarch_thread *thread, void(*function)(void *data), void *data)
Setup the stack frame for a thread that is being started.
Definition: mtarch.c:59
#define NULL
The null pointer.
void mtarch_exec(struct mtarch_thread *thread)
Start executing a thread.
Definition: mtarch.c:95
void mt_exit(void)
Exit a thread.
Definition: mt.c:101
void mtarch_stop(struct mtarch_thread *thread)
Clean up the stack of a thread.
Definition: mtarch.c:110
Copyright (c) 2014, Analog Devices, Inc.
Definition: mtarch.h:42