FreeRTOS【10】互斥锁使用

1.开发背景

       FreeRTOS 提供了多线程控制,并且是支持高低优先级抢占,这就意味着低优先级线程在执行任务时有可能被高优先级线程打断,如果两个线程共同操作同一个资源可能会导致不可意料的结果,因此,访问共享内存时需要添加互斥操作,因此互斥锁就有了。

        有人可能会考虑用信号量去实现互斥的功能,实时上也是可以的,FreeRTOS的互斥锁是二值信号量的一个特例,相对于二值信号量,互斥锁会有优先级继承的特性:

        【如果另一个更高优先级的任务尝试获取相同的互斥锁, 则将暂时提高“获取”互斥锁的任务的优先级。 拥有互斥锁的任务 “继承”试图“获取”相同 互斥锁的任务的优先级。 这意味着必须始终“归还”互斥锁,否则 优先级较高的任务将始终无法获得互斥锁,而优先级较低 的始终无法“取消继承”优先级。】

2.开发需求

设计实验1:利用互斥锁实现资源保护

        1)创建低优先级和高优先级线程

        2)低优先级线程先 100ms 获取互斥锁,在互斥锁期间 1000ms 后释放互斥锁

        3)高优先级线程后 100ms 尝试获取互斥锁

设计实验2:验证优先级继承现象

        1)创建低优先级和高优先级线程

        2)低优先级线程取锁后获取当前线程优先级

        3)低优先级线程等待高优先级线程取锁后,获取当前线程优先级

        4)等待高优先级线程获取互斥锁后,再获取当前线程优先级

3.开发环境

        window10 + MDK + STM32F429 + FreeRTOS10.3.1

4.实现步骤

4.1 互斥锁资源保护

4.1.1 软件编码
#include "appTest.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "mspDwt.h"
#include "mspGpio.h"
#include "mspExti.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#include "appLog.h"

typedef struct
{
    /* 信号量 */
    SemaphoreHandle_t lock;     // 信号锁
    
    /* 创建任务 */
    TaskHandle_t taskLow;       // 低优先级线程
    TaskHandle_t taskHigh;      // 高优先级线程
    
}Ctrl_t;

/* 文件指针 */
static Ctrl_t s_ctrl = {0};
static Ctrl_t *p = &s_ctrl;
static void TaskLow(void *pvParameters);
static void TaskHigh(void *pvParameters);

/* 接收线程 */
static void TaskLow(void *pvParameters)
{
    vTaskDelay(100);
    
    for ( ; ; )
    {
        /* 取锁 */
        xSemaphoreTake(p->lock, portMAX_DELAY);
        Log_Debug("%s 取锁成功\r\n", __func__);
        
        /* 等待高优先级线程取锁 */
        vTaskDelay(1000);
        
        Log_Debug("%s 解锁成功\r\n", __func__);
        xSemaphoreGive(p->lock);
    }
}

/* 发送线程 */
static void TaskHigh(void *pvParameters)
{
    vTaskDelay(200);
    
    for ( ; ; )
    {
        xSemaphoreTake(p->lock, portMAX_DELAY);
        Log_Debug("%s 取锁成功\r\n", __func__);
        
        vTaskDelay(1000);
        
        Log_Debug("%s 解锁成功\r\n", __func__);
        xSemaphoreGive(p->lock);
        
        vTaskDelay(100);
    }
}

/* 测试初始化 */
void aTest_Init(void)
{
    /* 创建信号锁 */
    p->lock = xSemaphoreCreateMutex();
    
    /* 创建动态任务 */
    xTaskCreate(TaskLow,  "TaskLow",   500, NULL, 4, &p->taskLow);
    xTaskCreate(TaskHigh, "TaskHigh",  500, NULL, 5, &p->taskHigh);
}

/* Key2 PC13   Key0 PH3 Key1 PH2 */
void Exti13_TriggerInterrupt(void)
{
    mspExti_Close(13);
    
    if (mspGpio_GetInput("PC13") == 0)
    {
        
    }
}


4.1.2 结果显示

4.2 互斥锁优先级继承

