13.3.4. Angel task management

All Angel operations are controlled by Angel task management. Angel task management:

Angel task management requires control of the processor mode. This can impose restrictions on using Angel with an RTOS. Refer to Using Angel with an RTOS for more information.

Task priorities

Angel assigns task priorities to tasks under its control. Angel ensures that its tasks have priority over any application task. Angel takes control of the execution environment by installing exception handlers at system initialization. The exception handlers enable Angel to check for commands from the debugger and process application semihosting requests.

Angel will not function correctly if your application or RTOS interferes with the execution of the interrupt, SWI or Data Abort exception handlers. Refer to Chaining exception handlers for more information.

When an exception occurs, Angel either processes it completely as part of the exception handler processing, or calls Angel_SerialiseTask() to schedule a task. For example:

  • When an Angel SWI occurs, Angel determines whether the SWI is a simple SWI that can be processed immediately, such as the EnterSVC SWI, or a complex SWI that requires access to the host communication system, and therefore to the serializer. Refer to Angel C library support SWIs for more information.

  • When an IRQ occurs, the Angel PID port determines whether or not the IRQ signals the receipt of a complete ADP packet. If it does, Angel task management is called to control the packet decode operation. Refer to Example of Angel processing: a simple IRQ for more information. Other Angel ports can make other choices for IRQ processing, provided the relevant task is eventually run.

The task management code maintains two values that relate to priority:

Task type

The task type indicates type of task being performed. For example, the application task is of type TP_Application, and Angel tasks are usually TP_AngelCallback. The task type labels a task for the lifetime of the task.

Task priority

The task priority is initially derived from the task type, but thereafter it is independent. Actual priority is indicated in two ways:

  • in the value of a variable in the task structure

  • in the relative position of the task structure in the task queue.

The task priority of the application task changes when an application SWI is processed, to ensure correct interleaving of processing.

Table 13.1 shows the relative task priorities used by Angel.

Table 13.1. Task priorities

HighestAngelWantLockHigh priority callback.
 AngelCallBackCallbacks for Angel.
 ApplCallBackCallbacks for the user application.
 ApplicationThe user application.
 AngelInitBoot task. Emits boot message on reset and then exits.

Angel task management is implemented through the following top-level functions:

  • Angel_SerialiseTask()

  • Angel_NewTask()

  • Angel_QueueCallback()

  • Angel_BlockApplication()

  • Angel_NextTask()

  • Angel_Yield()

  • Angel_Wait()

  • Angel_Signal()

  • Angel_TaskID().

Some of these functions call other Angel functions not documented here. The functions are described in brief below. For full implementation details, refer to the source code in serlock.h, serlock.c, and serlasm.s.


In most cases this function is the entrance function to Angel task management. The only tasks that are not a result of a call to Angel_SerialiseTask() are the boot task, the idle task, and the application. These are all created at startup. When an exception occurs, Angel_SerialiseTask() cleans up the exception handler context and calls Angel_NewTask() to create a new high priority task. It must be entered in a privileged mode.


Angel_NewTask() is the core task creation function. It is called by Angel_SerialiseTask() to create task contexts.


This function:

  • queues a callback

  • specifies the priority of the callback

  • specifies up to four arguments to the callback.

The callback executes when all tasks of a higher priority have completed. Table 13.1 shows relative task priorities.


This function is called to allow or disallow execution of the application task. The application task remains queued, but is not executed. If Angel is processing an application SWI when Angel_BlockApplication() is called, the block might be delayed until just before the SWI returns.


This is not a function, in that it is not called directly. Angel_NextTask() is executed when a task returns from its main function. This is done by setting the link register to point to Angel_NextTask() on function entry.

The Angel_NextTask() routine:

  • enters Supervisor mode

  • disables interrupts

  • calls Angel_SelectNextTask() to select the first task in the task queue that has not been blocked and run it.


This is a yield function for polled devices. It can be called either:

  • by the application

  • by Angel while waiting for communications on a polled device

  • within processor-bound loops such as the idle loop.

Angel_Yield() uses the same serialization mechanism as IRQ interrupts. Like an IRQ, it can be called from either User or Supervisor mode and returns cleanly to either mode. If it is called from User mode it calls the Angel_EnterSVC SWI to enter Supervisor mode, and then disables interrupts.


Angel_Wait() works in conjunction with Angel_Signal() to enable a task to wait for a predetermined event or events to occur before continuing execution. When AngelWait() is called, the task is blocked unless the predetermined event has already been signalled with AngelSignal().

AngelWait() is called with an event mask. The event mask denotes events that will result in the task continuing execution. If more than one bit is set, any one of the events corresponding to those bits will unblock the task. The task remains blocked until some other task calls Angel_Signal() with one or more of the event mask bits set. The meaning of the event mask must be agreed beforehand by the routines.

If AngelWait() is called with a zero event mask, execution continues normally.


Angel_Signal() works in conjunction with Angel_Wait(). This function sends an event to a task that is now waiting for it, or will in the future wait for it:

  • If the task is blocked, Angel_Signal() assumes that the task is waiting and subtracts the new signals from the signals the task was waiting for. The task is unblocked if the event corresponds to any of the event bits defined when the task called Angel_Wait().

  • If the task is running, Angel_Signal() assumes that the task will call Angel_Wait() at some time in the future. The signals are marked in the task signalWaiting member.

Angel_Signal() takes a task ID that identifies a current task, and signals the task that the event has occurred. See the description of Angel_Wait() for more information on event bits. The task ID for the calling task is returned by the Angel_TaskID() macro. The task must write its task ID to a shared memory location if an external task is to signal it.


This macro returns the task ID (a small integer) of the task that calls it. There is no way to obtain the ID of another task unless the other task writes its task ID to a shared memory location.

Copyright © 1997, 1998 ARM Limited. All rights reserved.ARM DUI 0040D