配置MSPM0G3507带有 Sysconfig 的 FreeRTOS 工程(在CCS+SDK环境下)

Lead In
最近在跟着正点原子学习FreeRTOS,刚好学院微机原理用的是TI板,于是用新学的Cadence画了块板子之后就打算把FreeRTOS搬上MSPM0G3507。结果发现,SDK的模板全都不支持sysconfig,在kernel文件夹里面的两个例程看似有sysconfig,实则被禁用了。去官方论坛的帖子一查——
果然,TI官方目前没有支持sysconfig和FreeRTOS的融合。。。
《To be honest, this would be potentially too late》——时不我待,那就来自己搞一搞吧!
CCS环境
来翻这篇文章的想必手上都有环境了。没有也没关系,这个环境很好配,sysconfig包含在CCS中了,SDK其实也可以在CCS里面自动下载,但是今天SDK是主角,我也把链接端上来。
如果(建议)手动安装SDK(毕竟不要什么都往C盘放),可以在CCS界面的左下角打开菜单-CCS Settings...,左侧找到Products的tag。如果是自己安装的SDK,就把SDK的安装路径补上去,后续就可以被软件、工程索引。如果是内置安装的SDK就在这个界面里面找到SDK的安装路径。


理论上,本文介绍的移植的方法并不依赖于CCS的开发环境,但是我没试过其他方案(IAR,Keil),留给大家探索叭~
创建、配置工程
基础工程——sysconfig启动!
左上角File - Import Project,然后browse索引,去SDK的路径下找到最基本的、含有sysconfig的空工程:
mspm0_sdk_2_04_00_06\examples\nortos\LP_MSPM0G3507\driverlib\empty
- 注意,你选择了哪个编译器,GCC还是TIClang,要记住,我跑起来的是TIClang。

然后打开sysconfig文件,配置好和板子适配的时钟树、debug引脚、GPIO,UART,跑一跑最基本的点灯和UART操作。
配置FreeRTOS文件
接下来,打开SDK的安装路径,开始配置FreeRTOS的文件:
配置工程路径
在刚才的工程主目录下创建FreeRTOS文件夹,并配置好目录。这里的目录可以根据个人喜好来处理,但是要记清楚,后面要头文件。


从SDK复制文件
\mspm0_sdk_2_04_00_06\kernel\freertos\Source
│ croutine.c
│ event_groups.c
│ list.c
│ queue.c
│ stream_buffer.c
│ tasks.c
│ timers.c
- 把这七个
.c文件复制到工程文件夹下的Src文件夹下
\mspm0_sdk_2_04_00_06\kernel\freertos\Source\include
│ atomic.h
│ croutine.h
│ deprecated_definitions.h
│ event_groups.h
│ FreeRTOS.h
│ list.h
│ message_buffer.h
│ mpu_prototypes.h
│ mpu_wrappers.h
│ portable.h
│ projdefs.h
│ queue.h
│ semphr.h
│ StackMacros.h
│ stack_macros.h
│ stream_buffer.h
│ task.h
│ timers.h
- 把所有头文件复制到
Inc文件夹下。
\mspm0_sdk_2_04_00_06\kernel\freertos\Source\portable
├─GCC
│ └─ARM_CM0
│ port.c
│ portmacro.h
│
├─IAR
│ └─ARM_CM0
│ port.c
│ portasm.s
│ portmacro.h
│
├─MemMang
│ heap_1.c
│ heap_2.c
│ heap_3.c
│ heap_4.c
│ heap_5.c
│
└─TI_ARM_CLANG
└─ARM_CM0
port.c
portmacro.h
- 刚才模板工程选择了TICLang编译器的,就把
TI_ARM_CLANG放进Port文件夹。如果选择的是GCC编译器,就把GCC文件夹复制过去。
可以点进去看一下,
TI_ARM_CLANG下面是ARM_CM0,顾名思义;再进去是两个文件,port.c,portmarco.h,这一个文件夹下的内容是对编译器和 MSPM0 做的适配。
- 回到
portable文件夹,打开MemMang(Memory Management),这几个文件是选择内存管理方案的,选择一个即可,具体区别是什么问问AI,大部分情况下选的是heap_4.c。把你选择的文件复制到工程文件夹的Port文件夹下。
\mspm0_sdk_2_04_00_06\kernel\freertos\builds\LP_MSPM0G3507\release\FreeRTOSConfig.h
注意这里的路径不是source了,是build,把FreeRTOSConfig.h复制到工程文件夹下FreeRTOS直接的目录下。
这样,所有需要的文件就配置到工程里了,检查一下路径:
\FreeRTOS
│
│ FreeRTOSConfig.h
│
├─Inc
│ atomic.h
│ croutine.h
│ deprecated_definitions.h
│ event_groups.h
│ FreeRTOS.h
│ list.h
│ message_buffer.h
│ mpu_prototypes.h
│ mpu_wrappers.h
│ portable.h
│ projdefs.h
│ queue.h
│ semphr.h
│ StackMacros.h
│ stack_macros.h
│ stream_buffer.h
│ task.h
│ timers.h
│
├─Port
│ │ heap_4.c
│ │
│ └─TI_ARM_CLANG
│ └─ARM_CM0
│ port.c
│ portmacro.h
│
└─Src
croutine.c
event_groups.c
list.c
queue.c
stream_buffer.c
tasks.c
timers.c
设置引用路径
- 如果在Keil里面配置,要先把所有的
.c文件添加到左侧的工程文件中,这样才会编译。- CCS好像会自己检索所有的工程文件夹,或者自己处理函数引用关系进行编译,反正我没处理过源文件的引用问题,编译就完整通过了。
- 右键点击工程文件夹,进入
Properties...,

