历史上的今天
今天是:2024年12月15日(星期日)
2018年12月15日 | STM32CubeMX中FreeRTOS系统CPU使用率监测测试
2018-12-15 来源:eefocus
1.测试描述:
使用STM32CubeMX自动配置的工程,对其提供的FreeRTOS系统的CPU使用率进行监测,并通过串口打印。
2.测试环境:
(1)软件环境:STM32CubeMX-4.22.0,IAR-7.5,串口调试工具
(2)硬件环境:原子战舰V3开发板
3.测试准备:
(1)STM32CubeMX软件主要配置:
管脚和其他外设的配置直接省略了,具体的可查看源码文件里的ioc文件。下面贴出主要的系统方面配置图:
首先是Configuration界面,从图中可以看出测试工程使用的东西并不多;

点击中间层的FREERTOS进入系统配置界面,主要注意下图中红色标注的部分;

下图对一些系统的函数进行使能和失能操作,由于测试工程里有用到vTaskDelayUntil函数,所以对其使能。

(2)IAR软件配置:
首先从stm32官网下载的固件包里找到如下文件:
细心的人会发现这个是在F7的固件包里找的,当然F1的固件包里也可以找到,所以此方式也适用于其他支持FreeRTOS的stm32芯片。
将两个文件复制到测试工程文件夹内,对应地址如下图(地址在后面添加头文件时有用,可实际根据自身情况拖放):

在工程里添加cpu_utils.c文件

在工程配置选项里添加cpu_utils.h文件路径,这里我用的是相对路径,如果换别的电脑上时使用只需要重新ReBuild一下工程就好了。

在cpu_utils.h里添加使用到的两个头文件:

最后在FreeRTOSConfig.h文件的用户代码区添加如下两段代码。这一步很重要,如果没有,那么监测到的使用率一直为100%。

4.测试代码:
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "cmsis_os.h"
/* USER CODE BEGIN Includes */
#include "gpio.h"
#include "string.h"
#include "usart.h"
#include "cpu_utils.h"
/* USER CODE END Includes */
/* Variables -----------------------------------------------------------------*/
osThreadId defaultTaskHandle;
/* USER CODE BEGIN Variables */
#define START_TASK_PRIO 1
#define START_STK_SIZE 64
TaskHandle_t xHandleTaskStart;
void StartTask(void const * argument);
#define LED1_TASK_PRIO 5
#define LED1_STK_SIZE 128
TaskHandle_t xHandleTaskLED1;
void TaskLED1(void const * argument);
#define LED2_TASK_PRIO 6
#define LED2_STK_SIZE 128
TaskHandle_t xHandleTaskLED2;
void TaskLED2(void const * argument);
void MX_FREERTOS_Init(void) {
//系统自建的任务,不去动它,屏蔽了也没关系。
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
//创建开始任务
xTaskCreate((TaskFunction_t )StartTask,
(const char * )"Start Task",
(uint16_t )START_STK_SIZE,
(void * )NULL,
(UBaseType_t )START_TASK_PRIO,
(TaskHandle_t * )&xHandleTaskStart);
/* USER CODE END RTOS_QUEUES */
}
//开始任务,用于创建两个新的测试任务
void StartTask(void const * argument)
{
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t )TaskLED1,
(const char * )"LED1 Task",
(uint16_t )LED1_STK_SIZE,
(void * )str1,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t * )&xHandleTaskLED1);
xTaskCreate((TaskFunction_t )TaskLED2,
(const char * )"LED2 Task",
(uint16_t )LED2_STK_SIZE,
(void * )str2,
(UBaseType_t )LED2_TASK_PRIO,
(TaskHandle_t * )&xHandleTaskLED2);
vTaskDelete(xHandleTaskStart);
taskEXIT_CRITICAL();
}
//LED1任务
void TaskLED1(void const * argument)
{
char str1[] = "TASK LED1 is Running!\r\n";
portTickType xLastWakeTime;
static uint16_t usage = 0;
uint32_t num = 0;
char buffer[100];
//延时时间单元初始值记录
xLastWakeTime = xTaskGetTickCount();
while(1)
{
//串口1发送提示字符串
HAL_UART_Transmit(&huart1,(uint8_t *)str1,strlen(str1),0xFFFF);
while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET);
//获取CPU使用率并串口打印
usage = osGetCPUUsage();
num = sprintf(buffer,"1---CPU 使用率为:%d%%\r\n",usage);
HAL_UART_Transmit(&huart1,(uint8_t *)buffer,num,0xFFFF);
while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET);
//LED闪烁
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
vTaskDelayUntil(&xLastWakeTime,(1000/portTICK_RATE_MS));
}
}
//LED2任务
void TaskLED2(void const * argument)
{
char str2[] = "TASK LED2 is Running!\r\n";
portTickType xLastWakeTime;
static uint16_t usage = 0;
uint32_t num = 0;
char buffer[100];
//延时时间单元初始值记录
xLastWakeTime = xTaskGetTickCount();
while(1)
{
//串口1发送提示字符串
HAL_UART_Transmit(&huart1,(uint8_t *)str2,strlen(str2),0xFFFF);
while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET);
//获取CPU使用率并串口打印
usage = osGetCPUUsage();
num = sprintf(buffer,"2---CPU 使用率为:%d%%\r\n",usage);
HAL_UART_Transmit(&huart1,(uint8_t *)buffer,num,0xFFFF);
while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET);
//LED闪烁
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET);
vTaskDelayUntil(&xLastWakeTime,(300/portTICK_RATE_MS));
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET);
vTaskDelayUntil(&xLastWakeTime,(1200/portTICK_RATE_MS));
}
}
/* USER CODE END Application */
5.测试源码分析:
在嵌入式系统中,如果当前没有任何计划的任务运行,则系统会自动切换到空闲任务当中去。当一个系统中空闲任务占用一段时间的比值越大,对应硬件CPU对于工程所留的计算余量也就越大,则这个系统的CPU使用率越低。
实际算法可简化为以下公式:
系统使用率 = 1 - 空闲任务占用时间/总测算时间
下图中箭头指向的位置是CPU使用率计算的算法核心,它是在Tick中断发生1000次时进行一次计算处理。也就是总测算时间为1000个心跳时钟。其中计算部分对原公式右边乘上了100倍,实际计算出来的osCPU_Usage为百分数。

