ELEC-C7222
Libraries for ELEC C7222 Course Work
Loading...
Searching...
No Matches
main_freertos_device.cpp File Reference

FreeRTOS C++ device example demonstrating buttons, LEDs, PWM, and synchronization. More...

#include <cassert>
#include <thread>
#include <chrono>
#include <cstdio>
#include "freertos_task.hpp"
#include "freertos_timer.hpp"
#include "gpio.hpp"
#include "platform.hpp"
#include "button_event.hpp"
#include "pwm.hpp"
#include "safe_led.hpp"
Include dependency graph for main_freertos_device.cpp:

Functions

void button1_irq_dispatcher (void *arg)
 Timer callback that publishes Button 1 events to the task.
 
void button1_irq_handler (uint32_t events)
 GPIO IRQ handler for Button 1.
 
void button1_monitor (void *param)
 Button 1 monitoring task.
 
void button2_monitor (void *param)
 Button 2 monitoring task.
 
void system_monitor (void *param)
 Periodic system task that blinks the shared system LED.
 
int main ()
 Program entry point.
 

Variables

c7222::FreeRtosTimerdispatcher_timer = nullptr
 One-shot timer used to defer GPIO IRQ handling to the timer task.
 
c7222::ButtonEvent button1_event
 Thread-safe event mailbox for Button 1 IRQ events.
 
c7222::SafeLedsystem_led = nullptr
 Shared LED protected by SafeLed for multi-task coordination.
 
std::unique_ptr< c7222::PwmOutpwm_led3_red = nullptr
 PWM-controlled LED instance (LED3_RED).
 
float duty_cycle = 1.0f
 Current PWM duty cycle used to dim LED3_RED.
 

Detailed Description

FreeRTOS C++ device example demonstrating buttons, LEDs, PWM, and synchronization.

Purpose of this example:

  • Show how to use the C++ device wrappers (GPIO/LED/Button/PWM) with FreeRTOS-CPP11 on the Pico W platform.
  • Demonstrate safe cross-task access to a shared LED using a mutex/condition_variable via the SafeLed helper.
  • Demonstrate event delivery from a GPIO ISR to normal task context using a FreeRTOS software timer and the ButtonEvent helper class.

Devices and objects used:

  • Board LEDs (LED1_GREEN, LED2_RED, LED2_GREEN) via Led and SafeLed.
  • Board buttons (BUTTON_B1, BUTTON_B2) via Button/GPIO IRQ and polling helpers.
  • PWM output for LED3_RED via PwmOut to demonstrate duty-cycle control.
  • FreeRTOS wrapper classes (FreeRtosTimer, FreeRtosTask) to defer ISR work to task context and use wrapper delay/scheduler helpers.

Concurrency and synchronization:

  • std::thread is used to create FreeRTOS tasks through FreeRTOS-CPP11 integration.
  • ButtonEvent uses std::mutex + std::condition_variable to provide a wait-with-timeout event mailbox for button IRQ events.
  • SafeLed uses std::mutex + std::condition_variable to serialize access to a shared LED across multiple tasks.

Helper classes:

  • ButtonEvent collects IRQ events and provides a blocking GetEvents() API.
  • SafeLed ensures exclusive LED control between tasks, avoiding concurrent writes.

ISR dispatching model:

  • The GPIO ISR for Button 1 records the event and starts a one-shot FreeRtosTimer, passing the event bitmask as a void* argument.
  • The timer callback runs in the FreeRTOS timer service task (normal execution context) and forwards the event to ButtonEvent.

ButtonEvent dispatch via one-shot timer (detailed flow):

  1. A GPIO interrupt fires for BUTTON_B1 and button1_irq_handler runs in IRQ context.
  2. The ISR does minimal work: it starts a one-shot FreeRtosTimer and passes the event bitmask as the timer's callback_arg (no heavy logic in IRQ).
  3. When the timer expires, button1_irq_dispatcher runs in the FreeRTOS timer service task (normal task context).
  4. The dispatcher converts the void* argument back to the event bitmask and calls button1_event.SetEvents(events), which notifies the waiting task.
  5. The button1_monitor task unblocks in GetEvents() and processes the event.

System LED behavior:

  • The system LED (LED1_GREEN) is shared by button2_monitor and system_monitor.
  • When Button 2 is pressed, button2_monitor tries to acquire the LED; if it succeeds, the LED stays on while the button remains pressed, then turns off on release.
  • When Button 2 is not holding the LED, system_monitor blinks it by acquiring the LED for 500 ms, turning it on, then off and releasing it.

Function Documentation

◆ button1_irq_dispatcher()

void button1_irq_dispatcher ( void *  arg)

Timer callback that publishes Button 1 events to the task.

This runs in the FreeRTOS timer service task context, not in interrupt context. It pushes the event bitmask into ButtonEvent.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ button1_irq_handler()

void button1_irq_handler ( uint32_t  events)

GPIO IRQ handler for Button 1.

Runs in IRQ context. It must be minimal, so it schedules the dispatcher timer and passes the event bitmask as the timer callback argument.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ button1_monitor()

void button1_monitor ( void *  param)

Button 1 monitoring task.

  • Arms the IRQ and the dispatcher timer.
  • Waits for events using ButtonEvent (condition-variable backed).
  • Toggles LED2_GREEN on timeout (heartbeat).
  • On press, turns LED2_RED on and decreases LED3_RED PWM duty cycle, which decreases brightness.
  • On release, turns LED2_RED off.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ button2_monitor()

void button2_monitor ( void *  param)

Button 2 monitoring task.

Uses polling (every 100 ms) and coordinates access to the shared system LED via SafeLed. This demonstrates cross-task protection of a shared LED.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( void  )

Program entry point.

Here is the call graph for this function:

◆ system_monitor()

void system_monitor ( void *  param)

Periodic system task that blinks the shared system LED.

It attempts to acquire the SafeLed with a timeout to avoid blocking indefinitely when another task holds the LED.

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ button1_event

c7222::ButtonEvent button1_event

Thread-safe event mailbox for Button 1 IRQ events.

Producers: the timer callback (not ISR). Consumers: the Button 1 monitor task.

◆ dispatcher_timer

c7222::FreeRtosTimer* dispatcher_timer = nullptr

One-shot timer used to defer GPIO IRQ handling to the timer task.

The ISR records the event and starts this timer. When it fires, it runs in the FreeRTOS timer service task and signals the ButtonEvent object.

◆ duty_cycle

float duty_cycle = 1.0f

Current PWM duty cycle used to dim LED3_RED.

◆ pwm_led3_red

std::unique_ptr<c7222::PwmOut> pwm_led3_red = nullptr

PWM-controlled LED instance (LED3_RED).

◆ system_led

c7222::SafeLed* system_led = nullptr

Shared LED protected by SafeLed for multi-task coordination.