-/* -------------------------------- Arctic Core ------------------------------
- * Arctic Core - the open source AUTOSAR platform http://arccore.com
- *
- * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
- *
- * This source code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- * -------------------------------- Arctic Core ------------------------------*/
-
+/* -------------------------------- Arctic Core ------------------------------\r
+ * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
+ *\r
+ * Copyright (C) 2009 ArcCore AB <contact@arccore.com>\r
+ *\r
+ * This source code is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 as published by the\r
+ * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
+ *\r
+ * This program is distributed in the hope that it will be useful, but\r
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\r
+ * for more details.\r
+ * -------------------------------- Arctic Core ------------------------------*/\r
+\r
#include <stdlib.h>\r
-#include "Os.h"
-
-#include "internal.h"
-#include "arc.h"
-#include "arch.h"
-
-/** @req OS067 */
-
-_Bool os_pcb_pid_valid( OsPcbType *restrict pcb ) {
- return ( pcb->pid > Os_CfgGetTaskCnt() ) ? 0 : 1;
-}
-/**
- * Start an extended task.
- * Tasks done:
- * - Grab the internal resource for the process
- * - Set it running state.
- * - Start to execute the process
- *
- */
-void Os_TaskStartExtended( void ) {
- OsPcbType *pcb;
-
- PRETASKHOOK();
-
- pcb = Os_TaskGetCurrent();
- Os_ResourceGetInternal();
- Os_TaskMakeRunning(pcb);
-
- Os_ArchFirstCall();
-
- /** @req OS239 */
- Irq_Disable();
- if( Os_IrqAnyDisabled() ) {
- Os_IrqClearAll();
- }
-
-// TODO:Dont I have to check this at terminate task also?
-
- /** @req OS069 */
- ERRORHOOK(E_OS_MISSINGEND);
-
- /** @req OS052 */
- TerminateTask();
-}
-
-/**
- * Start an basic task.
- * See extended task.
- */
-
-void Os_TaskStartBasic( void ) {
- OsPcbType *pcb;
-
- PRETASKHOOK();
-
- pcb = Os_TaskGetCurrent();
- Os_ResourceGetInternal();
- Os_TaskMakeRunning(pcb);
- Os_ArchFirstCall();
-
-
- /** @req OS239 */
- Irq_Disable();
- if( Os_IrqAnyDisabled() ) {
- Os_IrqClearAll();
- }
-
- /** @req OS069 */
- ERRORHOOK(E_OS_MISSINGEND);
-
- /** @req OS052 */
- TerminateTask();
-}
-
-
-static void Os_StackSetup( OsPcbType *pcbPtr ) {
- uint8_t *bottom;
-
- /* Find bottom of the stack so that we can place the
- * context there.
- *
- * stack bottom = high address. stack top = low address
- */
- bottom = (uint8_t *)pcbPtr->stack.top + pcbPtr->stack.size;
- pcbPtr->stack.curr = bottom;
- // TODO: alignments here..
- // TODO :use function os_arch_get_call_size() ??
-
- // Make some space for back-chain.
- bottom -= 16;
- // Set the current stack so that it points to the context
- pcbPtr->stack.curr = bottom - Os_ArchGetScSize();
-
- Os_StackSetEndmark(pcbPtr);
-}
-
-/**
- * Fill the stack with a predefined pattern
- *
- * @param pcbPtr Pointer to the pcb to fill with pattern
- */
-static void Os_StackFill(OsPcbType *pcbPtr) {
- uint8_t *p = pcbPtr->stack.curr;
-
- assert(pcbPtr->stack.curr > pcbPtr->stack.top);
-
- while (p > (uint8_t *) pcbPtr->stack.top) {
- --p;
- *p = STACK_PATTERN;
- }
-}
-
-#if 0
-/**
- *
- * @param pcbPtr
- */
-static void Os_TaskSetEntry(OsPcbType *pcbPtr ) {
-
-}
-#endif
-
-
-/**
- * Setup the context for a pcb. The context differs for different arch's
- * so we call the arch dependent functions also.
- * The context at setup is always a small context.
- *
- * @param pcb Ptr to the pcb to setup context for.
- */
-void Os_ContextInit( OsPcbType *pcb ) {
-
- if( pcb->autostart ) {
- Os_TaskMakeReady(pcb);
- } else {
- pcb->state = ST_SUSPENDED;
- }
-
- Os_StackSetup(pcb);
- Os_StackFill(pcb);
- Os_ArchSetTaskEntry(pcb);
-
- Os_ArchSetupContext(pcb);
-}
-
-/**
- *
- * @param pcb
- */
-void Os_ContextReInit( OsPcbType *pcbPtr ) {
- Os_StackSetup(pcbPtr);
-}
-
-/**
- * Search for a specific task in the pcb list.
- *
- * @param tid The task id to search for
- * @return Ptr to the found pcb or NULL
- */
-OsPcbType *os_find_task( TaskType tid ) {
- OsPcbType *i_pcb;
-
- /* TODO: Implement this as an array */
- TAILQ_FOREACH(i_pcb,& os_sys.pcb_head,pcb_list) {
- if(i_pcb->pid == tid ) {
- return i_pcb;
- }
- }
- assert(0);
- return NULL;
-}
-
-/**
- * Adds a pcb to the list of pcb's
- * @param pcb
- */
-TaskType Os_AddTask( OsPcbType *pcb ) {
- long msr;
-
- Irq_Save(msr); // Save irq status and disable interrupts
-
- pcb->pid = os_sys.task_cnt;
- // Add to list of PCB's
- TAILQ_INSERT_TAIL(& os_sys.pcb_head,pcb,pcb_list);
- os_sys.task_cnt++;
-
- Irq_Restore(msr); // Restore interrupts
- return pcb->pid;
-}
-
-
-#define PRIO_ILLEGAL -100
-
-/**
- * Find the top priority task. Even the running task is included.
- * TODO: There should be a priority queue (using a heap?) here instead.
- * giving O(log n) for instertions and (1) for getting the top
- * prio task. The curerent implementation is ehhhh bad.
- * @return
- */
-
-OsPcbType *Os_TaskGetTop( void ){
- OsPcbType *i_pcb;
- OsPcbType *top_prio_pcb = NULL;
- OsPriorityType top_prio = PRIO_ILLEGAL;
-
- OS_DEBUG(D_TASK,"os_find_top_prio_proc\n");
-
- TAILQ_FOREACH(i_pcb,& os_sys.ready_head,ready_list) {
- // all ready task are canidates
- if( i_pcb->state & (ST_READY|ST_RUNNING)) {
- if( top_prio != PRIO_ILLEGAL ) {
- if( i_pcb->prio > top_prio ) {
- top_prio = i_pcb->prio;
- top_prio_pcb = i_pcb;
- }
- } else {
- top_prio = i_pcb->prio;
- top_prio_pcb = i_pcb;
- }
- } else {
- assert(0);
- }
- }
-
- assert(top_prio_pcb!=NULL);
-
- OS_DEBUG(D_TASK,"Found %s\n",top_prio_pcb->name);
-
- return top_prio_pcb;
-}
-
-
-#define USE_LDEBUG_PRINTF
-#include "debug.h"
-
-// we come here from
-// - WaitEvent()
-// old_pcb -> WAITING
-// new_pcb -> READY(RUNNING)
-// - Schedule(),
-// old_pcb -> READY
-// new_pcb -> READY/RUNNING
-
-/*
- * two strategies
- * 1. When running ->
- * - remove from ready queue
- * - set state == ST_RUNNING
- *
- * 2. When running ->
- * * leave in ready queue
- * * set state == ST_RUNNING
- * - ready queue and ST_READY not the same
- * + No need to remove the running process from ready queue
- */
-
-OsPcbType *Os_FindTopPrioTask( void ) {
-
-
- return NULL;
-}
-
-/**
- * Tries to Dispatch.
- *
- * Used by:
- * ActivateTask()
- * WaitEvent()
- * TerminateTask()
- *
- * @param force Force a re-scheduling
- *
- */
-void Os_Dispatch( _Bool force ) {
- OsPcbType *pcbPtr;
- OsPcbType *currPcbPtr;
- (void)force;
-
- assert(os_sys.int_nest_cnt == 0);
- assert(os_sys.scheduler_lock == 0 );
-
- pcbPtr = Os_TaskGetTop();
- currPcbPtr = Os_TaskGetCurrent();
- /* Swap if we found any process or are forced (multiple activations)*/
- if( pcbPtr != currPcbPtr ) {
- /* Add us to the ready list */
- if( currPcbPtr->state & ST_RUNNING ) {
- Os_TaskRunningToReady(currPcbPtr);
- }
-
- /*
- * Swap context
- */
- /** @req OS052 */
- POSTTASKHOOK();
- assert(pcbPtr!=NULL);
-
- Os_ResourceReleaseInternal();
-
-#if (OS_STACK_MONITORING == 1)
- if( !Os_StackIsEndmarkOk(currPcbPtr) ) {
-#if ( OS_SC1 == 1) || ( OS_SC2 == 1)
- /** @req OS068 */
- ShutdownOS(E_OS_STACKFAULT);
-#else
-#error SC3 or SC4 not supported. Protection hook should be called here
-#endif
- }
-#endif
-
- Os_ArchSwapContext(currPcbPtr,pcbPtr);
-
- pcbPtr = Os_TaskGetCurrent();
- Os_TaskMakeRunning(pcbPtr);
-
- Os_ResourceGetInternal();
-
- PRETASKHOOK();
-
- } else {
- if( Os_GetOp() != OP_SET_EVENT ) {
-
- /* We want to run the same task, again. This only happens
- * when we have multiple activation of a basic task (
- * extended tasks have an activation limit of 1)
- */
-
- /* Setup the stack again, and just call the basic task */
- Os_StackSetup(pcbPtr);
- Os_ArchSetSpAndCall(pcbPtr->stack.curr,Os_TaskStartBasic);
- } else {
- /* Two cases:
- * 1. SetEvent() on itself
- * 2. SetEvent()
- *
- *
- * */
-
- }
- }
-}
-
-// We come here from
-// - os_init
-
-volatile static int a1, b1, c1;
-volatile static OsPcbType *o1;
-volatile static OsPcbType *n1;
-
-void hej(int a, int b, int c, OsPcbType *o, OsPcbType *n) {
- a1 = a;
- b1 = b;
- c1 = c;
- o1 = o;
- n1 = n;
-}
-
-/**
- * Called when a task is to be run for the first time.
- */
-void Os_TaskSwapContextTo(OsPcbType *old_pcb, OsPcbType *new_pcb ) {
-
- hej(1, 2, 3, old_pcb, new_pcb);
-
- Os_ArchSwapContextTo(old_pcb,new_pcb);
- /* TODO: When do we return here ?? */
-}
-
-
-void Os_Arc_GetStackInfo( TaskType task, StackInfoType *s) {
- OsPcbType *pcb = os_get_pcb(task);
-
- s->curr = Os_ArchGetStackPtr();
- s->top = pcb->stack.top;
- s->at_swap = pcb->stack.curr;
- s->size = pcb->stack.size;
- s->usage = (void *)Os_StackGetUsage(pcb);
-}
-
-
-/**
- * Returns the state of a task (running, ready, waiting, suspended)
- * at the time of calling GetTaskState.
- *
- * @param TaskId Task reference
- * @param State Reference to the state of the task
- */
-
+#include "Os.h"\r
+\r
+#include "internal.h"\r
+#include "arc.h"\r
+#include "arch.h"\r
+\r
+/** @req OS067 */\r
+\r
+_Bool os_pcb_pid_valid( OsPcbType *restrict pcb ) {\r
+ return ( pcb->pid > Os_CfgGetTaskCnt() ) ? 0 : 1;\r
+}\r
+/**\r
+ * Start an extended task.\r
+ * Tasks done:\r
+ * - Grab the internal resource for the process\r
+ * - Set it running state.\r
+ * - Start to execute the process\r
+ *\r
+ */\r
+void Os_TaskStartExtended( void ) {\r
+ OsPcbType *pcb;\r
+\r
+ pcb = Os_TaskGetCurrent();\r
+ Os_ResourceGetInternal();\r
+ Os_TaskMakeRunning(pcb);\r
+\r
+ PRETASKHOOK();\r
+\r
+ Os_ArchFirstCall();\r
+\r
+ /** @req OS239 */\r
+ Irq_Disable();\r
+ if( Os_IrqAnyDisabled() ) {\r
+ Os_IrqClearAll();\r
+ }\r
+\r
+// TODO:Dont I have to check this at terminate task also?\r
+\r
+ /** @req OS069 */\r
+ ERRORHOOK(E_OS_MISSINGEND);\r
+\r
+ /** @req OS052 */\r
+ TerminateTask();\r
+}\r
+\r
+/**\r
+ * Start an basic task.\r
+ * See extended task.\r
+ */\r
+\r
+void Os_TaskStartBasic( void ) {\r
+ OsPcbType *pcb;\r
+\r
+ pcb = Os_TaskGetCurrent();\r
+ Os_ResourceGetInternal();\r
+ Os_TaskMakeRunning(pcb);\r
+\r
+ PRETASKHOOK();\r
+\r
+ Os_ArchFirstCall();\r
+\r
+\r
+ /** @req OS239 */\r
+ Irq_Disable();\r
+ if( Os_IrqAnyDisabled() ) {\r
+ Os_IrqClearAll();\r
+ }\r
+\r
+ /** @req OS069 */\r
+ ERRORHOOK(E_OS_MISSINGEND);\r
+\r
+ /** @req OS052 */\r
+ TerminateTask();\r
+}\r
+\r
+\r
+static void Os_StackSetup( OsPcbType *pcbPtr ) {\r
+ uint8_t *bottom;\r
+\r
+ /* Find bottom of the stack so that we can place the\r
+ * context there.\r
+ *\r
+ * stack bottom = high address. stack top = low address\r
+ */\r
+ bottom = (uint8_t *)pcbPtr->stack.top + pcbPtr->stack.size;\r
+ pcbPtr->stack.curr = bottom;\r
+ // TODO: alignments here..\r
+ // TODO :use function os_arch_get_call_size() ??\r
+\r
+ // Make some space for back-chain.\r
+ bottom -= 16;\r
+ // Set the current stack so that it points to the context\r
+ pcbPtr->stack.curr = bottom - Os_ArchGetScSize();\r
+\r
+ Os_StackSetEndmark(pcbPtr);\r
+}\r
+\r
+/**\r
+ * Fill the stack with a predefined pattern\r
+ *\r
+ * @param pcbPtr Pointer to the pcb to fill with pattern\r
+ */\r
+static void Os_StackFill(OsPcbType *pcbPtr) {\r
+ uint8_t *p = pcbPtr->stack.curr;\r
+\r
+ assert(pcbPtr->stack.curr > pcbPtr->stack.top);\r
+\r
+ while (p > (uint8_t *) pcbPtr->stack.top) {\r
+ --p;\r
+ *p = STACK_PATTERN;\r
+ }\r
+}\r
+\r
+#if 0\r
+/**\r
+ *\r
+ * @param pcbPtr\r
+ */\r
+static void Os_TaskSetEntry(OsPcbType *pcbPtr ) {\r
+\r
+}\r
+#endif\r
+\r
+\r
+/**\r
+ * Setup the context for a pcb. The context differs for different arch's\r
+ * so we call the arch dependent functions also.\r
+ * The context at setup is always a small context.\r
+ *\r
+ * @param pcb Ptr to the pcb to setup context for.\r
+ */\r
+void Os_ContextInit( OsPcbType *pcb ) {\r
+\r
+ if( pcb->autostart ) {\r
+ Os_TaskMakeReady(pcb);\r
+ } else {\r
+ pcb->state = ST_SUSPENDED;\r
+ }\r
+\r
+ Os_StackSetup(pcb);\r
+ Os_StackFill(pcb);\r
+ Os_ArchSetTaskEntry(pcb);\r
+\r
+ Os_ArchSetupContext(pcb);\r
+}\r
+\r
+/**\r
+ *\r
+ * @param pcb\r
+ */\r
+void Os_ContextReInit( OsPcbType *pcbPtr ) {\r
+ Os_StackSetup(pcbPtr);\r
+}\r
+\r
+/**\r
+ * Search for a specific task in the pcb list.\r
+ *\r
+ * @param tid The task id to search for\r
+ * @return Ptr to the found pcb or NULL\r
+ */\r
+OsPcbType *os_find_task( TaskType tid ) {\r
+ OsPcbType *i_pcb;\r
+\r
+ /* TODO: Implement this as an array */\r
+ TAILQ_FOREACH(i_pcb,& os_sys.pcb_head,pcb_list) {\r
+ if(i_pcb->pid == tid ) {\r
+ return i_pcb;\r
+ }\r
+ }\r
+ assert(0);\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ * Adds a pcb to the list of pcb's\r
+ * @param pcb\r
+ */\r
+TaskType Os_AddTask( OsPcbType *pcb ) {\r
+ long msr;\r
+\r
+ Irq_Save(msr); // Save irq status and disable interrupts\r
+\r
+ pcb->pid = os_sys.task_cnt;\r
+ // Add to list of PCB's\r
+ TAILQ_INSERT_TAIL(& os_sys.pcb_head,pcb,pcb_list);\r
+ os_sys.task_cnt++;\r
+\r
+ Irq_Restore(msr); // Restore interrupts\r
+ return pcb->pid;\r
+}\r
+\r
+\r
+#define PRIO_ILLEGAL -100\r
+\r
+/**\r
+ * Find the top priority task. Even the running task is included.\r
+ * TODO: There should be a priority queue (using a heap?) here instead.\r
+ * giving O(log n) for instertions and (1) for getting the top\r
+ * prio task. The curerent implementation is ehhhh bad.\r
+ * @return\r
+ */\r
+\r
+OsPcbType *Os_TaskGetTop( void ){\r
+ OsPcbType *i_pcb;\r
+ OsPcbType *top_prio_pcb = NULL;\r
+ OsPriorityType top_prio = PRIO_ILLEGAL;\r
+\r
+ OS_DEBUG(D_TASK,"os_find_top_prio_proc\n");\r
+\r
+ TAILQ_FOREACH(i_pcb,& os_sys.ready_head,ready_list) {\r
+ // all ready task are canidates\r
+ if( i_pcb->state & (ST_READY|ST_RUNNING)) {\r
+ if( top_prio != PRIO_ILLEGAL ) {\r
+ if( i_pcb->prio > top_prio ) {\r
+ top_prio = i_pcb->prio;\r
+ top_prio_pcb = i_pcb;\r
+ }\r
+ } else {\r
+ top_prio = i_pcb->prio;\r
+ top_prio_pcb = i_pcb;\r
+ }\r
+ } else {\r
+ assert(0);\r
+ }\r
+ }\r
+\r
+ assert(top_prio_pcb!=NULL);\r
+\r
+ OS_DEBUG(D_TASK,"Found %s\n",top_prio_pcb->name);\r
+\r
+ return top_prio_pcb;\r
+}\r
+\r
+\r
+#define USE_LDEBUG_PRINTF\r
+#include "debug.h"\r
+\r
+// we come here from\r
+// - WaitEvent()\r
+// old_pcb -> WAITING\r
+// new_pcb -> READY(RUNNING)\r
+// - Schedule(),\r
+// old_pcb -> READY\r
+// new_pcb -> READY/RUNNING\r
+\r
+/*\r
+ * two strategies\r
+ * 1. When running ->\r
+ * - remove from ready queue\r
+ * - set state == ST_RUNNING\r
+ *\r
+ * 2. When running ->\r
+ * * leave in ready queue\r
+ * * set state == ST_RUNNING\r
+ * - ready queue and ST_READY not the same\r
+ * + No need to remove the running process from ready queue\r
+ */\r
+\r
+OsPcbType *Os_FindTopPrioTask( void ) {\r
+\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ * Tries to Dispatch.\r
+ *\r
+ * Used by:\r
+ * ActivateTask()\r
+ * WaitEvent()\r
+ * TerminateTask()\r
+ * ChainTask()\r
+ *\r
+ * @param force Force a re-scheduling\r
+ *\r
+ */\r
+void Os_Dispatch( _Bool force ) {\r
+ OsPcbType *pcbPtr;\r
+ OsPcbType *currPcbPtr;\r
+ (void)force;\r
+\r
+ assert(os_sys.int_nest_cnt == 0);\r
+ assert(os_sys.scheduler_lock == 0 );\r
+\r
+ pcbPtr = Os_TaskGetTop();\r
+ currPcbPtr = Os_TaskGetCurrent();\r
+ /* Swap if we found any process or are forced (multiple activations)*/\r
+ if( pcbPtr != currPcbPtr ) {\r
+\r
+ /* Add us to the ready list */\r
+ if( currPcbPtr->state & ST_RUNNING ) {\r
+ /** @req OS052 */\r
+ POSTTASKHOOK();\r
+ Os_TaskRunningToReady(currPcbPtr);\r
+ }\r
+\r
+ /*\r
+ * Swap context\r
+ */\r
+ assert(pcbPtr!=NULL);\r
+\r
+ Os_ResourceReleaseInternal();\r
+\r
+#if (OS_STACK_MONITORING == 1)\r
+ if( !Os_StackIsEndmarkOk(currPcbPtr) ) {\r
+#if ( OS_SC1 == 1) || ( OS_SC2 == 1)\r
+ /** @req OS068 */\r
+ ShutdownOS(E_OS_STACKFAULT);\r
+#else\r
+#error SC3 or SC4 not supported. Protection hook should be called here\r
+#endif\r
+ }\r
+#endif\r
+\r
+ Os_ArchSwapContext(currPcbPtr,pcbPtr);\r
+\r
+ pcbPtr = Os_TaskGetCurrent();\r
+ Os_TaskMakeRunning(pcbPtr);\r
+\r
+ Os_ResourceGetInternal();\r
+\r
+ PRETASKHOOK();\r
+\r
+ } else {\r
+ if( Os_GetOp() != OP_SET_EVENT ) {\r
+\r
+ /* We want to run the same task, again. This only happens\r
+ * when we have multiple activation of a basic task (\r
+ * extended tasks have an activation limit of 1)\r
+ */\r
+\r
+ /* Setup the stack again, and just call the basic task */\r
+ Os_StackSetup(pcbPtr);\r
+ Os_ArchSetSpAndCall(pcbPtr->stack.curr,Os_TaskStartBasic);\r
+ } else {\r
+ /* Two cases:\r
+ * 1. SetEvent() on itself\r
+ * 2. SetEvent()\r
+ *\r
+ *\r
+ * */\r
+\r
+ }\r
+ }\r
+}\r
+\r
+// We come here from\r
+// - os_init\r
+\r
+/**\r
+ * Called when a task is to be run for the first time.\r
+ */\r
+void Os_TaskSwapContextTo(OsPcbType *old_pcb, OsPcbType *new_pcb ) {\r
+\r
+ Os_ArchSwapContextTo(old_pcb,new_pcb);\r
+ /* TODO: When do we return here ?? */\r
+}\r
+\r
+\r
+void Os_Arc_GetStackInfo( TaskType task, StackInfoType *s) {\r
+ OsPcbType *pcb = os_get_pcb(task);\r
+\r
+ s->curr = Os_ArchGetStackPtr();\r
+ s->top = pcb->stack.top;\r
+ s->at_swap = pcb->stack.curr;\r
+ s->size = pcb->stack.size;\r
+ s->usage = (void *)Os_StackGetUsage(pcb);\r
+}\r
+\r
+\r
+/**\r
+ * Returns the state of a task (running, ready, waiting, suspended)\r
+ * at the time of calling GetTaskState.\r
+ *\r
+ * @param TaskId Task reference\r
+ * @param State Reference to the state of the task\r
+ */\r
+\r
StatusType GetTaskState(TaskType TaskId, TaskStateRefType State) {\r
state_t curr_state = os_pcb_get_state(os_get_pcb(TaskId));\r
StatusType rv = E_OK;\r
\r
OS_STD_END_2(OSServiceId_GetTaskState,TaskId, State);\r
}\r
-
-
-/**
- * GetTaskID returns the information about the TaskID of the task
- * which is currently running.
- *
- * @param task_id Reference to the task which is currently running
- * @return
+\r
+\r
+/**\r
+ * GetTaskID returns the information about the TaskID of the task\r
+ * which is currently running.\r
+ *\r
+ * @param task_id Reference to the task which is currently running\r
+ * @return\r
*/\r
StatusType GetTaskID( TaskRefType task_id ) {\r
*task_id = os_sys.curr_pcb->pid;\r
return E_OK;\r
}\r
-
-
-ISRType GetISRID( void ) {
-
- /** @req OS264 */
- if(os_sys.int_nest_cnt == 0 ) {
- return INVALID_ISR;
- }
-
- /** @req OS263 */
- return (ISRType)Os_TaskGetCurrent()->pid;
-}
-
-#define TASK_CHECK_ID(x) \
- if( (x) > Os_CfgGetTaskCnt()) { \
- rv = E_OS_ID; \
- goto err; \
- }
-
+\r
+\r
+ISRType GetISRID( void ) {\r
+\r
+ /** @req OS264 */\r
+ if(os_sys.int_nest_cnt == 0 ) {\r
+ return INVALID_ISR;\r
+ }\r
+\r
+ /** @req OS263 */\r
+ return (ISRType)Os_TaskGetCurrent()->pid;\r
+}\r
+\r
+#define TASK_CHECK_ID(x) \\r
+ if( (x) > Os_CfgGetTaskCnt()) { \\r
+ rv = E_OS_ID; \\r
+ goto err; \\r
+ }\r
+\r
+static inline void Os_Arc_SetCleanContext( OsPcbType *pcb ) {\r
+ if (pcb->proc_type == PROC_EXTENDED) {\r
+ /** @req OSEK ActivateTask Cleanup events\r
+ * OSEK,ActivateTask, When an extended task is transferred from suspended\r
+ * state into ready state all its events are cleared.*/\r
+ pcb->ev_set = 0;\r
+ pcb->ev_wait = 0;\r
+ }\r
+ Os_StackSetup(pcb);\r
+ Os_ArchSetTaskEntry(pcb);\r
+ Os_ArchSetupContext(pcb);\r
+}\r
\r
/**\r
* The task <TaskID> is transferred from the suspended state into\r
* If E_OS_LIMIT is returned the activation is ignored.\r
* When an extended task is transferred from suspended state\r
* into ready state all its events are cleared.\r
- *
- * Note!
- * ActivateTask will not immediately change the state of the task
- * in case of multiple activation requests. If the task is not
- * suspended, the activation will only be recorded and performed later.
- *
- * @param pid
- * @return
+ *\r
+ * Note!\r
+ * ActivateTask will not immediately change the state of the task\r
+ * in case of multiple activation requests. If the task is not\r
+ * suspended, the activation will only be recorded and performed later.\r
+ *\r
+ * @param pid\r
+ * @return\r
*/\r
\r
StatusType ActivateTask( TaskType TaskID ) {\r
StatusType rv = E_OK;\r
\r
OS_DEBUG(D_TASK,"ActivateTask %s\n",pcb->name);\r
-
-#if (OS_STATUS_EXTENDED == STD_ON )
- TASK_CHECK_ID(TaskID);
-
- /* @req OS093 ActivateTask */
- if( Os_IrqAnyDisabled() ) {
- rv = E_OS_DISABLEDINT;
- goto err;
- }
-#endif
-
- Irq_Save(msr);
-
- if( os_pcb_get_state(pcb) == ST_SUSPENDED ) {
- pcb->activations++;
- if (pcb->proc_type == PROC_EXTENDED) {
- /** @req OSEK ActivateTask Cleanup events
- * OSEK,ActivateTask, When an extended task is transferred from suspended
- * state into ready state all its events are cleared.*/
- pcb->ev_set = 0;
- pcb->ev_wait = 0;
- }
- Os_StackSetup(pcb);
- Os_ArchSetTaskEntry(pcb);
- Os_ArchSetupContext(pcb);
- Os_TaskMakeReady(pcb);
- } else {
-
- if( pcb->proc_type == PROC_EXTENDED ) {
- /** @req OSEK Activate task.
- * An extended task be activated once. See Chapter 4.3 in OSEK
- */
- rv = E_OS_LIMIT;
- goto err;
- }
-
- /** @req OSEK_? Too many task activations */
- if( pcb->activations == pcb->activationLimit ) {
- rv=E_OS_LIMIT;
- goto err;
- } else {
- pcb->activations++;
- }
- }
-
-
- /* Preempt only if higher prio than us */\r
- if( (pcb->scheduling == FULL) &&
- (os_sys.int_nest_cnt == 0) && (pcb->prio > Os_TaskGetCurrent()->prio) )
+\r
+#if (OS_STATUS_EXTENDED == STD_ON )\r
+ TASK_CHECK_ID(TaskID);\r
+\r
+ /* @req OS093 ActivateTask */\r
+ if( Os_IrqAnyDisabled() ) {\r
+ rv = E_OS_DISABLEDINT;\r
+ goto err;\r
+ }\r
+#endif\r
+\r
+ Irq_Save(msr);\r
+\r
+ if( os_pcb_get_state(pcb) == ST_SUSPENDED ) {\r
+ pcb->activations++;\r
+ Os_Arc_SetCleanContext(pcb);\r
+ Os_TaskMakeReady(pcb);\r
+ } else {\r
+\r
+ if( pcb->proc_type == PROC_EXTENDED ) {\r
+ /** @req OSEK Activate task.\r
+ * An extended task be activated once. See Chapter 4.3 in OSEK\r
+ */\r
+ rv = E_OS_LIMIT;\r
+ goto err;\r
+ }\r
+\r
+ /** @req OSEK_? Too many task activations */\r
+ if( pcb->activations == pcb->activationLimit ) {\r
+ rv=E_OS_LIMIT;\r
+ goto err;\r
+ } else {\r
+ pcb->activations++;\r
+ }\r
+ }\r
+\r
+\r
+ /* Preempt only if we are preemptable and target has higher prio than us */\r
+ if( (Os_TaskGetCurrent()->scheduling == FULL) &&\r
+ (os_sys.int_nest_cnt == 0) &&\r
+ (pcb->prio > Os_TaskGetCurrent()->prio) &&\r
+ (Os_SchedulerResourceIsFree()))\r
{\r
Os_Dispatch(0);\r
- }
-
+ }\r
+\r
Irq_Restore(msr);\r
\r
OS_STD_END_1(OSServiceId_ActivateTask,TaskID);\r
}\r
-
-/**
- * This service causes the termination of the calling task. The
- * calling task is transferred from the running state into the
- * suspended state.
- *
- * An internal resource assigned to the calling task is automatically
- * released. Other resources occupied by the task shall have been
- * released before the call to TerminateTask. If a resource is still
- * occupied in standard status the behaviour is undefined.
- *
- * If the call was successful, TerminateTask does not return to the
- * call level and the status can not be evaluated.
- *
- * If the version with extended status is used, the service returns
- * in case of error, and provides a status which can be evaluated
- * in the application.
- *
- * If the service TerminateTask is called successfully, it enforces a
- * rescheduling.
- *
- * [ Ending a task function without call to TerminateTask
- * or ChainTask is strictly forbidden and may leave the system in an
- * undefined state. ]
- *
- * [] is an OSEK requirement and is overridden by OS052
- *
- * @return
- */
+\r
+/**\r
+ * This service causes the termination of the calling task. The\r
+ * calling task is transferred from the running state into the\r
+ * suspended state.\r
+ *\r
+ * An internal resource assigned to the calling task is automatically\r
+ * released. Other resources occupied by the task shall have been\r
+ * released before the call to TerminateTask. If a resource is still\r
+ * occupied in standard status the behaviour is undefined.\r
+ *\r
+ * If the call was successful, TerminateTask does not return to the\r
+ * call level and the status can not be evaluated.\r
+ *\r
+ * If the version with extended status is used, the service returns\r
+ * in case of error, and provides a status which can be evaluated\r
+ * in the application.\r
+ *\r
+ * If the service TerminateTask is called successfully, it enforces a\r
+ * rescheduling.\r
+ *\r
+ * [ Ending a task function without call to TerminateTask\r
+ * or ChainTask is strictly forbidden and may leave the system in an\r
+ * undefined state. ]\r
+ *\r
+ * [] is an OSEK requirement and is overridden by OS052\r
+ *\r
+ * @return\r
+ */\r
\r
StatusType TerminateTask( void ) {\r
OsPcbType *curr_pcb = Os_TaskGetCurrent();\r
- StatusType rv = E_OK;
+ StatusType rv = E_OK;\r
uint32_t flags;\r
\r
OS_DEBUG(D_TASK,"TerminateTask %s\n",curr_pcb->name);\r
-
-#if (OS_STATUS_EXTENDED == STD_ON )
-
-
- if( os_sys.int_nest_cnt != 0 ) {
- rv = E_OS_CALLEVEL;
- goto err;
- }
-
- /** @req OS070 */
- if( Os_ResourceCheckAndRelease(curr_pcb) == 1 ) {
- rv = E_OS_RESOURCE;
- goto err;
-
- }
-
-
-#endif
-
-
- Irq_Save(flags);
-
- --curr_pcb->activations;
-
-
-// assert(curr_pcb->activations>=0);
-
- /*@req OSEK TerminateTask
- * In case of tasks with multiple activation requests,
- * terminating the current instance of the task automatically puts the next
- * instance of the same task into the ready state
- */
- if( curr_pcb->activations <= 0 ) {
- curr_pcb->activations = 0;
- Os_TaskMakeSuspended(curr_pcb);
- } else {
- /* We need to add ourselves to the ready list again,
- * with a startup context. */
- }
-
-// Os_ContextReInit(curr_pcb);
-
- /* Force the dispatcher to find something, even if its us */
- Os_Dispatch(1);
+\r
+#if (OS_STATUS_EXTENDED == STD_ON )\r
+\r
+\r
+ if( os_sys.int_nest_cnt != 0 ) {\r
+ rv = E_OS_CALLEVEL;\r
+ goto err;\r
+ }\r
+\r
+ if ( Os_SchedulerResourceIsOccupied() ) {\r
+ rv = E_OS_RESOURCE;\r
+ goto err;\r
+ }\r
+\r
+ /** @req OS070 */\r
+ if( Os_ResourceCheckAndRelease(curr_pcb) == 1 ) {\r
+ rv = E_OS_RESOURCE;\r
+ goto err;\r
+\r
+ }\r
+\r
+\r
+#endif\r
+\r
+\r
+ Irq_Save(flags);\r
+\r
+ --curr_pcb->activations;\r
+\r
+\r
+// assert(curr_pcb->activations>=0);\r
+\r
+ /*@req OSEK TerminateTask\r
+ * In case of tasks with multiple activation requests,\r
+ * terminating the current instance of the task automatically puts the next\r
+ * instance of the same task into the ready state\r
+ */\r
+ if( curr_pcb->activations <= 0 ) {\r
+ curr_pcb->activations = 0;\r
+ POSTTASKHOOK();\r
+ Os_TaskMakeSuspended(curr_pcb);\r
+ } else {\r
+ /* We need to add ourselves to the ready list again,\r
+ * with a startup context. */\r
+\r
+ /* We are already in ready list..\r
+ * This should give us a clean start /tojo */\r
+ Os_Arc_SetCleanContext(curr_pcb);\r
+ }\r
+\r
+// Os_ContextReInit(curr_pcb);\r
+\r
+ /* Force the dispatcher to find something, even if its us */\r
+ Os_Dispatch(1);\r
\r
Irq_Restore(flags);\r
// It must find something here...otherwise something is very wrong..\r
}\r
\r
StatusType ChainTask( TaskType TaskId ) {\r
- StatusType rv;
- uint32_t flags;
-
-#if (OS_STATUS_EXTENDED == STD_ON )
- TASK_CHECK_ID(TaskId);
-
- if( os_sys.int_nest_cnt != 0 ) {
- rv = E_OS_CALLEVEL;
- goto err;
- }
-#endif
+ OsPcbType *curr_pcb = Os_TaskGetCurrent();\r
+ StatusType rv = E_OK;\r
+ uint32_t flags;\r
+\r
+#if (OS_STATUS_EXTENDED == STD_ON )\r
+ TASK_CHECK_ID(TaskId);\r
+\r
+ if( os_sys.int_nest_cnt != 0 ) {\r
+ rv = E_OS_CALLEVEL;\r
+ goto err;\r
+ }\r
+\r
+ if ( Os_SchedulerResourceIsOccupied() ) {\r
+ rv = E_OS_RESOURCE;\r
+ goto err;\r
+ }\r
+\r
+ if( Os_ResourceCheckAndRelease(curr_pcb) == 1 ) {\r
+ rv = E_OS_RESOURCE;\r
+ goto err;\r
+ }\r
+#endif\r
+ OsPcbType *pcb = os_get_pcb(TaskId);\r
\r
Irq_Save(flags);\r
- rv = ActivateTask(TaskId);\r
- /* TODO: more more here..*/\r
- TerminateTask();\r
+\r
+ if (curr_pcb == pcb) {\r
+ /* If we are chaining same task just make a clean start */\r
+ /* TODO: Is it allowed to chain same task if extended? */\r
+ Os_Arc_SetCleanContext(curr_pcb);\r
+\r
+ /* Force the dispatcher to find something, even if its us */\r
+ Os_Dispatch(1);\r
+\r
+ Irq_Restore(flags);\r
+ /* It must find something here...otherwise something is very wrong.. */\r
+ assert(0);\r
+\r
+ } else {\r
+ /* We are chaining another task\r
+ * We need to make sure it is in valid state */\r
+ if( os_pcb_get_state(pcb) != ST_SUSPENDED ) {\r
+ if( pcb->proc_type == PROC_EXTENDED ) {\r
+ /** @req OSEK Activate task.\r
+ * An extended task be activated once. See Chapter 4.3 in OSEK */\r
+ rv = E_OS_LIMIT;\r
+ goto err;\r
+ }\r
+\r
+ /** @req OSEK_? Too many task activations */\r
+ if( pcb->activations == pcb->activationLimit ) {\r
+ rv=E_OS_LIMIT;\r
+ goto err;\r
+ }\r
+ }\r
+\r
+ // Terminate current task\r
+ --curr_pcb->activations;\r
+ if( curr_pcb->activations <= 0 ) {\r
+ curr_pcb->activations = 0;\r
+ POSTTASKHOOK();\r
+ Os_TaskMakeSuspended(curr_pcb);\r
+ }\r
+\r
+ rv = ActivateTask(TaskId);\r
+ // we return here only if something is wrong\r
+ }\r
+\r
Irq_Restore(flags);\r
\r
if (rv != E_OK) goto err;\r
* Otherwise the calling task is continued.\r
*\r
* TODO: The OSEK spec says a lot of strange things under "particulareties"\r
- * that I don't understand
- *
+ * that I don't understand\r
+ *\r
* See OSEK/VDX 13.2.3.4\r
- *
+ *\r
*/\r
StatusType Schedule( void ) {\r
// OsPcbType *pcb;\r
// OsPcbType *curr_pcb = get_curr_pcb();\r
- StatusType rv = E_OK;
+ StatusType rv = E_OK;\r
uint32_t flags;\r
-
- /* We need to figure out if we have an internal resource,
- * otherwise no re-scheduling.
- * NON - Have internal resource prio OS_RES_SCHEDULER_PRIO (32+)
- * FULL - Assigned internal resource OR
- * No assigned internal resource.
- * */
- if( Os_TaskGetCurrent()->scheduling != NON ) {
- return E_OK;
- }
-
-#if 0
- if( os_get_resource_int_p() == NULL ) {
- /* We do nothing */
- return E_OK;
- }
-#endif
-
- /* Check that we are not calling from interrupt context */
- if( os_sys.int_nest_cnt != 0 ) {
- rv = E_OS_CALLEVEL;
- goto err;
- }
-\r
- Irq_Save(flags);
- Os_Dispatch(0);\r
- Irq_Restore(flags);\r
+\r
+ /* Check that we are not calling from interrupt context */\r
+ if( os_sys.int_nest_cnt != 0 ) {\r
+ rv = E_OS_CALLEVEL;\r
+ goto err;\r
+ }\r
+\r
+ /* We need to figure out if we have an internal resource,\r
+ * otherwise no re-scheduling.\r
+ * NON - Have internal resource prio OS_RES_SCHEDULER_PRIO (32+)\r
+ * FULL - Assigned internal resource OR\r
+ * No assigned internal resource.\r
+ * */\r
+ if( Os_TaskGetCurrent()->scheduling != NON ) {\r
+ return E_OK;\r
+ }\r
+\r
+#if 0\r
+ if( os_get_resource_int_p() == NULL ) {\r
+ /* We do nothing */\r
+ return E_OK;\r
+ }\r
+#endif\r
+\r
+ OsPcbType* top_pcb = Os_TaskGetTop();\r
+ /* only dispatch if some other ready task has higher prio */\r
+ if (top_pcb->prio > Os_TaskGetCurrent()->prio) {\r
+ Irq_Save(flags);\r
+ Os_Dispatch(0);\r
+ Irq_Restore(flags);\r
+ }\r
\r
// Prevent label warning. Remove this when proper error handling is implemented.\r
if (0) goto err;\r