9.3.2. 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 allow 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 9.3 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. Refer to Chaining exception handlers for further details.

Example 9.3. 

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) 
	{
		printf ("Installation of Handler failed");
		exit (1);
	}
	vec = 0xea000000 | vec;
	oldvec = *vector;
	*vector = vec;
	return (oldvec);
}

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.

Load pc 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 allow for the pipeline.

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

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

Example 9.4 shows a C routine that implements this method.

Example 9.4. 

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;
unsigned *irqaddr = (unsigned *)0x38;									 /* For example */
*irqaddr = (unsigned)IRQHandler;
Install_Handler (irqaddr,irqvec);

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. Refer to Chaining exception handlers for more information.

Note

If you are operating on a processor with separate instruction and data caches, such as StrongARM, or ARM940T, 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 is written to main memory. You must then flush the instruction cache to ensure that the new vector contents is read from main memory.

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

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