Software Requirements Specification

Document ID Rev Date Classification
SWE.1-001 1.0 2026-03-21 Confidential

Revision History

Rev Date Author Reviewer Description
1.0 2026-03-21 An Dao -- Initial release

1. Purpose

This document specifies the software-level requirements for the foxBMS 2 POSIX port. Each requirement is derived from the system requirements in SYS.2-001 and is traceable forward to detailed design (SWE.3-001) and test cases (SWE.4-001 through SWE.6-001). This document satisfies ASPICE SWE.1 and ISO 26262 Part 6 Clause 6.

2. Scope

All software requirements for the BMS application, engine, and driver layers running on the POSIX SIL target.

3. References

ID Title
[SYS.2-001] System Requirements Specification
[SWE.2-001] Software Architecture Description
[SWE.3-001] Software Detailed Design
[ISO-SSR-001] Software Safety Requirements

4. Definitions

Term Definition
ASIL Automotive Safety Integrity Level
FATAL Highest DIAG severity; triggers ERROR state
DB entry A typed data structure in the foxBMS database

5. Safety Requirements

5.1 Voltage Safety

ID Requirement Derives From ASIL
SW-REQ-001 The SOA module shall compare each cell voltage against the overvoltage MSL threshold of 2800 mV. If any cell exceeds this value, SOA shall call DIAG_Handler with the CELL_VOLTAGE_OVERVOLTAGE_MSL event. SYS-REQ-020
↑ Traces Up
STKH-REQ-007
D
SW-REQ-002
↑ Traces Up
SYS-REQ-021TSR-001
The SOA module shall compare each cell voltage against the undervoltage MSL threshold of 1500 mV. If any cell falls below this value, SOA shall call DIAG_Handler with the CELL_VOLTAGE_UNDERVOLTAGE_MSL event. SYS-REQ-021 D
SW-REQ-003
↓ Traces Down
UT-010UT-011UT-016
The SOA module shall compare each cell voltage against the overvoltage RSL threshold of 2750 mV and MOL threshold of 2720 mV, reporting the corresponding events. SYS-REQ-020
↑ Traces Up
STKH-REQ-007
B
SW-REQ-004
↑ Traces Up
SYS-REQ-021
↓ Traces Down
UT-016
The SOA module shall compare each cell voltage against the undervoltage RSL threshold of 1550 mV and MOL threshold of 1580 mV, reporting the corresponding events. SYS-REQ-021 B
SW-REQ-005
↑ Traces Up
SYS-REQ-022
The SOA module shall detect deep discharge when any cell voltage falls to or below 1500 mV and report DEEP_DISCHARGE_DETECTED. This event shall latch and not auto-clear. SYS-REQ-022 D

5.2 Current Safety

ID Requirement Derives From ASIL
SW-REQ-010 The SOA module shall compare cell discharge current against MSL threshold of 180000 mA. If exceeded, SOA shall report OVERCURRENT_DISCHARGE_CELL_MSL. SYS-REQ-030
↑ Traces Up
STKH-REQ-008
D
SW-REQ-011
↑ Traces Up
SYS-REQ-031TSR-002
The SOA module shall compare cell charge current against MSL threshold of 180000 mA. If exceeded, SOA shall report OVERCURRENT_CHARGE_CELL_MSL. SYS-REQ-031 D
SW-REQ-012
↑ Traces Up
SYS-REQ-013
↓ Traces Down
SSR-003UT-020
The SOA module shall compare string current against the string overcurrent discharge and charge thresholds, reporting STRING_OVERCURRENT_DISCHARGE_MSL and STRING_OVERCURRENT_CHARGE_MSL respectively. SYS-REQ-013 D
SW-REQ-013
↑ Traces Up
SYS-REQ-014
↓ Traces Down
SSR-003UT-020
The SOA module shall compare pack current against the pack overcurrent thresholds, reporting PACK_OVERCURRENT_DISCHARGE_MSL and PACK_OVERCURRENT_CHARGE_MSL. SYS-REQ-014 D
SW-REQ-014
↑ Traces Up
SYS-REQ-013
↓ Traces Down
IT-039SSR-010UT-020
The SOA module shall detect current flow on an open string and report CURRENT_ON_OPEN_STRING. SYS-REQ-013 D

5.3 Temperature Safety

ID Requirement Derives From ASIL
SW-REQ-020 The SOA module shall compare each cell temperature against the overtemperature discharge MSL threshold of 55 deg C. If exceeded, SOA shall report TEMP_OVERTEMPERATURE_DISCHARGE_MSL. SYS-REQ-040
↑ Traces Up
STKH-REQ-009
D
SW-REQ-021 The SOA module shall compare each cell temperature against the undertemperature discharge MSL threshold of -20 deg C. If below, SOA shall report TEMP_UNDERTEMPERATURE_DISCHARGE_MSL. SYS-REQ-041
↑ Traces Up
STKH-REQ-010
D
SW-REQ-022 The SOA module shall compare each cell temperature against the overtemperature charge MSL threshold of 45 deg C. If exceeded, SOA shall report TEMP_OVERTEMPERATURE_CHARGE_MSL. SYS-REQ-042
↑ Traces Up
STKH-REQ-013
D
SW-REQ-023
↑ Traces Up
SYS-REQ-043TSR-003
The SOA module shall compare each cell temperature against the undertemperature charge MSL threshold of -20 deg C. If below, SOA shall report TEMP_UNDERTEMPERATURE_CHARGE_MSL. SYS-REQ-043 D

