FreeRTOS---SVC介绍

1. SVC介绍

#define vPortSVCHandler SVC_Handler

SVC(Supervisor Call) ,也称为SVC模式或SVC异常。在ARM架构中,SVC是一种处理器异常,它允许应用程序代码请求操作系统(OS)内核服务。当SVC异常被触发时,处理器会切换到SVC模式,并执行一个特定的异常处理函数(通常是SVC异常处理程序),该函数会处理来自用户模式的请求。
SVC通常用于执行系统调用、上下文切换、线程调度等任务。它是同步的,意味着在SVC异常处理期间,处理器不会响应其他中断或异常。

操作系统不让用户程序直接访问硬件,而是通过提供一些系统服务函数,用户程序使用SVC发出对系统服务函数的呼叫请求,以这种方式调用他们来间接访问硬件(提出要求—得到满足)。因此,当用户程序想要控制特定的硬件时,他就会产生一个SVC异常,然后操作系统提供的SVC异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务
用户程序—OS—硬件),通过SVC程序,让用户程序变得与硬件无关,因此在开发应用程序时无需了解硬件的操作细节,方便应用程序跨平台移植,
在这里插入图片描述
在这里插入图片描述

2. SVC使用

该例子介绍了 在函数prvStartFirstTask中调用svc 0,通过vPortSVCHandler处理,然后运行系统的第一个任务-IdleTask

2.1 SVC

在RTOS中,通常会定义一系列的服务号(SVC number),用于区分不同的SVC调用。例如,服务号0可能用于启动第一个任务,服务号1可能用于其他系统调用等。

/* Call SVC to start the first task. */
    svc 0

具体调用如下:

vTaskStartScheduler();
---xPortStartScheduler();
------prvStartFirstTask();//开始第一个任务
__asm void prvStartFirstTask( void )
{
/* *INDENT-OFF* */
    PRESERVE8

    /* Use the NVIC offset register to locate the stack. */
    ldr r0, =0xE000ED08   //0xE000ED08 ; 向量表偏移量寄存器的地址
    ldr r0, [ r0 ]
    ldr r0, [ r0 ]

    /* Set the msp back to the start of the stack. */
    msr msp, r0
    /* Globally enable interrupts. */
    cpsie i
    cpsie f
    dsb
    isb
    /* Call SVC to start the first task. */
    svc 0
    nop
    nop
/* *INDENT-ON* */
}

0xE000ED08 ; 向量表偏移量寄存器的地址,VTOR寄存器存放的是中断向量表的起始地址
在这里插入图片描述

svc 0之后的动作将会交给vPortSVCHandler函数处理

2.2 vPortSVCHandler 函数

vPortSVCHandler 函数是SVC异常的处理函数

__asm void vPortSVCHandler( void )
{
/* *INDENT-OFF* */
    PRESERVE8

    ldr r3, = pxCurrentTCB   /* Restore the context. */
    ldr r1, [ r3 ] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
    ldr r0, [ r1 ]           /* The first item in pxCurrentTCB is the task top of stack. */
    ldmia r0 !, { r4 - r11 } /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
    msr psp, r0 /* Restore the task stack pointer. */
    isb
    mov r0, # 0
    msr basepri, r0
    orr r14, # 0xd
    bx r14
/* *INDENT-ON* */
}

pxCurrentTCB指向当前执行的任务,函数prvAddNewTaskToReadyList将任务加到任务队列中去,
prvAddNewTaskToReadyList函数被xTaskCreate调用,而函数vTaskStartScheduler执行时便会创建系统的第一个任务—idle task,

typedef tskTCB TCB_t;

portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;


static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
{
    taskENTER_CRITICAL();
    {
        uxCurrentNumberOfTasks++;
        if( pxCurrentTCB == NULL )
        {
            pxCurrentTCB = pxNewTCB;
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值