# Lin_AutoBaud_Dma_Demo

---

## Overview

This example demonstrates how to implement **LIN slave auto-baud synchronization** on the **YTM32B1LE1** platform based on **UART0 + LIN Driver + GPIO single-edge DMA trigger + pTMR timestamp sampling**.

The focus of this demo is not regular LIN TX/RX at a fixed baud rate. Instead, it shows how the slave synchronizes after receiving a master header:

1. Use the LIN peripheral to detect Break.
2. After Break OK, switch RX to GPIO and enter falling-edge DMA sampling **before Sync start falling arrives**.
3. Continuously capture the timestamps of `5` falling edges of `Sync = 0x55`, and use `4` two-bit intervals to estimate the current bus baud rate.
4. Complete GPIO mode switching and UART baud pre-configuration within the `1 bit` window from the **5th falling edge to Sync stop rising**.
5. Switch back to UART mux only when **Sync stop rising** arrives, then continue receiving PID and subsequent data.

Compared with `Lin_AutoBaud_Interrupt_Demo`, the main differences are:

- The `5` falling-edge timestamps of Sync are moved by DMA automatically instead of being captured one by one in a GPIO ISR.
- The falling-edge sampling path is significantly less sensitive to ISR entry latency on each edge.
- Real-time constraints are concentrated in two places:
  - The DMA completion callback must switch GPIO mode within the `1 bit` window from `bit7 falling` to `Sync stop rising`.
  - The final rising-edge GPIO ISR must restore the RX path and complete UART baud pre-configuration before the PID start bit arrives.

**Default configuration:**

- **Communication role**: LIN Slave
- **LIN instance**: UART0
- **Nominal baud rate**: `19200 bps`
- **Auto-baud mode**: `recalculate every header` by default, switchable to `lock after the first successful startup sync`
- **Target auto-baud range**: `+/-10.5%` relative to the nominal baud rate
- **Receive PID**: `0x3C`
- **Transmit PID**: `0x3D`
- **Transmit data**: `55 AA 69 96 96 69 AA 55`

**Features:**

- **DMA timestamp sampling**: GPIO RX falling edges trigger DMA directly, which moves `pTMR0 CH0->TCV` into a memory array.
- **5-point sampling with 4 two-bit intervals**: captures the falling timestamps of `Sync start / bit1 / bit3 / bit5 / bit7`.
- **Fast UART reconfiguration**: searches the best `OSR/SBR` using the OSR candidate list `{16, 8, 32, 12, 24, 20, 4}`.
- **0.5% search precision target**: improves UART divider search quality and does not mean the acceptable bus baud range.
- **Switch back to UART only at stop rising**: the DMA callback performs only pre-configuration; the final RX handoff occurs only at `Sync stop rising`.
- **Selectable auto-baud policy**: supports `recalculate every header` or `lock after the first complete successful frame`.
- **Single-file portability**: the core logic is concentrated in the `USER CODE` region of `app/main.c`.
- **Debug-friendly**: test point macros are reserved for oscilloscope or logic analyzer observation of critical timing windows.

---

## Hardware Requirements

- **Evaluation board**: YTM32B1LE15-EVB-Q48
- **Debugger**: J-LINK v9.2 or later
- **External device**: a master node that can send LIN headers, a USB-LIN adapter, or another board running a LIN master demo

---

## Hardware Connections

This example uses the onboard LIN PHY by default. UART0 is connected to the LIN transceiver on the board. During testing, connect the board to an external LIN bus and make sure the onboard LIN PHY is powered correctly.

### 1. MCU to onboard LIN PHY mapping

| MCU Pin | Board Signal | Description |
| ------ | ------------ | ----------- |
| PTA3 | LIN_UART0_TX | UART0 TX, used as the LIN transmit path |
| PTA2 | LIN_UART0_RX | UART0 RX, also used as the GPIO/DMA sampling input during auto-baud |
| PTD2 | LIN_SLEEP_EN | LIN PHY enable/sleep control, default high output |