- 左侧打开
Build-tools-Arm Compiler-Include Options,然后把存在.h头文件的所有目录都添加到Include Path中

如果是GCC编译器,菜单不一样,在
Directory配置引用路径。如果是Keil,就打开魔法棒添加引用路径,左侧工程添加编译源文件。
修改FreeRTOSConfig.h
众所周知,FreeRTOS的内核是可裁剪的,有些功能是需要额外添加代码实现的,在配置第一个demo的时候,可以先裁剪掉,聚焦于最基本的调度。因此,这里先对FreeRTOSConfig.h进行修改。
注意,这些裁剪都有对应的宏定义,不要自己添加,先找到宏定义项,再修改对应的数值!
#include "ti_msp_dl_config.h"
/* Other Codes */
#define configCPU_CLOCK_HZ ((unsigned long) CPUCLK_FREQ)
- 在开头引用Driverlib的头文件,然后把系统主频改成Sysconfig生成的Marco:
#define configSUPPORT_STATIC_ALLOCATION 0
- 禁用静态管理内存,这样不需要手动配置空闲任务
#define configUSE_TIMERS 0
- 禁用软件定时器,在配置的时候用不上,而且不去管他的话会报错。
#define configCHECK_FOR_STACK_OVERFLOW 0
- 不检查栈溢出。对于这个小内存的板子,为了程序的安全性其实应该打开的,但是我们需要手动定义栈溢出的异常处理函数,所以先关掉了,上手后记得重新开起来。
#define configTOTAL_HEAP_SIZE ((size_t)(16 * 1024))
- MSPM0G3507 的 SRAM 有 32KB,这里配置16KB给RTOS自动管理,有需要后面再做调整。在 Create Task 的时候养成好习惯,检查返回值。
试试看跑任务!
配置完这些文件后,就可以编译、烧录、调试了!这里附上主文件的代码:
#include "ti_msp_dl_config.h"
#include "FreeRTOS.h"
#include "task.h"
void task_Blink(void*);
TaskHandle_t task_Blink_Handle = {0};
void task_TX(void*);
TaskHandle_t task_TX_Handle = {0};
int main(void)
{
SYSCFG_DL_init();
BaseType_t xReturn = pdPASS;
xReturn = xTaskCreate(task_Blink, "Blink", 128, NULL, 2, &task_Blink_Handle);
if (xReturn != pdPASS) while(1);
xReturn = xTaskCreate(task_TX, "UART_TX", 384, NULL, 1, &task_TX_Handle);
if (xReturn != pdPASS) while(1);
DL_GPIO_setPins(LED_PORT, LED_LEDR_PIN | LED_LEDY_PIN);
vTaskStartScheduler();
return 0;
}
/* ==================== DEFINITIONS ==================== */
void task_Blink(void* p)
{
(void)p;
while(1)
{
DL_GPIO_togglePins(LED_PORT, LED_LEDY_PIN);
vTaskDelay(500);
}
}
void task_TX(void* p)
{
(void)p;
char msg[8] = "task_TX\n";
while(1)
{
for(uint8_t i=0;i<8;i++)
{
DL_UART_transmitDataBlocking(UART0,msg[i]);
}
vTaskDelay(2000);
}
}
两个死循环能够“同时”运行,就说明任务调度器在正常工作,FreeRTOS成功跑起来了。
我把我自己配置完成的工程挂在 Gitee的仓库里 了,有需要的自取 QwQ
总结
听了 FreeRTOS 的课程,使用过 CCS 的人来配置这个环境,过程应该是比较简单的。Sysconfig虽然在 SDK 的 FreeRTOS 工程里不支持,但是目前看来是不影响 FreeRTOS运行的,毕竟在port.c文件中,强制覆盖 Systick 中断配置、Systick 中断、PendSV 中断、SVC 中断都写好了,在学习好 FreeRTOS 和 Arm Cortex-M0 的基础知识后,或许可以更加随心所欲地掌控这片 MCU 了。
有趣的是,TI 还给 FreeRTOS 的库又套了一层 POSIX 的壳,估计是为了更好地在嵌入式系统之间迁移,但是这就超出了我的知识范畴了——
若有错误与疏漏,还请多多指教!
更多推荐

所有评论(0)