PSoC5LP RTOS
Lab 18 — Integrated Application + Watchdog

FreeRTOS on PSoC 5LP · Lab Series Platform: CY8CKIT-059 (PSoC 5LP, Cortex-M3) · PSoC Creator 4.4 · FreeRTOS Kernel V11 Theme: one system from all the labs, guarded by a hardware watchdog fed only when every task is healthy Pairs with: Chapters 13, 14, 18 & 19 (architecture, memory, reliability, integration)


1. Introduction & Objectives

This is the capstone. Every mechanism from the series — periodic sampling and filtering, a PWM control loop, a UART command interface, queues, a bus mutex, software timers — comes together into one working system. And because a real product must survive the fault you did not foresee, it is guarded by a hardware watchdog: a timer that resets the MCU unless it is regularly fed. The craft is in how you feed it: not blindly, but only after a Supervisor task has confirmed that every worker is still making progress.

After this lab you can:

  • Integrate independent tasks into a coherent system with clear data flow and priorities.
  • Use a hardware watchdog (WDT) as the last line of defence against hangs and deadlocks.
  • Feed the watchdog correctly — from a supervisor that checks per-task heartbeats, never blindly.
  • Size the watchdog timeout against the supervisor period with margin.
  • Detect a watchdog reset on boot and handle it gracefully instead of silently.
  • (Extension) Have the Supervisor name the stalled worker with pcTaskGetName and read its eTaskGetState, to tell a hung task from a healthy blocked one.

2. Prerequisites

Hardware - CY8CKIT-059 PSoC 5LP Prototyping Kit - RobotSoC Kit: the peripherals from the labs you integrate (LED/PWM load, an analog source, UART); a "fault" LED

Software - PSoC Creator 4.4 with the FreeRTOS V11 BaseProject

Chapters (sync progress) - Required: Chapter 18 (watchdog & reliability) and Chapter 19 (system integration); draws on Chapter 13 (architecture) and Chapter 14 (memory). - Labs integrated: Lab 14 (UART commands), Lab 15 (ADC + filter), Lab 16 (PWM), with Lab 11 (timers) and Lab 17 (bus mutex) as needed.

3. Reading Materials / References

  • Chapter 18 slides — Watchdog & Reliability (the WDT, feeding, reset reasons).
  • Chapter 19 slides — System Integration (task decomposition, priorities, data flow).
  • PSoC API: CyWdtStart, CyWdtClear, CyResetStatus / CY_RESET_WD.
  • FreeRTOS API: xTaskDelayUntil, task notifications, queues, mutexes (from earlier labs).
  • (Extension) pcTaskGetName, eTaskGetState (and the TaskHandle_t of each worker) — identify and inspect a specific task.

4. Background & Theory of Operation

What a watchdog is. A watchdog timer is an independent hardware counter that counts up on its own clock. If it reaches its limit, it resets the MCU. Normal firmware must feed (kick/clear) it before that happens — CyWdtClear() resets the count to zero. So a running, healthy system keeps the count low; a system that has stopped feeding it gets reset. The watchdog cannot be stopped by the very bug it is meant to catch, because it lives in hardware, separate from your code.

