当前位置: 首页 > news >正文

FreeRTOS保姆级教程(以STM32为例)—任务创建和任务控制API说明

目录

一、任务创建:

(1)TaskHandle_t  任务句柄

(2) xTaskCreate:

函数原型:

参数说明:

返回值:

示例: 

注意事项:

用法示例:

(3)xTaskCreateStatic :

函数原型:

参数说明:

返回值:

使用场景:

注意事项:

用法示例:

 (4)vTaskDelete:

函数原型:

参数:

功能:

注意事项:

配置:

用法示例:

二、任务控制: 

(1)vTaskDelay:

函数原型:

参数:

功能:

注意事项:

配置:

用法示例:

计算实际延迟时间:

替代函数:

(2)vTaskDelayUntil:

函数原型:

参数:

功能:

注意事项:

配置:

用法示例:

计算实际延迟时间:

 (3)uxTaskPriorityGet :

函数原型:

参数:

返回值:

功能:

注意事项:

用法示例:

优先级比较:

 (4)vTaskPrioritySet :

函数原型:

参数:

功能:

注意事项:

用法示例:

优先级设置:

(5)vTaskSuspend:

函数原型:

参数:

功能:

注意事项:

用法示例:

挂起和恢复任务:

 (6)vTaskResume:

函数原型:

参数:

功能:

注意事项:

用法示例:

挂起和恢复任务:

(7)xTaskResumeFromISR:

函数原型:

参数:

返回值:

功能:

注意事项:

用法示例:

上下文切换:

 (8)xTaskAbortDelay :

函数原型:

参数:

返回值:

功能:

注意事项:

用法示例:

 (9)uxTaskPriorityGetFromISR:

函数原型:

参数:

返回值:

功能:

注意事项:

用法示例:

(10)uxTaskBasePriorityGet:

函数原型:

参数:

返回值:

功能:

注意事项:

用法示例:

(11)uxTaskBasePriorityGetFromISR:

函数原型:

参数:

返回值:

功能:

注意事项:

用法示例:


一、任务创建:

(1)TaskHandle_t  任务句柄

  • TaskHandle_t 是 FreeRTOS 中用于标识任务句柄的数据类型,它通常指向任务控制块(TCB)。当你创建一个任务时,例如使用 xTaskCreate 函数,你可以提供一个指针参数来接收新创建的任务的句柄。这个句柄可以用来对任务进行操作,比如删除任务。
TaskHandle_t myTaskHandler; // 定义一个任务句柄变量,用于跟踪任务。

(2) xTaskCreate:

  • 创建一项新任务并将其添加到准备运行的任务列表中。
  • configSUPPORT_DYNAMIC_ALLOCATION 必须在 FreeRTOSConfig.h 中设置为 1,或处于未定义状态(默认为 1), 才可使用此 RTOS API 函数。
  • 每项任务都需要 RAM 来保存任务状态,并由任务用作其堆栈。
  • 如果 使用 xTaskCreate() 创建任务,则所需的 RAM 会自动 从 FreeRTOS 堆分配。
  • 如果使用 xTaskCreateStatic() 创建任务, 则 RAM 由应用程序编写者提供,因此可以在编译时静态分配。
  • 如果使用的是 FreeRTOS-MPU,建议 使用 xTaskCreateRestricted(),而不是 xTaskCreate()。

函数原型:

BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,const char * const pcName,const configSTACK_DEPTH_TYPE uxStackDepth,void *pvParameters,UBaseType_t uxPriority,TaskHandle_t *pxCreatedTask
);

参数说明:

  • pvTaskCode:指向任务函数的指针,任务函数是实现任务逻辑的函数。
  • pcName:任务的名称,主要用于调试目的,也可以用于通过名称获取任务的句柄。
  • uxStackDepth:任务堆栈的深度,以字数(word)为单位,不是字节。具体的堆栈大小取决于处理器的架构(如16位、32位等)。
  • pvParameters:传递给任务的参数,如果是一个变量的地址,那么在任务执行期间该变量必须有效。
  • uxPriority:任务的优先级,可以结合 portPRIVILEGE_BIT 来创建特权任务。
  • pxCreatedTask:可选参数,用于存储创建的任务的句柄,可以用于后续的任务操作,如删除任务。

返回值:

  • pdPASS:表示任务成功创建。
  • errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY:表示创建任务失败,通常是因为内存不足。

示例: 

// 创建名为"led1"的任务,栈大小为64字节,优先级为2,任务函数为myTask1,不传递参数给任务。xTaskCreate(myTask1, "led1", 64, NULL, 2, &myTaskHandler);

注意事项:

  • 确保 configSUPPORT_DYNAMIC_ALLOCATION 在 FreeRTOSConfig.h 中被定义为 1,以启用动态内存分配。
  • 如果使用 MPU(内存保护单元),建议使用 xTaskCreateRestricted 而不是 xTaskCreate
  • 任务函数应该永远不返回,如果需要结束任务,应该在任务内部调用 vTaskDelete
  • 传递给 pvParameters 的参数在任务整个生命周期内都必须有效,如果需要在任务结束后释放资源,应在任务函数内部处理。

用法示例:

//要创建的任务。
void vTaskCode( void * pvParameters )
{//参数值预期为1,因为1是在下面的xTaskCreate()调用中的pvParameters值。configASSERT( ( ( uint32_t ) pvParameters ) == 1 );for( ;; )//无限循环{//任务代码在这里。}
}//创建任务的函数
void vOtherFunction( void )
{BaseType_t xReturned;TaskHandle_t xHandle = NULL;//创建任务,存储句柄。xReturned = xTaskCreate(vTaskCode,       //执行任务的函数。"NAME",          //任务的文本名称。STACK_SIZE,      //以字为单位的堆栈大小,而不是字节。( void * ) 1,    //传入任务的参数。tskIDLE_PRIORITY,//创建任务的优先级。&xHandle );      //用于传递创建的任务句柄。if( xReturned == pdPASS ){//任务创建成功。使用任务句柄删除任务。vTaskDelete( xHandle );}
}

(3)xTaskCreateStatic

xTaskCreateStatic 是 FreeRTOS 提供的一个 API 函数,它允许开发者在创建任务时使用静态内存分配,即在编译时就已经分配好内存。这种方式与 xTaskCreate 动态分配内存的方式相对。