以下两个函数是在FreeRTOSConfig.h宏定义中提到的函数,红色数字标注的是要重点关注的地方。这两个函数就是用来测算进入空闲函数的时间。

以上两个函数通过宏定义的方式,实际调用在系统任务切换函数里。也就是在这两个位置进行处理,进而得到需要的空闲任务占用时间。

6.测试结果:
在IAR的Live Watch窗口监测的系统使用率的值、系统心跳时基和空闲任务总占用时间。

下面是串口的输出,看出系统在刚开始时使用率有一段波动,后面趋于平稳,一直处于1%。

史海拾趣
|
问题: Query:在从原理图更新到PCB的时候,如何保持原有器件的布局? 在Protel中,通常都会遇到需要修改原理图时,如何保持原有PCB板中器件的布局的问题。下面讲述一种有效的方式就是在PCB编辑窗口中使用菜单命令Project » Component Links来完成 ...… 查看全部问答> |
|
之前介绍过如何创建一个基本的Windows CE的平台,现在咱就上一次没有提到的部分进行一下补充定制并build OS。 首先,在VS2005 IDE中的View -> Other Windows -> Catalog Items中,添加或者删除相应的模块来完成OS定制,选项如下: 然后配置buil ...… 查看全部问答> |
|
本帖最后由 辛昕 于 2018-4-8 22:59 编辑 关于这个东西,我后来其实从来没捡起过。 但是,也就没有必要惦记着了。 当然了,每次说到这个东西,都会想起,故人已去~ 在做运放的过程中,知道了一个叫做模拟乘法器的东西。 但是想上网看看这个东 ...… 查看全部问答> |
|
Windows CE 5.0的ARMV4I补丁,名称如下: WinCEPB50-051231-Product-Update-Rollup-Armv4I.msi WinCEPB50-060131-2006M01-Armv4I.msi WinCEPB50-060228-2006M02-Armv4I.msi WinCEPB50-06 ...… 查看全部问答> |
|
谁有这样的程序,急求,可以和我联系. email:gcgaoxj@yahoo.com [ 本帖最后由 dreaming123 于 2011-3-16 21:42 编辑 ]… 查看全部问答> |
|
刚刚看到可以用:用社区芯币兑换51开发板PCB板!早知道在这里换了,自己花了150快大洋买了一个 能不能用社区芯币兑换ARM的开发板呢… 查看全部问答> |
|
请问有没有建立工程的教程,我按照官方网站的教程建立,(用的是ise13.1), 各种无奈啊,遇到的问题: 1、头文件的处理,我把用到的头文件拷到板级包的include文件夹,开始时可以,但是后面工程关闭,又出现 没找到头文件,那不是又得拷贝一次, ...… 查看全部问答> |
|
摘要:鉴于FPGA和DSP各自的优势,FPGA+DSP信号处理架构,已成为信号处理系统的常用结构。但目前此结构处理平台功能固定、通用性差,或对平台的介绍缺乏具体实现。文中针对以上两点提出一种通用信号处理系统。该系统不仅将两种处理器的优点集于一身 ...… 查看全部问答> |




