GD32移植FreeRTOS

GD32F407移植FreeRTOS测试

一、基础代码与环境

文件路径:
标准库链接位置: 标准库
FreeRTOS链接位置: FreeRTOS
GD32F407资料链接: GD32F407资料

1、找到GD32的官方标准库下载

在这里插入图片描述

2、找到FreeRTOS 的官方示例代码下载

在这里插入图片描述

3、使用找到一个基础的点灯代码

点灯代码一般买开发板时问客服要这块开发板资料里面就有。
如果没有在这里下载 F407的代码资料:
链接: GD32F407资料
在这里插入图片描述
点灯代码:
在这里插入图片描述

二、移植

1、复制示例并改名

在这里插入图片描述

2、修改替换文件夹内容

  • 把标准库的头文件复制替换原有的头文件夹CMSIS在这里插入图片描述
  • 替换的文件夹
    在这里插入图片描述

3、创建文件夹并把freertos的文件粘贴进去

(1)创建一个名为FreeRTOS的文件夹到移植的主目录

在这里插入图片描述

(2)移植FreeRTOS文件
  • 把FreeRTOS的文件里的Source里面的文件复制到刚刚创建的那个FreeRTOS里面(叉掉的那几个可以不用复制,只要.c文件和两个文件夹就行)在这里插入图片描述
(3)删除portable文件里多余的文件夹只留下 (Keil 、MemMang、RVDS )三个文件夹

在这里插入图片描述

  • 到这里所有需要的文件已经放到主目录下面了

4、在kail里面先把需要的头文件的路径给加入进去(主要是下面三个路径)

在这里插入图片描述

5、创建目录组文件夹 FreeRTOSCore 和 FreeRTOSPort (分别为核心文件和接口文件的文件夹)

  • 7个核心文件和 2个接口文件
  • 接口文件路径1:FreeRTOS\portable\RVDS\ARM_CM4F
  • 接口文件路径2:FreeRTOS\portable\MemMang
  • 接口文件路径3:FreeRTOS
    文件在这几个路径里面找:
    在这里插入图片描述

6、 把 CMSIS 和 Startup 的文件夹里面的文件删掉,在去下面文件路径找到该文件导入进去:

  • 文件路径1: CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c
  • 文件路径2: CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f407_427.s
    在这里插入图片描述

7、 把 FreeRTOSConfig 放入 FreeRTOS\include 文件夹里面

  • 一般 FreeRTOSConfig 文件是需要根据自己的情况来写的,但是如果没有的话到我给的那个资料里面找:
  • 位置:GD32F407VET6开发板资料和例程\例程代码\13.FREERTOS实验\FreeRTOS\include
  • 复制到 主目录下的 FreeRTOS\include 里面:
    在这里插入图片描述

8、注释掉GD32的 SVC_Handler 和 PendSV_Handler

  • 这两个函数在 FreeRTOS里面已经有单独的实现了,所有不注释掉他们就会与FreeRTOS的文件冲突。
  • 函数所在的文件:gd32f4xx_it.c
    在这里插入图片描述

9、 重写 SysTick_Handler()

  • 注释掉 gd32f4xx_it.c 里面的 SysTick_Handler
    在这里插入图片描述

  • 在 systick.c 里面重写 SysTick_Handler

//systick.c

//需要先导入头文件
#include "FreeRTOS.h"
#include "task.h"

extern void xPortSysTickHandler(void);

//滴答定时器的回调函数,给freertos提供时基
void SysTick_Handler(void){
	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
	{
		xPortSysTickHandler();
	}
}

10、最后进行编译

  • 编译无报错就移植成功了
    在这里插入图片描述

三、测试代码的运行

  • 下面是个mian函数里面调用 freertos(只要复制粘贴到mian就好了)
  • 里面是一个点灯的实列
#include "gd32f4xx.h"
#include "gd32f4xx_libopt.h"
#include "systick.h"
#include "FreeRTOS.h"
#include "task.h"

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

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

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

int main(void)
{


    systick_config();//配置系统主频168M,外部8M晶振,配置在#define __SYSTEM_CLOCK_168M_PLL_8M_HXTAL        (uint32_t)(168000000)
    rcu_periph_clock_enable(RCU_GPIOB);//使能GPIOB时钟
    gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_4);//PB4配置成输出
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4);//PB4配置成推挽输出,50M速度
    //创建开始任务
		xTaskCreate((TaskFunction_t )start_task,            //任务函数
								(const char*    )"start_task",          //任务名称
								(uint16_t       )START_STK_SIZE,        //任务堆栈大小
								(void*          )NULL,                  //传递给任务函数的参数
								(UBaseType_t    )START_TASK_PRIO,       //任务优先级
								(TaskHandle_t*  )&StartTask_Handler);   //任务句柄   
								
		vTaskStartScheduler();          //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建LED1任务
    xTaskCreate((TaskFunction_t )LED_Thread1,     	
                (const char*    )"led1_task",   	
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED1_TASK_PRIO,	
                (TaskHandle_t*  )&LED1Task_Handler);   


	    xTaskCreate((TaskFunction_t )LED_Thread2,     	
                (const char*    )"led2_task",   	
                (uint16_t       )LED2_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED2_TASK_PRIO,	
                (TaskHandle_t*  )&LED2Task_Handler);   
													
							
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区

}

//LED1任务函数 
void LED_Thread1(void *pvParameters)
{
    while(1)
    {
      gpio_bit_set(GPIOB, GPIO_PIN_4);//PB4输出高电平
      vTaskDelay(100);
    }
} 

//LED2任务函数 
void LED_Thread2(void *pvParameters)
{
    while(1)
    {
			gpio_bit_reset(GPIOB, GPIO_PIN_4);//PB4输出低电平
      vTaskDelay(250);
    }
}  

最后编译烧录到开发板就好了。成功以后开发板就会有一颗灯一闪一闪的。
注意:开发板烧录完后记得按复位键,不然不会运行程序。

四、总结

这是一次GD32移植Freertos的示例,其他的GD32开发板也可以参照这个来移植。
主要大体移植步骤:

(1) 把需要的文件和文件夹放入主目录
(2) 在keil里面导入头文件路径
(3) 导入需要的freertos文件(7个核心文件2个接口文件)
(4) 提供时基 修改滴答定时器的回调函数 SysTick_Handler (一般为 1ms 调用 1次),不一定要使用滴答定时器,只需要能提供1ms调用1次的定时器就行
(5) 写测试的代码,调用 FreeRTOS的任务

下面为滴答定时器的初始化:

//在这里面 1000 表示 1s 调用 1千次 就是1ms 1次
void systick_config(void)
{
    /* setup systick timer for 1000Hz interrupts */
    if (SysTick_Config(SystemCoreClock / 1000U)){
        /* capture error */
        while (1){
        }
    }
    /* configure the systick handler priority */
    NVIC_SetPriority(SysTick_IRQn, 0x00U);
}

//每1ms调用1次
void SysTick_Handler(void){
	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
	{
		xPortSysTickHandler();
	}
}

这次移植主要是熟悉下 FreeRTOS的移植,写个博客方便自己以后翻阅,不然以后忘记了,不好查。如有不足请在参考其他的移植。

  • 26
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值