### 2. Recommended external test connections

- Connect the board LIN interface to an external **LIN master node**.
- The external master and the board must share **common ground**.
- Provide **12V VBAT** for the onboard LIN PHY.
- The master should be able to send a standard LIN header containing **Break + Sync + PID**.

### 3. Recommended debug setups

- **Method A**: use this demo as the slave and run `Lin_Master_Demo` on another EVB as the master
- **Method B**: use a USB-LIN adapter, CANoe, or a bus analyzer to send headers at different baud rates and observe whether the slave synchronizes correctly

---

## Software Requirements

- **SDK**: YTM32B1LE1_1_4_0 or later
- **GCC**: GNU GCC v10.3 or later
- **Keil/MDK**: ARM Keil/MDK v5.36 or later
- **IAR**: IAR v8.40 or later
- **VS Code**: Microsoft Visual Studio Code IDE v1.76 or later (GNU GCC toolchain, CMake v3.25, ninja, and Cortex-Debug extension required)
- **J-LINK**: SEGGER J-LINK v6.96 or later, with YTM32B1LE1 device support installed
- **Ozone**: SEGGER Ozone v3.28 or later

---

## LIN Auto-Baud Demo Design

### 1. Overall flow

```text
+--------------------------+      +--------------------------+      +--------------------------+
| 1. LIN slave waits for   | ---> | 2. LIN driver detects    | ---> | 3. RX switches to GPIO   |
|    the header at the     |      |    Break                 |      |    and enables falling-  |
|    nominal baud rate     |      |                          |      |    edge DMA              |
+--------------------------+      +--------------------------+      +------------+-------------+
                                                                                 |
                                                                                 v
+--------------------------+      +--------------------------+      +------------+-------------+
| 6. DMA callback checks   | <--- | 5. DMA captures 5 Sync  | <--- | 4. pTMR timestamps are   |
|    4 two-bit intervals   |      |    falling timestamps   |      |    transferred to memory |
|    and pre-configures    |      |                          |      |    by DMA automatically  |
|    the UART baud rate    |      |                          |      |                          |
+------------+-------------+      +--------------------------+      +--------------------------+
             |
             v
+------------+-------------+      +--------------------------+      +--------------------------+
| 7. GPIO switches to wait | ---> | 8. Sync stop rising      | ---> | 9. RX switches back to   |
|    for a single rising   |      |    arrives               |      |    UART and continues    |
|    edge interrupt        |      |                          |      |    receiving PID/data    |
+--------------------------+      +--------------------------+      +--------------------------+
```

Flow description:

1. After power-up, the slave enters LIN receive mode at the nominal baud rate to wait for the master header and detect Break.
2. Once auto-baud is confirmed, software immediately takes over the RX pin and switches the synchronization measurement path from UART sampling to GPIO falling-edge DMA sampling.
3. `pTMR` provides high-resolution timestamps. Each falling-edge DMA request moves the current `TCV` value into `s_dmaTimerValue[]`.
4. A total of `5` falling-edge timestamps are captured, corresponding to `Sync start / bit1 / bit3 / bit5 / bit7`.
5. After DMA completes, the callback changes GPIO to rising-edge mode, averages the `4` two-bit intervals, and estimates the current bus baud rate.
6. UART baud registers are only pre-configured in the DMA callback. The RX pin mux is **not switched back immediately**.
7. GPIO is then configured to wait only for the next rising edge, which must be `Sync stop rising`.
8. Only inside this rising-edge ISR does the software restore UART RX mux, publish `LIN_SYNC_OK`, and continue PID reception.

### 2. Why the DMA version is more robust than the interrupt-sampling version

In the interrupt-sampling version, the current `pTMR` counter is read after entering the GPIO ISR on each edge, so each sample is affected by GPIO ISR latency jitter. The DMA version is different:

