FreeRTOS review notes - semaphores

FreeRTOS review notes (IV) - semaphore

1, Binary semaphore and count semaphore

1. The idea of this routine:

In this chapter, binary semaphores and count semaphores are written into the same code_ USE_BINARY_SEMAPHORE and_ USE_COUNT_SEMAPHORE to distinguish

For binary semaphores, two tasks are created. One task is used to release semaphores and the other task is used to obtain semaphores. When key_ The semaphore is released when the falling edge of GPIO (PA0) appears

For counting semaphores, when key_ When the falling edge of GPIO (PA0) appears, obtain the semaphore and release semaphore, and print the number of semaphores currently available

For the creation of binary semaphores, you can call the xssemaphorecreatebinary function, and for the creation of counting semaphores, you can call the xssemaphorecreatecounting function

Use xssemaphoregive to release semaphores and xssemaphoretake to obtain semaphores

2. Coding

/**
  ******************************************************************************
  * @File name: XXX c
  * @author
  * @Version: v1 zero
  * @Date: December, 2021 twenty-four
  * @Introduction: None
  * @Note: None
  ******************************************************************************
  */
#include "stm32f10x.h"

#include "dr_usart.h"
#include "dr_led.h"
#include "dr_key.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

//#define _USE_BINARY_SEMAPHORE
#define _USE_COUNT_SEMAPHORE

void AppTaskCreateTask(void *);
void LEDTask(void *);
void KEYTask(void *);

/* --- Mission--- */
TaskHandle_t LEDTask_Handle = NULL;

#ifdef _USE_BINARY_SEMAPHORE
/* --- Binary semaphore--- */
SemaphoreHandle_t BinarySemaphore_Handle = NULL;
#endif

#ifdef _USE_COUNT_SEMAPHORE
/* --- Count semaphore--- */
SemaphoreHandle_t CountSemaphore_Handle = NULL;
#endif

/**
  * @Introduction: None
  * @Parameter: None
  * @Return value: None
  */
int main(void)
{
	/* --------- --------- --------- --------- --------- --------- ---------  */
	
	/* Interrupt packet 4 */
	NVIC_Priority_Group_Config();                                        /* * */
	
	/* Serial port 1 configuration */
	USART1_Config();                                                     /* * */
	
	/* LED(PA8, PA6)to configure */
	LED_GPIO_Config();                                                   /* * */
	
	/* KEY(PA0)to configure */
	KEY_GPIO_Config();
	
	/* --------- --------- --------- --------- --------- --------- ---------  */

	/* Create task */
	xTaskCreate(AppTaskCreateTask, "AppTaskCreateTask", 128, NULL, 1, NULL);

	/* Turn on task scheduling */
	vTaskStartScheduler();
	
	while(1);
}

/**
  * @Introduction: None
  * @Parameter: None
  * @Return value: None
  */
void AppTaskCreateTask(void *pvParameters)
{
	/* Critical protection */
	taskENTER_CRITICAL();
	
	/* Create task */
	xTaskCreate(LEDTask, "LEDTask", 128, NULL, 2, &LEDTask_Handle);
	
	xTaskCreate(KEYTask, "KEYTask", 128, NULL, 3, NULL);

#ifdef _USE_BINARY_SEMAPHORE
	/* Create binary semaphore */
	BinarySemaphore_Handle = xSemaphoreCreateBinary();
	
	if (BinarySemaphore_Handle != NULL)
		printf("--- The BinarySemaphore was created successful ---.\r\n\r\n");
#endif
	
#ifdef _USE_COUNT_SEMAPHORE
	/* Create count semaphores, and the number of semaphores can be obtained during initialization */
	CountSemaphore_Handle = xSemaphoreCreateCounting(2, 2);
	
	if (CountSemaphore_Handle != NULL)
		printf("--- The CountSemaphores was created ---.\r\n\r\n");
#endif
	
	vTaskDelete(NULL);
	
	taskEXIT_CRITICAL();
}

/**
  * @Introduction: None
  * @Parameter: None
  * @Return value: None
  */
void LEDTask(void *pvParameters)
{
	BaseType_t xReturn = pdFALSE;

	for (;;)
	{
	#ifdef _USE_BINARY_SEMAPHORE
		/* Get binary semaphore, semaphore handle wait timeout */
		xReturn = xSemaphoreTake(BinarySemaphore_Handle, 0);
		
		if (xReturn == pdTRUE)
			printf("The BinarySemaphore has been obtained.\r\n");
	#endif
	
		/* Flip LED */
		GPIOA->ODR ^= ((uint16_t)0x0100);
		
//		printf("LED %s\r\n", ((GPIOA->IDR & 0x0100) != 0) ? "is running." : "stops running.");
	
		(void)xReturn;
	
		vTaskDelay(50);
	}
}

/**
  * @Introduction: None
  * @Parameter: None
  * @Return value: None
  */
