RTX笔记

1、CMSIS-RTOS2 API 之 事件标志

1.1 函数

osEventFlagsId_t 	osEventFlagsNew (const osEventFlagsAttr_t *attr)

创建并初始化事件标志对象。更多…

uint32_t 	osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags)

设置指定的事件标志。更多…

uint32_t 	osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags)

清除指定的事件标志。更多…

uint32_t 	osEventFlagsGet (osEventFlagsId_t ef_id)

获取当前的事件标志。更多…

uint32_t 	osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout)

等待一个或多个事件标志发出信号。更多…

osStatus_t 	osEventFlagsDelete (osEventFlagsId_t ef_id)

删除事件标志对象。更多…

const char * 	osEventFlagsGetName (osEventFlagsId_t ef_id)

获取事件标志对象的名称。更多…

1.2 举例:

led_thread.h

#ifndef __LED_THREAD_H
#define __LED_THREAD_H
#include "stm32f4xx_hal.h"
#include "cmsis_os2.h"
#include "bsp_led.h"
#include "app_main.h"

void led_task (void * arg);

#define led1_event1 1<<0
#define led1_event2 1<<1
#define led1_event3 1<<2
#define led1_event4 1<<3

#define led2_event1 1<<0
#define led2_event2 1<<1
#define led2_event3 1<<2

#define led3_event1 1<<0
#define led3_event2 2<<1
#define led3_event3 3<<2

#endif


osEventFlagsId_t EventFlag_LED1;
osEventFlagsId_t EventFlag_LED2;
osEventFlagsId_t EventFlag_LED3;

static const osEventFlagsAttr_t EventFlagAttr_1 = {
	.name = "1_Events",
};
static const osEventFlagsAttr_t EventFlagAttr_2 = {
	.name = "2_Events",
};
static const osEventFlagsAttr_t EventFlagAttr_3 = {
	.name = "3_Events",
};

EventFlag_LED1 = osEventFlagsNew(&EventFlagAttr_1);
EventFlag_LED2 = osEventFlagsNew(&EventFlagAttr_2);
EventFlag_LED3 = osEventFlagsNew(&EventFlagAttr_3);

void main_task (void * arg) 
{

	while(1)
	{
		osDelay(100);
		//事件标志1		
		event_flag=osEventFlagsWait (EventFlag_LED1,led1_event1|led1_event2|led1_event3|led1_event4,osFlagsWaitAny,1);//osWaitForever
		if( event_flag== led1_event1)
		{
			LED_ERR_ON();//获取事件led1_event1,并自动清除标记
		}
		else if(event_flag== led1_event2)
		{
			LED_ERR_OFF();//获取事件led1_event2,并自动清除标记
		}
		else if((event_flag == led1_event3) || (event_flag == led1_event4))
		{
			LED_ERR_Toggle();//获取事件led1_event1或者led1_event2,并自动清除标记
		}
		
		//事件标志2
		event_flag=osEventFlagsWait (EventFlag_LED2,led2_event1|led2_event2,osFlagsWaitAll,1);//osWaitForever
		if(event_flag == (led2_event2|led2_event1))//同时发生
		{
			LED_ERR_Toggle();
		}
		
		//事件标志3
		event_flag=osEventFlagsGet (EventFlag_LED3);
		if(event_flag==led3_event1)
		{
			osDelay(1);//事件led3_event1获取,不清除标记,下次循环依旧进来
		}
		if(event_flag==led3_event2)
		{
			osDelay(1);//事件led3_event2获取,不清除标记,下次循环依旧进来
		}
		if(event_flag==(led3_event2|led3_event1))
		{
				osEventFlagsClear(EventFlag_LED3,led3_event2|led3_event1);//事件led3_event1,led3_event2获取,并且清除事件标记
		}
	}
}

void led_task (void * arg) 
{
	osStatus_t status;
	while(1)
	{
		switch(event_test){
			case 0:
				osDelay(1);
			break;
			case 1:
				osEventFlagsSet	(EventFlag_LED1,led1_event1);//标记1,事件1
				event_test=0;
			break;
			case 2:
				osEventFlagsSet	(EventFlag_LED1,led1_event2);//标记1,事件2
				event_test=0;
			break;
			case 3:
				osEventFlagsSet	(EventFlag_LED1,led1_event3);//标记1,事件3
				event_test=0;
			break;
			case 4:
				osEventFlagsSet	(EventFlag_LED1,led1_event4);//标记1,事件4
				event_test=0;
			break;
			case 5:
				osEventFlagsSet	(EventFlag_LED2,led2_event1);//标记2,事件1
				event_test=0;
			break;
			case 6:
				osEventFlagsSet	(EventFlag_LED2,led2_event2);//标记2,事件2
				event_test=0;
			break;
			case 7:
				osEventFlagsSet	(EventFlag_LED2,led2_event1);//标记3,事件1
				event_test=0;
			break;
			case 8:
				osEventFlagsSet	(EventFlag_LED2,led2_event2);//标记3,事件2
				event_test=0;
			break;
		}
	}
}

