diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 82edcb3737..2aac2bb1f5 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -131,6 +131,22 @@ "isDefault": true } }, + { + "label": "Build Firmware (TDG PDM8)", + "type": "shell", + "command": "make -j12 PROJECT_BOARD=tdg-pdm8", + "windows": { + "command": "wsl bash -lc 'make -j12 PROJECT_BOARD=tdg-pdm8'" + }, + "options": { + "cwd": "${workspaceRoot}/firmware" + }, + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": true + } + }, { "label": "Build Unit Tests", "type": "shell", diff --git a/firmware/config/boards/tdg-pdm8/board.mk b/firmware/config/boards/tdg-pdm8/board.mk index 22a075f9d8..a959c89d91 100644 --- a/firmware/config/boards/tdg-pdm8/board.mk +++ b/firmware/config/boards/tdg-pdm8/board.mk @@ -5,6 +5,12 @@ PROJECT_CPU = ARCH_STM32F4 DDEFS += -DLED_CRITICAL_ERROR_BRAIN_PIN=Gpio::C11 +# No serial ports for now +DDEFS += -DTS_NO_PRIMARY=TRUE -DTS_NO_SECONDARY=TRUE + +# No USB +DDEFS += -DEFI_USB_SERIAL=FALSE + # We're running on TDG PDM hardware! DDEFS += -DHW_TDG_PDM8=1 diff --git a/firmware/config/boards/tdg-pdm8/board_configuration.cpp b/firmware/config/boards/tdg-pdm8/board_configuration.cpp index 546427155c..8a2e474f81 100644 --- a/firmware/config/boards/tdg-pdm8/board_configuration.cpp +++ b/firmware/config/boards/tdg-pdm8/board_configuration.cpp @@ -1,5 +1,7 @@ #include "pch.h" +#include "protected_gpio.h" + void setSdCardConfigurationOverrides() { } @@ -14,3 +16,25 @@ void setBoardConfigOverrides() { engineConfiguration->canTxPin = Gpio::A12; engineConfiguration->canRxPin = Gpio::A11; } + +// TODO: these are made up values +static constexpr float AmpsPerVolt = 10; + +// instantaneous limit is 100A +// long-term limit is 20A +static constexpr float MaxCurrent = 100; + +static const ProtectedGpioConfig cfgs[] = { + { Gpio::A0, EFI_ADC_10, AmpsPerVolt, MaxCurrent }, + { Gpio::A1, EFI_ADC_11, AmpsPerVolt, MaxCurrent }, + { Gpio::A2, EFI_ADC_12, AmpsPerVolt, MaxCurrent }, + { Gpio::A3, EFI_ADC_13, AmpsPerVolt, MaxCurrent }, + { Gpio::C9, EFI_ADC_14, AmpsPerVolt, MaxCurrent }, + { Gpio::A8, EFI_ADC_15, AmpsPerVolt, MaxCurrent }, + { Gpio::A9, EFI_ADC_8, AmpsPerVolt, MaxCurrent }, + { Gpio::A10, EFI_ADC_9, AmpsPerVolt, MaxCurrent }, +}; + +void boardInitHardware() { + protectedGpio_add(Gpio::PROTECTED_PIN_0, cfgs); +} diff --git a/firmware/config/boards/tdg-pdm8/connectors/main.yaml b/firmware/config/boards/tdg-pdm8/connectors/main.yaml index ae288cf640..fdbdad84d7 100644 --- a/firmware/config/boards/tdg-pdm8/connectors/main.yaml +++ b/firmware/config/boards/tdg-pdm8/connectors/main.yaml @@ -7,56 +7,56 @@ pins: ts_name: Battery Sense - pin: 3/13 - id: A10 + id: PROTECTED_PIN_7 class: outputs function: High Side Output type: hs ts_name: Out 8 - pin: 4/14 - id: A9 + id: PROTECTED_PIN_6 class: outputs function: High Side Output type: hs ts_name: Out 7 - pin: 5/15 - id: A8 + id: PROTECTED_PIN_5 class: outputs function: High Side Output type: hs ts_name: Out 6 - pin: 6/16 - id: C9 + id: PROTECTED_PIN_4 class: outputs function: High Side Output type: hs ts_name: Out 5 - pin: 7/17 - id: A3 + id: PROTECTED_PIN_3 class: outputs function: High Side Output type: hs ts_name: Out 4 - pin: 8/18 - id: A2 + id: PROTECTED_PIN_2 class: outputs function: High Side Output type: hs ts_name: Out 3 - pin: 9/19 - id: A1 + id: PROTECTED_PIN_1 class: outputs function: High Side Output type: hs ts_name: Out 2 - pin: 10/20 - id: A0 + id: PROTECTED_PIN_0 class: outputs function: High Side Output type: hs diff --git a/firmware/controllers/algo/rusefi_hw_enums.h b/firmware/controllers/algo/rusefi_hw_enums.h index f52991c175..8d1f010941 100644 --- a/firmware/controllers/algo/rusefi_hw_enums.h +++ b/firmware/controllers/algo/rusefi_hw_enums.h @@ -270,42 +270,37 @@ enum class Gpio : uint16_t { L9779_OUT_MRD = 247, L9779_PIN_KEY = 248, - CAN_PIN_0 = 250, - CAN_PIN_1 = 251, - CAN_PIN_2 = 252, - CAN_PIN_3 = 253, - CAN_PIN_4 = 254, - CAN_PIN_5 = 255, - CAN_PIN_6 = 256, - CAN_PIN_7 = 257, + CAN_PIN_0 = 249, + CAN_PIN_1 = 250, + CAN_PIN_2 = 251, + CAN_PIN_3 = 252, + CAN_PIN_4 = 253, + CAN_PIN_5 = 254, + CAN_PIN_6 = 255, + CAN_PIN_7 = 256, - PROTECTED_PIN_0 = 290, - PROTECTED_PIN_1 = 291, - PROTECTED_PIN_2 = 292, - PROTECTED_PIN_3 = 293, - PROTECTED_PIN_4 = 294, - PROTECTED_PIN_5 = 295, - PROTECTED_PIN_6 = 296, - PROTECTED_PIN_7 = 297, - PROTECTED_PIN_8 = 298, - PROTECTED_PIN_9 = 299, - PROTECTED_PIN_10 = 300, - PROTECTED_PIN_11 = 301, - PROTECTED_PIN_12 = 302, - PROTECTED_PIN_13 = 303, - PROTECTED_PIN_14 = 304, - PROTECTED_PIN_15 = 305, - PROTECTED_PIN_16 = 306, - PROTECTED_PIN_17 = 307, + PROTECTED_PIN_0 = 257, + PROTECTED_PIN_1 = 258, + PROTECTED_PIN_2 = 259, + PROTECTED_PIN_3 = 260, + PROTECTED_PIN_4 = 261, + PROTECTED_PIN_5 = 262, + PROTECTED_PIN_6 = 263, + PROTECTED_PIN_7 = 264, + PROTECTED_PIN_8 = 265, + PROTECTED_PIN_9 = 266, + PROTECTED_PIN_10 = 267, + PROTECTED_PIN_11 = 268, + PROTECTED_PIN_12 = 269, + PROTECTED_PIN_13 = 270, + PROTECTED_PIN_14 = 271, + PROTECTED_PIN_15 = 272, }; /* Please keep updating these defines */ -#ifndef BRAIN_PIN_ONCHIP_LAST #define BRAIN_PIN_ONCHIP_LAST Gpio::I15 -#endif - #define BRAIN_PIN_ONCHIP_PINS (BRAIN_PIN_ONCHIP_LAST - Gpio::A0 + 1) -#define BRAIN_PIN_LAST Gpio::L9779_PIN_KEY +#define BRAIN_PIN_LAST Gpio::PROTECTED_PIN_15 #define BRAIN_PIN_TOTAL_PINS (BRAIN_PIN_LAST - Gpio::A0 + 1) /** diff --git a/firmware/hw_layer/adc/adc_inputs.cpp b/firmware/hw_layer/adc/adc_inputs.cpp index caae890c6b..2f212d0c0b 100644 --- a/firmware/hw_layer/adc/adc_inputs.cpp +++ b/firmware/hw_layer/adc/adc_inputs.cpp @@ -28,6 +28,7 @@ #include "AdcConfiguration.h" #include "mpu_util.h" #include "periodic_thread_controller.h" +#include "protected_gpio.h" /* Depth of the conversion buffer, channels are sampled X times each.*/ #ifndef ADC_BUF_DEPTH_FAST @@ -387,6 +388,8 @@ public: slowAdcCounter++; AdcSubscription::UpdateSubscribers(nowNt); + + protectedGpio_check(nowNt); } } }; diff --git a/firmware/hw_layer/drivers/drivers.mk b/firmware/hw_layer/drivers/drivers.mk index a165911ac2..b74c8529e9 100644 --- a/firmware/hw_layer/drivers/drivers.mk +++ b/firmware/hw_layer/drivers/drivers.mk @@ -26,4 +26,5 @@ HW_LAYER_DRIVERS_CPP = \ $(DRIVERS_DIR)/gpio/mc33810.cpp \ $(DRIVERS_DIR)/gpio/drv8860.cpp \ $(DRIVERS_DIR)/gpio/l9779.cpp \ + $(DRIVERS_DIR)/gpio/protected_gpio.cpp \ $(DRIVERS_DIR)/lcd/HD44780.cpp \ diff --git a/firmware/hw_layer/drivers/gpio/protected_gpio.cpp b/firmware/hw_layer/drivers/gpio/protected_gpio.cpp new file mode 100644 index 0000000000..0de5ce1e5e --- /dev/null +++ b/firmware/hw_layer/drivers/gpio/protected_gpio.cpp @@ -0,0 +1,152 @@ + +#include "pch.h" + +#include "protected_gpio.h" +#include "gpio/gpio_ext.h" + +#define PROTECTED_CHANNEL_COUNT 8 + +class ProtectedGpio { +public: + int setPadMode(iomode_t mode); + int set(bool value); + int get() const; + brain_pin_diag_e getDiag() const; + + void configure(const ProtectedGpioConfig& config); + void check(efitick_t nowNt); + +private: + OutputPin m_output; + + const ProtectedGpioConfig* m_config; +}; + +void ProtectedGpio::configure(const ProtectedGpioConfig& config) { + m_config = &config; +} + +int ProtectedGpio::setPadMode(iomode_t mode) { + if (mode == PAL_MODE_OUTPUT_PUSHPULL) { + m_output.initPin("protected", m_config->Pin); + } else { + m_output.deInit(); + } + + return 0; +} + +int ProtectedGpio::set(bool value) { + if (!m_config) { + return -1; + } + + // TODO: operate state machine to handle overcurrent + m_output.setValue(value); + + return 0; +} + +int ProtectedGpio::get() const { + return m_output.getLogicValue(); +} + +void ProtectedGpio::check(efitick_t /*nowNt*/) { + if (!m_config) { + return; + } + + float senseVolts = getVoltage("protected", m_config->SenseChannel); + float amps = senseVolts * m_config->AmpsPerVolt; + + // TODO: smarter state machine + if (amps > m_config->MaximumAllowedCurrent) { + m_output.setValue(false); + } +} + +brain_pin_diag_e ProtectedGpio::getDiag() const { + // TODO: return PIN_OVERLOAD if there's a problem + return PIN_OK; +} + +class ProtectedGpios : public GpioChip { +public: + int init() override { return 0; } + int setPadMode(size_t pin, iomode_t mode) override; + int writePad(size_t pin, int value) override; + int readPad(size_t pin) override; + + brain_pin_diag_e getDiag(size_t pin) override; + + void configure(const ProtectedGpioConfig* const configs); + void check(efitick_t nowNt); + +private: + ProtectedGpio m_channels[PROTECTED_CHANNEL_COUNT]; +}; + +int ProtectedGpios::setPadMode(size_t pin, iomode_t mode) { + if (pin >= PROTECTED_CHANNEL_COUNT) { + return -1; + } + + return m_channels[pin].setPadMode(mode); +} + +int ProtectedGpios::writePad(size_t pin, int value) { + if (pin >= PROTECTED_CHANNEL_COUNT) { + return -1; + } + + return m_channels[pin].set(value); +} + +int ProtectedGpios::readPad(size_t pin) { + if (pin >= PROTECTED_CHANNEL_COUNT) { + return -1; + } + + return m_channels[pin].get(); +} + +brain_pin_diag_e ProtectedGpios::getDiag(size_t pin) { + if (pin >= PROTECTED_CHANNEL_COUNT) { + return PIN_INVALID; + } + + return m_channels[pin].getDiag(); +} + +void ProtectedGpios::configure(const ProtectedGpioConfig* const configs) { + for (size_t i = 0; i < efi::size(m_channels); i++) { + m_channels[i].configure(configs[i]); + } +} + +void ProtectedGpios::check(efitick_t nowNt) { + for (size_t i = 0; i < efi::size(m_channels); i++) { + m_channels[i].check(nowNt); + } +} + +static ProtectedGpios protectedGpios; +static bool didInit = false; + +int protectedGpio_add(brain_pin_e base, const ProtectedGpioConfig* const configs) { + protectedGpios.configure(configs); + + int result = gpiochip_register(base, "protected", protectedGpios, PROTECTED_CHANNEL_COUNT); + + if (result == static_cast(base)) { + didInit = true; + } + + return result; +} + +void protectedGpio_check(efitick_t nowNt) { + if (didInit) { + protectedGpios.check(nowNt); + } +} diff --git a/firmware/hw_layer/drivers/gpio/protected_gpio.h b/firmware/hw_layer/drivers/gpio/protected_gpio.h new file mode 100644 index 0000000000..9628075661 --- /dev/null +++ b/firmware/hw_layer/drivers/gpio/protected_gpio.h @@ -0,0 +1,16 @@ +#pragma once + +struct ProtectedGpioConfig { + // Output config + brain_pin_e Pin; + + // Sense config + adc_channel_e SenseChannel; + float AmpsPerVolt; + + // Instantaneous trip current + float MaximumAllowedCurrent; +}; + +int protectedGpio_add(brain_pin_e base, const ProtectedGpioConfig* const configs); +void protectedGpio_check(efitick_t nowNt);