5.4 Diagnostic Handling

ID Requirement Derives From ASIL
SW-REQ-030 The DIAG module shall maintain a table of at least 85 diagnostic identifiers, each with a configurable threshold counter and evaluation delay. SYS-REQ-050, SYS-REQ-051, SYS-REQ-052
↑ Traces Up
STKH-REQ-009
D
SW-REQ-031 When DIAG_Handler is called for a diagnostic event, it shall increment the threshold counter for that event. When the counter reaches the configured threshold, the event shall be flagged as FATAL. SYS-REQ-053 D
SW-REQ-032 A FATAL diagnostic flag shall cause the BMS state machine to transition to the ERROR state within the next 100ms task cycle. SYS-REQ-053 D
SW-REQ-033 The DIAG module shall support a configurable evaluation delay per diagnostic ID. The handler shall not re-evaluate the same event more frequently than this delay. SYS-REQ-052
↑ Traces Up
STKH-REQ-009
C
SW-REQ-034
↓ Traces Down
UT-040
The POSIX port shall suppress 24 hardware-absent diagnostic IDs by setting their severity to non-FATAL or disabling evaluation. SYS-REQ-153
↑ Traces Up
STKH-REQ-010
↓ Traces Down
SW-REQ-034
QM
SW-REQ-035
↓ Traces Down
UT-040
The POSIX port shall retain 61 software-checkable diagnostic IDs with their original severity and thresholds. SYS-REQ-154
↑ Traces Up
STKH-REQ-010
↓ Traces Down
SW-REQ-035
D

5.5 BMS State Machine

ID Requirement Derives From ASIL
SW-REQ-040 The BMS state machine shall implement the states: STANDBY (5), PRECHARGE (6), NORMAL (7), ERROR (9). SYS-REQ-090
↓ Traces Down
SW-REQ-040
D
SW-REQ-041 Transition from STANDBY to PRECHARGE shall occur only upon receipt of a valid state request via CAN ID 0x210. SYS-REQ-091
↑ Traces Up
STKH-REQ-006
↓ Traces Down
SW-REQ-041
D
SW-REQ-042 Transition from PRECHARGE to NORMAL shall occur when precharge conditions are met (voltage within tolerance). SYS-REQ-092
↑ Traces Up
STKH-REQ-006
↓ Traces Down
SW-REQ-042
C
SW-REQ-043 Transition from any operational state to ERROR shall occur when any FATAL diagnostic flag is set. SYS-REQ-093
↑ Traces Up
STKH-REQ-006
↓ Traces Down
SW-REQ-043
D
SW-REQ-044 In ERROR state, the BMS shall command all three contactors (string+, string-, precharge) to open. SYS-REQ-054, SYS-REQ-114
↓ Traces Down
SW-REQ-044SW-REQ-201
D
SW-REQ-045 The BMS shall not exit ERROR state until both conditions are met: (a) the originating fault is cleared, and (b) an explicit STANDBY request is received via CAN. SYS-REQ-055
↑ Traces Up
STKH-REQ-013
, SYS-REQ-094
↓ Traces Down
SW-REQ-045SW-REQ-200
D

5.6 System State Machine

ID Requirement Derives From ASIL
SW-REQ-050
↓ Traces Down
IT-020UT-101
The SYS state machine shall implement states: UNINITIALIZED (0), INITIALIZATION (1), INITIALIZED (2), IDLE (3), RUNNING (5). SYS-REQ-080, SYS-REQ-081
↑ Traces Up
STKH-REQ-006
, SYS-REQ-082, SYS-REQ-083
C
SW-REQ-051 SYS shall transition from UNINITIALIZED to INITIALIZATION on system startup. SYS-REQ-080 C
SW-REQ-052 SYS shall transition from INITIALIZATION to INITIALIZED after all module initialization completes successfully. SYS-REQ-081
↑ Traces Up
STKH-REQ-006
C
SW-REQ-053
↓ Traces Down
IT-020
SYS shall transition from IDLE to RUNNING when all subsystems report ready. SYS-REQ-083 C

6. Functional Requirements

6.1 Database

