00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00034 #ifndef TASK_H
00035 #define TASK_H
00036
00037
00038 #include <avr/pgmspace.h>
00039
00040 #include "types.h"
00041 #include "otos_cfg.h"
00042 #include "message.h"
00043 #include "hardware.h"
00044
00045
00046 typedef struct otos_task OtosTask;
00047 #include "mutex.h"
00048
00049
00050 struct otos_task
00051 {
00052 OtosTask* pNext;
00053 uint16_t sp;
00054 uint8_t state;
00055 uint8_t priority;
00056 uint16_t events;
00057 uint16_t waitEvents;
00058 OtosMessageQueue* pWaitMsgQueue;
00059 OtosMutex* pWaitMutex;
00060 uint32_t sleepTicks;
00061 uint8_t name;
00062 #ifdef OTOS_STACK_CHECK
00063 uint16_t* pStack;
00064 #endif
00065 #ifdef OTOS_DEBUG_STACK
00066 uint16_t stacksize;
00067 #endif
00068 };
00069
00070
00071 #define OTOS_TASK_FUNCTION(pFunc, pArg) \
00072 void pFunc(void* pArg) __attribute__ ((noreturn)); \
00073 void pFunc(void* pArg)
00074
00075
00076
00077
00078
00079
00080 OtosTask* otosCreateTask(void (*pFunc)(void*), void* pArg, uint8_t prio, uint16_t stacksize, uint8_t name);
00081 inline OtosTask* otosGetRunningTask(void);
00082 uint8_t otosSetPriority(uint8_t prio);
00083 void otosScheduler(uint8_t operation);
00084 extern void otosMain(void) __attribute__ ((noreturn));
00085 uint8_t otosSetPreemtive(uint8_t timeSlice);
00086 inline uint8_t otosGetPreemtive(void);
00087
00088
00089
00090 #define SCHED_NORM 0
00091 #define SCHED_BLOCK 1
00092
00093
00102 #define otosInterruptReturn() otosScheduler(SCHED_NORM)
00103
00108 #define otosBlock() otosScheduler(SCHED_BLOCK)
00109
00110 #ifdef OTOS_PROFILING
00111 uint8_t otosGetIdleRate(void);
00112 #endif
00113
00114
00115
00116 #ifdef OTOS_DEBUG_TASK_QUEUES
00117 void otos_dump_queues(void);
00118 #define DUMP_QUEUES otos_dump_queues()
00119 #else
00120 #define DUMP_QUEUES ((void) 0)
00121 #endif
00122
00123 #ifdef OTOS_DEBUG_STACK
00124 void otos_dump_task_stack(OtosTask* pTask);
00125 void otos_dump_stack(void);
00126 #endif
00127
00128
00129
00130
00131
00132
00133
00134 #ifdef COMPILE_OTOS
00135
00136
00137 #define TASK_RUNNING 1
00138 #define TASK_READY 2
00139 #define TASK_BLOCKED 3
00140
00141
00142 #ifdef OTOS_STACK_CHECK
00143 #define STACK_CHECK 0xaffe
00144 #endif
00145
00146
00147
00148 typedef struct {
00149 #ifdef OTOS_BANKING
00150 uint8_t bank;
00151 #endif
00152 #ifdef RAMPZ
00153 uint8_t rampz;
00154 #endif
00155 uint8_t r31;
00156 uint8_t r30;
00157 uint8_t r29;
00158 uint8_t r28;
00159
00160
00161 uint8_t r25;
00162 uint8_t r24;
00163
00164
00165
00166
00167
00168
00169 uint8_t r17;
00170 uint8_t r16;
00171 uint8_t r15;
00172 uint8_t r14;
00173 uint8_t r13;
00174 uint8_t r12;
00175 uint8_t r11;
00176 uint8_t r10;
00177 uint8_t r9;
00178 uint8_t r8;
00179 uint8_t r7;
00180 uint8_t r6;
00181 uint8_t r5;
00182 uint8_t r4;
00183 uint8_t r3;
00184 uint8_t r2;
00185
00186
00187 uint8_t pcHi;
00188 uint8_t pcLo;
00189 } TaskStackLayout;
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 #define TASK_CONTEXT_SAVE_REGS \
00203 __asm__ volatile ( \
00204 \
00205 \
00206 \
00207 "push r2" "\n\t" \
00208 "push r3" "\n\t" \
00209 "push r4" "\n\t" \
00210 "push r5" "\n\t" \
00211 "push r6" "\n\t" \
00212 "push r7" "\n\t" \
00213 "push r8" "\n\t" \
00214 "push r9" "\n\t" \
00215 "push r10" "\n\t" \
00216 "push r11" "\n\t" \
00217 "push r12" "\n\t" \
00218 "push r13" "\n\t" \
00219 "push r14" "\n\t" \
00220 "push r15" "\n\t" \
00221 "push r16" "\n\t" \
00222 "push r17" "\n\t" \
00223 \
00224 \
00225 \
00226 \
00227 \
00228 \
00229 "push r24" "\n\t" \
00230 "push r25" "\n\t" \
00231 \
00232 \
00233 "push r28" "\n\t" \
00234 "push r29" "\n\t" \
00235 "push r30" "\n\t" \
00236 "push r31" "\n\t" \
00237 : \
00238 : \
00239 )
00240
00241 #define TASK_CONTEXT_SAVE_RAMPZ \
00242 __asm__ volatile ( \
00243 "in r16, %0" "\n\t" \
00244 "push r16" "\n\t" \
00245 : \
00246 : "I" (_SFR_IO_ADDR(RAMPZ)) \
00247 )
00248
00249 #define TASK_CONTEXT_SAVE_BANK \
00250 uint8_t sbank; \
00251 sbank = GET_RAM_BANK(); \
00252 __asm__ volatile ( \
00253 "push %0" "\n\t" \
00254 : \
00255 : "r" (sbank) \
00256 )
00257
00258 #define TASK_CONTEXT_SAVE_SP(pTask) \
00259 __asm__ volatile ( \
00260 \
00261 "in %A0, %1" "\n\t" \
00262 "in %B0, %2" "\n\t" \
00263 : "=r" (pTask->sp) \
00264 : "I" (_SFR_IO_ADDR(SPL)), "I" (_SFR_IO_ADDR(SPH)) \
00265 )
00266
00267
00268
00269 #define TASK_CONTEXT_SAVE1(pTask) \
00270 TASK_CONTEXT_SAVE_REGS;
00271
00272 #ifdef RAMPZ
00273 #define TASK_CONTEXT_SAVE2(pTask) \
00274 TASK_CONTEXT_SAVE1(pTask); \
00275 TASK_CONTEXT_SAVE_RAMPZ;
00276 #else
00277 #define TASK_CONTEXT_SAVE2(pTask) \
00278 TASK_CONTEXT_SAVE1(pTask);
00279 #endif
00280
00281 #ifdef OTOS_BANKING
00282 #define TASK_CONTEXT_SAVE3(pTask) \
00283 TASK_CONTEXT_SAVE2(pTask); \
00284 TASK_CONTEXT_SAVE_BANK;
00285 #else
00286 #define TASK_CONTEXT_SAVE3(pTask) \
00287 TASK_CONTEXT_SAVE2(pTask);
00288 #endif
00289
00290 #define TASK_CONTEXT_SAVE(pTask) \
00291 TASK_CONTEXT_SAVE3(pTask); \
00292 TASK_CONTEXT_SAVE_SP(pTask)
00293
00294
00295
00296
00297 #define TASK_CONTEXT_RESTORE_SP(pTask) \
00298 __asm__ volatile ( \
00299 \
00300 "out %1, %A0" "\n\t" \
00301 "out %2, %B0" "\n\t" \
00302 : \
00303 : "r" (pTask->sp), "I" (_SFR_IO_ADDR(SPL)), \
00304 "I" (_SFR_IO_ADDR(SPH)) \
00305 )
00306
00307 #define TASK_CONTEXT_RESTORE_BANK ({ \
00308 uint8_t rbank; \
00309 __asm__ volatile ( \
00310 "pop %0" "\n\t" \
00311 : "=r" (rbank) \
00312 : \
00313 ); \
00314 SET_RAM_BANK(rbank); \
00315 })
00316
00317 #define TASK_CONTEXT_RESTORE_RAMPZ \
00318 __asm__ volatile ( \
00319 \
00320 "pop r16" "\n\t" \
00321 "out %0, r16" "\n\t" \
00322 : \
00323 : "I" (_SFR_IO_ADDR(RAMPZ)) \
00324 )
00325
00326 #define TASK_CONTEXT_RESTORE_REGS \
00327 __asm__ volatile ( \
00328 "pop r31" "\n\t" \
00329 "pop r30" "\n\t" \
00330 "pop r29" "\n\t" \
00331 "pop r28" "\n\t" \
00332 \
00333 \
00334 "pop r25" "\n\t" \
00335 "pop r24" "\n\t" \
00336 \
00337 \
00338 \
00339 \
00340 \
00341 \
00342 "pop r17" "\n\t" \
00343 "pop r16" "\n\t" \
00344 "pop r15" "\n\t" \
00345 "pop r14" "\n\t" \
00346 "pop r13" "\n\t" \
00347 "pop r12" "\n\t" \
00348 "pop r11" "\n\t" \
00349 "pop r10" "\n\t" \
00350 "pop r9" "\n\t" \
00351 "pop r8" "\n\t" \
00352 "pop r7" "\n\t" \
00353 "pop r6" "\n\t" \
00354 "pop r5" "\n\t" \
00355 "pop r4" "\n\t" \
00356 "pop r3" "\n\t" \
00357 "pop r2" "\n\t" \
00358 \
00359 \
00360 : \
00361 : \
00362 )
00363
00364
00365 #define TASK_CONTEXT_RESTORE1(pTask) \
00366 TASK_CONTEXT_RESTORE_SP(pTask); \
00367
00368 #ifdef OTOS_BANKING
00369 #define TASK_CONTEXT_RESTORE2(pTask) \
00370 TASK_CONTEXT_RESTORE1(pTask); \
00371 TASK_CONTEXT_RESTORE_BANK;
00372 #else
00373 #define TASK_CONTEXT_RESTORE2(pTask) \
00374 TASK_CONTEXT_RESTORE1(pTask);
00375 #endif
00376
00377 #ifdef RAMPZ
00378 #define TASK_CONTEXT_RESTORE3(pTask) \
00379 TASK_CONTEXT_RESTORE2(pTask); \
00380 TASK_CONTEXT_RESTORE_RAMPZ;
00381 #else
00382 #define TASK_CONTEXT_RESTORE3(pTask) \
00383 TASK_CONTEXT_RESTORE2(pTask);
00384 #endif
00385
00386 #define TASK_CONTEXT_RESTORE(pTask) \
00387 TASK_CONTEXT_RESTORE3(pTask); \
00388 TASK_CONTEXT_RESTORE_REGS
00389
00390
00391
00392
00393
00394
00395 int main(void);
00396 OtosTask* otosCreateMainTask(uint8_t prio, uint16_t stacksize);
00397 void otosInsertTaskInQueue(OtosTask* volatile* pQueue, OtosTask* pTask, uint8_t state);
00398 void otosDispatch(OtosTask* pOldTask, OtosTask* pNewTask);
00399 void otosWakeup(OtosTask* pTask);
00400
00401
00402
00403 extern OtosTask* volatile g_pRunningTask;
00404 extern OtosTask* volatile g_pReadyQueue;
00405 extern OtosTask* volatile g_pBlockedQueue;
00406 extern uint8_t volatile g_performDispatch;
00407
00408 extern uint8_t volatile g_timeSliceTicks;
00409 extern uint8_t volatile g_timeSliceCounter;
00410
00411
00412 #endif
00413
00414 #endif