6.5.3. Installing the handlers from C

Sometimes during development work it is necessary to install exception handlers into the vectors directly from the main application. As a result, the required instruction encoding must be written to the appropriate vector address. This can be done for both the branch and the load PC method of reaching the handler.

Branch method

The required instruction can be constructed as follows:

  1. Take the address of the exception handler.

  2. Subtract the address of the corresponding vector.

  3. Subtract 0x8 to provide for prefetching.

  4. Shift the result to the right by two to give a word offset, rather than a byte offset.

  5. Test that the top eight bits of this are clear, to ensure that the result is only 24 bits long (because the offset for the branch is limited to this).

  6. Logically OR this with 0xEA000000 (the opcode for the Branch instruction) to produce the value to be placed in the vector.

Example 6.4 shows a C function that implements this algorithm.

It takes the following arguments:

  • the address of the handler

  • the address of the vector in which the handler is to be to installed.

The function can install the handler and return the original contents of the vector. This result can be used to create a chain of handlers for a particular exception. See Chaining exception handlers for more details.

The following code calls this to install an IRQ handler:

unsigned *irqvec = (unsigned *)0x18;
Install_Handler ((unsigned)IRQHandler, irqvec);

In this case, the returned, original contents of the IRQ vector are discarded.

Example 6.4. Implementing the branch method

unsigned Install_Handler (unsigned routine, unsigned *vector)
/* Updates contents of 'vector' to contain branch instruction */
/* to reach ’routine’ from ’vector’. Function return value is */
/* original contents of 'vector'.*/
/* NB: ’Routine’ must be within range of 32MB from ’vector’.*/

{   unsigned vec, oldvec;
    vec = ((routine - (unsigned)vector - 0x8)>>2);
    if ((vec & 0xFF000000))
    {
        /* diagnose the fault */
        printf ("Installation of Handler failed");
        exit (1);
    }
    vec = 0xEA000000 | vec;
    oldvec = *vector;
    *vector = vec;
    return (oldvec);
}

Load PC method

The required instruction can be constructed as follows:

  1. Take the address of the word containing the address of the exception handler.

  2. Subtract the address of the corresponding vector.

  3. Subtract 0x8 to provide for prefetching.

  4. Check that the result can be represented in 12 bits.

  5. Logically OR this with 0xe59FF000 (the opcode for LDR pc, [pc,#offset]) to produce the value to be placed in the vector.

  6. Put the address of the handler into the storage location.

Example 6.5 shows a C routine that implements this method.

Again in this example the returned, original contents of the IRQ vector are discarded, but they could be used to create a chain of handlers. See Chaining exception handlers for more information.

Example 6.5. Implementing the load PC method

unsigned Install_Handler (unsigned location, unsigned *vector)

/* Updates contents of 'vector' to contain LDR pc, [pc, #offset] */
/* instruction to cause long branch to address in 'location'. */
/* Function return value is original contents of 'vector'. */

{   unsigned vec, oldvec;
    vec = ((unsigned)location - (unsigned)vector - 0x8) | 0xe59ff000;
    oldvec = *vector;
    *vector = vec;
    return (oldvec);
}

The following code calls this to install an IRQ handler:

unsigned *irqvec = (unsigned *)0x18;
static unsigned pIRQ_Handler = (unsigned)IRQ_handler
Install_Handler (&pIRQHandler, irqvec);

Note

If you are using a processor with separate instruction and data caches you must ensure that cache coherence problems do not prevent the new contents of the vectors from being used.

The data cache (or at least the entries containing the modified vectors) must be cleaned to ensure the new vector contents are written to main memory. You must then flush the instruction cache to ensure that the new vector contents are read from main memory.

For details of cache clean and flush operations, see the Technical Reference Manual for your target processor.

Copyright © 2002-2006 ARM Limited. All rights reserved.ARM DUI 0203G
Non-Confidential