foxBMS 2 Integration — Findings & Setup (2026-03-20)

Note: This document contains historical findings from the integration process. Some sections describe approaches that were later abandoned (e.g., the FreeRTOS POSIX port with 7 pthreads was replaced by a cooperative main loop). See STATUS.md for the current architecture and PLAN.md for remaining work.

foxBMS Unit Test Infrastructure (Windows PC)

Tools Installed

GCC 15 Compatibility Fixes (conf/unit/app_project_win32.yml)

Added to :flags: :test: :compile: :*::

- -Wno-enum-conversion        # enum type mismatch in mock returns
- -Wno-incompatible-pointer-types  # pointer type differences
- -Wno-attributes             # section attribute conflicts in FreeRTOS MPU
- -Wno-unterminated-string-initialization  # string init without NUL
- -Wno-absolute-value         # abs() with time_t argument
- -fcommon                    # multiple definition of tentative globals

paths_win32.txt Changes

Changed mingw path from C:\foxbms\mingw-w64\x86_64-8.1.0-release-posix-seh-rt_v6-rev0\bin to C:\tools\msys64\ucrt64\bin

Build Commands

# Must add gcovr to PATH first
export PATH="<PYTHON_PATH>/Scripts:$PATH"

# Configure (once)
python fox.py waf configure

# Run all tests (clean first if stale cache suspected)
python fox.py waf clean_app_host_unit_test
python fox.py ceedling test:all

# Run single test
python fox.py ceedling test:test_bms

Critical Lesson: Always Clean Before Full Test Run

Stale Ceedling build cache causes mock generation to fail silently for files with hyphens in names (e.g., can_cbs_tx_crash-dump.h). After clean_app_host_unit_test, all 183+ tests pass. Without clean, 11 tests fail with "No such file" for mock headers.

Test Results: 100% PASS (after clean + GCC 15 fixes)

All non-AFE-vendor tests pass. ADI ADES1830 tests also pass after clean.

foxBMS CAN Message Map (for Plant Model)

RX: Plant → foxBMS (must send)

CAN ID Message Period Endianness DLC
0x210 BMS State Request aperiodic Big 8
0x270 AFE Cell Voltages periodic Big 8
0x280 AFE Cell Temperatures periodic Big 8
0x521 IVT String0 Current periodic Big 6
0x522 IVT String0 Voltage1 periodic Big 6

TX: foxBMS → Plant (will receive)

CAN ID Message Content
0x220 BMS State Operating state
0x221 BMS State Details Detailed state info
0x231 Pack Min/Max Values Min/max cell voltages
0x232 Pack Limits Current/voltage limits
0x233 Pack Values P0 Pack voltage, current
0x234 Pack Values P1 Additional pack data
0x235 Pack State Estimation SOC/SOE
0x240 String State Contactor/string state
0x241 String Min/Max Per-string min/max
0x243 String Values P0 String voltage
0x244 String Values P1 String current
0x245 String State Estimation Per-string SOC
0x250 Cell Voltages Individual cell V
0x260 Cell Temperatures Individual cell T

Cell Voltage Message Format (0x270)

BMS Configuration (conf/bms/bms.json)

foxBMS Hardware Port (TMS570 LaunchPad) — Status

What Works

What Blocks Boot

TMS570 LaunchPad Hardware Findings

foxBMS on Ubuntu Laptop

foxBMS POSIX vECU — WORKING (2026-03-20)

Achievement

foxBMS 2 v1.10.0 running as a native Linux x86-64 process on Ubuntu laptop. Sends CAN messages (0x220 BMS State, 0x600/0x601 debug AFE) on vcan0.

How It Works

Files (in foxbms-2/posix/)

Excluded Source Files (variants we don't use)

Build & Run

cd /home/an-dao/foxbms-2/posix
make -j4                              # Build
sudo ip link add vcan0 type vcan      # Create virtual CAN
sudo ip link set vcan0 up
./foxbms-vecu                         # Run (Ctrl+C to stop)
candump vcan0                         # See CAN output in another terminal

Environment Variable

FOXBMS_CAN_IF=can0 to use real CAN instead of vcan0

foxBMS POSIX vECU — CAN TX VERIFIED (2026-03-20 late)

Proof

(000.000000)  vcan1  222   [8]  01 00 00 00 00 00 00 00

foxBMS CAN ID 0x222 captured on isolated vcan1 with candump. No other processes on this bus.

Fixes Required for FreeRTOS POSIX Port

  1. Engine task vTaskDelay(10): Engine runs at REAL_TIME priority. Without delay, it monopolizes CPU and lower-priority tasks never run.
  2. All busy-waits need vTaskDelay(1): foxBMS uses while(condition) {} busy-waits between task phases. POSIX port's signal-based preemption doesn't interrupt these.
  3. portGET_HIGHEST_PRIORITY macro: ARM CLZ instruction replaced with __builtin_clz for x86.
  4. Early SocketCAN open: foxBMS sends CAN before SYS state machine calls canInit(). Open socket in constructor.
  5. SPS_Initialize stub: SPS driver accesses GIO hardware registers directly — must exclude sps.c and stub.
  6. SBC_GetState → RUNNING: System state machine waits for SBC. Bypass with #ifdef FOXBMS_POSIX.
  7. RTC_IsRtcModuleInitialized → true: State machine waits for RTC. Bypass.

Source Files Modified (on laptop, not committed upstream)

foxBMS POSIX vECU — FULLY RUNNING (2026-03-20 final)

Proof

 (000.000000)  vcan1  222   [8]  42 00 00 00 00 00 00 00
 (000.000142)  vcan1  222   [8]  44 00 00 00 00 00 00 00
 (000.240355)  vcan1  222   [8]  54 00 00 00 00 00 00 00
 (000.456715)  vcan1  222   [8]  35 00 00 00 00 00 00 00
 (000.951944)  vcan1  222   [8]  06 00 00 00 00 00 00 00

Multiple CAN 0x222 frames on isolated vcan1.

Working Architecture: Cooperative Mode (No FreeRTOS Scheduler)

SYS State Machine

Excluded Source Files (hardware-dependent)

Key Lesson: FAS_ASSERT = NO_OPERATION

foxBMS has ~100+ assert checks during init for hardware that doesn't exist on POSIX. With assert level 0 (infinite loop), ANY hardware-related check hangs forever. Setting FAS_ASSERT_LEVEL=2 (no-op) lets foxBMS continue past all hardware checks and reach the running state.

foxBMS POSIX — BMS in IDLE State, SOC 50% (2026-03-21)

Achieved

Fixes Applied

Next Steps