函数原型:

TaskHandle_t xTaskCreateStatic(TaskFunction_t pxTaskCode,const char * const pcName,const uint32_t ulStackDepth,void * const pvParameters,UBaseType_t uxPriority,StackType_t * const puxStackBuffer,StaticTask_t * const pxTaskBuffer
);

参数说明:

  • pxTaskCode:指向任务函数的指针,这是任务的入口点,任务函数不能返回,通常包含无限循环。
  • pcName:任务的名称,主要用于调试目的,也可以通过名称获取任务句柄。
  • ulStackDepth:任务堆栈的深度,以 StackType_t 类型的数组索引为单位。这个值表示堆栈数组的大小。
  • pvParameters:传递给任务的参数,这个参数在任务函数中可用。
  • uxPriority:任务的优先级,如果系统支持 MPU,可以通过设置 portPRIVILEGE_BIT 来创建特权任务。
  • puxStackBuffer:指向一个 StackType_t 类型的数组,这个数组用作任务的堆栈,必须在函数外部声明,以确保其内存在任务生命周期内持久存在。
  • pxTaskBuffer:指向一个 StaticTask_t 类型的变量,这个变量用于保存任务的控制块(TCB),同样必须在函数外部声明。

返回值:

  • 如果 puxStackBuffer 和 pxTaskBuffer 都不为 NULL,则函数会创建任务,并返回任务的句柄。
  • 如果 puxStackBuffer 或 pxTaskBuffer 为 NULL,则函数不会创建任务,并返回 NULL。

使用场景:

xTaskCreateStatic 适用于以下情况:

  • 当系统的内存资源非常有限,需要在编译时就确定任务使用的内存。
  • 当需要避免动态内存分配可能带来的内存碎片问题。
  • 当需要确保任务的内存使用可预测和确定。

注意事项:

  • 必须确保 puxStackBuffer 和 pxTaskBuffer 指向的内存区域在任务生命周期内不会被改变或释放。
  • configSUPPORT_STATIC_ALLOCATION 必须在 FreeRTOSConfig.h 中定义为 1,才能使用 xTaskCreateStatic
  • 如果你的系统使用 MPU,建议使用 xTaskCreateRestricted 来代替 xTaskCreateStatic,以便设置任务的内存访问权限。

使用 xTaskCreateStatic 可以提供更细粒度的内存管理控制,但同时也要求开发者更加注意内存的使用和管理。

用法示例:

//正在创建的任务将用作其堆栈的缓冲区的大小。
//注意:这是堆栈将保存的单词数,而不是单词数字节。
//例如,如果每个堆栈项都是32位,并且这个设置为100,
//然后将分配400字节(100 * 32位)。    #define STACK_SIZE 200//保存正在创建任务的TCB的结构。StaticTask_t xTaskBuffer;//正在创建的任务将用作栈的缓冲区。//注意这是StackType_t变量的数组。//StackType_t的大小取决于RTOS端口。StackType_t xStack[ STACK_SIZE ];//执行创建任务的函数。void vTaskCode( void * pvParameters ){//参数值预期为1,因为1是在在调用xTaskCreateStatic()中的pvParameters值。configASSERT( ( uint32_t ) pvParameters == 1UL );for( ;; ){//任务代码在这里。}}//创建任务的函数。void vOtherFunction( void ){TaskHandle_t xHandle = NULL;//创建不使用任何动态内存分配的任务。xHandle = xTaskCreateStatic(vTaskCode,       //执行任务的函数。"NAME",          //任务的文本名称。STACK_SIZE,      //xStack数组的索引数。( void * ) 1,    //传入任务的参数。tskIDLE_PRIORITY,//创建任务的优先级。xStack,          //作为任务栈的数组。&xTaskBuffer );  //保存任务数据结构的变量//puxStackBuffer和pxTaskBuffer不是NULL,//所以任务将有并且xHandle将是任务的句柄。//使用手柄暂停任务。[vTaskSuspend](/Documentation/02-Kernel/04-API-references/02-Task-control/06-vTaskSuspend)( xHandle );}

 (4)vTaskDelete:

vTaskDelete 是 FreeRTOS 提供的一个函数,用于删除一个任务。当一个任务不再需要时,可以使用这个函数来释放与该任务相关的资源。

函数原型:

void vTaskDelete( TaskHandle_t xTask );

参数:

  • xTask:要删除的任务的句柄。如果传递 NULL,则会删除调用 vTaskDelete 函数的任务本身。

功能:

  • vTaskDelete 会从 RTOS 内核管理中移除指定的任务,包括所有就绪、阻塞、挂起和事件列表。
  • 被删除的任务的堆栈和任务控制块(TCB)将由空闲任务在适当的时候释放,因此不需要手动释放这些资源。
  • 任务代码中动态分配的内存或其他资源不会自动释放,应在任务删除之前手动释放。

注意事项:

  • 确保在删除任务之前,该任务已经完成了所有必要的清理工作,包括释放它可能持有的任何资源。
  • 如果传递 NULL 给 vTaskDelete,那么当前执行的任务(即调用 vTaskDelete 的任务)将被删除。
  • 在任务删除后,不应再使用与该任务相关联的任何句柄或资源。
  • 确保空闲任务获得足够的处理时间,以便它能够释放被删除任务的资源。

配置:

  • 为了使用 vTaskDelete 函数,FreeRTOSConfig.h 文件中的 INCLUDE_vTaskDelete 宏必须定义为 1。如果这个宏没有定义,vTaskDelete 函数将不会被包含在编译中。

用法示例:

