RTX5可以在中断中调用的API
在 RTX5(Keil RTX5 实时操作系统) 中,中断服务程序(ISR) 可以调用部分 线程安全(ISR Callable) 的 API 函数,但必须遵循 非阻塞、无优先级反转 的原则。以下是 RTX5 允许在中断中调用的 API 列表(基于 CMSIS-RTOS2 规范):
✅ RTX5 中断中可安全调用的 API
1. 线程管理(Thread Management)
API 函数 | 功能 | 是否可中断调用 |
---|---|---|
osThreadFlagsSet | 向指定线程发送标志位(用于中断→任务通信) | ✅ 可以 |
osThreadResume | 恢复被挂起的线程 | ✅ 可以 |
❌ 不可调用:
osThreadNew
、osThreadTerminate
、osThreadSuspend
(可能阻塞或影响调度)。
2. 事件标志(Event Flags)
API 函数 | 功能 | 是否可中断调用 |
---|---|---|
osEventFlagsSet | 设置事件标志(任务可等待) | ✅ 可以 |
osEventFlagsClear | 清除事件标志 | ✅ 可以 |
❌ 不可调用:
osEventFlagsWait
(会阻塞,只能在任务中调用)。
3. 信号量(Semaphore)
API 函数 | 功能 | 是否可中断调用 |
---|---|---|
osSemaphoreRelease | 释放信号量(任务可获取) | ✅ 可以 |
osSemaphoreAcquire | 获取信号量(不可在中断调用,会阻塞) | ❌ 不可以 |
❌ 不可调用:
osSemaphoreNew
、osSemaphoreDelete
(可能涉及内存分配)。
4. 消息队列(Message Queue)
API 函数 | 功能 | 是否可中断调用 |
---|---|---|
osMessageQueuePut | 发送消息(非阻塞模式) | ✅ 可以 |
osMessageQueueGet | 接收消息(仅限超时=0 时可用) | ⚠️ 部分可调用(仅 timeout=0 时) |
❌ 不可调用:
osMessageQueueNew
、osMessageQueueDelete
(可能涉及内存分配)。
5. 内存池(Memory Pool)
API 函数 | 功能 | 是否可中断调用 |
---|---|---|
osMemoryPoolAlloc | 分配内存(仅限 timeout=0 时可用) | ⚠️ 部分可调用(仅 timeout=0 时) |
osMemoryPoolFree | 释放内存 | ✅ 可以 |
❌ 不可调用:
osMemoryPoolNew
、osMemoryPoolDelete
(可能涉及内存分配)。
6. 定时器(Timer)
API 函数 | 功能 | 是否可中断调用 |
---|---|---|
osTimerStart | 启动定时器 | ✅ 可以 |
osTimerStop | 停止定时器 | ✅ 可以 |
osTimerDelete | 删除定时器 | ❌ 不可以(可能涉及内存释放) |
❌ 不可调用:
osTimerNew
(可能涉及内存分配)。
7. 互斥锁(Mutex) & 递归互斥锁(Recursive Mutex)
API 函数 | 功能 | 是否可中断调用 |
---|---|---|
osMutexRelease | 释放互斥锁(任务可获取) | ✅ 可以 |
osMutexAcquire | 获取互斥锁(不可在中断调用,会阻塞) | ❌ 不可以 |
osRecursiveMutexRelease | 释放递归互斥锁 | ✅ 可以 |
osRecursiveMutexAcquire | 获取递归互斥锁(不可在中断调用) | ❌ 不可以 |
❌ 不可调用:
osMutexNew
、osMutexDelete
(可能涉及内存分配)。
❌ RTX5 中断中不可调用的 API
以下 API 绝对不能在中断中调用(会导致系统崩溃或未定义行为):
- 任何阻塞操作(如
osDelay
、osSemaphoreAcquire
、osMutexAcquire
、osEventFlagsWait
、osMessageQueueGet
带超时)。 - 动态内存分配/释放(如
osThreadNew
、osTimerNew
、osMutexNew
、osMemoryPoolNew
)。 - 线程挂起/删除(如
osThreadSuspend
、osThreadTerminate
)。 - 系统初始化/关闭(如
osKernelInitialize
、osKernelStart
、osKernelLock
)。
✅ 中断与任务通信的最佳实践
1. 使用 osThreadFlagsSet
(推荐)
// 中断中(非阻塞)
osThreadFlagsSet(task_id, 0x01); // 向任务发送标志位// 任务中(等待标志位)
uint32_t flags = osThreadFlagsWait(0x01, osFlagsWaitAny, osWaitForever);
2. 使用 osSemaphoreRelease
// 中断中(非阻塞)
osSemaphoreRelease(mySemaphore); // 释放信号量// 任务中(等待信号量)
osSemaphoreAcquire(mySemaphore, osWaitForever); // 阻塞等待
3. 使用 osMessageQueuePut
// 中断中(非阻塞)
osMessageQueuePut(myQueue, &data, 0, 0); // 发送消息(不阻塞)// 任务中(接收消息)
osMessageQueueGet(myQueue, &data, NULL, osWaitForever); // 阻塞等待
📌 总结
API 类型 | 是否可中断调用 | 备注 |
---|---|---|
osThreadFlagsSet | ✅ | 推荐用于中断→任务通信 |
osSemaphoreRelease | ✅ | 任务可 osSemaphoreAcquire 等待 |
osMessageQueuePut | ✅ | 任务可 osMessageQueueGet 等待 |
osMemoryPoolFree | ✅ | 释放内存 |
osEventFlagsSet | ✅ | 设置事件标志 |
osTimerStart / osTimerStop | ✅ | 控制定时器 |
osMutexRelease | ✅ | 释放互斥锁 |
任何阻塞 API | ❌ | 如 osDelay 、osSemaphoreAcquire |
动态创建/删除 API | ❌ | 如 osThreadNew 、osTimerNew |
关键规则:
- 中断中只能调用非阻塞 API。
- 避免在中断中分配/释放内存(除非使用静态分配)。
- 优先使用
osThreadFlagsSet
或信号量进行中断→任务通信。
参考官方文档:https://arm-software.github.io/CMSIS_5/RTOS2/html/group__CMSIS__RTOS__Definitions.html