FreeRTOS的同步机制---信号量semaphore

目录

1.semaphore的基本概念

2.semaphore的特点

3.semaphore的运行机制

4.semaphore的应用场景

5.demo分析


1.semaphore的基本概念

        信号量用于任务与任务之间,任务与中断之间的同步。也可以对临界资源的互斥访问。

2.semaphore的特点

        1)信号量是一个非负整数;

        2)可用于任务之间的同步或临界资源的访问;

        3)任务在无法获取到信号量时,会挂起当前的任务;

        4)用于同步时,信号量创建后设置为空,任务1获取信号量而阻塞,那么任务将会挂到该信号量阻塞的等待列表中,当任务2释放信号量时,会进行任务调度,那么任务1获取信号量而会进入就绪序列,如果任务1的优先级最高,那么任务1会得到立即执行;如果任务1相对于任务2的优先级低,那么任务2会执行结束后,任务调度到任务1的优先级最高时,任务1才会得到执行。

        4)释放信号量,信号量值+1,获取信号量,信号量值-1;

3.semaphore的运行机制

        任何任务都可以从创建的信号量中获取信号量值,获取成功则会根据当前任务和就绪任务列表的优先级来确定哪个任务执行,如果获取信号量失败,则将当前任务挂到阻塞任务的列表中。

4.semaphore的应用场景

        1)任务间的同步;

        2)临界资源的互斥访问。

5.demo分析

#include "APPTaskDef.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "event_groups.h"
#include "semphr.h"

#define 		START_TASK_PRIO			1
#define 		START_STACK_SIZE		128
TaskHandle_t 	startTask_handler;  //开始任务句柄
static void 	start_task(void *param);


#define 		GET_SEM_TASK_PRIO				3
#define 		GET_SEM_TASK_STACK_SIZE		128
TaskHandle_t 	get_sem_task_handler;		//任务1句柄
static void 	get_sem_task(void *pvPara);


#define 		SET_SEM_TASK_PRIO				2
#define 		SET_SEM_TASK_STACK_SIZE		128
TaskHandle_t 	set_sem_task_handler;		//任务2句柄
static void 	set_sem_task(void *pvPara);



void APP_task(void)
{
	xTaskCreate((TaskFunction_t)start_task,
				(const char *)"start_task",
				(uint16_t)START_STACK_SIZE,
				NULL,
				(UBaseType_t)START_TASK_PRIO,
				(TaskHandle_t *)&startTask_handler);
	vTaskStartScheduler();          //开启任务调度
}

static void start_task(void *param)
{
	
	SemaphoreHandle_t key_sem = xSemaphoreCreateCounting(10, 0);//创建一个计数信号量
	taskENTER_CRITICAL();           //进入临界区

    //创建获取event的任务
    xTaskCreate((TaskFunction_t )get_sem_task,     	
                (const char*    )"get_sem",   	
                (uint16_t       )GET_SEM_TASK_STACK_SIZE, 
                (void*          )key_sem,				
                (UBaseType_t    )GET_SEM_TASK_PRIO,	
                (TaskHandle_t*  )&get_sem_task_handler);   
    //创建设置event的任务
    xTaskCreate((TaskFunction_t )set_sem_task,     
                (const char*    )"set_sem",   
                (uint16_t       )SET_SEM_TASK_STACK_SIZE, 
                (void*          )key_sem,
                (UBaseType_t    )SET_SEM_TASK_PRIO,
                (TaskHandle_t*  )&set_sem_task_handler);      

    vTaskDelete(startTask_handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

/*
创建task0,不调用vTaskDelay();即不会引起任务调度,
为大致限定任务的执行时间,用delay_xms(10);这个函数不会引起任务调度,只是CPU在空等
*/

static void set_sem_task(void *param)
{
	u8 key_value = 0;
	
	//引用key sem
	SemaphoreHandle_t key_sem = (SemaphoreHandle_t)param;
	uint8_t	sem_count = 0;
	int times = 0;
	while(1){
		if(key_sem != NULL){
			key_value = KEY_Scan(0);
			switch(key_value){
				/*
				case KEY0_PRESS:
					xEventGroupSetBits(key_event, EVENTBIT_0);
					printf("KEY0 press\r\n");
					break;
				case KEY1_PRESS:
					xEventGroupSetBits(key_event, EVENTBIT_1);
				printf("KEY1 press\r\n");
					break;
				*/
				case KEY_UP_PRESS:
					xSemaphoreGive(key_sem);					
					sem_count = uxSemaphoreGetCount(key_sem);
					printf("give a sem succeed\r\n");
					printf("cur sem count is %d\r\n", sem_count);
					printf("--------------------------------------------------------------\r\n");

					break;
				default:
					break;				
			}
			LED0 = ~LED0;
			delay_ms(100);
		}
		delay_xms(10);
	}
}

/*
创建task0,不调用vTaskDelay();即不会引起任务调度,
为大致限定任务的执行时间,用delay_xms(10);这个函数不会引起任务调度,只是CPU在空等
*/
static void get_sem_task(void *param)
{
	EventBits_t EventValue;
	uint8_t sem_count;
		//引用key event
	SemaphoreHandle_t key_sem = (SemaphoreHandle_t)param;
	
	while(1){
		xSemaphoreTake(key_sem, portMAX_DELAY);
		sem_count = uxSemaphoreGetCount(key_sem);
		printf("receive semaphore succeed!\r\n");
		printf("cur sem count is %d\r\n", sem_count);
		printf("--------------------------------------------------------------\r\n");
		LED1 = ~LED1;
		delay_xms(10);
	}
}


        任务1通过按键发送同步信号量,任务2获取信号量达到同步任务1的操作。在发送和获取信号量的同时可以获取信号量的当前值:uxSemaphoreGetCount(key_sem);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值