STM32CubeIDE+FreeRTOS互斥量实验

  在 FreeRTOS 操作系统中为了降低优先级翻转问题利用了优先级继承算法。优先级继承算法是指,暂时提高某个占有某种资源的低优先级任务的优先级,使之与在所有等待该资源的任务中优先级最高那个任务的优先级相等,而当这个低优先级任务执行完毕释放该资源时,优先级重新回到初始设定值。因此,继承优先级的任务避免了系统资源被任何中间优先级的任务抢占。互斥量与二值信号量最大的不同是:互斥量具有优先级继承机制,而信号量没有。也就是说,某个临界资源受到一个互斥量保护,如果这个资源正在被一个低优先级任务使用,那么此时的互斥量是闭锁状态,也代表了没有任务能申请到这个互斥量,如果此时一个高优先级任务想要对这个资源进行访问,去申请这个互斥量,那么高优先级任务会因为申请不到互斥量而进入阻塞态,那么系统会将现在持有该互斥量的任务的优先级临时提升到与高优先级任务的优先级相同,这个优先级提升的过程叫做优先级继承。这个优先级继承机制确保高优先级任务进入阻塞状态的时间尽可能短,以及将已经出现的“优先级翻转”危害降低到最小。_ _ _ _ _ _ _ _以上内容摘自《野火FreeRTOS 内核实现与应用开发实战指南》

互斥量实验是基于优先级翻转实验进行修改的,目的是为了测试互斥量的优先级继承机制是否有效。

创建工程RTOS_Mutex,

配置HCLK,使用内部晶振,频率为180MHZ(根据板子设置)

将SYS中时基源(Timebase Source)改为除SysTick之外的任意定时器即可,如:

配置FreeRTOS,使用CMSIS_V1,先定义一个互斥信号量:

定义三个任务:

    

Ctrl + S生成代码

修改代码,

1,在main.h中添加

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

2,在mian.c中添加

/* USER CODE BEGIN PFP */
int _write(int file , char *ptr,int len)
{
    int i = 0;
    for(i = 0;i<len;i++)
        ITM_SendChar((*ptr++));
    return len;
}
/* USER CODE END PFP */

...
...
...

/* USER CODE BEGIN 2 */
printf("starting...\n");
/* USER CODE END 2 */

3,在main.c中修改3个任务入口函数的内容

/* USER CODE BEGIN Header_StartLowPriorityTask */
/**
  * @brief  Function implementing the LowPriorityTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartLowPriorityTask */
void StartLowPriorityTask(void const * argument)
{
  /* USER CODE BEGIN 5 */
    static uint32_t i;
  /* Infinite loop */
  for(;;)
  {
      printf("LowPriority_Task gets mutex!\n");
      //获取二值信号量 xSemaphore,没获取到则一直等待
      if(osMutexWait(myMutex01Handle, osWaitForever) == osOK)
      {
          printf("LowPriority_Task Runing\n\n");
      }

      for (i=0; i<2000000; i++) { //模拟低优先级任务占用信号量
          osThreadYield();//发起任务调度
      }
      printf("LowPriority_Task Releasing mutex!\r\n");
      osMutexRelease( myMutex01Handle );//给出二值信号量
      osDelay(500);
  }
  /* USER CODE END 5 */
}
/* USER CODE BEGIN Header_StartMidPriorityTask */
/**
* @brief Function implementing the MidPriorityTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartMidPriorityTask */
void StartMidPriorityTask(void const * argument)
{
  /* USER CODE BEGIN StartMidPriorityTask */
  /* Infinite loop */
  for(;;)
  {
    printf("MidPriority_Task Runing\n");
    osDelay(500);
  }
  /* USER CODE END StartMidPriorityTask */
}
/* USER CODE BEGIN Header_StartHighPriority_Task */
/**
* @brief Function implementing the HighPriority_Ta thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartHighPriority_Task */
void StartHighPriority_Task(void const * argument)
{
  /* USER CODE BEGIN StartHighPriority_Task */
  /* Infinite loop */
  for(;;)
  {
      printf("HighPriority_Task gets mutex!\n");
      //获取二值信号量 xSemaphore,没获取到则一直等待
      if(osMutexWait(myMutex01Handle, osWaitForever) == osOK)
      {
          printf("HighPriority_Task Runing\n\n");
      }

      printf("HighPriority_Task Releasing mutex!\r\n");
      osMutexRelease( myMutex01Handle );//给出二值信号量
      osDelay(500);
  }
  /* USER CODE END StartHighPriority_Task */
}

修改完毕后点击 小锤子 构建工程,然后点击Debug,按如下步骤配置ITM调试

全速运行之前一定要先点击SWV ITM data Console 页面中的红色圆圈

现象:

分析:

3个任务,LowPriority_Task,的优先级为 osPriorityLow ,任务先获取互斥量,获取成功后先不释放,进行任务调度2000000次,然后释放二值信号量。

MidPriority_Task的优先级为 osPriorityNormal ,任务每个500ms输出提示信息MidPriority_Task Runing。

HighPriority_Task的优先级为  osPriorityHigh,任务先获取互斥量,获取成功后输出提示信息,然后立即释放互斥量。

程序先执行优先级最高的HighPriority_Task的,然后执行优先级第二高的MidPriority_Task,最后执行优先级最低的LowPriority_Task 。在LowPriority_Task中,任务先获取互斥量,获取成功后先不释放,进行任务调度,调度到优先级最高的HighPriority_Task,HighPriority_Task任务获取互斥量,因为此时互斥量被占用,所以会获取失败,进入阻塞态。由于互斥量的优先级继承机制,此时的LowPriority_Task的优先级被暂时提高到与HighPriority_Task一样,所以即使进行任务调度也不会执行MidPriority_Task,直到LowPriority_Task释放信号量(此时,由于优先级继承机制,LowPriority_Task恢复到原来的优先级),程序立即执行HighPriority_Task,当HighPriority_Task执行完毕后,按照优先级执行MidPriority_Task,最后再执行LowPriority_Task。如此循环...

