1.CUBEMX配置
2.代码
void StartADC(void const * argument)
{
/* USER CODE BEGIN StartADC */
TickType_t pxPreviousWakeTime=xTaskGetTickCount();
/* Infinite loop */
for(;;)
{
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1,100)==HAL_OK)
{
uint32_t value=HAL_ADC_GetValue(&hadc1);
OLED_ShowNum(18,1,value,4,OLED_6X8);
OLED_Update();
}
vTaskDelayUntil(&pxPreviousWakeTime,pdMS_TO_TICKS(500));
}
/* USER CODE END StartADC */
}
/* USER CODE BEGIN Header_StartInfo */
/**
* @brief Function implementing the Task_Info thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartInfo */
void StartInfo(void const * argument)
{
/* USER CODE BEGIN StartInfo */
TaskHandle_t taskHandle=Task_ADCHandle;
TaskStatus_t Taskinfo;
BaseType_t getFreeStackSpace=pdTRUE;
eTaskState taskState=eInvalid;
vTaskGetInfo(taskHandle,&Taskinfo, getFreeStackSpace, taskState)PRIVILEGED_FUNCTION;//获取任务信息的函数
/*
该函数输入参数有四个,TaskHandle_t xTask为所要查询任务的任务句柄;
TaskStatus_t *pxTaskStatus为任务状态结构体,用于存放任务的状态,该结构体需要用户自定义;
BaseType_t xGetFreeStackSpace为是否计算任务剩余最小堆栈大小,传入参数pdTRUE表示计算,但需要耗费一些时间;
eTaskState eState为是否获取任务状态,输入参数eInvalid时表示获取任务状态,但同样也会消耗一些时间,否则用户指定任务状态,不会消耗时间。
*/
taskENTER_CRITICAL();//开启临界代码段,不允许任务调度CRITICAL主要的,关键的
// uint8_t temp_str[100];
// sprintf(temp_str,"Task Name=%s",Taskinfo.pcTaskName);
// OLED_ShowString(1,9,"*(temp_str)",OLED_6X8);
//1 OLED_Printf(1, 9,OLED_6X8,"Task Name=%s",Taskinfo.pcTaskName);
// OLED_Printf(1, 18,OLED_6X8,"Task Number=%d",Taskinfo.xTaskNumber);//获取任务编号
// OLED_Printf(1, 27,OLED_6X8,"Task State=%d",Taskinfo.eCurrentState);
// OLED_Printf(1, 36,OLED_6X8,"Task Priority=%d",Taskinfo.uxCurrentPriority);
// OLED_Printf(1, 45,OLED_6X8,"High Mark=%d(word)",Taskinfo.usStackHighWaterMark);
// OLED_Update();
//2 taskHandle=xTaskGetIdleTaskHandle();
// OLED_Printf(1, 9,OLED_6X8,"Idle Task =%d",uxTaskGetStackHighWaterMark(taskHandle));
// OLED_Printf(1, 18,OLED_6X8,"Task ADCr=%d",uxTaskGetStackHighWaterMark(Task_ADCHandle));
// OLED_Printf(1, 27,OLED_6X8,"Task Info=%d",uxTaskGetStackHighWaterMark(Task_InfoHandle));
// OLED_Update();
// OLED_Clear();
OLED_Printf(1, 9,OLED_6X8,"uxTaskGet=%d",uxTaskGetNumberOfTasks());//3获取任务的总数
OLED_Update();
taskEXIT_CRITICAL();
// OLED_ShowString(9,9,"taskIofo.pcTaskName",OLED_6X8);
// OLED_Update();
/* Infinite loop */
for(;;)
{
for(uint8_t i=0;i<10;i++)
{
// OLED_Clear();
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
vTaskDelay(pdMS_TO_TICKS(100));
}
break;
}
// OLED_Clear();
OLED_Printf(1, 18,OLED_6X8,"Task_Info is deleted");
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
OLED_Update();
vTaskDelete(NULL);
/* USER CODE END StartInfo */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
//void vApplicationIdleHook(void)
//{
// OLED_Clear();
//}
/* USER CODE END Application */
#define configUSE_TRACE_FACILITY 1 //vTaskGetInfo
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetIdleTaskHandle 1 //xTaskGetIdleTaskHandle()
使用静态创建函数创建 FreeRTOS 任务时,需要记住一点:必须实现 vApplicationGetIdleTaskMemory 函数来完成空闲任务的内存分配。这是因为在使用静态内存分配时,FreeRTOS 会自动创建一个空闲任务,该任务会在系统空闲时进行调度。
空闲任务可以执行某些不需要 CPU 时间的操作,比如暂时挂起 CPU、等待时钟中断、等待消息等,以便释放 CPU 资源给其它任务使用。
空闲任务需要分配堆栈和任务控制块,而这些内存区域需要手动向 FreeRTOS 系统申请。
在这种情况下,我们需要实现 vApplicationGetIdleTaskMemory 函数,该函数会在空闲任务创建之前被调用。
在该函数中,我们需要声明一个静态的变量作为空闲任务控制块的内存池,
并将该内存池的首地址和大小等信息传递给空闲任务创建函数,以完成空闲任务的内存分配。
任务使用的堆栈将随着任务的执行和中断的处理而增长和收缩。
uxTaskGetStackHighWaterMark()返回自任务开始执行以来任务可用的最小剩余堆栈空间量,
即任务堆栈达到最大(最深)值时未使用的堆栈量。这就是所谓的烟囱“高水位线”。
注意:返回值更新的前提是有新的最小值出现,否则即便初始化新的临时变量,可能也不会刷新这个 HiqhWaterMark 的值(因为 stacksize 减小了,但是没有到刷新最小值的地步)。
注意:Task 本身的 handle、状态管理不消耗这个 stack size(内部用的是malloc),
但是printf()这个函数是消耗 stack size 的。