当前位置 博文首页 > freemote的博客:STM32L1移植FreeRTOS

    freemote的博客:STM32L1移植FreeRTOS

    作者:[db:作者] 时间:2021-07-18 19:10

    目录

    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最主要的功能,其他信号量、队列、别表项等功能根据项目实际需要选配。

    cs
    下一篇:没有了