STM32L1移植FreeRTOS

目录

1、获取源码

2、添加FreeRTOS源码到目标工程源码

3、Keil工程管理

4、代码配置修改


1、获取源码

使用目前应用最广的一个版本v9.0.0,https://sourceforge.net/projects/freertos/files/FreeRTOS/V9.0.0/ 

选择适当的格式下载,可以直接下载zip压缩文档解压出源文件,也可以下载.exe安装源文件。

2、添加FreeRTOS源码到目标工程源码

移植主要用到FreeRTOS/Source下面的文件:

include文件夹里面主要是内核相关的头文件,portable里面是与编译器或者具体mcu相关的东西,croutine.c、event_groups.c、list.c、queue.c、task.c、timers.c是内核c文件。

Portable文件夹,只留keil、MemMang、RVDS目录,删掉其余的文件:

其中MemMang是内存管理相关的,Keil文件夹和RVDS文件夹是与IDE相关的,在这里使用Keil和RVDS都用RVDS下面的文件

添加FreeRTOSConfig.h配置文件到include目录中,FreeRTOSConfig.h这个文件可以从源码的demo中复制一个,是配置FreeRTOS功能相关的头文件。

3、Keil工程管理

Keil工程管理界面添加C文件:

添加头文件

4、代码配置修改

4.1、调试配置

#define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int)
#define configASSERT(x) if((x)==0) vAssertCalled(__FILE__,__LINE__)

要配置断言,一般都是配置为串口打印,如果出现问题,这个会打印freertos相关报错信息。

4.2、系统中断配置

/* Use the system definition, if there is one */
#ifdef __NVIC_PRIO_BITS
	#define configPRIO_BITS       __NVIC_PRIO_BITS
#else
	#define configPRIO_BITS       4        /* 15 priority levels */
#endif

用4bit来表示中断优先级,也就是可以表示16个优先级,既0-15。mcu相应的中断分组设置为组4,组4只有主优先级没有次优先级。

HAL_NVIC_SetPriorityGrouping( NVIC_PRIORITYGROUP_4 );

4.3、FreeRTOS能管理的中断设置

上面已经提到只有16个优先级,最低优先级就是15,这里把FreeRTOS能管理的中断设置为5,既就是整个系统中,中断优先级小于5的FreeRTOS不能管理。

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY		     15 //中断最低优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	     5  
//设置系统的优先级。最低优先级就是15,系统能管理的最高优先级是5,也就是说小于5的优先级FreeRTOS不能管理
#define configKERNEL_INTERRUPT_PRIORITY 	( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

4.4、FreeRTOS时钟配置

FreeRTOS默认使用了滴答定时器systick,且在启动FreeRTOS之后,FreeRTOS会配置systick,因此只需要我们配置系统时钟和时钟节拍:

#define configCPU_CLOCK_HZ			( HAL_RCC_GetHCLKFreq( )  )
#define configTICK_RATE_HZ			( ( TickType_t ) 1000 )

4.5、systick中断服务函数配置

在中断服务函数里面调用FreeRTOS提供的中断处理函数即可

void SysTick_Handler( void )
{
    HAL_IncTick( );
//    HAL_SYSTICK_IRQHandler( );
	
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    {
        xPortSysTickHandler();	
    }
}

4.6、引发异常中断和上下文切换中断

#define xPortPendSVHandler 	        PendSV_Handler
#define vPortSVCHandler 		SVC_Handler

这两个是mcu提供的,主要用于RTOS系统的,也是使用FreeRTOS提供的API,主要用于产生异常和任务切换。

4.7、完整FreeRTOSConfig.h文件

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

#include "debug.h"
/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
 *
 * See http://www.freertos.org/a00110.html.
 *----------------------------------------------------------*/

#define configUSE_PREEMPTION	        1	//1:使用抢占式内核,0:使用协程

#define configCPU_CLOCK_HZ		( HAL_RCC_GetHCLKFreq( )  ) //cpu频率
#define configTICK_RATE_HZ		( ( TickType_t ) 1000 )     //时钟节拍频率,这里设置为1000,周期就是1ms
#define configMAX_PRIORITIES		( 32 )			//可使用的最大优先级
#define configMINIMAL_STACK_SIZE	( ( unsigned short ) 70 )   //空闲任务堆栈大小
				
#define	configSUPPORT_DYNAMIC_ALLOCATION 1	//使能动态内存分配
#define configTOTAL_HEAP_SIZE		( ( size_t ) ( 6 * 1024 ) ) //总的堆大小,用于freertos动态分配

