##SVC应用
最近对照CM3指南看了一下SVC系统调用的使用方法,刚好先前碰到了NORDIC的蓝牙协议栈的接口,所以试着去研究了一下实现方式。以下为实验的代码:
/**
******************************************************************************
* @file svc_port.c
* @brief svc call test file.
* @author Yuzr
* @note
*******************************************************************************
*/
#include "stdint.h"
#include "ARMCM3.h"
//------------------------------------------------------------------------------//
//
// Define unused parameter.
//
#define UNUSED(_param) (void)_param
/**
******************************************************************************
* @brief svc call funtion 1,add.
* @param a,b
* @retval a+b
*******************************************************************************
*/
static unsigned int _svc_call1(unsigned int a, unsigned b)
{
return (unsigned int)(a+b);
}
/**
******************************************************************************
* @brief svc call funtion 2,add.
* @param a,b
* @retval a-b
*******************************************************************************
*/
static unsigned int _svc_call2(unsigned int a, unsigned int b)
{
return (unsigned int)(a-b);
}
/**
******************************************************************************
* @brief svc call funtion 3,unused.
* @param a,b,c,d
* @retval none
*******************************************************************************
*/
static void _svc_call3(unsigned int a, unsigned b, unsigned int c, unsigned int d)
{
UNUSED(a);
UNUSED(b);
UNUSED(c);
UNUSED(d);
}
/**
******************************************************************************
* @brief svc handler test function.
* @param pwdSF,pwdSF will hold the stack.
* pwdSF[0] = R0, pwdSF[1] = R1
* pwdSF[2] = R2, pwdSF[3] = R3
* pwdSF[4] = R12, pwdSF[5] = LR
* pwdSF[6] = The return address,
* pwdSF[7] = xPSR
* @retval
*******************************************************************************
*/
unsigned int svc_function(unsigned int *pwdSF)
{
unsigned int svc_number;
unsigned int param0,param1,param2,param3;
unsigned int retvalue;
//
// Hold the parameter.
//
svc_number = ((char *)pwdSF[6])[-2];
param0 = (unsigned int)pwdSF[0];
param1 = (unsigned int)pwdSF[1];
param2 = (unsigned int)pwdSF[2];
param3 = (unsigned int)pwdSF[3];
UNUSED(param0);UNUSED(param1);
UNUSED(param2);UNUSED(param3);
//
// Choose which call will be used.
//
switch (svc_number)
{
case 1:
{
retvalue = _svc_call1(param0, param1);
break;
}
case 2:
{
retvalue = _svc_call2(param0, param1);
break;
}
case 3:
{
_svc_call3(param0, param1, param2, param3);
break;
}
default : break;
}
//
// Hold and return the return value.
//
pwdSF[0] = retvalue;
//
// The return value will not be 0.
//
return 0;
}
/**
******************************************************************************
* @brief svc handler.
* @param none
* @retval none
*******************************************************************************
*/
__asm void SVC_Handler(void)
{
IMPORT svc_function
//
// Check if the caller is from handler mode or threaded mode,
// then call the svc_function.
//
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B svc_function
}
/**
******************************************************************************
* @brief main function.
* @param none
* @retval none
*******************************************************************************
*/
unsigned int __svc(1) svc_call1(unsigned int a, unsigned b);
unsigned int __svc(2) svc_call2(unsigned int a, unsigned b);
void __svc(3) svc_call3(unsigned int a, unsigned b, unsigned int c, unsigned int d);
int main(void)
{
unsigned int ret=0;
//
// Test the interface.
//
ret = svc_call1(2,3);
ret = svc_call2(6,3);
svc_call3(0,0,0,0);
UNUSED(ret);
while(1);
{
}
}