You copied the Doc URL to your clipboard.

SVC handlers in C and assembly language

Although the top-level handler must always be written in ARM assembly language, the routines that handle each SVC can be written in either assembly language or in C.

The top-level handler uses a BL instruction to jump to the appropriate C function. For example:

    BL    C_SVC_Handler     ; Call C routine to handle the SVC

You can add this instruction to the SVC_Handler routine, after the BIC instruction, shown in the following example:

Top-level SVC handler

    AREA TopLevelSVC, CODE, READONLY ; Name this block of code.
    EXPORT     SVC_Handler
    PUSH       {R0-R12,lr}           ; Store registers.
    LDR        R0,[lr,#-4]           ; Calculate address of SVC
                                     ; instruction and load it 
                                     ; into R0.
    BIC        R0,R0,#0xFF000000     ; Mask off top 8 bits of
                                     ; instruction to give SVC number.
    ; Use value in R0 to determine which SVC routine to execute.
    LDM         sp!, {R0-R12,pc}^    ; Restore registers and return.

Because the SVC number is loaded into R0 by the assembly routine, this is passed to the C function as the first parameter. The function can use this value in, for example, a switch() statement, see the following example:

SVC handler in C function

void C_SVC_Handler (unsigned number)
    switch (number)
        case 0 :                 /* SVC number 0 code */
        case 1 :                 /* SVC number 1 code */
        default :                /* Unknown SVC - report error */

The Supervisor mode stack space might be limited, so avoid using functions that require a large amount of stack space.

    MOV     R1, sp        ; Second parameter to C routine...
                          ; pointer to register values.
    BL    C_SVC_Handler   ; Call C routine to handle the SVC.

You can pass values in and out of an SVC handler written in C, provided that the top-level handler passes the stack pointer value into the C function as the second parameter, in R1, and the C function is updated to access it:

void C_SVC_Handler(unsigned number, unsigned *reg)

The C function can now access the values contained in the registers at the time the SVC instruction was encountered in the main application code, see the following example. It can read from them:

    value_in_reg_0 = reg [0];
    value_in_reg_1 = reg [1];
    value_in_reg_2 = reg [2];
    value_in_reg_3 = reg [3];

and also write back to them:

    reg [0] = updated_value_0;
    reg [1] = updated_value_1;
    reg [2] = updated_value_2;
    reg [3] = updated_value_3;

This causes the updated value to be written into the appropriate stack position, and then restored into the register by the top-level handler.

Figure 5-5 Accessing the Supervisor mode stack

To view this graphic, your browser must support the SVG format. Either install a browser with native support, or install an appropriate plugin such as Adobe SVG Viewer.