2、CMSIS-RTOS2 API 之信号量

2.1 函数

osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)
创建并初始化信号量对象。更多…
参数:
[in] max_count 可用令牌的最大数量。
[in] initial_count 可用令牌的初始数量。
[in] attr 信号量属性; NULL:默认值。
返回
信号标识以供其他功能参考,或者在发生错误时使用 NULL

const char * osSemaphoreGetName (osSemaphoreId_t semaphore_id)
获取信号量对象的名称。更多…

osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout)
如果没有令牌可用,则获取信号量标记或超时。更多…

osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id)
释放一个信号量令牌直到最初的最大数量。更多…

uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id)
获取当前的信号量令牌计数。更多…

osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id)
删除一个信号量对象。更多…

2.2 描述

信号量对象应初始化为可用令牌的最大数量。这个可用资源的数量被指定为 osSemaphoreNew 函数的参数。每次使用 osSemaphoreAcquire(处于可用状态)获得信号量标记时,信号量计数递减。当信号量计数为 0(即耗尽状态)时,不能获得更多的信号量标记。尝试获取信号量标记的线程/ISR 需要等待,直到下一个标记为空。信号量与 osSemaphoreRelease 一起发布,增加信号量计数。
在这里插入图片描述

2.3 简单举例

osSemaphoreId_t sem1;
static const osSemaphoreAttr_t semAttr_SEM1 = {
	.name = "SEM1",
};
sem1 = osSemaphoreNew(5, 0, &semAttr_SEM1 );

/*----------------------------------------------------------------------------
  Wait to acquire a semaphore token from sem1 then flash LED 1
 *---------------------------------------------------------------------------*/
__NO_RETURN void led_Thread1 (void  *argument) {
	
	for (;;) {
		osSemaphoreAcquire(sem1, osWaitForever);
		LED_On(1);                          
		osSemaphoreAcquire(sem1, osWaitForever);
		LED_Off(1);
	}
}

/*----------------------------------------------------------------------------
  Flash LED 2 and 'release' a semaphore token to sem1
 *---------------------------------------------------------------------------*/
__NO_RETURN void led_Thread2 (void *argument) {
	
	for (;;) {
		osSemaphoreRelease(sem1);
		LED_On(2);		
		osDelay(500);
		osSemaphoreRelease(sem1);
		LED_Off(2);
		osDelay(500);
	}
}

2.4 运用举例

使用信号量组举例:

//初始化
	osSemaphoreId_t RcvSem[8];
	for (i=0;i<8;i++)
	{
		RcvSem[i] = osSemaphoreNew(10,0,NULL);
	}
//	
/*----------------------------------------------------------------------------
  'release' a semaphore token to RcvSem
 *---------------------------------------------------------------------------*/
typedef struct
{
	uint8_t cmd
	uint8_t data[530];
	uint16_t length;
}rcvMessage_t;
__NO_RETURN void led_Thread2 (void *argument) {
	rcvMessage_t RcvMsg;
	for (;;) {
			//do something 接收到数据...
			switch(RcvMsg.cmd)
			{
				case 'l':
				if (RcvMsg.length==2)
				{
					k = RcvMsg->data[1];
					osSemaphoreRelease(RcvSem[k]);
				}
			}
	}
}

