RTX一般是由ARM-MDK链接到预编译的RL-RTX库的,但是修改RTX内核function或者是增添新的function并且在自己的工程里面编译和链接修改后的RTX都是没问题的。本篇笔记主要关于如何在利用ARM-MDK在RTX中添加一个新的function,并且在自己的工程文件里面使用这个新的function。同样地,需要安装ARM-MDK和一块硬件板,笔记以STM32F4Discovery为例子。
这部分内容可能实战中很少会用到!如果你只是应用开发,可以放心跳过。
首先我们要找到RTX的源文件。一般来说路径是 C:\Keil\ARM\RL\RTX,这个文件夹下我们需要的有:RTX_Lib_CM.uvpot, RTX_Lib_CM, Config和SRC下的CM中的部分文件。
SRC下CM文件夹中的HAL_CM1,HAL_CM3可以删除掉,因为STM32F4Discovery用的是Cortex-M4的核。而删除的这两个文件其实是Cortex-M1,Cortex-M3的硬件抽象层(Hardware Abstraction Layer)。不同的板子需要有不同的HAL。
在工程文件夹中,新建一个文件夹,例如MyProject\RTXMod,作为修改后的RTX的源代码文件夹。复制上诉文件并粘贴进RTXMod中,注意保持其相对路径!
然后用uVision打开RTX_Lib_CM。首先注意到工程下有这些文件:
SRC下CM文件夹中的HAL_CM1,HAL_CM3可以删除掉,因为STM32F4Discovery用的是Cortex-M4的核。而删除的这两个文件其实是Cortex-M1,Cortex-M3的硬件抽象层(Hardware Abstraction Layer)。不同的板子需要有不同的HAL。
在工程文件夹中,新建一个文件夹,例如MyProject\RTXMod,作为修改后的RTX的源代码文件夹。复制上诉文件并粘贴进RTXMod中,注意保持其相对路径!
然后用uVision打开RTX_Lib_CM。首先注意到工程下有这些文件:
同样地,从工程中删除HAL_CM1,HAL_CM3文件。工程目标也要作相应的改动,点查看Manage Project Items。删除所有CM1,CM3相关内容。CM4,如果你明确你的板子的Edinaness,那么也可以删除额外的工程目标。ST的板子都是小端(Little Endian)。
接下来就可以Build了。正常情况不会报错。
那么打开RTXMod中的CM4F_LE文件夹,就能够看到RTX_CN4.lib文件,这个就是我们在自己工程文件下编译的RTX库文件。
如果想修改过的RTX被多个工程使用,那么最好的办法就是建立一个多工程的workspace,那么任何对RTX的修改,都会在workspace下的所有工程中得到体现。
首先在uVision中,选择Project-New Multi-Project Workspace...然后选择一个合适的路径,建立workspace文件,例如在MyProject文件夹中建立一个叫MyWorkspacet的workspace。然后就可以添加相应的工程进入这个workspace了。
首先添加你的RTX工程文件,其路径应该是MyProject/RTXMod/RTX_Lib_CM。然后添加你想使用RTX的工程文件。uVision5的工程文件好像还不太支持workspace,所以如果工程文件是uVision5的,得先转存为uVision4的工程文件,再添加到workspace中。
在Blinky能够调用本地的RTX前,需要添加几个文件:
1.RTL.h: 这个文件是编译器自带的头文件,如果要使用修改的RTX的function,那么必须得使用相应修改过的RTX.h。这个文件可以在C:\Keil\ARM\RV31\INC中找到。在RTXMod下创建INC文件夹,将该头文件复制到这个目录下。并在main.c中,加入其路径,如
#include "C:\Users\User\Desktop\MyProject\RTXMod\INC\RTL.h"
这里使用""而不是<>去标明include的文件,是因为""会让编译器先搜索指定路径,而<>会让编译器直接在预编译的库里寻找相关文件。
2.RTX_Conf_CM.c : 这个文件是RTX的参数配置文件,在MyProject\Config\下,在uVision工程中添加该文件即可。RTX_Conf_CM中include的是原来的RTX,同样得按照main那样,修改include语句。
3.RTX_CM4.lib: 这个就是我们刚刚第一步编译好的库文件,在MyProject\RTXMod\CM4F_LE\下,同样用uVision添加进工程。
完成这几步就可以使用自己编译的RTX了。尝试加入os_sys_init(init);或者其他RTX的function,build和run。没有问题。
U32 os_mod_version (void){ return __RL_ARM_VER; }这个function的主要功能就是返回当前RTX的版本号。这个版本号在头文件RTL.h中有相关定义:
/* RL-ARM version number. */ #define __RL_ARM_VER 473
首先创建.c文件和相应的.h文件,例如rt_Mod.c和rt_Mod.h,为了和原来的路径系统协调,把这两个文件也放入SRC\CM目录下,然后在RTX工程中添加rt_Mod.c文件。
这个文件需要添加三个头文件,第一就是其对应的.h文件,这里就是rt_Mod.h文件,第二就是RTX_Config.h文件,最后就是rt_TypeDef.h文件,这些都是RTX提供的统一配置和类型定义文件,参考其他的.c文件你可以发现这些文件是必须被include的。
同时,由于我们这里要使用__RL_ARM_VER,所以也必须要引用RTL.h头文件,所以rt_Mod.c最后就是:
/*---------------------------------------------------------------------------- * RL-ARM - RTX Mod *---------------------------------------------------------------------------- * Modification to the RTX * New functions *---------------------------------------------------------------------------- * Raymond Kwan 2014 *---------------------------------------------------------------------------*/ #include "rt_TypeDef.h" #include "RTX_Config.h" #include "rt_Mod.h" #include "C:/Users/User/Desktop/OS/RTXMod/INC/RTL.h" U32 os_mod_version (void){ return __RL_ARM_VER; } /*---------------------------------------------------------------------------- * end of file *---------------------------------------------------------------------------*/
相应地,头文件rt_Mod.h是:
/*---------------------------------------------------------------------------- * RL-ARM - RTX Mod *---------------------------------------------------------------------------- * Modification to the RTX * Header of new functions *---------------------------------------------------------------------------- * Raymond Kwan 2014 *---------------------------------------------------------------------------*/ extern U32 os_sys_version (void); /*---------------------------------------------------------------------------- * end of file *---------------------------------------------------------------------------*/
最后,在RTL.h中加入函数签名,注意要在Functions Cortex-M部分中添加,而不是Functuions ARM部分添加。
/*---------------------------------------------------------------------------- * Functions Cortex-M *---------------------------------------------------------------------------*/ #define __SVC_0 __svc_indirect /* Mod Functions*/ //Return the current RTX Version Number extern U32 os_mod_version(void);
到这一步,就可以在你要使用新function os_sys_version();添加这个语句。然后注意因为你新添加了一个文件进入RTX projct,它还未被编译,所以要在build你的project前要先编译RTX project。
当然也可以Batch Build两个工程。注意选择当前Active Project为你的project,而不是RTX project。点击批量构建两个工程文件。ARM-MDK会分开编译这两部分,最后再链接编译好的RTX库到你的project。
至此,大工告成。
RTX本身源代码就是开放的,而且由于其轻量级和实用性都很突出,是一个很出色的RTOS。但它也不是面面俱到,能涵盖所有的工程需求的。修改RTX内核只是为了针对具体项目进一步优化OS本身。当然这个工作量不会小。
另一方面,查看RTX源代码,并尝试修改(或者破坏),也有利于对OS本身的理解。由于现在开发工具和开发手段的优化程度都很高了,很多应用开发并不需要深入到对OS的理解,所以OS源代码总给人庞大而枯燥的感觉。RTX是一个很好的出发点,让我们去了解一些OS更加细节的实现问题。我也希望能够通过结合对RTX内核源代码的理解和书本文献介绍的OS概念结合起来,拓宽和深化自己对OS设计的认识。