Feed it correctly — the key idea. The naive mistake is to kick the watchdog from a bare timer ISR or a single always-running task. That keeps the system alive even when the real work has died — the dog is fed while the tasks are dead. The correct pattern: each worker task bumps a heartbeat counter every time round its loop; a single Supervisor task wakes periodically, checks that every heartbeat has advanced since the last check (a logical AND of all tasks' progress), and only then feeds the watchdog. If any task has hung, deadlocked, or run away, its heartbeat stalls, the Supervisor withholds the feed, and the watchdog resets the system.

Sizing the timeout. The WDT timeout must be longer than the Supervisor's period, with margin — otherwise a single late check causes a false reset. But it must be short enough that a real hang is caught quickly. Pick the timeout a few times the supervisor period, after accounting for the slowest healthy case.

Recover visibly. A reset should not be silent. On boot, read the reset reason (CyResetStatus & CY_RESET_WD): if the last reset was the watchdog, that is a fault signal — light a fault LED, log it over UART, increment a stored counter. A watchdog reset returns the system to a known-good state, but you want to know it happened, so the underlying bug can be found and fixed.

The watchdog is the last line, not the first. Design tasks that do not hang: bounded waits, timeouts on every blocking call, consistent lock ordering (Lab 17), right-sized stacks (Lab 13). The watchdog then catches only the case you missed — it is a safety net, not a substitute for correct design.

Extension — name the culprit before you reset. A bare heartbeat tells you that the system is unhealthy, not which task failed or how. Before withholding the feed (or on the way down), make the Supervisor report the culprit: it already holds each worker's TaskHandle_t, so pcTaskGetName(handle) gives the task's name and eTaskGetState(handle) gives its state — eRunning, eReady, eBlocked, eSuspended, or eDeleted. This distinguishes two very different failures that a stalled heartbeat looks identical from the outside: a task stuck in eBlocked forever (deadlocked on a lock or a never-signalled semaphore) versus one spinning in eReady/eRunning (a runaway loop) versus one wrongly eSuspended. Logging "WDT: worker 'Comms' stalled in state eBlocked" over UART just before the reset turns the next boot's "it restarted" into "Comms deadlocked on the bus mutex" — the diagnostic bridge to Lab 27's fault post-mortem. eTaskGetState is a debug/health tool (it walks the kernel lists), so call it from the Supervisor, not from a hot path.

5. RTOS Task Architecture

INTEGRATED SYSTEM — WORKERS REPORT HEALTH, THE DOG GUARDS ALL Sensor Task (Lab 15) sample + filter · hb++ Control Task (Lab 16) PWM slew · hb++ Comms Task (Lab 14) UART cmd/status · hb++ readings q setpoint q Supervisor Task all heartbeats advanced? AND → feed the watchdog else: withhold the kick heartbeats Watchdog HW timer (WDT) counts to timeout MCU reset on timeout clean restart feed reset Feed the dog correctly · Never kick the WDT from a bare timer ISR — that would keep resetting even while tasks are dead. · One Supervisor feeds it, and only after confirming every monitored task has made progress. · WDT timeout > the slowest healthy supervisor period, with margin — or you get false resets. Integration & recovery · All the lab mechanisms in one system: queues, a bus mutex, software timers, notifications. · A hang, deadlock, or runaway task stops its heartbeat; the dog resets the MCU to a known-good state. · On boot, read the reset reason and log/flag a WDT reset so faults are visible, not silent. Capstone: the watchdog is the last line of defence — design tasks not to hang, then let the dog catch the case you missed.

The Sensor, Control, and Comms tasks do the real work and exchange data through queues; each bumps a heartbeat every loop. The Supervisor task checks that all heartbeats advanced and, only then, feeds the hardware watchdog; otherwise it withholds the feed and the WDT resets the MCU. The panels give the rules for feeding correctly and for integration and recovery.

6. The Watchdog Over Time

The watchdog counter — feeding keeps it low; a hang lets it reach timeout:

The watchdog counter — feeding keeps it low; a hang lets it reach timeout Each feed resets the WDT count; if the Supervisor stops feeding, the count climbs to the limit and resets the MCU 0 WDT timeout → MCU reset a task hangs → Supervisor stops feeding RESET feeds (count reset each time) — healthy system restarts, feeding resumes Conceptual / idealized

Each feed resets the count; when the Supervisor stops feeding, the count climbs to the timeout and the MCU resets, then healthy feeding resumes.

Health-gated kick — the dog is fed only if every task advanced:

Health-gated kick — the dog is fed only if every task advanced Each task bumps its heartbeat; the Supervisor feeds the WDT only when all have moved since the last check Sensor hb Control hb Comms hb Supervisor check 1 check 2 check 3 check 4 stalled feed ✓ feed ✓ withhold ✗ feed ✓ At check 3 the Comms heartbeat did not advance, so the Supervisor withholds the feed — the WDT then times out and resets. The watchdog is driven by real progress of every task, not by a blind periodic kick. Conceptual / idealized

At the check where the Comms heartbeat did not advance, the Supervisor withholds the feed — so the watchdog is driven by real progress, not a blind periodic kick.

Together: the watchdog reflects the health of the whole system. Feed it from evidence that every task is alive, and it becomes a true guardian rather than a rubber stamp.

7. Schematic Circuit & Pin Configuration

  • The peripherals of the labs you integrate (PWM load, analog input, UART).
  • Fault LED → GPIO + 220 Ω → GND, lit on a detected WDT reset.
  • Assign the pins in <project>.cydwr → Pins.

8. PSoC Creator Configuration

  • The components from the integrated labs; a Digital Output Pin for the fault LED.
  • The watchdog is a system resource — no component to place; start it with CyWdtStart(...) and feed with CyWdtClear().
  • FreeRTOSConfig.h (already set): configCHECK_FOR_STACK_OVERFLOW = 2, configUSE_MALLOC_FAILED_HOOK = 1, configUSE_TIME_SLICING = 1 (course default), heap_4.

9. Provided Template

You are given Lab18_Template_main.c:

  • Given: all includes (note #include "FreeRTOS_PSoC.h"), the per-worker heartbeat counters, worker-task skeletons that already bump their heartbeat, and a complete main() that checks the reset reason, starts the WDT, creates the tasks, and starts the scheduler.
  • You write: vSupervisorTask() — snapshot the heartbeats, wait one period, confirm each advanced, and feed the WDT only if all did — plus the Exp02/03 steps.
  • Do not change the boot sequence in main().
/* inside vSupervisorTask, each period: */
uint8_t healthy = 1u;
for (i = 0u; i < NUM_WORKERS; i++) {
    if (hb[i] == last[i]) healthy = 0u;   /* this task did not progress */
    last[i] = hb[i];
}
if (healthy) {
    CyWdtClear();            /* FEED -> no reset */
}                           /* else: withhold -> WDT times out and resets */

10. Lab Experiments

Exp01 — Basic: the supervised system

Drop your Lab 14/15/16 bodies into the worker tasks (or keep the stubs), and complete the Supervisor so it feeds the WDT only when all heartbeats advance. Run it. Expected: the system runs indefinitely without resetting, because every task keeps progressing and the Supervisor keeps feeding the dog.

Exp02 — Advanced: make the dog bite

Deliberately hang one worker — an infinite loop, a block on a never-signalled semaphore, or a long CyDelay. Its heartbeat stalls. Expected: the Supervisor withholds the feed, the WDT times out, and the MCU resets — observable as the system restarting (and the fault LED, from Exp03).

Exp03 — Challenge: recover visibly, and tune the timeout

On boot, check CyResetStatus & CY_RESET_WD; if set, light the fault LED and/or log "WDT reset" over UART. Then tune the WDT timeout and SUPERVISOR_MS: shorten the timeout until a healthy system suffers false resets, then back off to a safe margin. Expected: a watchdog reset is detected and reported on the next boot, and you can justify your chosen timeout relative to the supervisor period.

Exp04 — Extension: name and inspect the stalled worker

Give the Supervisor each worker's TaskHandle_t. When a heartbeat fails to advance, before withholding the feed, log pcTaskGetName(h) and eTaskGetState(h) for the offender over UART. Reproduce two distinct hangs from Exp02 — a deadlock (block on a never-given semaphore → eBlocked) and a runaway loop (eReady/eRunning) — and show the report tells them apart. Expected: a UART line naming the culprit task and its state just before the reset, with the deadlock and the runaway distinguishable from that line alone.

11. Testing & Verification

#Pass condition
Exp01 All tasks run; the Supervisor feeds on all-healthy; the system never falsely resets.
Exp02 Hanging one task stalls its heartbeat; the Supervisor withholds the feed; the MCU resets.
Exp03 A WDT reset is detected on boot and reported; the timeout is tuned with a justified margin.
Exp04 The Supervisor names the stalled worker (pcTaskGetName) and its eTaskGetState; a deadlock vs a runaway are distinguishable from the log.

Submit: your Supervisor task, your Exp02 hang + observed reset, and your Exp03 reset-reason handling and timeout justification.

12. Q&A & Troubleshooting

  • System resets even when healthy → WDT timeout too short relative to SUPERVISOR_MS; increase the timeout or shorten the supervisor period.
  • Hang does NOT reset the system → you fed the WDT unconditionally (e.g. from an ISR or without the AND check); feed only on all-healthy.
  • Resets but you never see why → not reading CyResetStatus; check CY_RESET_WD on boot and flag it.
  • One slow-but-healthy task trips the dog → its heartbeat period is longer than the supervisor check; count progress over a longer window for that task, or raise the timeout.
  • Everything resets right after programming → the WDT started before the first feed path was ready; start it only once the supervisor is about to run, with adequate timeout.
  • CyWdtClear seems ignored → the WDT was not started, or is being fed from the wrong place; keep one feed point in the Supervisor.

13. Analysis Questions & Lab Report

  1. What is a hardware watchdog, and why can it catch faults that software checks cannot?
  2. Why feed the watchdog from a Supervisor that checks per-task heartbeats, rather than from a timer ISR?
  3. How do you choose the WDT timeout relative to the supervisor period, and what goes wrong at each extreme?
  4. Why read the reset reason on boot, and what should the system do on a watchdog reset?
  5. (Extension) How do pcTaskGetName and eTaskGetState let the Supervisor tell a deadlocked task from a runaway one, when both show the same stalled heartbeat?

Your report should include your Supervisor task, your induced-hang result, your reset-reason handling, your Exp04 culprit report, and answers to the questions.

© 2026 Air Supply Information Center (Air Supply BBS)