当前位置: 首页 > news >正文

详细GD32F103的FreeRTOS移植含常见错误

目录

1、FreeRTO官方源码获取

2、新建相关文件夹

3、复制相关文件

4、文件加入到工程

5、DEBUG工程适配


1、FreeRTO官方源码获取

FreeRTOS源码的官方下载地址: FreeRTOS官方下载链接。

选择你需要的版本:我这选择的是最新版本即202411。

这里有三个文件,其中我们可以下载ZIP也可以下载EXE的。

下载一个即可,运行EXE或者解压ZIP均会获得源码

在官方源码文件夹中,主要包含两个目录:FreeRTOS 和 FreeRTOS-Plus。其中,FreeRTOS 文件夹是移植过程中需要重点关注的部分,它包含了 FreeRTOS 内核的源码以及各种 Demo 例程。而 FreeRTOS-Plus 文件夹则包含了一些第三方扩展组件,通常在移植过程中不会使用。

打开 FreeRTOS 文件夹后,可以看到其中主要包含以下三个子文件夹。以下是主要文件夹和文件的文件树结构总结:

2、新建相关文件夹

打开GD32F103的例程,并在其新建FreeRTOS文件夹。

打开FreeRTOSv202411.00\FreeRTOS\Source文件夹,

3、复制相关文件

(1)将include文件夹复制到GD32F103freertos\FreeRTOS

(2)在GD32F103freertos\FreeRTOS下新建portable文件夹,并将FreeRTOSv202411.00\FreeRTOS\Source\portable下的Keil、MemMang、RVDS复制到GD32F103freertos\FreeRTOS\portable

(3)将FreeRTOSv202411.00\FreeRTOS\Source下的使用.c文件复制到GD32F103freertos\FreeRTOS。注意FreeRTOS版本不同所对应的.c文件数量不同。

将FreeRTOSv202411.00\FreeRTOS\Demo\CORTEX_STM32F103_Keil下的FreeRTOSConfig.h复制到GD32F103freertos\User下

4、文件加入到工程

打开工程,点击文件管理

新建FreeROTS_CORE,并将GD32F103freertos\FreeRTOS下的使用.c添加到其中

再新建FreeROTS_PORTABLE,选择GD32F103freertos\FreeRTOS\portable\MemMang所需的内存管理方案

所对应的芯片型号GD32F103freertos\FreeRTOS\portable\RVDS\ARM_CM3添加到其中。

添加头文件地址

5、DEBUG工程适配

编写测试代码main.c文件

 
#include "gd32f10x.h"
#include "gd32f10x_libopt.h"
#include "systick.h"
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "croutine.h"
#include "portmacro.h"
 
//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED0_TASK_PRIO		2
//任务堆栈大小	
#define LED0_STK_SIZE 		128
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);

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

int main(void)
{
		rcu_apb2_clock_config(RCU_APB2_CKAHB_DIV1);//设置主频108M(#define __SYSTEM_CLOCK_108M_PLL_HXTAL         (uint32_t)(108000000)),8M外部晶振  (#define HXTAL_VALUE    ((uint32_t)8000000))
		systick_config();//配置1ms SysTick
		rcu_periph_clock_enable(RCU_AF);//AF时钟使能 

		gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE);//下载口NJTRST引脚当做普通I/O口
		rcu_periph_clock_enable(RCU_GPIOB);//GPIOB时钟打开
		gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4);//PB4配置成输出
	
			rcu_periph_clock_enable(RCU_GPIOB);//GPIOB时钟打开
		gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5);//PB4配置成输出
	
	//创建开始任务
    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();           //进入临界区
    //创建LED0任务
    xTaskCreate((TaskFunction_t )led0_task,     	
                (const char*    )"led0_task",   	
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED0_TASK_PRIO,	
                (TaskHandle_t*  )&LED0Task_Handler);   
    //创建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);         
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//LED0任务函数 
void led0_task(void *pvParameters)
{
    while(1)
    {
		 
        gpio_bit_set(GPIOB, GPIO_PIN_4); 
		vTaskDelay(500);          
        gpio_bit_reset(GPIOB, GPIO_PIN_4);
        vTaskDelay(500);
    }
}   

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
			gpio_bit_set(GPIOB, GPIO_PIN_5);
			vTaskDelay(800);
			gpio_bit_reset(GPIOB, GPIO_PIN_5); 
			vTaskDelay(800);
    }
}

打开"FreeRTOSConfig.h"进行如下更改:

#define configCPU_CLOCK_HZ			SystemCoreClock
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler

进行编译后::

报错: No space in execution regions with ...

原因:空间不够

解决:打开"FreeRTOSConfig.h"进行如下更改,将栈空间减小

