FreeRTOS Mutex意外行为


#include "main.h"
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
void Task1(void *argument);
void Task2(void *argument);
void PrintMsg(char *data);
/* USER CODE BEGIN PFP */
SemaphoreHandle_t hMutex = NULL;
TaskHandle_t hTask1 = NULL;
TaskHandle_t hTask2 = NULL;
UART_HandleTypeDef huart2;
int main(void) {
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
xTaskCreate(Task1, "Task 1", configMINIMAL_STACK_SIZE, NULL, 2, &hTask1);
xTaskCreate(Task2, "Task 2", configMINIMAL_STACK_SIZE, NULL, 2, &hTask2);
/* USER CODE END 2 */
hMutex = xSemaphoreCreateMutex();
if (hMutex == NULL) {
PrintMsg("Mutex not createdrn");
} else {
PrintMsg("Mutex createdrn");
}
vTaskStartScheduler();
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

void Task1(void *argument) {
/* USER CODE BEGIN 5 */
/* Infinite loop */
for (;;) {
if (xSemaphoreTake(hMutex,2000) == pdTRUE) {
PrintMsg("Shared Resource Start and Executing Task 1rn");
xSemaphoreGive(hMutex);
PrintMsg("Shared Resource End and Executing Task 1rn");
vTaskDelay(100);
} else {
PrintMsg("Task 1 Didn't get access to shared resourcern");
}
}
/* USER CODE END 5 */
}

void Task2(void *argument) {
/* USER CODE BEGIN 5 */
/* Infinite loop */
for (;;) {
if (xSemaphoreTake(hMutex,2000) == pdTRUE) {
PrintMsg("Shared Resource Start and Executing Task 2rn");
//xSemaphoreGive(hMutex);
PrintMsg("Shared Resource End and Executing Task 2rn");
vTaskDelay(100);
} else {
PrintMsg("Task 2 Didn't get access to shared resourcern");
}
}
/* USER CODE END 5 */
}

void PrintMsg(char *data) {
int i = 0;
while (*(data + i) != '') {
HAL_UART_Transmit(&huart2, (uint8_t*) &data[i], 1, 0xFF);
i++;
}
}

HW使用:STM32F446RE

当我运行这段代码时,我得到如下输出

//输出开始

创建互斥对象

共享资源启动并执行任务1

共享资源结束并执行任务1

任务2无法访问共享资源

任务1任务2无法访问共享资源

任务1无法访问共享资源

Task 2无法访问共享资源..

//输出端

问题1)

考虑Task1优先调度,因为Task1和task2的优先级相同。Task1执行正确

在此之后,Task2被调度,但无法接受互斥锁,因为我得到的输出为"任务2没有访问共享资源"。为什么会这样呢?

问题2)

任务1任务2无法访问共享资源在这一行中,Task1似乎正在执行,但它被Task2抢占了,这应该不会发生,因为两个任务具有相同的优先级??

Q1:这里可能的解释是,您被相互竞争的任务所愚弄,这些任务覆盖了彼此的缓冲UART输出。UART很慢,任务切换很快:)

Task1打印"共享资源启动和执行任务1";并且第一次释放互斥锁,调度器立即切换到Task2(可能是因为Task1已经用完了它的时隙?)Task2获取互斥锁,迅速将其两个消息吐到UART缓冲区中,并进入睡眠100个节拍。调度器立即切换回Task1,但不幸的是,来自Task2的缓冲消息还没有到达UART输出。UART缓冲区被消息"共享资源结束并执行任务1"覆盖。在输出Task2-s消息的单个字节之前。

之后,整个进程停止,因为你没有释放Task2中的互斥锁。

Q2:当调度程序决定这样做时,具有相同优先级的任务会被彼此抢占(通常当它们进入睡眠或耗尽其时间段时)

我推荐这本教程/书,第3章很好地解释了任务是如何工作的。

USART是一个资源,所以如果没有同步机制(如互斥锁),它不能被两个任务共享。您对PrintMsg()的使用违反了此规则。

调度程序以configTICK_RATE_HZ频率运行。如果configUSE_TIME_SLICING1(或未定义),调度程序在同等优先级的任务之间切换。如果您不想要这种默认行为,请将configUSE_TIME_SLICING设置为0

请记住,configTICK_RATE_HZ设置的1000给每个任务最多1毫秒的运行时间,除非没有其他任务准备运行。更高优先级的任务也可以在1毫秒通过之前抢占它。在115200波特率下,您可以在这~1 ms的时间周期内发送~10字节左右。

相关内容

  • 没有找到相关文章

最新更新