ID Requirement Derives From ASIL
SW-REQ-060 The database module shall enforce single-writer-per-entry at architecture level. Each DATA_BLOCK_ID shall have exactly one producer module. If a second producer attempts to write the same entry, the behavior is undefined and shall be prevented by design review. Acceptance: static analysis confirms no DATA_BLOCK_ID is written by more than one module. DIAG on failure: N/A (design-time constraint). SYS-REQ-060 C
SW-REQ-061
↓ Traces Down
UT-041UT-042
Database read operations (DATA_READ_DATA) shall return the most recent complete snapshot. Partial writes shall not be visible to readers. The database engine shall use double-buffering or equivalent to guarantee atomicity. Acceptance: concurrent write + read test shows no torn data over 10,000 iterations. DIAG on failure: N/A (structural guarantee). SYS-REQ-060 C
SW-REQ-062 The database shall provide DATA_BLOCK_ID_CELL_VOLTAGE containing 18 cell voltages as uint16_t in millivolts (mV), one per cell index [0..17]. Acceptance: writing 3700 mV to cell index 5, then reading back, returns exactly 3700. DIAG on failure: N/A. SYS-REQ-001
↑ Traces Up
STKH-REQ-001
, SYS-REQ-002
↑ Traces Up
STKH-REQ-002
, SYS-REQ-003
↑ Traces Up
STKH-REQ-003
, SYS-REQ-004
↑ Traces Up
STKH-REQ-004
, SYS-REQ-005, SYS-REQ-006, SYS-REQ-007, SYS-REQ-010
↑ Traces Up
STKH-REQ-005
, SYS-REQ-011
↑ Traces Up
STKH-REQ-006
, SYS-REQ-012, SYS-REQ-013, SYS-REQ-014, SYS-REQ-015, SYS-REQ-016
B
SW-REQ-063 The database shall provide DATA_BLOCK_ID_CELL_TEMPERATURE containing 8 temperature sensor readings as int16_t in deci-degrees Celsius (ddegC). Acceptance: writing 250 ddegC (25.0 C) to sensor index 3, then reading back, returns exactly 250. DIAG on failure: N/A. SYS-REQ-003
↑ Traces Up
STKH-REQ-003
, SYS-REQ-004
↑ Traces Up
STKH-REQ-004
B
SW-REQ-064 The database shall provide DATA_BLOCK_ID_CURRENT_SENSOR containing: current (int32_t, mA), voltage1/voltage2/voltage3 (int32_t, mV), power (int32_t, mW), and temperature (int16_t, ddegC). Acceptance: writing current=5000 mA, reading back returns 5000. DIAG on failure: N/A. SYS-REQ-005, SYS-REQ-006, SYS-REQ-007 B
SW-REQ-065 The database shall provide DATA_BLOCK_ID_SOC containing SOC percentage, SOE percentage, and min/max/avg values per string. Acceptance: after SOC algorithm writes 50.0%, read returns 50.0%. DIAG on failure: N/A. SYS-REQ-010
↑ Traces Up
STKH-REQ-005
, SYS-REQ-011
↑ Traces Up
STKH-REQ-006
B
SW-REQ-066 The database shall provide DATA_BLOCK_ID_BALANCING_CONTROL containing a per-cell balancing flag (one bit per cell, 18 cells). Acceptance: setting flag for cell 7 and reading back shows cell 7 active, all others inactive. DIAG on failure: N/A. SYS-REQ-003
↑ Traces Up
STKH-REQ-003
QM
SW-REQ-067 The database shall provide DATA_BLOCK_ID_CONTACTOR_FEEDBACK containing per-contactor state for string-plus, string-minus, and precharge contactors. Acceptance: writing CLOSED for string-plus, reading back returns CLOSED. DIAG on failure: N/A. SYS-REQ-054 C
SW-REQ-068 A producer shall write data by calling DATA_WRITE_DATA(), which enqueues the data block. The database engine task (FTSK_RunUserCodeEngine) shall dequeue and apply writes via DATA_IterateOverDatabaseEntries(). Acceptance: data written in CAN RX callback is readable by SOA within the same 10 ms cycle. DIAG on failure: N/A. SYS-REQ-060 C
SW-REQ-069 A consumer shall read data by calling DATA_READ_DATA(), which copies the latest complete snapshot into the caller's buffer. The caller receives a consistent view even if the producer writes concurrently. Acceptance: reader never observes a mixture of old and new field values across a single read. DIAG on failure: N/A. SYS-REQ-060 C
SW-REQ-06A
↑ Traces Up
SYS-REQ-151
On the POSIX port, DATA_WRITE_DATA() and DATA_READ_DATA() shall execute as direct synchronous calls (no FreeRTOS queue). DATA_IterateOverDatabaseEntries() shall be called synchronously within the engine task slot. Acceptance: database functional without FreeRTOS queue primitives on POSIX build. DIAG on failure: N/A. SYS-REQ-151 QM

6.2 SOC Estimation