__NO_RETURN void led_Thread1 (void *argument) {
	uint8_t sendFailTime = 0;
	uint32_t flags;
	osStatus_t status;
	
	for (;;) {
			status=  osMessageQueueGet(ReLoadMsg, &ReloadPoint, NULL, 0U);//等待是否发送数据
			if (osOK == status)
			{
				sendFailTime =0;
				while (sendFailTime <3)//没收到回复,重发三次
				{
//					while (osOK == osSemaphoreAcquire(RcvSem[channel],0x1u));
					osEventFlagsSet(photoDataSendEvt_id,0x1);//给发送线程发送数据
					while(1)
					{
						flags = osEventFlagsWait(SendFinishEvt_id,0x1,osFlagsWaitAny,0); //等待发送完成
						if (flags == 1)
						break;
						osDelay(10);
					}
					sem_status=osSemaphoreAcquire(photoRcvSem[channel],1000);// 1S内,等待回复
					if (sem_status == osOK)
					{
						sendFailTime = 5;		
					}
					sendFailTime ++;	
				}
			}
	}

3、CMSIS-RTOS2 API 之 互斥锁管理

互斥量通常在各种各样的操作系统上用于资源管理。MCU上的很多资源能被复用,但是,在同一个时刻上仅仅只有一个线程能访问这些资源(例如通讯(串口,SPI),内存,文件等)。互斥量通常用于保护一些共享资源的访问。在线程上获取互斥量,也必须释放互斥量(释放了互斥量,其他线程才能访问共享资源)。

在这里插入图片描述

在这里插入图片描述

osMutexId_t  sendPhotoMutex;
static const osMutexAttr_t MutexAttr_uartMutex = {
	.name = "uartMutex",
};
sendPhotoMutex = osMutexNew(&MutexAttr_uartMutex);	
void main_task (void * arg) 
{
	osStatus_t status;
	while(1)
	{
		osDelay(100);
		status=osMutexAcquire(sendPhotoMutex, osWaitForever);
		if(status == osOK)
		{
			//do someting.. 同一个时刻,仅有一个线程能访问的资源
			osDelay(1);
		}
		osMutexRelease(sendPhotoMutex);	
	}
}

创建互斥锁后,Lock counter :0
获取互斥锁后,Lock counter:1
释放互斥锁后,Lock counter:0
在这里插入图片描述

4、内核信息与控制

RTOS官方链接

4.1 uint32_t osKernelGetTickCount ( void )

功能:
Returns:RTOS kernel current tick count.
The function osKernelGetTickCount returns the current RTOS kernel tick count

#include "cmsis_os2.h"
 
void Thread_1 (void *arg)  {                // Thread function
  uint32_t tick;
  tick = osKernelGetTickCount();            // retrieve the number of system ticks
  for (;;) {
    tick += 1000;                           // delay 1000 ticks periodically
    osDelayUntil(tick);
    // ...
  }
}

//500ms或者200ms更新

//状态更新
void packPartStatus(unsigned char cmd)
{		
	if(msg_StautsAll.fb_epos.work_status==Running)
	{
		SendStatusPeriod  = 500;
	}
	else
	{
		SendStatusPeriod  = 2000;
	}
	if ((osKernelGetTickCount()-refreshTick)>SendStatusPeriod)
	{
		updata_status(cmd,temp_add);
		refreshTick = osKernelGetTickCount();
		sendStatusCount ++;
	}
}

4.2 uint32_t osKernelGetTickFreq (void )

功能:返回系统内核频率,一般是1000HZ,1mS

4.3 uint32_t osKernelGetSysTimerFreq (void )

功能:返回RTOS内核系统计数器时钟频率(我使用的是SysTick时钟180M)

4.4 uint32_t osKernelGetSysTimerCount (void )

功能:返回系统内核时钟计数值

void Thread_1 (void *arg)  {                // Thread function
	uint32_t TimerFreq=0;
	uint32_t TimerCounter1_last=0;
	uint32_t TimerCounter1_next=0;
	uint32_t TimerCounter2_last=0;
	uint32_t TimerCounter2_next=0;
  TimerFreq= osKernelGetSysTimerFreq(); //返回值为:180000000(我设置系统时钟 SYSCLK 等于 180M)
  for (;;) {
  			TimerFreq=  osKernelGetSysTimerFreq(); //180M 内核时钟(systick 时钟)频率
			TimerFreq=  osKernelGetTickFreq();		//1000 内核频率
			
			TimerCounter1_last=  osKernelGetSysTimerCount();//内核时钟计数值
			TimerCounter2_last=  osKernelGetTickCount();	//内核计数值
			osDelay(100);
			TimerCounter1_next=  osKernelGetSysTimerCount();//内核时钟计数值
			TimerCounter2_next=  osKernelGetTickCount();	//内核计数值
  }
}

从下图可以看出:
1、TimerCounter1_next - TimerCounter1_last = 17,993,028,约等于 18 000 000,内核时钟频率为180M,所以约等于100mS。
2、TimerCounter2_next - TimerCounter2_last = 100,内核频率为1000,所以约等于100mS
在这里插入图片描述

5、内存池

官方链接

osMemoryPoolAlloc : 从内存池中分配内存块。
osMemoryPoolDelete : 删除一个内存池对象。
osMemoryPoolFree : 将分配的内存块返还给内存池。
osMemoryPoolGetBlockSize : 获取内存池中的内存块大小。
osMemoryPoolGetCapacity : 获取内存池中的最大内存块数。
osMemoryPoolGetCount : 获取内存池中使用的内存块数量。
osMemoryPoolGetName : 获取内存池对象的名称。
osMemoryPoolGetSpace : 获取内存池中可用的内存块数量。
osMemoryPoolNew : 创建并初始化一个内存池对象。

数据结构文档:

/// Attributes structure for memory pool.
typedef struct {
  const char                   *name;   ///< name of the memory pool
  uint32_t                 attr_bits;   ///< attribute bits 保留位
  void                      *cb_mem;    ///< memory for control block 内存控制块
  uint32_t                   cb_size;   ///< size of provided memory for control block 
  void                      *mp_mem;    ///< memory for data storage 
  uint32_t                   mp_size;   ///< size of provided memory for data storage 
} osMemoryPoolAttr_t;

6、内存池与消息队列的结合

使用消息队列时,使用内存池地址来传递数据。从而提高消息队列效率
举例:
初始化

//.h 定义
#define MEMPOOL_OBJECTS 15     // number of Memory Pool Objects
#define TCPSENDPOOL 0xc0700000 //外部SDRAM
#define BYTE11K    1024*11
#define MAX_RECEIVE_LENGTH 512
typedef struct
{
	 char data[MAX_RECEIVE_LENGTH];
} sendMsg_t;

//.c创建地址池,消息队列
/*queue message*/
osMessageQueueId_t TcpSendMessage; 

/*memory pool*/
osMemoryPoolId_t ReplaySend_MemPool;                  // memory pool id		

const osMemoryPoolAttr_t TcpSendMemoryPool_attr = {
	.mp_mem = (void *)TCPSENDPOOL ,
	.mp_size = BYTE11K 
};
/*queue*/
TcpSendMessage = osMessageQueueNew(100, sizeof(uint32_t), NULL);//100*4Byte(地址)
	if(TcpSendMessage==NULL)
		return -1;
/*memory pool*/
//	ReplaySend_MemPool = osMemoryPoolNew(MEMPOOL_OBJECTS, sizeof(sendMsg_t), &TcpSendMemoryPool_attr);//创建内存池
ReplaySend_MemPool = osMemoryPoolNew(MEMPOOL_OBJECTS, sizeof(sendMsg_t), NULL);//创建内存池
if(ReplaySend_MemPool==NULL)
{
	return -1;//MemPool object not created, handle failure
}

task1

uint32_t GetPoolUsed=0,PoolRemain=0,MaxMemoryBlocks=0,GetBlockSizes=0;
sendMsg_t  *pMem1,*pMem2,*pMem3,*pMemMsg; 
void main_task (void * arg) 
{ 
	uint16_t i=0;
	static uint8_t j=0;
	osStatus_t status;

	while(1)
	{
		//内存池获取、释放测试
		#if 1
		pMem1 =  	(sendMsg_t *)osMemoryPoolAlloc(ReplaySend_MemPool, 0U);//申请内存
		GetPoolUsed = osMemoryPoolGetCount(ReplaySend_MemPool);			   //已用内存池个数
		PoolRemain = osMemoryPoolGetSpace	(ReplaySend_MemPool);		   //剩余内存池个数
		MaxMemoryBlocks = osMemoryPoolGetCapacity(ReplaySend_MemPool);	   //内存块最大个数
		GetBlockSizes=osMemoryPoolGetBlockSize(ReplaySend_MemPool);		   //单个内存块多少个字节
		
		pMem2 =  	(sendMsg_t *)osMemoryPoolAlloc(ReplaySend_MemPool, 0U);
		GetPoolUsed = osMemoryPoolGetCount(ReplaySend_MemPool);
		PoolRemain = osMemoryPoolGetSpace	(ReplaySend_MemPool);
		
		pMem3 =  	(sendMsg_t *)osMemoryPoolAlloc(ReplaySend_MemPool, 0U);
		GetPoolUsed = osMemoryPoolGetCount(ReplaySend_MemPool);
		PoolRemain = osMemoryPoolGetSpace	(ReplaySend_MemPool);
			
		osMemoryPoolFree(ReplaySend_MemPool,pMem1);//释放内存池
		GetPoolUsed = osMemoryPoolGetCount(ReplaySend_MemPool);
		PoolRemain = osMemoryPoolGetSpace	(ReplaySend_MemPool);
		
		osMemoryPoolFree(ReplaySend_MemPool,pMem2);
		GetPoolUsed = osMemoryPoolGetCount(ReplaySend_MemPool);
		PoolRemain = osMemoryPoolGetSpace	(ReplaySend_MemPool);
		
		osMemoryPoolFree(ReplaySend_MemPool,pMem3);
		GetPoolUsed = osMemoryPoolGetCount(ReplaySend_MemPool);
		PoolRemain = osMemoryPoolGetSpace	(ReplaySend_MemPool);
		#endif
		//消息队列数据传递-使用内存池地址
		pMemMsg =  	(sendMsg_t *)osMemoryPoolAlloc(ReplaySend_MemPool, 0U);//申请内存
		for(i=0;i<MAX_RECEIVE_LENGTH;i++)
		{
			pMemMsg->data[i]=j;			
		}
		j++;
		 osMessageQueuePut(TcpSendMessage, &pMemMsg, 0U, 0U);
	}
}

在这里插入图片描述

task2

void led_task (void * arg) 
{
	osStatus_t status;
	uint32_t ptr;
	sendMsg_t *prcv;
	while(1)
	{
		status=  osMessageQueueGet(TcpSendMessage, &ptr, NULL, 0U);
		if (osOK == status)
		{
			prcv = (sendMsg_t *)ptr;
			//do something...
			/*
			 HAL_UART_Transmit_IT(&huart3,(uint8_t *)&prcv->data[0],strlen(prcv->data));
			 osDelay(strlen(prcv->data));
			 while(huart3.gState != HAL_UART_STATE_READY) 
						osDelay(1);
			 */
			 osMemoryPoolFree(ReplaySend_MemPool,prcv);			
		}
	}
}

在这里插入图片描述

在这里插入图片描述

注意事项:当属性设置为NULL,自动申请片内RAM时,配置全局内存池不能设置的过小,否则会创建失败。
在这里插入图片描述
RTX中每个线程可拥有高达32个线程标志,这些线程标志存放在线程控制块中,其余线程可以通过设置这些Thread Flags来中断该线程的执行。当某个执行线程调用osThreadFlagsWait()时,该线程会被阻塞,并进入wait_event状态。若其他线程将所选(specified)的标志中的某个或全部Thread Flags置位,则该线程将会变为就绪态。在这里插入图片描述

7、CMSIS-RTOS2 API 之线程标志组

Thread flags官网解释

在这里插入图片描述

  RTX中每个线程可拥有高达32个线程标志,这些线程标志存放在线程控制块中,其余线程可以通过设置这些Thread Flags来中断该线程的执行。当某个执行线程调用osThreadFlagsWait()时,该线程会被阻塞,并进入wait_event状态。若其他线程将所选(specified)的标志中的某个或全部Thread Flags置位,则该线程将会变为就绪态。

抓重点,线程标志和事件标志的区别:
   1、线程标志只能发送给单个指定线程
   2、事件标志可以发送给多个线程

uint32_t osThreadFlagsSet(osThreadId_t thread_id, uint32_t flags)

输入:

  • thread_id : 线程ID
  • flags: 设置多个线程标志
    输出:
  • 返回设置后的线程标志,或者错误码
    osFlagsErrorUnknown: unspecified error.
    osFlagsErrorParameter: parameter thread_id is not a valid thread or flags has highest bit set.
    osFlagsErrorResource: the thread is in invalid state.

uint32_t osThreadFlagsClear ( uint32_t flags )

参数:

  • flags : 线程标志
    返回:
  • 清除前的线程标志或者错误码(如果最高位被置位)
    osFlagsErrorUnknown: unspecified error, i.e. not called from a running threads context.
    osFlagsErrorParameter: parameter flags has highest bit set.
    osFlagsErrorISR: the function osThreadFlagsClear cannot be called from interrupt service routines.

uint32_t osThreadFlagsGet ( void )

输入


  • 输出
  • 当前线程标志

uint32_t osThreadFlagsWait ( uint32_t flags,uint32_t options,uint32_t timeout )

// 输入

  • flags : 等待的线程标志,选定等待的标志位集合,比如1U表示只有标志0,3U则表示选中标志0和标志1
  • options : 标志选项
  • timeout : 超时设定
    /输出
  • 清除之前的线程标志,注意该函数返回时会自动清除等待线程标志(除非选项设定为osFlagsNoClear)
options
osFlagsWaitAnyWait for any flag (default).
osFlagsWaitAllWait for all flags.
osFlagsNoClearDo not clear flags which have been specified to wait for

任何线程都可以将其他线程的标志位置位,线程本身只能等待自己的标志位。

举例

/*
*********************************************************************************************************
*	函 数 名: AppTaskCreate
*	功能说明: 创建应用任务
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/

/* 任务句柄 */
osThreadId_t 	main_ids  = NULL;
osThreadId_t 	led_ids = NULL;

//Attributes structure for main_thread.
static const osThreadAttr_t ThreadAttr_MAIN = {
	.name = "Main_Thread",
	.priority=osPriorityNormal,
	.stack_size =512,
};

static const osThreadAttr_t ThreadAttr_LED = {
	.name = "LED_Thread",
	.priority=osPriorityNormal,
	.stack_size =512,
};
static void AppTaskCreate (void)
{

//main_task
	main_ids=osThreadNew(main_task, NULL, &ThreadAttr_MAIN);
	
//led_task
	led_ids=osThreadNew(led_task, NULL, &ThreadAttr_LED);
}

#define flag0 	(1 << 0)	//(32位 bit0)
#define flag1	(1 << 1)	//(32位 bit1)
#define flag2	(1 << 2)	//(32位 bit2)
#define flag3 	(1 << 3)	//(32位 bit3)
#define flag4 	(1 << 4)	//(32位 bit4)
uint8_t KEY_VALUE=0;
/*
** KEY_VALUE=1,线程组flag0置位
** KEY_VALUE=2,线程组flag1置位
** KEY_VALUE=3,线程组flag2置位
** KEY_VALUE=4,线程组flag1与flag2置位
** KEY_VALUE=5,线程组flag3与flag4置位
*/

void led_task(void *arg)
{
	uint32_t flags;
	while(1)
	{
		if(KEY_VALUE == 1)
		{
			flags=osThreadFlagsSet(main_ids,flag0);  /* 置位main_ids线程的flag0 */
			if(flags==flag0)
					KEY_VALUE = 0;
		}
		
		if(KEY_VALUE == 2)
		{
			flags=osThreadFlagsSet(main_ids,flag1);  /* 置位main_ids线程的flag1 */
			if(flags==flag1)
					KEY_VALUE = 0;
		}
		if(KEY_VALUE == 3)
		{
			flags=osThreadFlagsSet(main_ids,flag2);  /* 置位main_ids线程的flag2 */
			if(flags==flag2)
					KEY_VALUE = 0;
		}
		if(KEY_VALUE == 4)
		{
			flags=osThreadFlagsSet(main_ids,flag1|flag2);  /* 置位main_ids线程的flag1与flag2事件 */
			if(flags == (flag1|flag2))
					KEY_VALUE = 0;
		}		
		if(KEY_VALUE == 5)
		{
			flags=osThreadFlagsSet(main_ids,flag3|flag4);  /* 置位main_ids线程的flag3与flag4事件 */
			if(flags == (flag3|flag4))
					KEY_VALUE = 0;
		}

		osDelay(1);
	}
}


void main_task (void * arg) 
{
	osStatus_t status;
	uint32_t flags;
  while(1) 
	{
		flags = osThreadFlagsWait(flag0|flag1|flag2,osFlagsWaitAny,1);  /*  osWaitForever 一直等待自身线程事件组,直到flag0或flag1或 flag2被置1 */		

		/* 看看是不是flag0被置1 */
		if(flags == flag0)
			printf("get flag 0 !\r\n");		
		
		/* 看看是不是flag1被置1 */
		if(flags == flag1)
			printf("get flag 1 !\r\n");
		
		/* 看看是不是flag2被置1 */
		if(flags == flag2)
			printf("get flag 2 !\r\n");	

		/* 看看是不是flag2 flag1都被置1 */		
		if(flags == (flag2|flag1))
				printf("get flag 2 flag 1 !\r\n");
	
		
		flags = osThreadFlagsWait(flag3|flag4,osFlagsWaitAll,1); /*等待flag3 flag4一起被置位*/
		/* 看看是不是flag3 flag4 一起被置1 */
		if(flags == (flag3|flag4))
				printf("get flag 3 flog4 !\r\n");	
		osDelay(1);
	}
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值