Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2006, Technical University of Munich 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 * \file AVR specific implementation of multithreading architecture 00032 * 00033 * \author Adam Dunkels <adam@sics.se> 00034 * \author Simon Barner <barner@in.tum.de> 00035 * 00036 */ 00037 00038 #include <avr/io.h> 00039 #include <avr/interrupt.h> 00040 #include <stdio.h> 00041 #include "sys/mt.h" 00042 #include "dev/rs232.h" 00043 00044 /*--------------------------------------------------------------------------*/ 00045 void 00046 mtarch_init(void) 00047 { 00048 00049 } 00050 /*--------------------------------------------------------------------------*/ 00051 void 00052 mtarch_start(struct mtarch_thread *t, 00053 void (*function)(void *), void *data) 00054 { 00055 /* Initialize stack with number sequence (used for 00056 * measuring stack usage */ 00057 uint8_t i; 00058 00059 for(i = 0; i < MTARCH_STACKSIZE; ++i) { 00060 t->stack[i] = i; 00061 } 00062 00063 /* 00064 * Push pointer to mt_exit and the thread onto our stack: 00065 * Caveats: 00066 * - The stack is defined as an array of bytes, but pointers are 16 bit wide 00067 * - Function pointers are 16-bit addresses in flash ROM, but e.g. 00068 * avr-objdump displays byte addresses 00069 * - Get the high and low byte of the addresses onto the stack in the 00070 * right order 00071 */ 00072 00073 /* Initialize stack. This is done in reverse order ("pushing") the 00074 * pre-allocated array */ 00075 00076 /* mt_exit function that is to be invoked if the thread dies */ 00077 t->stack[MTARCH_STACKSIZE - 1] = (unsigned char)((unsigned short)mt_exit) & 0xff; 00078 t->stack[MTARCH_STACKSIZE - 2] = (unsigned char)((unsigned short)mt_exit >> 8) & 0xff; 00079 00080 /* The thread handler. Invoked when RET is called in mtarch_exec */ 00081 t->stack[MTARCH_STACKSIZE - 3] = (unsigned char)((unsigned short)function) & 0xff; 00082 t->stack[MTARCH_STACKSIZE - 4] = (unsigned char)((unsigned short)function >> 8) & 0xff; 00083 00084 /* Register r0-r23 in t->stack[MTARCH_STACKSIZE - 5] to 00085 * t->stack[MTARCH_STACKSIZE - 28]. 00086 * 00087 * Per calling convention, the argument to the thread handler function 00088 * (i.e. the 'data' pointer) is passed via r24-r25. 00089 * See http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage) */ 00090 t->stack[MTARCH_STACKSIZE - 29] = (unsigned char)((unsigned short)data) & 0xff; 00091 t->stack[MTARCH_STACKSIZE - 30] = (unsigned char)((unsigned short)data >> 8) & 0xff; 00092 00093 /* Initialize stack pointer: Space for 2 2-byte-addresses and 32 registers, 00094 * post-decrement POP / pre-increment PUSH scheme */ 00095 t->sp = &t->stack[MTARCH_STACKSIZE - 1 - 4 - 32]; 00096 } 00097 00098 /*--------------------------------------------------------------------------*/ 00099 static unsigned char *sptmp; 00100 static struct mtarch_thread *running; 00101 00102 static void 00103 sw(void) 00104 { 00105 /* Disable interrupts while we perform the context switch */ 00106 cli (); 00107 00108 /* Push 32 general purpuse registers */ 00109 __asm__("push r0"); 00110 __asm__("push r1"); 00111 __asm__("push r2"); 00112 __asm__("push r3"); 00113 __asm__("push r4"); 00114 __asm__("push r5"); 00115 __asm__("push r6"); 00116 __asm__("push r7"); 00117 __asm__("push r8"); 00118 __asm__("push r9"); 00119 __asm__("push r10"); 00120 __asm__("push r11"); 00121 __asm__("push r12"); 00122 __asm__("push r13"); 00123 __asm__("push r14"); 00124 __asm__("push r15"); 00125 __asm__("push r16"); 00126 __asm__("push r17"); 00127 __asm__("push r18"); 00128 __asm__("push r19"); 00129 __asm__("push r20"); 00130 __asm__("push r21"); 00131 __asm__("push r22"); 00132 __asm__("push r23"); 00133 __asm__("push r24"); 00134 __asm__("push r25"); 00135 __asm__("push r26"); 00136 __asm__("push r27"); 00137 __asm__("push r28"); 00138 __asm__("push r29"); 00139 __asm__("push r30"); 00140 __asm__("push r31"); 00141 00142 /* Switch stack pointer */ 00143 sptmp = running->sp; 00144 running->sp = (unsigned char*)SP; 00145 SP = (unsigned short)sptmp; 00146 00147 /* Pop 32 general purpose registers */ 00148 __asm__("pop r31"); 00149 __asm__("pop r30"); 00150 __asm__("pop r29"); 00151 __asm__("pop r28"); 00152 __asm__("pop r27"); 00153 __asm__("pop r26"); 00154 __asm__("pop r25"); 00155 __asm__("pop r24"); 00156 __asm__("pop r23"); 00157 __asm__("pop r22"); 00158 __asm__("pop r21"); 00159 __asm__("pop r20"); 00160 __asm__("pop r19"); 00161 __asm__("pop r18"); 00162 __asm__("pop r17"); 00163 __asm__("pop r16"); 00164 __asm__("pop r15"); 00165 __asm__("pop r14"); 00166 __asm__("pop r13"); 00167 __asm__("pop r12"); 00168 __asm__("pop r11"); 00169 __asm__("pop r10"); 00170 __asm__("pop r9"); 00171 __asm__("pop r8"); 00172 __asm__("pop r7"); 00173 __asm__("pop r6"); 00174 __asm__("pop r5"); 00175 __asm__("pop r4"); 00176 __asm__("pop r3"); 00177 __asm__("pop r2"); 00178 __asm__("pop r1"); 00179 __asm__("pop r0"); 00180 00181 /* Renable interrupts */ 00182 sei (); 00183 } 00184 /*--------------------------------------------------------------------------*/ 00185 void 00186 mtarch_exec(struct mtarch_thread *t) 00187 { 00188 running = t; 00189 sw(); 00190 running = NULL; 00191 } 00192 00193 /*--------------------------------------------------------------------------*/ 00194 void 00195 mtarch_remove(void) 00196 { 00197 00198 } 00199 /*--------------------------------------------------------------------------*/ 00200 void 00201 mtarch_yield(void) 00202 { 00203 sw(); 00204 } 00205 /*--------------------------------------------------------------------------*/ 00206 void 00207 mtarch_pstop(void) 00208 { 00209 00210 } 00211 /*--------------------------------------------------------------------------*/ 00212 void 00213 mtarch_pstart(void) 00214 { 00215 00216 } 00217 /*--------------------------------------------------------------------------*/ 00218 void 00219 mtarch_stop(struct mtarch_thread *t) 00220 { 00221 00222 } 00223 /*--------------------------------------------------------------------------*/ 00224 int 00225 mtarch_stack_usage(struct mt_thread *t) 00226 { 00227 uint8_t i; 00228 for(i = 0; i < MTARCH_STACKSIZE; ++i) { 00229 if(t->thread.stack[i] != i) { 00230 break; 00231 } 00232 } 00233 return MTARCH_STACKSIZE - i; 00234 } 00235 /*--------------------------------------------------------------------------*/