442|2

121

帖子

0

资源

一粒金砂(中级)

【GD32450I-EVAL】+ 05FreeRTOS移植与任务创建 [复制链接]

本帖最后由 DDZZ669 于 2020-9-26 15:34 编辑

        FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。

freertos.png

 

1 FreeRTOS基本结构

        FreeRTOS系统简单小巧、文件数量少、通常情况下内核占用4~9k字节空间,代码主要由C编写,可移植性高,已实现在30多种架构的芯片上移植。

        由于FreeRTOS的最新代码目前从官网下载的速度特别慢,这里先以之前的FreeRTOS v9.0.0版本为例进行实验。FreeRTOS代码包含FreeRTOS和FreeRTOS-Plus文件夹,后者是一些补充文件,一般用不到,可以先忽略。

        在FreeRTOS文件夹中主要关注source文件夹,这里是FreeRTOS的全部源码,包括6个c文件和include文件夹下的多个h文件。另外,在portable文件夹下,是针对不同硬件平台的单独区分使用的代码,目前考虑使用Keil开发STM32F407,所以portable文件夹只需使用RVDS的ARM_CM4F以及MemMang。

20200926135929.png

        关于各个c文件的主要用途:

  • port.c : 针对不同硬件平台的接口

  • heap_4.c : 内存管理相关

  • croutine.c : 协程相关

  • event_groups.c : 事件标志组相关

  • list.c : 列表,FreeRTOS的一种基础数据结构

  • queue.c : 队列相关

  • tasks.c : 任务创建、挂起、恢复、调度相关

  • timers.c : 软件定时器相关

        在Demo文件夹下还需要用到一个FreeRTOSConfig.h,该文件中通过各种宏定义的方式来配置FreeRTOS需要使用哪些资源。

freertos2.png

 

2 FreeRTOS移植

2.1 准备一个基础工程

        这里以光盘资料里的LED工程为基础,移植FreeRTOS系统。先来看一下LED基础工程的结构:

3.png

2.2 添加FreeRTOS库文件

        把FreeRTOS源码中的Source文件夹复制出来并重命名为FreeRTOS(便于与GD32F4库文件区分),用于添加到LED基础工程中,Source文件夹中的portable子文件夹中,只保留RVDS与MemMang,其余的用不到可以删除。

        另外还需要一个名为“FreeRTOSConfig.h”的配置文件,因为FreeRTOSv9.0中还没有GD32F450的Demo,可以先使用Demo文件夹下的CORTEX_M4F_STM32F407ZG-SK文件夹里的这个文件,因为它们同属M4内核。然后将该文件放到include子文件夹中。

        将FreeRTOS源码中的c文件添加到LED基础工程中:

20200926142633.png

 

        再添加头文件的路径:

20200926143018.png

2.3 编译与配置

        添加FreeRTOS的C文件并添加H文件搜索路径后,编译一下工程,提示3个错误:

20200926143217.png

        

        port.c和gd32f4xx_it.c中的函数重复定义了,因为port.c的FreeRTOS中的文件,那我们不修改它,而是把gd32f4xx_it.c中的同名函数先注释掉,并再次编译,就不报错了:

20200926143557.png

 

3 任务创建示例

        使用FreeRTOS开发,与裸机开发的最大区别就是,裸机程序是一条主线从上到下执行,再配合中断功能来实现紧急时间的处理。而使用FreeRTOS等实时操作系统,可以将所以实现的各个功能单独设计为一个个子任务,每个子任务都是一个死循环,通过任务的调度的方式来实现各个子任务的运行与信息交流。

        以下是两个LED灯的测试程序,LED1子任务的功能是每隔500ms进行亮灭转换,LED2子任务的功能是亮200ms,灭800ms循环。这两个子任务通过系统调度的方式,各自运行,互不影响。

        另外,FreeRTOS中首先需要一个起始任务,用来创建其它任务,创建完其它任务后,该任务将自己删除。

#include "gd32f4xx.h"
#include "gd32f450i_eval.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 TASK1_TASK_PRIO		2
#define TASK1_STK_SIZE 		128  
TaskHandle_t Task1Task_Handler;
void task1_task(void *pvParameters);

#define TASK2_TASK_PRIO		3	
#define TASK2_STK_SIZE 		128  
TaskHandle_t Task2Task_Handler;
void task2_task(void *pvParameters);

int main(void)
{ 
	//设置系统中断优先级分组4(FreeRTOS中的默认方式!)
	nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
	
    gd_eval_led_init(LED1);
    gd_eval_led_init(LED2);
    
	
	//创建开始任务
	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();           //进入临界区
	
    //创建TASK1任务
    xTaskCreate((TaskFunction_t )task1_task,             
                (const char*    )"task1_task",           
                (uint16_t       )TASK1_STK_SIZE,        
                (void*          )NULL,                  
                (UBaseType_t    )TASK1_TASK_PRIO,        
                (TaskHandle_t*  )&Task1Task_Handler);   
    //创建TASK2任务
    xTaskCreate((TaskFunction_t )task2_task,     
                (const char*    )"task2_task",   
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_TASK_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler); 
				
    vTaskDelete(StartTask_Handler); //删除开始任务
				
    taskEXIT_CRITICAL();            //退出临界区
}

//task1任务函数
void task1_task(void *pvParameters)
{
	while(1)
	{
		gd_eval_led_toggle(LED1);
        vTaskDelay(500); //延时500ms
	}
}

//task2任务函数
void task2_task(void *pvParameters)
{
	while(1)
	{
        gd_eval_led_on(LED2);;
        vTaskDelay(200); //延时200ms
		gd_eval_led_off(LED2);;
        vTaskDelay(800); //延时800ms
	}
}

4 测试效果

1.gif

此帖出自GD32 MCU论坛

回复

1万

帖子

133

资源

管理员

个人签名

玩板看这里:

http://bbs.eeworld.com.cn/elecplay.html

EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!


回复

1万

帖子

133

资源

管理员

谢谢楼主分享,报告很精彩!期待你后面的测评


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

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

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

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

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

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