Use Cases

Periodic Task Execution (LED Toggle)

This use case illustrates periodic GPIO toggling driven by the Sequencer. It requires:

  • A task that updates the GPIO state.

  • A periodic trigger (for example SysTick) that schedules the task, ensuring regular toggles without blocking the main loop.

The code required to implement the periodic LED toggle is as follows:

  • Task implementation (GPIO toggle):

void gpio_toggle_task(void)
{
  /* Toggle GPIO pin */
  HAL_GPIO_TogglePin(MX_EXAMPLE_GPIO_PORT, MX_EXAMPLE_GPIO_PIN);
}
  • Periodic trigger (for example SysTick) schedules the task:

void SysTick_Handler(void)
{
  /* Schedule LED task at high priority (0) */
  SEQ_SetTask(TASK1, 0);
}

The following diagram summarizes this periodic sequence:

@startuml Sequencer_usecase_led_toggle
' Extracted verbatim from dynamic_behavior.md (Simple LED toggle)
' Keep original styling

title  **Periodic LED toggle using the Sequencer**

participant "User Application" as UA
participant "Sequencer" as SEQ
participant "TASK1" as TASK1
participant "TASK_IDLE" as TASK_IDLE
participant "SysTick Handler" as PERIODIC

UA  -> PERIODIC: configure a periodic trigger
group #LightGreen Init
UA  -> SEQ : SEQ_init();
UA  -> SEQ : SEQ_RegTask(TASK1,..);
UA  -> SEQ : SEQ_SetTask(TASK1,...);
end
group #LightYellow Process : infinite loop
  UA  --> SEQ : SEQ_Run();
  SEQ  --> TASK1 : Call task 1
  rnote over "TASK1" : GPIO toggle
  SEQ  <-- TASK1 : Task 1 complete
  hnote over "TASK_IDLE" #LightBlue : no task set, the Sequencer execute the IDLE
  SEQ  --> TASK_IDLE : Call task IDLE
  PERIODIC <[#Orange]--  : Periodic interrupt/trigger
  PERIODIC  --> SEQ : SEQ_SetTask(TASK1,...);
  SEQ  <-- TASK_IDLE : task IDLE complete
end
@enduml

Task Idle and Low-Power Management (LED Toggle)

This use case extends the periodic toggle example and shows how the Sequencer enables low-power operation. Compared to the previous example, the following must be added:

  • Implement the idle task to enter low-power mode when no tasks are scheduled.

  • Ensure the periodic trigger (for example SysTick) wakes the system from low-power mode to schedule the toggle task.

The code required to implement low-power operation with the idle task is as follows:

  • Idle task implementation (enter low-power mode):

void sequencer_idle_task(void)
{
  /* Enter low-power mode until the next interrupt */
  HAL_PWR_EnterSleepMode(HAL_PWR_LOW_PWR_MODE_WFI);
}

The following diagram summarizes this low-power sequence:

@startuml Sequencer_usecase_led_toggle_low_power_mode
' Extracted verbatim from dynamic_behavior.md (Simple LED toggle)
' Keep original styling

title  **Periodic LED toggle using the Sequencer in Low Power Mode**

participant "User Application" as UA
participant "Sequencer" as SEQ
participant "TASK1" as TASK1
participant "TASK_IDLE" as TASK_IDLE
participant "SysTick Handler" as PERIODIC

UA  -> PERIODIC: configure a periodic trigger
group #LightGreen Init
UA  -> SEQ : SEQ_init();
UA  -> SEQ : SEQ_RegTask(TASK1,..);
UA  -> SEQ : SEQ_SetTask(TASK1,...);
end
group #LightYellow Process : infinite loop
  UA  --> SEQ : SEQ_Run();
  SEQ  --> TASK1 : Call task 1
  rnote over "TASK1" : GPIO toggle
  SEQ  <-- TASK1 : Task 1 complete
  hnote over "TASK_IDLE" #LightBlue : no task set, the Sequencer execute the IDLE
    SEQ  --> TASK_IDLE : Call task IDLE
  group IDLE Task
    SEQ  --> UA : HAL_PWR_EnterSleepMode(HAL_PWR_LOW_PWR_MODE_WFI)
  end
    PERIODIC <[#Orange]--  : Periodic interrupt/trigger
    PERIODIC  --> SEQ : SEQ_SetTask(TASK1,...);
    SEQ  <-- TASK_IDLE : task IDLE complete
end
@enduml

Managing Task Waiting with SEQ_WaitEvt (LED Toggle)

This use case illustrates an event-driven GPIO toggle using the Sequencer. It requires:

  • A task that waits for an event and toggles the GPIO when the event is signaled.

  • A periodic source (for example SysTick) that sets the event to wake the waiting task.

The code required to implement the event-based LED toggle is as follows:

  • Task function (waits for event before toggling):

void gpio_toggle_wait_evt(void)
{
  /* Wait for the event set by the timer interrupt */
  SEQ_WaitEvt(EVT_TOGGLE_READY);

  /* Perform the toggle */
  HAL_GPIO_TogglePin(MX_EXAMPLE_GPIO_PORT, MX_EXAMPLE_GPIO_PIN);

  /* Schedule the task at high priority (0) */
  SEQ_SetTask(TASK1, 0);
}
  • SysTick callback:

void SysTick_Handler(void)
{
  /* Signal the event to wake the waiting task */
  SEQ_SetEvt(EVT_TOGGLE_READY);
}

The following diagram summarizes this event-driven sequence:

@startuml sequencer_usecase_led_toggle_wait_evt
' Extracted verbatim from dynamic_behavior.md (LED Toggle using SEQ_WaitEvt())
' Keep original styling

title  **LED Toggle using SEQ_WaitEvt()**

participant "User Application" as UA
participant "Sequencer" as SEQ
participant "TASK1" as TASK1
participant "TASK_IDLE" as TASK_IDLE
participant "SysTick Handler" as TIM_INT

UA  -> TIM_INT: configure a periodic trigger
group #LightGreen Init
  UA  -> SEQ : SEQ_init();
  UA  -> SEQ : SEQ_RegTask(TASK1,..);
  UA  -> SEQ : SEQ_SetTask(TASK1,...);
end

group #LightYellow Process : infinite loop
  UA  -> SEQ : SEQ_Run();
  SEQ  --> TASK1 : Call task 1
  group #LightBlue infinite loop :Task1 on SEQ_WaitEvt
    group sub SEQ_Run until event occurs
      rnote over "SEQ" : SEQ_Run()
      SEQ  --> TASK_IDLE : Call task IDLE
      TIM_INT <[#Orange]--  : Periodic interrupt/trigger
      TIM_INT  --> SEQ : SEQ_SetEvt();
      SEQ  <-- TASK_IDLE : task IDLE complete
    end
    rnote over "TASK1" : GPIO toggle
  end
end
@enduml

Task Priority Management (LED Toggle)

This use case shows how the Sequencer manages task priorities using three tasks:

  • Task 0: schedules Task 0 (low priority), Task 1 (medium priority), and Task 2 (high priority).

  • Task 1: toggles a GPIO at 0.5 Hz for 5 seconds.

  • Task 2: toggles a GPIO at 4 Hz for 5 seconds.

The Sequencer executes tasks according to their assigned priorities.

The code required to implement the task priority management is as follows:

  • Task 0 function (schedules the three tasks):

void task0(void)
{
  /* Schedule Task 0 (low priority) */
  SEQ_SetTask(TASK0, 2);

  /* Schedule Task 1 (medium priority) */
  SEQ_SetTask(TASK1, 1);

  /* Schedule Task 2 (high priority) */
  SEQ_SetTask(TASK2, 0);
}
  • Task 1 function (toggles GPIO at 0.5 Hz for 5 seconds):

void task1(void)
{
  /* Store the start time in milliseconds */
  uint32_t low_freq_toggle_time_start = HAL_GetTick();

  /* Loop to toggle the GPIO pin at low frequency */
  do
  {
    HAL_GPIO_TogglePin(MX_EXAMPLE_GPIO_PORT, MX_EXAMPLE_GPIO_PIN);

    /* Wait for a predefined delay (LOW_FREQ_TOGGLE_PERIOD) */
    HAL_Delay(LOW_FREQ_TOGGLE_PERIOD);

    /* Continue looping until the toggle time limit is reached */
  } while ((HAL_GetTick() - low_freq_toggle_time_start) < GPIO_TOGGLE_DURATION);
}
  • Task 2 function (toggles GPIO at 4 Hz for 5 seconds):

void task2(void)
{
  /* Store the start time in milliseconds */
  uint32_t high_freq_toggle_time_start = HAL_GetTick();

  /* Loop to toggle the GPIO pin at high frequency */
  do
  {
    HAL_GPIO_TogglePin(MX_EXAMPLE_GPIO_PORT, MX_EXAMPLE_GPIO_PIN);

    /* Wait for a predefined delay (HIGH_FREQ_TOGGLE_PERIOD) */
    HAL_Delay(HIGH_FREQ_TOGGLE_PERIOD);

    /* Continue looping until the toggle time limit is reached */
  } while ((HAL_GetTick() - high_freq_toggle_time_start) < GPIO_TOGGLE_DURATION);
}

The following diagram summarizes this priority-based task execution:

@startuml Sequencer_usecase_multi_task_led_toggle

title **LED Toggle with Task Priority Management**

participant "Application" as APP
participant "Sequencer" as SEQ
participant "Task 0" as TASK0
participant "Task 1" as TASK1
participant "Task 2" as TASK2

group #LightGreen Init
APP -> SEQ : SEQ_init()
APP -> SEQ : SEQ_RegTask(TASK0, 0, task0)
APP -> SEQ : SEQ_RegTask(TASK1, 0, task1)
APP -> SEQ : SEQ_RegTask(TASK2, 0, task2)
end
group #LightYellow Process : infinite loop
    APP -> SEQ : SEQ_Run()
    SEQ -> TASK0 : execute task0
    group #LightBlue task0
        TASK0 -> SEQ : SEQ_SetTask(TASK0, PRIO_LOW)
        TASK0 -> SEQ : SEQ_SetTask(TASK1, PRIO_MEDIUM)
        TASK0 -> SEQ : SEQ_SetTask(TASK2, PRIO_HIGH)
    end
    SEQ <-- TASK0 : task action complete

    SEQ -> TASK2 : execute task2
    group #LightBlue task2
        rnote over TASK2 : GPIO toggle 1 Hz for 5 seconds
    end
    SEQ <-- TASK2 : task action complete

    SEQ -> TASK1 : execute task1
    group #LightBlue task1
        rnote over TASK1 : GPIO toggle 0.125 Hz for 5 seconds
    end
    SEQ <-- TASK1 : task action complete

    hnote over APP : infinite loop inside SEQ_Run because Task0 is always active
end

@enduml

Task Pause/Resume (LED Toggle)

This use case extends the task priority management example by using a pause/resume mechanism to adjust the execution order.

It requires:

  • A controller task (Task 0) that delays for 2 seconds, enables all tasks, and initially suspends Task 2.

  • A worker task (Task 1) that toggles a GPIO at TASK1_FREQ and resumes Task 2 afterward.

  • A worker task (Task 2) that toggles a GPIO at TASK2_FREQ once it has been resumed.

The code required for the pause/resume use case is as follows:

  • Task 0 function (delay, enable all, suspend Task 2):

void task0(void)
{
  /* Wait 2 seconds before configuring execution state */
  HAL_Delay(2000);

  /* Enable all tasks for execution */
  SEQ_SetTask(TASK0, PRIO_LOW);
  SEQ_SetTask(TASK1, PRIO_MEDIUM);
  SEQ_SetTask(TASK2, PRIO_HIGH);

  /* Pause Task 2: the Sequencer skips its execution */
  SEQ_PauseTask(TASK2);
}
  • Task 1 function (toggle at TASK1_FREQ, then resume Task 2):

void task1(void)
{
  /* Store the start time in milliseconds */
  uint32_t low_freq_toggle_time_start = HAL_GetTick();

  /* Loop to toggle the GPIO pin at low frequency */
  do
  {
    HAL_GPIO_TogglePin(MX_EXAMPLE_GPIO_PORT, MX_EXAMPLE_GPIO_PIN);

    /* Wait for a predefined delay (LOW_FREQ_TOGGLE_PERIOD) */
    HAL_Delay(LOW_FREQ_TOGGLE_PERIOD);

    /* Continue looping until the toggle time limit is reached */
  } while ((HAL_GetTick() - low_freq_toggle_time_start) < GPIO_TOGGLE_DURATION);

  /* Resume Task 2 to allow its execution */
  SEQ_ResumeTask(TASK2);
}
  • Task 2 function (toggle at TASK2_FREQ when not suspended):

void task2(void)
{
  /* Store the start time in milliseconds */
  uint32_t high_freq_toggle_time_start = HAL_GetTick();

  /* Loop to toggle the GPIO pin at high frequency */
  do
  {
    HAL_GPIO_TogglePin(MX_EXAMPLE_GPIO_PORT, MX_EXAMPLE_GPIO_PIN);

    /* Wait for a predefined delay (HIGH_FREQ_TOGGLE_PERIOD) */
    HAL_Delay(HIGH_FREQ_TOGGLE_PERIOD);

    /* Continue looping until the toggle time limit is reached */
  } while ((HAL_GetTick() - high_freq_toggle_time_start) < GPIO_TOGGLE_DURATION);
}

The following diagram summarizes this pause/resume sequence:

@startuml Sequencer_usecase_pause_resume

title **LED Toggle with Pause/Resume Control**

participant "Application" as APP
participant "Sequencer" as SEQ
participant "Task 0" as TASK0
participant "Task 1" as TASK1
participant "Task 2" as TASK2

group #LightGreen Initialization
APP -> SEQ : SEQ_init()
APP -> SEQ : SEQ_RegTask(TASK0, 0, task0)
APP -> SEQ : SEQ_RegTask(TASK1, 0, task1)
APP -> SEQ : SEQ_RegTask(TASK2, 0, task2)
end

group #LightYellow Main Loop
    APP -> SEQ : SEQ_Run()
    SEQ -> TASK0 : execute task0
    group #LightBlue task0
        rnote over TASK0 : Delay 2s
        TASK0 -> SEQ : SEQ_SetTask(TASK0, PRIO_LOW)
        TASK0 -> SEQ : SEQ_SetTask(TASK1, PRIO_MEDIUM)
        TASK0 -> SEQ : SEQ_SetTask(TASK2, PRIO_HIGH)
        TASK0 -> SEQ : SEQ_PauseTask(TASK2)
    end
    SEQ <-- TASK0 : task action complete

    SEQ -> TASK1 : execute task1
    group #LightBlue task1
        rnote over TASK1 : GPIO toggle at TASK1_FREQ
        TASK1 -> SEQ : SEQ_ResumeTask(TASK2)
    end
    SEQ <-- TASK1 : task action complete

    SEQ -> TASK2 : execute task2
    group #LightBlue task2
        rnote over TASK2 : GPIO toggle at TASK2_FREQ
    end
    SEQ <-- TASK2 : task action complete
end

@enduml

Note

SysTick is used here for simplicity, but any periodic source can trigger the task (hardware timer ISR, RTC alarm, external interrupt, DMA callback, or an event set by another module). This note applies to all use cases where a periodic trigger is referenced.

List of Sequencer Examples

The following table lists the available examples:

Example Name

Description

example_gpio_toggle

Periodic task execution performing a GPIO toggle.

example_task_prio

Task priority management using three tasks that perform GPIO toggling.