freertos 笔记一(HAL 库移植)

什么是freertos?

参考正点原子的教程

  1. 免费实时操作系统
  2. 对某一事件做实时响应,即:任务调度是可以预测的
  3. 用户分配优先级:文件系统比ucos小

移植

freertos v9

  1. FREERTOS/sources 所有文件复制到新建工程下

  2. /porttable 只留下 Keil;MemMang(内存管理);RVDs(针对架构的代码)

  3. 添加到工程
    FREERTOS/CORE:
    在这里插入图片描述

    FREERTOS/PORTABLE:
    ports/ARM_CM4F/port.c
    ports/MemMang/heap_4.c (5中不同的内存管理)
    在这里插入图片描述

  4. FreeRTOSConfig.h(demo 目录下)添加到库中
    配置文件
    并配置 SystemCoreClock 支持

#if __ICCARM__||__CC_ARM||__GNUC__
	#include <stdint.h>
	extern uint32_t SystemCoreClock;
#endif
  1. 屏蔽stm32f4xxit.c 中
PendSV_Handler()
SysTick_Handler()
SVC_Handler()
  1. 关闭钩子(回调)函数
#define configUSE_IDLE_HOOK				0
#define configUSE_TICK_HOOK				0
#define configUSE_MALLOC_FAILED_HOOK	0
  1. 修改sys.h
    sys和usart
sys
#define SYSTEM_SUPPORT_OS		1
usart
#include "FreeRTOS.H"//替换#include "includes.h"
删除usart 中对于ucos的支持

delay

//系统时钟
#include "task.h"
extern void xPortSysTickHandler(void);
void SysTick_Handler(void)
{	
	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)	//系统正在运行
	{
		xPortSysTickHandler();
	}
	HAL_IncTick();
	HAL_SYSTICK_IRQHandler();
}

void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
	u32 reload;
#endif
	HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);;//SysTick频率为HCLK
	fac_us=SYSCLK;						//不论是否使用OS,fac_us都需要使用
#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
	reload=SYSCLK;					    //每秒钟的计数次数 单位为K	   
	reload*=1000000/configTICK_RATE_HZ;	//根据configTICK_TATE_HZ 设置
											//reload为24位寄存器,最大值:16777216,在180M下
	fac_ms=1000/configTICK_RATE_HZ;		//代表OS可以延时的最少单位	   
	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启SYSTICK中断
	SysTick->LOAD=reload; 					//每1/OS_TICKS_PER_SEC秒中断一次	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
#else
#endif
}		

delay_us()//注释os
void delay_ms(u16 nms)
{	
	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)	    
	{		 
		if(nms>=fac_ms)						//延时的时间大于OS的最少时间周期 
		{ 
   			vTaskDelay(nms/fac_ms);	//OS延时
		}
		nms%=fac_ms;						//OS已经无法提供这么小的延时了,采用普通方式延时    
	}
	delay_us((u32)(nms*1000));				//普通方式延时
}

测试

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "FreeRTOS.h"
#include "task.h"
#define START_TASK_PRIO 1   //任务优先级
#define START_STK_SIZE 	128 //任务堆栈大小
TaskHandle_t StartTask_Handler;	//任务句柄
void start_task(void *pvParameters);//任务函数

#define LED0_TASK_PRIO 2
#define LED0_STK_SIZE  50
TaskHandle_t LED0Task_Handler;
void led0_task(void *p_arg);

#define LED1_TASK_PRIO 3
#define LED1_STK_SIZE		50
TaskHandle_t LED1Task_Handler;
void led1_task(void *p_arg);

