ARM SVC mode source code

Publisher:快乐兔子Latest update time:2019-10-15 Source: eefocusKeywords:ARM  bootload Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

The svc mode can separate SDK (API) and Application, and can also omit a lot of repeated code. For example, if USB is used in bootload and you want to reuse it in application, you can use svc

Principle: Similar to software interrupt, a software interrupt source is added to indicate the function interface to be called through the interrupt source


The source program is as follows:

#ifndef NRF_SVC__

#define NRF_SVC__


#ifdef SVCALL_AS_NORMAL_FUNCTION

#define SVCALL(number, return_type, signature) return_type signature

#else


#ifndef SVCALL

#if defined (__CC_ARM)

#define SVCALL(number, return_type, signature) return_type __svc(number) signature

#elif defined (__GNUC__)

#define SVCALL(number, return_type, signature)

  _Pragma("GCC diagnostic ignored "-Wunused-function"")

  _Pragma("GCC diagnostic push")

  _Pragma("GCC diagnostic ignored "-Wreturn-type"")

  __attribute__((naked)) static return_type signature

  {

    __asm(

        "svc %0n"

        "bx r14" : : "I" (number) : "r0"

    );

  }   

  _Pragma("GCC diagnostic pop")

#elif defined (__ICCARM__)

#define PRAGMA(x) _Pragma(#x)

#define SVCALL(number, return_type, signature)

PRAGMA(swi_number = number)

__swi return_type signature;

#else

#define SVCALL(number, return_type, signature) return_type signature  

#endif

#endif  // SVCALL


#endif  // SVCALL_AS_NORMAL_FUNCTION

#endif  // NRF_SVC__


void C_SVC_Handler(uint8_t svc_num, uint32_t * p_svc_args)

{

    switch (svc_num)

    {

        case NRF_SEC_SVC_HASH:

            p_svc_args[0] = nrf_sec_hash((nrf_sec_data_t *)     p_svc_args[0],

                                         (uint8_t *)            p_svc_args[1],

                                         (nrf_sec_hash_func_t)  p_svc_args[2]);

            break;


        case NRF_SEC_SVC_VERIFY:

            p_svc_args[0] = nrf_sec_verify((nrf_sec_data_t *)           p_svc_args[0],

                                           (nrf_sec_ecc_point_t *)      p_svc_args[1],

                                           (nrf_sec_ecc_signature_t *)  p_svc_args[2],

                                           (nrf_sec_algo_t)             p_svc_args[3]);

            break;

        

        default:

            p_svc_args[0] = NRF_ERROR_SVC_HANDLER_MISSING;

            break;

    }

}


#if defined ( __CC_ARM )

__asm void SVC_Handler(void)