void vTaskFunction(void *pvParameters)
{for (;;){// 任务代码}
}void vOtherFunction(void)
{TaskHandle_t xHandle = NULL;// 创建任务,存储句柄xTaskCreate(vTaskFunction, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);// 做一些工作...// 使用句柄删除任务if (xHandle != NULL){vTaskDelete(xHandle);}
}

在这个例子中,vTaskFunction 是一个简单的任务函数,它将无限循环执行。vOtherFunction 创建了这个任务,并保留了任务的句柄。在执行了一些工作之后,它使用 vTaskDelete 来删除这个任务。

二、任务控制: 

(1)vTaskDelay:

vTaskDelay 是 FreeRTOS 提供的一个函数,用于实现任务的延迟(阻塞)。这个函数使调用它的任务暂停执行指定的滴答数(ticks),从而让出 CPU 给其他任务。

函数原型:

void vTaskDelay( const TickType_t xTicksToDelay );

参数:

  • xTicksToDelay:任务将要延迟的滴答数(ticks)。这个值表示任务想要延迟的时间,以系统的滴答频率为单位。

功能:

  • vTaskDelay 按照指定的滴答数延迟调用它的任务。
  • 延迟时间的实际长度取决于系统的滴答频率,这通常在 FreeRTOSConfig.h 文件中定义。

注意事项:

  • vTaskDelay 延迟的是任务的执行,而不是实际的时间。这意味着如果系统非常繁忙,任务可能会延迟更长时间。
  • vTaskDelay 不应该用于生成精确的定时事件,因为它受到任务调度和系统负载的影响。

配置:

  • 为了使用 vTaskDelay 函数,FreeRTOSConfig.h 文件中的 INCLUDE_vTaskDelay 宏必须定义为 1。如果这个宏没有定义,vTaskDelay 函数将不会被包含在编译中。

用法示例:

以下是一个使用 vTaskDelay 的示例,其中任务每 500 毫秒切换一次 LED 的状态:

void vToggleLED(void) {// 切换 LED 的代码
}void vTaskFunction(void *pvParameters) {/* 计算 500ms 对应的滴答数 */const TickType_t xDelay = 500 / portTICK_PERIOD_MS;for (;;) {/* 每 500ms 切换 LED 状态,然后延迟 */vToggleLED();vTaskDelay(xDelay);}
}

在这个例子中,vToggleLED 是一个假设的函数,用于切换 LED 的状态。vTaskFunction 是一个任务函数,它使用 vTaskDelay 来实现每 500 毫秒切换一次 LED。

计算实际延迟时间:

portTICK_PERIOD_MS 是一个常量,定义了每个滴答周期的时长(以毫秒为单位)。要计算延迟时间,可以使用以下公式:

const TickType_t xDelay = desiredTimeInMs / portTICK_PERIOD_MS;

其中 desiredTimeInMs 是希望延迟的时间(以毫秒为单位)。

替代函数:

  • vTaskDelayUntil:如果您需要以固定频率执行任务,可以使用 vTaskDelayUntil 函数。它允许您指定任务下次应该被唤醒的绝对时间,而不是相对时间。

(2)vTaskDelayUntil:

vTaskDelayUntil 是 FreeRTOS 提供的一个函数,它允许任务以固定的频率执行,而不是简单地延迟一定的时间。这个函数特别适合于需要周期性执行的任务。

函数原型:

void vTaskDelayUntil( TickType_t *pxPreviousWakeTime,const TickType_t xTimeIncrement );

参数:

  • pxPreviousWakeTime:指向一个变量的指针,该变量用于保存任务最后一次解除阻塞的时间。在首次使用前,这个变量必须用当前时间(xTaskGetTickCount)初始化。在这之后,vTaskDelayUntil 会在每次调用时自动更新这个变量。
  • xTimeIncrement:周期时间段,以滴答数为单位。任务将在 (*pxPreviousWakeTime + xTimeIncrement) 的时间解除阻塞。使用相同的 xTimeIncrement 参数值调用 vTaskDelayUntil 将导致任务以固定的间隔执行。

功能:

  • vTaskDelayUntil 确保任务以恒定的执行频率运行。
  • 与 vTaskDelay 不同,vTaskDelayUntil 指定任务希望解除阻塞的绝对时间,而不是相对于调用时间的延迟。

注意事项:

  • 如果 vTaskDelayUntil 被用于指定已经过去的唤醒时间,该函数将立即返回(不阻塞)。
  • 使用 vTaskDelayUntil 定期执行的任务,在周期性执行因任何原因停止(例如,任务被挂起)而导致任务错过一个或多个周期性执行时,必须重新计算其所需的唤醒时间。
  • 当调用了 vTaskSuspendAll 挂起 RTOS 调度器时,不得调用此函数。

配置:

  • 为了使用 vTaskDelayUntil 函数,FreeRTOSConfig.h 文件中的 INCLUDE_vTaskDelayUntil 宏必须定义为 1。如果这个宏没有定义,vTaskDelayUntil 函数将不会被包含在编译中。

用法示例:

以下是一个使用 vTaskDelayUntil 的示例,其中任务每 10 个滴答周期执行一次动作:

void vTaskFunction(void *pvParameters)
{TickType_t xLastWakeTime;const TickType_t xFrequency = 10;// 初始化 xLastWakeTime 变量为当前时间xLastWakeTime = xTaskGetTickCount();for (;;){// 等待下一个周期vTaskDelayUntil(&xLastWakeTime, xFrequency);// 在这里执行动作}
}

在这个例子中,xLastWakeTime 被初始化为当前的滴答计数,然后任务会无限循环,每次循环都会调用 vTaskDelayUntil 来延迟到下一个周期。xFrequency 定义了任务执行的频率。

计算实际延迟时间:

portTICK_PERIOD_MS 是一个常量,定义了每个滴答周期的时长(以毫秒为单位)。要计算延迟时间,可以使用以下公式:

const TickType_t xTimeIncrement = desiredTimeInMs / portTICK_PERIOD_MS;

其中 desiredTimeInMs 是希望任务执行的周期(以毫秒为单位)。

 (3)uxTaskPriorityGet

uxTaskPriorityGet 是 FreeRTOS 提供的一个函数,用于获取指定任务的优先级。这个函数可以查询任何任务的优先级,包括调用它的任务。

函数原型:

UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask );

参数:

  • xTask:待查询任务的句柄。如果传递 NULL,则函数返回调用任务的优先级。

返回值:

  • 返回指定任务的优先级。

功能:

  • uxTaskPriorityGet 用于获取任务的当前优先级。
  • 如果任务的优先级在运行时被改变,可以使用这个函数来获取最新的优先级。

注意事项:

  • 在使用 uxTaskPriorityGet 之前,确保在 FreeRTOSConfig.h 中定义了 INCLUDE_uxTaskPriorityGet 为 1,以确保函数被包含在编译中。

用法示例:

以下是一个使用 uxTaskPriorityGet 的示例:

void vTaskFunction(void *pvParameters)
{// ... Task code ...
}void vAFunction(void)
{TaskHandle_t xHandle;// 创建一个任务,并存储句柄xTaskCreate(vTaskFunction, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);// ...// 使用句柄获取创建的任务的优先级// 它被创建时使用的是 tskIDLE_PRIORITY,但可能已经改变了if(uxTaskPriorityGet(xHandle) != tskIDLE_PRIORITY){// 任务已经改变了它的优先级}// ...// 我们的任务优先级是否高于创建的任务?if(uxTaskPriorityGet(xHandle) < uxTaskPriorityGet(NULL)){// 我们的任务优先级(使用 NULL 句柄获得)更高}
}

在这个例子中,vAFunction 函数创建了一个任务,并获取了它的句柄 xHandle。然后,它使用 uxTaskPriorityGet 来检查任务的优先级是否发生了变化。如果传递 NULLuxTaskPriorityGet,它将返回调用任务(即 vAFunction 函数中的当前任务)的优先级。

优先级比较:

  • 优先级数值越低,优先级越高。因此,如果一个任务的优先级数值小于另一个任务的优先级数值,那么它具有更高的优先级。

 (4)vTaskPrioritySet

vTaskPrioritySet 是 FreeRTOS 提供的一个函数,用于动态设置任务的优先级。这个函数允许你在运行时更改任务的优先级,从而可以对任务的执行顺序进行调整。

函数原型:

void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );

参数:

  • xTask:要设置优先级的任务的句柄。如果传递 NULL,则设置调用此函数的任务的优先级。
  • uxNewPriority:要设置的新优先级。这个值必须小于 configMAX_PRIORITIES,这是在 FreeRTOSConfig.h 中定义的系统支持的最大优先级数。

功能:

  • vTaskPrioritySet 用于更改任务的优先级。
  • 如果正在设置的优先级高于当前执行任务的优先级,并且当前任务不是唯一的最高优先级任务,则在函数返回之前会发生上下文切换。

注意事项:

  • 在使用 vTaskPrioritySet 之前,确保在 FreeRTOSConfig.h 中定义了 INCLUDE_vTaskPrioritySet 为 1,以确保函数被包含在编译中。
  • 改变任务优先级可能会影响系统的实时性,因此需要谨慎使用。
  • 如果任务的优先级被提高,它可能会立即抢占其他任务的执行(如果它是当前可运行的最高优先级任务)。
  • 如果任务的优先级被降低,它可能会立即被其他更高优先级的任务抢占。

用法示例:

以下是一个使用 vTaskPrioritySet 的示例:

