13.2.4. Developing an application under full Angel

This section gives useful information on how to develop applications under Angel, including:

Planning your development project

Before you begin your development project you must make basic decisions about such things as:

  • the APCS variant to be used for your project

  • whether or not ARM/Thumb interworking is required

  • the endianness of your target system.

Refer to the appropriate chapters of the ARM Software Development Toolkit Reference Guide and this book for more information on interworking ARM and Thumb code, and specifying APCS options.

In addition, you should consider:

  • Whether you are to move to a production system that includes minimal Angel, or a stand-alone system. If you are not using minimal Angel you must write your own initialization and exception handling code.

  • Whether or not you require C library support in your final application. You must decide how you will implement C library support if it is required, because the Angel semihosting SWI mechanism will not be available. Refer to Linking Angel C library functions for more information.

  • Whether or not debug information is included. You should be aware of the size overhead when using debuggable images as production code.

  • Communications requirements. You must write your own device drivers for your production hardware.

  • Memory requirements. You must ensure that your hardware has sufficient memory to hold both Angel and your program images.

Programming restrictions

Angel resource requirements introduce a number of restrictions on application development under Angel:

  • Angel requires control of its own Supervisor stack. If you are using an RTOS you must ensure that it does not change processor state while Angel is running. Refer to Using Angel with an RTOS for more information.

  • You should avoid using SWI 0x123456 or SWI 0xab. These SWIs are used by Angel to support C library semihosting requests. Refer to Configuring SWI numbers for information on changing the default Angel SWI numbers.

  • If you are using SWIs in your application, and using EmbeddedICE or Multi-ICE for debugging, you should usually set a break point on the SWI handler routine, where you know it is an Angel SWI, rather than at the SWI vector itself.

  • If you are using SWIs in your application you must restore registers to the state that they were when you entered the SWI.

  • If you want to use the Undefined instruction exception for any reason you must remember that Angel uses this to set breakpoints.

Using Angel with an RTOS

From the application perspective Angel is single threaded, modified by the ability to use interrupts provided the interrupt is not context switching. External functions must not change processor modes through interrupts. This means that running Angel and an RTOS together is difficult, and is not recommended unless you are prepared for a significant amount of development effort.

If you are using an RTOS you will have difficulties with contention between the RTOS and Angel when handling interrupts. Angel requires control over its own stacks, task scheduling, and the processor mode when processing an IRQ or FIQ.

An RTOS task scheduler must not perform context switches while Angel is running. Context switches should be disabled until Angel has finished processing.

For example, if an RTOS installs an ISR to perform interrupt-driven context switches and:

  • the ISR is enabled when Angel is active (for example, handling a debug request)

  • an interrupt occurs when Angel is running code

then the ISR switches the Angel context, not the RTOS context. That is, the ISR puts values in processor registers that relate to the application, not to Angel, and it is very likely that Angel will crash.

There are two ways to avoid this situation:

  • Detect ISR calls that occur when Angel is active, and do not task switch. The ISR can run, provided the registers for the other mode are not touched. For example, timers can be updated.

  • Disable either IRQ or FIQ interrupts, whichever Angel is not using, while Angel is active. This is not easy to do.

In summary, the normal process for handling an IRQ under an RTOS is:

  1. IRQ exception generated.

  2. Do any urgent processing.

  3. Enter the IRQ handler.

  4. Process the IRQ and issue an event to the RTOS if required.

  5. Exit by way of the RTOS to switch tasks if a higher priority task is ready to run.

Under Angel this procedure must be modified to:

  1. IRQ exception generated.

  2. Do any urgent processing.

  3. Check whether Angel is active:

    1. If Angel is active then the CPU context must be restored on return, so scheduling cannot be performed, although for example a counter could be updated. Exit by restoring the pc to the interrupted address.

    2. If Angel is not active, process as normal, exiting by way of the scheduler if required.

Using Supervisor mode

If you want your application to execute in Supervisor mode at any time, you must set up your own Supervisor stack. If you call an Angel SWI while in Supervisor mode, Angel uses four words of your Supervisor stack when entering the SWI. After entering the SWI Angel uses its own Supervisor stack, not yours.

This means that, if you set up your own Supervisor mode stack and call an Angel SWI, the Supervisor stack pointer register (sp_SVC) must point to four words of a full descending stack in order to provide sufficient stack space for Angel to enter the SWI.

Chaining exception handlers

