• PendSV


    先了解下如何使用PendSV异常。(为何要使用PendSV而不是其他的异常,请参考《cortex-M3权威指南》)

    PendSV异常

    ​ PendSV,即可悬起的系统调用,OS可以利用它缓期执行一个异常,直到其它重要的任务完成后才执行操作。触发PendSV只需往NVIC的PendSV悬起寄存器的第28为置1即可;其典型用于上下文切换。

    1,如何设定PendSV优先级?

    NVIC_SYSPRI14 EQU 0xE000ED22

    NVIC_PENDSV_PRI EQU 0xFF

        LDR R0, =NVIC_SYSPRI14 LDR R1, =NVIC_PENDSV_PRI

        STRB R1, [R0]

    2,如何触发PendSV异常?

    往ICSR第28位写1,即可将PendSV异常挂起。若是当前没有高优先级中断产生,那么程序将会进入PendSV handler

    NVIC_INT_CTRL EQU 0xE000ED04

    NVIC_PENDSVSET EQU 0x10000000

    LDR R0, =NVIC_INT_CTRL

    LDR R1, =NVIC_PENDSVSET

    STR R1, [R0]




    触发PendSV中断异常。

    #defineNVIC_INT_CTRL 0xE000Ed04 //PendSV中断控制器地址 #defineNVIC_PENDSV_SET 0x10000000 //PendSV触发的值 #defineNVIC_SYSPRI2 0xE000Ed22 //PendSV优先级控制地址 #defineNVIC_PENDSV_PRI 0x000000ff //PendSV设置为最低优先值 #defineMEM32(addr) *(volatile unsigned long *)(addr) #defineMEM8(addr) *(volatile unsigned char *)(addr) // 触发PendSV中断异常 void trigger_PendSV(void) { MEM32(NVIC_INT_CTRL) = NVIC_PENDSV_SET;//触发PendSV MEM8(NVIC_SYSPRI2) =NVIC_PENDSV_PRI; //设置PendSV优先级 }

    CPU何时响应PendSV异常

    我们都知道,「高优先级的中断会打断低优先级的中断」,这也是系统实时性的一个重要保障,所以就引入了一个问题:

    相比起GPIO中断、定时器中断、串口中断这些外部中断,PendSV异常的优先级更高呢?还是更低呢?

    想象这样一种情况:

    ① CPU正在开心的运行着任务1……

    ② 此时你按下了按键,产生了一个GPIO中断,CPU收到后马上跑去执行中断处理函数……

    ③ 处理过程中,此时系统产生了一个PendSV异常,CPU收到后,嘲讽了一句:“我就是从普通任务跑来处理中断的,还没处理完,现在又让我执行下一个普通任务,脑子抽风了?”,说完继续处理中断……

    所以说,无论任务的优先级有多高,它都没有中断高,「系统的PendSV异常优先级必须设为最低的」,以避免在外部中断服务函数中产生任务切换。

    设置PendSV异常优先级的寄存器如下,值可以为0-255:

    tos中在启动调度时设定pendsv异常的优先级,源码如下:

    NVIC_SYSPRI14   EQU     0xE000ED22
    NVIC_PENDSV_PRI EQU     0xFF
    

    同样,设置pendSV异常优先级为最低的汇编代码如下:

    ; set pendsv priority lowest
    ; otherwise trigger pendsv in port_irq_context_switch will cause a context switch in irq
    ; that would be a disaster
    MOV32   R0, NVIC_SYSPRI14
    MOV32   R1, NVIC_PENDSV_PRI
    STRB    R1, [R0]







    进入PendSV ISR时,cortex-M3做了什么?

    1,入栈。会有8个寄存器自动入栈。入栈内容及顺序如下:

    在步骤一中,我们已经设置了PSP,那这8个寄存器就会自动入栈到PSP所指地址处。

    2,取向量。找到PendSV ISR的入口地址,这样就能跳到ISR了。,

    3,更新寄存器内容

    做完这三步后,程序就进入ISR了。

    进入ISR前,我们已经完成了步骤一,cortex-M3已经帮我们完成了步骤二的一部分,剩下的需要我们手动完成。

     

    进入OS前的两步之PendSV(任务切换)

    RTOS内功修炼记(二)—— 优先级抢占式调度到底是怎么回事?

     
  • 相关阅读:
    redis的rpm包下载安装
    linux下创建普通用户并赋予某个目录的读写权限
    nginx软件优化
    GIT分支简单操作
    mysqldump导入导出数据
    rsync守护进程方式同步实例-004
    rsync多模块配置&排除功能-003
    rsync数据同步方式-002
    rsync简单介绍-001
    Redis cluster 日常操作命令
  • 原文地址:https://www.cnblogs.com/dream397/p/15898026.html
Copyright © 2020-2023  润新知