FreeRTOS的同步机制---事件event

目录

1.event的基本概念

2.event的特点

3.event的运行机制

4.event与semphore的区别

5.event的应用场景

6.demo分析


1.event的基本概念

        事件event是用于任务间通信的机制,主要用于任务与任务之间,任务与中断之间的同步。 事件只是任务之间的通信,无数据传输
        每一个事件组(eventGroup)需要很少的RAM空间来保存状态,在FreeRTOS中,eventBits的位宽由 configUSE_16_BIT_TICKS宏开关决定, configUSE_16_BIT_TICKS 为0,则事件eventGroup为32位,其中有24个bit来存储事件标志位, configUSE_16_BIT_TICKS 为1,则则事件eventGroup为16位,其中有8个bit来存储事件标志位。在stm32中, configUSE_16_BIT_TICKS 为0,即,事件标志位为32位。

2.event的特点

1) 事件是依附在任务中的,事件是与任务要关联在一起的,事件组中的任务之间是独立的,每个事件中发生则将该event中的位置1,没发生则将event的位置0,在stm32中有24个标志位可以用于事件的设置;

2)事件仅用于同步任务,不能传输数据; 

3)事件无排队性,也就是说,多次向任务中设置同一事件,则等效于只设置1次事件;

4)允许多个任务对同一事件进行读写操作,即设置event标志位,获取event标志位;

5)在等待事件中,如果超时,那么等待的任务也可以激活


3.event的运行机制

        发送event时,指定事件的句柄,指定事件的标志位(将该标志位置1),一次可以同时指定多个事件标志位;

xEventGroupSetBits(key_event, EVENTBIT_1);

        接受event时,事件所在的任务根据感兴趣的事件来接受单个或多个事件,在xEventGroupWaitBits中还需要指定xClearOnExit,即退出时是否清空标志位,pdTRUE:在函数xEventGroupWaitBits退出前清空标志位,pdFALSE:在函数xEventGroupWaitBits退出前不清空标志位;xWaitForAllBits用于设置事件的逻辑关系,pdTRUE:事件之间是逻辑与关系,pdFALSE:事件之间是逻辑或关系;xTicksToWait设置任务等待事件的时间,注意,如果超过指定的时间片,当前的任务也能判定激活,多以可以根据xEventGroupWaitBits()返回的值来判定是否等待的事件到来的。

xEventGroupWaitBits(key_event,
                            EVENTBIT_ALL,        //等待的event标志位
                            pdTRUE,                //退出xEventGroupWaitBits之前,event标志位是否清                除,若不清除,那么当3个标志位一起到来后,xEventGroupWaitBits持续激活态
                            pdFALSE,            //event事件之间的关系,& 还是 | 的关系,pdTRUE: &, pdFALSE:|
                            portMAX_DELAY);


         任务A对事件1或事件2感兴趣(逻辑或),任务B对事件1和事件2感兴趣(逻辑与),那么任务A当事件1或事件2任意哪个事件到来就会激活任务A,任务B当事件1和事件2同时到来时才激活任务B。

4.event与semphore的区别

       事件在一定条件下是可以替代信号量的,当事件只有一个时,可以实现与二值信号量同样的功能,任务与任务,任务与中断之间的同步。

        信号量具有计数性,即每来一次信号量semphore都会对当前的信号量值进行累加或累减(在信号量值没满或没空的情况下)

        事件是无序的,即不管来多少次事件都作为一次事件的触发。

        


5.event的应用场景

        事件是用于同步任务的,但不能传递数据,所以一般在应用场景中,一般用于一个任务在等待多个事件标志,事件标志之间可以是“逻辑与”,也可以是“逻辑或”,即一个任务要响应多个事件后才能与另外任务同步,否则就是将当前任务挂起等待。

        如,一辆巴士车A可承载10人,那么每个人就可以作为一个事件位,司机就是调度器,司机可以根据成员情况决定是否发车,司机可以等待10人全坐满(逻辑与),也可以只有部分人坐满(逻辑或),司机根据需求发车,即发送事件,到达车站后,乘客需要换成到另外一辆巴士B(任务B),巴士B根据情况,可以选择等全车满后(逻辑与)再出发,也可以部分人满(逻辑或)就出发,没等到想要的人就可以延长等待时间。


6.demo分析

        实现:任务A发送key的按键event事件,任务B响应按键的event事件。

        main.c文件

int main(void)
{
	//1. init_hardware
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 
	delay_init();	    				//初始化delay
	uart_init(115200);					//初始化uart
	LED_Init();		  					//初始化led
	init_key();							//初始化key
	
	//2.初始化thread
	APP_task();
	return 0;
}

taskA和taskB

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)
{
	
	EventGroupHandle_t key_event = xEventGroupCreate(); //创建一个事件event
	taskENTER_CRITICAL();           //进入临界区

    //创建获取event的任务
    xTaskCreate((TaskFunction_t )get_event_task,     	
                (const char*    )"get_event",   	
                (uint16_t       )GET_EVENT_TASK_STACK_SIZE, 
                (void*          )key_event,				
                (UBaseType_t    )GET_EVENT_TASK_PRIO,	
                (TaskHandle_t*  )&get_event_task_handler);   
    //创建设置event的任务
    xTaskCreate((TaskFunction_t )set_event_task,     
                (const char*    )"set_event",   
                (uint16_t       )SET_EVENT_TASK_STACK_SIZE, 
                (void*          )key_event,
                (UBaseType_t    )SET_EVENT_TASK_PRIO,
                (TaskHandle_t*  )&set_event_task_handler);      

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


static void set_event_task(void *param)
{
	u8 key_value = 0;
	
	//引用key event
	EventGroupHandle_t key_event = (EventGroupHandle_t)param;
	
	while(1){
		if(key_event != 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:
					xEventGroupSetBits(key_event, EVENTBIT_2);
					printf("KEY_UP press\r\n");
					break;
				default:
					break;				
			}
			LED0 = ~LED0;
		}
		delay_xms(10);
	}
}


static void get_event_task(void *param)
{
	EventBits_t EventValue;
		//引用key event
	EventGroupHandle_t key_event = (EventGroupHandle_t)param;
	
	while(1){
		EventValue = xEventGroupWaitBits(key_event,
							EVENTBIT_ALL,		//等待的event标志位
							pdTRUE,				//退出xEventGroupWaitBits之前,event标志位是否清除,若不清除,那么当3个标志位一起到来后,xEventGroupWaitBits持续激活态
							pdTRUE,			//event事件之间的关系,& 还是 | 的关系,pdTRUE: &, pdFALSE:|
							portMAX_DELAY);
		printf("eventValue = %d\r\n", EventValue);
		printf("--------------------------------------------------------------\r\n");
		LED1 = ~LED1;
		delay_xms(10);
	}
}

taskA轮询按键,有按键按下后,触发按键事件;taskB响应3个按键先后到来的事件,每次等待事件后均清除标志位,以方便下次再次响应。注意,任务的传入参数即为事件event

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值