Go to the documentation of this file.00001
00036
00037
00038
00039
00040
00041 #include <cfg/os.h>
00042
00043 #include <string.h>
00044
00045 #include <sys/atom.h>
00046 #include <sys/heap.h>
00047 #include <sys/thread.h>
00048
00049 #include <avr32/io.h>
00050
00055
00056
00064 typedef struct {
00065 uint32_t csf_cpsr;
00066 uint32_t csf_lr;
00067 uint32_t csf_r7;
00068 uint32_t csf_r6;
00069 uint32_t csf_r5;
00070 uint32_t csf_r4;
00071 uint32_t csf_r3;
00072 uint32_t csf_r2;
00073 uint32_t csf_r1;
00074 uint32_t csf_r0;
00075 } SWITCHFRAME;
00076
00082 typedef struct {
00083 uint32_t cef_pc;
00084 uint32_t cef_r12;
00085 } ENTERFRAME;
00086
00090 static void NutThreadEntry(void) __attribute__ ((naked));
00091 void NutThreadEntry(void)
00092 {
00093
00094 __asm__ volatile ("popm r12, lr\n\t"
00095 "mov pc,lr\n\t"
00096 :::"r12", "lr", "pc");
00097 }
00098
00099
00111 void NutThreadSwitch(void) __attribute__ ((naked));
00112 void NutThreadSwitch(void)
00113 {
00114
00115 __asm__ volatile ("pushm r0-r7, lr \n\t"
00116 "mfsr r10, %1 \n\t"
00117 "pushm r10 \n\t"
00118 "st.w %0, sp \n\t"
00119 :"=m" (runningThread->td_sp)
00120 :"i"(AVR32_SR)
00121 :"r10");
00122
00123
00124 runningThread = runQueue;
00125 runningThread->td_state = TDS_RUNNING;
00126
00127
00128
00129 __asm__ volatile ("ld.w sp, %0\n\t"
00130 "popm r10 \n\t"
00131 "mtsr %1, r10\n\t" "popm r0-r7, lr\n\t"
00132 "mov pc, lr\n\t"
00133 ::"m" (runningThread->td_sp), "i"(AVR32_SR)
00134 :"r10");
00135
00136 #if defined(NUT_CRITICAL_NESTING) && !defined(NUT_CRITICAL_NESTING_STACK)
00137 critical_nesting_level = 0;
00138 #endif
00139 }
00140
00161 HANDLE NutThreadCreate(char *name, void (*fn) (void *), void *arg, size_t stackSize)
00162 {
00163 uint8_t *threadMem;
00164 SWITCHFRAME *sf;
00165 ENTERFRAME *ef;
00166 NUTTHREADINFO *td;
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 if ((threadMem = NutHeapAlloc(stackSize + sizeof(NUTTHREADINFO))) == 0) {
00197 return 0;
00198 }
00199 td = (NUTTHREADINFO *) (threadMem + stackSize);
00200 ef = (ENTERFRAME *) ((uptr_t) td - sizeof(ENTERFRAME));
00201 sf = (SWITCHFRAME *) ((uptr_t) ef - sizeof(SWITCHFRAME));
00202
00203
00204
00205
00206
00207 #if defined(NUTDEBUG_CHECK_STACKMIN) || defined(NUTDEBUG_CHECK_STACK)
00208 {
00209 uint32_t *fip = (uint32_t *) threadMem;
00210 while (fip < (uint32_t *) sf) {
00211 *fip++ = DEADBEEF;
00212 }
00213 }
00214 #else
00215 *((uint32_t *) threadMem) = DEADBEEF;
00216 *((uint32_t *) (threadMem + 4)) = DEADBEEF;
00217 *((uint32_t *) (threadMem + 8)) = DEADBEEF;
00218 *((uint32_t *) (threadMem + 12)) = DEADBEEF;
00219 #endif
00220
00221
00222
00223
00224 ef->cef_pc = (uptr_t) fn;
00225 ef->cef_r12 = (uptr_t) arg;
00226
00227
00228
00229
00230 sf->csf_lr = (uptr_t) NutThreadEntry;
00231 sf->csf_cpsr = (AVR32_SR_M_SUP << AVR32_SR_M_OFFSET);
00232
00233
00234
00235
00236
00237 memcpy(td->td_name, name, sizeof(td->td_name) - 1);
00238 td->td_name[sizeof(td->td_name) - 1] = 0;
00239 td->td_state = TDS_READY;
00240 td->td_sp = (uptr_t) sf;
00241 td->td_priority = 64;
00242 td->td_memory = threadMem;
00243 td->td_timer = 0;
00244 td->td_queue = 0;
00245
00246 NutEnterCritical();
00247 td->td_next = nutThreadList;
00248 nutThreadList = td;
00249 NutThreadAddPriQueue(td, (NUTTHREADINFO **) & runQueue);
00250
00251
00252
00253
00254
00255 if (runningThread == 0) {
00256
00257 runningThread = runQueue;
00258 runningThread->td_state = TDS_RUNNING;
00259
00260 __asm__ volatile (
00261 "ld.w sp, %0\n\t"
00262 "popm r10 \n\t"
00263 "mtsr %1, r10\n\t" "popm r0-r7, lr\n\t"
00264 "mov pc, lr\n\t"
00265 ::"m" (runningThread->td_sp), "i"(AVR32_SR)
00266 :"r10");
00267 }
00268
00269
00270
00271
00272
00273 if (runningThread != runQueue) {
00274 runningThread->td_state = TDS_READY;
00275 NutThreadSwitch();
00276 }
00277 NutExitCritical();
00278
00279 return td;
00280 }
00281