Main Page   Modules   Data Structures   File List   Globals  

task.h

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2002, 2003, Oliver Tscherwitschke
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 are met:
00007 
00008 1. Redistributions of source code must retain the above copyright notice,
00009    this list of conditions and the following disclaimer.
00010 2. Redistributions in binary form must reproduce the above copyright notice,
00011    this list of conditions and the following disclaimer in the documentation
00012    and/or other materials provided with the distribution.
00013 3. The name of the author may not be used to endorse or promote products
00014    derived from this software without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
00017 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00018 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
00019 EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00020 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00021 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00022 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00023 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00025 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 /* task structure (tcb, task control block) */
00050 struct otos_task
00051 {
00052     OtosTask*           pNext;          /* pointer to next task queue entry */
00053     uint16_t            sp;             /* stack pointer of the task */
00054     uint8_t             state;          /* task state (running, ready or blocked) */
00055     uint8_t             priority;       /* task priority (1..250), 250 = highest */
00056     uint16_t            events;         /* received events */
00057     uint16_t            waitEvents;     /* events to wait for */
00058     OtosMessageQueue*   pWaitMsgQueue;  /* message queue on which the task waits for a message */
00059     OtosMutex*          pWaitMutex;     /* mutex for which the task waits */
00060     uint32_t            sleepTicks;     /* number of ticks to sleep */
00061     uint8_t             name;           /* name of the task */
00062 #ifdef OTOS_STACK_CHECK
00063     uint16_t*           pStack;         /* pointer to first word (lowest address) of task stack */
00064 #endif
00065 #ifdef OTOS_DEBUG_STACK
00066     uint16_t            stacksize;      /* size of the task stack */
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  * function prototypes
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 /* argument constants */
00090 #define SCHED_NORM  0           /* call scheduler normally */
00091 #define SCHED_BLOCK 1           /* block calling task */
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  * These definitions are only intended for otOS-internal use
00133  */
00134 #ifdef COMPILE_OTOS
00135 
00136 /* task states */
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 /* structure of task stack layout. Used for switching tasks */
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 /*    uint8_t r27;  */
00160 /*    uint8_t r26;  */
00161     uint8_t r25;
00162     uint8_t r24;
00163 /*    uint8_t r23;  */
00164 /*    uint8_t r22;  */
00165 /*    uint8_t r21;  */
00166 /*    uint8_t r20;  */
00167 /*    uint8_t r19;  */
00168 /*    uint8_t r18;  */
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 /*    uint8_t r1; */
00186 /*    uint8_t r0; */
00187     uint8_t pcHi;
00188     uint8_t pcLo;
00189 } TaskStackLayout;
00190 
00191 
00192 /* 
00193  * macros for task switching
00194  */
00195 
00196 /*                                                          
00197  * We don't save SREG here because we would only need it    
00198  * if the task switch was triggered by an interrupt. But    
00199  * interrupt routines save SREG by themselves.              
00200  * The same is true for R0 (temp reg) and R1 (zero reg).    
00201  */                                                         
00202 #define TASK_CONTEXT_SAVE_REGS                                  \
00203     __asm__ volatile (                                          \
00204         /* registers */                                         \
00205 /*        "push r0"           "\n\t"    */                      \
00206 /*        "push r1"           "\n\t"    */                      \
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 /*         "push r18"          "\n\t"     */                         \
00224 /*         "push r19"          "\n\t"     */                         \
00225 /*         "push r20"          "\n\t"     */                         \
00226 /*         "push r21"          "\n\t"     */                         \
00227 /*         "push r22"          "\n\t"     */                         \
00228 /*         "push r23"          "\n\t"     */                         \
00229         "push r24"          "\n\t"                              \
00230         "push r25"          "\n\t"                              \
00231 /*         "push r26"          "\n\t"     */                         \
00232 /*         "push r27"          "\n\t"     */                         \
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"      /* RAMPZ */             \
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         /* save stack pointer */                                \
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         /* load stack pointer */                                \
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"      /* get bank */          \
00311         : "=r" (rbank)                                          \
00312         :                                                       \
00313     );                                                          \
00314     SET_RAM_BANK(rbank);                                        \
00315 })
00316                                                                 
00317 #define TASK_CONTEXT_RESTORE_RAMPZ                              \
00318     __asm__ volatile (                                          \
00319         /* load registers */                                    \
00320         "pop r16"           "\n\t"      /* get RAMPZ */         \
00321         "out %0, r16"       "\n\t"      /* output */            \
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 /*         "pop r27"       "\n\t"       */                           \
00333 /*         "pop r26"       "\n\t"       */                           \
00334         "pop r25"       "\n\t"                                  \
00335         "pop r24"       "\n\t"                                  \
00336 /*         "pop r23"       "\n\t"       */                           \
00337 /*         "pop r22"       "\n\t"       */                           \
00338 /*         "pop r21"       "\n\t"       */                           \
00339 /*         "pop r20"       "\n\t"       */                           \
00340 /*         "pop r19"       "\n\t"       */                           \
00341 /*         "pop r18"       "\n\t"       */                           \
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 /*        "pop r1"        "\n\t"    */                          \
00359 /*        "pop r0"        "\n\t"    */                          \
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  * function prototypes
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 /* gobal variables (defined in task.c) */
00402 
00403 extern OtosTask*  volatile g_pRunningTask;      /* the running task */
00404 extern OtosTask*  volatile g_pReadyQueue;       /* ready queue */
00405 extern OtosTask*  volatile g_pBlockedQueue;     /* blocked queue */
00406 extern uint8_t    volatile g_performDispatch;   /* 1 if dispatch must be performed */
00407 
00408 extern uint8_t    volatile g_timeSliceTicks;
00409 extern uint8_t    volatile g_timeSliceCounter;
00410 
00411 
00412 #endif  /* #ifdef COMPILE_OTOS */
00413 
00414 #endif /* TASK_H */

Generated on Sat Jan 25 18:41:43 2003 for otOS by doxygen1.3-rc2