PSoC5LP RTOS
Lab 03 — Task Control: Suspend & Resume
FreeRTOS on PSoC 5LP · Lab Series. Platform: CY8CKIT-059 (PSoC 5LP, Cortex-M3) · PSoC Creator 4.4 · FreeRTOS Kernel V11. Pairs with Chapter 3 — Task Control (and Chapter 1 — Tasks).
1. Introduction & Objectives
So far, tasks have only paused themselves with vTaskDelay. This lab introduces control from one task over another: a button task pauses and resumes a blinking LED task through the blink task's handle, using vTaskSuspend and vTaskResume. Along the way, you see the difference between Blocked, Suspended, and Deleted.
After this lab you can:
- Keep a task handle from xTaskCreate and use it to control that task later.
- Suspend and resume a task with vTaskSuspend / vTaskResume.
- Explain why suspend/resume are not counted, and track your own paused flag.
- Tell Blocked (automatic, self-clearing) from Suspended (manual, no timeout) from Deleted (permanent).
- Debounce a button so one press = one action.
2. Prerequisites
Hardware: CY8CKIT-059 PSoC 5LP Prototyping Kit; RobotSoC Kit 1× LED + 220 Ω, 1× push button.
Software: PSoC Creator 4.4 with the FreeRTOS V11 BaseProject.
Chapters (sync progress): Required — Chapter 3 (Task Control: handle, suspend/resume, states), builds on Chapter 1 (tasks); Peripheral prerequisite — basic GPIO (LED/switch) is covered in the separate (non-FreeRTOS) Lab 01–02.
3. Reading Materials / References
- Chapter 3 slides — Task Control (suspend/resume, handle, Blocked vs Suspended vs Deleted).
- FreeRTOS API: vTaskSuspend, vTaskResume, xTaskResumeFromISR, eTaskGetState, vTaskDelete.
4. Background & Theory of Operation
Handles. xTaskCreate(..., &hTask) writes a handle — a reference to the created task — into hTask. Any task that holds the handle can act on that task: suspend it, resume it, query its state, change its priority, or delete it. In this lab the control task holds hBlink so it can pause the blink task.
Suspend vs delay. vTaskDelay is a timed pause the task asks for itself; it ends on its own. vTaskSuspend(hTask) is an open-ended stop another task applies: the task is taken off the scheduler and stays off — no timeout — until something calls vTaskResume(hTask). A suspended task uses no CPU, just like a blocked one, but it will never wake on its own.
The three states to keep straight.
- Blocked — automatic: waiting on a delay or an event; clears itself on timeout/event; the task stays alive.
- Suspended — manual: vTaskSuspend took it off the scheduler; only vTaskResume returns it; the task stays alive.
- Deleted — manual: vTaskDelete removes it permanently and frees its memory; it cannot be resumed.
Suspend/resume are not counted. Two vTaskSuspend calls still need only one vTaskResume. So you cannot rely on call-counting; keep your own paused flag and flip it on each press. eTaskGetState(hTask) lets you confirm the task reads eSuspended while paused and eBlocked while delaying.
From an ISR. vTaskResume is task-context only. If a resume comes from an interrupt, use xTaskResumeFromISR instead (introduced with interrupts later). This lab polls the button in a task, so vTaskResume is correct here.
Debounce. A mechanical button bounces: one press can read as many. Add a short delay after acting (or require a release) so one physical press produces one suspend/resume.
5. RTOS Task Architecture & State Model
Left — the two tasks: the Control (Button) Task (priority 2) owns hBlink and calls vTaskSuspend / vTaskResume on the Blink Task (priority 1). Right — the state model: the blink task moves Running ⇄ Ready ⇄ Blocked on its own, but only an explicit vTaskSuspend/vTaskResume crosses into and out of Suspended, and vTaskDelete is one-way to Deleted.
6. Suspend / Resume Over Time
The LED toggles every 200 ms. The first press suspends the blink task, so the LED freezes at whatever level it was at — the task is off the scheduler and does no further toggling. The next press resumes it and the toggling continues. Nothing happens to the LED during the suspended band because a suspended task simply does not run.
7. Schematic Circuit & Pin Configuration
- LED → GPIO + 220 Ω → GND.
- BTN → push button to GND, internal pull-up (active-low: pressed reads 0).
- Assign both in <project>.cydwr → Pins.
8. FreeRTOS API Reference
| API | Purpose |
|---|---|
| xTaskCreate(..., &handle) | Create a task and capture its handle for later control. |
| vTaskSuspend(h) | Take a task h off the scheduler; NULL suspends the caller. No timeout. |
| vTaskResume(h) | Resume a suspended task (task context only). |
| xTaskResumeFromISR(h) | ISR-safe resume; returns whether a context switch is needed. |
| eTaskGetState(h) | Query a task's state (Running/Ready/Blocked/Suspended). |
| vTaskDelete(h) | Remove a task permanently; NULL deletes the caller. |
9. Provided Template
You are given Lab03_Template_main.c:
- Given: all includes (note #include "FreeRTOS_PSoC.h"), both handles, and a complete main() that creates the blink task first (so hBlink is valid before the control task runs), then the control task. Both task functions have a placeholder so the project builds and runs.
- You write: the bodies of vBlinkTask() and vControlTask(), per the TODO(Exp01) comments — including a paused flag and a debounce.
- Do not change the boot sequence in main().
static void vControlTask(void *arg)
{
/* bool paused = false; */
for (;;)
{
/* TODO(Exp01): if (BTN_Read()==0) { paused=!paused;
* paused ? vTaskSuspend(hBlink) : vTaskResume(hBlink);
* vTaskDelay(pdMS_TO_TICKS(250)); }
* vTaskDelay(pdMS_TO_TICKS(10)); */
vTaskDelay(pdMS_TO_TICKS(10)); /* placeholder */
}
}
10. Lab Experiments
Exp01 — Basic: pause & resume a blink. Write both task bodies. One press pauses the blink (the LED freezes); the next resumes it. Use a paused flag and debounce so one press = one toggle. Expected: the LED freezes and continues cleanly, one press at a time.
Exp02 — Advanced: watch the states. In the control task, read eTaskGetState(hBlink) and print it over UART. Confirm the blink task reads eBlocked while it is delaying and eSuspended while paused. Then call vTaskSuspend(hBlink) twice in a row and show that a single vTaskResume still brings it back — proof that suspends are not counted. Expected: a short UART log of the state across a press cycle.
Exp03 — Challenge: delete vs suspend (and a third task). Add a third task (e.g. a 500 ms LED or a 1 s UART status). Then compare: after vTaskSuspend you can resume; after vTaskDelete(hBlink) the task is gone and a later resume does nothing (and hBlink is stale). Expected: you can state why suspend is reversible and delete is not, and the other tasks keep running throughout.
11. Testing & Verification
| # | Pass condition |
|---|---|
| Exp01 | One press pauses the blink (LED frozen), next press resumes; one press = one toggle. |
| Exp02 | UART shows eBlocked/eSuspended; two suspends + one resume still resumes. |
| Exp03 | Suspend is reversible; after delete, the task is gone; other tasks unaffected. |
Submit: your two task bodies, the Exp02 state log, and a one-line suspend-vs-delete explanation.
12. Q&A & Troubleshooting
- One press toggles several times → button bounce; add a debounce delay or require a release.
- LED never resumes → you suspended twice but resumed once, or lost track of paused; keep the flag.
- HardFault on resume → hBlink is stale (task was deleted), or you resumed before the task was created.
- Whole system freezes → you suspended a task that holds a shared resource, or suspended the control task itself.
- Must resume from an ISR → use xTaskResumeFromISR, not vTaskResume.
13. Analysis Questions & Lab Report
- What is a task handle, and what can another task do with it?
- Compare Blocked, Suspended, and Deleted: who causes each, and how does the task leave that state?
- Why are suspend/resume "not counted," and what does that force you to do in code?
- When must you use xTaskResumeFromISR instead of vTaskResume?
Your report should include your task bodies, the Exp02 log, and answers to the four questions.