mtarch.c

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  * @(#)$Id: mtarch.c,v 1.1 2006/12/22 16:55:53 barner Exp $
00037  */
00038 
00039 #include <avr/io.h>
00040 #include <avr/interrupt.h>
00041 #include <stdio.h>
00042 #include "sys/mt.h"
00043 #include "dev/rs232.h"
00044 
00045 /*--------------------------------------------------------------------------*/
00046 void
00047 mtarch_init(void)
00048 {
00049   
00050 }
00051 /*--------------------------------------------------------------------------*/
00052 void
00053 mtarch_start(struct mtarch_thread *t,
00054              void (*function)(void *), void *data)
00055 {
00056   /* Initialize stack with number sequence (used for
00057    * measuring stack usage */
00058   uint8_t i;
00059 
00060   for(i = 0; i < MTARCH_STACKSIZE; ++i) {
00061     t->stack[i] = i;
00062   }
00063 
00064   /*
00065    * Push pointer to mt_exit and the thread onto our stack:
00066    * Caveats:
00067    *  - The stack is defined as an array of bytes, but pointers are 16 bit wide
00068    *  - Function pointers are 16-bit addresses in flash ROM, but e.g.
00069    *    avr-objdump displays byte addresses
00070    *  - Get the high and low byte of the addresses onto the stack in the
00071    *    right order
00072    */
00073 
00074   /* Initialize stack. This is done in reverse order ("pushing") the
00075    *  pre-allocated array */
00076 
00077   /* mt_exit function that is to be invoked if the thread dies */
00078   t->stack[MTARCH_STACKSIZE -  1] = (unsigned char)((unsigned short)mt_exit) & 0xff;
00079   t->stack[MTARCH_STACKSIZE -  2] = (unsigned char)((unsigned short)mt_exit >> 8) & 0xff;
00080 
00081   /* The thread handler. Invoked when RET is called in mtarch_exec */
00082   t->stack[MTARCH_STACKSIZE -  3] = (unsigned char)((unsigned short)function) & 0xff;
00083   t->stack[MTARCH_STACKSIZE -  4] = (unsigned char)((unsigned short)function >> 8) & 0xff;
00084 
00085   /* Register r0-r23 in t->stack[MTARCH_STACKSIZE -  5] to
00086    *  t->stack[MTARCH_STACKSIZE -  28].
00087    *
00088    * Per calling convention, the argument to the thread handler function 
00089    *  (i.e. the 'data' pointer) is passed via r24-r25.
00090    * See http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage) */
00091   t->stack[MTARCH_STACKSIZE - 29] = (unsigned char)((unsigned short)data) & 0xff;
00092   t->stack[MTARCH_STACKSIZE - 30] = (unsigned char)((unsigned short)data >> 8) & 0xff;
00093 
00094   /* Initialize stack pointer: Space for 2 2-byte-addresses and 32 registers,
00095    * post-decrement POP / pre-increment PUSH scheme */
00096   t->sp = &t->stack[MTARCH_STACKSIZE - 1 - 4 - 32];
00097 }
00098 
00099 /*--------------------------------------------------------------------------*/
00100 static unsigned char *sptmp;
00101 static struct mtarch_thread *running;
00102 
00103 static void
00104 sw(void)
00105 {
00106   /* Disable interrupts while we perform the context switch */
00107   cli ();
00108 
00109   /* Push 32 general purpuse registers */
00110   __asm__("push r0");
00111   __asm__("push r1");
00112   __asm__("push r2");
00113   __asm__("push r3");
00114   __asm__("push r4");
00115   __asm__("push r5");
00116   __asm__("push r6");
00117   __asm__("push r7");
00118   __asm__("push r8");
00119   __asm__("push r9");
00120   __asm__("push r10");
00121   __asm__("push r11");
00122   __asm__("push r12");
00123   __asm__("push r13");
00124   __asm__("push r14");
00125   __asm__("push r15");
00126   __asm__("push r16");
00127   __asm__("push r17");
00128   __asm__("push r18");
00129   __asm__("push r19");
00130   __asm__("push r20");
00131   __asm__("push r21");
00132   __asm__("push r22");
00133   __asm__("push r23");
00134   __asm__("push r24");
00135   __asm__("push r25");
00136   __asm__("push r26");
00137   __asm__("push r27");
00138   __asm__("push r28");
00139   __asm__("push r29");
00140   __asm__("push r30");
00141   __asm__("push r31");
00142 
00143   /* Switch stack pointer */
00144   sptmp = running->sp;
00145   running->sp = (unsigned char*)SP;
00146   SP = (unsigned short)sptmp;
00147 
00148   /* Pop 32 general purpose registers */
00149   __asm__("pop r31");
00150   __asm__("pop r30");
00151   __asm__("pop r29");
00152   __asm__("pop r28");
00153   __asm__("pop r27");
00154   __asm__("pop r26");
00155   __asm__("pop r25");
00156   __asm__("pop r24");
00157   __asm__("pop r23");
00158   __asm__("pop r22");
00159   __asm__("pop r21");
00160   __asm__("pop r20");
00161   __asm__("pop r19");
00162   __asm__("pop r18");
00163   __asm__("pop r17");
00164   __asm__("pop r16");
00165   __asm__("pop r15");
00166   __asm__("pop r14");
00167   __asm__("pop r13");
00168   __asm__("pop r12");
00169   __asm__("pop r11");
00170   __asm__("pop r10");
00171   __asm__("pop r9");
00172   __asm__("pop r8");
00173   __asm__("pop r7");
00174   __asm__("pop r6");
00175   __asm__("pop r5");
00176   __asm__("pop r4");
00177   __asm__("pop r3");
00178   __asm__("pop r2");
00179   __asm__("pop r1");
00180   __asm__("pop r0");
00181 
00182   /* Renable interrupts */
00183   sei ();
00184 }
00185 /*--------------------------------------------------------------------------*/
00186 void
00187 mtarch_exec(struct mtarch_thread *t)
00188 {
00189   running = t;
00190   sw();
00191   running = NULL;
00192 }
00193 
00194 /*--------------------------------------------------------------------------*/
00195 void
00196 mtarch_remove(void)
00197 {
00198 
00199 }
00200 /*--------------------------------------------------------------------------*/
00201 void
00202 mtarch_yield(void)
00203 {
00204   sw();
00205 }
00206 /*--------------------------------------------------------------------------*/
00207 void
00208 mtarch_pstop(void)
00209 {
00210   
00211 }
00212 /*--------------------------------------------------------------------------*/
00213 void
00214 mtarch_pstart(void)
00215 {
00216   
00217 }
00218 /*--------------------------------------------------------------------------*/
00219 int
00220 mtarch_stack_usage(struct mt_thread *t)
00221 {
00222   uint8_t i;
00223   for(i = 0; i < MTARCH_STACKSIZE; ++i) {
00224     if(t->thread.stack[i] != i) {
00225       break;
00226     }
00227   }
00228   return MTARCH_STACKSIZE - i;
00229 }
00230 /*--------------------------------------------------------------------------*/

Generated on Mon Apr 11 14:23:34 2011 for Contiki 2.5 by  doxygen 1.6.1