# [Clone and deploy the application with Topo](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/deploy-ml-model-to-npu-with-topo/deploy/)

## In this learning path

- [Introduction](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/deploy-ml-model-to-npu-with-topo/)
- [Understand the architecture of the machine learning application](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/deploy-ml-model-to-npu-with-topo/overview/)
- [Understand the toolchains used in the Topo Project](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/deploy-ml-model-to-npu-with-topo/what-are-the-toolchains/)
- [Build the Topo Project from scratch](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/deploy-ml-model-to-npu-with-topo/build-the-project/)
- [Clone and deploy the application with Topo](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/deploy-ml-model-to-npu-with-topo/deploy/)
- [Next Steps](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/deploy-ml-model-to-npu-with-topo/_next-steps/)

## Prepare the target
Before deploying the Topo Project, confirm that the FRDM i.MX 93 board is reachable from your host and that it’s ready for deployment:

```
topo health --target <user>@<target-ip>
```

Replace `<target-ip>` with the IP address or hostname of your board.

Resolve any errors before continuing.

The target section includes successful checks similar to:

```
__output__ Host
__output__ ----
__output__ Topo: ✅ (topo)
__output__ SSH: ✅ (ssh)
__output__ Curl: ✅ (curl)
__output__ Container Engine: ✅ (docker)
__output__ 
__output__ Target
__output__ ------
__output__ Destination: ssh://<target-ip>
__output__ Connectivity: ✅
__output__ Container Engine: ✅ (docker)
__output__ Remoteproc Runtime: ✅ (remoteproc-runtime)
__output__ Remoteproc Shim: ✅ (containerd-shim-remoteproc-v1)
__output__ Hardware Info: ✅ (lscpu)
__output__ Subsystem Driver (remoteproc): ✅ (imx-rproc)
```

> **Note**  
> If `remoteproc-runtime` is missing, install it with Topo:
> 
> ```
> topo install remoteproc-runtime --target <user>@<target-ip>
> ```
> 
> Run the health check again:
> 
> ```
> topo health --target <user>@<target-ip>
> ```

## Reserve memory in the device tree
The web application and Cortex-M33 firmware exchange data through reserved physical memory. The target device tree must reserve memory for the model/input buffer and for the Ethos-U65. This prevents Linux from allocating memory that the firmware and Ethos-U65 need to access by physical address.

You’ll now modify the device tree and reboot the target so that these modifications take effect.

> **Warning**  
> Back up the board’s original device tree before modifying it. The exact boot partition can differ between Linux images, so check the paths on your board before copying files.

On your host, create a working directory and dump the live device tree from the target:

```
mkdir -p devicetree
ssh <user>@<target-ip> 'cat /sys/firmware/fdt' > devicetree/live.dtb
dtc -I dtb -O dts -o devicetree/live.dts devicetree/live.dtb
```

Open `devicetree/live.dts` in a text editor of your choice. Then, under `remoteproc-cm33`, add the CM33 power domain if it’s not already present:

```
power-domains = <0x61>;
```

Under `reserved-memory`, add the model memory range:

```
model@c0000000 {
    reg = <0x00 0xc0000000 0x00 0x400000>;
    no-map;
};
```

Update the Ethos-U reserved-memory node so it’s reserved and not reusable:

```
ethosu_region@A8000000 {
    compatible = "shared-dma-pool";
    reg = <0x00 0xa8000000 0x00 0x8000000>;
    no-map;
    phandle = <0x60>;
};
```

Add `iomem=relaxed` to `chosen.bootargs`. For example:

```
bootargs = "clk-imx93.mcore_booted console=ttyLP0,115200 earlycon root=/dev/mmcblk1p2 rootwait rw iomem=relaxed";
```

Return to your host machine terminal and build the patched device tree:

```
dtc -I dts -O dtb -o devicetree/patched.dtb devicetree/live.dts
```

Copy it to the board:

```
scp devicetree/patched.dtb <user>@<target-ip>:/tmp/patched.dtb
```

Install it on the board. Adjust the boot partition path if your image uses a different location:

```
ssh <user>@<target-ip>
cp /run/media/boot-mmcblk1p1/imx93-11x11-frdm.dtb \
   /run/media/boot-mmcblk1p1/imx93-11x11-frdm.dtb.bak
cp /tmp/patched.dtb \
   /run/media/boot-mmcblk1p1/imx93-11x11-frdm.dtb
sync
reboot
```

After the board reboots, run the Topo health check again from the host and verify everything is still correct:

```
topo health --target <user>@<target-ip>
```

## Deploy to the board
You can choose to deploy from the original Topo Project, or from the project you built from scratch. If you haven’t already cloned the original project, clone it now:

```
topo clone https://github.com/Arm-Examples/topo-imx93-npu-deployment.git
```

Topo prompts for optional build cache image arguments. Accept the defaults unless you have your own cache images.

> **Note**  
> If you build without cache images, the first build can take a long time and requires about 25 GB of free disk space. The first build involves downloading and building ExecuTorch, the Arm GNU toolchain, MCUX SDK components, RPMsg-Lite, and the Cortex-M33 runner sources. Later builds are faster when Docker can reuse local cache layers or import the configured GHCR cache layers.

Then `cd` into the correct directory:

```
cd topo-imx93-npu-deployment
```

Or:

```
cd new-topo-npu-template
```

Deploy the project to your target:

```
topo deploy --target <user>@<target-ip>
```

During deployment, Topo builds the required images, transfers them to the target, starts the Cortex-M33 firmware through `remoteproc-runtime`, and starts the web application.

When deployment succeeds, the output includes a successful service startup. You can also check the deployed services:

```
topo ps --target <user>@<target-ip>
```

The output shows a process on both the Cortex-M33 and the Linux Host, and is similar to:

```
__output__ Image                                   Status          Processing Domain   Address
__output__ topo-imx93-npu-deployment-cm33-runner   Up 50 minutes   imx-rproc
__output__ topo-imx93-npu-deployment-webapp        Up 50 minutes   Linux Host          imx93-scorpio.cambridge.arm.com:3001, [::]:3001%
```

## Open the web application
Open the web application in a browser:

```
http://<target-ip>:3001
```

> **Note**  
> If you need to use a different target port, set `WEBAPP_PORT` when deploying. For example:

```
WEBAPP_PORT=3002 topo deploy --target <user>@<target-ip>
```

Then open:

```
http://<target-ip>:3002
```

The application shows:
- an image selector
- a **Classify** button
- board prerequisite checks
- classification results
- an expandable analysis section with runtime details

![Image classification web app showing correctly classified German Shepherd](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/deploy-ml-model-to-npu-with-topo/topo_npu_classifier.png)  
Image classification web app showing correctly classified German Shepherd

When you choose an image in the browser and select **Classify**, the web application:
1. Resizes and normalizes the image to classify into an input tensor compatible with the [MobileNetV2](https://arxiv.org/abs/1801.04381) model.
2. Writes the ExecuTorch `.pte` program and input tensor into reserved physical memory.
3. Sends a `RUN` command to the Cortex-M33 runner over `RPMsg`.
4. Waits for the Cortex-M33 firmware to run inference using Ethos-U65 acceleration.
5. Displays the top-1 and top-5 ImageNet classification results in the browser.

Try this out with an image from an ImageNet-supported class.

## What you’ve accomplished
You’ve prepared an FRDM i.MX 93 board for shared-memory NPU inference, deployed the `topo-imx93-npu-deployment` Topo Project with Topo, and started Cortex-M33 firmware through `remoteproc-runtime`. You used a browser-based application to stage the ExecuTorch `.pte` program and input tensor for MobileNetV2 classification with Ethos-U65 acceleration.

You can now use the deployed application as a reference for your own heterogeneous Arm applications, or adapt the model, firmware runner, web interface, or Topo metadata for another target.
