FreeRTOS学习笔记——移植FreeRTOS至核心板

第一步:官网下载FreeRTOS v10.2.1,解压后包含的文件如下图所示
FreeRTOS学习笔记——移植FreeRTOS至核心板_第1张图片
第二步:提取FreeRTOS文件。将…\FreeRTOSv10.2.1\FreeRTOSv10.2.1_191129\FreeRTOS\Source文件夹复制到裸机工程模板的FreeRTOS v10.2.1文件夹,将portable文件夹中除keil、MemMang、RVDS文件夹外的其余文件夹删除,如下图。
并将…\FreeRTOSv10.2.1\FreeRTOSv10.2.1_191129\FreeRTOS\Demo\CORTEX_STM32F103_Keil文件夹中的FreeRTOSConfig.h文件拷贝至工程User文件夹。
FreeRTOS学习笔记——移植FreeRTOS至核心板_第2张图片FreeRTOS学习笔记——移植FreeRTOS至核心板_第3张图片
第三步:在裸机工程中添加FreeRTOS文件,如下图所示(需配置include中头文件的路径)。选择…\portable\MemMang文件夹中的heap_4.c以及…\portable\RVDS\ARM_CM3文件夹中的port.c和portmacro.h文件添加至port目录
FreeRTOS学习笔记——移植FreeRTOS至核心板_第4张图片
第四步:修改启动文件startup_stm32f10x_hd.s。由于FreeRTOS在port.c中定义了
116:void xPortPendSVHandler( void );
117:void xPortSysTickHandler( void );
118:void vPortSVCHandler( void );
三个中断供内核使用,所以需要在启动文件中重新定义中断的入口函数,以防止调用stm32f10x_it.c中的中断,汇编代码修改如下
第五步:编写main函数,创建点亮LED的任务,代码如下

/*
******************************************************************************
*     包含的头文件
******************************************************************************
*/
//FreeRTOS头文件
#include "FreeRTOS.h"
#include "task.h"
//开发板硬件bsp头文件
#include "./led/bsp_led.h"
#include "./uart/bsp_usart.h"

/***************************** 任务句柄 **************************************/
/*
 * 任务句柄是一个指针,用于指向一个任务。当任务创建好之后,它就具有一个任务句柄,
 * 以后我们想操作这个任务都需要用到这个任务句柄,如果是任务操作自身,那么这个句柄可以为NULL
*/
//创建任务句柄
static TaskHandle_t AppTaskCreate_Handle;
//LED1任务句柄
static TaskHandle_t LED1_Task_Handle = NULL;
//LED2任务句柄
static TaskHandle_t LED2_Task_Handle = NULL;

/*************************** 内核对象句柄 ************************************/
/*
 * 信号量、消息队列、事件标志组、软件定时器都属于内核的对象,要想使用这些内核对象,
 * 必须先创建,创建成功之后会返回相应的句柄。这实际上就是一个指针,后续我们就可以
 * 通过句柄操作这些内核对象。
 *
 *
 * 内核对象可以理解为一种全局的数据结构,通过这些数据结构可以实现任务间的通信、任
 * 务间的事件同步等功能。这些功能的实现是通过调用内核对象的函数来完成的。
 *
 *
*/

/*
******************************************************************************
*     函数声明
******************************************************************************
*/
static void AppTaskCreate(void);  //用于创建任务

static void LED1_Task(void* pvParameters);  //LED1_Task任务实现
static void LED2_Task(void* pvParameters);  //LED2_Task任务实现

static void BSP_Init(void);  //用于初始化板载相关资源