{

EXC_RETURN_CMD_PSP  EQU 0xFFFFFFFD  ; EXC_RETURN using PSP for ARM Cortex. If Link register contains this value it indicates the PSP was used before the SVC, otherwise the MSP was used.


    IMPORT C_SVC_Handler

    LDR   R0, =EXC_RETURN_CMD_PSP   ; Load the EXC_RETURN into R0 to be able to compare against LR to determine stack pointer used. 

    CMP   R0, LR                    ; Compare the link register with R0. If equal then PSP was used, otherwise MSP was used before SVC.

    BNE   UseMSP                    ; Branch to code fetching SVC arguments using MSP.

    MRS   R1, PSP                   ; Move PSP into R1.

    B     Call_C_SVC_Handler        ; Branch to Call_C_SVC_Handler below.

UseMSP

    MRS   R1, MSP                   ; MSP was used, therefore Move MSP into R1.

Call_C_SVC_Handler

    LDR   R0, [R1, #24]             ; The arguments for the SVC was stacked. R1 contains Stack Pointer, the values stacked before SVC are R0, R1, R2, R3, R12, LR, PC (Return address), xPSR. 

                                    ; R1 contains current SP so the PC of the stacked frame is at SP + 6 words (24 bytes). We load the PC into R0.

    SUBS  R0, #2                    ; The PC before the SVC is in R0. We subtract 2 to get the address prior to the instruction executed where the SVC number is located.

    LDRB  R0, [R0]                  ; SVC instruction low octet: Load the byte at the address before the PC to fetch the SVC number.

    LDR   R2, =C_SVC_Handler        ; Load address of C implementation of SVC handler.

    BX    R2                        ; Branch to C implementation of SVC handler. R0 is now the SVC number, R1 is the StackPointer where the arguments (R0-R3) of the original SVC are located.

    ALIGN

}

#elif defined ( __GNUC__ )

void __attribute__ (( naked )) SVC_Handler(void)

{

    const uint32_t exc_return = 0xFFFFFFFD;      // EXC_RETURN using PSP for ARM Cortex. If Link register contains this value it indicates the PSP was used before the SVC, otherwise the MSP was used.

    

    __asm volatile(

        "cmp   lr, %0tn"                       // Compare the link register with argument 0 (%0), which is exc_return. If equal then PSP was used, otherwise MSP was used before SVC.

        "bne   UseMSPtn"                       // Branch to code fetching SVC arguments using MSP.

        "mrs   r1, psptn"                      // Move PSP into R1.

        "b     Call_C_SVC_Handlertn"           // Branch to Call_C_SVC_Handler below.

        "UseMSP:  tn"                          //

        "mrs   r1, msptn"                      // MSP was used, therefore Move MSP into R1.

        "Call_C_SVC_Handler:  tn"              //

        "ldr   r0, [r1, #24]tn"                // The arguments for the SVC was stacked. R1 contains Stack Pointer, the values stacked before SVC are R0, R1, R2, R3, R12, LR, PC (Return address), xPSR. 

                                                 // R1 contains current SP so the PC of the stacked frame is at SP + 6 words (24 bytes). We load the PC into R0.

        "sub   r0, r0, #2tn"                   // The PC before the SVC is in R0. We subtract 2 to get the address prior to the instruction executed where the SVC number is located.

        "ldrb  r0, [r0]tn"                     // SVC instruction low octet: Load the byte at the address before the PC to fetch the SVC number.

        "bx    %1tn"                           // Branch to C implementation of SVC handler, argument 1 (%1). R0 is now the SVC number, R1 is the StackPointer where the arguments (R0-R3) of the original SVC are located.

        ".aligntn"

        :: "r" (exc_return), "r" (C_SVC_Handler) // Argument list for the gcc assembly. exc_return is %0, C_SVC_Handler is %1.

        : "r0", "r1"                             // List of register maintained manually.

    );

}

#else

#error Compiler not supported.

#endif



__asm void SVCHandler(void)

{

    IMPORT SVCHandler_main

    TST lr, #4

    ITE EQ

    MRSEQ R0, MSP

    MRSNE R0, PSP

    B SVCHandler_main

}

void SVCHandler_main(unsigned int * svc_args)

{

    unsigned int svc_number;

    /*

    * Stack contains:

    * R0, R1, R2, R3, R12, R14, the return address and xPSR

    * First argument (R0) is svc_args[0]

    */

    svc_number = ((char *)svc_args[6])[-2];

    switch(svc_number)

    {

        case SVC_00:

            /* Handle SVC 00 */

            break;

        case SVC_01:

            /* Handle SVC 01 */

            break;

        default:

            /* Unknown SVC */

            break;

    }

}


#define SVC_00 0x00

#define SVC_01 0x01

void __svc(SVC_00) svc_zero(const char *string);

void __svc(SVC_01) svc_one(const char *string);

int call_system_func(void)

{

    svc_zero("String to pass to SVC handler zero");

    svc_one("String to pass to a different OS function");

}


In ARM state, it is 0.


Both the ARM and Thumb instruction sets have SVC instructions. When calling SVC in Thumb state, the following must be considered:


The address of the instruction is at lr–2, not at lr–4.


The instruction itself is 16-bit and thus requires a half-word load, see Figure 6.3.


In ARM state, the SVC number is stored as 8 bits instead of 24 bits.

Example 6.8. SVC handler

    PRESERVE8

    AREA SVC_Area, CODE, READONLY

    EXPORT SVC_Handler    IMPORT C_SVC_Handler

T_bit   EQU    0x20                    ; Thumb bit (5) of CPSR/SPSR.

SVC_Handler

    STMFD   sp!, {r0-r3, r12, lr}  ; Store registers

    MOV     r1, sp                 ; Set pointer to parameters

    MRS     r0, spsr               ; Get spsr

    STMFD   sp!, {r0, r3}          ; Store spsr onto stack and another

                                   ; register to maintain 8-byte-aligned stack

    TST     r0, #T_bit             ; Occurred in Thumb state?

    LDRNEH  r0, [lr,#-2]           ; Yes: Load halfword and...

    BICNE   r0, r0, #0xFF00        ; ...extract comment field

    LDREQ   r0, [lr,#-4]           ; No: Load word and...

    BICEQ   r0, r0, #0xFF000000    ; ...extract comment field


    ; r0 now contains SVC number

    ; r1 now contains pointer to stacked registers


    BL      C_SVC_Handler          ; Call main part of handler

    LDMFD   sp!, {r0, r3}          ; Get spsr from stack

    MSR     SPSR_cxsf, r0               ; Restore spsr

    LDMFD   sp!, {r0-r3, r12, pc}^ ; Restore registers and return

    END


Keywords:ARM  bootload Reference address:ARM SVC mode source code

Previous article:AD9850 Function Signal Generator Production
Next article:Pedometer algorithm based on ARM7 ADUC7020+MPU6050

Recommended ReadingLatest update time:2024-11-16 13:29

ARM Linux kernel boot2
The previous article is about ARM Linux kernel booting (1). Continuing from the previous article, look at the following source code: /*  * Setup the initial page tables.  We only setup the barest  * amount which are required to get the kernel running, which  * generally means mapping in the kernel code.只创建内核代码的映射
[Microcontroller]
In-depth understanding of ARM architecture (S3C6410) --- PWM example
There are 5 timers in S3C6410X, which generate internal interrupts. Among them, Timer0 and Timer1 have PWM function, while Timer2, 3, 4 do not have this function. The S3C6410X RISC microprocessorcomprises of five 32-bit timers. These timers are used to generate internal interruptsto the ARM subsystem. In addition, T
[Microcontroller]
In-depth understanding of ARM architecture (S3C6410) --- PWM example
Building a cross-development environment based on ARM and Linux
0 Introduction At present, with the increasing maturity and widespread application of ARM technology, microprocessors based on ARM cores have become the mainstream of the embedded market. The establishment of embedded operating systems for ARM architecture has become a hot topic in current research. Among the m
[Microcontroller]
Building a cross-development environment based on ARM and Linux
ARM7 LPC2138 digital frequency meter design source code and report
1.1 Design Principle Frequency is the number of times a periodic signal changes within a unit time (1s). If the number of repeated changes of this periodic signal measured within a certain time interval T is N, then its frequency can be expressed as f=N/T. Among them, f is the frequency of the measured signal, N is t
[Microcontroller]
ARM7 LPC2138 digital frequency meter design source code and report
Connect 16x2 LCD with ARM7-LPC2148 and display text
In this tutorial, we will see how to interface a 16x2 LCD with ARM7-LPC2148 microcontroller and display a simple welcome message. If you are new to ARM7, start with the basics of the ARM7 LPC2148 and learn how to program it using Keil uVision materials needed hardware ARM7-LPC2148 Microcontroller Board LCD screen (1
[Microcontroller]
Connect 16x2 LCD with ARM7-LPC2148 and display text
ARM Cortex-A9 (tiny 4412)
Require Transplant Linux to add system calls and burn them to the development board detailed steps 1. Build Linux compilation environment 1. Installation of GCC compiler: tar xzvf arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz  -C/ arm-linux-gcc -v //View GCC version 2、gedit ~/.bashrc export PATH=$PATH:/opt/FriendlyAR
[Microcontroller]
ARM Cortex-A9 (tiny 4412)
ARM bare metal learning 2: S3C2440 serial port usage
1. Initialization of the serial port (only basic functions are used) 1. First, set the multiplexing pins. Taking serial port 0 as an example, RXD represents the pin for receiving data, and TXD represents the pin for sending data. These two are multiplexing pins. You need to set the pin multiplexing in the GPHCON regis
[Microcontroller]
Hardware Design of Fingerprint Attendance System Based on ARM7
Biometric technology relies on its uniqueness and reliability of identification. After nearly a decade of development, its application has become increasingly widespread and mature. Currently, fingerprint recognition technology has tended to be popularized in the civilian market, and fingerprint attendance machines
[Microcontroller]
Hardware Design of Fingerprint Attendance System Based on ARM7
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号