4.2.1 软件编码
#include "appTest.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "mspDwt.h"
#include "mspGpio.h"
#include "mspExti.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#include "appLog.h"

typedef struct
{
    /* 信号量 */
    SemaphoreHandle_t lock;     // 信号锁
    
    /* 创建任务 */
    TaskHandle_t taskLow;       // 低优先级线程
    TaskHandle_t taskHigh;      // 高优先级线程
    
}Ctrl_t;

/* 文件指针 */
static Ctrl_t s_ctrl = {0};
static Ctrl_t *p = &s_ctrl;
static void TaskLow(void *pvParameters);
static void TaskHigh(void *pvParameters);

/* 接收线程 */
static void TaskLow(void *pvParameters)
{
    vTaskDelay(100);
    UBaseType_t priority = 0;
    
    for ( ; ; )
    {
        /* 取锁前查看一下线程优先级 */
        priority = uxTaskPriorityGet(NULL);
        Log_Debug("%s 低优先级线程取锁前查看优先级 priority = %d\r\n", __func__, priority);
        
        /* 取锁 */
        xSemaphoreTake(p->lock, portMAX_DELAY);
        Log_Debug("%s 取锁成功\r\n", __func__);
        
        /* 取锁前查看一下线程优先级 */
        priority = uxTaskPriorityGet(NULL);
        Log_Debug("%s 低优先级线程取锁后查看优先级 priority = %d\r\n", __func__, priority);
        
        /* 等待高优先级线程取锁 */
        vTaskDelay(1000);
        
        /* 查看线程优先级 */
        priority = uxTaskPriorityGet(NULL);
        Log_Debug("%s 低优先级线程等高优先级线程取锁后查看优先级 priority = %d\r\n", __func__, priority);
        
        xSemaphoreGive(p->lock);
    }
}

/* 发送线程 */
static void TaskHigh(void *pvParameters)
{
    vTaskDelay(200);
    
    for ( ; ; )
    {
        xSemaphoreTake(p->lock, portMAX_DELAY);
        Log_Debug("%s 取锁成功\r\n", __func__);
        
        vTaskDelay(1000);
        
//        xSemaphoreGive(p->lock);
    }
}

/* 测试初始化 */
void aTest_Init(void)
{
    /* 创建信号锁 */
    p->lock = xSemaphoreCreateMutex();
    
    /* 创建动态任务 */
    xTaskCreate(TaskLow,  "TaskLow",   500, NULL, 4, &p->taskLow);
    xTaskCreate(TaskHigh, "TaskHigh",  500, NULL, 5, &p->taskHigh);
}

/* Key2 PC13   Key0 PH3 Key1 PH2 */
void Exti13_TriggerInterrupt(void)
{
    mspExti_Close(13);
    
    if (mspGpio_GetInput("PC13") == 0)
    {
    }
}


4.2.2 结果显示

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FreeRTOS中,互斥锁用于保护共享资源,防止多个线程同时访问共享资源而引发的竞争条件。互斥锁使用步骤如下: 1. 定义互斥锁变量和互斥锁句柄:在代码中先定义一个互斥锁变量和一个互斥锁句柄,例如: ``` osMutexId resource_mutex = NULL; // 定义互斥锁句柄 osMutexDef(resource_mutex); // 定义互斥锁变量 ``` 2. 创建互斥锁:在初始化函数中创建互斥锁,例如: ``` void resource_mutex_init(void) { resource_mutex = osMutexCreate(osMutex(resource_mutex)); } ``` 3. 获取互斥锁:在需要使用共享资源的函数中,首先获取互斥锁,例如: ``` void function(void) { resource_mutex_acquire(); // 获取互斥锁 // 操作共享资源 resource_mutex_release(); // 释放互斥锁 } ``` 总结:在FreeRTOS中,使用互斥锁的步骤包括定义互斥锁变量和句柄、创建互斥锁、获取互斥锁以及释放互斥锁。通过这些步骤,可以确保多个线程对共享资源的安全访问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [freertos互斥锁使用](https://blog.csdn.net/weixin_45379397/article/details/130604913)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [【FreeRTOS互斥锁使用](https://blog.csdn.net/qq_43581670/article/details/127688331)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值