> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

#  Sample applications

Use these sample applications to move from a working MCU setup to practical interface, event, and power-management flows. You can validate one capability at a time, confirm expected behavior, and reuse the patterns as starting points for your own application logic. This approach helps you reduce bring-up risk, isolate issues early, and build confidence before adding more complex features.

**3.1 Run a UART logging application**

Bring up a low-risk console or service path so you can verify image execution, interrupt delivery, and basic driver initialization before you move to more complex flows.

**Prerequisites**

■ UART path or loopback setup.

■ Logging and serial support enabled in project configuration.

■ Interrupt routing validated for the selected serial engine

**Procedure**

1. Enable the serial path and logging backend.
2. Initialize the required serial engine and confirm the driver binds correctly.
3. Start the MCU image and register the UART callback or service routine.
4. Send a small known string or wait for one expected boot message.
5. If the path is interrupt-driven, verify receive-ready or transmit-done behavior.

**Expected result.**

You see stable console output or loopback activity and the basic event-driven UART path stays stable.

**Related test source**

You can use the test source at core/buses/v2/uart/test/uart\_zephyr\_test.c as a starting point.

**Code example**

```text theme={null}
static void uart_user_cb(const struct device *dev,
 struct uart_event *evt,
 void *user_data)
{
 switch (evt->type) {
 case UART_RX_RDY:
 /* Consume bytes or wake a worker. */
 break;
 case UART_TX_DONE:
 case UART_RX_DISABLED:
 case UART_RX_BUF_REQUEST:
 default:
 break;
 }
}
```

**3.2 Run an Inter-Integrated Circuit sensor read application**

Verify a real peripheral path by reading one or more bytes from a known sensor register over I2C.

**Prerequisites**

■ I2C device with a stable address and one safe register to read.

■ The I2C subsystem enabled.

■ Clock and power dependencies for the selected QUP serial engine available through the platform API.

**Procedure**

1. Confirm the sensor address, target register, and bus instance.
2. Initialize the I2C instance and verify the driver binds correctly.
3. Assert the platform votes or dependencies needed for the QUP path.
4. Perform a register read with the native I2C write-read flow and capture the returned bytes.
5. Drop temporary votes or dependencies after the transfer and repeat the read.

**Expected result**

The sensor register read completes without a timeout or bus error and the response is stable across repeated reads.

**Related test source**

You can use the test source at core/buses/v2/i2c/test/i2c\_zephyr\_test.c as a starting point.

**Code example**

```text theme={null}
int sensor_reg_read(const struct i2c_dt_spec *bus,
 uint8_t reg,
 uint8_t *buf,
 size_t len)
{
 int ret;
 vote_clock(CLK_QUPx, ON);
 vote_vdd_cx(ON);
 ret = i2c_write_read_dt(bus, &reg, 1, buf, len);
 drop_vote(CLK_QUPx);
 drop_vote(VDD_CX);
 return ret;
}
```

**3.3 Run a GPIO interrupt and wake application**

Validate discrete event handling from an external line through interrupt registration, ISR handoff, and wake processing.

**Prerequisites**

■ A routed GPIO line that can generate a controlled edge or level event.

■ Interrupt routing confirmed for the external line.

■ A worker or callback ready to receive the event after ISR entry.

**Procedure**

1. Configure direction, pull, polarity, and edge or level behavior for the target line.
2. Register the interrupt handler and map the GPIO event to the MCU interrupt path.
3. If the event is also a wake source, classify it correctly before entering the wait path.
4. Trigger the external event and observe ISR entry and handoff.
5. Repeat the event in both active mode and a valid wait or low-power entry path.

**Expected result**

The MCU services the event reliably and the same GPIO line can be validated as a wake-capable source when the platform allows it.

**3.4 Run a low-power mode and wake-up application**

Validate low-power entry, wake-source handling, and resume behavior so you can confirm the MCU retains or restores the state you expect.

**Prerequisites**

■ At least one known functional protocol path such as UART or I2C.

■ A valid wake source such as QTIMER, GPIO, UART receive activity, or a sensor interrupt.

■ Logs, trace, or debug state capture available

**Procedure**

1. Start from a known-good protocol or application path.
2. Set up one valid wake source and confirm the system recognizes it.
3. Force the idle or workload condition required by the platform policy for the target power state.
4. Enter the target low-power condition and capture evidence that the expected state was
   reached.
5. Trigger the wake event and confirm that wake occurs and the active path recovers

**Expected result.**

The MCU enters the intended low-power condition, wakes on the selected source, restores the expected execution path, and keeps interface behavior stable after resume.

**3.5 Run an always-on monitoring application**

Turn the event-driven MCU model into a practical monitoring loop that waits for timer or sensor events, qualifies them locally, and only escalates to the host when policy requires it.

**Prerequisites**

■ A stable timer or sensor event source.

■ One logging path.

■ A clear policy for when the application should ignore, log, act on, or escalate an event

**Procedure**

1. Create a small event-driven loop that waits on a timer, interrupt, or another platform signal.
2. Capture the minimum data needed when the event arrives.
3. Apply local decision logic or thresholds.
4. If the event is actionable, perform the local work or escalate a concise signal to the host.
5. Return to the wait path and confirm repeatable long-run behavior

**Expected result**

The MCU stays responsive in an event-driven loop, keeps background work local, and limits host wake activity to only the cases that meet policy.

**3.6 Run a high-throughput data transfer through QUP and GPI**

Validate the optional transfer path that uses QUP as the protocol controller and GPI as the descriptor or ring-based data movement engine for bursty or higher-throughput traffic.

**Prerequisites**

■ A proven basic protocol path for the same serial engine before you introduce GPI.

■ Allocated ring or descriptor resources and their ownership model defined in software.

■ Completion, timeout, and error interrupts routed to the MCU.

**Procedure**

1. Initialize the QUP serial engine for the target protocol and mode.
2. Initialize the GPI channels and configure ring or descriptor resources before traffic starts.
3. Program completion, threshold, timeout, and error interrupts.
4. Queue a representative transfer and monitor descriptor ownership, completion, and status
   changes.
5. On completion, verify payload correctness and clean ring behavior.

**Expected result**

The MCU completes the transfer with lower core involvement, and the ring or descriptor state stays consistent after normal completion and controlled error tests.

**Code example**

```text theme={null}
int mcu_bus_stack_init(struct qup_ctx *ctx)
{
 vote_clock(ctx->clk_id, ON);
 vote_vdd_cx(ON);
 qup_reset(ctx->se_id);
 gpi_channel_init(ctx->tx_chan);
 gpi_channel_init(ctx->rx_chan);
 gpi_ring_config(ctx->tx_chan, ctx->tx_ring_base, ctx->tx_ring_size);
 gpi_ring_config(ctx->rx_chan, ctx->rx_ring_base, ctx->rx_ring_size);
 qup_enable_irqs(ctx->se_id,
 IRQ_XFER_DONE | IRQ_ERROR | IRQ_TIMEOUT);
 return 0;
}
```
