系统内核控制函数
内核控制函数就是 FreeRTOS 内核所使用的函数,一般情况下应用层程序不使用这些函数。如下所示:
临界段保护
临界段保护
FreeRTOS中关于临界区的定义:
/**
* 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)
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
可以看到,临界区保护其实是两个宏定义,具体实现在port.c文件中,如下所示:
void vPortEnterCritical(void)
{
// 1 禁止中断
// 2 变量++
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
if (uxCriticalNesting == 1)
{
configASSERT((portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK) == 0);
}
}
void vPortExitCritical(void)
{
// 1 变量--
// 2 如果 变量 = 0,则使能中断(实现了多层临界区嵌套)
configASSERT(uxCriticalNesting);
uxCriticalNesting--;
if (uxCriticalNesting == 0)
{
portENABLE_INTERRUPTS();
}
}
临界区源码说明:
中断中的临界区代码:
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)
{
// 先保存中断屏蔽值
status_value = taskENTER_CRITICAL_FROM_ISR();
total_num += 1;
printf("float_num 的值为: %d\r\n", total_num);
// 重新写入中断屏蔽值
taskEXIT_CRITICAL_FROM_ISR(status_value);
}
}
说明:
注意:
临界区代码一定要精简!因为进入临界区会关闭中断,这样会导致优先级低于 configMAX_SYSCALL_INTERRUPT_PRIORITY 的中断得不到及时的响应!