Contiki-Inga 3.x
fat-coop-arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Institute of Operating Systems and Computer Networks (TU Brunswick).
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  * Author: Wolf-Bastian Poettner <poettner@ibr.cs.tu-bs.de>
30  */
31 
32  /**
33  * \addtogroup Drivers
34  * @{
35  *
36  * \defgroup fat_coop_driver FAT Driver - Cooperative Additions - Platform specific
37  *
38  * <p></p>
39  * @{
40  *
41  */
42 
43 /**
44  * \file
45  * FAT driver Coop Additions implementation - Platform specific
46  * \author
47  * Wolf-Bastian P�ttner <poettner@ibr.cs.tu-bs.de>
48  */
49 
50 #include "cfs-fat.h"
51 #include "fat_coop.h"
52 #include "fat-coop-arch.h"
53 
54 static uint8_t stack[FAT_COOP_STACK_SIZE];
55 static uint8_t *sp = 0;
56 static uint8_t *sp_save = 0;
57 
58 /**
59  * This Function jumps back to perform_next_step()
60  */
62  /* Change SP back to original */
64 }
65 
66 /**
67  * This function is mostly copied from the arm/mtarch.c file.
68  */
69 void coop_mt_init( void *data ) {
70  memset(stack, 0, FAT_COOP_STACK_SIZE);
71 
72  /* coop_init function that is to be invoked if the thread dies */
73  stack[FAT_COOP_STACK_SIZE - 1] = (unsigned char)((unsigned short)coop_finished_op) & 0xff;
74  stack[FAT_COOP_STACK_SIZE - 2] = (unsigned char)((unsigned short)coop_finished_op >> 8) & 0xff;
75 
76  /* The thread handler. Invoked when RET is called in coop_switch_sp */
77  stack[FAT_COOP_STACK_SIZE - 3] = (unsigned char)((unsigned short)operation) & 0xff;
78  stack[FAT_COOP_STACK_SIZE - 4] = (unsigned char)((unsigned short)operation >> 8) & 0xff;
79 
80  /* Register r0-r23 in t->stack[MTARCH_STACKSIZE - 5] to
81  * t->stack[MTARCH_STACKSIZE - 28].
82  *
83  * Per calling convention, the argument to the thread handler function
84  * (i.e. the 'data' pointer) is passed via r24-r25.
85  * See http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage) */
86  stack[FAT_COOP_STACK_SIZE - 29] = (unsigned char)((unsigned short)data) & 0xff;
87  stack[FAT_COOP_STACK_SIZE - 30] = (unsigned char)((unsigned short)data >> 8) & 0xff;
88 
89  /* Initialize stack pointer: Space for 2 2-byte-addresses and 32 registers,
90  * post-decrement POP / pre-increment PUSH scheme */
91  sp = &stack[FAT_COOP_STACK_SIZE - 1 - 4 - 32];
92 }
93 
94 /**
95  * Set the interal stack to NULL to end process
96  */
97 void coop_mt_stop() {
98  sp = NULL;
99 }
100 
101 /**
102  * Function switches the stack pointers for Atmel based devices (32 GPR's).
103  */
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  if( sp_save == NULL ) {
144  sp_save = (uint8_t *) SP;
145  SP = (uint16_t) sp;
146  } else {
147  sp = (uint8_t *) SP;
148  SP = (uint16_t) sp_save;
149  sp_save = NULL;
150  }
151 
152  /* Pop 32 general purpose registers */
153  __asm__("pop r31");
154  __asm__("pop r30");
155  __asm__("pop r29");
156  __asm__("pop r28");
157  __asm__("pop r27");
158  __asm__("pop r26");
159  __asm__("pop r25");
160  __asm__("pop r24");
161  __asm__("pop r23");
162  __asm__("pop r22");
163  __asm__("pop r21");
164  __asm__("pop r20");
165  __asm__("pop r19");
166  __asm__("pop r18");
167  __asm__("pop r17");
168  __asm__("pop r16");
169  __asm__("pop r15");
170  __asm__("pop r14");
171  __asm__("pop r13");
172  __asm__("pop r12");
173  __asm__("pop r11");
174  __asm__("pop r10");
175  __asm__("pop r9");
176  __asm__("pop r8");
177  __asm__("pop r7");
178  __asm__("pop r6");
179  __asm__("pop r5");
180  __asm__("pop r4");
181  __asm__("pop r3");
182  __asm__("pop r2");
183  __asm__("pop r1");
184  __asm__("pop r0");
185 
186  /* Reenable interrupts */
187  sei ();
188 }
189 
190 /**
191  * Changes Stack pointer to internal Thread. Returns after one step has been completed.
192  *
193  * If this function was called with one specific QueueEntry, then this function must be
194  * called again and again with the same QueueEntry, until the QueueEntry is finished
195  * executing.
196  * \param *entry The QueueEntry, which should be processed.
197  */
198 void perform_next_step( QueueEntry *entry ) {
199  if( sp == NULL ) {
200  coop_mt_init( (void *) entry );
201  }
202 
203  coop_switch_sp();
204 }
205 
206 int calc_free_stack() {
207  int i;
208 
209  for( i = 0; i < FAT_COOP_STACK_SIZE; i++ ) {
210  if(stack[i] != 0) {
211  break;
212  }
213  }
214 
215  return i;
216 }