ID Requirement Derives From ASIL
SW-REQ-070
↓ Traces Down
IT-011UT-070
The SOC algorithm module shall compute state of charge using coulomb counting: SOC(t) = SOC(t-1) - (I_mA x dt_ms) / (Capacity_mAh x 3600000). The current (I_mA) shall be read from DATA_BLOCK_ID_CURRENT_SENSOR. Acceptance: at 1000 mA discharge for 3600 s with 1000 mAh capacity, SOC decreases from 100% to 0%. DIAG on failure: N/A. SYS-REQ-130
↑ Traces Up
STKH-REQ-008
↓ Traces Down
SW-REQ-070
B
SW-REQ-071 The SOC module shall initialize SOC to 50% at startup. Acceptance: on first algorithm cycle, SOC_avg reads 50.0%. DIAG on failure: N/A. SYS-REQ-131
↑ Traces Up
STKH-REQ-008
↓ Traces Down
SW-REQ-071
B
SW-REQ-072 The SOC module shall execute in the algorithm 100 ms task (FTSK_RunUserCodeCyclicAlgorithm100ms), updating SOC every 100 ms. Acceptance: SOC timestamp increments by ~100 ms between consecutive updates. DIAG on failure: N/A. SYS-REQ-134
↑ Traces Up
STKH-REQ-008
↓ Traces Down
SW-REQ-072
B
SW-REQ-073 The SOC module shall clamp the computed SOC to the range [0, 100] percent. Values below 0 shall be set to 0; values above 100 shall be set to 100. Acceptance: injecting a large negative current that would drive SOC below 0 results in SOC = 0.0%, not a negative value. DIAG on failure: N/A. SYS-REQ-133
↑ Traces Up
STKH-REQ-008
↓ Traces Down
SW-REQ-073
B
SW-REQ-074 The CAN TX callback for CAN ID 0x235 shall encode SOC_avg as byte 5 with factor 0.5 (raw = SOC% x 2). A SOC of 50% shall produce raw value 0xC8 (100 decimal). A SOC of 0% shall produce 0x00. A computed SOC of 101% (before clamping) shall be clamped to 100% and encoded as 0xC8. Acceptance: decode(encode(50.0)) == 50.0. DIAG on failure: N/A. SYS-REQ-132
↑ Traces Up
STKH-REQ-008
↓ Traces Down
SW-REQ-074
, SYS-REQ-066
↑ Traces Up
STKH-REQ-007
↓ Traces Down
SW-REQ-074SW-REQ-095
B
SW-REQ-075 The SOE algorithm shall compute state of energy as: SOE = SOC x cell_energy x n_cells, where cell_energy is derived from the voltage-energy lookup. SOE shall be written to DATA_BLOCK_ID_SOC. Acceptance: at SOC=100% with nominal cell energy, SOE equals total pack energy. DIAG on failure: N/A. SYS-REQ-011
↑ Traces Up
STKH-REQ-006
B
SW-REQ-076
↑ Traces Up
SYS-REQ-012
The SOF (state of function) algorithm shall compute charge and discharge power limits based on current cell voltage, temperature, and SOC. Limits shall be written to the database for CAN transmission. Acceptance: at SOC=5%, discharge power limit is reduced relative to SOC=50%. DIAG on failure: N/A. SYS-REQ-012 B

6.3 Balancing

ID Requirement Derives From ASIL
SW-REQ-080
↓ Traces Down
UT-080
The balancing module shall support three strategy selections: voltage-based (default), history-based, and none. The active strategy shall be selected at compile time via configuration. Acceptance: building with BAL_STRATEGY_VOLTAGE produces voltage-based balancing behavior. DIAG on failure: N/A. SYS-REQ-120 QM
SW-REQ-081 In voltage-based strategy, the balancing module shall activate balancing for any cell whose voltage exceeds V_min + BAL_GetBalancingThreshold_mV() (default 50 mV). V_min is the minimum cell voltage across the string. Acceptance: with cells at [3700, 3700, 3760] mV and threshold=50 mV, cell 2 (3760 mV > 3700+50=3750 mV) is flagged for balancing. DIAG on failure: N/A. SYS-REQ-120 QM
SW-REQ-082
↑ Traces Up
SYS-REQ-121
The balancing module shall implement hysteresis for deactivation: a cell's balancing shall deactivate only when its voltage falls below V_min + BAL_GetBalancingThreshold_mV() - BAL_HYSTERESIS_mV. This prevents oscillation at the threshold boundary. Acceptance: a cell at exactly threshold activates; it does not deactivate until it drops below (threshold - hysteresis). DIAG on failure: N/A. SYS-REQ-121
↓ Traces Down
SW-REQ-082
QM
SW-REQ-083 The balancing module shall activate balancing only when: (a) the BMS state machine is in NORMAL state, and (b) the absolute string current is below BS_REST_CURRENT_mA (200 mA). Acceptance: with BMS in STANDBY, no balancing flags are set regardless of voltage spread. With BMS in NORMAL and I =500 mA, no balancing flags are set. DIAG on failure: N/A.
SW-REQ-084
↑ Traces Up
SYS-REQ-120
When the balancing module activates balancing for a cell, it shall set the corresponding per-cell flag in DATA_BLOCK_ID_BALANCING_CONTROL and write the block via DATA_WRITE_DATA(). Acceptance: after balancing decision, reading DATA_BLOCK_ID_BALANCING_CONTROL shows the correct cell flags. DIAG on failure: N/A. SYS-REQ-120 QM
SW-REQ-085
↑ Traces Up
SYS-REQ-120
When balancing strategy is set to "none", the balancing module shall clear all per-cell flags in DATA_BLOCK_ID_BALANCING_CONTROL on every cycle. Acceptance: with strategy=none, no cell ever has its balancing flag set. DIAG on failure: N/A. SYS-REQ-120 QM

7. Interface Requirements

7.1 CAN Transmit

