【TencentOS】互斥量

(二)任务间通信

1) 互斥量

互斥量又称互斥锁,一般用于共享资源的互斥排他性访问保护。
互斥量在任意时刻处于且仅会处于解锁或锁定状态,当一个任务获取到一把锁后(互斥量锁定),其他任务再尝试获得这把锁时会失败或进入阻塞状态,当该任务释放持有的锁时(互斥量解锁),会唤醒一个正阻塞等待此互斥量的任务,被唤醒的任务将会获取这把锁。
在多任务运行环境中,有些共享资源不具有多线程可重入性,对于这类不希望被多任务同时访问的资源(临界资源),可以采用互斥量来进行保护,后面的编程实例章节会演示这一编程范式。

互斥量mutex
tos_mutex_create
k_err_t tos_mutex_create(k_mutex_t *mutex);
• 功能描述
创建一个互斥量。
• 参数解释
IN/OUT 参数名 描述
[in] mutex 互斥量句柄
• 返回值
K_ERR_NONE 互斥量创建成功。
K_ERR_OBJ_PTR_NULL mutex为空指针。
tos_mutex_destroy
k_err_t tos_mutex_destroy(k_mutex_t *mutex);
• 功能描述
销毁一个互斥量。
• 参数解释
IN/OUT 参数名 描述
[in] mutex 互斥量句柄
• 返回值
K_ERR_NONE 互斥量销毁成功。
K_ERR_OBJ_PTR_NULL mutex为空指针。
K_ERR_OBJ_INVALID mutex指向的不是一个合法的互斥量。
tos_mutex_pend
k_err_t tos_mutex_pend(k_mutex_t *mutex);
• 功能描述
尝试获取一个互斥量(永久阻塞式等待)。
• 参数解释
IN/OUT 参数名 描述
[in] mutex 互斥量句柄
• 返回值
K_ERR_NONE 获取互斥量成功。
K_ERR_MUTEX_NESTING_OVERFLOW 互斥量拥有者嵌套获取溢出。
K_ERR_MUTEX_NESTING 互斥量拥有者嵌套获取。
K_ERR_PEND_SCHED_LOCKED 此互斥量被其他任务持有,且系统调度处于锁定状态。
K_ERR_PEND_DESTROY 当前任务试图获取的互斥量被销毁(tos_mutex_destroy)了。
tos_mutex_pend_timed
k_err_t tos_mutex_pend(k_mutex_t *mutex, k_tick_t timeout);
• 功能描述
尝试获取一个互斥量(有限时间内的阻塞等待)。
• 参数解释
IN/OUT 参数名 描述
[in] mutex 互斥量句柄
[in] timeout 等待超时参数
• 返回值
K_ERR_NONE 获取互斥量成功。
K_ERR_MUTEX_NESTING_OVERFLOW 互斥量拥有者嵌套获取溢出。
K_ERR_MUTEX_NESTING 互斥量拥有者嵌套获取。
K_ERR_PEND_NOWAIT 此互斥量被其他任务持有,同时timeout参数为TOS_TIME_NOWAIT(表示获取不到互斥量时立即返回)
K_ERR_PEND_SCHED_LOCKED 此互斥量被其他任务持有(获取失败),且系统调度处于锁定状态。
K_ERR_PEND_TIMEOUT 在timeout时间范围内未获取到互斥量。
K_ERR_PEND_DESTROY 当前任务试图获取的互斥量被销毁(tos_mutex_destroy)了。
tos_mutex_post
k_err_t tos_mutex_post(k_mutex_t *mutex);
• 功能描述
释放互斥量。
• 参数解释
IN/OUT 参数名 描述
[in] mutex 互斥量句柄
• 返回值
K_ERR_NONE 互斥量释放成功。
K_ERR_MUTEX_NOT_OWNER 当前任务并非此互斥量的拥有者。
K_ERR_MUTEX_NESTING_OVERFLOW 互斥量拥有者嵌套释放溢出。
K_ERR_MUTEX_NESTING 互斥量拥有者嵌套释放。

程序实例:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "string.h"
#include "cmsis_os.h"
#include "tos.h"		

//定义相关堆栈大小
#define STK_SIZE_TASK_WRITER		512	
#define STK_SIZE_TASK_READER		512	 

//定义任务堆栈
k_stack_t stack_task_writer[STK_SIZE_TASK_WRITER];
k_stack_t stack_task_reader[STK_SIZE_TASK_READER];

//任务体
k_task_t task_write;
k_task_t task_read;

//任务函数
void write_task(void *arg);
void read_task(void *arg);

//定义互斥任务锁
k_mutex_t critical_resource_locker;

static char resource[10];

static void write_sth(void)
{
   u8 i=0;
	 printf("\r\nwrite something\r\n");
   for(i=0;i<=9;i++)
	{
		printf("write: %d\r\n",i);
		resource[i]=i;
	}
}

static void read_sth(void)
{
   u8 i=0;
	 printf("\r\nread something\r\n");
   for(i=0;i<=9;i++)
	{
		printf("read: %d\r\n",resource[i]);
	}
}

void write_task(void *arg)
{
	 k_err_t err;
   while(1)
	 {
				 //尝试获取保护锁
				 err=tos_mutex_pend(&critical_resource_locker);	          
				 if (err == K_ERR_NONE) 
					 {
								// 成功获取锁之后,向临界区写入数据
								write_sth();
								// 写完数据后,释放互斥锁
								tos_mutex_post(&critical_resource_locker);
						}
					 else
					 {
						 printf("\r\nwrite:the target is being visited");
					 }
					tos_task_delay(100);
	  }

}

void read_task(void *arg)
{
	k_err_t err;
	while(1)
	{
	      // 读取临界区数据之前,先尝试获取临界区保护锁
        err = tos_mutex_pend(&critical_resource_locker);
        if (err == K_ERR_NONE) {
            // 成功获取锁之后,从临界区读取数据
            read_sth();
            // 读取数据完毕后,释放互斥锁
            tos_mutex_post(&critical_resource_locker);
        }
						else
					 {
						 printf("\r\nwrite:the target is being visited");
					 }
        tos_task_delay(100);	
	}
}




int main(void)
{
    
    HAL_Init();                     //初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
    uart_init(115200);              //初始化USART
    LED_Init();                     //初始化LED 
    KEY_Init();                     //初始化按键
	LCD_Init();  
    tos_knl_init();
	tos_mutex_create(&critical_resource_locker);
    (void)tos_task_create(&task_write,                   //任务体指针
                    	"write_task",                  //任务名
		                 write_task,                   //任务函数入口
                         NULL  ,                       //入口参数
						 1,                            //任务优先级
                         stack_task_writer,            //任务堆栈起始地址
						 STK_SIZE_TASK_WRITER,         //堆栈大小
						 0                             //时间片大小
													);

	  (void)tos_task_create(&task_read,                     //任务体指针
                    	 "read_task",                    //任务名
		                  read_task,                     //任务函数入口
                          NULL,                          //入口参数
						  2,                             //任务优先级
                          stack_task_reader,             //任务堆栈起始地址
						  STK_SIZE_TASK_READER,          //堆栈大小
						  0                              //时间片大小
													);
			
		
    tos_knl_start();
	while(1)
	{}
	 
}
			

实验现象:
两个函数一个写,一个读
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

与光同程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值