diff --git a/FprimeZephyrReference/Components/CMakeLists.txt b/FprimeZephyrReference/Components/CMakeLists.txt index b4f276ad..c320c369 100644 --- a/FprimeZephyrReference/Components/CMakeLists.txt +++ b/FprimeZephyrReference/Components/CMakeLists.txt @@ -8,6 +8,7 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ComDelay/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Drv/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FatalHandler") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FsSpace/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/GenericDeviceMonitor/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ImuManager/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LoadSwitch/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ModeManager/") diff --git a/FprimeZephyrReference/Components/GenericDeviceMonitor/CMakeLists.txt b/FprimeZephyrReference/Components/GenericDeviceMonitor/CMakeLists.txt new file mode 100644 index 00000000..731a72e3 --- /dev/null +++ b/FprimeZephyrReference/Components/GenericDeviceMonitor/CMakeLists.txt @@ -0,0 +1,36 @@ +#### +# F Prime CMakeLists.txt: +# +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/ +# +#### + +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. + +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/GenericDeviceMonitor.fpp" + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/GenericDeviceMonitor.cpp" +# DEPENDS +# MyPackage_MyOtherModule +) + +### Unit Tests ### +# register_fprime_ut( +# AUTOCODER_INPUTS +# "${CMAKE_CURRENT_LIST_DIR}/GenericDeviceMonitor.fpp" +# SOURCES +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/GenericDeviceMonitorTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/GenericDeviceMonitorTester.cpp" +# DEPENDS +# STest # For rules-based testing +# UT_AUTO_HELPERS +# ) diff --git a/FprimeZephyrReference/Components/GenericDeviceMonitor/GenericDeviceMonitor.cpp b/FprimeZephyrReference/Components/GenericDeviceMonitor/GenericDeviceMonitor.cpp new file mode 100644 index 00000000..17bca66e --- /dev/null +++ b/FprimeZephyrReference/Components/GenericDeviceMonitor/GenericDeviceMonitor.cpp @@ -0,0 +1,45 @@ +// ====================================================================== +// \title GenericDeviceMonitor.cpp +// \author nate +// \brief cpp file for GenericDeviceMonitor component implementation class +// ====================================================================== + +#include "FprimeZephyrReference/Components/GenericDeviceMonitor/GenericDeviceMonitor.hpp" + +namespace Components { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +GenericDeviceMonitor ::GenericDeviceMonitor(const char* const compName) : GenericDeviceMonitorComponentBase(compName) {} + +GenericDeviceMonitor ::~GenericDeviceMonitor() {} + +// ---------------------------------------------------------------------- +// Helper methods +// ---------------------------------------------------------------------- + +void GenericDeviceMonitor::configure(const struct device* dev) { + this->m_dev = dev; +} + +// ---------------------------------------------------------------------- +// Handler implementations for typed input ports +// ---------------------------------------------------------------------- + +Fw::Health GenericDeviceMonitor ::healthGet_handler(FwIndexType portNum) { + return device_is_ready(this->m_dev) ? Fw::Health::HEALTHY : Fw::Health::FAILED; +} + +void GenericDeviceMonitor ::run_handler(FwIndexType portNum, U32 context) { + if (!device_is_ready(this->m_dev)) { + this->tlmWrite_Healthy(Fw::Health::FAILED); + this->log_WARNING_LO_DeviceNotReady(); + return; + } + + this->tlmWrite_Healthy(Fw::Health::HEALTHY); +} + +} // namespace Components diff --git a/FprimeZephyrReference/Components/GenericDeviceMonitor/GenericDeviceMonitor.fpp b/FprimeZephyrReference/Components/GenericDeviceMonitor/GenericDeviceMonitor.fpp new file mode 100644 index 00000000..e5da4abc --- /dev/null +++ b/FprimeZephyrReference/Components/GenericDeviceMonitor/GenericDeviceMonitor.fpp @@ -0,0 +1,38 @@ +module Components { + port HealthGet -> Fw.Health +} + +module Components { + @ Generic Device Health Reporter + @ Use for devices which only need to report simple health status and have no interactivity + passive component GenericDeviceMonitor { + + @ Port receiving calls from the rate group + sync input port run: Svc.Sched + + @ Port receiving calls to request device health + sync input port healthGet: HealthGet + + @ Telemetry showing device health + telemetry Healthy: Fw.Health + + @ Event indicating device not ready + event DeviceNotReady() severity warning low id 0 format "Device not ready" throttle 5 + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + @ Port for sending telemetry channels to downlink + telemetry port tlmOut + + } +} diff --git a/FprimeZephyrReference/Components/GenericDeviceMonitor/GenericDeviceMonitor.hpp b/FprimeZephyrReference/Components/GenericDeviceMonitor/GenericDeviceMonitor.hpp new file mode 100644 index 00000000..ea0d741f --- /dev/null +++ b/FprimeZephyrReference/Components/GenericDeviceMonitor/GenericDeviceMonitor.hpp @@ -0,0 +1,65 @@ +// ====================================================================== +// \title GenericDeviceMonitor.hpp +// \author nate +// \brief hpp file for GenericDeviceMonitor component implementation class +// ====================================================================== + +#ifndef Components_GenericDeviceMonitor_HPP +#define Components_GenericDeviceMonitor_HPP + +#include "FprimeZephyrReference/Components/GenericDeviceMonitor/GenericDeviceMonitorComponentAc.hpp" +#include + +namespace Components { + +class GenericDeviceMonitor final : public GenericDeviceMonitorComponentBase { + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct GenericDeviceMonitor object + GenericDeviceMonitor(const char* const compName //!< The component name + ); + + //! Destroy GenericDeviceMonitor object + ~GenericDeviceMonitor(); + + public: + // ---------------------------------------------------------------------- + // Public helper methods + // ---------------------------------------------------------------------- + + //! Configure the zephyr mux channel device + void configure(const struct device* dev); + + private: + // ---------------------------------------------------------------------- + // Handler implementations for typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for healthGet + //! + //! Port receiving calls to request device health + Fw::Health healthGet_handler(FwIndexType portNum //!< The port number + ) override; + + //! Handler implementation for run + //! + //! Port receiving calls from the rate group + void run_handler(FwIndexType portNum, //!< The port number + U32 context //!< The call order + ) override; + + private: + // ---------------------------------------------------------------------- + // Private member variables + // ---------------------------------------------------------------------- + + //! Zephyr device stores the initialized mux channel + const struct device* m_dev; +}; + +} // namespace Components + +#endif diff --git a/FprimeZephyrReference/Components/GenericDeviceMonitor/docs/sdd.md b/FprimeZephyrReference/Components/GenericDeviceMonitor/docs/sdd.md new file mode 100644 index 00000000..7caaa23f --- /dev/null +++ b/FprimeZephyrReference/Components/GenericDeviceMonitor/docs/sdd.md @@ -0,0 +1,95 @@ +# Components::GenericDeviceMonitor + +Generic Device Health Reporter + +## Usage Examples + +The GenericDeviceMonitor component is designed to monitor and report the health status of simple devices that do not require complex interactivity. It can be scheduled to periodically check or report status, and it provides a port for external components to query its health. + +### Typical Usage + +1. The component is instantiated and connected to a rate group and/or a health monitoring service. +2. The scheduler calls the `run` port. +3. External components can call the `healthGet` port to retrieve the current health status. +4. The component emits telemetry indicating its health status (`Healthy`). +5. If the device is not ready, it emits a `DeviceNotReady` event. + +## Class Diagram + +```mermaid +classDiagram + namespace Components { + class GenericDeviceMonitorComponentBase { + <> + } + class GenericDeviceMonitor { + + GenericDeviceMonitor(const char* compName) + + ~GenericDeviceMonitor() + - run_handler(FwIndexType portNum, U32 context): void + - healthGet_handler(FwIndexType portNum, Fw::Health& health): void + } + } + GenericDeviceMonitorComponentBase <|-- GenericDeviceMonitor : inherits +``` + +## Port Descriptions +| Name | Type | Description | +|---|---|---| +| run | sync input | Port receiving calls from the rate group | +| healthGet | sync input | Port receiving calls to request device health | +| timeCaller | time get | Port for requesting the current time | +| logTextOut | text event | Port for sending textual representation of events | +| logOut | event | Port for sending events to downlink | +| tlmOut | telemetry | Port for sending telemetry channels to downlink | + +## Component States +The component is stateless in terms of FSM, but tracks the health status of the monitored device. + +## Sequence Diagrams + +```mermaid +sequenceDiagram + participant Scheduler + participant GenericDeviceMonitor + participant ExternalRequester + + Scheduler->>GenericDeviceMonitor: run + GenericDeviceMonitor-->>GenericDeviceMonitor: Check Status (Internal) + GenericDeviceMonitor->>Telemetry: Healthy + + ExternalRequester->>GenericDeviceMonitor: healthGet + GenericDeviceMonitor-->>ExternalRequester: return Health Status +``` + +## Parameters +None + +## Commands +None + +## Events +| Name | Description | +|---|---| +| DeviceNotReady | Event indicating device not ready | + +## Telemetry +| Name | Description | +|---|---| +| Healthy | Telemetry showing device health | + +## Unit Tests +| Name | Description | +|---|---| +| TestHealthReporting | Verify health status reporting via telemetry | + +## Requirements +| Name | Description | Validation | +|---|---|---| +| Health Reporting | The component shall report the health status of the monitored device via telemetry | Verify `Healthy` telemetry channel | +| Health Query | The component shall respond to health queries via the `healthGet` port | Verify `healthGet` port return value | +| Error Reporting | The component shall emit an event if the device is not ready | Verify `DeviceNotReady` event | + +## Change Log +| Date | Description | +|---|---| +| 2025-11-30 | Initial Draft | diff --git a/FprimeZephyrReference/ReferenceDeployment/Main.cpp b/FprimeZephyrReference/ReferenceDeployment/Main.cpp index c4d250c5..d40792b8 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Main.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Main.cpp @@ -17,6 +17,15 @@ const struct device* lora = DEVICE_DT_GET(DT_NODELABEL(lora0)); const struct device* lsm6dso = DEVICE_DT_GET(DT_NODELABEL(lsm6dso0)); const struct device* lis2mdl = DEVICE_DT_GET(DT_NODELABEL(lis2mdl0)); const struct device* rtc = DEVICE_DT_GET(DT_NODELABEL(rtc0)); +const struct device* tca9548a = DEVICE_DT_GET(DT_NODELABEL(tca9548a)); +const struct device* mux_channel_0 = DEVICE_DT_GET(DT_NODELABEL(mux_channel_0)); +const struct device* mux_channel_1 = DEVICE_DT_GET(DT_NODELABEL(mux_channel_1)); +const struct device* mux_channel_2 = DEVICE_DT_GET(DT_NODELABEL(mux_channel_2)); +const struct device* mux_channel_3 = DEVICE_DT_GET(DT_NODELABEL(mux_channel_3)); +const struct device* mux_channel_4 = DEVICE_DT_GET(DT_NODELABEL(mux_channel_4)); +const struct device* mux_channel_5 = DEVICE_DT_GET(DT_NODELABEL(mux_channel_5)); +const struct device* mux_channel_6 = DEVICE_DT_GET(DT_NODELABEL(mux_channel_6)); +const struct device* mux_channel_7 = DEVICE_DT_GET(DT_NODELABEL(mux_channel_7)); int main(int argc, char* argv[]) { // ** DO NOT REMOVE **// @@ -27,6 +36,8 @@ int main(int argc, char* argv[]) { Os::init(); // Object for communicating state to the topology ReferenceDeployment::TopologyState inputs; + + // Flight Control Board device bindings inputs.ina219SysDevice = ina219Sys; inputs.ina219SolDevice = ina219Sol; inputs.loraDevice = lora; @@ -34,6 +45,16 @@ int main(int argc, char* argv[]) { inputs.lsm6dsoDevice = lsm6dso; inputs.lis2mdlDevice = lis2mdl; inputs.rtcDevice = rtc; + inputs.tca9548aDevice = tca9548a; + inputs.muxChannel0Device = mux_channel_0; + inputs.muxChannel1Device = mux_channel_1; + inputs.muxChannel2Device = mux_channel_2; + inputs.muxChannel3Device = mux_channel_3; + inputs.muxChannel4Device = mux_channel_4; + inputs.muxChannel5Device = mux_channel_5; + inputs.muxChannel6Device = mux_channel_6; + inputs.muxChannel7Device = mux_channel_7; + inputs.baudRate = 115200; // Setup, cycle, and teardown topology diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi index 6055131c..df328712 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi @@ -91,7 +91,18 @@ telemetry packets ReferenceDeploymentPackets { ComCcsdsUart.authenticate.AuthenticatedPacketsCount ComCcsdsUart.authenticate.RejectedPacketsCount ComCcsdsUart.authenticate.CurrentSequenceNumber + } + packet TcaMonitor id 12 group 4 { + ReferenceDeployment.tcaMonitor.Healthy + ReferenceDeployment.muxChannel0Monitor.Healthy + ReferenceDeployment.muxChannel1Monitor.Healthy + ReferenceDeployment.muxChannel2Monitor.Healthy + ReferenceDeployment.muxChannel3Monitor.Healthy + ReferenceDeployment.muxChannel4Monitor.Healthy + ReferenceDeployment.muxChannel5Monitor.Healthy + ReferenceDeployment.muxChannel6Monitor.Healthy + ReferenceDeployment.muxChannel7Monitor.Healthy } } omit { diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp index af8e02a4..13004e7f 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp @@ -115,6 +115,14 @@ void setupTopology(const TopologyState& state) { lis2mdlManager.configure(state.lis2mdlDevice); ina219SysManager.configure(state.ina219SysDevice); ina219SolManager.configure(state.ina219SolDevice); + tcaMonitor.configure(state.tca9548aDevice); + muxChannel0Monitor.configure(state.muxChannel0Device); + muxChannel1Monitor.configure(state.muxChannel1Device); + muxChannel2Monitor.configure(state.muxChannel2Device); + muxChannel3Monitor.configure(state.muxChannel3Device); + muxChannel4Monitor.configure(state.muxChannel4Device); + muxChannel5Monitor.configure(state.muxChannel5Device); + muxChannel7Monitor.configure(state.muxChannel7Device); } void startRateGroups() { diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp index 00b11005..cf7aee2f 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp @@ -80,6 +80,15 @@ struct TopologyState { const device* lsm6dsoDevice; //!< LSM6DSO device path for accelerometer/gyroscope const device* lis2mdlDevice; //!< LIS2MDL device path for magnetometer const device* rtcDevice; //!< RTC device path + const device* tca9548aDevice; //!< TCA9548A I2C multiplexer device + const device* muxChannel0Device; //!< Multiplexer channel 0 device + const device* muxChannel1Device; //!< Multiplexer channel 1 device + const device* muxChannel2Device; //!< Multiplexer channel 2 device + const device* muxChannel3Device; //!< Multiplexer channel 3 device + const device* muxChannel4Device; //!< Multiplexer channel 4 device + const device* muxChannel5Device; //!< Multiplexer channel 5 device + const device* muxChannel6Device; //!< Multiplexer channel 5 device + const device* muxChannel7Device; //!< Multiplexer channel 7 device }; namespace PingEntries = ::PingEntries; diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp index a2cd9211..430025d3 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp @@ -142,4 +142,22 @@ module ReferenceDeployment { instance startupManager: Components.StartupManager base id 0x1003F000 + instance tcaMonitor: Components.GenericDeviceMonitor base id 0x10041000 + + instance muxChannel0Monitor: Components.GenericDeviceMonitor base id 0x10042000 + + instance muxChannel1Monitor: Components.GenericDeviceMonitor base id 0x10043000 + + instance muxChannel2Monitor: Components.GenericDeviceMonitor base id 0x10044000 + + instance muxChannel3Monitor: Components.GenericDeviceMonitor base id 0x10045000 + + instance muxChannel4Monitor: Components.GenericDeviceMonitor base id 0x10046000 + + instance muxChannel5Monitor: Components.GenericDeviceMonitor base id 0x10047000 + + instance muxChannel6Monitor: Components.GenericDeviceMonitor base id 0x10048000 + + instance muxChannel7Monitor: Components.GenericDeviceMonitor base id 0x10049000 + } diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp index 0390534e..58855540 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp @@ -68,6 +68,15 @@ module ReferenceDeployment { instance ina219SolManager instance resetManager instance modeManager + instance tcaMonitor + instance muxChannel0Monitor + instance muxChannel1Monitor + instance muxChannel2Monitor + instance muxChannel3Monitor + instance muxChannel4Monitor + instance muxChannel5Monitor + instance muxChannel6Monitor + instance muxChannel7Monitor # ---------------------------------------------------------------------- @@ -173,6 +182,14 @@ module ReferenceDeployment { rateGroup1Hz.RateGroupMemberOut[11] -> startupManager.run rateGroup1Hz.RateGroupMemberOut[12] -> powerMonitor.run rateGroup1Hz.RateGroupMemberOut[13] -> modeManager.run + rateGroup1Hz.RateGroupMemberOut[14] -> tcaMonitor.run + rateGroup1Hz.RateGroupMemberOut[15] -> muxChannel0Monitor.run + rateGroup1Hz.RateGroupMemberOut[16] -> muxChannel1Monitor.run + rateGroup1Hz.RateGroupMemberOut[17] -> muxChannel2Monitor.run + rateGroup1Hz.RateGroupMemberOut[18] -> muxChannel3Monitor.run + rateGroup1Hz.RateGroupMemberOut[19] -> muxChannel4Monitor.run + rateGroup1Hz.RateGroupMemberOut[20] -> muxChannel5Monitor.run + rateGroup1Hz.RateGroupMemberOut[21] -> muxChannel7Monitor.run } diff --git a/FprimeZephyrReference/project/config/AcConstants.fpp b/FprimeZephyrReference/project/config/AcConstants.fpp index 8eeefb4b..50398f38 100644 --- a/FprimeZephyrReference/project/config/AcConstants.fpp +++ b/FprimeZephyrReference/project/config/AcConstants.fpp @@ -4,7 +4,7 @@ # ====================================================================== @ Number of rate group member output ports for ActiveRateGroup -constant ActiveRateGroupOutputPorts = 15 +constant ActiveRateGroupOutputPorts = 22 @ Number of rate group member output ports for PassiveRateGroup constant PassiveRateGroupOutputPorts = 10 diff --git a/FprimeZephyrReference/test/int/generic_device_monitor_test.py b/FprimeZephyrReference/test/int/generic_device_monitor_test.py new file mode 100644 index 00000000..e64f6b7c --- /dev/null +++ b/FprimeZephyrReference/test/int/generic_device_monitor_test.py @@ -0,0 +1,24 @@ +""" +generic_device_monitor_test.py: + +Integration tests for the Generic Device Monitor component. +""" + +from fprime_gds.common.data_types.ch_data import ChData +from fprime_gds.common.testing_fw.api import IntegrationTestAPI + +# We use the tcaMonitor instance to test the GenericDeviceMonitor component +tcaMonitor = "ReferenceDeployment.tcaMonitor" + + +def test_01_generic_device_monitor_healthy( + fprime_test_api: IntegrationTestAPI, start_gds +): + """Test that the Generic Device Monitor reports Healthy""" + result: ChData = fprime_test_api.assert_telemetry( + f"{tcaMonitor}.Healthy", start="NOW", timeout=5 + ) + + assert str(result.get_val()) == "Healthy", ( + f"Generic Device Monitor should be Healthy, got {result.get_val()}" + ) diff --git a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5-pinctrl.dtsi b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5-pinctrl.dtsi index 48167dd4..ce52e817 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5-pinctrl.dtsi +++ b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5-pinctrl.dtsi @@ -11,6 +11,26 @@ input-enable; }; }; + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + + group2 { + pinmux = ; + input-enable; + }; + }; + uart1_default: uart1_default { + group1 { + pinmux = ; + }; + + group2 { + pinmux = ; + input-enable; + }; + }; spi1_default: spi1_default { group1 { pinmux = , ; diff --git a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi index 78eb6a54..4a3b310a 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi +++ b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi @@ -136,6 +136,285 @@ zephyr_udc0: &usbd { lsb-microamp = <61>; label = "INA219 sol"; }; + + tca9548a: tca9548a@77 { + compatible = "ti,tca9548a"; + status = "okay"; + reg = <0x77>; + #address-cells = <1>; + #size-cells = <0>; + label = "TCA9548A"; + reset-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + + mux_channel_0: i2c_mux@0 { + compatible = "ti,tca9548a-channel"; + label = "mux_channel_0"; + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + face0_temp_sens: tmp112@48 { + compatible = "ti,tmp112"; + reg = <0x48>; + status = "okay"; + label = "FACE0_TMP112"; + zephyr,deferred-init; + }; + + face0_light_sens: light@29 { + compatible = "vishay,veml6031"; + reg = <0x29>; + status = "okay"; + label = "FACE0_VEML6031"; + zephyr,deferred-init; + }; + + face0_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "FACE0_DRV2605"; + zephyr,deferred-init; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + + }; + + mux_channel_1: i2c_mux@1 { + compatible = "ti,tca9548a-channel"; + label = "mux_channel_1"; + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + face1_temp_sens: tmp112@48 { + compatible = "ti,tmp112"; + reg = <0x48>; + status = "okay"; + label = "FACE1_TMP112"; + zephyr,deferred-init; + }; + + face1_light_sens: light@29 { + compatible = "vishay,veml6031"; + reg = <0x29>; + status = "okay"; + label = "FACE1_VEML6031"; + zephyr,deferred-init; + }; + + face1_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "FACE1_DRV2605"; + zephyr,deferred-init; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + + }; + + mux_channel_2: i2c_mux@2 { + compatible = "ti,tca9548a-channel"; + label = "mux_channel_2"; + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + face2_temp_sens: tmp112@48 { + compatible = "ti,tmp112"; + reg = <0x48>; + status = "okay"; + label = "FACE2_TMP112"; + zephyr,deferred-init; + }; + + face2_light_sens: light@29 { + compatible = "vishay,veml6031"; + reg = <0x29>; + status = "okay"; + label = "FACE2_VEML6031"; + zephyr,deferred-init; + }; + + face2_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "FACE2_DRV2605"; + zephyr,deferred-init; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + + }; + + mux_channel_3: i2c_mux@3 { + compatible = "ti,tca9548a-channel"; + label = "mux_channel_3"; + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + face3_temp_sens: tmp112@48 { + compatible = "ti,tmp112"; + reg = <0x48>; + status = "okay"; + label = "FACE3_TMP112"; + zephyr,deferred-init; + }; + + face3_light_sens: light@29 { + compatible = "vishay,veml6031"; + reg = <0x29>; + status = "okay"; + label = "FACE3_VEML6031"; + zephyr,deferred-init; + }; + + face3_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "FACE3_DRV2605"; + zephyr,deferred-init; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + + }; + + // Battery + mux_channel_4: i2c_mux@4 { + compatible = "ti,tca9548a-channel"; + label = "mux_channel_4"; + reg = <4>; + #address-cells = <1>; + #size-cells = <0>; + batt_cell1_temp_sens: tmp112@48 { + compatible = "ti,tmp112"; + reg = <0x48>; + status = "okay"; + }; + batt_cell2_temp_sens: tmp112@49 { + compatible = "ti,tmp112"; + reg = <0x49>; + status = "okay"; + }; + batt_cell3_temp_sens: tmp112@4a { + compatible = "ti,tmp112"; + reg = <0x4a>; + status = "okay"; + }; + batt_cell4_temp_sens: tmp112@4b { + compatible = "ti,tmp112"; + reg = <0x4b>; + status = "okay"; + }; + }; + + // Z- Face x1 + mux_channel_5: i2c_mux@5 { + compatible = "ti,tca9548a-channel"; + label = "mux_channel_5"; + reg = <5>; + #address-cells = <1>; + #size-cells = <0>; + + face5_temp_sens: tmp112@48 { + compatible = "ti,tmp112"; + reg = <0x48>; + status = "okay"; + label = "FACE5_TMP112"; + zephyr,deferred-init; + }; + + face5_light_sens: light@29 { + compatible = "vishay,veml6031"; + reg = <0x29>; + status = "okay"; + label = "FACE5_VEML6031"; + zephyr,deferred-init; + }; + + face5_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "FACE5_DRV2605"; + zephyr,deferred-init; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + + }; + + // Z- Face x2 + mux_channel_6: i2c_mux@6 { + compatible = "ti,tca9548a-channel"; + label = "mux_channel_6"; + reg = <6>; + #address-cells = <1>; + #size-cells = <0>; + + face6_temp_sens: tmp112@48 { + compatible = "ti,tmp112"; + reg = <0x48>; + status = "okay"; + label = "FACE5_TMP112"; + zephyr,deferred-init; + }; + + face6_light_sens: light@29 { + compatible = "vishay,veml6031"; + reg = <0x29>; + status = "okay"; + label = "FACE5_VEML6031"; + zephyr,deferred-init; + }; + + face6_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "FACE5_DRV2605"; + zephyr,deferred-init; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + + }; + + // Top is always powered so no deferred init needed + mux_channel_7: i2c_mux@7 { + compatible = "ti,tca9548a-channel"; + label = "mux_channel_7"; + reg = <7>; + #address-cells = <1>; + #size-cells = <0>; + // TODO add top cap temp sensor (it's not a TMP112) + face7_light_sens: light@29 { + compatible = "vishay,veml6031"; + reg = <0x29>; + status = "okay"; + label = "FACE7_VEML6031"; + }; + }; + }; }; @@ -187,19 +466,19 @@ zephyr_udc0: &usbd { * 5: RF2_IO1 (GPA5) * 6: RF2_IO0 (GPA6) * 7: RF2_IO3 (GPA7) - * 8: FACE4_ENABLE (GPB0) + * 8: FACE5_ENABLE (GPB5) * 9: FACE0_ENABLE (GPB1) * 10: FACE1_ENABLE (GPB2) * 11: FACE2_ENABLE (GPB3) * 12: FACE3_ENABLE (GPB4) - * 13: FACE5_ENABLE (GPB5) + * 13: FACE4_ENABLE (GPB0) * 14: READONLY (GPB6) * 15: CHARGE (GPB7) */ gpio-line-names = "ENABLE_HEATER", "PAYLOAD_PWR_ENABLE", "FIRE_DEPLOY2_B", "PAYLOAD_BATT_ENABLE", "RF2_IO2", "RF2_IO1", "RF2_IO0", "RF2_IO3", - "FACE4_ENABLE", "FACE0_ENABLE", "FACE1_ENABLE", "FACE2_ENABLE", - "FACE3_ENABLE", "FACE5_ENABLE", "READONLY", "CHARGE"; + "FACE5_ENABLE", "FACE0_ENABLE", "FACE1_ENABLE", "FACE2_ENABLE", + "FACE3_ENABLE", "FACE4_ENABLE", "READONLY", "CHARGE"; reset-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; @@ -214,10 +493,10 @@ zephyr_udc0: &usbd { gpio_outputs { compatible = "gpio-leds"; // Using gpio-leds as a convenient container - face4_enable: face4-enable { + face5_enable: face5-enable { - gpios = <&mcp23017 8 GPIO_ACTIVE_HIGH>; // GPB0 - label = "FACE4_ENABLE"; + gpios = <&mcp23017 8 GPIO_ACTIVE_HIGH>; // GPB5 + label = "FACE5_ENABLE"; }; face0_enable: face0-enable { @@ -244,10 +523,10 @@ zephyr_udc0: &usbd { label = "FACE3_ENABLE"; }; - face5_enable: face5-enable { + face4_enable: face4-enable { - gpios = <&mcp23017 13 GPIO_ACTIVE_HIGH>; // GPB5 - label = "FACE5_ENABLE"; + gpios = <&mcp23017 13 GPIO_ACTIVE_HIGH>; // GPB0 + label = "FACE4_ENABLE"; }; enable_heater: enable-heater { diff --git a/boards/bronco_space/proves_flight_control_board_v5c/proves_flight_control_board_v5c_rp2350a_m33_defconfig b/boards/bronco_space/proves_flight_control_board_v5c/proves_flight_control_board_v5c_rp2350a_m33_defconfig index 176cb4e4..7a5b0c34 100644 --- a/boards/bronco_space/proves_flight_control_board_v5c/proves_flight_control_board_v5c_rp2350a_m33_defconfig +++ b/boards/bronco_space/proves_flight_control_board_v5c/proves_flight_control_board_v5c_rp2350a_m33_defconfig @@ -18,11 +18,15 @@ CONFIG_CDC_ACM_SERIAL_PID=0x000F CONFIG_CDC_ACM_SERIAL_VID=0x0028 CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING="PROVES Flight Control Board v5c" +CONFIG_I2C_TCA954X=y + # Sensors CONFIG_LSM6DSO=y CONFIG_LSM6DSO_ENABLE_TEMP=y CONFIG_LIS2MDL=y CONFIG_INA219=y +CONFIG_TMP112=y +CONFIG_VEML6031=y # Radio CONFIG_LORA=y diff --git a/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33_defconfig b/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33_defconfig index 12f07e11..daaf56bd 100644 --- a/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33_defconfig +++ b/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33_defconfig @@ -18,11 +18,15 @@ CONFIG_CDC_ACM_SERIAL_PID=0x000F CONFIG_CDC_ACM_SERIAL_VID=0x0028 CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING="PROVES Flight Control Board v5d" +CONFIG_I2C_TCA954X=y + # Sensors CONFIG_LSM6DSO=y CONFIG_LSM6DSO_ENABLE_TEMP=y CONFIG_LIS2MDL=y CONFIG_INA219=y +CONFIG_TMP112=y +CONFIG_VEML6031=y # Radio CONFIG_LORA=y diff --git a/prj.conf b/prj.conf index 1829a68f..d54b91ee 100644 --- a/prj.conf +++ b/prj.conf @@ -28,6 +28,13 @@ CONFIG_SPI=y CONFIG_PINCTRL=y CONFIG_ASSERT=y +#### I2C Multiplexer Configuration #### +CONFIG_I2C_TCA954X=y +# Priority order: I2C Bus (16) < GPIO (11) < Mux Root (70) < Mux Channels (71) < Load Switches (75) < Sensors (90) +# Mux must initialize AFTER I2C bus (16) and GPIO (11) but BEFORE sensors (90) +CONFIG_I2C_TCA954X_ROOT_INIT_PRIO=70 +CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO=71 + CONFIG_DYNAMIC_THREAD=y CONFIG_KERNEL_MEM_POOL=y CONFIG_DYNAMIC_THREAD_ALLOC=n @@ -46,7 +53,8 @@ CONFIG_COMMON_LIBC_MALLOC=y CONFIG_SENSOR=y -CONFIG_LOG=n +# Enable detailed logging for I2C and sensor debugging +CONFIG_LOG=y CONFIG_LOG_DEFAULT_LEVEL=3 CONFIG_CBPRINTF_FP_SUPPORT=y