ID Requirement Derives From ASIL
SW-REQ-090 The CAN module shall transmit CAN ID 0x220 (DLC 8) every 100 ms via CAN_PeriodicTransmit() in the 10 ms task. Byte 0 lower nibble bits[3:0] = BmsState (STANDBY=5, PRECHARGE=6, NORMAL=7, ERROR=9). Byte 0 upper nibble bits[7:4] = ConnectedStrings count. Remaining bytes encode EmergencyShutoff flag and error flags. Acceptance: when BMS is in NORMAL with 1 string connected, byte 0 = 0x17 (upper nibble=1, lower nibble=7). DIAG on failure: N/A. SYS-REQ-060 B
SW-REQ-091
↓ Traces Down
IT-002
The CAN module shall transmit CAN ID 0x221 (DLC 8) every 100 ms. This frame shall contain pack voltage (mV), pack current (mA), and pack power (mW) encoded per the DBC specification. Acceptance: at 0 A and 66.6 V pack voltage, the decoded pack voltage matches 66600 mV within rounding tolerance. DIAG on failure: N/A. SYS-REQ-061 B
SW-REQ-092
↑ Traces Up
SYS-REQ-067
↓ Traces Down
IT-005
The CAN module shall transmit CAN IDs 0x240 through 0x245 (DLC 8 each) every 100 ms. Each frame carries 3 cell voltages as uint16_t big-endian (6 frames x 3 = 18 cells). Acceptance: cell voltage index 0 appears in 0x240 bytes 0-1, index 1 in bytes 2-3, index 2 in bytes 4-5. DIAG on failure: N/A. SYS-REQ-067
↓ Traces Down
SW-REQ-092SW-REQ-093
B
SW-REQ-093
↓ Traces Down
IT-006
The CAN module shall transmit CAN ID 0x250 (DLC 8) every 100 ms using multiplexing. Byte 0 = mux index (0 through 49). Each frame carries 4 cell voltages encoded as 13-bit values in big-endian format per CAN_BIG_ENDIAN_TABLE. Acceptance: encode(3700 mV) then decode yields exactly 3700 mV for each of the 4 voltage slots. DIAG on failure: N/A. SYS-REQ-067
↓ Traces Down
SW-REQ-092SW-REQ-093
B
SW-REQ-094
↑ Traces Up
SYS-REQ-068
The CAN module shall transmit CAN ID 0x260 (DLC 8) every 100 ms using multiplexing. Byte 0 = mux index (0 through 29). Each frame carries 6 temperature values as 8-bit signed integers (degC). Acceptance: a temperature of 25 degC encodes as 0x19 in the corresponding byte position. DIAG on failure: N/A. SYS-REQ-068
↓ Traces Down
SW-REQ-094
B
SW-REQ-095 The CAN module shall transmit CAN ID 0x235 (DLC 8) every 100 ms. Byte 4 = SOC_min x 2, byte 5 = SOC_avg x 2, byte 6 = SOC_max x 2 (factor 0.5, offset 0). Acceptance: at SOC_avg=50%, byte 5 = 0x64 (100 decimal, since 50/0.5=100). SOC_avg decreases monotonically under constant discharge. DIAG on failure: N/A. SYS-REQ-066
↑ Traces Up
STKH-REQ-007
↓ Traces Down
SW-REQ-074SW-REQ-095
B
SW-REQ-096 All CAN TX messages shall be transmitted by CAN_PeriodicTransmit(), which is called from the 10 ms task (FTSK_RunUserCodeCyclic10ms). Each message shall maintain its own 100 ms period counter, decrementing every 10 ms call and transmitting when the counter reaches zero. Acceptance: CAN bus trace shows each TX ID appearing at 100 ms +/- 10 ms intervals. DIAG on failure: N/A. SYS-REQ-060 B
SW-REQ-097 The CAN TX module shall read all signal data from the database (DATA_READ_DATA) at the time of transmission. It shall not cache stale data between transmit cycles. Acceptance: a voltage change written to the database at time T appears in the next CAN TX frame at time T + [0, 100] ms. DIAG on failure: N/A. SYS-REQ-060 B
SW-REQ-098 Each CAN TX callback function shall construct the 8-byte CAN data payload and call CAN_DataSend() with the correct CAN node, message ID, data length, and data pointer. CAN_DataSend() shall write the frame to the SocketCAN interface. Acceptance: the frame appears on the vcan0 interface as captured by candump. DIAG on failure: N/A. SYS-REQ-060 B
SW-REQ-099 The CAN TX module shall transmit string-specific messages (contactor state, string voltage, string current) for each configured string. The string index shall be embedded in the message encoding. Acceptance: with 1 string configured, string 0 messages appear on the bus; no string 1 messages appear. DIAG on failure: N/A. SYS-REQ-060 B
SW-REQ-09A The CAN TX module shall transmit SOF (state of function) data including recommended charge/discharge current limits and power limits. Acceptance: SOF limits decrease when cell voltage approaches overvoltage threshold. DIAG on failure: N/A. SYS-REQ-060, SYS-REQ-012 B
SW-REQ-09B The CAN TX module shall transmit minimum, maximum, and average cell voltage and temperature values. Acceptance: with cells at [3680, 3700, 3720] mV, min=3680, max=3720, avg=3700 in the transmitted frame. DIAG on failure: N/A. SYS-REQ-062, SYS-REQ-063 B
SW-REQ-09C
↑ Traces Up
SYS-REQ-060
The CAN TX module shall transmit the insulation monitoring result (if available) or a default safe value when the hardware monitor is absent (POSIX port). Acceptance: on POSIX, no spurious insulation fault is reported. DIAG on failure: N/A. SYS-REQ-060 QM
SW-REQ-09D
↑ Traces Up
SYS-REQ-060
The CAN TX module shall transmit open-wire detection results for each cell tap. On the POSIX port, all taps shall report no open wire. Acceptance: open-wire byte fields are all zero on POSIX. DIAG on failure: N/A. SYS-REQ-060 QM
SW-REQ-09E
↑ Traces Up
SYS-REQ-120
The CAN TX module shall transmit balancing status per cell. The frame shall indicate which cells are currently being balanced. Acceptance: when cell 5 is flagged for balancing, the corresponding bit/byte in the TX frame is set. DIAG on failure: N/A. SYS-REQ-120 QM

