FreeRTOS on the ARM Automotive Kit (NXP S32Z2) =============================================== Status note ----------- This page records hardware bring-up design notes for the ``freertos-s32z2`` target. It is intentionally lower-level than the user guide and may reference NXP-generated/private files or bench scripts that are not present in the public repository. For the supported build entry point and current user workflow, see :doc:`/user_guide/freertos_s32z2`. This document records the design of Phase 5 of the FreeRTOS port: bringing the actuation firmware to the ARM Automotive Kit (X-S32Z27X-DC, NXP S32Z2, Cortex-R52). Issue: ``autowarefoundation/autoware-safety-island#1``. Scope ----- The kit runs FreeRTOS with feature parity to the existing Zephyr backend on the same SoC: - Cortex-R52 RTU0, lock-step mode (reset default). - FreeRTOS V11.1.0 via NXP's Real-Time Drivers (RTD) Cortex-R52 port. - lwIP socket layer, BSD-socket-compatible, driving the NETC Ethernet controller. - CycloneDDS cross-compiled statically into the firmware image. - ``DDS_ONLY`` control-command output mode; CAN is not validated on the kit in Phase 5. - 150 ms periodic controller loop, identical to the Zephyr backend. Out of scope: eSync OTA, Linux-side Autoware integration, CAN frame observation, Phase 6 tuning, an on-hardware CI job, migration to the Phase 2 stack (issue #14). Build tree layout ----------------- The Phase 5 build is an additional CMake entry point under ``actuation_module/freertos_s32z2/`` that does not modify the existing ``actuation_module/freertos/`` POSIX-simulator build, the Zephyr boards under ``actuation_module/boards/``, or the PAL backend headers under ``actuation_module/include/platform/freertos/*.h``. The intended hardware path may add S32Z2-specific variant headers under ``actuation_module/include/platform/freertos/s32z2/`` when carrying the lwIP bring-up forward. The intended hardware networking path uses an S32Z2-specific FreeRTOS network backend. In the public tree, ``platform_network.h`` still dispatches FreeRTOS targets through ``platform/freertos/freertos_network.h``; update this dispatcher and the matching backend when carrying the S32Z2 lwIP bring-up path forward. Boot bring-up (B-1) ------------------- ``board_init()`` calls ``Mcu_Init`` / ``Platform_Init`` / ``Port_Init`` from the RTD, brings UART9 up at 115200 8N1, and registers the PIT as the FreeRTOS tick source. ``configCPU_CLOCK_HZ`` matches the clock programmed by ``Mcu_Init``. Newlib's ``_write`` is retargeted to UART9 so ``printf`` reaches the FT232RQ serial port exposed as ``/dev/ttyUSB0`` on the carrier's J11 USB-C console (the OpenSDA debug probe exposes ``/dev/ttyACM0`` separately). A heartbeat task prints ``actuation alive ticks=N`` every 150 ms. The B-1 acceptance gate is the appearance of at least five such lines within ten seconds of reset. PB configuration prerequisite ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The NXP RTD MCAL drivers (``Mcu``, ``Clock_Ip``, ``Siul2_Port_Ip``, ``Uart``, ``Pit``) expect post-build configuration structures (``*_PBcfg.c``) that are generated by S32 Design Studio's S32 Config Tools from a ``.mex`` board configuration. The driver packages ship those structures as EB Tresos templates under ``$S32_RTD_PATH/RTD/_TS_*/generate_PB/src/``; the templates contain ``[!...!]`` markers that must be expanded by S32 Config Tools. Until the generated files exist, the firmware does not link. Workflow: 1. In S32 Design Studio 3.6.x, import or recreate the ``lwip_S32Z27X_FreeRTOS_R52`` example shipped at ``$LWIP_PATH/examples/S32Z270/lwip_S32Z27X_FreeRTOS_R52/`` as a starting point. 2. Open the project's ``.mex`` in the S32 Configuration Tools editor and configure clock ≥ 240 MHz, UART9 at 115200 8N1, PIT channel 0 as the tick, and Ethernet 0 enabled. 3. Use the *Update Code* action to expand the templates into the project's ``generate/src/*.c``, ``generate/include/*.h`` and ``board/`` directories. 4. Point ``S32CT_GENERATED_DIR`` at that project root; the build consumes ``generate/src``, ``generate/include`` and ``board``. The generated files inherit the NXP **Confidential and Proprietary** header from the RTD templates, so they are *not* committed to this public repository: they are bundled as the private ``s32ct_config`` submodule, or regenerated locally by developers without submodule access (see the README). Networking and DDS (B-2) ------------------------ The intended S32Z2 ``configure_network()`` path dispatches to an lwIP bring-up function that calls ``tcpip_init()``, registers the NETC driver via ``ethif_ethernetif_init`` (from the NXP ``eth_port.c`` glue, not the generic upstream ``ethernetif_init``) / ``netif_add``, requests DHCP, and blocks on a semaphore until a lease arrives. Keep the dispatcher and backend implementation in sync before treating this as current behavior. CycloneDDS is cross-compiled as a static library for Cortex-R52 with the upstream ``WITH_FREERTOS=ON`` and ``WITH_LWIP=ON`` options enabled (CycloneDDS ships dedicated ``sync/freertos.h`` and ``sockets/posix.h`` + lwIP backends — no patches required). Security, SSL, shared memory, IPv6, source-specific multicast, and network partitions are all disabled (see ``actuation_module/freertos_s32z2/scripts/build-cdds-target.sh``). The host ``idlc`` built by ``build.sh --platform freertos-s32z2`` is reused for IDL → C generation of ``autoware_msgs``. The cross-build needs two non-obvious workarounds: - ``-D__int64_t_defined=1`` — Ubuntu 24.04's ``libnewlib-arm-none-eabi`` 4.4.0 has a header-name mismatch in ``machine/_default_types.h`` (defines ``___int64_t_defined`` with three leading underscores) so ``inttypes.h`` never exposes ``PRId64`` / ``PRIu64``. Pre-defining the symbol works around the packaging bug. - ``-include inttypes.h`` plus ``-DUSING_RTD=1 -DS32Z27`` — the NXP-supplied lwIP ``arch/cc.h`` has a ``#ifdef USING_RTD`` branch that pulls in the RTD-friendly ``Devassert.h`` path instead of the toolchain-dependent ``device_registers.h`` path. The Edge ECU peer is the development host itself: ``dds_pub`` and ``dds_sub`` (unchanged) compile with host gcc against the host CycloneDDS and run as ``edge_ecu_pub`` / ``edge_ecu_sub``. The acceptance gates are: - ``Controller Node Started`` and ``Actuation Safety Island is Live`` appear on UART9. - ``edge_ecu_sub`` receives ``STEERING REPORT`` at least twice. - ``actuation_main`` does not return during the verification window. These are the same string markers used by the POSIX-simulator smoke (PRs #10 / #13). Flash workflow -------------- The kit is flashed via the NXP ``s32dbg`` debugger through ``west debug`` (the ``nxp_s32dbg`` runner does not implement the ``flash`` command). The driver scripts live in an out-of-tree ``MRM_repo/`` working directory on the dev host (the copy used for the production demo rig). ``MRM_repo/run_before.sh`` STEP 4 starts an Xvfb on ``DISPLAY=:99`` before STEP 5 invokes ``west_debug.sh`` — ``s32dbg`` is a GUI tool that aborts at SoC connect with ``CCS: connection to server refused`` when no X display is available, even in batch mode. From inside a Zephyr workspace whose ``runners.yaml`` selects ``nxp_s32dbg`` (the ``s32z270dc2_rtu0_r52@D`` board config does): .. code-block:: bash export DISPLAY=:99 pgrep -x Xvfb >/dev/null || \\ nohup Xvfb :99 -screen 0 1024x768x24 > /tmp/xvfb.log 2>&1 & source ~/zephyr-env/bin/activate west debug \\ --s32ds-path=/usr/local/NXP/S32DS.3.6.2 \\ -d build/actuation_module \\ --tool-opt='--batch' The ``--tool-opt='--batch'`` flag makes the GDB session non-interactive so the firmware is loaded, the entry breakpoint is released, and control returns to the shell after the kit starts running. A successful run loads roughly 1.2 MB in 6 s and shortly afterwards ``/dev/ttyUSB0`` prints ``Starting Controller Node...``, ``Controller Node Started`` and ``Actuation Safety Island is Live``. When the SoC connection still fails after Xvfb is up, clean up residual debugger state per the demo's retry recipe (``pkill -9 -f '(gta|s32dbg|arm-none-eabi-gdb)'``, ``rm -rf /tmp/*nxp_s32dbg*``, free TCP/45000) and retry. If three retries fail, the SoC is unreachable for physical reasons: power, J6 JTAG seating, J14 jumper, J17/J18 boot mode, or the front-panel S2 reset. References ---------- - NXP S32Z2 product page: https://www.nxp.com/products/S32Z2 - S32Z2 block diagram: https://www.nxp.com/assets/block-diagram/en/S32Z2.pdf - X-S32Z27X-DC Zephyr docs (cross-reference for hardware wiring): https://docs.zephyrproject.org/latest/boards/nxp/s32z2xxdc2/doc/index.html - How to download RTD: https://www.nxp.com/company/about-nxp/smarter-world-videos/HOW-TO-DWLD-RTD