精华内容
下载资源
问答
  • freertos信号量
    2022-05-09 09:09:14

    1、二值信号量

    概念:长度为1 的队列,无优先级机制。

    说明:二值信号量看作只有一个消息的队列,这个队列只能为空或满,运用的时候只需要知道队列中是否有消息即可,而无需关注消息是什么。

    应用场景:既可以用于临界资源访问也可以用于同步功能,主要偏向同步功能(任务与任务间的同步或任务和中断间同步)

    应用案例:用作同步时,信号量在创建后被置为空,任务1 获取信号量失败而进入阻塞,任务2 在某种条件发生后,释放信号量,于是任务1 获得信号量得以进入就绪态,如果任务1 的优先级是最高的,那么就会立即切换任务,从而达到了两个任务间的同步。同样的,在中断服务函数中释放信号量,任务1 也会得到信号量,从而达到任务与中断间的同步。

    2、互斥信号量

    概念:长度为1 的队列,有优先级机制。

    说明:用作互斥时,信号量创建后可用信号量个数是满的,任务在需要使用临界资源时,先获取互斥信号量,使其变空,其他任务需要使用临界资源时就会因为无法获取信号量而进入阻塞,从而保证了临界资源的安全。

    应用场景:适用于保护临界资源。

    应用案例:在操作系统中,使用信号量为临界资源建立一个标志,信号量表示了该临界资源被占用情况。当一个任务在访问临界资源的时候,就会先对这个资源信息进行查询,从而在了解资源被占用的情况之后,再做处理,从而使得临界资源得到有效的保护。类似于Linux系统中的互斥锁。

    3、计数信号量

    概念:长度大于1的队列。

    说明:

    用作事件计数时。当某个事件发生时,任务或者中断将释放一个信号量(信号量计数值加1),当处理完事件时(一般在任务中处理),处理任务会取走该信号量(信号量计数值减1),信号量的计数值则表示还有多少个事件没被处理。

    用作资源管理时。使用计数信号量进行资源管理,信号量的计数值表示系统中可用的资源数目,任务必须先获取到信号量才能获取资源访问权,当信号量的计数值为零时表示系统没有可用的资源。

    应用场景:用于事件计数与资源管理。

    应用案例:计数型信号量允许多个任务对其进行操作,但限制了任务的数量。比如有一个停车场,里面只有 100 个车位,那么能停的车只有 100 辆,相当于信号量有 100 个,每进去一辆车就要消耗一个停车位,车位的数量就要减一,对应的信号量在使用之后也需要减一,当停车场停满了 100 辆车的时候,此时的停车位为 0,再来的车就不能停进去了,否则将造成事故,也相当于信号量为 0,后面的任务对这个停车场资源的访问也无法进行,当有车从停车场离开的时候,车位又空余出来了,那么,后面的车就能停进去了,信号量的操作也是一样的,当释放了这个资源,后面的任务才能对这个资源进行访问。

    4、递归信号量

    概念:可以重复获取调用的信号量。

    说明:对于已经获取递归互斥量的任务可以重复获取该递归互斥量,该任务拥有递归信号量的所有权。任务成功获取几次递归互斥量,就要返还几次,在此之前递归互斥量都处于无效状态,其他任务无法获取,只有持有递归信号量的任务才能获取与释放。

    更多相关内容
  • FreeRTOS信号量

    千次阅读 2022-01-05 20:40:39
    信号量是操作系统中重要的一部分,信号量一般用来进行资源管理和任务同步, FreeRTOS信号量又分为二值信号量、 计数型信号量、互斥信号量和递归互斥信号量。不同的信号量其应用场景不同,但有些应用场景是可以互换...

      信号量是操作系统中重要的一部分,信号量一般用来进行资源管理和任务同步, FreeRTOS中信号量又分为二值信号量、 计数型信号量、互斥信号量和递归互斥信号量。不同的信号量其应用场景不同,但有些应用场景是可以互换着使用的
      信号量用于控制共享资源访问的场景相当于一个上锁机制, 代码只有获得了这个锁的钥匙才能够执行。
      信号量的另一个重要的应用场合就是任务同步,用于任务与任务或中断与任务之间的同步。 在执行中断服务函数的时候可以通过向任务发送信号量来通知任务它所期待的事件发生了, 当退出中断服务函数以后在任务调度器的调度下同步的任务就会执行。在编写中断服务函数的时候我们都知道一定要快进快出,中断服务函数里面不能放太多的代码,否则的话会影响的中断的实时性。 裸机编写中断服务函数的时候一般都只是在中断服务函数中打个标记,然后在其他的地方根据标记来做具体的处理过程。在使用 RTOS 系统的时候我们就可以借助信号量完成此功能, 当中断发生的时候就释放信号量,中断服务函数不做具体的处理。具体的处理过程做成一个任务,这个任务会获取信号量,如果获取到信号量就说明中断发生了,那么就开始完成相应的处理,这样做的好处就是中断执行时间非常短。 这个例子就是中断与任务之间使用信号量来完成同步,当然了, 任务与任务之间也可以使用信号量来完成同步。

    一、二值信号量

      二值信号量通常用于互斥访问或同步, 二值信号量和互斥信号量非常类似,但是互斥信号量拥有优先级继承机制, 二值信号量没有优先级继承。 因此二值信号另更适合用于同步(任务与任务或任务与中断的同步),而互斥信号量适合用于简单的互斥访问。
      使用二值信号量来完成中断与任务同步的这个机制中,任务优先级确保了外设能够得到及时的处理,这样做相当于推迟了中断处理过程。 也可以使用队列来替代二值信号量,在外设事件的中断服务函数中获取相关数据,并将相关的数据通过队列发送给任务。如果队列无效的话任务就进入阻塞态,直至队列中有数据,任务接收到数据以后就开始相关的处理过程。
      二值信号量的使命就是同步,完成任务与任务或中断与任务之间的同步。大多数情况下都是中断与任务之间的同步

    1.1、创建二值信号量

      1、函数 xSemaphoreCreateBinary()
      使用此函数创建二值信号量的话信号量所需要的 RAM 是由 FreeRTOS 的内存管理部分来动态分配的。函数原型如下:

    SemaphoreHandle_t xSemaphoreCreateBinary( void )
    

      返回值:NULL: 二值信号量创建失败。其他值: 创建成功的二值信号量的句柄。
      2、函数 xSemaphoreCreateBinaryStatic()
      此函数也是创建二值信号量的,只不过使用此函数创建二值信号量的话信号量所需要的RAM 需要由用户来分配,函数原型如下:

    SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )
    

      参数:pxSemaphoreBuffer: 此参数指向一个 StaticSemaphore_t 类型的变量,用来保存信号量结构体。
      返回值:NULL: 二值信号量创建失败。其他值: 创建成功的二值信号量句柄。

    1.2、释放信号量

      释放信号量分为任务级和中断级。不管是二值信号量、计数型信号量还是互斥信号量,它们都使用以下两个函数释放信号量。
      1、 函数 xSemaphoreGive()
      此函数用于释放二值信号量、计数型信号量或互斥信号量, 函数原型如下:

    BaseType_t xSemaphoreGive( xSemaphore )
    

      参数:xSemaphore: 要释放的信号量句柄。
      返回值:pdPASS: 释放信号量成功。errQUEUE_FULL: 释放信号量失败。
      2、函数 xSemaphoreGiveFromISR()
      此函数用于在中断中释放信号量, 此函数只能用来释放二值信号量和计数型信号量,绝对不能用来在中断服务函数中释放互斥信号量。此函数原型如下:

    BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore,BaseType_t * pxHigherPriorityTaskWoken)
    

      参数:xSemaphore: 要释放的信号量句柄。pxHigherPriorityTaskWoken: 标记退出此函数以后是否进行任务切换,这个变量的值由这三个函数来设置的,用户不用进行设置,用户只需要提供一个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退出中断服务函数之前一定要进行一次任务切换。
      返回值:pdPASS: 释放信号量成功。errQUEUE_FULL: 释放信号量失败。

    1.3、获取信号量

      不管是二值信号量、计数型信号量还是互斥信号量,它们都使用以下两个函数获取信号量。
      1、函数 xSemaphoreTake()
      此函数用于获取二值信号量、计数型信号量或互斥信号量,函数原型如下:

    BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore,TickType_t xBlockTime)
    

      参数:xSemaphore: 要获取的信号量句柄。xBlockTime: 阻塞时间。
      返回值:pdTRUE: 获取信号量成功。pdFALSE: 超时,获取信号量失败。
      2、函数 xSemaphoreTakeFromISR ()
      此函数用于在中断服务函数中获取信号量, 此函数用于获取二值信号量和计数型信号量,绝 对 不 能 使 用 此 函 数 来 获 取 互 斥 信 号 量 。此函数原型如下:

    BaseType_t xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore,BaseType_t * pxHigherPriorityTaskWoken)
    

      参数:xSemaphore: 要获取的信号量句柄。pxHigherPriorityTaskWoken: 标记退出此函数以后是否进行任务切换,这个变量的值由这三个函数来设置的,用户不用进行设置,用户只需要提供一个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退出中断服务函数之前一定要进行一次任务切换。
      返回值:pdPASS: 获取信号量成功。pdFALSE: 获取信号量失败。

    二、计数型信号量

      计数型信号量叫做数值信号量

    2.1、创建计数型信号量

      1、函数 xSemaphoreCreateCounting()
      此函数用于创建一个计数型信号量,所需要的内存通过动态内存管理方法分配。此函数原型如下:

    SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount,UBaseType_t uxInitialCount )
    

      参数:uxMaxCount: 计数信号量最大计数值,当信号量值等于此值的时候释放信号量就会失败。uxInitialCount: 计数信号量初始值。
      返回值:NULL: 计数型信号量创建失败。其他值: 计数型信号量创建成功,返回计数型信号量句柄。
      2、函数 xSemaphoreCreateCountingStatic()
      此函数也是用来创建计数型信号量的,使用此函数创建计数型信号量的时候所需要的内存需要由用户分配。函数原型如下:

    SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount,UBaseType_t uxInitialCount,StaticSemaphore_t * pxSemaphoreBuffer )
    

      参数:uxMaxCount: 计数信号量最大计数值,当信号量值等于此值的时候释放信号量就会失败。uxInitialCount: 计数信号量初始值。pxSemaphoreBuffer: 指向一个 StaticSemaphore_t 类型的变量,用来保存信号量结构体。
      返回值:NULL: 计数型信号量创建失败。其他值: 计数型号量创建成功,返回计数型信号量句柄。

    2.2、释放和获取计数信号量

      计数型信号量的释放和获取与二值信号量相同。

    三、互斥信号量

      互斥信号量其实就是一个拥有优先级继承的二值信号量, 在同步的应用中(任务与任务或中断与任务之间的同步)二值信号量最适合。 互斥信号量适合用于那些需要互斥访问的应用中。
      互斥信号量使用和二值信号量相同的 API 操作函数,所以互斥信号量也可以设置阻塞时间,不同于二值信号量的是互斥信号量具有优先级继承的特性。 当一个互斥信号量正在被一个低优先级的任务使用,而此时有个高优先级的任务也尝试获取这个互斥信号量的话就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级, 这个过程就是优先级继承。优先级继承尽可能的降低了高优先级任务处于阻塞态的时间,并且将已经出现的“优先级翻转”的影响降到最低。
      优先级继承并不能完全的消除优先级翻转, 它只是尽可能的降低优先级翻转带来的影响。硬实时应用应该在设计之初就要避免优先级翻转的发生。互斥信号量不能用于中断服务函数中,原因如下:
      1、互斥信号量有优先级继承的机制,所以只能用在任务中,不能用于中断服务函数。
      2、中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。

    3.1、创建互斥信号量

      1、函数 xSemaphoreCreateMutex()
      此函数用于创建一个互斥信号量,所需要的内存通过动态内存管理方法分配。此函数原型如下:

    SemaphoreHandle_t xSemaphoreCreateMutex( void )
    

      返回值:NULL: 互斥信号量创建失败。其他值: 创建成功的互斥信号量的句柄。
    2、函数 xSemaphoreCreateMutexStatic()
      此函数也是创建互斥信号量的,只不过使用此函数创建互斥信号量的话信号量所需要的RAM 需要由用户来分配,函数原型如下:

    SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )
    

      参数:pxMutexBuffer: 此参数指向一个 StaticSemaphore_t 类型的变量,用来保存信号量结构体。
      返回值:NULL: 互斥信号量创建失败。其他值: 创建成功的互斥信号量的句柄。

    3.2、释放互斥信号量

      释放互斥信号量的时候和二值信号量 、计数型信号量一样 、都是用的函数xSemaphoreGive()

    3.3、获取互斥信号量

      获取互斥信号量的函数同获取二值信号量和计数型信号量的函数 相同 ,都是xSemaphoreTake()

    展开全文
  • FreeRTOS 信号量

    2021-07-27 11:23:37
    FreeRTOS 信号量 一、信号量简介 信号量常常用于控制对共享资源的访问和任务的同步。 二、二值信号量 1、二值信号量的简介 二值信号量通常用于互斥访问或同步,二值信号量和互斥信号量非常类似,但是还是有一些细微...

    FreeRTOS 信号量

    一、信号量简介

    信号量常常用于控制对共享资源的访问和任务的同步。

    二、二值信号量

    1、二值信号量的简介

    二值信号量通常用于互斥访问或同步,二值信号量和互斥信号量非常类似,但是还是有一些细微的差别,互斥信号量具有优先级继承机制,但是二值信号量没有继承机制。

    2、二值信号量的操作

    1、动态创建二值信号量

    SemaphoreHandle_t xSemaphoreCreateBinary( void )
    

    失败返回NULL,

    成功返回二值信号量的句柄。

    2、静态创建二值信号量,参数是用来保存信号量的结构体

    SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer );
    

    失败返回NULL,

    成功返回二值信号量的句柄。

    3、释放信号量,此函数用来释放二值信号量、计数型信号量、互斥信号量,这是一个宏函数,参数是要释放的信号量句柄。

    BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );
    

    失败返回:err_QUEUE_FULL

    成功返回:pdPASS

    4、在中断中释放信号量,此函数不能在中断中释放互斥信号量,第二个参数只需要提供一个变量来保存这个值就行了。

    BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore,BaseType_t *pxHigherPriorityTaskWoken );
    

    失败返回:err_QUEUE_FULL

    成功返回:pdPASS

    5、获取信号量,第二个参数是阻塞时间

    BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );
    

    失败返回:pdFALSE

    成功返回:pdPASS

    6、在中断中获取信号量

    BaseType_t xSemaphoreTakeFromISR( SemaphoreHandle_t xSemaphore,signed BaseType_t *pxHigherPriorityTaskWoken );
    

    失败返回:pdFALSE

    成功返回:pdPASS

    三、计数型信号量

    1、简介

    二值信号量相当于长度为1的队列,那么计数型信号量就是长度大于1的队列。主要用于计数事件和资源管理等应用场景。

    2、计数型信号量的操作

    1、动态创建计数型信号量

    uxMaxCount:计数型信号量的最大值,超过这个最大值释放信号量就会失败

    uxInitialCount:计数型信号量分初始值

    SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount,UBaseType_t uxInitialCount );
    

    失败返回NULL,

    成功返回计数信号量的句柄。

    2、静态创建计数型信号量

    uxMaxCount:计数型信号量的最大值,超过这个最大值释放信号量就会失败

    uxInitialCount:计数型信号量分初始值

    pxSempahoreBuffer:用来保存信号量的结构体

    SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount,UBaseType_t uxInitialCount,StaticSemaphore_t pxSempahoreBuffer );
    

    失败返回NULL,

    成功返回计数信号量的句柄。

    3、释放和获取信号量与二值信号量相同。

    四、互斥信号量

    1、互斥信号量的简介

    互斥信号量就是一个拥有优先级继承的二值信号量。

    互斥信号量不能在中断服务函数中使用:

    1、互斥信号量具有优先级继承机制,所以只能在任务重使用

    2、中断服务函数不能因为要等待互斥信号量而设置阻塞延时,进入阻塞态

    2、创建互斥信号量

    1、动态创建互斥信号量

    SemaphoreHandle_t xSemaphoreCreateMutex(void);
    

    失败返回NULL,

    成功返回互斥信号量的句柄。

    2、静态创建互斥信号量

    pxMutexBuffer:用来保存信号量的结构体

    SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer );
    

    失败返回NULL,

    成功返回互斥信号量的句柄。

    3、释放和获取信号量与二值信号量相同。只是不能用在中断服务函数的API

    展开全文
  • 二十四、freertos信号量-二值信号量-中断方式 源码: main.c /** 1. 学习FreeRTOS的二值信号量(中断方式) 2. 使用二值信号量实现任务同步功能 **/ #include <stdio.h> #include "board.h" #include "led.h...

    二十四、freertos信号量-二值信号量-中断方式

    源码:

    main.c

    /**
    1. 学习FreeRTOS的二值信号量(中断方式)
    2. 使用二值信号量实现任务同步功能
    **/
    #include <stdio.h>
    #include "board.h"
    #include "led.h"
    #include "key.h"
    #include "uart.h"
    #include "tim_mrt.h"
    
    
    /*** System oscillator rate and clock rate on the CLKIN pin  ****/
    /**/const uint32_t OscRateIn = MAIN_OSC_XTAL_FREQ_HZ;		 /**/
    /**/const uint32_t ExtRateIn = EXT_CLOCK_IN_FREQ_HZ;		 /**/
     //系统复位
    #define	System_restart	(LPC_SWM->PINENABLE0 = 0xffffffffUL) /**/
    /***************************************************************/
    static void TIM_CallBack1(void);
    
    
    
    #include "FreeRTOSConfig.h"
    /* FreeRTOS头文件 */
    #include "FreeRTOS.h"
    #include "task.h"
    #include "event_groups.h"//事件头文件
    #include "queue.h"//队列头文件
    #include "semphr.h"//信号量头文件
    
    
    #define TASK_STACK_SIZE 32
    /**************************** 任务句柄 ********************************/
    /* 
     * 任务句柄是一个指针,用于指向一个任务。
     */
    
    static TaskHandle_t LED1_Task_Handle= NULL;	
    static xTaskHandle KEY_Task_Handle = NULL;	
    static xSemaphoreHandle BinarySem_Handle = NULL;
    
    
    
    /* Sets up system hardware 
    **********************************************************************
      * @ 函数名  : BSP_Init
      * @ 功能说明: 板级外设初始化,所有板子上的初始化均可放在这个函数里面
      * @ 参数    :   
      * @ 返回值  : 无
    	*********************************************************************/
    	static void prvSetupHardware(void)
    	{
    
    	SystemCoreClockUpdate();
    
    	DEBUGINIT();
    	led_Init() ;	
    	Key_INIT();
    	MRT_Init();
    
    	Board_UARTPutSTR("build date: " __DATE__ " build time: " __TIME__ "\n");
    
    }
    
    /*
    *********************************************************************************************************
    *	函 数 名: vKEY_task
    *	功能说明: 按键任务
    *	形    参: pvParameters 是在创建该任务时传递的形参
    *	返 回 值: 无
    *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
    *********************************************************************************************************
    */
    static void vKEY_task(void* pvParameters)
    {
    
    	uint8_t pcWriteBuffer[200];
    
    
    ​	 
    	u8 key2=0;
    	while(1)
    	{
    		u8 key=0;
    		if(Scan_Key())
    			vTaskDelay(20);
    		else continue;
    		if(!Scan_Key())continue;
    		else
    		{
    			key=Scan_Key();
    			key2=key;
    		}
    		
    		while(Scan_Key()){};//等按键抬起
    	
    		if(key2)
    		{
    	
    			switch(key2)
    			{
    				case 1:
    				{
    					printf("=================================================\r\n");
    					printf("任务名      任务状态 优先级   剩余栈 任务序号\r\n");
    					vTaskList((char *)&pcWriteBuffer);
    					printf("%s\r\n", pcWriteBuffer);
    				 
    				}break;
    				case 2:
    				{
    					printf("K2键按下,启动单次定时器中断,100ms后在定时器中断给任务vTaskMsgPro发送消息\r\n");
    					bsp_HardTimer(2,(void *)TIM_CallBack1);
    	
    				}break;
    				case 3:
    				{
    
    
     					
    				}break;
    				default:break;
    			}
    			key2=0;
    		}}
    }
    
    /**********************************************************************
      * @ 函数名  : vLED_Task0
      * @ 功能说明: LED_Task任务主体,接收任务 vKEY_task 发送的消息队列数据(xQueue2)
      * @ 参数    :   
      * @ 返回值  : 无
        ********************************************************************/
    
    static void vLED1_Task (void *pvParameters)
    {
    	
    	TickType_t xLastWakeTime;
    	const TickType_t xFrequency = 500;
    	/* 获取当前的系统时间 */
    	xLastWakeTime = xTaskGetTickCount();
    	 
    	while (1) {
    		
    		Board_LED_Toggle(0);
    		vTaskDelayUntil(&xLastWakeTime, xFrequency);
    	
    	}
    
    }
    
    /*
    *********************************************************************************************************
    *	函 数 名: vTaskMsgPro
    *	功能说明: 使用函数 xQueueReceive 接收任务 vKEY_task 发送的消息队列数据(xQueue1)
    *	形    参: pvParameters 是在创建该任务时传递的形参
    *	返 回 值: 无
    *   优 先 级: 3  
    *********************************************************************************************************
    */
    static void vTaskMsgPro(void *pvParameters)
    {
    	BaseType_t xResult;
    	const TickType_t xMaxBlockTime = pdMS_TO_TICKS(300); /* 设置最大等待时间为300ms */
    	
        while(1)
        {
        	/* 获取K2按键按下的信号 */
        	xResult = xSemaphoreTake(BinarySem_Handle,xMaxBlockTime); 
        	/* 成功接收,并通过串口将数据打印出来 */
        	if(xResult == pdTRUE)
        	{
        		/* 接收到同步信号 */
        		printf("接收到同步信号\r\n");
        		Board_LED_Toggle(1);
        	}
        	else
        	{
        		/* 超时 */
        		
        	}
        	
        }
    }
    
    /*
    *********************************************************************************************************
    *	函 数 名: AppObjCreate
    *	功能说明: 创建任务通信机制
    *	形    参: 无
    *	返 回 值: 无
    *********************************************************************************************************
    */
    static void AppObjCreate (void)
    {
    	/* 创建二值信号量,首次创建信号量计数值是0 */
    	BinarySem_Handle = xSemaphoreCreateBinary();
    	if(NULL == BinarySem_Handle)
     	{
    		/* 没有创建成功*/
    		DEBUGSTR("二值信号量创建失败\n");
    	}
    	
    	
    }
    /***********************************************************************
      * @ 函数名  : AppTaskCreate
      * @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面
      * @ 参数    : 无  
      * @ 返回值  : 无
        **********************************************************************/
    	static void AppTaskCreate()
    	{
    	BaseType_t xReturn=pdPASS;/*定义任务返回值*/
    	
    	taskENTER_CRITICAL();//进入临界区,禁止中断打断
    
    
    	xReturn=xTaskCreate(vLED1_Task, 
    						"vLED1_Task",
    						TASK_STACK_SIZE*2, 
    						NULL, 
    						(tskIDLE_PRIORITY + 1UL),
    						(TaskHandle_t *) &LED1_Task_Handle);
    	
    	xReturn=xTaskCreate(vKEY_task, 
    						"vKEY_Task",
    						TASK_STACK_SIZE*4, 
    						NULL, 
    						(tskIDLE_PRIORITY + 1UL),
    						(TaskHandle_t *) &KEY_Task_Handle);
    	
    	xReturn=xTaskCreate(vTaskMsgPro, 
    						"vTaskMsgPro",
    						TASK_STACK_SIZE*5, 
    						NULL, 
    						(tskIDLE_PRIORITY + 3UL),
    						NULL);
    				
    	if(pdPASS==xReturn)
    	{
    		printf("创建LED_Task任务成功\r\n");
    	}taskEXIT_CRITICAL(); //退出临界区
    
    
    }
    
    /**
     * @brief	main routine for blinky example
     * @return	Function should not exit.
     */
    	int main(void)
    	{
    	
    	prvSetupHardware();
    	Board_UARTPutSTR("LPC824 FreeRTOS 任务管理\n\r");
    	printf("Key按下中断中发送信号量\r\n");
    
    	AppTaskCreate();
    	
    	/* 创建任务通信机制 */
    	AppObjCreate();
    	
    	vTaskStartScheduler();//任务调度
    
    	
    	
    	/* Loop forever */
    	while (1) {
    			printf("FreeRTOS 运行失败\n\r");
    
     	}}
    
    
    /*
    *********************************************************************************************************
    *	函 数 名: TIM_CallBack1和TIM_CallBack2
    *	功能说明: 定时器中断的回调函数,此函数被bsp_HardTimer所调用。		  			  
    *	形    参: 无
    *	返 回 值: 无
    *********************************************************************************************************
    */
    static void TIM_CallBack1(void)
    {
    	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    	
    	
    
    	/* 发送同步信号 */
    	xSemaphoreGiveFromISR(BinarySem_Handle, &xHigherPriorityTaskWoken);/* 如果xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */
    	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);					  
    
    
    }
    

    tim_mrt.h

    #ifndef _TIM_MRT_H_
    #define _TIM_MRT_H_
     
    void MRT_Init(void);
    void setupMRT(uint8_t ch, MRT_MODE_T mode, uint32_t rate);
    void bsp_HardTimer(u8 ch, void * _pCallBack);
    
    #endif
    

    tim_mrt.c

    /*
     * 	注意,MRT定时器有4个独立通道,但共用中断号10。
     */
    #include "board.h"
    #include "tim_mrt.h"
    /*****************************************************************************
     * Private types/enumerations/variables
     ****************************************************************************/
    
    /* 保存 TIM定时中断到后执行的回调函数指针 */
    static void (*s_TIM_CallBack0)(void);
    static void (*s_TIM_CallBack1)(void);
    static void (*s_TIM_CallBack2)(void);
    static void (*s_TIM_CallBack3)(void);
    
     
    
    /*****************************************************************************
     * Public types/enumerations/variables
     ****************************************************************************/
    
     
     
    /* Interrupt fire reference counters for t0/1, t2, and t3 */
    //bool Ms500;
    //static uint32_t t01 , t3;
    //static uint32_t t2;
    
    /*****************************************************************************
     * Private functions
     ****************************************************************************/
    
    /*  设置定时器
    
    参数:
    ch :定时器通道(0,1,2,3)
    mode :模式(单次或者循环)
    rate :速率,数字越小,间隔越长。
    	--	1 表示 1Hz,即1s。
    	--	2 表示 2Hz,即500ms。
    	--	100表示100Hz,即10ms。
    */
    void setupMRT(uint8_t ch, MRT_MODE_T mode, uint32_t rate)
    {
    	LPC_MRT_CH_T *pMRT;
    	 
    	pMRT = Chip_MRT_GetRegPtr(ch); //返回定时器的指针 
    
    									//12MHz
    	Chip_MRT_SetInterval(pMRT, (Chip_Clock_GetSystemClockRate() / rate) |\
    						 MRT_INTVAL_LOAD);//立即加载
     
    	Chip_MRT_SetMode(pMRT, mode);
    	/* Clear pending interrupt and enable timer */
    	Chip_MRT_IntClear(pMRT); 
    	Chip_MRT_SetEnabled(pMRT); 
    }
    
    /*****************************************************************************
     * Public functions
     ****************************************************************************/
    
    /**
     * @brief	MRT example main function
     * @return	Status (This function will not return)
     */
    void MRT_Init(void)
    {
    	
    	Chip_MRT_Init();//启用MRT时钟,复位MET
    	Chip_MRT_SetDisabled(Chip_MRT_GetRegPtr(3));//禁用定时器通道3
    	Chip_MRT_SetDisabled(Chip_MRT_GetRegPtr(2));//禁用定时器通道2 
    	
    	NVIC_EnableIRQ(MRT_IRQn);	//启用定时器外设中断
    
    	//通道初始化
    //	setupMRT(2, MRT_MODE_REPEAT, 100); //10ms循环
    //	setupMRT(3, MRT_MODE_ONESHOT, 2); //单次,中断只发生一次,需要再次赋值。
    //	setupMRT(3, MRT_MODE_REPEAT, 1); //1s循环
    
    
    }
    
    /**
     * @brief	Handle interrupt from MRT
     * @return	Nothing
     */
    void MRT_IRQHandler(void)
    {
    	uint32_t int_pend;
    
    	int_pend = Chip_MRT_GetIntPending();
    	Chip_MRT_ClearIntPending(int_pend);
    
    	 //判断中断通道0和1
    	if (int_pend & (MRTn_INTFLAG(0) | MRTn_INTFLAG(1))) {
    		Board_LED_Set(4, true);
    
    		s_TIM_CallBack0();
    		s_TIM_CallBack1();
    	}
    
    	 //判断中断通道2
    	if (int_pend & (MRTn_INTFLAG(2))) {	 
    
    		s_TIM_CallBack2();
    //		t2++;
    		
    	}
    
    	 //判断中断通道3
    	if (int_pend & (MRTn_INTFLAG(3))) {
    		
    		s_TIM_CallBack3();
    
    	}
    }
    
    /*
    *********************************************************************************************************
    *	函 数 名: bsp_HardTimer
    *	功能说明: 定时时间到后执行回调函数。
    *	形    参: 
    			ch: 多速率定时器通道(0,1,2,3)
    *             _pCallBack : 定时时间到后,被执行的函数
    *	返 回 值: 无
    *********************************************************************************************************
    */
    void bsp_HardTimer(u8 ch,void * _pCallBack)
    {
    	
    	switch(ch)
    	{
    		case 0:	{}break;
    		case 1:{}break;
    		case 2:
    		{
    			//因为函数指针赋值后才能正常运行,所以必须在调用时再初始化。
    			setupMRT(2, MRT_MODE_ONESHOT, 100); //100ms单次
    			s_TIM_CallBack2=(void (*)(void))_pCallBack;
    		}break;
    		case 3:
    		{
    			setupMRT(3, MRT_MODE_ONESHOT, 1); //1s单次
    			s_TIM_CallBack3=(void (*)(void))_pCallBack;
    		}break;
    		default:break;
    	}
    	 
    	
    }
    /**
    *END_TMI
    */
    
    展开全文
  • 信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务之间同步或临界资源的互斥访问, 常用于协助一组相互竞争的任务来访问临界资源。在多任务系统中,各任务之间需要同步或互斥实现临界资源的保护,信号量...
  • 信号量是操作系统中重要的一部分,信号量一般用来进行资源管理和任务同步,FreeRTOS信号量又分为二值信号量、计数型信号量、互斥信号量和递归互斥信号量。不同的信号量其应用场景不同,但有些应用场景是可以互换着...
  • FreeRTOS信号量 基于STM32

    千次阅读 2022-07-03 08:29:25
    FRTOS基于STM32怎么创建、删除信号量和怎么发送、获得信号量
  • 22 freertos信号量

    2022-01-04 22:21:03
    二十二、LPC824_freertos信号量 一、信号量 1. 二值信号量:只有两种状态,有或无。 2. 计数信号量:释放一个信号量时,信号量计数值加1。处理一个信号量时,信号量计数值减1。 3. 互斥信号量:是特殊的二值信号量,...
  • 本项目设计一个类似自行车码表的产品,除了LCD显示骑行速度、骑行里程外、日期时间外,增加了GPS卫星状态、电池...任务间通过队列交互信息,通过二值信号量阻塞相关任务,完成任务调度。在空闲任务中进入低功耗模式。
  • 有些资料中也将计数型信号量叫做数值信号量,二值信号量相当于长度为1的队列,那么计数型信号量就是长度大于1的队列。**同二值信号量一样,用户不需要关心队列中存储了什么数据,只需要关心队列是否为空即可。**计数...
  • 创建二进制信号量,并返回一个句柄,通过该句柄可以引用信号...如果使用xSemaphoreCreateBinary()创建二进制信号量,则从FreeRTOS堆自动分配所需的RAM。如果使用xSemaphoreCreateBinaryStatic()创建二进制信号量..
  • FreeRTOS 信号量FreeRTOS 信号量信号量简介二进制信号量计数信号量互斥量递归互斥量 FreeRTOS 信号量 信号量简介 FreeRTOS信号量包括二进制信号量、计数信号量、互斥信号量(以后简称互斥量)和递归互斥信号量...
  • FreeRTOS(18)---FreeRTOS 信号量分析

    千次阅读 2018-10-12 14:51:06
    FreeRTOS 信号量分析FreeRTOS 信号量分析信号量创建创建二进制信号量创建计数信号量创建互斥量创建递归互斥量释放信号量xSemaphoreGive()xSemaphoreGiveFromISR()获取信号量xSemaphoreTakexSemaphoreTakeFromISR()...
  • ESP32 FreeRTOS信号量

    2021-06-13 21:52:20
    开发板:NodeMCU 32 V1.3 开发板引脚图: ...(2)任务2接收信号量,如果在一定时间内接收到信号量,则翻转LED灯;这个时间由函数xSemaphoreTake的第二个参数决定,该函数原型为:BaseType_t xSem
  • FreeRTOS 信号量API函数FreeRTOS 信号量API函数创建二进制信号量函数描述返回值用法举例创建计数信号量函数描述参数描述返回值用法举例创建互斥量函数描述返回值用法举例创建递归互斥量函数描述返回值用法举例删除...
  • FreeRtos信号量详解 文章目录FreeRtos信号量详解前言一、信号量介绍二、二值信号量2.1 二值信号量介绍2.2 二值信号量的创建2.3 二值信号量释放2.4 二值信号量获取2.5 二值信号量实验演示三、计数型信号量3.1 计数型...
  • 我当时使用的是FreeRTOS 9,而在设备在某一些时刻会出现异常的通讯问题,且问题呈现概率式的分布,我查看了很长时间才找到问题点。所以在这里作为记录,聊以备忘并且希望可以给一些遇到差不多的问题的同志一些思路
  • STM32F103 Freertos信号量

    2017-02-14 09:44:25
    STM32F103 Freertos信号量
  • 二十五、LPC824_freertos信号量-计数信号量 /** **************************************************************************************************/ #include <stdio.h> #include "board.h" #include ...
  • FreeRTOS,简单,易用,强大,并针对Arduino IDE进行了优化。 使用FreeRTOS信号量共享和保护物理资源。
  • 我们在前面单独介绍过FreeRTOS的任务通知和消息队列, 但是在FreeRTOS中任务间的通讯还有信号量,邮箱,事件组标志等可以使用 这篇文章就这些成员与消息队列和任务通知的关系进行说明分析
  • 一、互斥信号量简介 ...互斥信号量使用和二值信号量相同的API操作函数,所以互斥信号量也可以设置阻塞时间,不同于二值信号量的是互斥信号量具有优先级继承的特性。当一个互斥信号量正在被一个低优先
  • 默认配置创建的FreeRTOS 工程,手动在任务中创建信号量,没有配置configUSE_COUNTING_SEMAPHORES 所以创建的都是二值量 osSemaphoreDef(Log_rx_Sem); log_rx_SemHandle = osSemaphoreCreate(osSemaphore(Log_rx_...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,551
精华内容 1,820
关键字:

freertos信号量