#define FLOAT_TASK_PRIO	4
#define FLOAT_STK_SIZE	128
TaskHandle_t FLOATTask_Hanlder;
void float_task(void *p_arg);
int main(void)
{
	HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
		HAL_Init();//初始化 flash 预存取(FLASH访问周期FLASH 存储器具有由两个64 位缓存器组成的预取缓冲器,这些缓冲器可以从FLASH 存储器中进行64 位宽读取,然后传递独立的16 位或32 位指令给Cortex CPU执性) 系统中断 系统时钟 中断回调
		Stm32_Clock_Init(336,8,2,7);
		delay_init(168);
			uart_init(115200);
	LED_Init();
		
		//创建起始任务
		xTaskCreate(	(TaskFunction_t ) start_task,//任务函数
									(const char*)		"start_task",//任务名
									(uint16_t ) START_STK_SIZE,	//堆栈大小
									(void *) NULL,								//传递参书
									(UBaseType_t) START_TASK_PRIO,//优先级 unsign long
									(TaskHandle_t *) &StartTask_Handler//人去句柄
									);
		vTaskStartScheduler();
}


void start_task(void *pvParameters)
{
	taskENTER_CRITICAL();//进入临界区
	//创建任务1
	xTaskCreate(	(TaskFunction_t)led0_task,
								(const char *)"led 0",
								(uint16_t) LED0_STK_SIZE,
								(void *)NULL,
								(UBaseType_t) LED0_TASK_PRIO,
								(TaskHandle_t *) &LED0Task_Handler
								);
	
	xTaskCreate(	(TaskFunction_t)led1_task,
								(const char*)"led1",
								(uint16_t)LED1_STK_SIZE,
								(void *)NULL,
								(UBaseType_t) LED1_TASK_PRIO,
								(TaskHandle_t *)&LED1Task_Handler
								);
	xTaskCreate( 	(TaskFunction_t)float_task,
								(const char *)"float task",
									(uint16_t)FLOAT_STK_SIZE,
								(void *)NULL,
									(UBaseType_t)FLOAT_TASK_PRIO,
								(TaskHandle_t *)&FLOATTask_Hanlder
								);
	vTaskDelete(StartTask_Handler); //删除开始任务
	taskEXIT_CRITICAL();//推出临界区				
}
void led0_task(void *p_arg)
{
	while(1)
	{
		LED0=!LED0;
		vTaskDelay(500);
	}
}

void led1_task(void *p_arg)
{
	while(1)
	{
		LED1=0;
		vTaskDelay(200);
		LED1=1;
		vTaskDelay(800);
	}
}

void float_task(void *p_arg)
{
	static float float_num=0.0;
	while(1)
	{
		float_num +=0.01f;
		printf("float_num:%.4f\r\n",float_num);
		vTaskDelay(1000);
	}
}

FreeRTOSConfig.h 文件简单阅读

  1. include宏
对应函数说明
INCLUDE_vTaskPrioritySetuxTaskPriorityGet()函数用于查询一个任务的优先级
INCLUDE_uxTaskPriorityGetvTaskPrioritySet()修改任务的优先级
INCLUDE_vTaskDeletevTaskDelete删除任务
INCLUDE_vTaskCleanUpResourcesvTaskCleanUpResources( )回收任务的ram等资源
INCLUDE_vTaskSuspendvTaskSuspend();vTaskResume();prvTaskIsTaskSusPended()与任务挂起相关
INCLUDE_vTaskDelayUntilvTaskDelayUntil()指定任务离开阻塞态进入就绪态那一刻的心跳计数值
INCLUDE_vTaskDelayvTaskDelay任务将进入阻塞态
INCLUDE_xSemaphoreGetMutexHolderxQueueGetMutexHolder获取函数参数中互斥量的任务句柄
INCLUDE_xTaskAbortDelayxTaskAbortDelay()任务中止延时函数,该函数能立即解除任务的阻塞状态,将任务插入就绪列表中
INCLUDE_xTaskGetCurrentTaskHandlexTaskGetCurentTaskHandle()获得当前任务句柄
INCLUDE_xTaskGetHandlexTaskGetHandle()
INCLUDE_xTaskGetSchedulerStatexTaskGetSchedulerState()获取任务调度器的壮态,开启或未开启。
INCLUDE_uxTaskGetStackHIghWaterMarkxTaskGetSchedulerState获取任务的堆栈的历史剩余最小值, FreeRTOS 中叫做“高水位线”
INCLUDE_xTaskResumeFromISRxTaskResumeFromISR()j将任务从挂起状态恢复
INCLUDE_xTimerPendFunctionCallxTImerPendFunctionCall xTimerPendFunctionCallFromISR需要configUSE_TIMERS=1 定时器任务
  1. config 宏
