王超的小站
认证:VIP会员
所在专题目录 查看专题
FreeRTOS移植详解1-专题概览(基于Microchip dsPIC33C系列芯片)
FreeRTOS移植详解2-滴答定时器实现(基于Microchip dsPIC33C系列芯片)
FreeRTOS移植详解3-内核裁剪(基于Microchip dsPIC33C系列芯片)
FreeRTOS移植详解4-中断配置(基于Microchip dsPIC33C系列芯片)
FreeRTOS移植详解5-临界段处理(基于Microchip dsPIC33C系列芯片)
FreeRTOS移植详解6-任务堆栈初始化和启动(基于Microchip dsPIC33C系列芯片)
作者动态 更多
PIC24 & dsPIC33 MCU Bootloader开发
2021-11-08 15:12
PIC16 & PIC18 MCU Bootloader开发
2021-11-08 15:00
Python开发环境搭建(for Bootloader)
2021-11-08 14:58
Python开发环境搭建 (for Control)
2021-01-27 18:43
MCU扩展CAN/CAN FD接口方案-MCU软件动手实验
2020-11-25 14:11

FreeRTOS移植详解5-临界段处理(基于Microchip dsPIC33C系列芯片)

      临界段代码也叫临界区,是指那些必须完整运行、不能被打断的代码段,比如有的外设的初始化需要严格的时序,初始化过程中不能被打断。FreeRTOS在进入临界段代码的时候需要关闭中断,处理完临界段代码以后再打开中断。FreeRTOS系统本身就有很多的临界段,这些代码都加了临界段代码保护,写自己用户程序的时候有些地方也需要添加临界段代码保护。

      FreeRTOS与临界段代码保护有关的函数有4个,在task.h中定义,分别是:taskENTER_CRITICAL()、taskEXIT_CRITICAL() 、taskENTER_CRITICAL_FROM_ISR()和taskEXIT_CRITICAL_FROM_ISR( x )。其中前2个是任务级的临界段代码保护,后2个是中断级的临界段代码保护,无论哪种情况临界段的代码都要尽量短小,下面分别来看。

      1. 任务级临界段代码保护

      taskENTER_CRITICAL()和taskEXIT_CRITICAL()是任务级的临界段代码保护,一个是进入临界段,一个是退出临界段,这2个函数是成对使用的,这函数的定义如下:

      而portENTER_CRITICAL()和portEXIT_CRITICAL()也是宏定义,在portmacro.h中有定义,如下:

      函数vPortEnterCritical()和vPortExitCritical()在文件port.c中,函数如下:

      可以看出,进入函数vPortEnterCritical()以后首先调用函数portDISABLE_INTERRUPTS()来关闭中断,然后给变量uxCriticalNesting加1。uxCriticalNesting是一个全局变量,用来记录临界段嵌套次数。函数vPortExitCritical()是退出临界段调用,函数每次将uxCriticalNesting 减1,只有当uxCriticalNesting 减到0才会调用函数portENABLE_INTERRUPTS()来使能中断。这样保证了在有多个临界段代码的时候不会因为某一个临界段代码的退出而打乱其他临界段的保护,只有所有的临界段代码都退出以后才会使能中断。

      2. 中断级临界段代码保护

      函数taskENTER_CRITICAL_FROM_ISR()和taskEXIT_CRITICAL_FROM_ISR( x )为中断级临界段代码保护函数,用在中断服务程序中,而且这个中断的优先级一定要小于等于configMAX_SYSCALL_INTERRUPT_PRIORITY。这2个函数在task.h中有如下定义:

      接下来看portSET_INTERRUPT_MASK_FROM_ISR()和portCLEAR_INTERRUPT_MASK_FROM_ISR( x ),这2个函数在文件portmacro.h中有如下定义:

      函数usPortRaiseCpuIPL()和vPortSetCpuIPL( x )在文件port.c中,函数如下:

      可以看出,进入函数usPortRaiseCpuIPL()实现的功能为首先保存当前CPU的优先级IPL[2:0] 到变量usOldIPL中,作为函数返回值用于vPortSetCpuIPL( x ) 的形参在退出临界段时恢复IPL[2:0] 。另一个usPortRaiseCpuIPL() 的操作就是将CPU的优先级IPL[2:0]赋值configMAX_SYSCALL_INTERRUPT_PRIORITY,使优先级小于等于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断被屏蔽。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 4
收藏 3
关注 39
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