void vTaskFunction(void *pvParameters)
{for (;;){// 任务代码}
}void vAFunction(void)
{TaskHandle_t xHandle;// 创建一个任务,并存储句柄xTaskCreate(vTaskFunction, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);// ...// 使用句柄提高创建的任务的优先级vTaskPrioritySet(xHandle, tskIDLE_PRIORITY + 1);// ...// 使用 NULL 句柄提高我们自己的优先级到相同的值vTaskPrioritySet(NULL, tskIDLE_PRIORITY + 1);
}

在这个例子中,vAFunction 函数创建了一个任务,并获取了它的句柄 xHandle。然后,它使用 vTaskPrioritySet 来提高任务的优先级。如果传递 NULLvTaskPrioritySet,它将提高调用任务(即 vAFunction 函数中的当前任务)的优先级。

优先级设置:

  • 优先级数值越低,优先级越高。因此,tskIDLE_PRIORITY + 1 表示将任务的优先级提高到比空闲任务更高的级别。

(5)vTaskSuspend:

vTaskSuspend 是 FreeRTOS 提供的一个函数,用于挂起(暂停)一个任务。挂起的任务将无法运行,直到它被另一个任务恢复。

函数原型:

void vTaskSuspend( TaskHandle_t xTaskToSuspend );

参数:

  • xTaskToSuspend:要挂起的任务的句柄。如果传递 NULL,则挂起调用此函数的任务本身。

功能:

  • vTaskSuspend 用于挂起指定的任务。
  • 挂起的任务将从就绪状态列表中移除,并且不会获得任何 CPU 时间,直到它被恢复。
  • 对 vTaskSuspend 的调用不会累积。这意味着即使一个任务被多次挂起,也只需要一次对应的 vTaskResume 调用来恢复它。

注意事项:

  • 在使用 vTaskSuspend 之前,确保在 FreeRTOSConfig.h 中定义了 INCLUDE_vTaskSuspend 为 1,以确保函数被包含在编译中。
  • 挂起一个任务可能会影响系统的实时性,因此需要谨慎使用。
  • 挂起一个任务不会释放它占用的资源,例如内存和堆栈。
  • 挂起一个任务不会影响其他任务的执行,但是需要注意不要永久挂起一个任务,因为它可能持有重要的资源或需要定期执行。

用法示例:

以下是一个使用 vTaskSuspend 的示例:

void vTaskFunction(void *pvParameters)
{for (;;){// 任务代码}
}void vAFunction(void)
{TaskHandle_t xHandle;// 创建一个任务,并存储句柄xTaskCreate(vTaskFunction, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);// ...// 使用句柄挂起创建的任务vTaskSuspend(xHandle);// ...// 创建的任务在这段时间内不会运行,除非// 另一个任务调用 vTaskResume( xHandle )。// ...// 挂起我们自己vTaskSuspend(NULL);// 除非另一个任务调用 vTaskResume 并使用我们的句柄作为参数,// 否则我们无法到达这里。
}

在这个例子中,vAFunction 函数创建了一个任务,并获取了它的句柄 xHandle。然后,它使用 vTaskSuspend 来挂起任务。如果传递 NULLvTaskSuspend,它将挂起调用任务(即 vAFunction 函数中的当前任务)。

挂起和恢复任务:

  • 挂起任务通常用于调试或当任务不再需要执行时。
  • 恢复任务通常由另一个任务或中断服务例程执行,使用 vTaskResume 函数。

 (6)vTaskResume:

vTaskResume 是 FreeRTOS 提供的一个函数,用于恢复之前被挂起的任务。这个函数可以使得因为一次或多次调用 vTaskSuspend() 而停止执行的任务重新获得 CPU 时间。

函数原型:

void vTaskResume( TaskHandle_t xTaskToResume );

参数:

  • xTaskToResume:要恢复的任务的句柄。

功能:

  • vTaskResume 用于恢复一个已经被挂起的任务。
  • 无论任务被挂起了一次还是多次,只需要调用一次 vTaskResume 就可以使其恢复运行。

注意事项:

  • 在使用 vTaskResume 之前,确保在 FreeRTOSConfig.h 中定义了 INCLUDE_vTaskSuspend 为 1,以确保函数被包含在编译中。
  • 恢复一个任务不保证立即执行,任务的实际执行时间取决于任务的优先级和调度器的状态。
  • 如果任务被挂起并且持有重要的资源,恢复该任务可能对系统的实时性有重要影响。

用法示例:

以下是一个使用 vTaskResume 的示例:

void vTaskFunction(void *pvParameters)
{for (;;){// 任务代码}
}void vAFunction(void)
{TaskHandle_t xHandle;// 创建一个任务,并存储句柄xTaskCreate(vTaskFunction, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);// ...// 使用句柄挂起创建的任务vTaskSuspend(xHandle);// ...// 创建的任务在这段时间内不会运行,除非// 另一个任务调用 vTaskResume( xHandle )。// ...// 恢复被挂起的任务vTaskResume(xHandle);// 被挂起的任务将再次获得微控制器的处理时间// 根据其在系统中的优先级。
}

在这个例子中,vAFunction 函数创建了一个任务,并获取了它的句柄 xHandle。然后,它使用 vTaskSuspend 来挂起任务。在某个时刻,它使用 vTaskResume 来恢复任务,使得任务可以重新获得 CPU 时间并继续执行。

挂起和恢复任务:

  • 挂起和恢复任务是管理任务执行流的两种有用机制,特别是在需要临时停止任务或在任务间同步时。
  • 这些操作应该谨慎使用,以避免死锁或不必要的性能开销。

(7)xTaskResumeFromISR:

xTaskResumeFromISR 是 FreeRTOS 提供的一个函数,它允许从中断服务例程(ISR)中恢复一个被挂起的任务。这个函数是 vTaskResume 的 ISR 安全版本,可以在中断上下文中调用。

函数原型:

BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume );

参数:

  • xTaskToResume:要恢复的任务的句柄。

返回值:

  • 如果恢复任务导致上下文切换,则返回 pdTRUE,否则返回 pdFALSE。ISR 使用此信息来确定 ISR 之后是否需要进行上下文切换。

功能:

  • xTaskResumeFromISR 用于从 ISR 中恢复一个被挂起的任务。
  • 与 vTaskResume 相比,xTaskResumeFromISR 可以安全地在中断上下文中使用,因为它是被设计为与 FreeRTOS 的中断锁定机制兼容的。

注意事项:

  • 在 FreeRTOSConfig.h 中,INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 宏必须定义为 1,才能使用 xTaskResumeFromISR 函数。
  • xTaskResumeFromISR 通常被视为“危险”函数,因为它的操作未被锁定,如果中断可能在任务被挂起之前到达,可能会导致中断丢失。因此,它不应该用于同步任务与中断。
  • 为了避免这种可能性,可以使用信号量或者直达任务通知(direct task notifications)。

用法示例:

以下是一个使用 xTaskResumeFromISR 的示例:

TaskHandle_t xHandle;void vAFunction(void)
{// 创建一个任务,并存储句柄xTaskCreate(vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);// ... 其他代码 ...
}void vTaskCode(void *pvParameters)
{// 这个任务被挂起和恢复for (;;){// ... 执行一些功能 ...// 任务挂起自己vTaskSuspend(NULL);// 任务现在被挂起,所以除非 ISR 恢复它,否则不会到达这里}
}void vAnExampleISR(void)
{BaseType_t xYieldRequired;// 恢复被挂起的任务xYieldRequired = xTaskResumeFromISR(xHandle);// 根据需要切换上下文,所以 ISR 返回到不同的任务// 注意:这如何完成取决于你使用的端口。检查你的端口的文档和示例。portYIELD_FROM_ISR(xYieldRequired);
}

在这个例子中,vAFunction 函数创建了一个任务,并获取了它的句柄 xHandle。然后,在 ISR vAnExampleISR 中,使用 xTaskResumeFromISR 来恢复任务,并根据返回值决定是否需要在 ISR 之后进行上下文切换。

上下文切换:

  • xTaskResumeFromISR 返回的值用于确定是否需要在 ISR 结束后进行上下文切换。如果返回 pdTRUE,则调用 portYIELD_FROM_ISR 来请求上下文切换。

 (8)xTaskAbortDelay

xTaskAbortDelay 是 FreeRTOS 提供的一个函数,它用于强制一个正在延迟或阻塞状态的任务立即离开阻塞状态,并进入就绪状态。这个函数可以用于取消任务的 vTaskDelayvTaskDelayUntilulTaskNotifyTakexSemaphoreTake 等阻塞调用。

函数原型:

BaseType_t xTaskAbortDelay( TaskHandle_t xTask );

参数:

  • xTask:要强制退出阻塞状态的任务的句柄。

返回值:

  • BaseType_t:如果操作成功,返回 pdPASS;如果任务不在阻塞状态,返回 pdFAIL

功能:

  • xTaskAbortDelay 可以使任务立即退出延迟或阻塞状态,即使它正在等待的事件还没有发生或者指定的超时时间还没有结束。

注意事项:

  • 在 FreeRTOSConfig.h 中,INCLUDE_xTaskAbortDelay 宏必须定义为 1,才能使用 xTaskAbortDelay 函数。
  • 使用 xTaskAbortDelay 时要小心,因为它会强制任务退出它可能正在等待的重要事件或条件。

用法示例:

以下是一个使用 xTaskAbortDelay 的示例:

void vTaskFunction(void *pvParameters)
{TickType_t xDelayPeriod = 1000 / portTICK_PERIOD_MS;for (;;){// 任务执行一些工作...// 任务进入延迟状态vTaskDelay(xDelayPeriod);// 任务执行更多工作...}
}void vSomeOtherFunction(void)
{TaskHandle_t xTaskHandle;// 创建任务并获取句柄xTaskCreate(vTaskFunction, "Task", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTaskHandle);// ...// 假设我们需要在某个时刻强制任务退出延迟状态if (xTaskAbortDelay(xTaskHandle) == pdPASS){// 任务成功退出延迟状态}else{// 任务不在延迟状态,或者任务句柄无效}// ...
}

在这个例子中,vTaskFunction 是一个任务函数,它在执行一些工作后会调用 vTaskDelay 进入延迟状态。在 vSomeOtherFunction 函数中,我们使用 xTaskAbortDelay 来强制任务退出延迟状态。如果任务成功退出延迟状态,xTaskAbortDelay 返回 pdPASS;如果任务不在延迟状态或者句柄无效,则返回 pdFAIL

 (9)uxTaskPriorityGetFromISR:

uxTaskPriorityGetFromISR 是 FreeRTOS 提供的一个函数,它允许从中断服务例程(ISR)中安全地获取任务的优先级。这个函数是 uxTaskPriorityGet 的 ISR 安全版本,可以在中断上下文中调用。

函数原型:

UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask );

参数:

  • xTask:待查询的任务的句柄。如果传递 NULL,则返回调用此函数的中断服务例程的优先级。

返回值:

  • 返回指定任务的优先级。

功能:

  • uxTaskPriorityGetFromISR 用于在中断服务程序中获取任务的优先级。
  • 这个函数是 ISR 安全的,意味着它不会调用任何可能会被中断锁定机制阻止的 API。

注意事项:

  • 在 FreeRTOSConfig.h 中,INCLUDE_uxTaskPriorityGet 宏必须定义为 1,才能使用 uxTaskPriorityGetFromISR 函数。
  • 与 uxTaskPriorityGet 相比,uxTaskPriorityGetFromISR 可以在中断上下文中安全使用,而 uxTaskPriorityGet 则不能。

用法示例:

以下是一个使用 uxTaskPriorityGetFromISR 的示例:

void vTaskFunction(void *pvParameters)
{for (;;){// 任务代码}
}void vAnExampleISR(void)
{UBaseType_t uxPriority;TaskHandle_t xTaskHandle;// 创建一个任务,并存储句柄xTaskCreate(vTaskFunction, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTaskHandle);// ...// 在 ISR 中获取任务的优先级uxPriority = uxTaskPriorityGetFromISR(xTaskHandle);// 如果我们传递 NULL,我们可以得到调用此 ISR 的任务的优先级// uxPriority = uxTaskPriorityGetFromISR(NULL);
}

在这个例子中,vAnExampleISR 是一个中断服务例程,它使用 uxTaskPriorityGetFromISR 来获取一个任务的优先级。如果传递 NULLuxTaskPriorityGetFromISR,它将返回调用中断服务例程的任务的优先级。

(10)uxTaskBasePriorityGet:

uxTaskBasePriorityGet 是 FreeRTOS 提供的一个函数,用于获取任务的基础优先级。基础优先级是指任务在没有因为互斥锁(mutexes)或其他原因而继承其他任务优先级时的原始优先级。

函数原型:

UBaseType_t uxTaskBasePriorityGet( const TaskHandle_t xTask );

参数:

  • xTask:待查询任务的句柄。如果传递 NULL,则返回调用此函数的任务的基础优先级。

返回值:

  • 返回指定任务的基础优先级。

功能:

  • uxTaskBasePriorityGet 用于获取任务的基础优先级,这是任务在没有继承其他优先级时的原始优先级。

注意事项:

  • 在 FreeRTOSConfig.h 中,INCLUDE_uxTaskPriorityGet 宏必须定义为 1,才能使用 uxTaskBasePriorityGet 函数。
  • 如果你的应用程序使用了互斥锁,configUSE_MUTEXES 宏也必须定义为 1。
  • 基础优先级的概念主要用于处理优先级反转问题。当一个高优先级任务持有一个互斥锁,而一个低优先级任务需要这个互斥锁时,可能会发生优先级反转。为了防止这种情况,低优先级任务可以临时提高其优先级(优先级继承),这样它就可以在不等待高优先级任务释放互斥锁的情况下继续执行。

用法示例:

以下是一个使用 uxTaskBasePriorityGet 的示例:

void vTaskFunction(void *pvParameters)
{// 任务代码
}void vAFunction(void)
{TaskHandle_t xHandle;// 创建一个任务,并存储句柄xTaskCreate(vTaskFunction, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);// ...// 获取并打印创建的任务的基础优先级UBaseType_t uxBasePriority = uxTaskBasePriorityGet(xHandle);printf("Task Base Priority: %lu\n", uxBasePriority);// 如果我们传递 NULL,我们可以得到调用此函数的任务的基础优先级UBaseType_t uxOurBasePriority = uxTaskBasePriorityGet(NULL);printf("Current Task Base Priority: %lu\n", uxOurBasePriority);
}

在这个例子中,vAFunction 函数创建了一个任务,并获取了它的句柄 xHandle。然后,它使用 uxTaskBasePriorityGet 来获取任务的基础优先级,并打印出来。如果传递 NULLuxTaskBasePriorityGet,它将返回调用任务的基础优先级。

(11)uxTaskBasePriorityGetFromISR:

uxTaskBasePriorityGetFromISR 是 FreeRTOS 提供的一个函数,它允许从中断服务例程(ISR)中安全地获取任务的基础优先级。这个函数是 uxTaskBasePriorityGet 的 ISR 安全版本,可以在中断上下文中调用。

函数原型:

UBaseType_t uxTaskBasePriorityGetFromISR( const TaskHandle_t xTask );

参数:

  • xTask:待查询任务的句柄。如果传递 NULL,则返回调用此函数的中断服务例程的任务的基础优先级。

返回值:

  • 返回指定任务的基础优先级。

功能:

  • uxTaskBasePriorityGetFromISR 用于在中断服务程序中获取任务的基础优先级。
  • 基础优先级是指任务在没有因为互斥锁(mutexes)或其他原因而继承其他任务优先级时的原始优先级。

注意事项:

  • 在 FreeRTOSConfig.h 中,INCLUDE_uxTaskPriorityGet 和 configUSE_MUTEXES 宏必须定义为 1,才能使用 uxTaskBasePriorityGetFromISR 函数。
  • 此函数可以安全地在中断上下文中使用,因为它不会调用任何可能会被中断锁定机制阻止的 API。

用法示例:

以下是一个使用 uxTaskBasePriorityGetFromISR 的示例:

void vTaskFunction(void *pvParameters)
{for (;;){// 任务代码}
}void vAnExampleISR(void)
{UBaseType_t uxBasePriority;TaskHandle_t xTaskHandle;// 创建一个任务,并存储句柄xTaskCreate(vTaskFunction, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTaskHandle);// ...// 在 ISR 中获取任务的基础优先级uxBasePriority = uxTaskBasePriorityGetFromISR(xTaskHandle);// 如果我们传递 NULL,我们可以得到调用此 ISR 的任务的基础优先级// uxBasePriority = uxTaskBasePriorityGetFromISR(NULL);
}

在这个例子中,vAnExampleISR 是一个中断服务例程,它使用 uxTaskBasePriorityGetFromISR 来获取一个任务的基础优先级。如果传递 NULLuxTaskBasePriorityGetFromISR,它将返回调用中断服务例程的任务的基础优先级。

 

相关文章:

FreeRTOS保姆级教程(以STM32为例)—任务创建和任务控制API说明

目录 一、任务创建&#xff1a; &#xff08;1&#xff09;TaskHandle_t 任务句柄 &#xff08;2&#xff09; xTaskCreate&#xff1a; 函数原型&#xff1a; 参数说明&#xff1a; 返回值&#xff1a; 示例&#xff1a; 注意事项&#xff1a; 用法示例&#xff1a…...

Go语言现代web开发14 协程和管道

概述 Concurrency is a paradigm where different parts of the program can be executed in parallel without impact on the final result. Go programming supports several concurrency concepts related to concurrent execution and communication between concurrent e…...

Llama3.1的部署与使用

✨ Blog’s 主页: 白乐天_ξ( ✿&#xff1e;◡❛) &#x1f308; 个人Motto&#xff1a;他强任他强&#xff0c;清风拂山冈&#xff01; &#x1f4ab; 欢迎来到我的学习笔记&#xff01; 什么是Llama3.1&#xff1f; Llama3.1 是 Meta&#xff08;原 Facebook&#xff09;公…...

Java/Spring项目的包开头为什么是com?

Java/Spring项目的包开头为什么是com&#xff1f; 下面是一个使用Maven构建的项目初始结构 src/main/java/ --> Java 源代码com.example/ --->为什么这里是com开头resources/ --> 资源文件 (配置、静态文件等)test/java/ --> 测试代码resourc…...

深度学习自编码器 - 随机编码器和解码器篇

序言 在深度学习领域&#xff0c;自编码器作为一种无监督学习技术&#xff0c;凭借其强大的特征表示能力&#xff0c;在数据压缩、去噪、异常检测及生成模型等多个方面展现出独特魅力。其中&#xff0c;随机编码器和解码器作为自编码器的一种创新形式&#xff0c;进一步拓宽了…...

Spring IoC DI

Spring 框架的核心是其控制反转&#xff08;IoC&#xff0c;Inversion of Control&#xff09;和依赖注入&#xff08;DI&#xff0c;Dependency Injection&#xff09;机制。这些概念是为了提高代码的模块化和灵活性&#xff0c;进而简化开发和测试过程。下面将详细介绍这两个…...

[数据集][目标检测]无人机飞鸟检测数据集VOC+YOLO格式6647张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6647 标注数量(xml文件个数)&#xff1a;6647 标注数量(txt文件个数)&#xff1a;6647 标注…...

Vue 中 watch 的使用方法及注意事项

前言 Vue 的 Watch 是一个非常有用的功能&#xff0c;它能够监听 Vue 实例数据的变化并执行相应的操作。本篇文章将详细介绍 Vue Watch 的使用方法和注意事项&#xff0c;让你能够充分利用 Watch 来解决 Vue 开发中的各种问题。 1. Watch 是什么&#xff1f; 1.1 Watch 的作…...

情指行一体化平台建设方案和必要性-———未来之窗行业应用跨平台架构

一、平台建设必要性 以下是情指行一体化平台搭建的一些必要性&#xff1a; 1. 提高响应速度 - 实现情报、指挥和行动的快速协同&#xff0c;大大缩短从信息获取到决策执行的时间&#xff0c;提高对紧急情况和突发事件的响应效率。 2. 优化资源配置 - 整合各类资源信…...

窗口框架frame(HTML前端)

一.窗口框架 作用&#xff1a;将网页分割为多个HTML页面&#xff0c;即将窗口分为多个小窗口&#xff0c;每个小窗口可以显示不同的页面&#xff0c;但是在浏览器中是一个完整的页面 基本语法 <frameset cols"" row""></frameset><frame…...

51单片机——数码管

一、数码管原理图 我们发现&#xff0c;总共有8个数码管。 它们的上面接8个LED&#xff0c;用来控制选择哪个数码管。例如要控制第三个数码管&#xff0c;就让LED6为0&#xff0c;其他为1&#xff0c;那LED又接到哪呢&#xff1f; 二、LED 由图可以看出&#xff0c;这个一个1…...

`re.compile(r“(<.*?>)“)` 如何有效地从给定字符串中提取出所有符合 `<...>` 格式的引用

regexp re.compile(r"(<.*?>)") 这行代码是在Python中使用正则表达式的一个示例&#xff0c;具体含义如下&#xff1a; re.compile(): 这个函数来自Python的 re&#xff08;正则表达式&#xff09;模块&#xff0c;用于将一个正则表达式模式编译成一个正则表…...

算法打卡:第十一章 图论part01

今日收获&#xff1a;图论理论基础&#xff0c;深搜理论基础&#xff0c;所有可达路径&#xff0c;广搜理论基础&#xff08;理论来自代码随想录&#xff09; 1. 图论理论基础 &#xff08;1&#xff09;邻接矩阵 邻接矩阵存储图&#xff0c;x和y轴的坐标表示节点的个数 优点…...

为C#的PetaPoco组件增加一个批量更新功能(临时表模式)

总有一些数据是需要批量更新的&#xff0c;并且更新的字段&#xff0c;每个数据都不一样。 为了实现这样一个功能&#xff0c;写了这样一个方法&#xff1a; using System.Linq.Expressions; using System.Reflection; using System.Text; using NetRube.Data; using PetaPoc…...

Spring实战——入门讲解

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 Spring介绍 Spring实战的入门讲解主要涵盖了Spring框架的基本概念、核心功能以及应用场景。以下是关于Spring实战入门的具体介绍&#xff1a; Spring框架概述&#xff1a;Spring是一个轻量级的Java开发框架…...

MTK芯片机型的“工程固件” 红米note9 5G版资源预览 写入以及改写参数相关步骤解析

小米机型:小米5 小米5x 米6 米6x 米8 米9 米10系列 米11系列 米12系列 mix mix2 mix2s mix3 max max2 max3 note3 8se 9se cc9系列 米play 平板系列等分享 红米机型:红米note4 红米note4x 红米note5 红米note6 红米note7 红米note8 红米note8pro 红米s2 红米note7pro 红米…...

[Golang] Context

[Golang] Context 文章目录 [Golang] Context什么是context创建context创建根context创建context context的作用并发控制context.WithCancelcontext.WithDeadlinecontext.WithTimeoutcontext.WithValue 什么是context Golang在1.7版本中引入了一个标准库的接口context&#xf…...

【JAVA集合总结-壹】

文章目录 synchronized 的实现原理以及锁优化&#xff1f;ThreadLocal原理&#xff0c;使用注意点&#xff0c;应用场景有哪些&#xff1f;synchronized和ReentrantLock的区别&#xff1f;说说CountDownLatch与CyclicBarrier 区别Fork/Join框架的理解为什么我们调用start()方法…...

Mysql梳理7——分页查询

目录 7、分页查询 7.1 背景 7.2 实现规则 分页原理 7.3 使用 LIMIT 的好处 7、分页查询 7.1 背景 背景1&#xff1a;查询返回的记录太多了&#xff0c;查看起来很不方便&#xff0c;怎么样能够实现分页查询呢&#xff1f; 背景2&#xff1a;表里有 4 条数据&#xff0c…...

智能制造与工业互联网公益联播∣企企通副总经理杨华:AI的浪潮下,未来智慧供应链迭代方向

近两年在IT圈子里面&#xff0c;AI毫无疑问是最火的一个词语&#xff0c;最近的ChatGPT、文心一言、通义千问&#xff0c;从千亿参数到万亿参数&#xff0c;再往前就是Sora文生视频异军突起... 在人工智能的浪潮下&#xff0c;AI之于供应链的价值体现在哪些地方&#xff1f;其发…...

《深度学习》—— 卷积神经网络(CNN)的简单介绍和工作原理

文章目录 一、卷积神经网络的简单介绍二、工作原理(还未写完)1.输入层2.卷积层3.池化层4.全连接层5.输出层 一、卷积神经网络的简单介绍 基本概念 定义&#xff1a;卷积神经网络是一种深度学习模型&#xff0c;通常用于图像、视频、语音等信号数据的分类和识别任务。其核心思想…...

数据结构:线性表

1、线性表概述 1.1线性表的定义 线性表&#xff08;list&#xff09;&#xff1a;零个或多个数据元素的有限序列。 简单地来说&#xff0c;我们可以用下面这张图来描述一个线性表&#xff1a; 1.2 线性表的存储结构 1.2.1顺序存储结构——顺序表 顺序表是将数据全部存储到…...

Ansible PlayBook实践案例

一、PlayBook介绍 1.什么是playbook playbook 顾名思义&#xff0c;即剧本&#xff0c;现实生活中演员按照剧本表演&#xff0c;在 ansible 中&#xff0c;由被控计算机表演,进行安装&#xff0c;部署应用&#xff0c;提供对外的服务等&#xff0c;以及组织计算机处理各种各样…...

Tomcat后台弱口令部署war包

1.环境搭建 cd /vulhub/tomcat/tomcat8 docker-compose up -d 一键启动容器 2.访问靶场 点击Manager App tomcat8的默认用户名和密码都是tomcat进行登录 3.制作war包 先写一个js的一句话木马 然后压缩成zip压缩包 最后修改后缀名为war 4.在网站后台上传war文件 上传war文件…...

胤娲科技:DeepMind的FermiNet——带你穿越“薛定谔的早餐桌”

当AI遇上量子迷雾&#xff0c;FermiNet成了你的“量子导航仪” 想象一下&#xff0c;你早晨醒来&#xff0c;发现家里的厨房变成了薛定谔的实验室&#xff0c;你的咖啡杯和吐司同时处于“存在与不存在”的叠加态。 你伸手去拿&#xff0c;却不确定会不会摸到冰冷的空气或是热腾…...

迅为iTOP-STM32MP157开发板板载4G接口(选配)_千兆以太网_WIFI蓝牙模块_HDMI_CAN_RS485_LVDS接口等

迅为ITOP-STM32MP157是基于ST的STM32MP157芯片开发的一款开发平台。在STM32MP157开发平台上&#xff0c;我们也做了比较多的创新&#xff0c;其中重要的一点就是&#xff0c;iTOP-STM32MP157核心板电源管理采用ST全新配套研制的PMIC电源管理芯片STPMU1A。为整个系统的稳定运行提…...

Android Choreographer 监控应用 FPS

Choreographer 是 Android 提供的一个强大的工具类&#xff0c;用于协调动画、绘制和视图更新的时间。它的主要作用是协调应用的绘制过程&#xff0c;以确保流畅的用户体验。Choreographer 也可以帮助我们获取帧时间信息&#xff0c;从而为性能监测和优化提供重要的数据支持。 …...

关于 mybatis-plus-boot-starter 与 mybatis-spring-boot-starter 的错误

不是知道你是否 出现过这样的错误 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): 经过各种度娘&#xff0c;无非就是让你检查三种情况 情况一&#xff1a;mapper.xml没有按照传统的maven架构进行放置 情况二&#xff1a;mybatis的配置信…...

NLP 文本分类任务核心梳理

解决思路 分解为多个独立二分类任务将多标签分类转化为多分类问题更换 loss 直接由模型进行多标签分类 数据稀疏问题 标注更多数据&#xff0c;核心解决方案&#xff1a; 自己构造训练样本 数据增强&#xff0c;如使用 chatGPT 来构造数据更换模型 减少数据需求增加规则弥补…...

k8s中pod的创建过程和阶段状态

管理k8s集群 kubectl k8s中有两种用户 一种是登录的 一种是/sbin/nologin linux可以用密码登录&#xff0c;也可以用证书登录 k8s只能用证书登录 谁拿到这个证书&#xff0c;谁就可以管理集群 在k8s中&#xff0c;所有节点都被网络组件calico设置了路由和通信 所以pod的ip是可以…...