This project demonstrates inter-task communication using queues in an STM32 microcontroller with FreeRTOS. Queues are used to safely pass data between tasks and even from interrupt service routines (ISRs) to tasks.
The application creates three tasks with different priorities:
- Sender_HPT_Task (Highest Priority: 3) - Sends value 222 every 2000ms
- Sender_LPT_Task (Medium Priority: 2) - Sends value 111 every 1000ms
- Receiver_Task (Lowest Priority: 1) - Receives and displays values every 5000ms
A queue with capacity of 5 integers is used to pass data between sender tasks and the receiver task. This demonstrates how FreeRTOS queues provide thread-safe communication between tasks.
This project uses native FreeRTOS APIs directly, not the CMSIS-RTOS wrapper.
- Two Producer Tasks: Both sender tasks continuously put data into the queue
- One Consumer Task: Receiver task takes data out of the queue
- ISR as Special Producer: UART interrupt can also send data when user types 'r'
- Queue as Buffer: Temporarily stores messages when consumer is busy
Uart_output.mp4
- STM32 development board (STM32F103C8T6 "Blue Pill")
- USB-to-UART converter (for viewing debug messages and sending commands)
- UART connection (PA9/PA10 for USART1 on STM32F103)
| Pin | Function | Description |
|---|---|---|
| PA9 | USART1 TX | Debug output from STM32 |
| PA10 | USART1 RX | Receive 'r' command to trigger ISR send |
| Task | Priority | Data Sent | Send/Receive Rate | Role |
|---|---|---|---|---|
| Sender_HPT_Task | 3 (Highest) | 222 | Every 2000ms | Producer |
| Sender_LPT_Task | 2 | 111 | Every 1000ms | Producer |
| Receiver_Task | 1 (Lowest) | N/A (Receives) | Every 5000ms | Consumer |
- Queue Length: 5 elements
- Element Size: sizeof(int) (4 bytes)
- Total Size: 20 bytes
- Access Method: FIFO (First In, First Out)
- Thread-Safe Communication
- Multiple tasks can safely send to the same queue
- No data corruption or race conditions
- Automatic mutual exclusion handled by FreeRTOS
- Task Synchronization
- Receiver blocks when queue is empty
- Senders block when queue is full (portMAX_DELAY)
- Tasks automatically unblock when condition changes
- Priority-Based Scheduling
- Higher priority sender tasks run more frequently
- Lower priority receiver processes data when available
- ISR to Task Communication
- UART ISR can send data to queue (special FromISR function)
- Demonstrates safe interrupt-to-task data transfer
- Shows proper context switching from ISR
| Operation | Task Context | ISR Context | Blocking Behavior |
|---|---|---|---|
| Send | xQueueSend() |
xQueueSendFromISR() |
Blocks if queue full |
| Send to Back | xQueueSendToBack() |
xQueueSendToBackFromISR() |
Adds to end of queue |
| Send to Front | xQueueSendToFront() |
xQueueSendToFrontFromISR() |
Adds to front of queue |
| Receive | xQueueReceive() |
xQueueReceiveFromISR() |
Blocks if queue empty |
| Peek | xQueuePeek() |
xQueuePeekFromISR() |
Views without removing |
When you type 'r' in the serial terminal:
- UART ISR is triggered
- ISR sends value 12345 to the queue using xQueueSendToBackFromISR()
- Proper context switching is handled with portEND_SWITCHING_ISR()
- Receiver task will process this data when it runs
This demonstrates:
- Interrupt safety: Special FromISR functions must be used
- Context switching: Higher priority tasks may need to run immediately
- Real-time response: Interrupts can communicate with tasks
| Aspect | Task Operation | ISR Operation |
|---|---|---|
| Send Function | xQueueSend() |
xQueueSendFromISR() |
| Receive Function | xQueueReceive() |
xQueueReceiveFromISR() |
| Blocking | Can block with timeouts | Cannot block (returns immediately) |
| Context Switch | Automatic when blocked | Manual with portEND_SWITCHING_ISR() |
| Use Case | Normal task communication | Interrupt-driven events |
When Queue Has Space (Not Full)
- Sender tasks: Send immediately, no blocking
- Receiver task: Receives immediately if data available
When Queue is Full
- Sender tasks: Block until space becomes available
- Receiver task: Must take data to free space
When Queue is Empty
- Sender tasks: Send immediately
- Receiver task: Blocks until data arrives
Rubin Khadka Chhetri
📧 rubinkhadka84@gmail.com
🐙 GitHub: https://github.com/rubin-khadka