Skip to main content

Aidge logo

EPL 2.0 Examples PyPi Examples Documentation Status GitLab Contributors Open GitLab Issues Closed GitLab Issues

Aidge Export for ARM CortexM systems

This plugin allow Aidge to create exports for ARM CortexM systems. It generates standalone C/C++ code intended to run on STM32 targets.

pip install aidge_export_arm_cortexm

Examples

If you want to generate exports and/or better understand how it works in Aidge, you may take a look at the following resources :

Supported targets

  • STM32F746
  • STM32H743
  • STM32L4R5
  • STM32F413

Additional targets can be added upon request. Normally, any recent STM32 board should be compatible with the generated code. You must only ensure that the corresponding pack is installed in pyOCD (e.g., stm32h743zitx for NUCLEO-H743ZI), the board_config.json file is properly configured for your board, along with the respective hardware configuration (RAM/Flash size, UART settings, etc.) along with a template project for your board in aidge/aidge_core/aidge_core/hw_model/targets.

Backends

This export provides two backends:

  • arm_cortexm: Provides specific optimizations for Convolution and Fully Connected (FC) layers, and is largely based on the aidge_export_cpp backend.

  • CMSIS-NN: Relies on the optimized kernels provided by CMSIS-NN.

Supported layers

arm_cortexm backend

Layer Supported
Convolution ✔️
Depthwise Convolution ✔️
Convolution Transpose ✔️
Fully Connected ✔️

CMSIS-NN backend

Layer Supported
Add ✔️
Mul
Convolution ✔️
Depthwise Convolution ✔️
Fully Connected ✔️
Average Pooling ✔️
Max Pooling ✔️
Global Average Pooling ✔️
Concat
Reshape
Softmax

[!NOTE]:

  • If your model contains unsupported operators, the export will still work. In that case, the implementation from the aidge_export_cpp module will be used.
  • The CMSIS-NN backend only supports quantized models (int8).

Examples

Several example scripts are available in aidge/examples.

Model arm_cortexm CMSIS-NN Notes
LeNet ✔️ ✔️
Deep Autoencoder ✔️ 🔶 Generation works, but slight output differences are observed on the last FC layer
DS-CNN ✔️ ✔️
MobileNetV1 VWW ✔️ ✔️
ResNet8 ✔️ 🔶 Generation works, but slight output differences are observed on the third convolution

Running an example

First of all, please make sure to execute the setup.sh script inside your target folder (eg. aidge/aidge_core/aidge_core/hw_model/targets/stm32/stm32h7/stm32h743/board_files/setup.sh) before trying to build for the first time. This will download the Drivers/HAL files directly from ST repository.

Then, navigate to the root of the repository and run the following command to execute the LeNet example:

cd aidge/examples/benchmark

Run the Python script:

python benchmark_model.py --profiling --board stm32h7 --model_path lenet_mnist

Run python <model>.py --help to see all available options. The script will generate the export, compile it, flash it on the board, and capture the UART output to measure inference time and perform some benchmarking. Some chats will be generated with the results of the benchmark, and the raw output will be stored in export_folder/uart_output.txt. By default, the compilation will be done using a docker container, but you can also choose to compile it locally by installing the required toolchain (e.g., arm-none-eabi-gcc for STM32 targets) and running the command with the --no_docker flag.

Running an tinyML benchmark

This module also provides a template for running the tinyMLPerf benchmark. The benchmark can be executed for the following models:

Model Dataset Notes
Deep AutoEncoder ToyADMOS
DS-CNN Speech Commands
MobileNetV1 VWW Visual Wake Words
ResNet8 Cifar10

Each dataset can be evaluated in terms of accuracy and inference time. For the moment, the evaluation of power consumption is not supported, since it relies on external hardware to do the measurement. In order to run the benchmark, you can use the following command :

python benchmark_model.py --board stm32h7 --model_path resnet8_cifar10 --tinymlbenchmark

This will create a different main file that communicates with the tinyML framework to perform the evaluation. Once you have flashed the board, you need to cancel the execution of the script (CTRL+C), and follow the instructions provided by tinyML to run the benchmark.

git clone https://github.com/mlcommons/tiny.git
cd tiny

