1122|7

180

帖子

0

资源

一粒金砂(中级)

【GD32L233C-START评测】3.移植FreeRTOS到GD32L233 [复制链接]

本帖最后由 hehung 于 2022-1-18 21:45 编辑

FreeRTOS作为一款开源的嵌入式实时操作系统,广泛的运用在嵌入式行业,在芯片中集成嵌入式系统也是很有必要的一件事,可以方便的处理各个任务之间的关系,进行精确地时间控制等。本文将讲解如何在GD32L233C中集成FreeRTOS OS

 

本文讲解将FreeRTOS移植到GD32L233C 单片机上,同样也适用任何Cortex-M23的芯片。

本文使用的最新源码包:V10.4.6

一、下载FreeRTOS源码

FreeRTOS的源码可以在其官网进行下载,网址:https://www.freertos.org/a00104.html

这个下载的软件包,包含了源码与DemoGD32L233CCortex-M32内核的,在Demo中只有一个具有参考价值,在Demo/CORTEX_MPU_M23_Nuvoton_NuMaker_PFM_M2351_IAR_GCC下,但是本文只是讲解如何将freeRTOS移植到CM32,这个Demo中有MPUtrust zone,本次移植都将不考虑,但是FreeRTOSconfig.h文件为了方便仍然采用了该Demo下的配置文件作为参考。

因为网址是在国外,下载速度实在有点感人,可以只下载内核源码(不含Demo),在github上,网址:https://github.com/FreeRTOS/FreeRTOS-Kernel/releases/tag/V10.4.6

 

二、添加源码到工程目录

在上一篇帖子中,讲解了如何创建一个全新的工程,本文将会在上一篇创建的工程的基础上添加FreeRTOS功能,观看上一篇帖子请移步:http://bbs.eeworld.com.cn/thread-1192155-1-1.html

1.将源码包改名之后放在工程目录下:

1.png

2.删除不用的文件,留下需要的文件:

  • 这里还需要重点说一下的是,Cortex-M23使用的是ARMv8-M架构,其中有TrustZone,用于安全代码存放,本文将不使用TrustZone
  • 我们需要使用的FreeRTOS源码除了公共源码之外,还有针对每种内核的核心代码,Cortex-M23有两个地方都有这部分代码,选择其中一个保留就行。
  • 第一个地方在:FreeRTOS-Kernel-10.4.6\portable\ARMv8M下,其中secure文件夹下保存的是带有trustZonefreeRTOS源码,non_secure文件夹下保存的是不带trustZone的代码。
  • 第二个地方在FreeRTOS-Kernel-10.4.6\portable\GCC下,其中ARM_CM23文件夹下是带有trustzonefreeRTOS源码,ARM_CM23_NTZ文件夹下是不带trustZonefreeRTOS源码,本文将使用这个目录下的文件。
  1. 公共文件

如下文件都要保留,包括include文件夹机里面的所有文件

2.png

  1. 内核文件

需要保留这个文件夹下的所有文件

3.png

  1. 堆管理文件以及Common文件

还需要保留MemMang下的内存管理文件,一般使用的是heap_4.c这个文件,保留改文件即可,还有Common文件夹内容也需要保留。

21.png

除此之外的所有文件都可以删除

    D.新建文件夹config

新建一个config文件夹在FreeRTOS文件夹下,里面只存在配置文件,也就是FreeRTOSConfig.h,这个文件里面的内容可以参考其他的freeRTOS的示例,本文参考的是Demo/CORTEX_MPU_M23_Nuvoton_NuMaker_PFM_M2351_IAR_GCC(上文有提及)。

到了这一步文件相关的工作就准备就绪了。

 

三、添加FreeRTOS文件进工程

1.新建Group

增加FreeRTOS组,将所有的FreeRTOS相关的*.c*.h文件添加到这个组下面,为什么要添加.h文件呢?为了后期方便查看。

4.png

2.添加头文件

include, non_secure以及config文件夹添加进头文件目录

5.png

到了这一步,文件添加进工程的步骤算是完成了,接下来就是编译,改错。

 

四、编译工程,修改错误

系统移植需要先确保编译没有问题,先编译一下,发现存在如下错误。

6.png

意思是这些文件重定义了,这是和freeRTOS系统运行相关的文件,进行不同任务的上下文切换的。之前的freeRTOS版本名字和这些是不一样的,需要我们自己到启动文件.s中去修改,现在新版本的freeRTOS将名字写成了一样,方便我们移植了,我们只需要把工程中原来的这些函数屏蔽掉就行了。

8.png 7.png

如上,再次编译可能会出现一些函数找不到的问题,如下。

93.png

main.c中添加改函数的处理即可,如下:

/* Stack overflow hook. */
void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
{
/* Force an assert. */
configASSERT( pcTaskName == 0 );
}

还有些需要在FreeRTOSconfig.h文件中禁掉相关功能即可,见下一步。

 

五、修改配置文件

配置文件需要修改一下时钟频率,以及添加gd32的头文件到FreeRTOSconfig.h文件中,同时禁掉trustZone功能以及MPU功能。

90.png

修改任务周期为1000Hz,也就是1ms的心跳节拍,使用vTaskDelay函数时,参数为1就表示1ms

91.png

  1. 添加任务

上一步完成之后我们的移植工作就完成了大半了,接下来就是创建任务实践一下看看我们到底移植成功没有。

我们添加两个LED的任务,先看下原理图,LED接线如下,修改下gd32l233r_eval.h文件中的宏定义,这个文件中堆LED3LED4端口定义不正确。

9.png 92.png

Main函数中创建两个任务:

  • 任务一LED1 500ms翻转一次
  • 任务二LED2 1s 翻转一次

代码如下:

#include "gd32l23x.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "gd32l233r_eval.h"
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"


#define LED1_TASK_PRIO		3		//任务优先级
#define LED1_STK_SIZE 		50  	//任务堆栈大小
TaskHandle_t LED1Task_Handler;		//任务句柄
void led1_task(void *pvParameters);	//任务函数

#define LED2_TASK_PRIO		3		//任务优先级
#define LED2_STK_SIZE 		50  	//任务堆栈大小
TaskHandle_t LED2Task_Handler;		//任务句柄
void led2_task(void *pvParameters);	//任务函数

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
    /* configure systick */
    systick_config();
    /* initilize the LEDs, USART and key */
    gd_eval_led_init(LED1);
    gd_eval_led_init(LED2);
	
	  gd_eval_led_on(LED1);
	  gd_eval_led_on(LED2);

		//创建led1任务
    xTaskCreate((TaskFunction_t )led1_task,            //任务函数
                (const char*    )"led1_task",          //任务名称
                (uint16_t       )LED1_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )LED1_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&LED1Task_Handler);   //任务句柄  
				//创建led1任务
    xTaskCreate((TaskFunction_t )led2_task,            //任务函数
                (const char*    )"led2_task",          //任务名称
                (uint16_t       )LED2_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )LED2_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&LED2Task_Handler);   //任务句柄  
								
		vTaskStartScheduler();          //开启任务调度
    while(1) 
		{

    }
}

void led1_task(void *pvParameters)
{
	while(1)
	{
		gd_eval_led_toggle(LED1);
		vTaskDelay(500);
	}
}

void led2_task(void *pvParameters)
{
	while(1)
	{
		gd_eval_led_toggle(LED2);
		vTaskDelay(1000);
	}
}

 

LED1 500ms闪烁一次,LED2 1s才闪烁一次,移植成功,接下来就可以用FreeRTOS老做更多的工作了。

演示图片

1642512676690.gif.gif

 

六、源码分享

有需求的小伙伴可以参考:

GD32L233C_Prj_FreeRTOS_220118.zip (2.08 MB, 下载次数: 13)


回复

1477

帖子

3

资源

版主

移植起来还是很方便快捷

回复

403

帖子

1

资源

一粒金砂(中级)

不错不错


回复

7

帖子

0

资源

一粒金砂(中级)

大佬,可以试下这个工程能进深度睡眠模式吗,我配置了个定时器加上,就进不去了

点评

你看下是不是定时器影响了休眠,把定时器作为了唤醒源,让休眠进不去了,或者是已休眠就被唤醒了,  详情 回复 发表于 2022-2-25 13:44

回复

8

帖子

1

资源

一粒金砂(中级)

好用


回复

180

帖子

0

资源

一粒金砂(中级)

xiaoming668 发表于 2022-2-24 11:19 大佬,可以试下这个工程能进深度睡眠模式吗,我配置了个定时器加上,就进不去了

你看下是不是定时器影响了休眠,把定时器作为了唤醒源,让休眠进不去了,或者是已休眠就被唤醒了,


回复

7

帖子

0

资源

一粒金砂(中级)

hehung 发表于 2022-2-25 13:44 你看下是不是定时器影响了休眠,把定时器作为了唤醒源,让休眠进不去了,或者是已休眠就被唤醒了,

定时器初始化的时候忘了清标志位了,不过我有点疑惑,普通定时器中断不是外部事件,为啥会影响到他休眠呢

点评

  如果你不清楚定时器标志的话,定时器相当于会一直触发,进入休眠之前应该不允许有中断存在,一般在单片机休眠之前都需要将不用的中断都关掉,只留下需要作为唤醒源的中断  详情 回复 发表于 2022-3-7 10:30

回复

180

帖子

0

资源

一粒金砂(中级)

xiaoming668 发表于 2022-3-7 09:46 定时器初始化的时候忘了清标志位了,不过我有点疑惑,普通定时器中断不是外部事件,为啥会影响到他休眠呢 ...

 

如果你不清除定时器标志的话,定时器相当于会一直触发,进入休眠之前应该不允许有中断存在,一般在单片机休眠之前都需要将不用的中断都关掉,只留下需要作为唤醒源的中断


回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

最新文章 更多>>
    关闭
    站长推荐上一条 1/10 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表