# Emergency Stop Procedure for RF Power Amplifier Protection in PLFM-RADAR

> Learn the emergency stop procedure for RF power amplifier protection in PLFM-RADAR. Discover how this routine prevents damage during critical faults like over-current or over-temperature.

- Repository: [NawfalMotii79/PLFM_RADAR](https://github.com/NawfalMotii79/PLFM_RADAR)
- Tags: how-to-guide
- Published: 2026-08-20

---

**The PLFM-RADAR firmware implements a three-layer emergency stop routine that immediately disables RF power amplifier rails and enters a safe-hold loop when critical faults are detected.** This protection mechanism prevents catastrophic damage to the GaN PA during over-current, over-temperature, or watchdog timeout conditions.

This guide explains how the emergency stop procedure works in the open-source PLFM-RADAR project, walking through the fault detection logic, shutdown sequence, and verification test suite. All implementations are found in the microcontroller firmware under [`9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp).

## Three-Layer Protection Architecture

The RF power amplifier protection system operates through coordinated hardware and software layers:

| Layer | Purpose | Key Component |
|-------|---------|-------------|
| **Fault detection** | Identify PA-damaging conditions | `SystemError_t` enum in [`main.cpp`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/main.cpp) (lines 808-826) |
| **Decision logic** | Classify critical vs. recoverable faults | `handleSystemError()` function (lines 1088-1095) |
| **Shutdown execution** | Safely de-energize all PA rails | `Emergency_Stop()` function (lines 820-858) |

## Fault Detection and Error Classification

Hardware faults that threaten the RF power amplifier are enumerated in the `SystemError_t` type definition. Located at [`9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp) lines 808-826, this enum includes:

- `ERROR_RF_PA_OVERCURRENT` — PA drain current exceeds safe threshold
- `ERROR_RF_PA_BIAS_FAULT` — GaN gate bias regulation failure
- `ERROR_TEMPERATURE_HIGH` — Thermal runaway condition
- `ERROR_POWER_SUPPLY` — Bulk rail collapse or sequencing error
- `ERROR_WATCHDOG_TIMEOUT` — Control loop deadlock detected

These values represent conditions where continued operation risks permanent PA damage or fire hazard.

## Critical Error Handling Logic

The `handleSystemError()` function serves as the central dispatcher for all fault conditions. Implemented in [`main.cpp`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/main.cpp) lines 1088-1095, it performs three essential operations before deciding on recovery or shutdown:

1. **State tracking** — increments `error_count` and stores `last_error` for diagnostic logging
2. **Error logging** — outputs diagnostic message via debug console
3. **Severity classification** — checks if error falls within critical range

For critical errors, the function sets `system_emergency_state = true` **before** invoking `Emergency_Stop()`. This ordering—documented as *GAP-3 FIX 5* in the source—ensures external systems receive immediate notification that an emergency stop is in progress.

```c
// Critical error range check triggers emergency stop
if (error >= ERROR_RF_PA_OVERCURRENT && 
    error <= ERROR_WATCHDOG_TIMEOUT) {
    system_emergency_state = true;  // Notify external systems FIRST
    Emergency_Stop();                // Enter infinite safe-hold loop
}

```

Non-critical errors route to `attemptErrorRecovery()` for transient fault handling.

## Emergency Stop Shutdown Sequence

The `Emergency_Stop()` function at [`main.cpp`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/main.cpp) lines 820-858 implements a deterministic, fast-to-slow rail shutdown protocol. This sequencing prevents dangerous operating modes in GaN PAs, which can self-bias or oscillate if control voltages persist while drain supplies collapse.

The ordered actions are:

1. **Clear all DAC outputs** via `DAC5578_ActivateClearPin` — removes bias voltages immediately
2. **Disable TX mixers** — deasserts `GPIOD` pin 11 to stop RF drive
3. **Cut PA 5V auxiliary supplies** — disables `EN_P_5V0_PA1`, `EN_P_5V0_PA2`, `EN_P_5V0_PA3`
4. **Cut PA 5.5V bulk supply** — disables `EN_P_5V5_PA`
5. **Disable RF-PA VDD** — deasserts `EN_DIS_RFPA_VDD` (main drain supply)
6. **Enter infinite hold loop** — refreshes independent watchdog (IWDG) every 100ms to prevent reset

```c
void Emergency_Stop(void) {
    // 1. Clear DAC outputs immediately
    DAC5578_ActivateClearPin();
    
    // 2. Disable TX mixers
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_RESET);
    
    // 3-5. Cut PA power rails in sequence
    HAL_GPIO_WritePin(GPIOA, EN_P_5V0_PA1 | EN_P_5V0_PA2 | EN_P_5V0_PA3, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, EN_P_5V5_PA, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB, EN_DIS_RFPA_VDD, GPIO_PIN_RESET);
    
    // 6. Infinite safe-hold with watchdog servicing
    while (1) {
        HAL_IWDG_Refresh(&hiwdg);
        HAL_Delay(100);
    }
}

```

The IWDG refresh is critical: without it, the watchdog would timeout and reset the MCU, potentially re-enabling power rails during boot before fault conditions are cleared.

## System State Exposure

The global `system_emergency_state` flag propagates emergency status to external systems. The `getSystemStatusForGUI()` function reports `"EMERGENCY_STOP"` when this flag is set, allowing the operator interface to display appropriate alarms and block further operation attempts.

```c
// Query system state for GUI display
char status_buffer[256];
getSystemStatusForGUI(status_buffer, sizeof(status_buffer));
// Returns: "System Status: EMERGENCY_STOP" when flag is set

```

## Unit Test Verification

The PLFM-RADAR repository includes comprehensive unit tests validating emergency stop behavior under `9_Firmware/9_1_Microcontroller/tests/`:

- **[`test_gap3_overtemp_emergency_stop.c`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/test_gap3_overtemp_emergency_stop.c)** — Confirms over-temperature and watchdog errors trigger the complete shutdown path
- **[`test_gap3_emergency_stop_rails.c`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/test_gap3_emergency_stop_rails.c)** — Verifies correct GPIO sequencing for PA rail cut-off
- **[`test_gap3_emergency_state_ordering.c`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/test_gap3_emergency_state_ordering.c)** — Validates that `system_emergency_state` is set **before** `Emergency_Stop()` is called (GAP-3 FIX 5)

These tests ensure deterministic, repeatable protection behavior across firmware builds.

## Summary

- **Fault detection** uses the `SystemError_t` enum to classify PA-threatening conditions
- **`handleSystemError()`** routes critical faults to emergency stop while allowing recovery attempts for transient errors
- **`Emergency_Stop()`** executes a sequenced shutdown: DAC clear → mixer disable → rail cut-off → infinite IWDG-serviced hold
- The **state flag ordering** ensures external notification precedes the non-returning stop routine
- **Unit tests** verify correct implementation of all protection paths

## Frequently Asked Questions

### What triggers the emergency stop in PLFM-RADAR?

Critical faults in the `ERROR_RF_PA_OVERCURRENT` through `ERROR_WATCHDOG_TIMEOUT` range trigger the emergency stop procedure. These include PA over-current, bias faults, over-temperature conditions, power supply failures, and watchdog timeouts detected in [`main.cpp`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/main.cpp) lines 808-826.

### Why does the emergency stop enter an infinite loop instead of resetting?

The infinite loop with IWDG refresh prevents the MCU from resetting and potentially re-enabling PA power rails before fault conditions are cleared. This safe-hold state maintains all rails de-energized until manual intervention or power cycle occurs, eliminating the risk of automatic restart into a damaged or hazardous condition.

### How can I manually trigger an emergency stop for testing?

Call `Emergency_Stop()` directly from diagnostic code. This function never returns, placing the system into the same safe state as fault-triggered stops:

```c
extern void Emergency_Stop(void);

void run_manual_estop_test(void) {
    Emergency_Stop();  // Enters infinite loop, requires power cycle
}

```

### Where is the emergency stop sequence verified in the codebase?

Three unit test files validate the implementation: [`test_gap3_overtemp_emergency_stop.c`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/test_gap3_overtemp_emergency_stop.c) tests thermal and watchdog triggers; [`test_gap3_emergency_stop_rails.c`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/test_gap3_emergency_stop_rails.c) verifies GPIO rail sequencing; and [`test_gap3_emergency_state_ordering.c`](https://github.com/NawfalMotii79/PLFM_RADAR/blob/main/test_gap3_emergency_state_ordering.c) confirms state flag timing.