HarmonyOS小熊派 | HarmonyOS内核编程开发—互斥锁

BearPi-HM_Nano开发板HarmonyOS内核编程开发——互斥锁

本示例将演示如何在BearPi-HM_Nano开发板上使用cmsis 2.0 接口使用互斥来同步任务

BearPi-HM_Nano

Mutex API分析

osMutexNew()

osMutexId_t osMutexNew(const osMutexAttr_t *attr)

描述:

函数osMutexNew创建并初始化一个新的互斥锁对象,并返回指向互斥锁对象标识符的指针,如果出现错误则返回NULL可以在RTOS启动(调用 osKernelStart)之前安全地调用该函数,但不能在内核初始化 (调用 osKernelInitialize)之前调用该函数。

注意 :不能在中断服务调用该函数

参数:

名字 描述
attr 互斥对象的属性.

osMutexAcquire()

osStatus_t osMutexAcquire(osMutexId_t mutex_id,uint32_t timeout)

描述: 函数osMutexAcquire一直等待,直到参数mutex_id指定的互斥对象可用为止。如果没有其他线程获得互斥锁,该函数立即返回并阻塞互斥锁对象。

注意 :不能在中断服务调用该函数

参数:

名字 描述
mutex_id 通过osMutexNew获得互斥锁ID.
timeout 超时值.

osMutexRelease()

osStatus_t osMutexRelease(osMutexId_t mutex_id)

描述: 函数osMutexRelease释放一个由参数mutex_id指定的互斥量。当前等待这个互斥锁的其他线程将被置于就绪状态。

注意 :不能从中断服务例程调用此函数。

参数:

名字 描述
mutex_id 通过osMutexNew获得互斥锁ID.

软件设计

主要代码分析

在Mutex_example函数中,通过osMutexNew()函数创建了互斥锁ID,并创建的三个不同优先级的任务,在第一秒,高优先级和中优先级线程被延迟。因此,低优先级线程可以启动自己的工作,获得互斥锁并在持有它时延迟。在第一秒之后,高优先级和中优先级线程就准备好了。因此高优先级线程获得优先级并尝试获取互斥锁。因为互斥锁已经被低优先级线程所拥有,所以高优先级线程被阻塞,中间优先级线程被执行,并开始执行许多非阻塞的工作,3S后低优先级释放互斥锁,高优先级线程准备就绪并立即被调度。

mutex_yuchuan_example.c

#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"

#define GPIO_LED 2

osMutexId_t mutex_id;

void highPrioThread(void)
{
    osStatus_t status;

    osDelay(100U);
    while (1)
    {
        /* code */
        status = osMutexAcquire(mutex_id,osWaitForever);
        if (status != osOK)
        {
            /* code */
            printf("acquire mutex fialed !!!\n");
        }
        else
        {
            printf("acquire mutex success!!\n");
        }

        printf("HightPrioThread is Runing!!!\n");
        //设置GPIO为高电平输出,点亮LED灯
        IoTGpioSetOutputVal(GPIO_LED,IOT_GPIO_VALUE1);

        osDelay(300U);
        status = osMutexRelease(mutex_id);
        if (status != osOK)
        {
            /* code */
            printf("release mutex fialed!!!\n");
        }
        else
        {
            printf("release mutex success!!!\n");
        }
        
    }
    
}

void midPrioThread(void)
{
    osDelay(100U);

    while (1)
    {
        /* code */
        printf("MidPrioThread is Runing!!!\n");
        osDelay(100);
    }
    
}

void lowPrioThread(void)
{
    osStatus_t status;

    while (1)
    {
        /* code */
        status = osMutexAcquire(mutex_id,osWaitForever);
        if (status != osOK)
        {
            /* code */
            printf("acquire mutex fialed!!!\n");
        }
        else
        {
            printf("acquire mutex success!!!\n");
        }
        

        printf("LowPrioThread is Runing!!!\n");
        //设置GPIO为低电平输出,熄灭LED灯
        IoTGpioSetOutputVal(GPIO_LED,IOT_GPIO_VALUE0);

        osDelay(300U);
        status = osMutexRelease(mutex_id);
        if (status != osOK)
        {
            /* code */
            printf("release mutex fialed!!!\n");
        }
        else
        {
            printf("release mutex success!!!\n");
        }
        
    }
    
}