//#define configTOTAL_HEAP_SIZE		( ( size_t ) ( 17 * 1024 ) )
#define configTOTAL_HEAP_SIZE		( ( size_t ) ( 2 * 1024 ) )

报错:Symbol SVC_Handler multiply defined (by port.o and gd32f10x_it.o).
            Symbol PendSV_Handler multiply defined (by port.o and gd32f10x_it.o).

原因:函数被多处定义(需要调用FreeRTOS的函数舍去源码的相关函数)

解决:打开gd32f10x_it.c,注释如下函数

//void SVC_Handler(void)
//{
//}


//void PendSV_Handler(void)
//{
//}

报错:identifier "SystemCoreClock" is undefined

原因:未找到SystemCoreClock定义(这是系统时钟,RTOS需要调用,要指明它在何处)

解决:打开"FreeRTOSConfig.h"添加如下代码

#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
 #include <stdint.h>
 extern uint32_t SystemCoreClock;
#endif

报错:Undefined symbol vApplicationIdleHook (referred from tasks.o).
          Undefined symbol vApplicationTickHook (referred from tasks.o).

         Undefined symbol vApplicationMallocFailedHook (referred from heap_4.o).

         Undefined symbol vApplicationStackOverflowHook (referred from tasks.o).

原因:相关钩子函数为找到

解决:打开"FreeRTOSConfig.h"进行如下更改

#define configUSE_IDLE_HOOK	  	0   //1
#define configUSE_TICK_HOOK		0   //1
#define configUSE_MALLOC_FAILED_HOOK	0 //1
#define configCHECK_FOR_STACK_OVERFLOW	0 //2

当解决上面错误是,出现了无报错无警告,但是调度器开启失败的情况,这是可能是因为滴答定时器相关配置出现了问题。

让我们打开gd32f10x_it.c对SysTick_Handler函数注释,在main.c文件中添加如下代码

//void SysTick_Handler(void)
//{
//    delay_decrement();
//}




#include "FreeRTOS.h"			 
#include "task.h"
extern void xPortSysTickHandler(void);
void SysTick_Handler(void)
{
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
        xPortSysTickHandler();
    }
}

注意此函数是滴答定时器的中断服务函数
FreeRTOS的心跳就是由滴答定时器产生的,根据FreeRTOS的系统时钟节拍设置好滴答定时器的周期,这样就会周期触发滴答定时器中断了。在滴答定时器中断服务函数中调用FreeRTOS的API函数。

报错:.Undefined symbol xTaskGetSchedulerState

原因:未显式启用 xTaskGetSchedulerState() 函数

解决:打开"FreeRTOSConfig.h"添加如下代码

#define INCLUDE_xTaskGetSchedulerState 1

//或者加入如下代码:
/*
#define configUSE_TIMERS				1
#define configTIMER_TASK_PRIORITY		( 2 )
#define configTIMER_QUEUE_LENGTH		10
#define configTIMER_TASK_STACK_DEPTH	( configMINIMAL_STACK_SIZE * 2 )
*/

最后,编译、烧入、运行,成功移植!

相关文章:

  • 基于火山引擎的DeepSeek-V3 api实现简单的数据查询功能
  • Python爬虫实战:爬取财金网实时财经信息
  • 2、数据库的基础学习(中):分组查询、连接查询 有小例子
  • CV毕业宝典[02_目标检测概述]
  • 山东省网络安全技能大赛历年真题 山东网络安全创意大赛
  • python从入门到精通(二十三):文件操作和目录管理难度分级练习题
  • 浅谈 DeepSeek 对 DBA 的影响
  • Python 性能优化:从入门到精通的实用指南
  • TypeError: xxx is not a function
  • 从零到多页复用:我的WPF MVVM国际化实践
  • 【OMCI实践】ONT上线过程的omci消息(九)
  • DeepGEMM 论文和实现浅析(二)
  • Manus:AI 新纪元的破局者,是神话还是现实?
  • 数据库 网页 和 deepseek 并在一起,直接选择问题,
  • nginx服务器实现上传文件功能_使用nginx-upload-module模块
  • STM32点亮LED灯
  • 利用 HAI 平台进行 DeepSeek 模型训练的详细指南
  • 梯度本质论:从黎曼流形到神经网络的拓扑寻优
  • 最近很火的通用人工智能Manus复现链接
  • 在NVIDIA RTX 4090显卡上部署阿里千问QwQ-32B-AWQ模型教程
  • 做网站开发的有外快嘛/磁力猫引擎入口
  • 沈阳网站建设技术公司/防疫管控优化措施
  • 网站建设嘉兴公司电话/青岛seo建站
  • 阿里巴巴怎么做企业网站/市场推广方案模板
  • 怎么做自己的一个网站/如何弄一个自己的网站
  • 住房和城乡建设部网站登录/优秀企业网站欣赏