第2章 新建FreeRTOS工程——软件仿真
在开始写FreeRTOS内核之前,先新建一个FreeRTOS的工程,Device选择Cortex-M3(Cortex-M4或Cortex-M7)内核的处理器,调试方式选择软件仿真,然后我们再开始一步一步地教大家把FreeRTOS内核从0到1写出来,让大家彻底搞懂FreeRTOS的内部实现和设计的思想。最后我们再把FreeRTOS移植到野火STM32开发板上,最后的移植其实已经非常简单,只需要换一下启动文件和添加bsp驱动即可。
2.1 新建本地工程文件夹
在开始新建工程之前,我们先在本地计算机端新建一个文件夹用于存放工程。文件夹名设置为“新建FreeRTOS工程——软件仿真”(名字可以随意设置),然后在该文件夹下面新建各个文件夹和文件,有关这些文件夹的包含关系和作用具体如表2-1所示。
表2-1 工程文件夹根目录下的文件夹及作用
2.2 使用KEIL新建工程
开发环境我们使用KEIL5,版本为5.23,高于版本5即可。
2.2.1 New Project
首先打开KEIL5软件,新建一个工程,工程文件放在目录Project下面,名称为Fire_FreeRTOS,文件夹名称必须是英文,不能是中文。
2.2.2 Select Device for Target
设置好工程名称,单击OK按钮之后会弹出Select Device for Target对话框,让我们选择处理器,这里选择ARMCM3(ARMCM4或ARMCM7),具体如图2-1(图2-2或图2-3)所示。
图2-1 Select Device(ARMCM3)for Target
图2-2 Select Device(ARMCM4)for Target
图2-3 Select Device(ARMCM7)for Target
2.2.3 Manage Run-Time Environment
选择好处理器,单击OK按钮后会弹出Manage Run-Time Environment对话框。这里我们在CMSIS栏中选中CORE,在Device栏中选中Startup即可,具体如图2-4所示。
图2-4 Manage Run-Time Environment
单击OK按钮,关闭Manage Run-Time Environment对话框之后,刚刚我们选择的CORE和Startup这两个文件就会添加到工程组的CMSIS中,具体如图2-5所示。
图2-5 CORE和Startup文件
其实这两个文件刚开始都是存放在KEIL的安装目录下,当我们配置Manage Run-Time Environment对话框之后,软件就会把选中的文件从KEIL的安装目录复制到我们的工程目录Project\RTE\Device\ARMCM3(ARMCM4或ARMCM7)下面。其中startup_ARMCM3.s(startup_ARMCM4.s或startup_ARMCM7.s)是用汇编语言编写的启动文件,system_ARMCM3.c(system_ARMCM4.c或system_ARMCM7.c)是用C语言编写的与时钟相关的文件。更加具体的内容可直接参见这两个文件的源码。只要是Cortex-M3(Cortex-M4或Cortex-M7)内核的单片机,这两个文件都适用。
2.3 在KEIL工程中新建文件组
在工程里面添加user、rtt/ports、rtt/source和doc这几个文件组,用于管理文件,具体如图2-6所示。
对于新手,这里有个问题,就是如何添加文件组,具体的方法为右击Target 1,在弹出的快捷菜单中选择Add Group…命令,具体如图2-7所示,需要创建多少个组,就按上述方法操作多少次。
图2-6 新添加的文件组
图2-7 如何添加组
2.4 在KEIL工程中添加文件
在工程中添加组之后,需要把本地工程中新建的文件添加到工程,具体为把readm.txt文件添加到doc组,main.c文件添加到user组,FreeRTOS相关的文件我们还没有编写,那么FreeRTOS相关的组暂时为空,具体如图2-8所示。
图2-8 向组中添加文件
对于新手,这里有个问题就是如何将本地工程中的文件添加到工程组,具体的方法为双击相应的组,在弹出的对话框中找到要添加的文件,默认的文件类型是C文件,如果要添加的是文本或者汇编文件,那么此时将看不到,这时就需要把文件类型设置为All Files,最后单击Add按钮即可,具体如图2-9所示。
图2-9 向组中添加文件
下面编写main()函数。
一个工程如果没有main()函数是无法编译成功的,因为系统在开始执行时先执行启动文件中的复位程序,复位程序里面会调用C库函数__main,__main的作用是初始化系统变量,如全局变量、只读的变量、可读可写的变量等。__main最后会调用__rtentry,再由__rtentry调用main()函数,从而由汇编进入C的世界,这里面的main()函数就需要我们手动编写,如果没有编写main()函数,就会出现main()函数没有定义的错误,具体如图2-10所示。
图2-10 没定义main()函数的错误
我们将main()函数写在main.c文件中,因为是刚刚新建的工程,所以main()函数暂时为空,具体参见代码清单2-1。
代码清单2-1 main()函数
1 /* 2 ************************************************************************ 3 * main()函数 4 ************************************************************************ 5 */ 6 int main(void) 7 { 8 for (;;) 9 { 10 /* 无操作 */ 11 } 12 }
2.5 调试配置
2.5.1 设置软件仿真
最后,我们再配置一下与调试相关的参数。为了方便,全部代码都用软件仿真,既不需要开发板也不需要仿真器,只需要一个KEIL软件即可,有关软件仿真的配置具体如图2-11所示。
图2-11 软件仿真的配置
2.5.2 修改时钟大小
在时钟相关文件system_ARMCM3.c(system_ARMCM4.c或system_ARMCM7.c)的开头,有一段代码定义了系统时钟的频率为25MHz,具体参见代码清单2-2。在软件仿真时,为确保时间的准确性,代码中的系统时钟与软件仿真的时钟必须一致,所以Options for Target对话框中Target的时钟频率应该由默认的12MHz改成25MHz,具体如图2-12所示。
代码清单2-2 时钟相关宏定义
1 #define __HSI ( 8000000UL) 2 #define __XTAL ( 5000000UL) 3 4 #define __SYSTEM_CLOCK (5*__XTAL) /* 5×5000000 = 25M */
2.5.3 添加头文件路径
在C/C++选项卡中指定工程头文件的路径,否则编译会出错。头文件路径的具体指定方法如图2-13所示。
图2-12 软件仿真时钟配置
图2-13 指定头文件的路径
至此,一个完整的基于Cortex-M3(Cortex-M4或Cortex-M7)内核的FreeRTOS软件仿真工程建立完毕。