static void yuchuanMutexExample(void)
{
    osStatus_t status;
    //初始化GPIO
    IoTGpioInit(GPIO_LED);

    //设置GPIO的方向
    IoTGpioSetDir(GPIO_LED,IOT_GPIO_DIR_OUT);

    osThreadAttr_t attr;
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024 * 4;

    attr.name = "HighPrioThread";
    attr.priority = 26;
    if (osThreadNew((osThreadFunc_t)highPrioThread,NULL,&attr) == NULL)
    {
        /* code */
        printf("Fialed to Create HighPrioThread !!!\n");
    }
    
    attr.name = "MidPrioThread";
    attr.priority = 25;
    if (osThreadNew((osThreadFunc_t)midPrioThread,NULL,&attr) == NULL)
    {
        /* code */
        printf("Fialed to Create MidPrioThread !!!\n");
    }
    
    attr.name = "LowPrioThread";
    attr.priority = 24;
    if (osThreadNew((osThreadFunc_t)lowPrioThread,NULL,&attr) == NULL)
    {
        /* code */
        printf("Fialed to Create LowPrioThread !!!\n");
    }
    
    mutex_id = osMutexNew(NULL);
    if(mutex_id == NULL)
    {
        printf("Fialed to Create Mutex !!!\n");
    }

    status = osMutexDelete(mutex_id);
    if (status != osOK)
    {
        /* code */
        printf("Delete Mutex Fialed!!!\n");
    }
    else
    {
        printf("Delete Mutex Success!!!\n");
    }
    
    status = osMutexDelete(mutex_id);
    if (status != osOK)
    {
        /* code */
        printf("Delete Mutex Fialed!!!\n");
    }
    else
    {
        printf("Delete Mutex Success!!!\n");
    }
}

APP_FEATURE_INIT(yuchuanMutexExample);

编译调试

applications/sample/BearPi/BearPi-HM_Nano/sample/A4_YuchuanMutex/BUILD.gn

static_library("yuchuanMutex"){
    sources = [
        "mutex_yuchuan_example.c",
    ]

    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/kal/cmsis",
        "//base/iot_hardware/peripheral/interfaces/kits",
    ]
}

修改 BUILD.gn 文件

修改 applications\BearPi\BearPi-HM_Nano\sample路径下 BUILD.gn 文件,指定 yuchuanMutex 参与编译。

# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import("//build/lite/config/component/lite_component.gni")

lite_component("sample") {
    features = [
        #"A1_kernal_thread:thread_example",
        #"A2_kernel_timer:timer_example",
        #"A3_kernel_event:event_example",
        #"A4_kernel_mutex:mutex_example",
        #"A5_kernel_semaphore:semaphore_example",
        #"A6_kernel_message:message_example",

        #"B1_basic_led_blink:led_example",
        #"B2_basic_button:button_example",
        #"B3_basic_pwm_led:pwm_example",
        #"B4_basic_adc:adc_example", 
        #"B5_basic_i2c_nfc:i2c_example",
        #"B6_basic_uart:uart_example",
        
        #"C1_e53_sf1_mq2:e53_sf1_example",
        #"C2_e53_ia1_temp_humi_pls:e53_ia1_example",
        #"C3_e53_sc1_pls:e53_sc1_example",
        #"C4_e53_sc2_axis:e53_sc2_example",
        #"C5_e53_is1_infrared:e53_is1_example",

        #"D1_iot_wifi_ap:wifi_ap",
        #"D2_iot_wifi_sta_connect:wifi_sta_connect",        
        #"D3_iot_udp_client:udp_client",
        #"D4_iot_tcp_server:tcp_server",
        #"D5_iot_mqtt:iot_mqtt",        
        #"D6_iot_cloud_oc:oc_mqtt",
        #"D7_iot_cloud_onenet:onenet_mqtt",
        #"D8_iot_cloud_oc_smoke:cloud_oc_smoke",
        #"D9_iot_cloud_oc_light:cloud_oc_light",
        #"D10_iot_cloud_oc_manhole_cover:cloud_oc_manhole_cover",
        #"D11_iot_cloud_oc_infrared:cloud_oc_infrared",
        #"D12_iot_cloud_oc_agriculture:cloud_oc_agriculture",
        #"D13_iot_cloud_oc_gps:cloud_oc_gps",
        #"A1_YuchuanThread:yuchuanThread",
        #"A2_YuchuanTimer:yuchuanTimer",
        "A4_YuchuanMutex:yuchuanMutex",
    ]
}

