$npx -y skills add matlab/matlab-agentic-toolkit --skill matlab-deploy-embedded-codeDeploy MATLAB-generated code to embedded hardware using Embedded Coder. Use when configuring code generation for microcontrollers (STM32, Raspberry Pi, ARM Cortex), setting up PIL/SIL verification, disabling dynamic memory allocation, or configuring hardware-specific code generat
| 1 | # Deploy Embedded Code |
| 2 | |
| 3 | Configure MATLAB Coder with Embedded Coder for production-quality code generation |
| 4 | targeting embedded hardware, and verify correctness with processor-in-the-loop (PIL) |
| 5 | testing. |
| 6 | |
| 7 | ## When to Use |
| 8 | |
| 9 | - Generating C/C++ code for a microcontroller or embedded Linux board |
| 10 | - Setting up PIL or SIL verification for generated code |
| 11 | - Configuring code generation with no dynamic memory allocation |
| 12 | - Deploying deep learning models to resource-constrained hardware |
| 13 | - Selecting a hardware target board (STM32, Raspberry Pi) |
| 14 | |
| 15 | ## When NOT to Use |
| 16 | |
| 17 | - Generating MEX or desktop libraries — use standard `codegen` workflows |
| 18 | - Simulink-based deployment — use Simulink Coder / Embedded Coder workflows directly |
| 19 | - GPU code generation (CUDA) — use GPU Coder |
| 20 | |
| 21 | ## Workflow |
| 22 | |
| 23 | ### 1. Create an ERT-Based Configuration |
| 24 | |
| 25 | ```matlab |
| 26 | cfg = coder.config("lib", "ecoder", true); |
| 27 | ``` |
| 28 | |
| 29 | The `"ecoder", true` flag creates an ERT-based (Embedded Real-Time) configuration |
| 30 | that generates production-quality code with no OS dependencies. |
| 31 | |
| 32 | ### 2. Select Target Hardware |
| 33 | |
| 34 | With `coder.hardware`: |
| 35 | |
| 36 | ```matlab |
| 37 | cfg.Hardware = coder.hardware("STM32F746G-Discovery"); |
| 38 | ``` |
| 39 | |
| 40 | Without the support package, configure hardware manually: |
| 41 | |
| 42 | ```matlab |
| 43 | cfg.HardwareImplementation.ProdHWDeviceType = 'ARM Compatible->ARM Cortex-M'; |
| 44 | cfg.HardwareImplementation.ProdBitPerFloat = 32; |
| 45 | cfg.HardwareImplementation.ProdBitPerDouble = 64; |
| 46 | ``` |
| 47 | |
| 48 | See `references/supported-hardware.md` for the full list of supported boards and |
| 49 | their constraints. |
| 50 | |
| 51 | ### 3. Configure Memory for Bare-Metal Targets |
| 52 | |
| 53 | ```matlab |
| 54 | cfg.EnableDynamicMemoryAllocation = false; |
| 55 | cfg.StackUsageMax = 512; |
| 56 | ``` |
| 57 | |
| 58 | - `EnableDynamicMemoryAllocation = false` — disables `malloc`/`free` for targets |
| 59 | where heap is unavailable or non-deterministic. All arrays must be bounded at |
| 60 | compile time. |
| 61 | - `StackUsageMax` — set based on target SRAM. The code generation report shows |
| 62 | actual usage after compilation. |
| 63 | |
| 64 | For entry-points that use deep learning inference (`invoke`, `predict`): |
| 65 | |
| 66 | ```matlab |
| 67 | cfg.DeepLearningConfig = coder.DeepLearningConfig('none'); |
| 68 | cfg.LargeConstantGeneration = "KeepInSourceFiles"; |
| 69 | ``` |
| 70 | |
| 71 | - `DeepLearningConfig('none')` — generates C with no external DL library dependencies |
| 72 | (MKL-DNN, cuDNN, TensorRT). Required for bare-metal targets. Without this, codegen |
| 73 | may attempt to link an unavailable library and fail. |
| 74 | - `LargeConstantGeneration = "KeepInSourceFiles"` — keeps weight constants in source |
| 75 | files rather than separate data files. Needed for bare-metal targets where external |
| 76 | data file linking is unsupported. |
| 77 | |
| 78 | ### 4. Configure Performance (SIMD and OpenMP) |
| 79 | |
| 80 | **SIMD vectorization** — generates vectorized code for the target ISA: |
| 81 | |
| 82 | ```matlab |
| 83 | cfg.InstructionSetExtensions = 'Neon v7'; % ARM Cortex-A (128-bit, 4x float32) |
| 84 | ``` |
| 85 | |
| 86 | | Target | Value | Notes | |
| 87 | |--------|-------|-------| |
| 88 | | ARM Cortex-A (Raspberry Pi) | `'Neon v7'` | 128-bit SIMD | |
| 89 | | Intel x86-64 | `'SSE'`, `'SSE4.1'`, `'AVX'`, `'AVX2'`, `'AVX512F'` | Match target CPU | |
| 90 | | ARM Cortex-M | Do not set — use `CodeReplacementLibrary` instead | Different mechanism | |
| 91 | |
| 92 | **OpenMP multi-threading** — enables parallel loops in generated code: |
| 93 | |
| 94 | ```matlab |
| 95 | cfg.EnableOpenMP = true; % multi-core targets (Cortex-A, x86) |
| 96 | cfg.EnableOpenMP = false; % single-core targets (Cortex-M) — no OS/threading support, won't compile |
| 97 | ``` |
| 98 | |
| 99 | ### 5. Set Up PIL Verification |
| 100 | |
| 101 | PIL compiles the generated code, deploys it to the physical board, sends test |
| 102 | vectors, and compares outputs against MATLAB. This catches precision differences, |
| 103 | stack overflows, and memory issues that SIL cannot detect. |
| 104 | |
| 105 | **Cortex-M (serial transport):** |
| 106 | |
| 107 | ```matlab |
| 108 | cfg.VerificationMode = "PIL"; |
| 109 | cfg.Hardware.PILInterface = "Serial"; |
| 110 | cfg.Hardware.PILCOMPort = "COM4"; % adjust to your system |
| 111 | ``` |
| 112 | |
| 113 | **Cortex-A / Raspberry Pi (SSH transport):** |
| 114 | |
| 115 | ```matlab |
| 116 | cfg.VerificationMode = "PIL"; |
| 117 | cfg.Hardware = coder.hardware("Raspberry Pi"); |
| 118 | cfg.Hardware.DeviceAddress = "192.168.1.10"; |
| 119 | cfg.Hardware.Username = "<your-pi-username>"; |
| 120 | cfg.Hardware.Password = "<your-pi-password>"; |
| 121 | cfg.Hardware.BuildDir = "/home/pi/mymodel"; % optional: defaults to /home/pi/MATLAB_ws/<release> |
| 122 | ``` |
| 123 | |
| 124 | Pi PIL runs over SSH (not serial). The support package uses `DeviceAddress`, |
| 125 | `Username`, and `Password` to establish the SSH connection. `BuildDir` specifies |
| 126 | where the compiled binary is deployed on the target; if omitted, defaults to |
| 127 | `/home/pi/MATLAB_ws/<release>/`. Do not set `PILInterface` or `PILCOMPort` — th |