freeRTOS总结(一)

FreeRTOS是一个可剪裁的小型RTOS系统,其特点包括:

  1.  FreeRTOS的内核支持抢占式,合作式和时间片调度
  2. 提供一个用于低功耗的Tickless模式
  3. 系统组件在创建时可以选择动态或静态的RAM,比如任务、消息队列、信号量、软件定时器等等
  4. 支持实时任务和协程(co-routines也有称作合作式、协同程序https://blog.csdn.net/lqk1985/article/details/6535598
  5. 任务与任务/中断通信和同步(消息队列、二值信号量、计数型信号量、互斥信号量和递归互斥信号量、任务通知)
  6. 互斥信号量具有优先级继承特性(但不可在中断中使用)
  7. 堆栈溢出检测功能
  8. 任务数量和任务优先级不限

1. 互斥量、二值信号量:

  • 二值信号量:用于任务间同步,用完丢弃,不再归还
  • 互斥量:用于共享资源的访问,用完必须归还。互斥量自动提供了一个基本的”优先级继承”机制。

2. 优先级反转:

3.优先级继承:

4.死锁:

当两个任务都在等待被对方持有的资源时,两个任务都无法再继续执行,这种情况就被称为死锁

考虑如下情形,任务 A 与任务 B 都需要获得互斥量 X 与互斥量 Y 以完成各自的工作:
1. 任务 A 执行,并成功获得了互斥量 X。
2. 任务 A 被任务 B 抢占。
3. 任务 B 成功获得了互斥量 Y,之后又试图获取互斥量 X——但互斥量 X 已经被任务 A 持有,所以对任务 B 无效。任务 B 选择进入阻塞态以等待互斥量 X 被释放。
4. 任务 A 得以继续执行。其试图获取互斥量 Y——但互斥量 Y 已经被任务 B持有而对任务 A 无效。任务 A 也选择进入阻塞态以等待互斥量 Y 被释放。
 

// 任务优先级反转
#include "user_task.h"
#include "queue.h"
#include "semphr.h"


#define DELAY_LOOP_CNT	1000000000

static TaskHandle_t Task1;
static TaskHandle_t Task2;
static TaskHandle_t Task3;
static xSemaphoreHandle xMutex;

void User_TickHook(void)
{
}

void Delay(int cnt)
{
	int i = 0, j = 0;

	for (j = 0; j < cnt; j++)
	for (i = 0; i < DELAY_LOOP_CNT; i++)
	{
		;
	}
}

static void vTaskHi(void *pvParam)
{
	TickType_t tick;

	vTaskDelay(10);

	pvParam = pvParam;
	tick = xTaskGetTickCount();
	for (;;)
	{
		printf("vTaskHi1\r\n");
		xSemaphoreTake(xMutex, portMAX_DELAY);
		printf("vTaskHi2\r\n");
		Delay(1);
		printf("vTaskHi3\r\n");
		xSemaphoreGive(xMutex);
		printf("vTaskHi4\r\n");
		vTaskDelay(1000);
	}
}

static void vTaskMi(void *pvParam)
{
	TickType_t tick;

	vTaskDelay(10);

	pvParam = pvParam;
	tick = xTaskGetTickCount();
	for (;;)
	{
		printf("vTaskMi\r\n");
		vTaskDelay(500);
	}
}

static void vTaskLo(void *pvParam)
{
	TickType_t tick;

	pvParam = pvParam;
	tick = xTaskGetTickCount();
	for (;;)
	{
		printf("vTaskLo1\r\n");
		xSemaphoreTake(xMutex, portMAX_DELAY);
		printf("vTaskLo2\r\n");
		Delay(1);
		printf("vTaskLo3\r\n");
		xSemaphoreGive(xMutex);
		printf("vTaskLo4\r\n");
	}
}

void vTask_main(void)
{
	srand(567);
	xMutex = xSemaphoreCreateMutex();
	if (xMutex != NULL)
	{
		printf("vTask_main\r\n");

		xTaskCreate(vTaskLo, "Low", 1000, (void*)"TaskLo", 1, &Task3);
		xTaskCreate(vTaskMi, "Middle", 1000, (void*)"TaskMi", 2, &Task2);
		xTaskCreate(vTaskHi, "High", 1000, (void*)"TaskHi", 3, &Task1);

		vTaskStartScheduler();
	}
	else
	{
		printf("xSemaphoreCreateMutex failed!\r\n");
	}

	for (;;) { ; }
}

运行结果:

//任务死锁
#include "user_task.h"
#include "queue.h"
#include "semphr.h"


#define DELAY_LOOP_CNT	1000000000

static TaskHandle_t TaskA;
static TaskHandle_t TaskB;
static xSemaphoreHandle xMutexX;
static xSemaphoreHandle xMutexY;

void User_TickHook(void)
{
}

void Delay(int cnt)
{
	int i = 0, j = 0;

	for (j = 0; j < cnt; j++)
	for (i = 0; i < DELAY_LOOP_CNT; i++)
	{
		;
	}
}

static void vTaskA(void *pvParam)
{
	pvParam = pvParam;
	for (;;)
	{
		printf("TaskA wait X\r\n");
		xSemaphoreTake(xMutexX, portMAX_DELAY);
		printf("TaskA take X\r\n");
		vTaskDelay(1000);
		printf("TaskA wait Y\r\n");
		xSemaphoreTake(xMutexY, portMAX_DELAY);
		printf("TaskA take Y\r\n");
		vTaskDelay(100);
		xSemaphoreGive(xMutexY);
		printf("TaskA give Y\r\n");
		xSemaphoreGive(xMutexX);
		printf("TaskA give X\r\n");
	}
}

static void vTaskB(void *pvParam)
{
	pvParam = pvParam;
	for (;;)
	{
		printf("TaskB wait Y\r\n");
		xSemaphoreTake(xMutexY, portMAX_DELAY);
		printf("TaskB take Y\r\n");
		vTaskDelay(500);
		printf("TaskB wait X\r\n");
		xSemaphoreTake(xMutexX, portMAX_DELAY);
		printf("TaskB take X\r\n");
		xSemaphoreGive(xMutexX);
		printf("TaskB give X\r\n");
		xSemaphoreGive(xMutexY);
		printf("TaskB give Y\r\n");
	}
}

void vTask_main(void)
{
	srand(567);
	xMutexX = xSemaphoreCreateMutex();
	xMutexY = xSemaphoreCreateMutex();

	if ((xMutexX != NULL) && (xMutexY != NULL))
	{
		printf("vTask_main\r\n");

		xTaskCreate(vTaskA, "TaskA", 1000, (void*)"TaskA", 1, &TaskA);
		xTaskCreate(vTaskB, "TaskB", 1000, (void*)"TaskB", 2, &TaskB);

		vTaskStartScheduler();
	}
	else
	{
		if (!xMutexX)
			printf("Create xMutexX failed!\r\n");
		if (!xMutexY)
			printf("Create xMutexY failed!\r\n");
	}

	for (;;) { ; }
}

运行结果:

5.守护任务
守护任务提供了一种干净利落的方法来实现互斥功能,而不用担心会发生优先级反转和死锁。
守护任务是对某个资源具有唯一所有权的任务。只有守护任务才可以直接访问其守
护的资源——其它任务要访问该资源只能间接地通过守护任务提供的服务。
 

猜你喜欢

转载自blog.csdn.net/findmu/article/details/89021925