运行结果

示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,中优先级任务一直正常运行,而高优先级和低优先级的任务因为互相抢占互斥锁,交替运行。

ready to OS start
sdk ver:Hi3861V100R001C00SPC025 2020-09-03 18:10:00
formatting spiffs...
FileSystem mount ok.
wifi init success!

hiview init success.Delete Mutex Success!!!
Delete Mutex Fialed!!!
00 00:00:00 0 132 D 0/HIVIEW: log limit init success.
00 00:00:00 0 132 I 1/SAMGR: Bootstrap core services(count:3).
00 00:00:00 0 132 I 1/SAMGR: Init service:0x4b0348 TaskPool:0xe4b3c
00 00:00:00 0 132 I 1/SAMGR: Init acquire mutex fialed!!!
LowPrioThread is Runing!!!
service:0x4b0354 TaskPool:0xe4b5c
00 00:00:00 0 132 I 1/SAMGR: Init service:0x4b0820 TaskPool:0xe4b7c
00 00:00:00 0 164 I 1/SAMGR: Init service 0x4b0354 <time: 10ms> success!
00 00:00:00 0 64 I 1/SAMGR: Init service 0x4b0348 <time: 10ms> success!
00 00:00:00 0 8 I 1/SAMGR: Init service 0x4b0820 <time: 10ms> success!
00 00:00:00 0 8 I 1/SAMGR: Initialized all core system services!
00 00:00:00 0 64 I 1/SAMGR: Bootstrap system and application services(count:0).
00 00:00:00 0 64 I 1/SAMGR: Initialized all system and application services!
00 00:00:00 0 64 I 1/SAMGR: Bootstrap dynamic registered services(count:0).
acquire mutex fialed !!!
HightPrioThread is Runing!!!
MidPrioThread is Runing!!!
MidPrioThread is Runing!!!
MidPrioThread is Runing!!!
release mutex fialed!!!
acquire mutex fialed!!!
LowPrioThread is Runing!!!
release mutex fialed!!!
acquire mutex fialed !!!
HightPrioThread is Runing!!!
MidPrioThread is Runing!!!
MidPrioThread is Runing!!!
MidPrioThread is Runing!!!
release mutex fialed!!!
acquire mutex fialed!!!
LowPrioThread is Runing!!!
release mutex fialed!!!
acquire mutex fialed !!!
HightPrioThread is Runing!!!
MidPrioThread is Runing!!!
MidPrioThread is Runing!!!
MidPrioThread is Runing!!!
release mutex fialed!!!
acquire mutex fialed!!!
LowPrioThread is Runing!!!
release mutex fialed!!!
acquire mutex fialed !!!
HightPrioThread is Runing!!!
MidPrioThread is Runing!!!
MidPrioThread is Runing!!!
MidPrioThread is Runing!!!
release mutex fialed!!!
acquire mutex fialed!!!
LowPrioThread is Runing!!!
release mutex fialed!!!
acquire mutex fialed !!!
(完)