#define configMAX_TASK_NAME_LEN		( 16 )        //任务名称的最大长度
#define configUSE_TRACE_FACILITY        1	      //为1启用可视化跟踪调试
#define configUSE_16_BIT_TICKS	        0	      //系统节拍计数器变量数据类型,
#define configIDLE_SHOULD_YIELD		1	      //为1时空闲任务放弃CPU使用权给其他同优先级的用户任务
#define configUSE_MUTEXES		1	      //为1时使用互斥信号量
#define configQUEUE_REGISTRY_SIZE       5	      //不为0时表示启用队列记录,具体的值是可以记录的队列和信号量最大数目。
                                                                 



/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet		1
#define INCLUDE_uxTaskPriorityGet		1
#define INCLUDE_vTaskDelete			1
#define INCLUDE_vTaskCleanUpResources	        0
#define INCLUDE_vTaskSuspend			1
#define INCLUDE_vTaskDelayUntil			1
#define INCLUDE_vTaskDelay			1
#define INCLUDE_xTaskGetSchedulerState          1                       


#define configUSE_IDLE_HOOK			0   //1:使用空闲钩子,需要自行编写钩子函数,0:不使用
#define configUSE_TICK_HOOK			0   //1:使用时间片钩子,0:不使用

/* Use the system definition, if there is one */
#ifdef __NVIC_PRIO_BITS
	#define configPRIO_BITS       __NVIC_PRIO_BITS
#else
	#define configPRIO_BITS       4        /* 15 priority levels */
#endif

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY	       15 //中断最低优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5  //设置系统的优先级。最低优先级就是15,系统能管理的最高优先级是5,也就是说小于5的优先级FreeRTOS不能管理
#define configKERNEL_INTERRUPT_PRIORITY 	            ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	        ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )


//断言
#define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int)
#define configASSERT(x) if((x)==0) vAssertCalled(__FILE__,__LINE__)
	
#define xPortPendSVHandler 	PendSV_Handler
#define vPortSVCHandler 	SVC_Handler

#endif /* FREERTOS_CONFIG_H */

4.8、测试程序

#include <string.h>
#include <math.h>
#include "board.h"

#include "FreeRTOS.h"
#include "task.h"


#define TEST_TASK0_PRIO		        2    //任务优先级
#define TEST_TASK0_STK_SIZE 		50   //任务堆栈大小
TaskHandle_t TestTask0Handler;               //任务句柄
void TestTask0Func(void *pvParameters);      //任务函数


#define TEST_TASK1_PRIO			3    //任务优先级
#define TEST_TASK1_STK_SIZE 		80   //任务堆栈大小
TaskHandle_t TestTask1Handler;               //任务句柄
void TestTask1Func(void *pvParameters);      //任务函数


void OtherTest(void )
{
    BaseType_t ret;
	
    BoardInitMcu();
    BoardInitPeriph();
	
    //创建Test0任务
    ret=xTaskCreate((TaskFunction_t )TestTask0Func,     	
		    (const char*    )"testtask0",   	
		    (uint16_t       )TEST_TASK0_STK_SIZE, 
		    (void*          )NULL,				
		    (UBaseType_t    )TEST_TASK0_PRIO,	
		    (TaskHandle_t*  )&TestTask0Handler);   
				
    //创建Test1任务
    ret=xTaskCreate((TaskFunction_t )TestTask1Func,     
		    (const char*    )"testtask1",   
		    (uint16_t       )TEST_TASK1_STK_SIZE, 
		    (void*          )NULL,
		    (UBaseType_t    )TEST_TASK1_PRIO,
		    (TaskHandle_t*  )&TestTask1Handler); 

    vTaskStartScheduler(); 
}


//Test0任务函数 
void TestTask0Func(void *pvParameters)
{
    while(1)
    {
        printf("task0\r\n");
        vTaskDelay(1500);
    }
}   

//Test1任务函数
void TestTask1Func(void *pvParameters)
{
    while(1)
    {
        vTaskDelay(2000);
	printf("task1\r\n");
    }
}

4.9、测试结果

测试结果与设定一致。

注意:mcu中断优先级和任务优先级没有关系,stm32中断优先级的数值越小,优先级越高;FreeRTOS的任务优先级是,任务优先级数值越小,任务优先级越低。

以上,就简单的完成了FreeRTOS在STM32L1上面的移植运行。多任务是FreeRTOS最主要的功能,其他信号量、队列、别表项等功能根据项目实际需要选配。

发布了35 篇原创文章 · 获赞 25 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/freemote/article/details/104266601