7.2 CAN Receive

ID Requirement Derives From ASIL
SW-REQ-100 The CAN RX module shall receive CAN ID 0x210 (DLC 8). Byte 0 encodes the state request: 0x00 = STANDBY, 0x02 = NORMAL. The decoded request shall be written to the database. The BMS state machine shall read the request from the database in the 10 ms task and act on it. Acceptance: sending 0x210 with byte0=0x02 causes BMS to initiate STANDBY->PRECHARGE->NORMAL transition. DIAG on failure: CAN_TIMING (if no frames received for timeout period). SYS-REQ-070
↑ Traces Up
STKH-REQ-018
D
SW-REQ-101 The CAN RX module shall receive CAN ID 0x521 (DLC 8) for IVT current measurement. Bytes 2-5 encode a signed 32-bit big-endian integer representing current in milliamperes (mA). Bytes 0-1 encode the measurement status. The decoded current shall be written to DATA_BLOCK_ID_CURRENT_SENSOR.current. Acceptance: at rest (0 A physical), decoded current = 0 +/- 1 mA. DIAG on failure: CURRENT_SENSOR_RESPONDING. SYS-REQ-073 C
SW-REQ-102
↑ Traces Up
SYS-REQ-074
↓ Traces Down
IT-005
The CAN RX module shall receive CAN ID 0x522 (DLC 8) for IVT voltage 1 measurement. Bytes 2-5 encode voltage in mV as signed 32-bit big-endian. The decoded value shall be written to DATA_BLOCK_ID_CURRENT_SENSOR.highVoltage_mV[string][0]. Acceptance: at 66600 mV pack voltage, decoded value = 66600 +/- 10 mV. DIAG on failure: CURRENT_SENSOR_RESPONDING. SYS-REQ-074
↓ Traces Down
SW-REQ-102
C
SW-REQ-103
↑ Traces Up
SYS-REQ-075
↓ Traces Down
IT-006
The CAN RX module shall receive CAN ID 0x523 (DLC 8) for IVT voltage 2. Decoded value written to highVoltage_mV[string][1]. Acceptance: value matches physical measurement within IVT tolerance. DIAG on failure: CURRENT_SENSOR_RESPONDING. SYS-REQ-075
↓ Traces Down
SW-REQ-103
C
SW-REQ-104
↑ Traces Up
SYS-REQ-076
The CAN RX module shall receive CAN ID 0x524 (DLC 8) for IVT voltage 3. Decoded value written to highVoltage_mV[string][2]. This voltage is used by the redundancy module for precharge voltage comparison and MUST match the string voltage within the configured tolerance. Acceptance: highVoltage_mV[s][2] - sum(cellVoltages) < precharge_tolerance_mV. DIAG on failure: CURRENT_SENSOR_RESPONDING.
SW-REQ-105
↑ Traces Up
SYS-REQ-073
The CAN RX module shall receive CAN ID 0x525 (DLC 8) for IVT power measurement. Decoded value (mW, signed 32-bit big-endian) written to DATA_BLOCK_ID_CURRENT_SENSOR.power. Acceptance: power = voltage x current within rounding tolerance. DIAG on failure: CURRENT_SENSOR_RESPONDING. SYS-REQ-073 C
SW-REQ-106
↑ Traces Up
SYS-REQ-073
The CAN RX module shall receive CAN ID 0x526 (DLC 8) for IVT coulomb counting. The decoded value shall update the coulomb counter in the current sensor data block. Acceptance: accumulated charge matches integral of current over time. DIAG on failure: CURRENT_SENSOR_CC_RESPONDING. SYS-REQ-073 C
SW-REQ-107
↑ Traces Up
SYS-REQ-077
The CAN RX module shall receive CAN ID 0x527 (DLC 8) for IVT energy counting. The decoded value shall update the energy counter in the current sensor data block. Acceptance: accumulated energy matches integral of power over time. DIAG on failure: CURRENT_SENSOR_CC_RESPONDING. SYS-REQ-077
↓ Traces Down
SW-REQ-107SW-REQ-113
C
SW-REQ-108 The CAN RX module shall receive CAN ID 0x270 (DLC 8) for AFE cell voltages. Byte 0 = mux index (0-49). Each frame carries 4 cell voltages encoded as 13-bit big-endian values per CAN_BIG_ENDIAN_TABLE. Each voltage slot includes a 1-bit invalid flag (1 = VALID, 0 = INVALID). Only voltages with invalid_flag = 1 shall be stored. Acceptance: after receiving mux frames 0-4, all 18 cell voltages are populated in the database. DIAG on failure: CAN_TIMING. SYS-REQ-071
↑ Traces Up
STKH-REQ-019
C
SW-REQ-109 The CAN RX module shall receive CAN ID 0x280 (DLC 8) for AFE cell temperatures. Byte 0 = mux index (0-29). Each frame carries 6 temperature values as 8-bit signed integers. Acceptance: after receiving mux frames 0-1, all 8 temperature sensors are populated. DIAG on failure: CAN_TIMING. SYS-REQ-072
↑ Traces Up
STKH-REQ-020
C

