提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
`昨天看了一会正点原子的FreeRTOS的学习手册,随便也把今天学习成果记录一下
一、任务创建成功标志
1.动态任务
当我们使用xTaskCreate动态创建任务时都会有一个创建成功的标志pdPASS
下面是xTaskCreate源码
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
{
TCB_t * pxNewTCB;
BaseType_t xReturn;
/* If the stack grows down then allocate the stack then the TCB so the stack
* does not grow into the TCB. Likewise if the stack grows up then allocate
* the TCB then the stack. */
#if ( portSTACK_GROWTH > 0 )
{
/* Allocate space for the TCB. Where the memory comes from depends on
* the implementation of the port malloc function and whether or not static
* allocation is being used. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
if( pxNewTCB != NULL )
{
/* Allocate space for the stack used by the task being created.
* The base of the stack memory stored in the TCB so the task can
* be deleted later if required. */
pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
if( pxNewTCB->pxStack == NULL )
{
/* Could not allocate the stack. Delete the allocated TCB. */
vPortFree( pxNewTCB );
pxNewTCB = NULL;
}
}
}
#else /* portSTACK_GROWTH */
{
StackType_t * pxStack;
/* Allocate space for the stack used by the task being created. */
pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
if( pxStack != NULL )
{
/* Allocate space for the TCB. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
if( pxNewTCB != NULL )
{
/* Store the stack location in the TCB. */
pxNewTCB->pxStack = pxStack;
}
else
{
/* The stack cannot be used as the TCB was not created. Free
* it again. */
vPortFreeStack( pxStack );
}
}
else
{
pxNewTCB = NULL;
}
}
#endif /* portSTACK_GROWTH */
if( pxNewTCB != NULL )
{
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */
{
/* Tasks can be created statically or dynamically, so note this
* task was created dynamically in case it is later deleted. */
pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
}
#endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
prvAddNewTaskToReadyList( pxNewTCB );
xReturn = pdPASS;
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
}
return xReturn;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
上面代码可以得出xTaskCreate是一个带BaseTybe(typedef long)的返回值, 并且动态任务创建成功return pdPASS;,失败 return errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
2.静态任务
静态任务xTaskCreateStatic函数创建任务失败是NULL成功返回其他数
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer,
StaticTask_t * const pxTaskBuffer )
{
TCB_t * pxNewTCB;
TaskHandle_t xReturn;
configASSERT( puxStackBuffer != NULL );
configASSERT( pxTaskBuffer != NULL );
#if ( configASSERT_DEFINED == 1 )
{
/* Sanity check that the size of the structure used to declare a
* variable of type StaticTask_t equals the size of the real task
* structure. */
volatile size_t xSize = sizeof( StaticTask_t );
configASSERT( xSize == sizeof( TCB_t ) );
( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
}
#endif /* configASSERT_DEFINED */
if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
{
/* The memory used for the task's TCB and stack are passed into this
* function - use them. */
pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
{
/* Tasks can be created statically or dynamically, so note this
* task was created statically in case the task is later deleted. */
pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
}
#endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
prvAddNewTaskToReadyList( pxNewTCB );
}
else
{
xReturn = NULL;
}
return xReturn;
}
#endif /* SUPPORT_STATIC_ALLOCATION */
二、使用一个任务中创建另外几个任务注意(我就说成父任务和子任务)
1.注意优先级,
1.1.父任务(包含小任务)优先级必须小于子任务,不然不会运行。
下面的源码里面大任务的优先级是1,小任务的优先级都是2
1.2.其次父任务运行完后必须使用vTaskDelete函数自杀,不然程序要卡死。
1.3.可以添加临界区来保证子任务会完整的运行
下面是源码main.c
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "FreeRTOS.h"
#include "task.h"
TaskHandle_t HandlerTask1;
TaskHandle_t Task_Name4;
BaseType_t xReturn;
void SystemClock_Config(void);
StackType_t xTask3Static[128];
StaticTask_t xTaskTCB;
StackType_t xIdle3Static[128];
StaticTask_t xIdleTCB;
static int task1flag=0;
static int task2flag=0;
static int task3flag=0;
static int task4flag=0;
void Task1Function( void * param){
for(;;){
task1flag=1;
task2flag=0;
task3flag=0;
task4flag=0;
uint8_t buff[10]="1\r\n";
HAL_UART_Transmit(&huart1,(uint8_t*)buff,strlen(buff)*sizeof(char),HAL_MAX_DELAY);
vTaskDelay(30);
}
}
void Task2Function(void* param){
/* GPIO_InitTypeDef GPIO_Init;
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_Init.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_Init.Pin=GPIO_PIN_5;
HAL_GPIO_Init(GPIOB,&GPIO_Init);*/
for(;;)
{
task1flag=0;
task2flag=1;
task3flag=0;
task4flag=0;
uint8_t buff2[10]="2\r\n";
HAL_UART_Transmit(&huart1,(uint8_t*)buff2,strlen(buff2)*sizeof(char),HAL_MAX_DELAY);
vTaskDelay(30);
}
}
void Task3Funtion(void* param){
TickType_t st_time=xTaskGetTickCount();
int str[]={1,2,4,5,6};
int j;
while(1){
task1flag=0;
task2flag=0;
task3flag=1;
task4flag=0;
//vTaskDelet();
uint8_t buff[20]="3\r\n";
for(int i=0;i<j;i++){
HAL_UART_Transmit(&huart1,(uint8_t*)buff,strlen(buff)*sizeof(char),HAL_MAX_DELAY);
}
j++;
if(j==5)j=0;
xTaskDelayUntil(&st_time,30);
}
}
void Task4Funtion(void* param){
taskENTER_CRITICAL();
task1flag=0;
task2flag=0;
task3flag=0;
task4flag=1;
xReturn=xTaskCreate(Task1Function,"Task1",128,NULL,2,&HandlerTask1);
xTaskCreate(Task2Function,"Task2",128,NULL,2,NULL);
xTaskCreateStatic(Task3Funtion,"Task3",128,NULL,2,xTask3Static,&xTaskTCB);
if(xReturn == pdPASS){
uint8_t buffS[20]="Task1 Create OK..\r\n";
HAL_UART_Transmit(&huart1,(uint8_t*)buffS,strlen(buffS)*sizeof(char),HAL_MAX_DELAY);
}
vTaskDelete(Task_Name4);
taskEXIT_CRITICAL();
}
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,StackType_t ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize ){
*ppxIdleTaskTCBBuffer=&xIdleTCB;
*ppxIdleTaskStackBuffer=xIdle3Static;
*pulIdleTaskStackSize=128;
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
xTaskCreate(Task4Funtion,"Task4",600,NULL,1,&Task_Name4);
vTaskStartScheduler();
while (1)
{
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */
代码如下(示例):
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
#三、相关API
/*
这个是定义typedef long的数据类型。
这个变量是获取创建任务是否成功的返回值
*/
BaseType_t xReturn;
/*
进入临界区 注意taskENTER_CRITICAL();和taskEXTI_CRITICAL();要连用
*/
taskENTER_CRITICAL();
/*
退出临界区 注意taskENTER_CRITICAL();和taskEXTI_CRITICAL();要连用
*/
taskEXIT_CRITICAL();
总结
这个为了弥补昨天的学习成果。
因依老宿发心初,半学修心半读书