硬汉嵌入式论坛

 找回密码
 立即注册
查看: 5988|回复: 3
收起左侧

[FreeRTOS] FreeRTOS的临界区开关函数:taskENTER_CRITICAL和taskEXIT_CRITICAL

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
发表于 2015-8-18 17:58:38 | 显示全部楼层 |阅读模式
/**
* task. h
*
* Macro to mark the start of a critical code region.  Preemptive context
* switches cannot occur when in a critical region.
*
* NOTE: This may alter the stack (depending on the portable implementation)
* so must be used with care!
*
* \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
* \ingroup SchedulerControl
*/
#define taskENTER_CRITICAL()                       portENTER_CRITICAL()
#define taskENTER_CRITICAL_FROM_ISR()    portSET_INTERRUPT_MASK_FROM_ISR()

/**
* task. h
*
* Macro to mark the end of a critical code region.  Preemptive context
* switches cannot occur when in a critical region.
*
* NOTE: This may alter the stack (depending on the portable implementation)
* so must be used with care!
*
* \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL
* \ingroup SchedulerControl
*/
#define taskEXIT_CRITICAL()                   portEXIT_CRITICAL()
#define taskEXIT_CRITICAL_FROM_ISR( x )     portCLEAR_INTERRUPT_MASK_FROM_ISR( x )
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
 楼主| 发表于 2015-8-18 18:03:30 | 显示全部楼层
#define portENTER_CRITICAL()                                            vPortEnterCritical()
#define portEXIT_CRITICAL()                                                vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR()                ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)          vPortClearInterruptMask(x)
================================================================

void vPortEnterCritical( void )
{
    portDISABLE_INTERRUPTS();
    uxCriticalNesting++;
    __dsb( portSY_FULL_READ_WRITE );
    __isb( portSY_FULL_READ_WRITE );

    /* This is not the interrupt safe version of the enter critical function so
    assert() if it is being called from an interrupt context.  Only API
    functions that end in "FromISR" can be used in an interrupt.  Only assert if
    the critical nesting count is 1 to protect against recursive calls if the
    assert function also uses a critical section. */
    if( uxCriticalNesting == 1 )
    {
        configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
    }
}
/*--------------------------------------------------------------------------------------------------------*/
void vPortExitCritical( void )
{
    configASSERT( uxCriticalNesting );
    uxCriticalNesting--;
    if( uxCriticalNesting == 0 )
    {
        portENABLE_INTERRUPTS();
    }
}
回复

使用道具 举报

1

主题

109

回帖

112

积分

初级会员

固件開發工程師

积分
112
QQ
发表于 2016-1-19 09:47:33 | 显示全部楼层
请教一下,如果有一个函数既需要在Task中调用,又需要在ISR中调用,这种情况该如何处理?
虽然可以通过IPSR或者NVIC的Register判断当前的状态,但不知道用混了会有什么后果。
比如在ISR中调用taskENTER_CRITICAL(),并且断言关掉。又或者在Task中调用taskENTER_CRITICAL_FROM_ISR()。

FreeRTOS其它API也有类似问题,很多API提供了普通版本以及FromISR版本,不晓得为什么在中断中必须调用FromISR版本。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
 楼主| 发表于 2016-1-21 09:33:00 | 显示全部楼层

回 ----- 的帖子

-----:请教一下,如果有一个函数既需要在Task中调用,又需要在ISR中调用,这种情况该如何处理?
虽然可以通过IPSR或者NVIC的Register判断当前的状态,但不知道用混了会有什么后果。
比如在ISR中调用taskENTER_CRITICAL(),并且断言关掉。又或者在Task中调用taskENTER_CRITICAL_FROM_ISR( .. (2016-01-19 09:47) 
不好意思,现在才回复你。
1. 自己写的函数多线程调用,或者中断函数也调用,一定要保证你的函数是可重入的。
    保证重入性,基本就可以保证线程安全。
2. FreeRTOS提供两种不同的函数,原因有二
   (1)中断函数里面是不能设置等待,要跟任务里面执行的函数区分开,中断函数执行时间要
        越短越好,FreeRTOS也是按照这个原则来的。
    (2) 中断级任务切换和任务级任务切换是有区别的,不过表现在CM系列内核,基本没区别。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-29 04:42 , Processed in 0.170121 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表