- When a GPIO falling edge arrives, a hardware DMA request transfers `pTMR->TCV` directly into RAM.
- There is no need to enter an ISR and read the counter in software for every falling edge.
- Therefore, the falling-edge timestamp path is less sensitive to ISR entry jitter on every edge.

This does not mean the DMA version has no real-time requirements. Two critical windows still exist:

1. **DMA completion callback window**
   - Only about `1 bit` time exists from the `5th` falling edge to `Sync stop rising`.
   - GPIO must be switched to rising-edge mode in this window. Sample processing, target baud calculation, and `OSR/SBR` search may be deferred as long as they finish before PID start-bit sampling.
2. **Final rising-edge ISR window**
   - UART RX must be restored before PID start-bit sampling.
   - If the rising-edge ISR is blocked for too long, PID reception becomes unstable.

The customer system should still avoid:

- Long global interrupt disable periods
- Long critical sections
- High-priority ISRs that occupy the CPU for too long
- System load that delays DMA IRQ or GPIO IRQ handling

### 3. Time measurement and common clock source requirement

This demo uses `pTMR` to measure Sync edge intervals, then reconfigures `UART` according to the measured result. Therefore:

- **The pTMR functional clock and UART functional clock should use the same source**
- More precisely, both should come from **the same root clock** or from the same root clock through a **fixed divider chain**
- If the two clock sources differ, or one comes from a high-accuracy source while the other comes from a drifting independent source, systematic measurement error will be introduced

Example of a wrong setup:

- `pTMR` measures the target bit time using clock source A
- `UART` calculates `OSR/SBR` using clock source B
- If A and B have frequency offset, the actual UART baud rate will deviate from the measured target

### 4. DMA sampling must start before Sync start falling after Break detection

This demo no longer requires "the first observed edge must be the Break rising edge", but it still requires:

- After the LIN driver has recognized the Break condition (default `11 bit`)
- Software must complete the RX pin switch from UART to GPIO and enable GPIO falling-edge DMA requests **before Sync start falling arrives**

This is required because:

- The first DMA sample must be **Sync start falling**
- Only then do the following `5` falling edges and `4` two-bit intervals match the algorithm assumptions
- If the switch is too late, the first recorded falling edge may already be `bit1 / bit3 / bit5 / bit7`, causing sample misalignment and baud calculation failure

Timing example:

```text
LIN bus:    |_____________________|‾|_|‾|_|‾|_|‾|_|‾|_|‾|....
                Break      ^     ^  ^<--- Sync = 0x55 --->
                           |     |  |
Stage                      |     |  Sync start falling
                           |     GPIO already switched to falling-edge DMA
                           Break detection completed
Requirement: the first valid DMA falling edge must be Sync start falling
```

### 5. Sync falling-edge sampling and baud estimation

The LIN Sync field is always `0x55`. Its regular edge pattern is well suited to estimating bit width from a falling-edge sequence.

In this demo:

- A total of `5` falling edges are used
- The `1st` falling edge is `Sync start falling` and is used only as the reference timestamp
- The `2nd` to `5th` falling edges form `4` two-bit interval samples
- The `4` two-bit intervals are averaged, then divided by `2` to obtain `s_averageBitTimeLength`
- The current bus baud rate is estimated as:

```text
BaudRate = pTMR_Clock / AverageBitTime
```

Edge mapping:

| Falling Edge Index | Position | Purpose |
| ------------------ | -------- | ------- |
| 1st | `Sync start falling` | Establish reference timestamp |
| 2nd | `bit1 falling` | Record the 1st two-bit interval |
| 3rd | `bit3 falling` | Record the 2nd two-bit interval |
| 4th | `bit5 falling` | Record the 3rd two-bit interval |
| 5th | `bit7 falling` | Record the 4th two-bit interval and immediately complete baud calculation and UART pre-configuration |
| next rising edge | `Sync stop rising` | Switch back to UART and enter PID reception |

### 6. Baud acceptance policy

The DMA version uses the same published rule as the interrupt version and accepts baud rates according to the nominal baud window:

- `LIN_SYNC_NOMINAL_BAUD = 19200`
- `LIN_SYNC_BAUD_TOLERANCE_PERMILLE = 105`

That means the default acceptance range is:

```text
LIN_SYNC_NOMINAL_BAUD +/- 10.5%
```

Meaning:

- First calculate the measured baud rate from the `4` two-bit intervals
- Then check whether the measured value falls within the `+/-10.5%` window relative to the nominal baud rate
- If it is outside that window, auto-baud for the current frame fails, the current header is discarded, and the slave waits for the next frame

### 7. UART baud reconfiguration policy and the meaning of 0.5%

After calculating the target baud rate, the demo does not linearly scan all OSR values. It first tries a set of candidates with better sampling quality:

```c
{16, 8, 32, 12, 24, 20, 4}
```

Policy characteristics:

- Prefer commonly used OSR values with better sampling quality
- Derive `SBR` each time from `UART source clock / (OSR * Baud)`
- Compare the back-calculated baud rate with the target baud rate
- Exit the search early once the error is below `0.5%`
- Disable global interrupts only briefly when actually writing UART registers, keeping the critical section short

The meaning of `0.5%` should be clarified:

- `+/-10.5%` is the target auto-baud acceptance range
- `0.5%` is the search precision target after baud reconfiguration
- In other words, when the master's actual baud rate falls within `+/-10.5%`, the software tries to find a UART reconfiguration result with no more than `0.5%` error to improve stable reception

When `OSR < 8`, the code automatically enables UART Both Edge Sampling to improve sampling robustness at low OSR.

### 8. Stop handoff behavior

Like the interrupt version, the final `Sync stop rising` handoff in this demo performs only the minimum required actions:

- Disable GPIO edge capture
- Switch the RX pin mux back to UART
- Update the state to `LIN_SYNC_OK`
- Move the LIN node to `RECV_PID`
- Continue receiving the subsequent PID field

Important clarification:

- The DMA callback only performs **baud calculation and UART pre-configuration**
- It **does not switch back the RX pin mux immediately**
- The stop-rising ISR performs only the **final path handoff**
- Additional UART cleanup is not part of the externally defined stop-handoff behavior

### 9. Lock timing

When `LIN_SYNC_AUTOBAUD_MODE` is configured as `LIN_SYNC_MODE_STARTUP_RETRY_UNTIL_SUCCESS`, the lock timing is the same as in the interrupt version:

- It does not lock immediately after `SYNC stop`
- It locks only after a **complete frame finishes successfully**
- Specifically, the first successful synchronization is considered complete only after `LIN_RX_COMPLETED` or `LIN_TX_COMPLETED`

This ensures that "lock after first success" means a complete usable frame, not only header synchronization.

### 10. Timeout and error recovery

The demo uses `lpTMR0` as a common time base for the LIN protocol stack to manage timeouts in both the Header and Response phases.

The following abnormal cases cause the demo to re-arm for the next header:

- Sync error
- PID error
- Frame error
- Readback error
- Checksum error
- RX overrun
- Header or Response timeout

Recovery is handled uniformly by `LinSync_RearmForNextHeader()`, including:

- Clearing local auto-baud state variables
- Disabling GPIO edge capture
- Returning the LIN node to Idle when necessary
- Preparing the DMA sampling context again for the next frame

---

## How to Use the Demo

### 1. Default communication behavior

The demo runs as a LIN slave and performs the following actions for different PIDs:

| PID | Behavior | Description |
| --- | -------- | ----------- |
| `0x3C` | Receive data | The slave calls `LIN_DRV_ReceiveFrameData()` to receive 8 bytes into `s_linRxBuff[]` |
| `0x3D` | Send data | The slave calls `LIN_DRV_SendFrameData()` to transmit a fixed 8-byte response |

The default transmitted data is:

```text
55 AA 69 96 96 69 AA 55
```

### 2. Key configuration items

The items below are grouped by impact on customer integration. Focus on the first group during porting. The second group usually should stay at its default values.

#### Configuration items that must be checked by customers

| Configuration Item | Default Value | Description |
| ------------------ | ------------- | ----------- |
| `LIN_SYNC_UART_INSTANCE` / `LIN_SYNC_UART_BASE` | `0 / UART0` | Bound LIN/UART instance; must match the actual hardware connection |
| `LIN_SYNC_UART_CLOCK_NAME` | `UART0_CLK` | UART functional clock name, used as the basis for baud reconfiguration |
| `LIN_SYNC_RX_GPIO` / `LIN_SYNC_RX_PIN` | `GPIOA / 2` | RX sampling port and pin used during auto-baud |
| `LIN_SYNC_RX_MUX` | `PCTRL_MUX_ALT6` | Mux function used when switching RX back from GPIO to UART |
| `LIN_SYNC_NOMINAL_BAUD` | `19200` | Nominal baud rate, used as the basis for the auto-baud range and timeout design |
| `LIN_SYNC_AUTOBAUD_MODE` | `LIN_SYNC_MODE_EVERY_HEADER_RECAL` | `LIN_SYNC_MODE_EVERY_HEADER_RECAL` means recalculation for every frame; `LIN_SYNC_MODE_STARTUP_RETRY_UNTIL_SUCCESS` means lock after the first complete successful frame |
| `LIN_SYNC_LPTMR_INSTANCE` / `LIN_SYNC_LPTMR_PERIOD_US` / `LIN_SYNC_LPTMR_TICKS_PER_US` | `0 / 520 / 48` | Time base for timeout service, usually adjusted together with the board clock configuration |
| `LIN_SYNC_TIMEOUT_HEADER_TICKS` / `LIN_SYNC_TIMEOUT_RESPONSE_TICKS` | `5 / 15` | LIN timeout thresholds; keep the defaults unless the protocol timing changes as a whole |

#### Implementation parameters that are usually not recommended to change

| Configuration Item | Default Value | Description |
| ------------------ | ------------- | ----------- |
| `LIN_SYNC_BAUD_TOLERANCE_PERMILLE` | `105` | Recommended to interpret this as `+/-10.5%` relative to the nominal baud rate |
| `LIN_SYNC_PTMR_INSTANCE` / `LIN_SYNC_PTMR_CLOCK_NAME` | `0 / pTMR0_CLK` | Sync timestamp resource and clock; should share the same source or fixed divider chain as UART |
| `LIN_SYNC_FALLING_EDGE_COUNT` | `5` | Total number of Sync falling edges; tightly coupled to the current sampling algorithm |
| `LIN_SYNC_TWOBIT_SAMPLE_COUNT` | `4` | Number of valid two-bit interval samples; tightly coupled to the current averaging algorithm |

### 3. Run steps

1. Open the project in YCT and confirm that the resource configuration of `UART0`, `GPIOA/PTA2`, `DMA`, `pTMR0`, and `lpTMR0` matches the hardware.
2. Confirm that the `pTMR` and `UART` functional clocks share the same source or fixed divider chain.
3. Download the program to `YTM32B1LE15-EVB-Q48`.
4. Connect an external LIN master and provide `12V VBAT` for the onboard LIN PHY.
5. Let the master send LIN headers at different baud rates, preferably covering values near the nominal baud and the `+/-10.5%` range boundaries.
6. When the master sends `PID=0x3C`, send 8 bytes of data to the slave.
7. When the master sends `PID=0x3D`, read the fixed 8-byte response from the slave.

### 4. Expected results

- After Break, the slave should enter the GPIO falling-edge DMA sampling stage and capture a sequence of `5` falling edges starting from `Sync start falling`.
- After the `5th` falling edge, UART baud pre-configuration should complete before `Sync stop rising`, and the RX path should switch back to UART at stop rising.
- When the master sends `PID=0x3C`, received data should be visible in `s_linRxBuff[]`.
- When the master sends `PID=0x3D`, the master should receive the fixed response data.
- In `LIN_SYNC_MODE_STARTUP_RETRY_UNTIL_SUCCESS` mode, lock should occur only after `LIN_RX_COMPLETED` or `LIN_TX_COMPLETED`.
- If the master baud rate is out of range, the header is incomplete, or a critical timing window is missed and causes timeout, the demo should abandon the current frame and wait for the next one automatically.

This example does not include built-in serial print output. It is recommended to verify behavior in these ways:

- Observe `s_currentBaudRate`, `s_averageBitTimeLength`, and `s_linRxBuff[]` in the debugger
- Use a logic analyzer or LIN analyzer to observe Break, Sync, PID, and the switching window
- Cross-check TX/RX results with logs from the master side

---

## Interrupt Priority and Real-Time Constraints

### 1. Recommended default interrupt priorities

The auto-baud process in this demo is sensitive to interrupt response time. The recommended priority assignment is:

| Interrupt | Recommended Priority | Description |
| --------- | -------------------- | ----------- |
| `DMA0_IRQn` | `0` | DMA callback after Sync falling-edge timestamp capture; highest priority for the critical window |
| `GPIOA_IRQn` | `0` | Final switch back to UART at `Sync stop rising`; highest priority for the critical window |
| `UART0_IRQn` | `1` | LIN event handling |
| `lpTMR0_IRQn` | `1` | LIN timeout service |

Design intent:

- The DMA callback and stop-rising ISR must not be delayed by lower-priority work
- UART pre-configuration must complete before stop rising arrives
- The stop-rising ISR must restore the UART path before the PID start bit arrives
- LPTMR serves timeouts, but should not preempt the critical sampling window

### 2. Three core real-time constraints

#### Constraint A: DMA sampling must start before Sync start falling after Break detection

```text
T_break_detect_to_gpio_dma_enable < T_break_ok_to_sync_start_falling
```

Meaning:

- The time from Break detection becoming valid to GPIO falling-edge DMA actually being enabled
- Must be shorter than the remaining time until `Sync start falling`
- Otherwise the first valid DMA sample will not be `Sync start falling`

#### Constraint B: GPIO interrupt mode switching must complete within the 1-bit window from the 5th falling edge to Sync stop rising

```text
T_gpio_switch_to_rising < T_bit_time
```

Meaning:

- Starting from the completion of the `5th` falling-edge sample
- Before `Sync stop rising` arrives
- Software must complete the GPIO edge-mode switch

#### Constraint C: UART path restoration must complete between Sync stop rising and PID arrival

```text
T_stop_rising_isr + T_mux_switch_back < T_stop_to_pid
```

Meaning:

- Inside the single `Sync stop rising` GPIO ISR
- Software must disable GPIO capture, restore UART RX mux, publish `LIN_SYNC_OK`, and advance to `RECV_PID`
- This ensures the UART does not miss the PID start bit

### 3. Real-time window illustration

```text
+----------------------+     +----------------------+     +----------------------+     +----------------------+
| 1. Break detected    | --> | 2. GPIO falling DMA  | --> | 3. Sync start        | --> | 4. 5th falling edge  |
|                      |     |    enabled           |     |    falling arrives   |     |    sampled           |
+----------------------+     +----------------------+     +----------------------+     +----------+-----------+
                                                                                                  |
                                                                                                  v
                             +----------------------+     +----------------------+     +----------------------+
                             | 7. Sync stop rising  | <-- | 6. Calculate +       | <-- | 5. Switch to         |
                             |    arrives           |     |    search + UART     |     |    rising-edge mode  |
                             |                      |     |    pre-config         |     |                      |
                             +----------+-----------+     +----------------------+     +----------------------+
                                        |
                                        v
                             +----------------------+     +----------------------+
                             | 8. Mux switches back | --> | 9. PID start bit     |
                             |    to UART +         |     |    arrives           |
                             |    publish SYNC_OK   |     |                      |
                             +----------------------+     +----------------------+
```

Critical windows:

- `1 -> 2`: must finish before `Sync start falling` arrives
- `4 -> 5`: must fit within the `1 bit` pre-configuration window
- `7 -> 8`: must fit between `Sync stop rising` and PID arrival

If any of these timing windows fail, the symptoms on a customer system are typically:

- Constraint A fails: the current header cannot enter synchronization correctly, causing occasional desynchronization or full-frame loss
- Constraint B fails: falling edges are captured, but UART pre-configuration is not completed before stop rising, causing PID loss or header parsing failure
- Constraint C fails: the switch back to UART is too late, causing PID first-bit loss, subsequent frame errors, or occasional timeouts

---

## Porting and Debug Recommendations

### 1. Verify resource mapping first

First confirm that these settings match the YCT-generated configuration:

- UART0 RX/TX pin mux
- RX GPIO port and pin number
- GPIO falling-edge DMA request source
- DMA channel number and interrupt number
- pTMR channel number
- LPTMR period configuration

### 2. Key observation points

It is recommended to use test points or a logic analyzer to observe:

- The time when Break detection completes
- The time when GPIO/DMA falling-edge sampling starts
- The DMA completion callback execution window
- The GPIO rising-edge ISR execution window
- The time when UART RX is restored

### 3. Common failure causes

- GPIO/DMA switching happens too late after Break, so the first sample is not `Sync start falling`
- DMA request routing is incorrect, so `s_dmaTimerValue[]` never fills all `5` samples
- `pTMR` and `UART` do not share the same clock source, causing mismatch between measurement and UART reconfiguration
- The DMA callback takes too long and cannot complete pre-configuration before `Sync stop rising`
- The final rising-edge ISR is blocked by a higher-priority task, causing PID reception failure
- The master baud rate is outside the `+/-10.5%` acceptance window relative to `LIN_SYNC_NOMINAL_BAUD`

### 4. File description

- `app/main.c`
  - Contains the core logic of the DMA-based LIN auto-baud implementation
  - Auto-baud related code is concentrated in the `USER CODE` regions for easier porting
- `Lin_AutoBaud_Dma_Demo.yct`
  - YCT project configuration file, including clocks, pins, DMA, LIN, and timer resources
- `ReadMe_zh.md`
  - Current Chinese release note
  - Future unified release wording takes precedence and does not necessarily match the exact current code snapshot
- `ReadMe_en.md`
  - English version of this document

### 5. Porting suggestion

If this demo needs to be migrated into a customer project, the recommended order is:

1. Port and verify the low-level resource mapping first: UART / GPIO / DMA / pTMR / LPTMR
2. Verify the basic Break -> Sync -> PID receive flow
3. Verify that DMA can stably capture `5` falling-edge timestamps
4. Verify baud acceptance policy, UART pre-configuration, and stop-rising handoff stability
5. Finally evaluate interrupt priorities, critical-section length, and real-time margin under the customer system load

---

## Summary

`Lin_AutoBaud_Dma_Demo` demonstrates a LIN slave auto-baud implementation that is closer to production use:

- Use **UART** to detect Break
- Use **GPIO + DMA + pTMR** to capture Sync timestamps
- Use the **DMA callback** to estimate baud rate and pre-configure the UART
- Use a **single rising-edge GPIO ISR** to complete the final RX path handoff

Compared with pure GPIO interrupt-based sampling, this project significantly reduces the sensitivity of falling-edge samples to ISR latency jitter. At the same time, it keeps the same externally published baud acceptance policy, OSR search method, macro naming, and lock semantics as the interrupt demo, making it easier for customers to understand, port, and compare both implementation approaches.
