cancel
Showing results for 
Search instead for 
Did you mean: 

How does the event flag work on STM32? Part 3

B.Montanari
ST Employee

How does the event flag work on STM32? Part 3

This is the part 3 of the article to explain How the Event Flag work on STM32 with a working example. Welcome back!

After generation, locate and open the app_threadx.c file. There is inside Core → Src folder on project files. In this file, let us start including some headers to allow the access of HAL Timer and GPIO configurations.
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "main.h"
#include "tim.h"
#include "gpio.h"
/* USER CODE END Includes */
Create some masks for each event button, it is helpful to manage the event flags. The EV_UNION_MSK it is a union between directional buttons events (up, right, down, and left buttons).
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define EV_SELECT_MSK			0b00000001
#define EV_UP_MSK				0b00000010
#define EV_RIGHT_MSK			0b00000100
#define EV_DOWN_MSK				0b00001000
#define EV_LEFT_MSK				0b00010000

#define EV_UNION_MSK			(EV_UP_MSK | EV_RIGHT_MSK | EV_DOWN_MSK | EV_LEFT_MSK)

#define THREAD_STACK_SIZE		1024
/* USER CODE END PD */
Since this demo uses 2 threads to manage the RGB Color LED, we need to create 2 stack buffers, 2 thread pointers and 2 thread prototype functions OneColorThread and RainbowThread.  If you need more information about the ThreadX resources, refer: How to create a Thread using AzureRTOS and STM32CubeIDE?
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
uint8_t thread_stack1[THREAD_STACK_SIZE];
uint8_t thread_stack2[THREAD_STACK_SIZE];

TX_THREAD threadOneColor_ptr;
TX_THREAD threadRainbow_ptr;

TX_EVENT_FLAGS_GROUP event_ptr;

