Contiki 2.6

mtarch.c

00001 /*
00002  * Copyright (c) 2007, Takahide Matsutsuka.
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
00011  *    copyright notice, this list of conditions and the following
00012  *    disclaimer in the documentation and/or other materials provided
00013  *    with the distribution.
00014  * 3. The name of the author may not be used to endorse or promote
00015  *    products derived from this software without specific prior
00016  *    written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00019  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00022  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00024  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00027  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  */
00031  /*
00032   * \file
00033   *     Z80 machine-specific implementation for supporting multithread.
00034   * \author
00035   *     Takahide Matsutsuka <markn@markn.org>
00036   */
00037 #include "sys/mt.h"
00038 #include "mtarch.h"
00039 
00040 /*--------------------------------------------------------------------------*/
00041 void
00042 mtarch_init(void)
00043 {
00044 }
00045 /*--------------------------------------------------------------------------*/
00046 void
00047 mtarch_start(struct mtarch_thread *t,
00048              void (*function)(void *), void *data)
00049 {
00050   uint16_t i;
00051   
00052   for(i = 0; i < MTARCH_STACKSIZE; i++) {
00053     t->stack[i] = i;
00054   }
00055 
00056   t->sp = &t->stack[MTARCH_STACKSIZE - 1];
00057 
00058   
00059   /* A parameter for method for thread function. */
00060   *t->sp = (uint16_t)data;
00061   --t->sp;
00062 
00063   /* This will be a return address of thread function. */
00064   *t->sp = (uint16_t)mt_exit;
00065   --t->sp;
00066 
00067   /* The thread function, is used as a return address of mtarch_switch. */
00068   *t->sp = (uint16_t)function;
00069   --t->sp;
00070 
00071   /*
00072    * Space for registers.
00073    * af, bc, de, hl, ix, iy, af', bc', de', hl'
00074    */
00075   /*
00076    * Z80 stack basis:  
00077    * push stores the data AFTER decrementing sp. 
00078    * pop reads the data BEFORE incrementing sp.
00079    */
00080 
00081   t->sp = t->sp - 9;
00082 }
00083 /*--------------------------------------------------------------------------*/
00084 static struct mtarch_thread *running_thread;
00085 static uint16_t *sptmp;
00086 static void
00087 mtarch_switch()
00088 {
00089   __asm
00090     di  ; disable interrupt
00091     ; normal registers
00092     push af
00093     push bc
00094     push de
00095     push hl
00096     push ix
00097     push iy
00098 
00099     ; back registers
00100     ex af,af'
00101     push af
00102     exx
00103     push bc
00104     push de
00105     push hl
00106 
00107     ; swap between running_thread->sp and SP reg
00108     ; _running_thread in asembler below points running_thread->sp
00109     ; sptmp = sp;
00110     ld (_sptmp),sp
00111     
00112     ; sp = *(running_thread->sp);
00113     ld ix,(_running_thread)
00114     ld l,0(ix)
00115     ld h,1(ix)
00116     ld sp,hl
00117     
00118     ; running_thread->sp = sptmp;
00119     ld hl,(_sptmp)
00120     ld 0(ix),l
00121     ld 1(ix),h
00122 
00123     ; back registers
00124     pop hl
00125     pop de
00126     pop bc
00127     exx
00128     pop af
00129     ex af,af'
00130 
00131     ; normal registers
00132     pop iy
00133     pop ix  
00134     pop hl
00135     pop de
00136     pop bc
00137     pop af
00138     ei  ; enable interrupt
00139   __endasm;
00140   // here sp indicates the address that point the function
00141 }
00142 /*--------------------------------------------------------------------------*/
00143 void
00144 mtarch_exec(struct mtarch_thread *t)
00145 {
00146   running_thread = t;
00147   mtarch_switch();
00148   running_thread = NULL;
00149 }
00150 /*--------------------------------------------------------------------------*/
00151 void
00152 mtarch_remove()
00153 {
00154 }
00155 /*--------------------------------------------------------------------------*/
00156 void
00157 mtarch_yield()
00158 {
00159   if (running_thread == NULL) {
00160     /* ERROR! we have no runnning thread. */
00161     return; 
00162   }
00163   mtarch_switch();
00164 }
00165 /*--------------------------------------------------------------------------*/
00166 void mtarch_stop(struct mtarch_thread *thread)
00167 {
00168 }
00169 /*--------------------------------------------------------------------------*/
00170 void
00171 mtarch_pstop()
00172 {  
00173 }
00174 /*--------------------------------------------------------------------------*/
00175 void
00176 mtarch_pstart()
00177 {  
00178 }
00179 /*--------------------------------------------------------------------------*/
00180 int
00181 mtarch_stack_usage(struct mtarch_thread *t)
00182 {
00183   uint16_t i;
00184   for (i = 0; i < MTARCH_STACKSIZE; i++) {
00185     if (t->stack[i] != i) {
00186       return MTARCH_STACKSIZE - i;
00187     }
00188   }
00189   
00190   return 0;
00191 }
00192 /*--------------------------------------------------------------------------*/