GCC Code Coverage Report


Directory: lib/fprime-samd/fprime-samd/
File: Drv/I2cDriver/I2cDriverHardwareStub.cpp
Date: 2026-09-26 00:05:09
Exec Total Coverage
Lines: 0 75 0.0%
Functions: 0 16 0.0%
Branches: 0 14 0.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title I2cDriverHardwareStub.cpp
3 // \author tumbar
4 // \brief Stub hardware implementation for the I2C peripheral (Linux/test builds)
5 //
6 // This file is compiled for Linux/test builds to enable unit testing.
7 // For SAMD21 target builds, I2cDriverHardware.cpp is used instead.
8 //
9 // The stub records the arguments of each hardware call and exposes injectable
10 // interrupt/bus status so unit tests can drive the component's state machine,
11 // ISR error dispatch and telemetry mapping without any real MCU.
12 // ======================================================================
13
14 #include "fprime-samd/Drv/I2cDriver/I2cDriverHardware.hpp"
15
16 namespace Samd21 {
17 namespace I2cHardware {
18
19 static StubState s_state = {};
20
21 ✗ StubState& getStubState() {
22 ✗ return s_state;
23 }
24
25 ✗ void resetStubState() {
26 // Assign a fresh value-initialized instance rather than memset: several
27 // members (e.g. SercomKind) are autocoded classes with vtables that
28 // memset would corrupt.
29 ✗ s_state = StubState{};
30 ✗ }
31
32 ✗ void fireIsr() {
33 ✗ if (s_state.isr_callback != nullptr) {
34 ✗ s_state.isr_callback(s_state.isr_data, s_state.isr_sercom);
35 }
36 ✗ }
37
38 ✗ void I2cHal::registerIsr(SercomKind sercom,
39 void (*callback)(Fw::PassiveComponentBase*, SercomKind),
40 Fw::PassiveComponentBase* data) {
41 ✗ s_state.isr_callback = callback;
42 ✗ s_state.isr_data = data;
43 ✗ s_state.isr_sercom = sercom;
44 ✗ }
45
46 ✗ void I2cHal::configure(SercomKind sercom,
47 I2cDriver::SclLowTimeout scl_low_timeout,
48 I2cDriver::InactiveTimeout inactive_timeout,
49 I2cDriver::ClockStretchMode clock_stretch_mode,
50 I2cDriver::Frequency frequency,
51 I2cDriver::ClientSclLowTimeout client_scl_low_timeout,
52 I2cDriver::HostSclLowTimeout host_scl_low_timeout,
53 I2cDriver::SdaHold sda_hold,
54 I2cDriver::PinUsage pin_usage,
55 I2cDriver::RunInStandby run_in_standby) {
56 ✗ s_state.configured = true;
57 ✗ s_state.configure_count++;
58 ✗ s_state.sercom = sercom;
59 ✗ s_state.scl_low_timeout = scl_low_timeout;
60 ✗ s_state.inactive_timeout = inactive_timeout;
61 ✗ s_state.clock_stretch_mode = clock_stretch_mode;
62 ✗ s_state.frequency = frequency;
63 ✗ s_state.client_scl_low_timeout = client_scl_low_timeout;
64 ✗ s_state.host_scl_low_timeout = host_scl_low_timeout;
65 ✗ s_state.sda_hold = sda_hold;
66 ✗ s_state.pin_usage = pin_usage;
67 ✗ s_state.run_in_standby = run_in_standby;
68 ✗ }
69
70 ✗ U32 I2cHal::getDataRegisterAddress(SercomKind sercom) {
71 ✗ return s_state.data_register_address;
72 }
73
74 ✗ I2cInterruptStatus I2cHal::readInterruptStatus(SercomKind sercom) {
75 ✗ return s_state.interrupt_status;
76 }
77
78 ✗ I2cBusStatus I2cHal::readBusStatus(SercomKind sercom) {
79 ✗ return s_state.bus_status;
80 }
81
82 ✗ I2cRawRegisters I2cHal::readRawRegisters(SercomKind sercom) {
83 ✗ return s_state.raw_registers;
84 }
85
86 ✗ void I2cHal::recoverBusToIdle(SercomKind sercom) {
87 ✗ s_state.recover_bus_count++;
88
89 // Model the write-1-clear recovery: after recovery no interrupt/error flags
90 // remain pending and the bus is IDLE, so the driver can start fresh.
91 ✗ s_state.interrupt_status = I2cInterruptStatus{};
92 ✗ s_state.bus_status.busState = 0x1; // IDLE
93 ✗ s_state.bus_status.clockHold = false;
94 ✗ s_state.bus_status.masterOnBus = false;
95 ✗ s_state.bus_status.slaveOnBus = false;
96 ✗ }
97
98 ✗ void I2cHal::acknowledgeErrors(SercomKind sercom) {
99 ✗ s_state.acknowledge_errors_count++;
100 // Model the write-1-clear: once acked, the pending error/flags go away so a
101 // subsequent readInterruptStatus() does not re-report the same error.
102 ✗ s_state.interrupt_status.error = false;
103 ✗ s_state.interrupt_status.busError = false;
104 ✗ s_state.interrupt_status.arbLost = false;
105 ✗ s_state.interrupt_status.lowTimeout = false;
106 ✗ s_state.interrupt_status.masterExtTimeout = false;
107 ✗ s_state.interrupt_status.slaveExtTimeout = false;
108 ✗ s_state.interrupt_status.lengthError = false;
109 ✗ }
110
111 ✗ void I2cHal::acknowledgeMasterOnBus(SercomKind sercom) {
112 ✗ s_state.acknowledge_mb_count++;
113 ✗ s_state.interrupt_status.masterOnBus = false;
114 ✗ }
115
116 ✗ void I2cHal::enableMasterOnBusInterrupt(SercomKind sercom) {
117 ✗ s_state.enable_mb_count++;
118 ✗ }
119
120 ✗ void I2cHal::disableMasterOnBusInterrupt(SercomKind sercom) {
121 ✗ s_state.disable_mb_count++;
122 ✗ }
123
124 ✗ void I2cHal::beginRead(SercomKind sercom, U32 addr, U8 byteCount) {
125 ✗ s_state.begin_read_count++;
126 ✗ s_state.begin_read_addr = addr;
127 ✗ s_state.begin_read_len = byteCount;
128 ✗ }
129
130 ✗ void I2cHal::beginWrite(SercomKind sercom, U32 addr, U8 byteCount, bool generateStopCondition) {
131 ✗ s_state.begin_write_count++;
132 ✗ s_state.begin_write_addr = addr;
133 ✗ s_state.begin_write_len = byteCount;
134 ✗ s_state.begin_write_stop = generateStopCondition;
135 ✗ }
136
137 } // namespace I2cHardware
138 } // namespace Samd21
139