7.3 CAN Timing Supervision

ID Requirement Derives From ASIL
SW-REQ-110
↓ Traces Down
SSR-040
The CAN module shall monitor overall CAN message reception. If no valid CAN frame is received for 100 consecutive 10 ms checks (= 1000 ms), the DIAG module shall evaluate CAN_TIMING. After the configured 200 ms evaluation delay, CAN_TIMING shall be flagged as FATAL. Total fault-tolerant time interval (FTTI) = 1200 ms. Acceptance: stopping all CAN traffic for >1200 ms causes BMS to enter ERROR state. DIAG on failure: DIAG_ID_CAN_TIMING. SYS-REQ-05A
↓ Traces Down
SW-REQ-110
D
SW-REQ-111
↓ Traces Down
SSR-041
The CAN module shall monitor IVT current sensor frames (0x521-0x527). If IVT frames stop arriving for 100 consecutive checks, the DIAG module shall evaluate CURRENT_SENSOR_RESPONDING. After 200 ms evaluation delay, it shall be flagged as FATAL. FTTI = 1200 ms. Acceptance: stopping IVT frames for >1200 ms causes ERROR state. DIAG on failure: DIAG_ID_CURRENT_SENSOR_RESPONDING. SYS-REQ-073 D
SW-REQ-112
↑ Traces Up
SYS-REQ-073
The CAN module shall monitor IVT coulomb counting frames (0x526). If coulomb counting frames stop arriving for 100 consecutive checks, the DIAG module shall evaluate CURRENT_SENSOR_CC_RESPONDING with a 2000 ms evaluation delay. FTTI = 3000 ms. Acceptance: stopping 0x526 for >3000 ms triggers the diagnostic event. DIAG on failure: DIAG_ID_CURRENT_SENSOR_CC_RESPONDING. SYS-REQ-073 D
SW-REQ-113
↑ Traces Up
SYS-REQ-077
The CAN module shall monitor IVT energy counting frames (0x527). If energy counting frames stop arriving for 100 consecutive checks, the DIAG module shall evaluate CURRENT_SENSOR_EC_RESPONDING with a 2000 ms evaluation delay. FTTI = 3000 ms. Acceptance: stopping 0x527 for >3000 ms triggers the diagnostic event. DIAG on failure: DIAG_ID_CURRENT_SENSOR_EC_RESPONDING. SYS-REQ-077
↓ Traces Down
SW-REQ-107SW-REQ-113
D

8. POSIX Port-Specific Requirements

8.1 Cooperative Loop

ID Requirement Derives From ASIL
SW-REQ-120 The POSIX cooperative main loop shall iterate at approximately 2 kHz by calling usleep(500) (500 microseconds) per iteration. Acceptance: measured iteration rate is 1800-2200 Hz over a 10-second window. DIAG on failure: N/A. SYS-REQ-151 QM
SW-REQ-121 The 1 ms task slot shall fire every 1000 microseconds of elapsed time. It shall execute: FTSK_RunUserCodeCyclic1ms(), FTSK_RunUserCodeEngine() (database processing), and MEAS_Control(). Acceptance: task fires at 1.0 ms +/- 0.5 ms intervals measured by gettimeofday(). DIAG on failure: N/A (deadline violation counted). SYS-REQ-151 QM
SW-REQ-122
↓ Traces Down
UT-110UT-111UT-112
The 10 ms task slot shall fire every 10000 microseconds of elapsed time. It shall execute: FTSK_RunUserCodeCyclic10ms() which contains SYS_Trigger(), BMS_Trigger(), and CAN_PeriodicTransmit(). Acceptance: BMS state machine advances within 10 ms of a state request. DIAG on failure: N/A (deadline violation counted). SYS-REQ-151 QM
SW-REQ-123
↓ Traces Down
UT-100UT-104UT-105
The 100 ms task slot shall fire every 100000 microseconds of elapsed time. It shall execute: FTSK_RunUserCodeCyclic100ms() and FTSK_RunUserCodeCyclicAlgorithm100ms() (SOC/SOE/SOF algorithms). Acceptance: SOC updates appear at 100 ms intervals. DIAG on failure: N/A (deadline violation counted). SYS-REQ-151 QM
SW-REQ-124
↑ Traces Up
SYS-REQ-151
The cooperative loop shall call task functions in priority order within each iteration: Engine, 1 ms, AFE, 10 ms, 100 ms, I2C, 100 ms-Algorithm. Higher-priority tasks are checked first. Acceptance: instrumenting task entry shows Engine always runs before 10 ms in any iteration where both fire. DIAG on failure: N/A. SYS-REQ-151 QM
SW-REQ-125
↑ Traces Up
SYS-REQ-151
The cooperative loop shall implement deadline monitoring. If any task slot takes longer to execute than its period (e.g., 1 ms task takes >1 ms), the loop shall log the violation and increment a per-slot violation counter. Acceptance: injecting a 2 ms delay in the 1 ms task increments the 1 ms violation counter. DIAG on failure: N/A (logged, not FATAL). SYS-REQ-151 QM
SW-REQ-126
↑ Traces Up
SYS-REQ-152
The cooperative loop shall perform a non-blocking CAN read from the SocketCAN interface on every iteration. Received frames shall be injected into the foxBMS CAN RX path via posix_can_rx_inject(). Acceptance: a frame sent by the plant model is received and processed within 1 ms (2 loop iterations). DIAG on failure: N/A. SYS-REQ-152 QM
SW-REQ-127
↑ Traces Up
SYS-REQ-151
Upon receiving SIGINT, the cooperative loop shall set running=0, command all contactors to open, print a timing summary (task counts, deadline violations), and exit with code 0. Acceptance: sending SIGINT during NORMAL operation results in contactors opening and a clean exit. DIAG on failure: N/A. SYS-REQ-151 QM

