freertos stm32xsemaphoretake 没有

后使用快捷导航没有帐号?
查看: 649|回复: 5
STM32F107VCT6金龙107 Freertos实验
在线时间79 小时
威望308 分
芯币497 枚
TA的帖子TA的资源
一粒金砂(高级), 积分 308, 距离下一级还需 192 积分
一粒金砂(高级), 积分 308, 距离下一级还需 192 积分
实验一、任务调度
本节我们主要介绍的是Freertos的任务创建,及任务调度。1、任务创建对于操作系统的学习,创建任务是首要工作,freertos对任务的数量没有限制,而且同一个优先级可以有多个任务。创建任务使用FreeRTOS的API函数xTaskCreate(),其函数原型及参数描述如下:portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode, const signed portCHAR * const pcName, unsigned portSHORT usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask ); pvTaskCode&&& & & & 任务函数名,实现常通常是一个死循环。pcName&&& & & & & & & & 具有描述性的任务名。(最大长度通过由config_MAX_TASK_NAME_LEN来定义,大于最大长度会被自动截断)usStackDepth&&& & & & 内核为任务分配堆栈空间大小usStackDepth字。(应用程序通过定义常量configMINIMAL_STACK_SIZE来决定空闲任务任用的栈空间大小)pvParameters&&& & & & 任务函数接受一个指向void的指针(void*)。pvParameters的值即是传递到任务中的值。uxPriority&&& & & & & & & & 指定任务执行的优先级。优先级的取值范围可以从最低优先级0到最高优先级(configMAX_PRIORITIES–1),数值越小优先级越高。pxCreatedTask&&pxCreatedTask用于传出任务的句柄。这个句柄将在API调用中对该创建出来的任务进行引用,比如改变任务优先级,或者删除任务。如果应用程序中不会用到这个任务的句柄,则pxCreatedTask可以被设为NULL。返回值&&& & & & & & & & 有两个可能的返回值:1)pdTRUE 表明任务创建成功。2)errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY 由于内存堆空间不足,FreeRTOS无法分配足够的空间来保存任务结构数据和任务栈,因此无法创建任务。2、任务调度方法FreeRTOS支持多个任务具有相同的优先级,因此,当它被配置为可抢占内核时,调度算法既支持基于优先级的调度,也支持时间片轮流调度。任何时候调度器运行时它都选择处于就绪状态下的优先级最高的那个任务;如果有多个任务处于同一优先级,则FreeRTOS每个时钟节拍的中断服务程序中,将对这些任务应用换调度算法,轮流执行这些任务。 优先级的调度执行流程 时间片的调度执行流程3、实验分析本次实验创建两个优先级不同的任务,采用优先级调度,两个任务分别控制两个LED灯的点亮与熄灭,向串口打印任务名后延时挂起。其源代码如下:/*****主函数*****/int main(void){& & & & USART_Configuration();&&& & & & //串口初始化& & & & LED_Configuration();& & & & xTaskCreate( vLED1Task, ( signed portCHAR * ) &vLED1Task&, configMINIMAL_STACK_SIZE, NULL, vLED1Task_PRIORITY, NULL );//创建一个让LED1闪烁的任务& & & & & & & & xTaskCreate( vLED2Task, ( signed portCHAR * ) &vLED2Task&, configMINIMAL_STACK_SIZE, NULL, vLED2Task_PRIORITY, NULL );//创建一个让LED2闪烁的任务& & & & vTaskStartScheduler();& & & & //开始任务调度& & & & while(1);} //LED1闪烁任务void vLED1Task( void *pvParameters ){& & & & while(1){& & & & & & & & GPIO_ResetBits(LED1_GPIO,LED1_GPIO_Pin);& &//点亮LED1& & & & & & & & vTaskDelay(3000);& & & & & & & & GPIO_SetBits(LED1_GPIO,LED1_GPIO_Pin);& & & && & //熄灭LED1& & & & & & & & printf(&\r\nvLED1Task&);& & & & & & & & vTaskDelay(3000);& & & & }}//LED2闪烁任务void vLED2Task( void *pvParameters ){& & & & while(1){& & & & & & & & GPIO_ResetBits(LED2_GPIO,LED2_GPIO_Pin);& &//点亮LED2& & & & & & & & vTaskDelay(1000);& & & & & & & & GPIO_SetBits(LED2_GPIO,LED2_GPIO_Pin);& & & && & //熄灭LED2& & & & & & & & printf(&\r\nvLED2Task&);& & & & & & & & vTaskDelay(1000);& & & & }}如下图是串口打印的数据,通过修改vTaskDelay()的延时值,可以看到打印速度的变化及两个字符串打印出来的比例。
本帖子中包含更多资源
才可以下载或查看,没有帐号?
在线时间79 小时
威望308 分
芯币497 枚
TA的帖子TA的资源
一粒金砂(高级), 积分 308, 距离下一级还需 192 积分
一粒金砂(高级), 积分 308, 距离下一级还需 192 积分
实验三、二值信号量
本节我们主要介绍的是Freertos的二值信号量1、信号量介绍信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号量在此过程中负责数据操作的互斥、同步等功能。当请求一个使用信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可用。如果大于0则资源可以请求,等于0则无资源可用,进程会进入睡眠状态直至资源可用。Freertos提供了两种信号量:二值信号量和计数信号量。二值信号量只有两种状态即0和1,当任务调用P(Take-信号量减1)操作判断信号量是否为1,若不为1则获取失败进入阻塞,等待信号量为1,当其他任务或中断进行V(Give-信号量加1)操作,此时信号量为1,使得阻塞的任务解除阻塞P操作成功对信号量减1后为0。如下图是实现任务与中断同步: 在中断以相对较慢的频率发生的情况下,上面描述的流程是足够而完美的。如果在延迟处理任务完成上一个中断事件的处理之前,新的中断事件又发生了,等效于将新的事件锁存在二值信号量中,使得延迟处理任务在处理完上一个事件之后,立即就可以处理新的事件。也就是说,延迟处理任务在两次事件处理之间,会有进入阻塞态的机会,因为信号量中锁存有一个事件,所以当SempaphoreTake()调用时,信号量立即有效。一个二值信号量只可以锁存一个中断事件,在锁存的事件还未被处理之前,如果还有中断事件发生,那么后续发生的中断事件将会丢失。如果用计数信号量代替二值信号量,那么,这种丢中断的情形将可以避免。如下图是计数信号量对事件“计数(Count)”: 2、信号量操作Freertos提供了一系列函数对信号量进行创建、获取和给出等。1)创建信号量void vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore );//二值信号量 xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE & & & & & & & & & & & & & & & & uxMaxCount, unsigned portBASE_TYPE uxInitialCount );//计数信号量xSemaphore & & & & & & & & 信号量的句柄uxMaxCount&&& & & & 最大计数值uxInitialCount&&信号量的初始计数值返回值&&& & & & & & & & NULL创建失败&&否则信号量的句柄2)信号量获取xSemaphoreTake( )portBASE_TYPE xSemaphoreTake( xSemaphoreHandle xSemaphore, & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & portTickType xTicksToWait )xSemaphore& & & & & & & & 信号量的句柄xTicksToWait&&& & & & 阻塞超时时间。任务进入阻塞态以等待信号量有效的最长时间。如果xTicksToWait为0,则xSemaphoreTake()在信号量无效时会立即返回。如果设置为portMAX_DELAY,并且在FreeRTOSConig.h中设定INCLUDE_vTaskSuspend为1,那么阻塞等待将没有超时限制。返回值&&& & & & & & & & pdPASS获取成功&&pdFALSE获取失败 3)信号量给出xSemaphoreGiveFromISR()和xSemaphoreGive()portBASE_TYPE xSemaphoreGiveFromISR( xSemaphoreHandle xSemaphore, portBASE_TYPE *pxHigherPriorityTaskWoken )& & & & //中断模式下xSemaphoreGive(xSemaphoreHandle&&xSemaphore )& & & & & & & & //任务模式下xSemaphore& & & & & & & & 信号量的句柄pxHigherPriorityTaskWoken& & & & pdTRUE:在中断退出前应当进行一次上下文切换,pdFALSE:若给出信号量是的解除阻塞任务优先级高于当前任务优先级(被中断的任务)则,函数内部将该值设为pdTRUE。返回值& & & & & & & & & & & & pdPASS给出成功 pdFAIL 无法给出。3、实验分析本实验分为中断管理的二值信号量同步和计数信号量同步,在工程中创建两个任务,阻塞在获取信号量,分别使用两个外部中断给出信号量使得程序继续运行,其源代码如下(二值信号量和计数信号量创建不同):/*****主函数*****/int main(void){& & & & USART_Configuration();&&& & & & //串口初始化& & & & LED_Configuration();& & & & & & & & vSemaphoreCreateBinary( xBinarySemaphore1 );//创建二值信号量& & & & vSemaphoreCreateBinary( xBinarySemaphore2 );//创建二值信号量& & & & xSemaphoreTake(xBinarySemaphore1,portMAX_DELAY) ;& & & & & & & & //由于创建时进行了一次V操作,因此这里进行一次P操作& & & & xSemaphoreTake(xBinarySemaphore2,portMAX_DELAY) ;& & & & NVIC_Configuration();& & & & GpioLed_Init();& & & & & & & &&&& & & & & & & & //LED灯初始化& & & & USART1_Configuration();& & & & & & & & printf(&\r\n&);& & & & printf(&\r\n二值信号量实验&); & & & & xTaskCreate( vLED1Task, ( signed portCHAR * ) &LED&, configMINIMAL_STACK_SIZE, NULL, vLED1Task_PRIORITY, NULL );//创建一个让LED1闪烁的任务& & & & & & & & xTaskCreate( vLED2Task, ( signed portCHAR * ) &LED&, configMINIMAL_STACK_SIZE, NULL, vLED2Task_PRIORITY, NULL );//创建一个让LED2闪烁的任务& & & & vTaskStartScheduler();& & & & //开始任务调度& & & & while(1);} //LED1闪烁任务void vLED1Task( void *pvParameters ){& & & & while(1){& & & & & & & & xSemaphoreTake(xBinarySemaphore1,portMAX_DELAY) ;& & & & & & & & printf(&\r\nvLED1Task&);& & & & }}//LED2闪烁任务void vLED2Task( void *pvParameters ){& & & & while(1){& & & & & & & & xSemaphoreTake(xBinarySemaphore2,portMAX_DELAY) ;& & & & & & & & printf(&\r\nvLED2Task&);& & & & }} void EXTI9_5_IRQHandler(void){& & & & static portBASE_TYPE xHigherPriorityTaskWoken1; & & & & xHigherPriorityTaskWoken1 = pdFALSE; & & & & if(EXTI_GetITStatus(EXTI_Line8)!= RESET)&&& & & & {&&& & & & & & & & EXTI_ClearITPendingBit(EXTI_Line8);xSemaphoreGiveFromISR( xBinarySemaphore1, &xHigherPriorityTaskWoken1 );& & & & }&&} void EXTI3_IRQHandler(void){& & & & static portBASE_TYPE xHigherPriorityTaskWoken2; & & & & xHigherPriorityTaskWoken2 = pdFALSE; & & & & if(EXTI_GetITStatus(EXTI_Line3)!= RESET)&&& & & & {&&& & & & & & & & EXTI_ClearITPendingBit(EXTI_Line3);xSemaphoreGiveFromISR( xBinarySemaphore2, &xHigherPriorityTaskWoken2 );& & & & }&&}程序使用按键USER1和USER2连接到外部中断线,USER1控制向xBinarySemaphore1给出信号,USER2控制向xBinarySemaphore2给出信号,如下图是按下USER1和USER2后的串口输出结果:
本帖子中包含更多资源
才可以下载或查看,没有帐号?
在线时间79 小时
威望308 分
芯币497 枚
TA的帖子TA的资源
一粒金砂(高级), 积分 308, 距离下一级还需 192 积分
一粒金砂(高级), 积分 308, 距离下一级还需 192 积分
实验四、计数信号量
上一节我们对计数信号量和二值信号量进行了说明,本节我们主要分析Freertos的计数信号量程序1、实验分析本实验在工程中创建两个任务,任务一每次发送三次信号,任务二阻塞在获取信号量,并打印状态,其源代码如下:/*****主函数*****/int main(void){& & & & USART_Configuration();&&& & & & //串口初始化& & & & LED_Configuration();& & & & xSemaphore = xSemaphoreCreateCounting( 10,5); & & & & //信号量,改变初始值可以看到第一次打印的接收数量有变化& & & & if(xSemaphore == NULL)& & & & {& & & & & & & & printf(&\r\n创建信号量失败\r\n&);& & & & & & & & while(1);& & & & } & & & & xTaskCreate( vLED1Task, ( signed portCHAR * ) &LED&, configMINIMAL_STACK_SIZE, NULL, vLED1Task_PRIORITY, NULL );//创建一个让LED1闪烁的任务& & & & & & & & xTaskCreate( vLED2Task, ( signed portCHAR * ) &LED&, configMINIMAL_STACK_SIZE, NULL, vLED2Task_PRIORITY, NULL );//创建一个让LED2闪烁的任务& & & & vTaskStartScheduler();& & & & //开始任务调度& & & & while(1);} //LED1闪烁任务void vLED1Task( void *pvParameters ){& & & & for(;;){& & & & & & & & printf(&\r\n发送数据3次\r\n&);& & & & & & & & xSemaphoreGive(xSemaphore);& & & & //三次给出信号量& & & & & & & & xSemaphoreGive(xSemaphore);& & & & & & & & xSemaphoreGive(xSemaphore);& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & vTaskDelay(1000);& & & & }}//LED2闪烁任务void vLED2Task( void *pvParameters ){& & & & portBASE_TYPE xS& & & & while(1)& & & & {& & & & & & & & xStatus=xSemaphoreTake( xSemaphore, portMAX_DELAY );& & & & //得到一次信号量& & & & & & & & printf(&\r\n接收到数据\r\n&);& & & & & & & & //打印提示& & & & }} 如下图是串口输出结果:
本帖子中包含更多资源
才可以下载或查看,没有帐号?
在线时间79 小时
威望308 分
芯币497 枚
TA的帖子TA的资源
一粒金砂(高级), 积分 308, 距离下一级还需 192 积分
一粒金砂(高级), 积分 308, 距离下一级还需 192 积分
实验二、消息队列
本节我们主要介绍的是Freertos的通信方式--消息队列1、队列介绍FreeRTOS中所有的通信与同步机制都是基于队列实现的,队列可以保存有限个具有确定长度的数据单元。队列可以保存的最大单元数目被称为队列的“深度”。在队列创建时需要设定其深度和每个单元的大小。通常情况下,队列被作为FIFO(先进先出)使用,即数据由队列尾写入,从队列首读出。当然,由队列首写入也是可能的。往队列写入数据是通过字节拷贝把数据复制存储到队列中;从队列读出数据使得把队列中的数据拷贝删除。下图展现了队列的写入与读出过程,以及读写操作对队列中数据的影响 2、队列操作Freertos提供了一系列函数对队列进行创建、接收和发送等。1)创建队列xQueueCreate()xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ); uxQueueLength&&& & & & 队列能够存储的最大单元数目,即队列深度。uxItemSize&&& & & & & & & & 队列中数据单元的长度,以字节为单位。返回值& & & & & & & & & & & & & & & & NULL表示没有足够的堆空间分配给队列而导致创建失败。非NULL值表示队列创建成功。此返回值应当保存下来,以作为操作此队列的句柄。2)将数据发送到队列尾xQueueSendToBack()与头xQueueSendToFront() portBASE_TYPE xQueueSendToFront( xQueueHandle xQueue, const void * pvItemToQueue, portTickType xTicksToWait );portBASE_TYPE xQueueSendToBack( xQueueHandle xQueue, const void * pvItemToQueue, portTickType xTicksToWait ); xQueue&&& & & & & & & & & & & & 目标队列的句柄。pvItemToQueue&&& & & & 发送数据的指针。xTicksToWait & & & &&&& & & & 阻塞超时时间。如果在发送时队列已满,这个时间即是任务处于阻塞态等待队列空间有效的最长等待时间。返回值&&& & & & & & & & & & & & 有两个可能的返回值: 1、pdPASS & & & & & & & & & & & & 数据被成功发送到队列中。2、errQUEUE_FULL 如果由于队列已满而无法将数据写入,则将返回errQUEUE_FULL。3)从队列中接收数据,接收后删除xQueueReceive()与不删除xQueuePeek()portBASE_TYPE xQueueReceive( xQueueHandle xQueue, const void * pvBuffer, portTickType xTicksToWait );portBASE_TYPE xQueuePeek( xQueueHandle xQueue, const void * pvBuffer, portTickType xTicksToWait ); xQueue&&& & & & & & & & 被读队列的句柄。pvBuffer&&& & & & & & & & 接收缓存指针。xTicksToWait&&& & & & 阻塞超时时间。返回值&&& & & & & & & & 有两个可能的返回值: 1.pdPASS & & & & & & & & 成功地从队列中读到数据。2.errQUEUE_FULL 如果在读取时由于队列已空而没有读到任何数据,则将返回errQUEUE_FULL。4)查询队列中有效数据的个数uxQueueMessagesWaiting()unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle xQueue ); xQueue&&被查询队列的句柄。的返回值。返回值&&当前队列中保存的数据单元个数。返回0表明队列为空。3、实验分析实验创建两个任务,一个用于向队列发送数据,另一个接收数据。发送任务不停向队列发送数据Send,当队列满后,打印“不能发送数据到消息队列”。接收任务不停的查询队列中有多少个数据,并打印出来,如果有数据就读取出来,并使用串口打印出接收到的数据。其源代码如下:/*****主函数*****/int main(void){USART_Configuration();&&& & & & //串口初始化& & & & LED_Configuration();& & & & xQueue = xQueueCreate( 5, sizeof( long ) ); & & & & //创建队列& & & & //创建一个发送数据任务& & & & xTaskCreate( vSendTask, ( signed portCHAR * ) &LED&, configMINIMAL_STACK_SIZE, NULL, vSendTask_PRIORITY, NULL );& & & & //创建一个接收数据任务& & & & xTaskCreate( vReceiveTask, ( signed portCHAR * ) &LED&, configMINIMAL_STACK_SIZE, NULL, vReceiveTask_PRIORITY, NULL );& & & & vTaskStartScheduler();& & & & //开始任务调度& & & & while(1);}//队列发送任务void vSendTask( void *pvParameters ){& & & & long Send=1;& & & & portBASE_TYPE xS& & & & & & & & while(1){& & & & & & & & xStatus = xQueueSendToBack(xQueue, &Send,0);& & & & & & & & if(xStatus != pdPASS)& & & & & & & & {& & & & & & & & & & & & printf(&\r\n不能发送数据到消息队列\r\n&);& & & & & & & & }& & & & & & & & else Send++;& & & & & & & & & & & & & & & & vTaskDelay(500);& & & & }}//队列接收任务void vReceiveTask( void *pvParameters ){& & & & long R & & & & portBASE_TYPE xS & & & & portBASE_TYPE& & & & const portTickType xTicksToWait = 100 / portTICK_RATE_MS; & & & & & & & & while(1){& & & & & & & & if( (num=uxQueueMessagesWaiting( xQueue )) != 0 ) & & & & & & & & { & & & & & & & & & & & & printf( &\r\n消息队列中有%d个数据 &,num ); & & & & & & & & }& & & & & & & & else& & & & & & & & & & & & printf( &\r\n消息队列为空&); & & & & & & & & xStatus = xQueueReceive( xQueue, &Received, xTicksToWait ); & & & & & & & & if( xStatus == pdPASS ) & & & & & & & & { & & & & & & & & & & & & printf( &\r\n读出的数据为%d&, Received ); & & & & //打印数据& & & & & & & & } & & & & & & & & else & & & & & & & & { & & & & & & & & & & & & /* 等待100ms也没有收到任何数据。& & & & & & & & & & & & & & & & 必然存在错误,因为发送任务在不停地往队列中写入数据*/ & & & & & & & & & & & & printf( &不能从消息队列中读取数据\r\n& ); & & & & & & & & } & & & & & & & & & & & & & & & & vTaskDelay(700);& & & & }}如下图是串口打印的数据:
本帖子中包含更多资源
才可以下载或查看,没有帐号?
在线时间8 小时
TA的帖子TA的资源
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
写的不错 学习了
在线时间79 小时
威望308 分
芯币497 枚
TA的帖子TA的资源
一粒金砂(高级), 积分 308, 距离下一级还需 192 积分
一粒金砂(高级), 积分 308, 距离下一级还需 192 积分
写的不错 学习了
Powered by
逛了这许久,何不进去瞧瞧?  semphr. h
  xTake(
  xSemaphoreHandle xSemaphore,
  portTickType xBlockTime
  用于获取信号量的宏。信号量必须已经通过调用vSemaphoreCreateBinary(), xSemaphoreCreateMutex() 或 ()来创建。 这个宏不能在服务中断程序中调用。如果有必要,可以调用xQueueReceiveFromISR() 来在中断服务程序中获取信号量,虽然这并不是一种正规的操作。 xSemaphoreTake() 是一个全功能任务间通讯API, xSemaphoreAltTake() 是其等价的API 。这两个版本均需要同样的参数并返回同样的值。 Parameters: xSemaphore&将被获得的信号量句柄,此信号量必须已经被创建xBlockTime&等待信号量可用的时钟滴答次数,可以使用 portTICK_RATE_MS宏来转换为实际的时间 。当为0时可以用于 对信号量进行轮询(poll the semaphore) 如果INCLUDE_vTaskSuspend置位“1”,则指定xBlockTime为 portMAX_DELAY会导致任务阻塞时间不确定(不会超时)
  返回: 如果成功获取信号量则返回pdTRUE,如果xBlockTime超时而信号量还未可用则返回pdFALSE。 应用范例: xSemaphoreHandle xSemaphore = NULL;
  // A task that creates a semaphore. void vATask( void * pvParameters ) { // 创建一个信号量用于标识一个共享资源。 // 因为我们使用信号量来互斥,因此创建互斥锁信号量而不是二元信号量 xSemaphore = xSemaphoreCreateMutex(); }
  //使用信号量的任务 void vAnotherTask( void * pvParameters ) { // ... 完成其他事情
  if( xSemaphore != NULL ) { // 查看是否可以获得信号量,如果信号量不可用,则用10个时钟滴答来查看信号量是否可用& & & &&&if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE ) { //已经能够获得信号量并且现在可以访问共享资源
  // ...
  // 完成共享资源访问,释放信号量 xSemaphoreGive( xSemaphore ); } else { //无法获取信号量,因此无法安全地访问共享资源 } } }
为本词条添加和相关影像
互动百科的词条(含所附图片)系由网友上传,如果涉嫌侵权,请与客服联系,我们将按照法律之相关规定及时进行处理。未经许可,禁止商业网站等复制、抓取本站内容;合理使用者,请注明来源于。
登录后使用互动百科的服务,将会得到个性化的提示和帮助,还有机会和专业认证智愿者沟通。
您也可以使用以下网站账号登录:
此词条还可添加&
编辑次数:5次
参与编辑人数:5位
最近更新时间: 09:28:43
贡献光荣榜
扫描二维码用手机浏览词条
保存二维码可印刷到宣传品
扫描二维码用手机浏览词条
保存二维码可印刷到宣传品[FreeRTOS] 临界区处理 - kdurant - 博客园
每个进程中访问的那段代码称为临界区(Critical Section) (是一次仅允许一个进程使用的共享资源)。
每次只准许一个进程进入临界区,进入后不允许其他进程进入。不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。
多个进程中涉及到同一个临界资源的临界区称为。
程序调度法则
进程进入临界区的调度原则是:
1. 如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
2. 任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。
3. 进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。
4. 如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
FreeRTOS解决方法
void process_data(void)
taskENTER_CRITICAL(); //or portENTER_CRITICAL();
taskEXIT_CRITICAL();
//or portEXIT_CRITICAL();
抢占式上下文切换只可能在某个中断完成,所以调用taskENTER_CRITICAL()的任务可以在中断关闭的时段一直保持运行态,直到退出临界区
临界区必须只具有很短的时间,否则会影响中断响应时间
使用信号量或者互斥量
推荐使用互斥量,因为互斥量解决了的问题
void process_data(void)
if(xSemaphoreTake(xSemaphore, 10) == pdTRUE)
xSemaphoreGive( xSemaphore );
信号量和互斥量的最大区别是
用于互斥的信号量必须归还
用于同步的信号量在完成同步后变丢弃,不需要归还
禁止任务调度
void process_data(void)
vTaskSuspendAll();
xTaskResumeAll();
如果一段临界区太长而不适合简单的关中断来实现,可以考虑采用挂起调度器的方式
唤醒调度器是一个相对较长的操作
在使用临界区时,一般不允许其运行时间过长,只要进入临界区的线程还没有离开,其他所有试图进入此临界区的线程都会被挂起而进入到等待状态,并会在一定程度上影响程序的运行性能FreeRTOS实时系统简介_图文_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
FreeRTOS实时系统简介
上传于||暂无简介
阅读已结束,如果下载本文需要使用
想免费下载本文?
下载文档到电脑,查找使用更方便
还剩19页未读,继续阅读
你可能喜欢FreeRTOS 的互斥信号量与二进制信号量_stm32吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:13,184贴子:
FreeRTOS 的互斥信号量与二进制信号量收藏
FreeRTOS Ver4.5以上支持两种信号量:
互斥型性号量mutex和二进制信号量binary.二进制信号量相关宏或函数:vSemaphoreCreateBinary
// Macro that creates a Binary semaphorexSemaphoreTake
// Macro to obtain a semaphorexSemaphoreGive
// Macro to release a semaphorexSemaphoreGiveFromISR // Macro to release a semaphore (used from ISR)互斥型信号量相关宏或函数:xSemaphoreCreateRecursiveMutex
// Macro that creates a mutex semaphorexQueueTakeMutexRecursive
// obtain a semaphorexQueueGiveMutexRecursive
// release a semaphore 注:二进制信号量与互斥型信号量比较英文版:
Binary semaphores and mutexes are very similar but have some subtle differences: Mutexes include a priority inheritance mechanism, binary semaphores do not. This makes binary semaphores the better choice for implementing synchronisation (between tasks or between tasks and an interrupt), and mutexes the better choice for implementing simple mutual exclusion.
A binary semaphore need not be given back once obtained, so task synchronisation can be implemented by one task/interrupt continuously 'giving' the semaphore while another continuously 'takes' the semaphore.
The priority of a task that 'takes' a mutex can potentially be raised if another task of higher priority attempts to obtain the same mutex. The task that owns the mutex 'inherits' the priority of the task attempting to 'take' the same mutex. This means the mutex must always be 'given' back - otherwise the higher priority task will never be able to obtain the mutex, and the lower priority task will never 'disinherit' the priority.======================================中文版:互斥型信号量必须是同一个任务申请,同一个任务释放,其他任务释放无效。二进制信号量,一个任务申请成功后,可以由另一个任务释放。二进制信号量实现任务互斥: 打印机资源只有一个,abc三个任务共享,当a取得使用权后,为了防止其他任务错误地释放了信号量(),必须将打印机房的门关起来(进入临界段),用完后,释放信号量,再把门打开(出临界段),其他任务再进去打印。(而互斥型信号量由于必须由取得信号量的那个任务释放,故不会出现其他任务错误地释放了信号量的情况出现,故不需要有临界段。互斥型信号量是二进制信号量的子集。)二进制信号量实现任务同步: a任务一直等待信号量,b任务定时释放信号量,完成同步功能========================================Example usage:xSemaphoreHandle xSemaphore = NULL;// A task that creates a semaphore.void vATask( void * pvParameters ){/* Create the semaphore to guard a shared resource.As we are using the semaphore for mutual exclusionwe create a mutex semaphore rather than a binary semaphore.*/
xSemaphore = xSemaphoreCreateMutex();}// A task that uses the semaphore.void vAnotherTask( void * pvParameters ){// ... Do other things.
if( xSemaphore != NULL )
/* See if we can obtain the semaphore. If the semaphore
is not available wait 10 ticks to see if it becomes free.*/
if(xSemaphoreTake(xSemaphore,(portTickType)10)
/* We were able to obtain the semaphore and can now
access the shared resource....
We have finished accessing the shared resource.
Release the semaphore.*/
xSemaphoreGive( xSemaphore );
/* We could not obtain the semaphore and can therefore
not access the shared resource safely. */
经验拿好。。。。。
FreeRTOS我觉得还可以的,挺好的。
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或

我要回帖

更多关于 freertos视频教程 的文章

 

随机推荐