Angel provides exception handlers for the Undefined, SWI, IRQ/FIQ, Data Abort, and Prefetch Abort exceptions. If you are working with exceptions you must ensure that any exception handler that you add is chained correctly with the Angel exception handlers. Refer to Chapter 9 Handling Processor Exceptions for more information.

If you are chaining an interrupt handler and you know that the next handler in the chain is the Angel interrupt handler, you can use the Angel interrupt table rather than the processor vector table. You do not have to modify the processor vector table. The Angel interrupt table is easier to manipulate because it contains the 32-bit address of the handler. The processor vector table is limited to 24-bit addresses.

Note

If your application chains exception handlers, Angel must be reset with a hardware reset if the application is killed. This ensures that the vectors are set up correctly when the application is restarted.

The consequences of not passing an exception on to Angel from your exception handler depend on the type of exception, as follows:

Undefined

You will not be able to single step or set breakpoints from the debugger.

SWI

If you do not implement the EnterSVC SWI, Angel will not work. If you do not implement any of the other SWIs you will not be able to use semihosting.

Prefetch abort

The exception will not be trapped in the debugger.

Data abort

The exception will not be trapped in the debugger. If a Data abort occurs during a debugger-originated memory read or write, the operation might not proceed correctly, depending on the action of the handler.

IRQ

This depends on how Angel is configured. Angel will not work if it is configured to use IRQ as its interrupt source.

FIQ

This depends on how Angel is configured. Angel will not work if it is configured to use FIQ as its interrupt source.

Linking Angel C library functions

The C libraries provided with the ARM Software Development Toolkit use Angel SWIs to implement semihosting requests. You have a number of options for using ARM C library functionality:

  • Use the ARM C library for early prototyping only and replace it with your own C library targeted at your hardware and operating system environment.

  • Support Angel SWIs in your own application or operating system and use the ARM C libraries as provided.

  • Port the ARM C library to your own environment. The ARM C libraries are supplied as full source code so that you can retarget them to your own system.

    Refer to Retargeting the ANSI C library of the ARM Software Development Toolkit Reference Guide for more information.

  • Use the embedded C library with your own startup code. The embedded C library does not rely on underlying Angel or operating system functionality. Refer to The embedded C library of the ARM Software Development Toolkit Reference Guide for more information.

Using assertions when debugging

To speed up debugging, Angel includes runtime assertion code that checks that the state of Angel is as expected. The Angel code defines the ASSERT_ENABLED option to enable and disable assertions.

If you use assertions in your code you should wrap them in the protection of ASSERT_ENABLED macros so that you can disable them in the final version if required.


#if ASSERT_ENABLED
...
#endif

Angel uses such assertions wherever possible. For example, assertions are made when it is assumed that a stack is empty, or that there are no items in a queue. You should use assertions whenever possible when writing device drivers. The ASSERT macro is available if the code is a simple condition check (variable = value).

Setting breakpoints

Angel can set breakpoints in RAM only. You cannot set breakpoints in ROM or Flash.

In addition, you must be careful when using single step or breakpoints on the UNDEF, IRQ, FIQ, or SWI vectors. Do not single step or set breakpoints on interrupt service routines on the code path used to enter or exit Angel.

Changing from little-endian to big-endian Angel

You can use the Flash download program to change from a little-endian version of Angel on the ARM PID board to a big-endian version. However, because of an incompatibility between the way big-endian and little-endian code is stored in 16-bit wide devices, this works only if the target device is an 8-bit Flash device:

  1. Make sure you are using the 8-bit Flash device (U12).

  2. Start little-endian Angel by switching on the board and connecting to the debugger.

  3. Run the Flash download program and program the Flash with the big-endian Angel image. This works because Angel operates out of SRAM.

  4. Quit the debugger and switch off the board.

  5. Change the EPROM controller (U10) to be the big-endian controller. Refer to your board documentation for details.

  6. Insert the BIGEND link (LK4).

  7. Power up the board and connect the debugger. Make sure that the debugger is configured for big-endian operation.

When you have a big-endian Angel in Flash, you can use a big-endian version of the Flash downloader to program a new copy of Angel into the 16-bit device. To do this:

  1. Switch on the board.

  2. Start the debugger.

  3. Insert the SEL8BIT link (LK6-4) so that the target device is now the 16-bit Flash chip.

You must provide a 16-bit wide Flash device, because one is not supplied with the board.

Refer to The Flash downloader of the ARM Software Development Toolkit Reference Guide for more information on using the Flash download utility.

Note

There is no performance gain from using a 16-bit wide device in this case, because Angel copies itself to SRAM and executes from there.

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