求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
要资料
 
追随技术信仰

随时听讲座
每天看新闻
 
 
FreeRTOS源码分析及应用开发
1. FreeRTOS系列 | FreeRTOS简介
2. FreeRTOS系列 | 开发环境
3. FreeRTOS系列 | 任务基础知识
4. FreeRTOS系列 | 任务创建和删除
5. FreeRTOS系列 | 任务挂起和恢复
6. FreeRTOS系列|多任务调度
7. FreeRTOS系列|时间管理
8. FreeRTOS系列|中断管理和临界段
9. FreeRTOS系列|任务堆栈
10. FreeRTOS系列 | 处理器利用率
11. FreeRTOS系列|任务相关API函数
12. FreeRTOS系列 | 列表和列表项
13. FreeRTOS系列|消息队列一
14. FreeRTOS系列|消息队列二
15. FreeRTOS系列 | 二值信号量
16. FreeRTOS系列 | 互斥信号量
17. FreeRTOS系列 | 计数信号量
18. FreeRTOS系列 | 递归互斥信号量
19. FreeRTOS系列 | 事件标志组
20. FreeRTOS系列 | 软件定时器
21. FreeRTOS系列 | 低功耗管理
22. FreeRTOS系列 | 内存管理一
23. FreeRTOS系列 | 内存管理二
 

 
目录
FreeRTOS系列|任务堆栈
作者:安迪西嵌入式
398 次浏览
3次  

任务堆栈

运行freertos系统的大部分都是资源有限的MCU,所以对于RAM我们都要考虑尽量的节省,避免资源浪费。下面将会基于Cortex-M3内核的STM32F103型MCU来介绍FreeRTOS任务栈大小的确定方法以及栈溢出检测方法

1. 任务堆栈大小

需要用到堆栈的地方:

  • 函数嵌套:函数局部变量、函数形参、函数返回地址、函数内部状态值
  • 任务切换:任务切换时所有的寄存器都需要入栈
  • 中断:M3内核MCU有8个寄存器是自动入栈的(任务栈),进入中断以后其余寄存器入栈以及可能发生的中断嵌套都是用的系统栈

2. 任务堆栈大小确定方法

2.1 MDK html文件分析

通过查看工程源码中“MDK-ARM”里的工程名文件夹下的html文件可以知道每个被调用函数的最大栈需求以及各个函数之间的调用关系

2.2 栈溢出检测

栈溢出有两种检测方案

方案一:在任务切换时检测任务栈指针是否过界;

方案二:任务创建的时候将任务栈所有数据初始化为0xa5,任务切换并进行任务栈检测的时候检查末尾的16个字节是否都是0xa5;

/*******************栈溢出检测宏的配置********************/
#define configCHECK_FOR_STACK_OVERFLOW
0, 配置为0,表示不启动栈溢出检测
1, 配置为1,表示启用栈溢出检测方案一
2, 配置为2,表示启用栈溢出检测方案二
/*********************栈溢出回调函数**********************/
函数原型:void vApplicationStackOverflowHook(TaskHandle_t *pxTask,signed char *pcTaskName)
传 入 值:pxTask 堆栈溢出任务的句柄
     pcTaskName 堆栈溢出任务的名称

 

2.3 任务状态打印

通过调用vTaskList()函数打印每个任务的详细信息(栈名、栈状态、优先级、栈的剩余空间、任务序号)

/*******************任务状态信息打印宏的配置*******************/
#define configUSE_TRACE_FACILITY  //必须置1
#define configUSE_STATS_FORMATTING_FUNCTIONS  //必须置1
/*********************任务状态信息打函数**********************/
函数原型:void vTaskList(char *pcWriteBuffer)
传 入 值:pcWriteBuffer 缓冲区地址

 

根据传入的缓冲区(缓冲区要足够大,以容纳生成的报告,每个任务大约需要40个字节)生成字符串,这个字符串包含所有任务信息

3. 任务堆栈检测应用

以较常用的任务状态打印的堆栈检测方法为例:使用STM32CubeMX配置FreeRTOS,打开任务状态配置,创建如下三个任务:

Led_Task:D2指示灯闪烁

Usart_Task:每隔1s向串口输出字符串

Key_Task:按下K_UP,打印任务状态信息

3.1 STM32CubeMX设置

RCC设置外接HSE,时钟设置为72M

PC1设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平

PA0设置为GPIO输入模式、下拉模式;PE2/PE3/PE4设置为GPIO输入模式、上拉模式

USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位

激活FreeRTOS,添加任务,设置任务名称、优先级、堆栈大小、函数名称等参数

 

配置宏configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS为1

 

使用FreeRTOS操作系统,一定要将HAL库的Timebase Source从SysTick改为其他定时器,选好定时器后,系统会自动配置TIM

 

输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码

3.2 MDK-ARM软件编程

  • 创建按键驱动文件key.c和key.h,参考 按键输入 例程
  • 添加Led_Task、Usart_Task和Key_Task任务函数代码
void Led_Task(void const * argument){
  /* USER CODE BEGIN Led_Task */
  /* Infinite loop */
                for(;;){
	                 HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_RESET);
                        osDelay(500);  //1ms时基
	                 HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);
                       osDelay(500);  //1ms时基
                       }
          /* USER CODE END Led_Task */
    }

void Usart_Task(void const * argument){
  /* USER CODE BEGIN Usart_Task */
  /* Infinite loop */
               for(;;){
	                printf("UsartTask is Runing!\r\n");
                        osDelay(1000);
                      }
          /* USER CODE END Usart_Task */
    }

void KeyTask(void const * argument){
  /* USER CODE BEGIN KeyTask */
	uint8_t key = 0;	
  /* Infinite loop */
               for(;;){
                  key = KEY_Scan(0);	
	              switch(key){
		             case KEY_UP_PRES:
			             memset(u8TaskListBuff, 0, 400);
			             vTaskList((char*)u8TaskListBuff);
			             printf("Name      State    Priority    Stack   Num\r\n");
			             printf("******************************************************\r\n");
			             printf("%s",u8TaskListBuff);
			             printf("******************************************************\r\n");
			             key = 0;
			      break;
		              case KEY_DOWN_PRES:
			             //....
			             key = 0;
			      break;
	                         }  
	                  osDelay(10);
                      }
              /* USER CODE END KeyTask */
      }
               

 

3.3 下载验证

编译无误下载到开发板后,D2指示灯闪烁表示程序正常运行。打开串口调试助手,可以看到串口每隔1s输出相应字符;按下K_UP按键,串口打印出每个任务的详细信息


您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码: 验证码,看不清楚?请点击刷新验证码 必填



398 次浏览
3次