说明
configUSE_PREEMPTION1:抢占式优先级 0:使用协程(1) 调用taskYIELD() 发生 (2):调用了使任务进入阻塞态的API函数 (3):中断中执行上下文切换
configUSE_IDLE_HOOK空闲钩子函数,需要用户自己实现
configUSE_TICK_HOOK使能时间片钩子函数,用户自己实现
configCPU_CLOCK_HZCPUI频率
configTICK_RATE_HZFreertos 系统时钟节拍,单位HZ,1000=1ms
configMAX_PRIORITIES系统优先级的数量 0:为最低优先级(与ucos不同)
configMINIMAL_STACK_SIZE空闲任务的最小任务堆栈大小,单位(字 = 4字节)
configTOTAL_HEAP_SIZE如果使能动态内存管理,会使用heap_x中的内存申请函数来申请内存
configUSE_TRACE_FACILITY与configUSE_STATS_FORMATTING_FUNCTIONS=1 生成vTaskList() 和vTaskGetRunTImeStatus()分析任务内存和状态
configUSE_16_BIT_TICKS设置系统节拍的变量类型 1:TickType_t 16位 0:32位
configIDLE_SHOULD_YIELD空闲任务与同优先级的执行机制,0:空闲任务优先 1:空闲人无让出CPU给同优先级的任务
configUSE_MUTEXES是否使用信号量
configQUEUE_REGISTRY_SIZE可以注册的队列和信号量的最大数量,使用内核调试器需要查看信号量和队列时需要设置,且先注册消息队列和信号量
configCHECK_FOR_STACK_OVERFLOW堆栈溢出检测,xTaskCreate()大小自动从任务堆栈分配,xTaskCreateStatic()从用户设置堆栈中分配,用户必须自己设置一个钩子函数(void vApplicationStackOverflowHook(TaskHandle_t xTask,char* pcTaskName)) ,其余暂时没遇到
configUSE_RECURSIVE_MUTEXES使用互斥信号量
configUSE_MALLOC_FAILED_HOOK内存分配失败的回调函数
configUSE_APPLICATION_TASK_TAGconfigUSE_APPLICATION_TASK_TAGF() &xTaskCallApplicationTaskHook() 可以为任务绑定回调函数
configUSE_COUNTING_SEMAPHORES是否启用计数型信号量
configGENERATE_RUN_TIME_STATS是否时间统计功能 ,需要定义一个宏
协程
configUSE_CO_ROUTINES是否启用协程
configMAX_CO_ROUTINE_PRIORITIES分配给协程的最大优先级(0 最低)
定时器
configUSE_TIMERS1 使能软件定时器
configTIMER_TASK_PRIORITY软件定时器优先级
configTIMER_QUEUE_LENGTH软件定时器的命令队列长度
configTIMER_TASK_STACK_DEPTH软件定时器任务堆栈大小
中断配置
configPRIO_BITSMCU优先级的位数 STM32 4位(16个抢占)
configLIBRARY_LOWEST_INTERRUPT_PRIORITY设置最低优先级,stm32 使用组4,最低值位15
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITYFreeRtos可管理的最大优先级
configKERNEL_INTERRUPT_PRIORITY内核中断优先级
configASSERT错误判断函数
vPortSVCHandler中断服务函数
vPortSVCHandlerSVC中断服务函数
xPortSysTickHandler系统滴答定时器
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值