void KEYTask(void *pvParameters)
{
	uint8_t level_high = 0;
	uint8_t level_low  = 0;
	uint8_t edge_fall  = 0;
	uint8_t edge_rise  = 0;
	
	uint8_t _switch = 0;
	
	BaseType_t xReturn = pdFALSE;
	UBaseType_t CurrentSemaphoreNum = 0;
	
	for (;;)
	{
		/* High level / rising edge detection */
		if ( (GPIOA->IDR & 0x0001) != 0 )
		{
			if(level_low == 1)
				edge_rise = 1;
				
			level_low  = 0;
			level_high = 1;
		}
		
		/* Low level / falling edge detection */
		if ( (GPIOA->IDR & 0x0001) == 0 )
		{
			if(level_high == 1)
				edge_fall  = 1;
				
			level_high = 0; 
			level_low  = 1;
		}
		
		/* Falling edge appears */
		if (edge_fall)
		{
		#ifdef _USE_BINARY_SEMAPHORE
			/* Release binary semaphore */
			xReturn = xSemaphoreGive(BinarySemaphore_Handle);
			
			if (xReturn == pdTRUE)
				printf("The BinarySemaphore has been released successful.\r\n");
		#endif
		
		#ifdef _USE_COUNT_SEMAPHORE
			switch(_switch)
			{
			case 0:
				/* Get count semaphore, semaphore handle wait timeout */
				xReturn = xSemaphoreTake(CountSemaphore_Handle, 0);
				_switch++;
				break;
				
			case 1:
				/* Get count semaphore */
				xReturn = xSemaphoreTake(CountSemaphore_Handle, 0);
				_switch++;
				break;
				
			case 2:
				/* Get count semaphore */
				xReturn = xSemaphoreTake(CountSemaphore_Handle, 0);
				_switch++;
				break;
				
			case 3:
				/* Release count semaphore, semaphore handle */
				xReturn = xSemaphoreGive(CountSemaphore_Handle);
				_switch++;
				break;
				
			case 4:
				/* Release count semaphore */
				xReturn = xSemaphoreGive(CountSemaphore_Handle);
				_switch = 0;
				break;
				
			default: _switch = 0;
			}
			
			if ( (_switch == 1) || (_switch == 2) || (_switch == 3) )
			{
				if (xReturn == pdTRUE)
					printf("obtained. ");
				else
					printf("#error: no Semaphore. ");
			}
			
			if ( (_switch == 0) || (_switch == 4) )
				printf("released. ");
				
			/* Count semaphore quantity */
			CurrentSemaphoreNum = uxSemaphoreGetCount(CountSemaphore_Handle);

			printf("CurrentSemphoresNum: %lu\r\n", CurrentSemaphoreNum);
		#endif
		}
	
		edge_fall = 0;
		edge_rise = 0;
		
		(void)edge_rise;
		(void)_switch;
		(void)CurrentSemaphoreNum;
	
		vTaskDelay(20);
	}
}

3. Use the serial port to observe the output information

Binary semaphore (one task releases semaphore and the other task obtains semaphore)

Count semaphores (the number of semaphores decreases after acquisition and increases after release)

After verification, the running result of the program is consistent with the expectation

2, Mutually exclusive semaphore

1. The idea of this routine:

Create three tasks. First, use binary semaphores to simulate priority reversal, and then change binary semaphores to use mutually exclusive semaphores. Compare with binary semaphores to show the priority inheritance mechanism of mutually exclusive semaphores

This article uses_ USE_BINARY_SEMAPHORE and_ USE_MUTEX_SEMAPHORE distinguishes between binary semaphores and mutually exclusive semaphores

Create a binary semaphore and call the xssemaphorecreatebinary function. Create a mutually exclusive semaphore and call the xssemaphorecreatemutex function

2. Coding

/**
  ******************************************************************************
  * @File name: XXX c
  * @author
  * @Version: v1 zero
  * @Date: December, 2021 twenty-six
  * @Introduction: None
  * @Note: None
  ******************************************************************************
  */
#include "stm32f10x.h"

#include "dr_usart.h"
#include "dr_led.h"
#include "dr_key.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

//#define _USE_BINARY_SEMAPHORE
#define _USE_MUTEX_SEMAPHORE

void AppTaskCreateTask(void *);
void LowPriorityTask(void *);
void MidPriorityTask(void *);
void HighPriorityTask(void *);

#ifdef _USE_BINARY_SEMAPHORE
/* --- Binary semaphore--- */
SemaphoreHandle_t BinarySemaphore_Handle = NULL;
#else
/* --- Mutually exclusive semaphore--- */
SemaphoreHandle_t MutexSemaphore_Handle = NULL;
#endif

/**
  * @Introduction: None
  * @Parameter: None
  * @Return value: None
  */
int main(void)
{
	/* --------- --------- --------- --------- --------- --------- ---------  */
	
	/* Interrupt packet 4 */
	NVIC_Priority_Group_Config();                                        /* * */
	
	/* Serial port 1 configuration */
	USART1_Config();                                                     /* * */
	
	/* LED(PA8, PA6)to configure */
	LED_GPIO_Config();                                                   /* * */
	
	/* KEY(PA0)to configure */
	KEY_GPIO_Config();
	
	/* --------- --------- --------- --------- --------- --------- ---------  */

	/* Create task */
	xTaskCreate(AppTaskCreateTask, "AppTaskCreateTask", (uint16_t)128, NULL, (UBaseType_t)1, NULL);

	/* Turn on task scheduling */
	vTaskStartScheduler();
	
	while(1);
}