# Install dependencies into virtual environment
python -m venv .venv
source .venv/bin/activate  # On Windows, use `.venv\Scripts\activate`
pip install -r benchmark/training/streaming_wakeword/requirements.txt pyusb libusb

To execute the benchmark itself, you'll first need to generate the dataset samples. Each folder inside tiny/benchmark/training/ contains the instructions to download and generate the samples for each model. For example, for the MobileNetV1 VWW model, you can run:

cd benchmark/training/visual_wake_words
./download_and_train_vww.sh
python generate_y_labels.py

Note: This procedure may change in the future, so please refer to the official tinyML repository for the most up-to-date instructions on dataset generation and benchmark execution.

Once you have generated the dataset samples (and placed them in the correct directory, which is tiny/evaluation/datasets/), you can run the benchmark using the command provided above.

cd benchmark/runner
python main.py --dataset_path=../evaluation/datasets/ --test_script=tests_accuracy.yaml --device_list=devices_kws_ic_vww.yaml --mode=a # for accuracy evaluation
python main.py --dataset_path=../evaluation/datasets/ --test_script=tests_performance.yaml --device_list=devices_kws_ic_vww.yaml --mode=p # for performance evaluation

This will generate a report with the results of the benchmark in tiny/runner/sessions/.

Flashing through an API

