要使用 API 版本 2 功能,请遵循以下步骤中描述的步骤:
- RTX 迁移指南 - 从 API 版本 1 迁移到 API 版本 2 的步骤
- 详细的 API 函数差异 - 功能差异列表
RTX5 提供两个 API 层:CMSIS-RTOS v1 和 CMSIS-RTOS v2 。这允许从 v1 到 v2 的梯度转换。修改的 v1 头文件和特殊的 v1 兼容性模块使现有代码可以在几乎不做任何修改的情况下在 v2 实现上运行。
只有少数不兼容和局限性存在:
- 内核启动
osKernelRunning 函数已被弃用。“main” 通常是 v1 实现中的一个正在运行的线程,而 v2 中不再是这种情况。也可能不初始化和启动内核,而只是假设 “main” 是一个正在运行的线程。可移植代码通常会初始化内核(osKernelInitialize),然后启动内核(osKernelStart)或如果osKernelRunning 表明它已在运行,则跳过该部分。
下面的示例代码显示了如何克服这种情况。 - OS 滴答
RTX5 使用 OS Tick API 配置滴答中断。间隔计算通常基于 SystemCoreClock 变量。因此必须在调用 osKernelStart 之前确保该变量已正确设置。 - osWait 函数已被弃用。
- 错误代码不兼容
CMSIS-RTOS v1 针对无效参数使用了两个不同的错误代码:osErrorParameter 和 osErrorValue 。新版本只使用通用的 osErrorParameter 代码。因此,依赖 osErrorValue 的代码不兼容。以下功能受到影响: - osDelay 返回码已经从 osErrorTimeout 更改为 osOK 。
迁移等级取决于项目在其生命周期中的阶段:
- 第一级迁移是在不改变 API 级别的情况下迁移到 RTX5 。
- 转换的第二个层次是使用 v2 API 函数和 v1 API 函数的混合变体。
- 第三个层次是完全转换到 API v2 。这不是微不足道的,需要一些额外的开发工作才能将所有 API v1 调用迁移到 v2。
1 级迁移 - 在 API v1 上升级到 RTX5
使用 API v1 兼容层从任何 4.x 版本升级到 RTX 版本 5 。按如下所示配置现有项目:
- 打开 Manage Run-Time Environment 窗口。
- 展开 CMSIS 软件组件。
- 展开 RTOS (API) , 取消 Keil RTX , 然后选择 Keil RTX5 。
- 展开 RTOS2 (API) 并选择 Keil RTX5 。
- 解决缺少的组件。
- 点击确定。
- 在 Project 窗口中展开 CMSIS 组:
- 打开 RTX_Config.h 并调整配置以适应包括(参考配置 RTX v5)在内的应用程序:
- 系统配置 -> 全局动态内存大小
- 内核节拍频率
- 线程配置 -> 默认线程堆栈大小
- 将函数 int main(void)重命名为 void app_main(void * arg)。
- 创建一个新的函数 int main(void),它至少实现:
示例 - 应用程序主线程
-
注意
- 在 RTOS API v1 中,所有时序均以毫秒为单位指定。RTX5 定义了内核滴答中的所有时间。为了与两者匹配,建议在系统配置中将内核节拍频率设置为 1000Hz 。
为了在迁移后验证 RTOS 的正确操作,您可以暂时将 RTOS 验证组件集成到您的项目中。
2 级迁移 - 在 RTX5 中使用 API v2 和 v1
在您的项目中实现新功能最好使用新的 API 来完成。这两个 API 版本都在 RTX5 中提供,并且可以一起存在。
组件选择与迁移级别 1 相同。
在需要访问 API v2 函数的所有模块中包含 “cmsis_os2.h” 。
以下片段显示了如何使用两个 API 版本创建的线程同时存在:
完整的示例 “RTX5 迁移” 是 CMSIS5 包的一部分,可从包安装程序中获取。
3 级迁移 - 完全转换到 API v2
完全迁移到 API v2 可以减少翻译层的开销并简化项目。有一些努力来替换和重新测试所有 API v1 调用。建议采用以下步骤作为粗略指导:
- 打开管理运行环境窗口:
- 展开 CMSIS 软件组件:
- 展开 RTOS(API)软件组件并取消 Keil RTX5
- 点击确定
- 交换所有的
#include "cmsis_os.h"
#include "cmsis_os2.h" - 确定所有对 API v1 的引用,并用 v2 中的相应调用进行替换。您可能想要使用 uVision 中的错误列表窗口快速识别相关的代码段落。
-
注意
- 有关详细信息,请参阅 详细的 API 函数差异。
通常不再有 os * Def 宏来声明 OS 对象。
-
注意
-
- 信号事件已被替换。改为使用 “线程标志” 和 “事件标志” 下列出的功能。
- 邮件队列 RTOS v1 功能已被弃用。改为使用消息队列的功能。差异在消息队列下列出。
本节列出 CMSIS-RTOS API v1 和 API v2 函数以及功能差异。该列表按照 API v2 函数名称的字母顺序进行排序,结构如下:
- RTOS API v2 函数原型。
- RTOS API v1 函数原型相当于或提供了类似的功能。
- RTOS v2 功能简述。
- 差别的描述。
背景颜色表示:
-
绿色:API v2 中的新功能在 API v1 中不可用
-
琥珀色:与 API v1 相比,在 API v2 中修改或替换的功能
-
红色:在 API v2 中弃用的 API v1 中的函数
内核信息和控制
osStatus_t osKernelGetInfo (osVersion_t* version, char* id_buf, uint32_t id_size)
没有
获取 RTOS 内核信息。
新功能 osKernelGetInfo 。
osKernelState_t osKernelGetState (void)
int32_t osKernelRunning (void)
获取当前的 RTOS 内核状态。
- 函数 osKernelGetState 替换了 RTOS v1 函数 osKernelRunning 。
- 返回类型更改为 osKernelState_t 。
uint32_t osKernelGetTickFreq (void)
没有
获取 RTOS 内核滴答频率。
- 函数 osKernelGetTickFreq 替换了 RTOS v1 宏 osKernelTickMicroSec 。
uint32_t osKernelGetSysTimerCount (void)
uint32_t osKernelSysTick (void)
获取 RTOS 内核系统计时器计数。
- 函数 osKernelGetSysTimerCount 替换了 RTOS v1 函数 osKernelSysTick 。
osStatus_t osKernelInitialize (void)
osStatus osKernelInitialize (void)
初始化 RTOS 内核。
- 返回类型更改为 osStatus_t 。
线程管理
osThreadId_t osThreadGetId (void)
osThreadId osThreadGetId (void)
返回当前正在运行的线程的线程 ID 。
- 返回类型更改为 osThreadId_t 。
osPriority_t osThreadGetPriority (osThreadId_t thread_id)
osPriority osThreadGetPriority (osThreadId thread_id)
获取线程的当前优先级。
- 返回类型更改为 osPriority_t 。
- 参数类型更改为 osThreadId_t 。
osThreadId_t osThreadNew (osThreadFunc_t function, void *argument, const osThreadAttr_t *attr)
osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument)
创建一个线程并将其添加到活动线程。
- 函数 osThreadNew 替换了 RTOS v1 函数 osThreadCreate 。
- 现在使用 osThreadAttr_t 结构体传递项目, 取代 osThreadDef 宏。
- 新的函数原型是
void func (void *arg)
, 之前是:void func (const void *arg)
。
osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority)
osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority)
更改线程的优先级。
- 返回类型更改为 osStatus_t 。
- 参数类型更改为 osThreadId_t 和 osPriority_t 。
osStatus_t osThreadTerminate (osThreadId_t thread_id)
osStatus osThreadTerminate (osThreadId thread_id)
终止线程的执行。
- 返回类型更改为 osStatus_t 。
- 参数类型更改为 osThreadId_t 。
osStatus_t osThreadYield (void)
osStatus osThreadYield (void)
将控制权交给状态为 READY 的下一个线程。
- 返回类型更改为 osStatus_t 。
线程标志
新部分使用标志同步线程。线程标志和更灵活的事件标志取代了 RTOS v1 信号事件。请参阅信号事件以获取不推荐使用的功能列表。有关详细信息,请参阅线程标记。
uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout)
没有
等待当前正在运行的线程的一个或多个线程标志发出信号。
新功能。
事件标志
新部分使用标志同步事件。事件标志和线程标志取代了 RTOS v1 信号事件。RTOS v1 信号事件中列出的所有功能已被弃用。请参阅信号事件以获取不推荐使用的功能列表。 有关新功能的详细信息,请参阅事件标志。
uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout)
没有
等待一个或多个事件标志发出信号。
新功能。
通用等待函数
详情请参阅通用等待功能。
osStatus_t osDelay (uint32_t ticks)
osStatus osDelay (uint32_t timeout)
等待超时(时间延迟)。
- 返回类型更改为 osStatus_t 。
osEvent osWait (uint32_t millisec)
已过时。
定时器管理
详情请参阅定时器管理。
osStatus_t osTimerDelete (osTimerId_t timer_id)
osStatus osTimerDelete (osTimerId timer_id)
删除一个定时器。
- 返回类型更改为 osStatus_t 。
- 参数类型更改为 osTimerId_t 。
osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr)
osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument)
创建并初始化一个定时器。
- 函数 osTimerNew 替换了 RTOS v1 函数 osTimerCreate 。
- 返回类型更改为 osTimerId_t 。
- 参数列表和类型已更改。
osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks)
osStatus osTimerStart (osTimerId timer_id, uint32_t timeout)
启动或重新启动定时器。
- 返回类型更改为 osStatus_t 。
- 第一个参数类型更改为 osTimerId_t 。
osStatus_t osTimerStop (osTimerId_t timer_id)
osStatus osTimerStop (osTimerId timer_id)
停止一个定时器。
- 返回类型更改为 osStatus_t 。
- 参数类型更改为 osTimerId_t 。
互斥管理
有关详细信息,请参阅互斥管理。
osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout)
osStatus osMutexWait (osMutexId mutex_id, uint32_t timeout)
如果它被锁定,则获取互斥锁或超时值。
- 函数 osMutexAcquire 替换了 RTOS v1 函数 osMutexWait 。
- 返回类型更改为 osStatus_t 。
- 第一个参数类型更改为 osMutexId_t 。
osStatus_t osMutexDelete (osMutexId_t mutex_id)
osStatus osMutexDelete (osMutexId mutex_id)
删除互斥对象。
- 返回类型更改为 osStatus_t 。
- 参数类型更改为 osMutexId_t 。
osMutexId_t osMutexNew (const osMutexAttr_t *attr)
osMutexId osMutexCreate (const osMutexDef_t *mutex_def)
创建并初始化一个互斥对象。
- 函数 osMutexNew 替换了 RTOS v1 函数 osMutexCreate 。
- 返回类型更改为 osMutexId_t 。
- 参数类型更改为 osMutexAttr_t 。
osStatus_t osMutexRelease (osMutexId_t mutex_id)
osStatus osMutexRelease (osMutexId mutex_id)
释放由 osMutexAcquire 获取的互斥锁。
- 返回类型更改为 osStatus_t 。
- 参数类型更改为 osMutexId_t 。
信号量
有关详细信息,请参阅信号量。
osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout)
没有
如果没有令牌可用,则获取信号标记或超时。
新功能。取代
osSemaphoreWait
。
osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id)
osStatus osSemaphoreDelete (osSemaphoreId semaphore_id)
删除一个信号量对象。
- 返回类型更改为 osStatus_t 。
- 参数类型更改为 osSemaphoreId_t 。
osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)
osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count)
创建并初始化信号量对象。
- 函数 osSemaphoreNew 替换了 RTOS v1 函数 osSemaphoreCreate 。
- 返回类型更改为 osSemaphoreId_t 。
- 参数列表和类型已更改。
osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id)
osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)
释放一个信号量令牌直到最初的最大数量。
- 返回类型更改为 osStatus_t 。
- 参数类型更改为 osSemaphoreId_t 。
int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t timeout)
已过时。取而代之 osSemaphoreAcquire 。
内存池
void * osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout)
void * osPoolAlloc (osPoolId pool_id)
从内存池中分配内存块。
- 函数 osMemoryPoolAlloc 替换了 RTOS v1 函数 osPoolAlloc 。
- 参数列表和类型已更改。
osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void * block)
osStatus osPoolFree (osPoolId pool_id, void * block)
将分配的内存块返回到内存池。
- 函数 osMemoryPoolFree 替换了 RTOS v1 函数 osPoolFree 。
- 第一个参数类型 osMemoryPoolId_t 替换了 ROTS v1 类型 osPoolId 。
osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr)
osPoolId osPoolCreate (const osPoolDef_t * pool_def)
获取内存池中可用的内存块数量。
- 函数 osMemoryPoolNew 替换了 RTOS v1 函数 osPoolCreate 。
- 返回类型更改为 osMemoryPoolId_t 。
- 参数列表和参数类型已更改。
消息队列
通常,消息现在使用固定大小的内存,而不是32位值。有关详细信息,请参阅消息队列。
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout)
osEvent osMessageGet (osMessageQId queue_id, uint32_t timeout)
如果队列为空,则从队列获取消息或超时。
- 函数 osMessageQueueGet 替换了 RTOS v1 函数 osMessageGet 。
- 返回类型更改为 osStatus_t 。
- 参数列表和参数类型已更改。
osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr)
osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id)
创建并初始化消息队列对象。
- 函数 osMessageQueueNew 替换了 RTOS v1 函数 osMessageCreate 。
- 返回类型更改为 osMessageQueueId_t 。
- 参数列表和参数类型已更改。
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout)
osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t timeout)
如果队列已满,请将消息放入队列或超时。
- 函数 osMessageQueuePut 替换了 RTOS v1 函数 osMessagePut 。
- 返回类型更改为 osStatus_t 。
- 参数列表和参数类型已更改。
邮件队列
邮件队列 RTOS v1 功能已被弃用。改为使用 Message Queue 的功能。差异在 Message Queue 下列出。
void * osMailAlloc (osMailQId queue_id, uint32_t timeout)
已过时。
void * osMailCAlloc (osMailQId queue_id, uint32_t timeout)
已过时。
osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id)
已过时。
osStatus osMailFree (osMailQId queue_id, void *mail)
已过时。
osEvent osMailGet (osMailQId queue_id, uint32_t timeout)
已过时。
osStatus osMailPut (osMailQId queue_id, void *mail)
已过时。
信号事件
RTOS v1 信号事件部分已被弃用。改用线程标志下面列出的功能。
int32_t osSignalClear (osThreadId thread_id, int32_t signals)
已过时。
int32_t osSignalSet (osThreadId thread_id, int32_t signals)
已过时。
osEvent osSignalWait (int32_t signals, uint32_t timeout)
已过时。