【TencentOS】信号量

2)信号量
信号量是一种实现任务间同步的机制,一般用于多个任务间有限资源竞争访问。
通常来说,一个信号量中持有一个整形数值,用以表示可用资源的数量。当一个信号量的可用资源数量大于0时,任务尝试获取该信号量成功,信号量的可用资源数减一;当一个信号量的可用资源数等于0时,任务尝试获取该信号量失败或进入阻塞状态。信号量的这一模式,当可用资源数为1时,可将其用于资源的互斥访问;或者解决生产者-消费者问题中的资源生产-消费问题。编程实例章节会演示生产者-消费者问题的解决范式。

信号量semaphore
tos_sem_create
k_err_t tos_sem_create(k_sem_t *sem, k_sem_cnt_t init_count);
• 功能描述
创建一个信号量。
• 参数解释
IN/OUT 参数名 描述
[in] sem 信号量句柄
[in] init_count 信号量初始量
• 返回值
K_ERR_NONE 信号量创建成功。
K_ERR_OBJ_PTR_NULL sem指针为空。
tos_sem_destroy
k_err_t tos_sem_destroy(k_sem_t *sem);
• 功能描述
销毁一个信号量。
• 参数解释
IN/OUT 参数名 描述
[in] sem 信号量数据结构指针
• 返回值
K_ERR_NONE 信号量销毁成功。
K_ERR_OBJ_INVALID sem指向的不是一个合法的信号量。
K_ERR_OBJ_PTR_NULL sem指针为空。
tos_sem_pend
k_err_t tos_sem_pend(k_sem_t *sem, k_tick_t timeout);
• 功能描述
尝试获取一个信号量。
• 参数解释
IN/OUT 参数名 描述
[in] sem 信号量句柄
[in] timeout 等待超时参数
• 返回值
K_ERR_NONE 获取信号量成功。
K_ERR_PEND_NOWAIT 获取信号量失败(信号量资源不足),同时timeout参数为TOS_TIME_NOWAIT(表示获取不到信号量时立即返回)
K_ERR_PEND_SCHED_LOCKED 获取信号量失败,同时系统调度处于锁定状态。
K_ERR_PEND_TIMEOUT 在timeout超时范围内未获取到信号量。
K_ERR_PEND_DESTROY 试图获取的信号量被销毁了(tos_sem_destroy)
tos_sem_post
k_err_t tos_sem_post(k_sem_t *sem);
• 功能描述
释放信号量,并唤醒等待队列上的一个任务。如果有多个任务在此信号量的等待队列上,唤醒优先级最高的任务。
• 参数解释
IN/OUT 参数名 描述
[in] sem 信号量句柄
• 返回值
K_ERR_NONE 信号量释放成功。
K_ERR_SEM_OVERFLOW 信号量值溢出。
tos_sem_post_all
k_err_t tos_sem_post_all(k_sem_t *sem);
• 功能描述
释放信号量,并唤醒等待队列上的所有任务。
• 参数解释
IN/OUT 参数名 描述
[in] sem 信号量句柄
• 返回值
K_ERR_NONE 信号量释放成功。
K_ERR_SEM_OVERFLOW 信号量值溢出。

其实就是反应资源的多少,比如我们经常会遇到的图像采集与显示,可以通过这个方法来同步

编程实例:

#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_PRODUCER      512
#define STK_SIZE_TASK_CONSUMER      512

k_stack_t stack_task_producer[STK_SIZE_TASK_PRODUCER];
k_stack_t stack_task_consumer[STK_SIZE_TASK_CONSUMER];

k_task_t task_producer;
k_task_t task_consumer;

extern void entry_task_producer(void *arg);
extern void entry_task_consumer(void *arg);

k_mutex_t buffer_locker;
k_sem_t   full;
k_sem_t   empty;

#define RESOURCE_COUNT_MAX      3

struct resource_st {
    int cursor;
    uint32_t buffer[RESOURCE_COUNT_MAX];
} resource = { 0, {0} };

static void produce_item(int salt)
{
    printf("produce item:");
    printf("%d\n", salt);
    resource.buffer[resource.cursor++] = salt;
    printf("\n");
}

void entry_task_producer(void *arg)
{
    size_t salt = 0;
    k_err_t err;

    while (1)
		{
		  
        err = tos_sem_pend(&empty, TOS_TIME_FOREVER);
        if (err != K_ERR_NONE) {
            continue;
        }
        err = tos_mutex_pend(&buffer_locker);
        if (err != K_ERR_NONE) {
            continue;
        }

        produce_item(salt);

        tos_mutex_post(&buffer_locker);
        tos_sem_post(&full);
        tos_task_delay(1000);
        ++salt;
    }
}

static void consume_item(void)
{

    printf("cosume item:\n");
    printf("%d\n", resource.buffer[--resource.cursor]);
    printf("\n");

}
void entry_task_consumer(void *arg)
{
    k_err_t err;

    while (1) 
			{
		
        err = tos_sem_pend(&full, TOS_TIME_FOREVER);
        if (err != K_ERR_NONE) {
            continue;
        }
        tos_mutex_pend(&buffer_locker);
        if (err != K_ERR_NONE) {
            continue;
        }

        consume_item();

        tos_mutex_post(&buffer_locker);
        tos_sem_post(&empty);
        tos_task_delay(2000);
     }
}


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(&buffer_locker);
	  tos_sem_create(&full, 0);
    tos_sem_create(&empty, RESOURCE_COUNT_MAX);
    (void)tos_task_create(&task_producer,
                      			"producer",
                            entry_task_producer,
                         		NULL,
                            1,
                         		stack_task_producer, 
		                        STK_SIZE_TASK_PRODUCER, 
		                        0);
    (void)tos_task_create(&task_consumer, 
			                     "consumer",
                         		entry_task_consumer, 
		                        NULL,
                            2,
                         		stack_task_consumer,
                        		STK_SIZE_TASK_CONSUMER, 
		                        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、付费专栏及课程。

余额充值