It is also possible to use the flashing and UART capture functionalities of this module through an API. Basically, instead flashing the board locally, the export will generate a .elf file that will then be flashed by the API using pyOCD. The API is available in the (repository)[https://gitlab.eclipse.org/antoniopereira/api_board_farms], along will all the necessary instructions. Once everything is set up, you can run the same example script as before, but with the --backend api flag:

cd aidge/examples/benchmark
python benchmark_model.py \
  --board stm32h7 \
  --backend api \
  --api-url http://127.0.0.1:8000 \
  --api-username admin \
  --api-password changeme \
  --api-board-name stm32h7_lab_01
  --model_path lenet_mnist

Benchmarks with ST Edge AI Developer Cloud (STZooAPI)

You can also compare your model's performance against the ST Edge AI Developer Cloud using the stzooapi backend. This backend uploads your model to ST's cloud services and benchmarks it on their remote board farms.

Installation

To use this feature, you must install the stm32ai-dc Python package:

pip install pycurl seaborn numpy matplotlib ipywidgets gitdir shutils marshmallow tqdm
gitdir https://github.com/STMicroelectronics/stm32ai-modelzoo-services/tree/main/common/stm32ai_dc

Usage

You can use the benchmark_interface.py script (found in examples/) to compare onnxruntime, aidge_backend_cpu, and aidge_export_arm_cortexm with the ST Cloud results:

python examples/benchmark_interface.py \
  --stmai-username your_email@st.com \
  --stmai-password your_password \
  --stmai-board B-U585I-IOT02A

Note: You need an active account on ST Edge AI Developer Cloud. You can also check the boards available on their website.

Installation

Prerequisite:

  • pyocd >= 0.35.0
  • pyserial >= 3.5
pip install aidge_export_arm_cortexm

🛠 Build from Source

Prerequisite (in addition to previous one):

1. Python installation using setup scripts
Environment Python Development
Windows .\setup.ps1 -Modules backend_cpu -Tests
Unix ./setup.sh -m backend_cpu --tests

[!TIP] Use Get-Help setup.ps1 (Win) or ./setup.sh -h (Unix) for full documentation.

2. Python Installation using pip

Run these commands from the aidge_export_arm_cortexm/ directory:

#fStandard install
pip install . -v

# Install with testing dependencies
pip install .[test] -v && pytest

Manual download of HAL/Drivers files

Recently, we have changed the way we handle the HAL/Drivers files for STM32 boards. Now, these files are not included in the repository and must be downloaded manually. For each board in th hardware model, there is a setup.sh script that will download the necessary files from the ST repository. You must run this script before the first compilation. For example, for the STM32H7 board, you can run:

cd aidge/aidge_core/aidge_core/hw_model/targets/stm32/stm32h7/stm32h743/board_files
./setup.sh

Since every board has its own setup script, please make sure to run the script corresponding to your board before trying to compile the code.

Manual update of the STM32 pack is required

By default, pyOCD does not include all STM32 packs. The pack corresponding to NUCLEO-H743ZI (stm32h743zitx) must be installed manually:

pyocd pack install stm32h743zitx

This operation can take several minutes.

Verify that the board is correctly detected

If you are on Windows, make sure you installed the ST-LINK USB Driver that you can find on ST website.

Then connect your board via USB and run:

pyocd list

Expected output example:

  #   Probe/Board     Unique ID                  Target 
------------------------------------------------------------------
  0   STM32 STLink    066DFF343339415043185830   ✔︎ stm32h743zitx 
      NUCLEO-H743ZI

If you see a green check ✔︎, the board is properly detected. If you see a red cross x, manually install the pack as described above.

A permissions issue with PyOCD: "No available debug probes are connected"

If running the following command results in an error:

pyocd list

No available debug probes are connected

but your STM32 device is visible via lsusb, this may be due to missing USB permissions.

Follow these steps to fix the issue :

  • Create a new udev rule:

    sudo nano /etc/udev/rules.d/50-st-link.rules

  • Paste this content:

    SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="374b", MODE="0666"

  • Reload udev and trigger:

    sudo udevadm control --reload-rules

    sudo udevadm trigger

  • Unplug and replug your STM32 device.

  • Try again:

    pyocd list

    You should now see your board listed.


Important notes

Serial Port: "Permission denied: '/dev/ttyACM0'"

If you see an error like this when trying to flash :

Error connecting to serial port: [Errno 13] could not open port /dev/ttyACM0: [Errno 13] Permission denied: '/dev/ttyACM0'

This usually means your user doesn't have the right permissions for serial access.

For fix that you have to add your user to the dialout group :

sudo usermod -a -G dialout $USER

Then Restart your terminal for the change to take effect

Capture timeout and longer UART output

  • When measuring inference time using multiple forward calls, capture times may increase. To avoid premature interruption of the capture process, it is important to increase uart_capture_duration in the board_config.json accordingly (e.g., from 30s to 60 or more),

Retrying flash in case of UART failure

  • The flashing process now includes a retry mechanism:
    if the UART output file is missing or empty, the firmware is reflashed up to 5 times by default (this can be changed via the MAX_RETRIES constant in the code).

  • This improves robustness against rare flashing issues caused by the pyOCD library, where firmware may not start correctly despite successful flashing.

  • A special end keyword (default: "DEMO END") is now expected in the UART output to determine when inference is complete and to stop UART capture.

  • The file uart_output.txt is automatically generated during execution and placed in the export_folder.

  • An export_log.log file is generated at compilation to store the build logs.

  • The board_config.json file is essential for configuring board flashing. When testing dimensions like [16], you must increase uart_capture_duration to at least 60 or more.


Limitations

1. Memory limitations (RAM / Flash)

  • From dimensions like [32, 32, 32, 32] (e.g., for ReLU), compilation errors or RAM/Flash overflows may occur.
  • It is recommended to stay within maximum dimensions of 16, such as [1,1,1,1], [4,4,4,4], or [16,16,16,16].

Recommendations

  • Separate different tensor dimensions into different JSON config files.
  • Running benchmarks individually helps reduce flashing failures.
  • Increase uart_capture_duration when working with large output tensors.

License

Aidge has a Eclipse Public License 2.0, as found in the LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aidge_export_arm_cortexm-0.10.0.post3-py3-none-any.whl (102.0 kB view details)

Uploaded Python 3

File details

Details for the file aidge_export_arm_cortexm-0.10.0.post3-py3-none-any.whl.

File metadata

File hashes

Hashes for aidge_export_arm_cortexm-0.10.0.post3-py3-none-any.whl
Algorithm Hash digest
SHA256 f649310f2ae8f3020697c0bc84fe10f21f2062a7f8fd0f220c54a177bc6fae55
MD5 36c0b3be8f1568c281b98aa37d4a673a
BLAKE2b-256 1899efcfc3d255081f5ba8970612ac776758420d92382c0f52da59df61359dc3

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.10.0.post3 This release

1 file

0.10.0.post2

1 file

0.10.0

1 file

0.9.1.post2

1 file

0.9.1

1 file

0.9.0.post3

1 file

0.9.0.post2

1 file

0.9.0

1 file

0.2.1

1 file

0.2.0

1 file

0.1.3

1 file

0.1.2

1 file

0.1.1

1 file

0.1.0

1 file

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page