📄 serlock.c
字号:
}/* * Function: angel_SerialiseTaskCore * * Purpose: To queue a new task for the scheduler. This calls NewTask * to create a new SVC mode task and if possible, executes the * it (it may not be possible due to a current SVC task in * progress. * * Arguments: * interrupted_regblock- a regblock pointer to the context * for the task which was interrupted * * desired_regblock - a regblock pointer containing the * PC and R0 for the new task * * * Pre-conditions: This function must be called from SVC mode with the * SVC stack set up for use. On entry IRQ's and * FIQ's will be disabled. It must only ever be * called from the assembler veneer code in * Angel_SerialiseTask * * Post-conditions: An SVC task will be executing. */void angel_SerialiseTaskCore(int yielded, unsigned pc, void *state, angel_RegBlock *interrupted_regblock){ angel_TaskQueueItem *tqi; IGNORE(yielded); /* LogInfo(LOG_SERLOCK, ("SerialiseTaskCore: drb %x, irb %x, " "old pc %8X, new pc %8X\n", desired_regblock, interrupted_regblock, interrupted_regblock->pc, desired_regblock->pc)); */#ifdef DEBUG_APPLINT if (angel_CurrentTask->type == TP_Application) LogInfo(LOG_SERLOCK, ("Interrupting Application, PC = %08lx, CPSR = %08lx\n", interrupted_regblock->pc, interrupted_regblock->cpsr));#endif ASSERT(((Angel_GetCPSR() & 0xf) != 0), ("SerialiseTaskCore: in USR mode\n")); /* * first off, we need a tqi for this new task. Create one from * the info in desired_regblock */ tqi = Angel_NewTask(TS_Runnable, TP_AngelWantLock, pc, (void*)state);#if DEBUG tqi->name = "Handler";#endif /* * interrupted_regblock represents the state of the current task, * which might be the one we continue with. If we are already running * a task with WantLock priority, then we just continue with it. * If not, then use interrupted_regblock to update the memory context * for the interrupted task and enter the scheduler, which will pick * the current highest-priority task and run it. */ ASSERT((angel_CurrentTask != NULL), ("SerialiseTaskCore: current task is NULL\n")); if (angel_CurrentTask->type == TP_AngelWantLock) angel_StartTask(interrupted_regblock); else { angel_QueueTask(interrupted_regblock, angel_CurrentTask); angel_SelectNextTask(); }}/* * Function: angel_IdleLoop * * Purpose: The idle loop just marks time. It runs (in user mode) * when the serialiser finds no other task can run. * * The task starts out with the Angel interrupt(s) enabled, * and the non-Angel interrupt (if any) disabled. The * state of the non-Angel interrupt can change if the * serialiser "pokes" the CPSR when a interrupts happen, * which it would do if it was "following" the application * interrupt state. * * The ifdef's surround a code chunk which will flash the * LED managed by the LED_DEVICE at approximately 1s * intervals (on a PIE) when Angel is idling, and slower * when it is performing "real" work. If heartbeats are * disabled and an application which doesn't use * semihosting is running, the led will stop flashing. * * THIS ROUTINE NEVER RETURNS. * * Arguments: none. * * Return: none. * * Pre-conditions: Devices initialised. * * Post-conditions: Device poll carried out; interrupts serviced. * */static void angel_IdleLoop(void){ #ifdef IDLE_FLASH_LEDS#ifndef FLASH_LED_LOOP_COUNT /* this is a magic number which works ok on PIE */#define FLASH_LED_LOOP_COUNT 0x00040000#endif static int c = 0, s = 1;#endif while(TRUE) {#ifdef IDLE_FLASH_LEDS if (++c > FLASH_LED_LOOP_COUNT ) { s = ! s; c = 0; angel_DeviceControl((DeviceID)DI_LED_DEVICE, (DeviceControl)DC_SET_LED, (void*)s); }#endif }}/* * Function: angel_PollLoop * * Purpose: This routine calls the device poll code for each configured * polling device, enabling devices which can't themselves generate * an interrupt to gain control of the processor from an application. * * The code claims a timer`, requesting the timer code to send a given * signal every 100ms; on receipt of such a signal, the poll is * performed and the task goes back to sleep * * Arguments: none. * * Return: none. * * Pre-conditions: Devices initialised. * * Post-conditions: Device poll carried out; interrupts serviced. * */#if TIMER_SUPPORTED && POLLING_SUPPORTEDstatic void angel_PollLoop(void){ /* set up a signal to happen every 10 ms */ int t = Timer_NewTimer(20, TF_SIGNALME | TF_RELOAD, (TimerCallback)Angel_TaskID(), SIGBIT_POLL); LogInfo(LOG_SERLOCK, ("PollLoop: Using timer %d\n", t)); while(TRUE) { Angel_Wait(SIGBIT_POLL); /* LogInfo(LOG_SERLOCK, ("PollLoop: poll devices\n")); */ angel_DeviceYield(); }}#endif/* * Function: Angel_YieldCore * * Purpose: The core of Angel_Yield. This just calls the device Yield * routine which should poll any defined devices and return. * The main point of this routine outside of a poll is that * it is called with interrupts enabled, and thus any devices * with interrupts pending will be serviced as well. * * Arguments: none. * * Return: none. * * Pre-conditions: Devices initialised. * * Post-conditions: Device poll carried out; interrupts serviced. * */void Angel_YieldCore(void){ angel_DeviceYield();}/* * Function: angel_SelectNextask * * Purpose: To select the first available task in the highest * priority queue which is not empty, and to effect it * by calling angel_StartTask. * * Arguments: None. * * Pre-conditions: This routine must be called in SVC, with Angel interrupts * disabled. * * Effect: The queue is scanned in descending order * of priority. The first non blocked item in the * queue is removed, and then effected. * If there is no task then go into an idle loop. */void angel_SelectNextTask(void){ register angel_TaskQueueItem *tqi; ASSERT(((Angel_GetCPSR() & 0xf) != 0), ("SelectNextTask: in USR mode\n")); /* * This flag is used to say we need to get to the scheduler... now we're * here, reset it. */ Angel_Needschedule = 0; /* * push the current task back onto the task list, in priority order */ if (angel_CurrentTask) { Task_Enqueue(&angel_TQI_Run, angel_CurrentTask); } angel_PrintTaskQueueShort("SNT", &angel_TQI_Run); /* * Get the current highest priority task. */ tqi = Task_RemHead(&angel_TQI_Run); /* * if task in stupid state, complain */ ASSERT((tqi->state == TS_Runnable ), ("Task in invalid state\n")); /* Otherwise this is the highest priority task so execute it ! */#ifdef DEBUG_TASKS/* LogInfo(LOG_SERLOCK, ("SelectNextTask: Select %d, pc 0x%lx, " *//* "usr (lr 0x%lx, sp 0x%lx) " *//* "svc (lr 0x%lx, sp 0x%lx) " *//* "type %d, pri %d\n", *//* tqi->index, tqi->rb.pc, *//* tqi->rb.r14usr, tqi->rb.r13usr, *//* tqi->rb.r14svc, tqi->rb.r13svc, *//* tqi->type, tqi->priority)); */ LogInfo(LOG_SERLOCK, ("SelectNextTask: Select %d, pc 0x%lx\n", tqi->index, tqi->rb.pc));#endif angel_CurrentTask = tqi; tqi->state = TS_Running; #ifdef DEBUG_APPLINT if (angel_CurrentTask->type == TP_Application) LogInfo(LOG_SERLOCK, ("Resuming Application, PC = %08lx, CPSR = %08lx\n", tqi->rb.pc, tqi->rb.cpsr));#endif angel_StartTask(&(tqi->rb)); /*NOTREACHED*/ /* * Should never get here... (the idle task should always be runnable) */ LogFatalError(LOG_SERLOCK, ("SelectNextTask: No task to run!"));}/* * Function: angel_InitialiseOneOff * * Purpose: To initialise the scheduler and create an application * context which is linked onto the task queue, although * it is blocked from actually starting. It also sets the * scheduler in 'initialisaion' mode. This is one way of * setting a task running in Angel... * * Arguments: None. * * Pre-conditions: This routine must be called in SVC, with the I-bit * and F-bit set. * */void angel_InitialiseOneOff(void){ int i; unsigned base, stackBase; unsigned stackLimit; angel_TaskQueueItem *tqi; LogInfo(LOG_SERLOCK, ( "angel_InitialiseOneOff entered\n")); NewList(&angel_TQI_Free); NewList(&angel_TQI_Wait); NewList(&angel_TQI_Run); NewList(&angel_Stack_Free); Angel_Needschedule = 0; /* stackBase is the highest address used by the descending stack */ base = Angel_StackBase; stackBase = base + Angel_AngelStackOffset; stackLimit = base + Angel_AngelStackLimitOffset; angel_SVCStack.stackBase = base + Angel_SVCStackOffset; angel_SVCStack.stackLimit = base + Angel_SVCStackLimitOffset; angel_CurrentTask = NULL; for (i = 0; i < POOLSIZE; i++) { /* set up TQI's; n_type is the task ID... */ angel_TQ_Pool[i].index = i; angel_TQ_Pool[i].priority = 0; angel_TQ_Pool[i].name = 0; angel_TQ_Pool[i].type = TP_IdleLoop; angel_TQ_Pool[i].state = TS_Undefined; AddTail(&angel_TQI_Free, (MinNode*)&angel_TQ_Pool[i]); /* ... and stacks */ angel_Stack_Pool[i].stackBase = stackBase;#if DEBUG angel_Stack_Pool[i].HWM = stackBase;#endif angel_Stack_Pool[i].stackLimit = stackBase - Angel_AngelStackFreeSpace; AddTail(&angel_Stack_Free, (MinNode*)&angel_Stack_Pool[i]); stackBase -= Angel_AngelStackFreeSpace; if (stackBase < stackLimit) { LogError(LOG_SERLOCK, ("Not enough stack: %d: stackBase = %p, stackLimit = %p\n", i, stackBase, stackLimit)); break; } } LogInfo(LOG_SERLOCK, ("Set up tasks and stacks:\n %d Tasks\n Total %6d (%dKb)\n Wasted %d\n", i, Angel_CombinedAngelStackSize, Angel_CombinedAngelStackSize / 1024, stackBase - stackLimit)); /* The idle loop: this is needed! */ tqi = Angel_NewTask(TS_Runnable, TP_IdleLoop, (unsigned)angel_IdleLoop, 0); if (tqi == NULL) /* sorry, can't do it! */ { LogFatalError(LOG_SERLOCK, ("angel_InitialiseOneOff: CANNOT ALLOCATE IDLE TASK!\n")); } tqi->name = "Idle"; angel_IdleTask = tqi;#if POLLING_SUPPORTED /* The poll loop */ tqi = Angel_NewTask(TS_Runnable, TP_PollLoop, (unsigned)angel_PollLoop, 0); if (tqi == NULL) /* sorry, can't do it! */ { LogFatalError(LOG_SERLOCK, ("angel_InitialiseOneOff: CANNOT ALLOCATE POLL TASK!\n")); } tqi->name = "Poll"; angel_PollTask = tqi;#endif /* The application: always allocate one. */ tqi = Angel_NewTask(TS_Blocked, TP_Application, 0x8000, 0); if (tqi == NULL) /* sorry, can't do it! */ { LogFatalError(LOG_SERLOCK, ("angel_InitialiseOneOff: CANNOT ALLOCATE APPL TASK!\n")); } tqi->signalWaiting = 1; tqi->state = TS_Blocked; tqi->name = "Application"; angel_ApplTask = tqi;}/* * Function: angel_InitialiseTaskFinished * * Purpose: To signal that Angel initialisation has completed, * and the application task can be run. This is only * used in minimal angel systems, where no debugger * will step in and Execute the application. * * Arguments: None. * * Pre-conditions: angel_InitialiseOneOff must have been called, and * no other task run since. * */void Angel_InitialiseTaskFinished(void){ LogInfo(LOG_SERLOCK, ( "Angel_InitialiseTaskFinished\n"));}#endif /* NOT MINIMAL_ANGEL *//* EOF serlock.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -