【发布时间】:2019-12-03 02:45:34
【问题描述】:
为了使我正在编写的函数能够在 ISR 内部和外部使用,只使用 FreeRTOS API 调用的 ISR 安全版本是否安全?
// NOT ISR-safe
uint32_t messages_waiting(void)
{
return uxQueueMessagesWaiting(queue);
}
// ISR-safe
// - maybe just use this function ALL THE TIME??--both inside and outside ISRs?
uint32_t messages_waiting(void)
{
return uxQueueMessagesWaitingFromISR(queue);
}
FreeRTOS API 参考:https://www.freertos.org/a00018.html#ucQueueMessagesWaitingFromISR
以下是每个函数的 FreeRTOS 实现,来自 queue.c:
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
{
UBaseType_t uxReturn;
configASSERT( xQueue );
taskENTER_CRITICAL();
{
uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;
}
taskEXIT_CRITICAL();
return uxReturn;
} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )
{
UBaseType_t uxReturn;
configASSERT( xQueue );
uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;
return uxReturn;
} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
跟进:我可以看到非 ISR-safe 版本添加了访问保护:
taskENTER_CRITICAL();
taskEXIT_CRITICAL();
也许我也可以添加这些 ISR 安全版本,如下所示? 现在,这个函数可以在 ISR 内部和外部使用吗?
uint32_t messages_waiting(void)
{
UBaseType_t saved_interrupt_status = taskENTER_CRITICAL_FROM_ISR();
uint32_t num_msgs_waiting = uxQueueMessagesWaitingFromISR(queue);
taskEXIT_CRITICAL_FROM_ISR(saved_interrupt_status);
return num_msgs_waiting;
}
taskENTER_CRITICAL_FROM_ISR()的参考和示例用法:https://www.freertos.org/taskENTER_CRITICAL_FROM_ISR_taskEXIT_CRITICAL_FROM_ISR.html
【问题讨论】: