Changes between Version 28 and Version 29 of expansion/gw16168


Ignore:
Timestamp:
08/25/2026 07:01:13 PM (7 hours ago)
Author:
Tim Harvey
Comment:

reorder info

Legend:

Unmodified
Added
Removed
Modified
  • expansion/gw16168

    v28 v29  
    8686- [https://huggingface.co/nxp/Qwen2.5-VL-7B-Instruct-Ara240 nxp/Qwen2.5-VL-7B-Instruct-Ara240] ~12.3GB - multimodal vision-language model
    8787- [https://huggingface.co/nxp/YOLOv8 nxp/YOLOv8] ~712MB object detection, segmentation, pose 
    88 
    89 = NXP Ara240 DNPU AI Accelerator Quick Start
    90 
    91 [=#ara2-runtime]
    92 == Ara Runtime
    93 NXP has a runtime library for the Ara240 which consists of some statically built libraries as well as a dynamic linked GStreamer plugin.
    94 
    95 The Ara runtime includes a couple of Python Wheels. A Python Wheel is a standard built-package format for distributing Python libraries. It is essentially a ZIP-format archive with a .whl extension that contains all the files needed for a package to run immediately after being. It's fairly standard when using Python to run into package version incompatibilities which is why user based Python virtual environments are used.
    96 
    97 The Ara runtime provides a complete runtime environment for AI/ML acceleration using the Ara240 NPU on for aarch64. This package includes:
    98  * Runtime libraries for Ara240 NPU integration
    99  * Python bindings (DVAPI) for custom inference applications
    100  * Optimum-Ara framework for LLMs and VLMs
    101  * GStreamer plugin for Real-Time Detection Object Applications
    102  * Helper scripts for monitoring, benchmarking, and model management
    103  * Systemd service for automatic hardware initialization
    104 
    105 Installation on a Gateworks board with Ubuntu based OS:
    106  - Download and extract the self-extracting binary from NXP:
    107 {{{#!bash
    108 VER=imx-nxp-ara2-2.1.1-063d56c
    109 wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/$VER.bin
    110 sh $VER.bin
    111 }}}
    112  - take care of postinst steps
    113   - miscellaneous
    114 {{{#!bash
    115 # create dirs (used for models)
    116 mkdir -pv /usr/share/{cnn,llm}
    117 }}}
    118   - configure swap (necessary if using VLM)
    119 {{{#!bash
    120 /usr/bin/enable_swap 2
    121 }}}
    122   - install uv package manager for Python virtualization and packaging for local user (which is installed to ~/.local/bin so we create symlinks to /usr/bin)
    123 {{{#!bash
    124 apt update && apt install -y curl
    125 curl -LsSf https://astral.sh/uv/install.sh | sh
    126 ln -s /root/.local/bin/uv /usr/bin/uv
    127 ln -s /root/.local/bin/uvx /usr/bin/uvx
    128 }}}
    129   - build driver
    130 {{{#!bash
    131 apt update && apt install -y build-essential git bc file flex bison
    132 git clone https://github.com/nxp-imx-support/uiodma-driver
    133 ( cd uiodma-driver/uiodma; make )
    134 # install it where the rt service expects to find it (over the top of the non-compatible one)
    135 cp uiodma-driver/uiodma/uiodma.ko /usr/share/rt-sdk-ara240/driver/
    136 }}}
    137   - enable service:
    138 {{{#!bash
    139 # enable service
    140 systemctl enable rt-sdk-ara2.service
    141 # start service now (unless you reboot)
    142 systemctl start rt-sdk-ara2.service
    143 }}}
    144   - use 'fetch_models' to pre-compiled models for testing via the fetch_models script which will fetch models from !HuggingFace.
    145 {{{#!bash
    146 # list models available for nxp/ara
    147 fetch_models --list
    148 # install YOLOv8
    149 fetch_models --repo-id nxp/YOLOv8 # 746MB (711MiB)
    150 }}}
    151    - the script is a python wrapper that uses uvx and the fetch-models python wheel (/usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl) to fetch and install models from !HuggingFace HUB
    152    - the models will be installed in either /usr/share/cnn (Convolutional Neural Network) and /usr/share/llm (Large Language Model)
    153    - NXP has Ara2 optimized models at https://huggingface.co/nxp
    154    - the script has a hard coded list of models available and where to install them locally. You can use 'python -m zipfile -e /usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl ./fetch_models' to see what it's doing
    155 
    156 Notable Files:
    157  - /usr/lib/
    158   - libaraclient_aarch64.so - base library for interfacing with ara2
    159   - libara_vision_inference.so - inference lib that builds on libaraclient
    160  - /usr/lib/gstreamer-1.0
    161   - libgstdvInf.so - GStreamer plugin
    162  - /usr/share/rt-sdk-ara240 (symlink to a version independent dir at same location)
    163   - hw_utils/boot_img - firmware files
    164   - hw_utils/ddr_config - ddr binaries
    165   - hw_utils/bins/ - the hw utils for bringup/programming
    166   - optimum-ara/ - extension of the Hugging Face library that integrates with Ara240 DNPU
    167   - scripts - various wrappers around the tools etc
    168   - nnapp - tool for benchmarking models
    169   - config - various example yaml config files used for proxy/nnapp
    170   - include/dvapi.py - python bindings to dvapi
    171   - driver/uiodma.ko - driver (where the setup script expects to find it)
    172  - /usr/share/python-wheels - python wheels for fetch_models and optimum_ara
    173  - /usr/shar/doc/rt-sdk-ara2 - license info
    174  - /usr/include/sdk_ara - headers for C libs
    175  - /usr/bin - various scripts
    176  - /etc/udev/rules.d/99-ara2.rules - udev rule which makes the PCI ID dependent on the systemd service
    177  - /etc/systemd/system/rt-sdk-ara2.service - systemd service that handles the various hw util config
    178  - /etc/rt-sdk-ara240/cnn_config.yaml - config for nnapp
    179  - /etc/rt-sdk-ara240/proxy_config.yam - config for proxy
    180 
    181 Notes:
    182  - The 'uv' package manager is a fast all-in-one Python package and project manager written in Rust which makes it easy to work with virtual env's to avoid Python package version clashing which is essential
    183  - on bootup make sure you wait for the console messages indicating the Proxy is launched before using it as it can take a couple of minutes
    184  - the binary tools and libs are all static linked for compatibility
    185  - the GStreamer libs require GStreamer 1.26 or newer and is dynamic linked
    186 
    187 Verification steps:
    188  1. show chip_info
    189 {{{#!bash
    190 chip_info.sh
    191 }}}
    192  1. verify service
    193 {{{#!bash
    194 # show service status
    195 systemctl status rt-sdk-ara2.service --no-pager -l
    196 # view detailed service logs for the current boot and follow the journal
    197 journalctl --boot --follow --unit rt-sdk-ara2.service
    198 # verify proxy is running (critical)
    199 ps -eaf | grep proxy_ara240
    200 }}}
    201 
    202 Examples:
    203  - Download pre-compiled models for testing:
    204   - The fetch_models script from the ara2-rt will fetch models from !HuggingFace.
    205 {{{#!bash
    206 # list models available for nxp/ara
    207 fetch_models --list
    208 # install YOLOv8
    209 fetch_models --repo-id nxp/YOLOv8 # 746MB (711MiB)
    210 }}}
    211   - the 'fetch_models' script is a python wrapper that uses uvx and the fetch-models python wheel (/usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl) to fetch and install models from !HuggingFace HUB
    212   - the models will be installed in /usr/share/cnn (Convolutional Neural Network) and /usr/share/llm (Large Language Model)
    213   - NXP has Ara2 optimized models at https://huggingface.co/nxp
    214  - Run performance benchmark (uses nnapp)
    215 {{{#!bash
    216 run_model_perf.sh
    217 }}}
    218   - the 'run_model_perf.sh' script makes it easy to list and show model categories and models and is a wrapper around the nnapp app which has a lot of options and a config file
    219  - monitor real-time NPU metrics including utilization, temperature, DRAM usage and device state (interactively during benchmarking or model execution)
    220 {{{#!bash
    221 ara2_metrics.sh
    222 }}}
    223 
    224 [=#gstreamer]
    225 === GStreamer plugins
    226 The Ara runtime provides an OpenSource GStreamer plugin for detection models:
    227  - [https://github.com/nxp-imx-support/gstreamer-plugins-ara240 dvInf]
    228 
    229 The plugin can sink 32bit pixel samples (ie format=BGRx using 4 bytes per pixel, blue, green, red, and a pading byte as a structural spacer)
    230 
    231 The model is specified via the 'model' property. If using yolov8x for example you would specify the path to the yolov8x.dvm
    232 
    233 For detection models the element frame data will contain a buffer with number of bytes (32bit) followed by a series of detection structures containing the bounding box, confidence level, and COCO class ID of the object detected.
    234 
    235 The units for the bounding box are relative to the models size and will need to be scaled back to your original image size. For example the YOLO models operate on 640x640 pixel data. You can pass something larger in and it will essentially tile but its unclear if there is an advantage of doing that.
    236 
    237 While the gstreamer plugin source provided is provided [https://github.com/nxp-imx-support/gstreamer-plugins-ara240 here] it is included in the Ara runtime pre-compiled for convenience linked against stdlibc (libc.so.6) and libgstreamer-1.0.so.0 and compatible with GStreamer 1.26 or newer.
    238 
    239 Install GStreamer:
    240 {{{#!bash
    241 apt-get update && apt install -y \
    242    gstreamer1.0-x \
    243    gstreamer1.0-tools \
    244    gstreamer1.0-plugins-base \
    245    gstreamer1.0-plugins-good \
    246    gstreamer1.0-plugins-bad \
    247    gstreamer1.0-plugins-ugly \
    248    gstreamer1.0-libav \
    249    v4l-utils
    250 }}}
    251  - this adds about 500MiB of disk space
    252 
    253 Specify Plugin path:
    254 {{{#!bash
    255 # export now to current shell
    256 export GST_PLUGIN_PATH=/usr/lib/gstreamer-1.0/
    257 # put in .bashrc so it happens for any new bash shell
    258 echo "export GST_PLUGIN_PATH=/usr/lib/gstreamer-1.0/" >> ~/.bashrc
    259 }}}
    260  - this tells GStreamer to look for plugins in the non-standard location of the ARA gstreamer plugins
    261 
    262 At this point you can inspect the dvInf element:
    263 {{{#!bash
    264 gst-inspect-1.0 dvInf
    265 }}}
    266 
    267 Examples:
    268  * gst-launch pipeline prototyping:
    269   - enabling debug level 6 on dvPost will show the number of object detections in its debug output but if you want to do anything with that data you need to write an application that can decode frame buffers. Still this is useful for prototyping:
    270    * perform detection on a v4l2 video device like a webcam:
    271 {{{#!bash
    272 DEV=/dev/video_webcam
    273 MODEL=/usr/share/cnn/detection/yolov8n/model.dvm
    274 GST_DEBUG="dvInf:6" \
    275 gst-launch-1.0 -v \
    276   v4l2src device=$DEV ! \
    277   video/x-raw,width=640,height=480,framerate=30/1 ! \
    278   videoconvert ! video/x-raw,format=BGRx ! \
    279   dvInf model=$MODEL orig-width=640 orig-height=480 stream=0 \
    280         sock=/var/run/proxy.sock use-shm=true shm-path=/dev/shm/ara_shm ! \
    281   fakesink sync=false | grep Detected
    282 }}}
    283     - see wiki:linux/persistent_device_naming#video for details about making video devices have persistent device names
    284    * perform a detection on an image:
    285 {{{#!bash
    286 URI=file:///$PWD/traffic.png
    287 MODEL=/usr/share/cnn/detection/yolov8n/model.dvm
    288 GST_DEBUG="dvInf:6" \
    289 gst-launch-1.0 -v \
    290   filesrc location=traffic.png ! \
    291   pngdec ! imagefreeze num-buffers=10 ! \
    292   videoscale ! videoconvert ! video/x-raw,format=BGRx,width=640,height=480 ! \
    293   dvInf model=$MODEL orig-width=640 orig-height=480 stream=0 \
    294         sock=/var/run/proxy.sock use-shm=true shm-path=/dev/shm/ara_shm ! \
    295   fakesink sync=false | grep Detected
    296 }}}
    297 
    298 For a more complete example see below
    299 
    300 
    301 [=#eiq-aaf-connector]
    302 == eIQ AAF Connector for LLM inference
    303 The eIQ AAF Connector (edge Intelligence Ara Application Framework)
    304 is a REST-based server that enables LLM inference on NXP i.MX processors with the ARA-240 DNPU. The API implemented is the de-facto API standard created by OpenAI for ChatGPT. It provides a simple Chat Completions-based HTTP interface for serving models to client applications.
    305 
    306 Requirements:
    307  - python 3.13 (we will install in a virtual env)
    308  - uv - used for the user-specific Python virtual environment
    309  - Optimum Ara framework for running Large Language Models (LLMs) and Vision-Language Models (VLMs) on Ara240 (part of rt-sdk)
    310  - OpenCV (dependency of the QwenVL engine)
    311  - Models
    312 
    313 Source:
    314  - https://github.com/nxp-imx-support/eiq-aaf-connector
    315 
    316 For ease of use Gateworks provides a pre-built deb package of eiq-aaf-connector v2.1 built from the NXP IMX Yocto BSP which you can install with:
    317 {{{#!bash
    318 # fetch
    319 wget https://dev.gateworks.com/ara/eiq-aaf-connector_2.1-r0_arm64.deb
    320 # extract data (but don't install)
    321 dpkg-deb --vextract eiq-aaf-connector_2.1-r0_arm64.deb /
    322 # run the install script
    323 /usr/share/eiq/aaf-connector/install.sh
    324 # fetch LLM models (installed to /usr/share/llm)
    325 fetch_models --repo-id nxp/Qwen2.5-7B-Instruct-Ara240 # 7.7GiB LLM
    326 fetch_models --repo-id nxp/Qwen2.5-Coder-1.5B-Ara240 # 1.67GiB LLM
    327 fetch_models --repo-id nxp/Qwen2.5-VL-7B-Instruct-Ara240 # 12GB VLM
    328 }}}
    329 
    330 files:
    331  - /usr/share/eiq/aaf-connector/install.sh (install script)
    332  - /usr/share/python-wheels/eiq_aaf_connector-2.1-py3-none-any.whl (python wheel)
    333  - /usr/share/eiq/aaf-connector/server_config.json (config file)
    334  - /etc/systemd/system/eiq-aaf-connector.service (created from install script)
    335 
    336 The install script creates a systemd eiq-aaf-connector.service:
    337 {{{#!bash
    338 # Enable service on boot
    339 systemctl enable eiq-aaf-connector.service
    340 # Start the service now (or reboot)
    341 systemctl start eiq-aaf-connector.service
    342 }}}
    343 
    344 Notes:
    345  - By default the connector will listen on 127.0.0.1:8000. If you wish the service to be accessible externally set the host to '0.0.0.0' instead:
    346 {{{#!bash
    347 sed -i 's|--host 127.0.0.1|--host 0.0.0.0|g' /etc/systemd/system/eiq-aaf-connector.service
    348 }}}
    349  - the default config file has configuration for all of the above Ara models but they are not 'enabled' by default. You must only enable 1 model at a time and doing so loads the model onto the Ara when the servoce starts. To enable a model change the appropriate 'enabled' property to 'true' in /etc/systemd/system/eiq-aaf-connector.service and restart the service
    350  - it takes several minutes for the service to actually be ready for connections as it must process the models (monitor with 'journalctl -u eiq-aaf-connector.service --no-pager -f' and test that its ready for listening with 'ss -tulpn | grep :8000').
    351  - the connector self-hosts API documentation at http://<serverip>:8000/docs (available externally if configured for a host of 0.0.0.0)
    352 
    353 Example Usage:
    354  - verify connector running
    355 {{{#!bash
    356 # show service status
    357 systemctl status eiq-aaf-connector.service --no-pager -l
    358 # view detailed service logs for the current boot and follow the journal
    359 journalctl --boot --follow --unit eiq-aaf-connector.service
    360 # verify process exists
    361 ps -ef | grep aaf-connector
    362 # verify port open
    363 ss -tulpn | grep :8000 # show IP:PORT server is listening on
    364 }}}
    365  - view API docs and interact with server (requires changing the host to '0.0.0.0' in the !ExecStart config for /etc/systemd/system/eiq-aaf-connector.service by opening !http://<serverip>:8000/docs
    366  - use API via curl/jq
    367 {{{#!bash
    368 # make sure curl and jq are installed (jq allows easy interaction with json data)
    369 apt install -y curl jq
    370 # list of models
    371 curl -X 'GET' \
    372   'http://127.0.0.1:8000/v1/models' \
    373   -H 'accept: application/json' | jq
    374 # get info about a specific model (Qwen2.5-7B-Instruct)
    375 curl -X 'GET' \
    376   'http://127.0.0.1:8000/params/Qwen2.5-7B-Instruct' \
    377   -H 'accept: application/json' | jq
    378 # send a LLM query
    379 curl -X POST http://127.0.0.1:8000/v1/chat/completions -H "Content-Type: application/json" -d '{
    380   "model": "Qwen2.5-7B-Instruct",
    381   "messages": [
    382     {"role": "system", "content": "You are a helpful assistant running on NXP i.MX hardware."},
    383     {"role": "user", "content": "Explain what an NPU is in one sentence."}
    384   ],
    385   "max_tokens": 50
    386 }' | jq
    387 }}}
    388  - run connector by hand (useful for troubleshooting or monitoring)
    389 {{{#!bash
    390 systemctl stop eiq-aaf-connector.service
    391 source "/usr/share/eiq/aaf-connector/venv/bin/activate"
    392 connector --host 0.0.0.0 --port 8000 # will run until stopped
    393 deactivate
    394 }}}
    395 
    396 
    397 [=#examples]
    398 == Examples
    399 Here are some Ara example applications put together by Gateworks
    400 
    401 === dvapi stats
    402 This is an ANSI c app that provides an example of using the dvapi to connect to the proxy and obtain NPU endpoint stats such as temperature, clocks and usage. Basically it's a re-implementation of the closed source /usr/share/rt-sdk-ara240/scripts/ara2_metrics_bin/hw_metrics.out.
    403 
    404 ara_status.c:
    405 {{{#!c
    406 #include <stdio.h>
    407 #include <stdlib.h>
    408 #include "dvapi.h"
    409 
    410 int main() {
    411     dv_session_t *session = NULL;
    412     dv_endpoint_t *ep_list = NULL;
    413     int ep_count = 0;
    414     dv_status_code_t status;
    415     const char *socket_path = "/run/proxy.sock";
    416 
    417     // 1. Establish session
    418     status = dv_session_create_via_unix_socket(socket_path, &session);
    419     if (status != DV_SUCCESS) {
    420         fprintf(stderr, "Failed to connect: %s\n", dv_stringify_status_code(status));
    421         return 1;
    422     }
    423 
    424     // 2. Get list of NPU endpoints
    425     dv_endpoint_get_list(session, &ep_list, &ep_count);
    426 
    427     for (int i = 0; i < ep_count; i++) {
    428         dv_endpoint_t *ep = &ep_list[i];
    429         dv_endpoint_statistics_t *stats = NULL;
    430         int s_count = 0;
    431         bool is_busy = false;
    432 
    433         // 3. Retrieve status and statistics
    434         dv_get_endpoint_busyness(session, ep, &is_busy);
    435         status = dv_endpoint_get_statistics(session, ep, &stats, &s_count);
    436 
    437         if (status == DV_SUCCESS && s_count > 0) {
    438             // DRAM Calculations (Bytes to GB)
    439             double used_gb = (double)stats->ep_dram_stats.ep_total_dram_occupancy_size / 1073741824.0;
    440             double total_gb = (double)stats->ep_dram_stats.ep_total_dram_size / 1073741824.0;
    441             double dram_pct = (total_gb > 0) ? (used_gb / total_gb) * 100.0 : 0.0;
    442 
    443             // NPU Utilization (Queue occupancy)
    444             double npu_load = 0.0;
    445             if (stats->ep_infq_stats && stats->ep_infq_stats->length > 0) {
    446                 npu_load = ((double)stats->ep_infq_stats->occupancy_count / stats->ep_infq_stats->length) * 100.0;
    447             }
    448 
    449             printf("--- NPU Endpoint %d Statistics ---\n", i);
    450             printf("Busy State:       %s\n", is_busy ? "TRUE" : "FALSE");
    451             printf("NPU Utilization:  %.1f%%\n", npu_load);
    452             printf("Temperature:      %.1f C\n", stats->ep_temp);
    453             printf("NNP Clock:        %d MHz\n", stats->ep_nnp_clk);
    454             printf("SBP Clock:        %d MHz\n", stats->ep_sbp_clk);
    455             printf("DRAM Clock:       %d MHz\n", stats->ep_dram_clk);
    456            
    457             // Format: DRAM Usage: 8.2GB/16.0GB (51.3%)
    458             printf("DRAM Usage:       %.1fGB/%.1fGB (%.1f%%)\n", used_gb, total_gb, dram_pct);
    459             printf("\n");
    460 
    461             dv_endpoint_free_statistics(stats, s_count);
    462         }
    463     }
    464 
    465     // 4. Cleanup
    466     dv_endpoint_free_group(ep_list);
    467     dv_session_close(session);
    468     return 0;
    469 }
    470 }}}
    471 
    472 Compile:
    473 {{{#!bash
    474 apt update && apt install build-essential
    475 gcc ara_status.c -I/usr/include/sdk_ara/ -L/usr/lib/ -laraclient_aarch64 -o ara_status
    476 }}}
    477 
    478 Execution:
    479 {{{#!bash
    480 # ./ara_status
    481 --- NPU Endpoint 0 Statistics ---
    482 Busy State:       FALSE
    483 NPU Utilization:  0.0%
    484 Temperature:      56.0 C
    485 NNP Clock:        900 MHz
    486 SBP Clock:        355 MHz
    487 DRAM Clock:       1066 MHz
    488 DRAM Usage:       10.0GB/16.0GB (62.5%)
    489 }}}
    490 
    491 
    492 === Image Detection with boxying via Python
    493 Python is incredibly useful for accessing GStreamer and handling the ARA detection frame data and imagemagick provides excellent tools for converting and drawing on images. We use PyGObject which is a Python package that provides bindings for libraries based on GObject Introspection such as GTK, !WebKit, and GStreamer. It allows you to use C-based frameworks in python.
    494 
    495 Steps:
    496  1. We need to install the C libs for GStreamer and build utilities:
    497 {{{#!bash
    498 apt-get install -y \
    499   libcairo2-dev \
    500   libgirepository-2.0-dev \
    501   python3-dev \
    502   python3-gst-1.0 \
    503   cmake pkg-config
    504 # we are also going to need to install gstreamer and its dev packages
    505 apt-get install -y \
    506   libgstreamer1.0-dev \
    507   libgstreamer-plugins-base1.0-dev \
    508   libgstreamer-plugins-bad1.0-dev \
    509   gstreamer1.0-plugins-base \
    510   gstreamer1.0-plugins-good \
    511   gstreamer1.0-plugins-bad \
    512   gstreamer1.0-plugins-ugly \
    513   gstreamer1.0-libav \
    514   gstreamer1.0-tools
    515 }}}
    516  1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need:
    517 {{{#!bash
    518 # create a dir for the venv
    519 mkdir image-detect
    520 cd image-detect
    521 # create a venv (.venv)
    522 uv venv
    523 # install our scripts dependencies
    524 uv pip install pygobject
    525 }}}
    526  1. (optional) fetch some images for detection
    527 {{{#!bash
    528 # fetch a coco validation image; it contains a dog on a bench and the dog is at 208,147 to 293,289
    529 wget http://images.cocodataset.org/val2017/000000546829.jpg -O dog.jpg
    530 # use ffmpeg to grab a frame from within an MP4
    531 apt install -y ffmpeg
    532 ffmpeg -i /usr/share/ara2-vision-examples/sample_videos/video_0.mp4 -f null - # shows how lon git is (time=00:00:15.50)
    533 ffmpeg -i /usr/share/ara2-vision-examples/sample_videos/video_0.mp4 -ss 00:00:5 -frames:v 1 traffic.png
    534 }}}
    535  1. fetch the script
    536 {{{#!bash
    537 wget https://dev.gateworks.com/ara/examples/image_detect.py
    538 }}}
    539  1. run the script (image_detect.py <source-image> <destination-image> [model-path])
    540 {{{#!bash
    541 uv run image_detect.py dog.jpg coco_detections.jpg
    542 }}}
    543    - Note that without shm the pipeline needs to copy the raw image bytes over a local network-style socket connection. By mounting a dedicated memory path to /dev/shm you can eliminate that transfer (zero-copy): dvPre dumps the processed directly into a designated block of system RAM and dvInf uses a pointer to it
    544    - you would think that if your original image was 1080x1920 and you resized it to the model size of 640x640 that if you tell dvPost the orig-width=1080 orig-height=1920 that it would scale the bounding boxes properly however in practice it seems it does not unless your image has the same aspect ratio of the model. mapping it as above (telling dvPost that the image is 640x640 and scaling ourselves) resolves this
    545    - images:
    546 
    547 [[Image(dog.jpg,400px)]]
    548 [[Image(dog_detect.jpg,400px)]]
    549 
    550 [[Image(traffic.jpg,400px)]]
    551 [[Image(traffic_detect_yolo8n.jpg,400px)]]
    552 [[Image(traffic_detect_yolo8x.jpg,400px)]]
    553 
    554 
    555 === Video Detection Webapp via Python
    556 Python is incredibly useful for accessing GStreamer and handling the ARA detection frame data and building webapps. The script using PyGObject which is a Python package that provides bindings for libraries based on GObject Introspection such as GTK, !WebKit, and GStreamer. It allows you to use C-based frameworks in python. We need to install the C libs for GStreamer for this
    557 
    558 Steps:
    559  1. We need to install the C libs for GStreamer and build utilities:
    560 {{{#!bash
    561 apt-get install -y \
    562   libcairo2-dev \
    563   libgirepository-2.0-dev \
    564   python3-dev \
    565   python3-gst-1.0 \
    566   cmake pkg-config
    567 # we are also going to need to install GStreamer and its dev packages
    568 apt-get install -y \
    569   libgstreamer1.0-dev \
    570   libgstreamer-plugins-base1.0-dev \
    571   libgstreamer-plugins-bad1.0-dev \
    572   gstreamer1.0-plugins-base \
    573   gstreamer1.0-plugins-good \
    574   gstreamer1.0-plugins-bad \
    575   gstreamer1.0-plugins-ugly \
    576   gstreamer1.0-libav \
    577   gstreamer1.0-tools
    578 }}}
    579  1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need:
    580 {{{#!bash
    581 # create a dir for the venv
    582 mkdir vision-webapp
    583 cd vision-webapp
    584 # create a venv (.venv)
    585 uv venv
    586 # install our scripts dependencies
    587 uv pip install pygobject opencv-python-headless flask
    588 }}}
    589  1. fetch the script
    590 {{{#!bash
    591 wget https://dev.gateworks.com/ara/examples/vision-webapp.py
    592 }}}
    593  1. run the script (vison-webapp.py [--port <portno>] [--camera <camera-dev>] [--mp4 <mp4-dir>]
    594 {{{#!bash
    595 uv run vision-webapp.py --camera /dev/video_webcam --mp4 /usr/share/media/sample_videos/
    596 }}}
    597   - you can provide a webcam device path to enable streaming from a webcam and/or an mp4 directory to enable processing those. A dropdown will allow you to select the input stream and the model and the browser window will show you detections and statistics
    598 
    599 [[Image(vision-webapp.jpg,400px)]]
    600 
    601 
    602 === command-line python eIQ chatbot (chat.py)
    603 This is a command-line chatbot written in python using the eIQ AAF Connector
    604  1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need:
    605 {{{#!bash
    606 # create a dir for the venv
    607 mkdir chat
    608 cd chat
    609 # create a venv (.venv)
    610 uv venv
    611 # install our scripts dependencies
    612 uv pip install -q requests
    613 }}}
    614  1. fetch the script
    615 {{{#!bash
    616 wget https://dev.gateworks.com/ara/examples/chat.py
    617 }}}
    618  1. run the script
    619 {{{#!bash
    620 uv run chat.py
    621 }}}
    622 
    623 Example session:
    624 {{{#!bash
    625 --- i.MX LLM Session (Model: Qwen2.5-7B-Instruct) ---
    626 Type 'exit' to stop.
    627 
    628 You: Why is the sky blue
    629 AI: The sky appears blue because of a phenomenon called Rayleigh scattering. When sunlight enters the Earth's atmosphere, it collides with molecules and small particles in the air. Sunlight is made up of different colors, each of which has a different wavelength. Blue light has a shorter wavelength and is scattered more than other colors by the gases and particles in the atmosphere. This scattering makes the sky appear blue to our eyes.
    630 
    631 During sunrise and sunset, the sky can appear red or orange because the light has to travel through more of the Earth's atmosphere. This longer path means that more blue and green light is scattered out of the beam, leaving the red and orange wavelengths to dominate the light that reaches our eyes.
    632 
    633 So, the blue color of the sky is primarily due to the way shorter wavelength light is scattered by the Earth's atmosphere.
    634 
    635 --- Stats ---
    636 Time taken: 29.18 seconds
    637 Throughput: 5.04 tokens/sec
    638 -------------
    639 
    640 You: exit
    641 }}}
    642 
    643 
    644 === Web based python eIQ chatbot (webchat.py)
    645 This is a web based chatbot in python using eIQ AAF Connector
    646 
    647  1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need:
    648 {{{#!bash
    649 # create a dir for the venv
    650 mkdir webchat
    651 cd webchat
    652 # create a venv (.venv)
    653 uv venv
    654 # install our scripts dependencies
    655 uv pip install -q fastapi psutil uvicorn
    656 }}}
    657  1. fetch the script
    658 {{{#!bash
    659 wget https://dev.gateworks.com/ara/examples/webchat.py
    660 }}}
    661  1. run the script
    662 {{{#!bash
    663 uv run webchat.py
    664 }}}
    665  1. Open a web browser to your boards IP address port 8080: http://<ipaddr>:8080
    666 
    667 Notes:
    668  * By default this will listen for HTTP requests on port 8080
    669  * On startup it will enable the model (specified in the script) and restart the eIQ server if needed - waiting for the model to load may take several minutes
    670 
    671 
    672 [=#vlm]
    673 === Web based python VLM eIQ example (webvlm.py)
    674 The eIQ AAF Connector can be used to analyze video and images.
    675 
    676 Here is an example of a headless web-app based off NXP's [https://github.com/nxp-imx-support/vlm-edge-studio/tree/main/src vlm-edge-studio example] using:
    677  - Qwen2.5-VL-7B-Instruct-Ara240
    678  - eIQ AAF Connector
    679 
    680 Requirements:
    681  - Ara runtime
    682  - eIQ AAF Connector
    683  - Qwen2.5-VL-7B-Instruct-Ara240 model
    684 
    685 Steps:
    686  1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need:
    687 {{{#!bash
    688 # create a dir for the venv
    689 mkdir webvlm
    690 cd webvlm
    691 # create a venv (.venv)
    692 uv venv
    693 # install our scripts dependencies
    694 uv pip install -q httpx uvicorn fastapi argparse
    695 }}}
    696  1. fetch the script
    697 {{{#!bash
    698 wget https://dev.gateworks.com/ara/examples/webvlm.py
    699 }}}
    700  1. run the script
    701 {{{#!bash
    702 uv run webvlm.py --video-dir /usr/share/media/sample_videos/
    703 }}}
    704  1. Open a web browser to your boards IP address port 8080: http://<ipaddr>:8080
    705 
    706 Notes:
    707  * By default this will listen for HTTP requests on port 8080
    708  * On startup it will enable the model (specified in the script) and restart the eIQ server if needed - waiting for the model to load may take several minutes
    709 
    710 
    711 [[Image(vlm-webapp.jpg,400px)]]
    712 
    713 
    714 == Troubleshooting
    715 
    716 Please note software support should be routed through NXP, who produces the Ara240 DNPU Chip and Software SDK.
    717 
    718 [https://community.nxp.com]
    71988
    72089
     
    1105474INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
    1106475}}}
     476
     477
     478= NXP Ara240 DNPU AI Accelerator Quick Start
     479Below are details regarding installing the ARA2 runtime software requirements manually. If you are using the Gateworks i.MX95 Catalina AI Devkit this software is already installed. Please see [#ai-devkit above for details]
     480 
     481[=#ara2-runtime]
     482== Ara Runtime
     483NXP has a runtime library for the Ara240 which consists of some statically built libraries as well as a dynamic linked GStreamer plugin.
     484
     485The Ara runtime includes a couple of Python Wheels. A Python Wheel is a standard built-package format for distributing Python libraries. It is essentially a ZIP-format archive with a .whl extension that contains all the files needed for a package to run immediately after being. It's fairly standard when using Python to run into package version incompatibilities which is why user based Python virtual environments are used.
     486
     487The Ara runtime provides a complete runtime environment for AI/ML acceleration using the Ara240 NPU on for aarch64. This package includes:
     488 * Runtime libraries for Ara240 NPU integration
     489 * Python bindings (DVAPI) for custom inference applications
     490 * Optimum-Ara framework for LLMs and VLMs
     491 * GStreamer plugin for Real-Time Detection Object Applications
     492 * Helper scripts for monitoring, benchmarking, and model management
     493 * Systemd service for automatic hardware initialization
     494
     495Installation on a Gateworks board with Ubuntu based OS:
     496 - Download and extract the self-extracting binary from NXP:
     497{{{#!bash
     498VER=imx-nxp-ara2-2.1.1-063d56c
     499wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/$VER.bin
     500sh $VER.bin
     501}}}
     502 - take care of postinst steps
     503  - miscellaneous
     504{{{#!bash
     505# create dirs (used for models)
     506mkdir -pv /usr/share/{cnn,llm}
     507}}}
     508  - configure swap (necessary if using VLM)
     509{{{#!bash
     510/usr/bin/enable_swap 2
     511}}}
     512  - install uv package manager for Python virtualization and packaging for local user (which is installed to ~/.local/bin so we create symlinks to /usr/bin)
     513{{{#!bash
     514apt update && apt install -y curl
     515curl -LsSf https://astral.sh/uv/install.sh | sh
     516ln -s /root/.local/bin/uv /usr/bin/uv
     517ln -s /root/.local/bin/uvx /usr/bin/uvx
     518}}}
     519  - build driver
     520{{{#!bash
     521apt update && apt install -y build-essential git bc file flex bison
     522git clone https://github.com/nxp-imx-support/uiodma-driver
     523( cd uiodma-driver/uiodma; make )
     524# install it where the rt service expects to find it (over the top of the non-compatible one)
     525cp uiodma-driver/uiodma/uiodma.ko /usr/share/rt-sdk-ara240/driver/
     526}}}
     527  - enable service:
     528{{{#!bash
     529# enable service
     530systemctl enable rt-sdk-ara2.service
     531# start service now (unless you reboot)
     532systemctl start rt-sdk-ara2.service
     533}}}
     534  - use 'fetch_models' to pre-compiled models for testing via the fetch_models script which will fetch models from !HuggingFace.
     535{{{#!bash
     536# list models available for nxp/ara
     537fetch_models --list
     538# install YOLOv8
     539fetch_models --repo-id nxp/YOLOv8 # 746MB (711MiB)
     540}}}
     541   - the script is a python wrapper that uses uvx and the fetch-models python wheel (/usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl) to fetch and install models from !HuggingFace HUB
     542   - the models will be installed in either /usr/share/cnn (Convolutional Neural Network) and /usr/share/llm (Large Language Model)
     543   - NXP has Ara2 optimized models at https://huggingface.co/nxp
     544   - the script has a hard coded list of models available and where to install them locally. You can use 'python -m zipfile -e /usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl ./fetch_models' to see what it's doing
     545
     546Notable Files:
     547 - /usr/lib/
     548  - libaraclient_aarch64.so - base library for interfacing with ara2
     549  - libara_vision_inference.so - inference lib that builds on libaraclient
     550 - /usr/lib/gstreamer-1.0
     551  - libgstdvInf.so - GStreamer plugin
     552 - /usr/share/rt-sdk-ara240 (symlink to a version independent dir at same location)
     553  - hw_utils/boot_img - firmware files
     554  - hw_utils/ddr_config - ddr binaries
     555  - hw_utils/bins/ - the hw utils for bringup/programming
     556  - optimum-ara/ - extension of the Hugging Face library that integrates with Ara240 DNPU
     557  - scripts - various wrappers around the tools etc
     558  - nnapp - tool for benchmarking models
     559  - config - various example yaml config files used for proxy/nnapp
     560  - include/dvapi.py - python bindings to dvapi
     561  - driver/uiodma.ko - driver (where the setup script expects to find it)
     562 - /usr/share/python-wheels - python wheels for fetch_models and optimum_ara
     563 - /usr/shar/doc/rt-sdk-ara2 - license info
     564 - /usr/include/sdk_ara - headers for C libs
     565 - /usr/bin - various scripts
     566 - /etc/udev/rules.d/99-ara2.rules - udev rule which makes the PCI ID dependent on the systemd service
     567 - /etc/systemd/system/rt-sdk-ara2.service - systemd service that handles the various hw util config
     568 - /etc/rt-sdk-ara240/cnn_config.yaml - config for nnapp
     569 - /etc/rt-sdk-ara240/proxy_config.yam - config for proxy
     570
     571Notes:
     572 - The 'uv' package manager is a fast all-in-one Python package and project manager written in Rust which makes it easy to work with virtual env's to avoid Python package version clashing which is essential
     573 - on bootup make sure you wait for the console messages indicating the Proxy is launched before using it as it can take a couple of minutes
     574 - the binary tools and libs are all static linked for compatibility
     575 - the GStreamer libs require GStreamer 1.26 or newer and is dynamic linked
     576
     577Verification steps:
     578 1. show chip_info
     579{{{#!bash
     580chip_info.sh
     581}}}
     582 1. verify service
     583{{{#!bash
     584# show service status
     585systemctl status rt-sdk-ara2.service --no-pager -l
     586# view detailed service logs for the current boot and follow the journal
     587journalctl --boot --follow --unit rt-sdk-ara2.service
     588# verify proxy is running (critical)
     589ps -eaf | grep proxy_ara240
     590}}}
     591
     592Examples:
     593 - Download pre-compiled models for testing:
     594  - The fetch_models script from the ara2-rt will fetch models from !HuggingFace.
     595{{{#!bash
     596# list models available for nxp/ara
     597fetch_models --list
     598# install YOLOv8
     599fetch_models --repo-id nxp/YOLOv8 # 746MB (711MiB)
     600}}}
     601  - the 'fetch_models' script is a python wrapper that uses uvx and the fetch-models python wheel (/usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl) to fetch and install models from !HuggingFace HUB
     602  - the models will be installed in /usr/share/cnn (Convolutional Neural Network) and /usr/share/llm (Large Language Model)
     603  - NXP has Ara2 optimized models at https://huggingface.co/nxp
     604 - Run performance benchmark (uses nnapp)
     605{{{#!bash
     606run_model_perf.sh
     607}}}
     608  - the 'run_model_perf.sh' script makes it easy to list and show model categories and models and is a wrapper around the nnapp app which has a lot of options and a config file
     609 - monitor real-time NPU metrics including utilization, temperature, DRAM usage and device state (interactively during benchmarking or model execution)
     610{{{#!bash
     611ara2_metrics.sh
     612}}}
     613
     614[=#gstreamer]
     615=== GStreamer plugins
     616The Ara runtime provides an OpenSource GStreamer plugin for detection models:
     617 - [https://github.com/nxp-imx-support/gstreamer-plugins-ara240 dvInf]
     618
     619The plugin can sink 32bit pixel samples (ie format=BGRx using 4 bytes per pixel, blue, green, red, and a pading byte as a structural spacer)
     620
     621The model is specified via the 'model' property. If using yolov8x for example you would specify the path to the yolov8x.dvm
     622
     623For detection models the element frame data will contain a buffer with number of bytes (32bit) followed by a series of detection structures containing the bounding box, confidence level, and COCO class ID of the object detected.
     624
     625The units for the bounding box are relative to the models size and will need to be scaled back to your original image size. For example the YOLO models operate on 640x640 pixel data. You can pass something larger in and it will essentially tile but its unclear if there is an advantage of doing that.
     626
     627While the gstreamer plugin source provided is provided [https://github.com/nxp-imx-support/gstreamer-plugins-ara240 here] it is included in the Ara runtime pre-compiled for convenience linked against stdlibc (libc.so.6) and libgstreamer-1.0.so.0 and compatible with GStreamer 1.26 or newer.
     628
     629Install GStreamer:
     630{{{#!bash
     631apt-get update && apt install -y \
     632   gstreamer1.0-x \
     633   gstreamer1.0-tools \
     634   gstreamer1.0-plugins-base \
     635   gstreamer1.0-plugins-good \
     636   gstreamer1.0-plugins-bad \
     637   gstreamer1.0-plugins-ugly \
     638   gstreamer1.0-libav \
     639   v4l-utils
     640}}}
     641 - this adds about 500MiB of disk space
     642
     643Specify Plugin path:
     644{{{#!bash
     645# export now to current shell
     646export GST_PLUGIN_PATH=/usr/lib/gstreamer-1.0/
     647# put in .bashrc so it happens for any new bash shell
     648echo "export GST_PLUGIN_PATH=/usr/lib/gstreamer-1.0/" >> ~/.bashrc
     649}}}
     650 - this tells GStreamer to look for plugins in the non-standard location of the ARA gstreamer plugins
     651
     652At this point you can inspect the dvInf element:
     653{{{#!bash
     654gst-inspect-1.0 dvInf
     655}}}
     656
     657Examples:
     658 * gst-launch pipeline prototyping:
     659  - enabling debug level 6 on dvPost will show the number of object detections in its debug output but if you want to do anything with that data you need to write an application that can decode frame buffers. Still this is useful for prototyping:
     660   * perform detection on a v4l2 video device like a webcam:
     661{{{#!bash
     662DEV=/dev/video_webcam
     663MODEL=/usr/share/cnn/detection/yolov8n/model.dvm
     664GST_DEBUG="dvInf:6" \
     665gst-launch-1.0 -v \
     666  v4l2src device=$DEV ! \
     667  video/x-raw,width=640,height=480,framerate=30/1 ! \
     668  videoconvert ! video/x-raw,format=BGRx ! \
     669  dvInf model=$MODEL orig-width=640 orig-height=480 stream=0 \
     670        sock=/var/run/proxy.sock use-shm=true shm-path=/dev/shm/ara_shm ! \
     671  fakesink sync=false | grep Detected
     672}}}
     673    - see wiki:linux/persistent_device_naming#video for details about making video devices have persistent device names
     674   * perform a detection on an image:
     675{{{#!bash
     676URI=file:///$PWD/traffic.png
     677MODEL=/usr/share/cnn/detection/yolov8n/model.dvm
     678GST_DEBUG="dvInf:6" \
     679gst-launch-1.0 -v \
     680  filesrc location=traffic.png ! \
     681  pngdec ! imagefreeze num-buffers=10 ! \
     682  videoscale ! videoconvert ! video/x-raw,format=BGRx,width=640,height=480 ! \
     683  dvInf model=$MODEL orig-width=640 orig-height=480 stream=0 \
     684        sock=/var/run/proxy.sock use-shm=true shm-path=/dev/shm/ara_shm ! \
     685  fakesink sync=false | grep Detected
     686}}}
     687
     688For a more complete example see below
     689
     690
     691[=#eiq-aaf-connector]
     692== eIQ AAF Connector for LLM inference
     693The eIQ AAF Connector (edge Intelligence Ara Application Framework)
     694is a REST-based server that enables LLM inference on NXP i.MX processors with the ARA-240 DNPU. The API implemented is the de-facto API standard created by OpenAI for ChatGPT. It provides a simple Chat Completions-based HTTP interface for serving models to client applications.
     695
     696Requirements:
     697 - python 3.13 (we will install in a virtual env)
     698 - uv - used for the user-specific Python virtual environment
     699 - Optimum Ara framework for running Large Language Models (LLMs) and Vision-Language Models (VLMs) on Ara240 (part of rt-sdk)
     700 - OpenCV (dependency of the QwenVL engine)
     701 - Models
     702
     703Source:
     704 - https://github.com/nxp-imx-support/eiq-aaf-connector
     705
     706For ease of use Gateworks provides a pre-built deb package of eiq-aaf-connector v2.1 built from the NXP IMX Yocto BSP which you can install with:
     707{{{#!bash
     708# fetch
     709wget https://dev.gateworks.com/ara/eiq-aaf-connector_2.1-r0_arm64.deb
     710# extract data (but don't install)
     711dpkg-deb --vextract eiq-aaf-connector_2.1-r0_arm64.deb /
     712# run the install script
     713/usr/share/eiq/aaf-connector/install.sh
     714# fetch LLM models (installed to /usr/share/llm)
     715fetch_models --repo-id nxp/Qwen2.5-7B-Instruct-Ara240 # 7.7GiB LLM
     716fetch_models --repo-id nxp/Qwen2.5-Coder-1.5B-Ara240 # 1.67GiB LLM
     717fetch_models --repo-id nxp/Qwen2.5-VL-7B-Instruct-Ara240 # 12GB VLM
     718}}}
     719
     720files:
     721 - /usr/share/eiq/aaf-connector/install.sh (install script)
     722 - /usr/share/python-wheels/eiq_aaf_connector-2.1-py3-none-any.whl (python wheel)
     723 - /usr/share/eiq/aaf-connector/server_config.json (config file)
     724 - /etc/systemd/system/eiq-aaf-connector.service (created from install script)
     725
     726The install script creates a systemd eiq-aaf-connector.service:
     727{{{#!bash
     728# Enable service on boot
     729systemctl enable eiq-aaf-connector.service
     730# Start the service now (or reboot)
     731systemctl start eiq-aaf-connector.service
     732}}}
     733
     734Notes:
     735 - By default the connector will listen on 127.0.0.1:8000. If you wish the service to be accessible externally set the host to '0.0.0.0' instead:
     736{{{#!bash
     737sed -i 's|--host 127.0.0.1|--host 0.0.0.0|g' /etc/systemd/system/eiq-aaf-connector.service
     738}}}
     739 - the default config file has configuration for all of the above Ara models but they are not 'enabled' by default. You must only enable 1 model at a time and doing so loads the model onto the Ara when the servoce starts. To enable a model change the appropriate 'enabled' property to 'true' in /etc/systemd/system/eiq-aaf-connector.service and restart the service
     740 - it takes several minutes for the service to actually be ready for connections as it must process the models (monitor with 'journalctl -u eiq-aaf-connector.service --no-pager -f' and test that its ready for listening with 'ss -tulpn | grep :8000').
     741 - the connector self-hosts API documentation at http://<serverip>:8000/docs (available externally if configured for a host of 0.0.0.0)
     742
     743Example Usage:
     744 - verify connector running
     745{{{#!bash
     746# show service status
     747systemctl status eiq-aaf-connector.service --no-pager -l
     748# view detailed service logs for the current boot and follow the journal
     749journalctl --boot --follow --unit eiq-aaf-connector.service
     750# verify process exists
     751ps -ef | grep aaf-connector
     752# verify port open
     753ss -tulpn | grep :8000 # show IP:PORT server is listening on
     754}}}
     755 - view API docs and interact with server (requires changing the host to '0.0.0.0' in the !ExecStart config for /etc/systemd/system/eiq-aaf-connector.service by opening !http://<serverip>:8000/docs
     756 - use API via curl/jq
     757{{{#!bash
     758# make sure curl and jq are installed (jq allows easy interaction with json data)
     759apt install -y curl jq
     760# list of models
     761curl -X 'GET' \
     762  'http://127.0.0.1:8000/v1/models' \
     763  -H 'accept: application/json' | jq
     764# get info about a specific model (Qwen2.5-7B-Instruct)
     765curl -X 'GET' \
     766  'http://127.0.0.1:8000/params/Qwen2.5-7B-Instruct' \
     767  -H 'accept: application/json' | jq
     768# send a LLM query
     769curl -X POST http://127.0.0.1:8000/v1/chat/completions -H "Content-Type: application/json" -d '{
     770  "model": "Qwen2.5-7B-Instruct",
     771  "messages": [
     772    {"role": "system", "content": "You are a helpful assistant running on NXP i.MX hardware."},
     773    {"role": "user", "content": "Explain what an NPU is in one sentence."}
     774  ],
     775  "max_tokens": 50
     776}' | jq
     777}}}
     778 - run connector by hand (useful for troubleshooting or monitoring)
     779{{{#!bash
     780systemctl stop eiq-aaf-connector.service
     781source "/usr/share/eiq/aaf-connector/venv/bin/activate"
     782connector --host 0.0.0.0 --port 8000 # will run until stopped
     783deactivate
     784}}}
     785
     786
     787[=#examples]
     788== Examples
     789Here are some Ara example applications put together by Gateworks
     790
     791=== dvapi stats
     792This is an ANSI c app that provides an example of using the dvapi to connect to the proxy and obtain NPU endpoint stats such as temperature, clocks and usage. Basically it's a re-implementation of the closed source /usr/share/rt-sdk-ara240/scripts/ara2_metrics_bin/hw_metrics.out.
     793
     794ara_status.c:
     795{{{#!c
     796#include <stdio.h>
     797#include <stdlib.h>
     798#include "dvapi.h"
     799
     800int main() {
     801    dv_session_t *session = NULL;
     802    dv_endpoint_t *ep_list = NULL;
     803    int ep_count = 0;
     804    dv_status_code_t status;
     805    const char *socket_path = "/run/proxy.sock";
     806
     807    // 1. Establish session
     808    status = dv_session_create_via_unix_socket(socket_path, &session);
     809    if (status != DV_SUCCESS) {
     810        fprintf(stderr, "Failed to connect: %s\n", dv_stringify_status_code(status));
     811        return 1;
     812    }
     813
     814    // 2. Get list of NPU endpoints
     815    dv_endpoint_get_list(session, &ep_list, &ep_count);
     816
     817    for (int i = 0; i < ep_count; i++) {
     818        dv_endpoint_t *ep = &ep_list[i];
     819        dv_endpoint_statistics_t *stats = NULL;
     820        int s_count = 0;
     821        bool is_busy = false;
     822
     823        // 3. Retrieve status and statistics
     824        dv_get_endpoint_busyness(session, ep, &is_busy);
     825        status = dv_endpoint_get_statistics(session, ep, &stats, &s_count);
     826
     827        if (status == DV_SUCCESS && s_count > 0) {
     828            // DRAM Calculations (Bytes to GB)
     829            double used_gb = (double)stats->ep_dram_stats.ep_total_dram_occupancy_size / 1073741824.0;
     830            double total_gb = (double)stats->ep_dram_stats.ep_total_dram_size / 1073741824.0;
     831            double dram_pct = (total_gb > 0) ? (used_gb / total_gb) * 100.0 : 0.0;
     832
     833            // NPU Utilization (Queue occupancy)
     834            double npu_load = 0.0;
     835            if (stats->ep_infq_stats && stats->ep_infq_stats->length > 0) {
     836                npu_load = ((double)stats->ep_infq_stats->occupancy_count / stats->ep_infq_stats->length) * 100.0;
     837            }
     838
     839            printf("--- NPU Endpoint %d Statistics ---\n", i);
     840            printf("Busy State:       %s\n", is_busy ? "TRUE" : "FALSE");
     841            printf("NPU Utilization:  %.1f%%\n", npu_load);
     842            printf("Temperature:      %.1f C\n", stats->ep_temp);
     843            printf("NNP Clock:        %d MHz\n", stats->ep_nnp_clk);
     844            printf("SBP Clock:        %d MHz\n", stats->ep_sbp_clk);
     845            printf("DRAM Clock:       %d MHz\n", stats->ep_dram_clk);
     846           
     847            // Format: DRAM Usage: 8.2GB/16.0GB (51.3%)
     848            printf("DRAM Usage:       %.1fGB/%.1fGB (%.1f%%)\n", used_gb, total_gb, dram_pct);
     849            printf("\n");
     850
     851            dv_endpoint_free_statistics(stats, s_count);
     852        }
     853    }
     854
     855    // 4. Cleanup
     856    dv_endpoint_free_group(ep_list);
     857    dv_session_close(session);
     858    return 0;
     859}
     860}}}
     861
     862Compile:
     863{{{#!bash
     864apt update && apt install build-essential
     865gcc ara_status.c -I/usr/include/sdk_ara/ -L/usr/lib/ -laraclient_aarch64 -o ara_status
     866}}}
     867
     868Execution:
     869{{{#!bash
     870# ./ara_status
     871--- NPU Endpoint 0 Statistics ---
     872Busy State:       FALSE
     873NPU Utilization:  0.0%
     874Temperature:      56.0 C
     875NNP Clock:        900 MHz
     876SBP Clock:        355 MHz
     877DRAM Clock:       1066 MHz
     878DRAM Usage:       10.0GB/16.0GB (62.5%)
     879}}}
     880
     881
     882=== Image Detection with boxying via Python
     883Python is incredibly useful for accessing GStreamer and handling the ARA detection frame data and imagemagick provides excellent tools for converting and drawing on images. We use PyGObject which is a Python package that provides bindings for libraries based on GObject Introspection such as GTK, !WebKit, and GStreamer. It allows you to use C-based frameworks in python.
     884
     885Steps:
     886 1. We need to install the C libs for GStreamer and build utilities:
     887{{{#!bash
     888apt-get install -y \
     889  libcairo2-dev \
     890  libgirepository-2.0-dev \
     891  python3-dev \
     892  python3-gst-1.0 \
     893  cmake pkg-config
     894# we are also going to need to install gstreamer and its dev packages
     895apt-get install -y \
     896  libgstreamer1.0-dev \
     897  libgstreamer-plugins-base1.0-dev \
     898  libgstreamer-plugins-bad1.0-dev \
     899  gstreamer1.0-plugins-base \
     900  gstreamer1.0-plugins-good \
     901  gstreamer1.0-plugins-bad \
     902  gstreamer1.0-plugins-ugly \
     903  gstreamer1.0-libav \
     904  gstreamer1.0-tools
     905}}}
     906 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need:
     907{{{#!bash
     908# create a dir for the venv
     909mkdir image-detect
     910cd image-detect
     911# create a venv (.venv)
     912uv venv
     913# install our scripts dependencies
     914uv pip install pygobject
     915}}}
     916 1. (optional) fetch some images for detection
     917{{{#!bash
     918# fetch a coco validation image; it contains a dog on a bench and the dog is at 208,147 to 293,289
     919wget http://images.cocodataset.org/val2017/000000546829.jpg -O dog.jpg
     920# use ffmpeg to grab a frame from within an MP4
     921apt install -y ffmpeg
     922ffmpeg -i /usr/share/ara2-vision-examples/sample_videos/video_0.mp4 -f null - # shows how lon git is (time=00:00:15.50)
     923ffmpeg -i /usr/share/ara2-vision-examples/sample_videos/video_0.mp4 -ss 00:00:5 -frames:v 1 traffic.png
     924}}}
     925 1. fetch the script
     926{{{#!bash
     927wget https://dev.gateworks.com/ara/examples/image_detect.py
     928}}}
     929 1. run the script (image_detect.py <source-image> <destination-image> [model-path])
     930{{{#!bash
     931uv run image_detect.py dog.jpg coco_detections.jpg
     932}}}
     933   - Note that without shm the pipeline needs to copy the raw image bytes over a local network-style socket connection. By mounting a dedicated memory path to /dev/shm you can eliminate that transfer (zero-copy): dvPre dumps the processed directly into a designated block of system RAM and dvInf uses a pointer to it
     934   - you would think that if your original image was 1080x1920 and you resized it to the model size of 640x640 that if you tell dvPost the orig-width=1080 orig-height=1920 that it would scale the bounding boxes properly however in practice it seems it does not unless your image has the same aspect ratio of the model. mapping it as above (telling dvPost that the image is 640x640 and scaling ourselves) resolves this
     935   - images:
     936
     937[[Image(dog.jpg,400px)]]
     938[[Image(dog_detect.jpg,400px)]]
     939
     940[[Image(traffic.jpg,400px)]]
     941[[Image(traffic_detect_yolo8n.jpg,400px)]]
     942[[Image(traffic_detect_yolo8x.jpg,400px)]]
     943
     944
     945=== Video Detection Webapp via Python
     946Python is incredibly useful for accessing GStreamer and handling the ARA detection frame data and building webapps. The script using PyGObject which is a Python package that provides bindings for libraries based on GObject Introspection such as GTK, !WebKit, and GStreamer. It allows you to use C-based frameworks in python. We need to install the C libs for GStreamer for this
     947
     948Steps:
     949 1. We need to install the C libs for GStreamer and build utilities:
     950{{{#!bash
     951apt-get install -y \
     952  libcairo2-dev \
     953  libgirepository-2.0-dev \
     954  python3-dev \
     955  python3-gst-1.0 \
     956  cmake pkg-config
     957# we are also going to need to install GStreamer and its dev packages
     958apt-get install -y \
     959  libgstreamer1.0-dev \
     960  libgstreamer-plugins-base1.0-dev \
     961  libgstreamer-plugins-bad1.0-dev \
     962  gstreamer1.0-plugins-base \
     963  gstreamer1.0-plugins-good \
     964  gstreamer1.0-plugins-bad \
     965  gstreamer1.0-plugins-ugly \
     966  gstreamer1.0-libav \
     967  gstreamer1.0-tools
     968}}}
     969 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need:
     970{{{#!bash
     971# create a dir for the venv
     972mkdir vision-webapp
     973cd vision-webapp
     974# create a venv (.venv)
     975uv venv
     976# install our scripts dependencies
     977uv pip install pygobject opencv-python-headless flask
     978}}}
     979 1. fetch the script
     980{{{#!bash
     981wget https://dev.gateworks.com/ara/examples/vision-webapp.py
     982}}}
     983 1. run the script (vison-webapp.py [--port <portno>] [--camera <camera-dev>] [--mp4 <mp4-dir>]
     984{{{#!bash
     985uv run vision-webapp.py --camera /dev/video_webcam --mp4 /usr/share/media/sample_videos/
     986}}}
     987  - you can provide a webcam device path to enable streaming from a webcam and/or an mp4 directory to enable processing those. A dropdown will allow you to select the input stream and the model and the browser window will show you detections and statistics
     988
     989[[Image(vision-webapp.jpg,400px)]]
     990
     991
     992=== command-line python eIQ chatbot (chat.py)
     993This is a command-line chatbot written in python using the eIQ AAF Connector
     994 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need:
     995{{{#!bash
     996# create a dir for the venv
     997mkdir chat
     998cd chat
     999# create a venv (.venv)
     1000uv venv
     1001# install our scripts dependencies
     1002uv pip install -q requests
     1003}}}
     1004 1. fetch the script
     1005{{{#!bash
     1006wget https://dev.gateworks.com/ara/examples/chat.py
     1007}}}
     1008 1. run the script
     1009{{{#!bash
     1010uv run chat.py
     1011}}}
     1012
     1013Example session:
     1014{{{#!bash
     1015--- i.MX LLM Session (Model: Qwen2.5-7B-Instruct) ---
     1016Type 'exit' to stop.
     1017
     1018You: Why is the sky blue
     1019AI: The sky appears blue because of a phenomenon called Rayleigh scattering. When sunlight enters the Earth's atmosphere, it collides with molecules and small particles in the air. Sunlight is made up of different colors, each of which has a different wavelength. Blue light has a shorter wavelength and is scattered more than other colors by the gases and particles in the atmosphere. This scattering makes the sky appear blue to our eyes.
     1020
     1021During sunrise and sunset, the sky can appear red or orange because the light has to travel through more of the Earth's atmosphere. This longer path means that more blue and green light is scattered out of the beam, leaving the red and orange wavelengths to dominate the light that reaches our eyes.
     1022
     1023So, the blue color of the sky is primarily due to the way shorter wavelength light is scattered by the Earth's atmosphere.
     1024
     1025--- Stats ---
     1026Time taken: 29.18 seconds
     1027Throughput: 5.04 tokens/sec
     1028-------------
     1029
     1030You: exit
     1031}}}
     1032
     1033
     1034=== Web based python eIQ chatbot (webchat.py)
     1035This is a web based chatbot in python using eIQ AAF Connector
     1036
     1037 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need:
     1038{{{#!bash
     1039# create a dir for the venv
     1040mkdir webchat
     1041cd webchat
     1042# create a venv (.venv)
     1043uv venv
     1044# install our scripts dependencies
     1045uv pip install -q fastapi psutil uvicorn
     1046}}}
     1047 1. fetch the script
     1048{{{#!bash
     1049wget https://dev.gateworks.com/ara/examples/webchat.py
     1050}}}
     1051 1. run the script
     1052{{{#!bash
     1053uv run webchat.py
     1054}}}
     1055 1. Open a web browser to your boards IP address port 8080: http://<ipaddr>:8080
     1056
     1057Notes:
     1058 * By default this will listen for HTTP requests on port 8080
     1059 * On startup it will enable the model (specified in the script) and restart the eIQ server if needed - waiting for the model to load may take several minutes
     1060
     1061
     1062[=#vlm]
     1063=== Web based python VLM eIQ example (webvlm.py)
     1064The eIQ AAF Connector can be used to analyze video and images.
     1065
     1066Here is an example of a headless web-app based off NXP's [https://github.com/nxp-imx-support/vlm-edge-studio/tree/main/src vlm-edge-studio example] using:
     1067 - Qwen2.5-VL-7B-Instruct-Ara240
     1068 - eIQ AAF Connector
     1069
     1070Requirements:
     1071 - Ara runtime
     1072 - eIQ AAF Connector
     1073 - Qwen2.5-VL-7B-Instruct-Ara240 model
     1074
     1075Steps:
     1076 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need:
     1077{{{#!bash
     1078# create a dir for the venv
     1079mkdir webvlm
     1080cd webvlm
     1081# create a venv (.venv)
     1082uv venv
     1083# install our scripts dependencies
     1084uv pip install -q httpx uvicorn fastapi argparse
     1085}}}
     1086 1. fetch the script
     1087{{{#!bash
     1088wget https://dev.gateworks.com/ara/examples/webvlm.py
     1089}}}
     1090 1. run the script
     1091{{{#!bash
     1092uv run webvlm.py --video-dir /usr/share/media/sample_videos/
     1093}}}
     1094 1. Open a web browser to your boards IP address port 8080: http://<ipaddr>:8080
     1095
     1096Notes:
     1097 * By default this will listen for HTTP requests on port 8080
     1098 * On startup it will enable the model (specified in the script) and restart the eIQ server if needed - waiting for the model to load may take several minutes
     1099
     1100
     1101[[Image(vlm-webapp.jpg,400px)]]
     1102
     1103
     1104== Troubleshooting
     1105
     1106Please note software support should be routed through NXP, who produces the Ara240 DNPU Chip and Software SDK.
     1107
     1108[https://community.nxp.com]
     1109