欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32L1移植FreeRTOS

程序员文章站 2022-06-09 10:49:23
...

目录

1、获取源码

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

3、Keil工程管理

4、代码配置修改


1、获取源码

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

STM32L1移植FreeRTOS

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

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

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

STM32L1移植FreeRTOS

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

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

STM32L1移植FreeRTOS

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

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

3、Keil工程管理

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

STM32L1移植FreeRTOS

添加头文件

STM32L1移植FreeRTOS

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、测试结果

STM32L1移植FreeRTOS

测试结果与设定一致。

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

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