GCC Code Coverage Report


Directory: lib/fprime-samd/fprime-samd/
File: Drv/GpioDriver/GpioDriverHardwareStub.cpp
Date: 2026-09-26 00:05:09
Exec Total Coverage
Lines: 0 67 0.0%
Functions: 0 13 0.0%
Branches: 0 6 0.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title GpioDriverHardwareStub.cpp
3 // \author tumbar
4 // \brief Stub hardware implementation for GPIO peripheral (Linux/test builds)
5 //
6 // This file is compiled for Linux/test builds to enable unit testing.
7 // For SAMD21 target builds, GpioDriverHardware.cpp is used instead.
8 //
9 // The stub records every HAL interaction in an observable GpioState so that
10 // unit tests can verify the driver drives the HAL correctly, and lets tests
11 // inject the value returned by read().
12 // ======================================================================
13
14 #include "Fw/Types/LogicEnumAc.hpp"
15 #include "fprime-samd/Drv/GpioDriver/GpioDriverHardware.hpp"
16
17 namespace Samd21 {
18 namespace GpioHardware {
19
20 //! Number of EIC external interrupt lines (EXTINT[0..15]); a pin maps to line pinIdx % this.
21 static constexpr U8 EXTINT_LINE_COUNT = 16;
22
23 //! Global GPIO state instance for stub
24 static GpioState g_gpio_state = {
25 .configure_input_count = 0,
26 .configure_external_interrupt_count = 0,
27 .configure_output_count = 0,
28 .write_count = 0,
29 .read_count = 0,
30 .last_group = 0,
31 .last_pin = 0,
32 .last_input_pull_mode = GpioDriver::InputPullMode::NO_PULL,
33 .last_input_interrupt_mode = GpioDriver::ExternalInterruptMode::NONE,
34 .last_write_group = 0,
35 .last_write_pin = 0,
36 .last_write_state = Fw::Logic::LOW,
37 .last_read_group = 0,
38 .last_read_pin = 0,
39 .read_value = Fw::Logic::HIGH,
40 };
41
42 //! Components registered for ISR dispatch, indexed by EXTINT line.
43 static GpioDriver* g_interrupt_handlers[EXTINT_LINE_COUNT] = {};
44
45 ✗ GpioState& getGpioState() {
46 ✗ return g_gpio_state;
47 }
48
49 ✗ void GpioHal::configureInput(U8 groupIdx, U8 pinIdx, GpioDriver::InputPullMode input_pull_mode) {
50 ✗ g_gpio_state.configure_input_count++;
51 ✗ g_gpio_state.last_group = groupIdx;
52 ✗ g_gpio_state.last_pin = pinIdx;
53 ✗ g_gpio_state.last_input_pull_mode = input_pull_mode;
54 ✗ }
55
56 ✗ void GpioHal::configureExternalInterrupt(U8 groupIdx, U8 pinIdx, GpioDriver::ExternalInterruptMode interrupt_mode) {
57 ✗ g_gpio_state.configure_external_interrupt_count++;
58 ✗ g_gpio_state.last_group = groupIdx;
59 ✗ g_gpio_state.last_pin = pinIdx;
60 ✗ g_gpio_state.last_input_interrupt_mode = interrupt_mode;
61 ✗ }
62
63 ✗ U32 GpioHal::getInterruptFlags() {
64 ✗ return 0;
65 }
66
67 ✗ void GpioHal::clearInterruptFlags(U32 mask) {
68 (void)mask;
69 ✗ }
70
71 ✗ void registerInterruptHandler(U8 pinIdx, GpioDriver* handler) {
72 ✗ FW_ASSERT(handler != nullptr);
73 ✗ g_interrupt_handlers[pinIdx % EXTINT_LINE_COUNT] = handler;
74 ✗ }
75
76 ✗ GpioDriver* getInterruptHandler(U8 extintLine) {
77 ✗ return g_interrupt_handlers[extintLine % EXTINT_LINE_COUNT];
78 }
79
80 ✗ void GpioHal::configureOutput(U8 groupIdx, U8 pinIdx) {
81 ✗ g_gpio_state.configure_output_count++;
82 ✗ g_gpio_state.last_group = groupIdx;
83 ✗ g_gpio_state.last_pin = pinIdx;
84 ✗ }
85
86 ✗ Fw::Logic GpioHal::read(U8 groupIdx, U8 pinIdx) {
87 ✗ g_gpio_state.read_count++;
88 ✗ g_gpio_state.last_read_group = groupIdx;
89 ✗ g_gpio_state.last_read_pin = pinIdx;
90 ✗ return g_gpio_state.read_value;
91 }
92
93 ✗ void GpioHal::write(U8 groupIdx, U8 pinIdx, const Fw::Logic& state) {
94 ✗ g_gpio_state.write_count++;
95 ✗ g_gpio_state.last_write_group = groupIdx;
96 ✗ g_gpio_state.last_write_pin = pinIdx;
97 ✗ g_gpio_state.last_write_state = state;
98 ✗ }
99
100 //! Test helper: reset stub state for clean test runs
101 ✗ void resetGpioState() {
102 ✗ g_gpio_state.configure_input_count = 0;
103 ✗ g_gpio_state.configure_external_interrupt_count = 0;
104 ✗ g_gpio_state.configure_output_count = 0;
105 ✗ g_gpio_state.write_count = 0;
106 ✗ g_gpio_state.read_count = 0;
107 ✗ g_gpio_state.last_group = 0;
108 ✗ g_gpio_state.last_pin = 0;
109 ✗ g_gpio_state.last_input_pull_mode = GpioDriver::InputPullMode::NO_PULL;
110 ✗ g_gpio_state.last_input_interrupt_mode = GpioDriver::ExternalInterruptMode::NONE;
111 ✗ g_gpio_state.last_write_group = 0;
112 ✗ g_gpio_state.last_write_pin = 0;
113 ✗ g_gpio_state.last_write_state = Fw::Logic::LOW;
114 ✗ g_gpio_state.last_read_group = 0;
115 ✗ g_gpio_state.last_read_pin = 0;
116 ✗ g_gpio_state.read_value = Fw::Logic::HIGH;
117
118 ✗ for (U8 line = 0; line < EXTINT_LINE_COUNT; line++) {
119 ✗ g_interrupt_handlers[line] = nullptr;
120 }
121 ✗ }
122
123 //! Test helper: set the value returned by the next read()
124 ✗ void setReadValue(const Fw::Logic& state) {
125 ✗ g_gpio_state.read_value = state;
126 ✗ }
127
128 //! Test helper: dispatch an edge to a pin's registered handler like EIC_Handler would.
129 ✗ void simulateInterrupt(U8 pinIdx) {
130 ✗ GpioDriver* handler = g_interrupt_handlers[pinIdx % EXTINT_LINE_COUNT];
131 ✗ if (handler != nullptr) {
132 ✗ handler->gpioInterruptIsr();
133 }
134 ✗ }
135
136 } // namespace GpioHardware
137 } // namespace Samd21
138