/*
******************************************************************************
*     主函数
******************************************************************************
*/
int main(void)
{
	//定义一个创建信息返回值,默认为pdPASS
	BaseType_t xReturn = pdPASS;
	
	//开发板硬件初始化
	BSP_Init();
	printf("动态创建任务\r\n");

	//创建AppTaskCreate任务
	xReturn = xTaskCreate((TaskFunction_t)AppTaskCreate,
												(const char*   )"AppTaskCreate",//任务名称
												(uint16_t      )512,						//任务栈大小
												(void*         )NULL,					  //传递给任务函数的参数
												(UBaseType_t   )1,						  //任务优先级
												(TaskHandle_t* )&AppTaskCreate_Handle);//任务控制块指针
	
	printf("创建AppTaskCreate任务成功\r\n");

	//启动任务调度											
  if (pdPASS == xReturn)	
		vTaskStartScheduler();					//启动任务,开启调度
	else
		return -1;
	
	while(1);													//正常情况下不会执行到这里
}

/*
******************************************************************************
*     AppTaskCreate函数
******************************************************************************
*/
static void AppTaskCreate(void)
{
	//定义一个创建信息返回值,默认为pdPASS
	BaseType_t xReturn = pdPASS;
	
	taskENTER_CRITICAL();//进入临界区
	
	//创建LED1_Task任务
	xReturn = xTaskCreate((TaskFunction_t)LED1_Task,
												(const char*   )"LED1_Task",//任务名称
												(uint16_t      )512,						 //任务栈大小
												(void*         )NULL,					 //传递给任务函数的参数
												(UBaseType_t   )2,							 //任务优先级
												(TaskHandle_t* )&LED1_Task_Handle); //任务控制块
	
	if (pdPASS == xReturn)	
		printf("LED1_Task任务创建成功!\n");
	else
		printf("LED1_Task任务创建失败!\n");
	
	//创建LED2_Task任务
	xReturn = xTaskCreate((TaskFunction_t)LED2_Task,
												(const char*   )"LED2_Task",//任务名称
												(uint16_t      )512,						 //任务栈大小
												(void*         )NULL,					 //传递给任务函数的参数
												(UBaseType_t   )3,							 //任务优先级
												(TaskHandle_t* )&LED2_Task_Handle); //任务控制块
	
	if (pdPASS == xReturn)	
		printf("LED2_Task任务创建成功!\n");
	else
		printf("LED2_Task任务创建失败!\n");
	
	vTaskDelete(AppTaskCreate_Handle);	//删除AppTaskCreate任务
	
	taskEXIT_CRITICAL();	//退出临界区
}

/*
******************************************************************************
*     LED1_Task函数
******************************************************************************
*/
static void LED1_Task(void* parameter)
{
	while(1)
	{
		LED1_ON();
		vTaskDelay(500);//延时500个tick
		printf("led1_task running,LED1_ON\r\n"); 
		
	  LED1_OFF();
		vTaskDelay(500);//延时500个tick
		printf("led1_task running,LED1_OFF\r\n"); 
	}
}

/*
******************************************************************************
*     LED2_Task函数
******************************************************************************
*/
static void LED2_Task(void* parameter)
{
	while(1)
	{
		LED2_ON();
		vTaskDelay(1000);//延时500个tick
		printf("led2_task running,LED1_ON\r\n"); 
		
	  LED2_OFF();
		vTaskDelay(1000);//延时500个tick
		printf("led2_task running,LED1_OFF\r\n"); 
	}
}

/*
******************************************************************************
*     BSP_Init函数
******************************************************************************
*/
static void BSP_Init(void)
{
	/*
	 * STM32中断优先级分组为4,即4位都用来表示抢占优先级,范围为0~15,
	 * 优先级只需要分组一次即可,以后如果有其他任务需要用到中断,
	 * 都统一用这个优先级分组,千万不要再分组
	 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	
	//LED初始化
	LED_Init();
	
	//测试硬件是否正常工作
	//LED1_ON();
	
	//串口初始化
	USART_Config();
}

第六步:编译、下载。编译报“Error: L6218E: Undefined symbol xTaskGetCurrentTaskHandle (referred from stream_buffer.o).”错误,需将FreeRTOS.h中的INCLUDE_xTaskGetCurrentTaskHandle定义为1,如下图
FreeRTOS.h中修改相关的宏定义
更改后可以正常运行。

你可能感兴趣的:(FreeRTOS笔记,stm32,freertos)