原文地址:https://www.cnblogs.com/tianxxl/p/12023562.html

时间: 2024-10-19 05:48:48

STM32CubeIDE+FreeRTOS互斥量实验的相关文章

STM32CubeIDE+FreeRTOS软件定时器实验

软件定时器实验是在 FreeRTOS 中创建了两个软件定时器,其中一个软件定时器是单次模式, 5000 个 tick 调用一次回调函数,另一个软件定时器是周期模式, 1000 个 tick 调用一次回调函数,在回调函数中输出相关信息,. 创建工程RTOS_Timer, 配置HCLK,使用内部晶振,频率为180MHZ(根据板子设置) 将SYS中时基源(Timebase Source)改为除SysTick之外的任意定时器即可,如: 配置FreeRTOS,使用CMSIS_V1,使能USE_TIMERS

秒杀多线程第十五篇 关键段,事件,互斥量,信号量的“遗弃”问题

版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 秒杀多线程第十五篇 关键段,事件,互斥量,信号量的“遗弃”问题 在<秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量>中对经典多线程同步互斥问题进行了回顾和总结,这篇文章对Windows系统下常用的线程同步互斥机制——关键段.事件.互斥量.信号量进行了总结.有网友问到互斥量能处理“遗弃”问题,事件和信号量是否也能处理“遗弃”问题.因此本文将对事件和信号量作个试验,看看事件和信号量能否处理“遗弃”问题. 一.

理解互斥量和信号量

互斥量(Mutex) 互斥量表现互斥现象的数据结构,也被当作二元信号灯.一个互斥基本上是一个多任务敏感的二元信号,它能用作同步多任务的行为,它常用作保护从中断来的临界段代码并且在共享同步使用的资源. Mutex本质上说就是一把锁,提供对资源的独占访问,所以Mutex主要的作用是用于互斥.Mutex对象的值,只有0和1两个值.这两个值也分别代表了Mutex的两种状态.值为0, 表示锁定状态,当前对象被锁定,用户进程/线程如果试图Lock临界资源,则进入排队等待:值为1,表示空闲状态,当前对象为空闲

信号量、互斥量、同步变量、条件变量和事件变量

信号量:信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用.在进入一个关键代码段之前,线程必须获取一个信号量:一旦该关键代码段完成了,那么该线程必须释放信号量.其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量.为了完成这个过程,需要创建一个信号量VI,然后将Acquire Semaphore VI以及Release Semaphore VI分别放置在每个关键代码段的首末端.确认这些信号量VI引用的是初始创建的

线程同步---互斥量mutex

1. 问题引入:开两个线程同时对一个全局变量10万次做自加,结果会如何? #include <stdio.h> #include <string.h> #include <pthread.h> unsigned int g_cn = 0; void* thread_proc (void* arg) { unsigned int i; for (i = 0; i < 100000; i++) ++g_cn; return NULL; } int main (void

线程------竞争,互斥量---多线程对同一文件读写问题

当多个控制线程共享相同的内存时呢,需要确保每个线程看到一致的数据视图. 如果每个线程使用的变量都是其他线程不会读取和修改,那么就不存在一致性的问题. 线程互斥接口用来保护数据,用于确保同一时间只有一个线程访问数据. 互斥:限制代码---独占 很久以前: 下面程序存在竞争问题的哟,当创建20个线程,每个线程都对同一个文件进行读写操作,有可能发生N个线程同时对文件进行打开和读操作,在写的过程可能会对同一个数重复进行+1操作.比如说读到  1, 然后N个线程取到1 并对1这个数做+1操作. /* 实现

互斥量函数

一.互斥锁互斥锁,是一种信号量,常用来防止两个进程或线程在同一时刻访问相同的共享资源.需要的头文件:pthread.h互斥锁标识符:pthread_mutex_t (1)互斥锁初始化:函数原型: int pthread_mutex_init (pthread_mutex_t* mutex,const pthread_mutexattr_t* mutexattr);函数传入值:  mutex:互斥锁.mutexattr:PTHREAD_MUTEX_INITIALIZER 创建快速互斥锁.PTHRE

数据共享之互斥量mutex

互斥量介绍 互斥量可以保护某些代码只能有一个线程运行这些代码.如果有个线程使用互斥量执行某些代码,其他线程访问是会被阻塞,直到这个线程执行完这些代码,其他线程才可以执行. 一个线程在访问共享数据前,给互斥量上锁,这时其他线程再给互斥量上锁会阻塞直到这个线程给互斥量解锁. 互斥量是C++中最常用的数据保护机制,但是它也不万能的.在编写代码时,合理的组织代码来避免资源竞争非常重要.使用互斥量可能会带来其他问题,比如死锁. 在C++中使用互斥量 创建互斥量使用mutex,给互斥量上锁使用函数lock(

C++11多线程编程之互斥量

+(UIImage*)createImageFromView:(UIView*)view { //obtain scale CGFloat scale = [UIScreen mainScreen].scale; 开始绘图,下面方法,第一个参数表示区域大小.第二个参数表示是否是非透明的.如果需要显示半透明效果,需要传NO,否则传YES.第三个参数就是屏幕密度了 UIGraphicsBeginImageContextWithOptions(CGSizeMake(view.frame.size.wi