/**
  * @Introduction: None
  * @Parameter: None
  * @Return value: None
  */
void AppTaskCreateTask(void *pvParameters)
{
	/* Critical protection */
	taskENTER_CRITICAL();
	
	/* Create task */
	xTaskCreate(HighPriorityTask, "HighPriorityTask", (uint16_t)128, NULL, (UBaseType_t)4, NULL);
	xTaskCreate(MidPriorityTask, "MidPriorityTask", (uint16_t)128, NULL, (UBaseType_t)3, NULL);
	xTaskCreate(LowPriorityTask, "LowPriorityTask", (uint16_t)128, NULL, (UBaseType_t)2, NULL);
	
#ifdef _USE_BINARY_SEMAPHORE
	/* Create binary semaphore */
	BinarySemaphore_Handle = xSemaphoreCreateBinary();
	
	if (BinarySemaphore_Handle != NULL)
		printf("--- BinarySemaphore was Created ---.\r\n\r\n");
		
	/* Release binary semaphore */
	xSemaphoreGive(BinarySemaphore_Handle);
#else
	/* Create mutually exclusive semaphores */
	MutexSemaphore_Handle = xSemaphoreCreateMutex();
	
	if (MutexSemaphore_Handle != NULL)
		printf("--- MutexSemaphore was Created ---.\r\n\r\n");
#endif

	vTaskDelete(NULL);
	
	taskEXIT_CRITICAL();
}

/**
  * @Introduction: None
  * @Parameter: None
  * @Return value: None
  */
void LowPriorityTask(void *pvParameters)
{
	uint32_t i = 0;
	BaseType_t xReturn = pdFALSE;

	for (;;)
	{
	#ifdef _USE_BINARY_SEMAPHORE
		/* Wait for binary semaphore */
		xReturn = xSemaphoreTake(BinarySemaphore_Handle, portMAX_DELAY);
	#else
		/* Wait for mutex semaphores */
		xReturn = xSemaphoreTake(MutexSemaphore_Handle, portMAX_DELAY);
	#endif
		
		/* LowPriorityTask Occupied semaphore */
		if (xReturn == pdTRUE)
			printf("LowPriorityTask has obtained the semaphore.\r\n");
		
		/* Task switching */
		for(i = 0; i < 0x7ffff; i++)
			taskYIELD();
			
	#ifdef _USE_BINARY_SEMAPHORE
		/* Release binary semaphore */
		xReturn = xSemaphoreGive(BinarySemaphore_Handle);
	#else
		/* Release mutex semaphore */
		xReturn = xSemaphoreGive(MutexSemaphore_Handle);
	#endif
		
		/* LowPriorityTask Release semaphore */
		if (xReturn == pdTRUE)
			printf("LowPriorityTask has released the semaphore.\r\n");
			
		vTaskDelay(50);
	}
}

/**
  * @Introduction: None
  * @Parameter: None
  * @Return value: None
  */
void MidPriorityTask(void *pvParameters)
{
	for (;;)
	{
		/* Flip LED */
		GPIOA->ODR ^= ((uint16_t)0x0100);
		
		printf("MidPriorityTask is running.\r\n");
		
		vTaskDelay(50);
	}
}
 
/**
  * @Introduction: None
  * @Parameter: None
  * @Return value: None
  */
void HighPriorityTask(void *pvParameters)
{
	BaseType_t xReturn = pdFALSE;
	
	for (;;)
	{
	#ifdef _USE_BINARY_SEMAPHORE
		/* Wait for binary semaphore */
		xReturn = xSemaphoreTake(BinarySemaphore_Handle, portMAX_DELAY);
	#else
		/* Wait for mutex semaphores */
		xReturn = xSemaphoreTake(MutexSemaphore_Handle, portMAX_DELAY);
	#endif
	
		/* HighPriorityTask Occupied semaphore */
		if (xReturn == pdTRUE)
			printf("HighPriorityTask has obtained the semaphore.\r\n");
			
	#ifdef _USE_BINARY_SEMAPHORE
		/* Release binary semaphore */
		xReturn = xSemaphoreGive(BinarySemaphore_Handle);
	#else
		/* Release mutex semaphore */
		xReturn = xSemaphoreGive(MutexSemaphore_Handle);
	#endif
		
		/* HighPriorityTask Release semaphore */
		if (xReturn == pdTRUE)
			printf("HighPriorityTask has released the semaphore.\r\n");
		
		vTaskDelay(50);
	}
}

3. Use the serial port to observe the output information

Binary semaphore (priority reversal occurs and high priority tasks are interrupted)

Mutex semaphore (reflects the priority inheritance mechanism of mutex and improves the priority of low priority tasks)

After verification, the running result of the program is consistent with the expectation

Keywords: FreeRTOS

Added by Ghostgator on Tue, 28 Dec 2021 19:05:22 +0200