STM32L1移植FreeRTOS
目录
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最主要的功能,其他信号量、队列、别表项等功能根据项目实际需要选配。
上一篇: 帝都上班族的真实写照
下一篇: Tomcat相关