原创 六、freeRTOS 系统内核控制函数与临界段保护

2020-8-23 16:41 1495 16 16 分类: 汽车电子 文集: FreeRTOS

系统内核控制函数

内核控制函数就是 FreeRTOS 内核所使用的函数,一般情况下应用层程序不使用这些函数。如下所示:

 

临界段保护

临界段保护

FreeRTOS中关于临界区的定义:

  1. /**
  2. * task. h
  3. *
  4. * Macro to mark the start of a critical code region. Preemptive context
  5. * switches cannot occur when in a critical region.
  6. *
  7. * NOTE: This may alter the stack (depending on the portable implementation)
  8. * so must be used with care!
  9. *
  10. * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
  11. * \ingroup SchedulerControl
  12. */
  13. #define taskENTER_CRITICAL() portENTER_CRITICAL()
  14. #define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
  15. /**
  16. * task. h
  17. *
  18. * Macro to mark the end of a critical code region. Preemptive context
  19. * switches cannot occur when in a critical region.
  20. *
  21. * NOTE: This may alter the stack (depending on the portable implementation)
  22. * so must be used with care!
  23. *
  24. * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL
  25. * \ingroup SchedulerControl
  26. */
  27. #define taskEXIT_CRITICAL() portEXIT_CRITICAL()
  28. #define taskEXIT_CRITICAL_FROM_ISR(x) portCLEAR_INTERRUPT_MASK_FROM_ISR(x)
  29. #define portENTER_CRITICAL() vPortEnterCritical()
  30. #define portEXIT_CRITICAL() vPortExitCritical()

可以看到,临界区保护其实是两个宏定义,具体实现在port.c文件中,如下所示:

  1. void vPortEnterCritical(void)
  2. {
  3. // 1 禁止中断
  4. // 2 变量++
  5. portDISABLE_INTERRUPTS();
  6. uxCriticalNesting++;
  7. if (uxCriticalNesting == 1)
  8. {
  9. configASSERT((portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK) == 0);
  10. }
  11. }
  12. void vPortExitCritical(void)
  13. {
  14. // 1 变量--
  15. // 2 如果 变量 = 0,则使能中断(实现了多层临界区嵌套)
  16. configASSERT(uxCriticalNesting);
  17. uxCriticalNesting--;
  18. if (uxCriticalNesting == 0)
  19. {
  20. portENABLE_INTERRUPTS();
  21. }
  22. }

临界区源码说明:

中断中的临界区代码:

  1. void TIM3_IRQHandler(void)
  2. {
  3. if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)
  4. {
  5. // 先保存中断屏蔽值
  6. status_value = taskENTER_CRITICAL_FROM_ISR();
  7. total_num += 1;
  8. printf("float_num 的值为: %d\r\n", total_num);
  9. // 重新写入中断屏蔽值
  10. taskEXIT_CRITICAL_FROM_ISR(status_value);
  11. }
  12. }

说明:

注意:

临界区代码一定要精简!因为进入临界区会关闭中断,这样会导致优先级低于 configMAX_SYSCALL_INTERRUPT_PRIORITY 的中断得不到及时的响应!

转载于:https://blog.csdn.net/dingyc_ee/article/details/104088202

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
16
关闭 站长推荐上一条 /3 下一条