8.2 SocketCAN and HAL

ID Requirement Derives From ASIL
SW-REQ-128
↑ Traces Up
SYS-REQ-152
The SocketCAN interface shall provide send and receive operations compatible with the foxBMS CAN driver API (CAN_DataSend, CAN receive callback). The interface shall bind to vcan0 (or a configurable interface name). Acceptance: CAN frames sent via CAN_DataSend() appear on the vcan0 interface. DIAG on failure: N/A. SYS-REQ-152 QM
SW-REQ-129 HAL stubs shall implement all function signatures of the TMS570 HAL with no-op or RAM-mapped behavior. Functions that return status shall return success. Acceptance: the POSIX build links without undefined symbol errors for any HAL function. DIAG on failure: N/A. SYS-REQ-155
↓ Traces Down
SW-REQ-129
, SYS-REQ-156
↓ Traces Down
SW-REQ-129
QM
SW-REQ-12A
↑ Traces Up
SYS-REQ-150
The POSIX build shall compile 170+ source files with GCC 13 for x86-64 without errors or warnings treated as errors. Acceptance: make completes with exit code 0. DIAG on failure: N/A. SYS-REQ-150
↓ Traces Down
SW-REQ-129SW-REQ-12A
QM

9. Negative Requirements

ID Requirement Derives From ASIL
SW-REQ-200 The BMS state machine shall NOT transition directly from ERROR to NORMAL. Recovery from ERROR shall always pass through STANDBY first (ERROR -> STANDBY -> PRECHARGE -> NORMAL). Acceptance: sending state request NORMAL (0x02) while in ERROR does not cause transition to NORMAL; BMS remains in ERROR. Only after fault clears and STANDBY request (0x00) moves BMS to STANDBY can NORMAL be requested. DIAG on failure: N/A (state machine design constraint). SYS-REQ-055
↑ Traces Up
STKH-REQ-013
, SYS-REQ-094
↓ Traces Down
SW-REQ-045SW-REQ-200
D
SW-REQ-201 The BMS shall NOT close any contactor (string+, string-, precharge) while in ERROR state. Any contactor close command shall be suppressed. Acceptance: injecting a contactor-close command while in ERROR results in all contactors remaining open. DIAG on failure: N/A (state machine design constraint). SYS-REQ-054, SYS-REQ-114
↓ Traces Down
SW-REQ-044SW-REQ-201
D
SW-REQ-202
↑ Traces Up
SYS-REQ-152
The cooperative main loop shall NOT block on CAN read operations. The SocketCAN socket shall be configured as non-blocking (O_NONBLOCK or equivalent). If no frame is available, the read shall return immediately with EAGAIN/EWOULDBLOCK. Acceptance: with no CAN traffic, the loop iteration rate remains at ~2 kHz (not degraded by blocking). DIAG on failure: N/A. SYS-REQ-152 QM
SW-REQ-203 The plant model shall NOT send cell voltage frames (0x270) with invalid_flag = 0 for valid data. The invalid_flag encoding is counterintuitive: 1 = VALID, 0 = INVALID. All valid cell voltages shall have invalid_flag = 1. Acceptance: all cell voltage frames from the plant model have invalid_flag = 1 for populated cells, and the BMS stores all 18 cell voltages. DIAG on failure: N/A (plant model constraint). SYS-REQ-071
↑ Traces Up
STKH-REQ-019
, SYS-REQ-142
↓ Traces Down
SW-REQ-108SW-REQ-203
C
SW-REQ-204 The database shall NOT allow two producer modules to write the same DATA_BLOCK_ID. This is a design-time invariant enforced by code review and static analysis, not a runtime check. Acceptance: grep of all DATA_WRITE_DATA() call sites confirms each DATA_BLOCK_ID has exactly one writer. DIAG on failure: N/A (design-time constraint). SYS-REQ-060 C
SW-REQ-205
↑ Traces Up
SYS-REQ-151
FAS_ASSERT shall NOT silently continue execution on assertion failure. On the POSIX port, FAS_ASSERT shall log the file, line, and expression to stderr and call exit(1) to terminate the process. Acceptance: triggering FAS_ASSERT produces a log message on stderr and non-zero exit code. DIAG on failure: N/A (assertion = immediate termination). SYS-REQ-151 D

10. Acceptance Criteria

Each software requirement is accepted when:

  1. It is traced backward to at least one system requirement in SYS.2-001.
  2. It is traced forward to detailed design in SWE.3-001.
  3. It is covered by at least one test case in SWE.4-001, SWE.5-001, or SWE.6-001.
  4. The covering test case passes on the POSIX SIL target.

End of Document