const uint8_t lookupTABLE[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0};
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
VOID RGBColorChange(uint8_t RED_PWM, uint8_t GREEN_PWM, uint8_t BLUE_PWM);
VOID OneColorThread(ULONG initial_input);
VOID RainbowThread(ULONG initial_input);
/* USER CODE END PFP */
The RGBColorChange function changes the LED color according to the parameters sent, this updates the PWM duty cycles changing the pulse compare timer registers. It was implemented to avoid repeated code (this function could be placed into user code region 1, i.e., between user code begin/end 1).
VOID RGBColorChange(uint8_t RED_PWM, uint8_t GREEN_PWM, uint8_t BLUE_PWM)
{
	__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, RED_PWM); 	/* RED PWM */
	__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, GREEN_PWM); 	/* GREEN PWM */
	__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, BLUE_PWM); 	/* BLUE PWM */
}
In App_ThreadX_Init function starts the three PWM channels, create the event flags using tx_event_flags_create function and two threads with tx_thread_create.
UINT App_ThreadX_Init(VOID *memory_ptr)
{
	UINT ret = TX_SUCCESS;
	TX_BYTE_POOL *byte_pool = (TX_BYTE_POOL*)memory_ptr;

	/* USER CODE BEGIN App_ThreadX_MEM_POOL */
	(void)byte_pool;
	/* USER CODE END App_ThreadX_MEM_POOL */

	/* USER CODE BEGIN App_ThreadX_Init */
	HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);

	tx_event_flags_create(&event_ptr, "External Interrupt");

	tx_thread_create(&threadOneColor_ptr, "Change Color thread", OneColorThread, 0x1234, thread_stack1, THREAD_STACK_SIZE, 15, 15, 1, TX_AUTO_START);
	tx_thread_create(&threadRainbow_ptr, "Rainbow thread", RainbowThread, 0x1234, thread_stack2, THREAD_STACK_SIZE, 15, 15, 1, TX_AUTO_START);
	/* USER CODE END App_ThreadX_Init */

	return ret;
}
Redeclare the HAL_GPIO_EXTI_Callback function in the app_threadx file (it could also be placed into user code region 1). In this function, clear the SELECT button event to update the next color that should be shown. Add a switch case to check what button was pressed and set their respective event flag.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	ULONG event;

	tx_event_flags_get(&event_ptr, EV_SELECT_MSK, TX_OR_CLEAR, &event, TX_NO_WAIT);

	switch(GPIO_Pin)
	{
	case JOYSTICK_SELECT_Pin:
		tx_event_flags_set(&event_ptr, EV_SELECT_MSK, TX_OR);
		break;

	case JOYSTICK_UP_Pin:
		tx_event_flags_set(&event_ptr, EV_UP_MSK, TX_OR);
		break;

	case JOYSTICK_RIGHT_Pin:
		tx_event_flags_set(&event_ptr, EV_RIGHT_MSK, TX_OR);
		break;

	case JOYSTICK_DOWN_Pin:
		tx_event_flags_set(&event_ptr, EV_DOWN_MSK, TX_OR);
		break;

	case JOYSTICK_LEFT_Pin:
		tx_event_flags_set(&event_ptr, EV_LEFT_MSK, TX_OR);
		break;
	}
}
Now, create the OneColorThread function. This thread should wait for an event fag according to the Event Union Mask. Whenever an event flag is set by a directional button pressing, this thread clears that and check what flag was set. According to this flag, the thread changes the LED color calling the RGBColorChange.
VOID OneColorThread(ULONG initial_input)
{
	ULONG event;

	while(1)
	{
		tx_event_flags_get(&event_ptr, EV_UNION_MSK, TX_OR_CLEAR, &event, TX_WAIT_FOREVER);

		if(event & EV_LEFT_MSK)			/* Turn LED Off */
		{
			RGBColorChange(0, 0, 0);   	/* RED = 0, GREEN = 0, BLUE = 0 */
		}
		else if(event & EV_UP_MSK)		/* Turn LED RED */
		{
			RGBColorChange(10, 0, 0);   /* RED = 10, GREEN = 0, BLUE = 0 */
		}
		else if(event & EV_RIGHT_MSK)	/* Turn LED GREEN */
		{
			RGBColorChange(0, 10, 0);   /* RED = 0, GREEN = 10, BLUE = 0 */
		}
		else if(event & EV_DOWN_MSK)	/* Turn LED BLUE */
		{
			RGBColorChange(0, 0, 10);   /* RED = 0, GREEN = 0, BLUE = 10 */
		}
	}
}
The RainbowThread function it’s a thread that manages the colors when the led is set to a rainbow mode. This thread runs while the SELECT event button is set because this flag is not cleared in get function. To change the color, add a counter and use this as index of the lookup table to send the parameters to the RGBColorChange function. Finally, add a logic to give a phase between the led signals as the following code:
VOID RainbowThread(ULONG initial_input)
{
	ULONG event;
	uint8_t count = 0;

	while(1)
	{
		tx_event_flags_get(&event_ptr, EV_SELECT_MSK, TX_OR, &event, TX_WAIT_FOREVER);

		if(count < 16)
		{
			RGBColorChange(lookupTABLE[count], lookupTABLE[count + 16], lookupTABLE[count + 32]);
			count++;
		}
		else if(count < 32)
		{
			RGBColorChange(lookupTABLE[count], lookupTABLE[count + 16], lookupTABLE[count - 16]);
			count++;
		}
		else if(count < 48)
		{
			RGBColorChange(lookupTABLE[count], lookupTABLE[count - 32], lookupTABLE[count - 16]);
			count ++;
		}
		else
		{
			RGBColorChange(lookupTABLE[count], lookupTABLE[count - 32], lookupTABLE[count - 16]);
			count = 0;
		}

		tx_thread_sleep(15);
	}
}
This is all the necessary code. So, press Ctrl + B to build the project and check if no one errors or warnings occurs. Connect the board to the computer and enter in debug mode clicking on the following button.
227.pngIn Debug Configurations menu, let the standard settings and then click on debug. Once in the Debug perspective, click on “Window → Show view → ThreadX → ThreadX Event Flags”.
229.png
It should open a tab at a bottom window group of STM32CubeIDE.
231.png
Run the code, test the demo by pressing the buttons and enjoy the RGB Led behavior. Pause the code in the Debug, and check the ThreadX Event Flags tab. In this tab you can see the created event groups, their actual flags counting, and the threads that interact with that. Since this code clears the flag after the color update, the flag should be zero if you pause the code when the Led is not in rainbow mode. Furthermore, the threads are suspended because these are waiting for an event.
232.png
If you pause the code during the rainbow mode, you see a flag set, and just the Change Color thread will be suspended, the Rainbow thread runs continuously updating the Led color.
234.png
RESULTS:
The code was built to change the Led color in according to the following button events:
  • Up button: Change color to red
  • Right button: Change color to green
  • Down button: Change color to blue
  • Left button: Turn Led off
  • Select button: Turn Led to rainbow mode
The following image shows the behavior of the OS, it is possible to check how the application works.
236.png
In the first block, we have the kernel initialization, the Event Creation (EC), two Thread Creations (TC) and after their first Event Gets (EG) as programmed.
          The second block, we can see an EG at the interrupt level (it is the event get inside the EXTI callback function, that is, a button was pressed), then an ES that set a flag bit (also inside the EXTI callback). After the flag is set, the Change Color Thread run, get and clear the flag, change the led color, and then enter in suspend mode waiting for a new Event. This cycle occurs four times, the same as shown in previous GIF.
          The third block shows the AzureRTOS kernel behavior when the LED is in Rainbow mode. At the beginning of the block, we have an event get and set (in the EXTI) and then the Rainbow thread starts to run. As we can see, this thread runs continuously because it does not clear the flag to keep the thread running and updating the color of the led.
This graph was made by the TraceX feature. If you need more information about TraceX and a tutorial showing how to implement this, refer: How can I add TraceX support in STM32CubeIDE?
         
REFERENCES AND LINKS:
About the Azure RTOS ThreadX Guide | Microsoft Docs
Chapter 3 - Functional Components of Azure RTOS ThreadX | Microsoft Docs
How to create a Thread using AzureRTOS and STM32CubeIDE?
How can I add TraceX support in STM32CubeIDE?
STM32CubeIDE - Integrated Development Environment for STM32
STM32G474RE - STMicroelectronics
Discovery kit with STM32G474RE MCU - B-G474E-DPOW1
Application note - high-brightness RGB LED control using the B-G474E-DPOW1 Discovery kit
 
Version history
Last update:
‎2022-09-06 12:40 AM
Updated by: