From f3557a66ac51d1e103dfecf58d6fb82103715565 Mon Sep 17 00:00:00 2001 From: qzhhhi Date: Mon, 9 Mar 2026 13:51:48 +0000 Subject: [PATCH 1/2] feat(gpio): Add GPIO PWM write support and implement for c_board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Define GPIO digital/analog write protocol (header, serializer, deserializer) with read variants reserved for future work. - Expose gpio_digital_transmit / gpio_analog_transmit in host CBoard agent. - Map c_board channels 1–7 to TIM1 CH1–4 and TIM8 CH1–3 PWM outputs at 50 Hz. --- core/include/librmcs/data/datas.hpp | 10 + core/src/protocol/deserializer.cpp | 44 ++++ core/src/protocol/deserializer.hpp | 6 + core/src/protocol/protocol.hpp | 20 ++ core/src/protocol/serializer.hpp | 67 +++++ firmware/c_board/app/src/app.cpp | 4 + firmware/c_board/app/src/gpio/gpio.cpp | 2 + firmware/c_board/app/src/gpio/gpio.hpp | 73 ++++++ firmware/c_board/app/src/usb/vendor.hpp | 9 + firmware/c_board/bsp/cubemx/Core/Inc/main.h | 14 ++ firmware/c_board/bsp/cubemx/Core/Inc/tim.h | 6 + firmware/c_board/bsp/cubemx/Core/Src/gpio.c | 2 + firmware/c_board/bsp/cubemx/Core/Src/tim.c | 266 +++++++++++++++++++- firmware/c_board/bsp/cubemx/rmcs_slave.ioc | 130 +++++++--- firmware/rmcs_board/src/usb/vendor.hpp | 8 + host/include/librmcs/agent/c_board.hpp | 13 + host/include/librmcs/protocol/handler.hpp | 4 + host/src/protocol/handler.cpp | 26 ++ 18 files changed, 671 insertions(+), 33 deletions(-) create mode 100644 firmware/c_board/app/src/gpio/gpio.hpp diff --git a/core/include/librmcs/data/datas.hpp b/core/include/librmcs/data/datas.hpp index 34e5686..a85140a 100644 --- a/core/include/librmcs/data/datas.hpp +++ b/core/include/librmcs/data/datas.hpp @@ -42,6 +42,16 @@ struct UartDataView { bool idle_delimited = false; }; +struct GpioDigitalDataView { + uint8_t channel; + bool high; +}; + +struct GpioAnalogDataView { + uint8_t channel; + uint16_t value; +}; + struct AccelerometerDataView { int16_t x; int16_t y; diff --git a/core/src/protocol/deserializer.cpp b/core/src/protocol/deserializer.cpp index 24d6d0c..a9375ae 100644 --- a/core/src/protocol/deserializer.cpp +++ b/core/src/protocol/deserializer.cpp @@ -51,6 +51,7 @@ coroutine::LifoTask Deserializer::process_stream() { case FieldId::kUart1: case FieldId::kUart2: case FieldId::kUart3: success = co_await process_uart_field(id); break; + case FieldId::kGpio: success = co_await process_gpio_field(id); break; case FieldId::kImu: success = co_await process_imu_field(id); break; default: break; } @@ -150,6 +151,49 @@ coroutine::LifoTask Deserializer::process_uart_field(FieldId field_id) { co_return true; } +coroutine::LifoTask Deserializer::process_gpio_field(FieldId) { + GpioHeader::PayloadEnum payload_type; + std::uint8_t channel = 0; + { + const auto* header_bytes = co_await peek_bytes(sizeof(GpioHeader)); + if (!header_bytes) [[unlikely]] + co_return false; + + auto header = GpioHeader::CRef{header_bytes}; + payload_type = header.get(); + channel = header.get(); + consume_peeked(); + } + + switch (payload_type) { + case GpioHeader::PayloadEnum::kDigitalWriteLow: + case GpioHeader::PayloadEnum::kDigitalWriteHigh: { + data::GpioDigitalDataView data_view{}; + data_view.channel = channel; + data_view.high = payload_type == GpioHeader::PayloadEnum::kDigitalWriteHigh; + callback_.gpio_digital_deserialized_callback(data_view); + break; + } + case GpioHeader::PayloadEnum::kAnalogWrite: { + const auto* payload_bytes = co_await peek_bytes(sizeof(GpioAnalogPayload)); + if (!payload_bytes) [[unlikely]] + co_return false; + + auto payload = GpioAnalogPayload::CRef{payload_bytes}; + data::GpioAnalogDataView data_view{}; + data_view.channel = channel; + data_view.value = payload.get(); + consume_peeked(); + + callback_.gpio_analog_deserialized_callback(data_view); + break; + } + default: co_return false; + } + + co_return true; +} + coroutine::LifoTask Deserializer::process_imu_field(FieldId) { ImuHeader::PayloadEnum payload_type; { diff --git a/core/src/protocol/deserializer.hpp b/core/src/protocol/deserializer.hpp index 2e1ae2a..d2b069a 100644 --- a/core/src/protocol/deserializer.hpp +++ b/core/src/protocol/deserializer.hpp @@ -27,6 +27,10 @@ class DeserializeCallback { virtual void uart_deserialized_callback(FieldId id, const data::UartDataView& data) = 0; + virtual void gpio_digital_deserialized_callback(const data::GpioDigitalDataView& data) = 0; + + virtual void gpio_analog_deserialized_callback(const data::GpioAnalogDataView& data) = 0; + virtual void accelerometer_deserialized_callback(const data::AccelerometerDataView& data) = 0; virtual void gyroscope_deserialized_callback(const data::GyroscopeDataView& data) = 0; @@ -101,6 +105,8 @@ class Deserializer : private coroutine::InlineLifoContext<1024> { coroutine::LifoTask process_uart_field(FieldId field_id); + coroutine::LifoTask process_gpio_field(FieldId field_id); + coroutine::LifoTask process_imu_field(FieldId field_id); // Await until at least `size` contiguous bytes are available at the current read position. diff --git a/core/src/protocol/protocol.hpp b/core/src/protocol/protocol.hpp index d124954..f53274a 100644 --- a/core/src/protocol/protocol.hpp +++ b/core/src/protocol/protocol.hpp @@ -82,6 +82,26 @@ struct UartHeaderExtended , layouts::UartHeaderLayout , layouts::UartHeaderExtendedLayout {}; +struct GpioHeader : utility::Bitfield<2> { + enum class PayloadEnum : uint8_t { + kDigitalWriteLow = 0b0000, + kDigitalWriteHigh = 0b0001, + kAnalogWrite = 0b0010, + kDigitalRead = 0b0100, + kAnalogRead = 0b0110, + kDigitalReadResultLow = 0b1000, + kDigitalReadResultHigh = 0b1001, + kAnalogReadResult = 0b1010, + }; + + using PayloadType = utility::BitfieldMember<4, 4, PayloadEnum>; + using Channel = utility::BitfieldMember<8, 8>; +}; + +struct GpioAnalogPayload : utility::Bitfield<2> { + using Value = utility::BitfieldMember<0, 16, uint16_t>; +}; + struct ImuHeader : utility::Bitfield<1> { enum class PayloadEnum : uint8_t { kAccelerometer = 0, diff --git a/core/src/protocol/serializer.hpp b/core/src/protocol/serializer.hpp index c521c4f..869ae3a 100644 --- a/core/src/protocol/serializer.hpp +++ b/core/src/protocol/serializer.hpp @@ -120,6 +120,53 @@ class Serializer { return SerializeResult::kSuccess; } + SerializeResult write_gpio_digital(const data::GpioDigitalDataView& view) noexcept { + const auto payload_type = view.high ? GpioHeader::PayloadEnum::kDigitalWriteHigh + : GpioHeader::PayloadEnum::kDigitalWriteLow; + const std::size_t required = required_gpio_size(FieldId::kGpio, payload_type); + LIBRMCS_VERIFY_LIKELY(required, SerializeResult::kInvalidArgument); + + auto dst = buffer_.allocate(required); + LIBRMCS_VERIFY_LIKELY(!dst.empty(), SerializeResult::kBadAlloc); + utility::assert_debug(dst.size() == required); + std::byte* cursor = dst.data(); + + write_field_header(cursor, FieldId::kGpio); + + auto header = GpioHeader::Ref(cursor); + cursor += sizeof(GpioHeader); + header.set(payload_type); + header.set(view.channel); + + utility::assert_debug(cursor == dst.data() + dst.size()); + return SerializeResult::kSuccess; + } + + SerializeResult write_gpio_analog(const data::GpioAnalogDataView& view) noexcept { + const std::size_t required = + required_gpio_size(FieldId::kGpio, GpioHeader::PayloadEnum::kAnalogWrite); + LIBRMCS_VERIFY_LIKELY(required, SerializeResult::kInvalidArgument); + + auto dst = buffer_.allocate(required); + LIBRMCS_VERIFY_LIKELY(!dst.empty(), SerializeResult::kBadAlloc); + utility::assert_debug(dst.size() == required); + std::byte* cursor = dst.data(); + + write_field_header(cursor, FieldId::kGpio); + + auto header = GpioHeader::Ref(cursor); + cursor += sizeof(GpioHeader); + header.set(GpioHeader::PayloadEnum::kAnalogWrite); + header.set(view.channel); + + auto payload = GpioAnalogPayload::Ref(cursor); + cursor += sizeof(GpioAnalogPayload); + payload.set(view.value); + + utility::assert_debug(cursor == dst.data() + dst.size()); + return SerializeResult::kSuccess; + } + SerializeResult write_imu_accelerometer(const data::AccelerometerDataView& view) noexcept { const std::size_t required = required_imu_size(FieldId::kImu, ImuPayload::kAccelerometer); LIBRMCS_VERIFY_LIKELY(required, SerializeResult::kInvalidArgument); @@ -231,6 +278,26 @@ class Serializer { return total; } + static std::size_t + required_gpio_size(FieldId field_id, GpioHeader::PayloadEnum payload) noexcept { + const std::size_t field_header_bytes = required_field_header_size(field_id); + const std::size_t gpio_header_bytes = sizeof(GpioHeader); + std::size_t payload_bytes = 0; + switch (payload) { + case GpioHeader::PayloadEnum::kDigitalWriteLow: + case GpioHeader::PayloadEnum::kDigitalWriteHigh: payload_bytes = 0; break; + case GpioHeader::PayloadEnum::kAnalogWrite: + payload_bytes = sizeof(GpioAnalogPayload); + break; + default: return 0; + } + + const std::size_t total = (field_header_bytes + gpio_header_bytes - 1) + payload_bytes; + utility::assert_debug(total <= kProtocolBufferSize); + + return total; + } + enum class ImuPayload : std::uint8_t { kAccelerometer = 0, kGyroscope = 1 }; static std::size_t required_imu_size(FieldId field_id, ImuPayload payload) noexcept { diff --git a/firmware/c_board/app/src/app.cpp b/firmware/c_board/app/src/app.cpp index 21c8e6e..cc3821c 100644 --- a/firmware/c_board/app/src/app.cpp +++ b/firmware/c_board/app/src/app.cpp @@ -11,6 +11,7 @@ #include #include "firmware/c_board/app/src/can/can.hpp" +#include "firmware/c_board/app/src/gpio/gpio.hpp" #include "firmware/c_board/app/src/led/led.hpp" #include "firmware/c_board/app/src/spi/bmi088/accel.hpp" #include "firmware/c_board/app/src/spi/bmi088/gyro.hpp" @@ -41,6 +42,8 @@ App::App() { timer::timer.init(); MX_GPIO_Init(); + MX_TIM1_Init(); + MX_TIM8_Init(); MX_DMA_Init(); MX_SPI1_Init(); MX_CAN1_Init(); @@ -58,6 +61,7 @@ App::App() { uart::uart1.init(); uart::uart2.init(); uart::uart_dbus.init(); + gpio::gpio.init(); spi::bmi088::accelerometer.init(); spi::bmi088::gyroscope.init(); } diff --git a/firmware/c_board/app/src/gpio/gpio.cpp b/firmware/c_board/app/src/gpio/gpio.cpp index 7b1434a..2aeefb6 100644 --- a/firmware/c_board/app/src/gpio/gpio.cpp +++ b/firmware/c_board/app/src/gpio/gpio.cpp @@ -1,3 +1,5 @@ +#include "firmware/c_board/app/src/gpio/gpio.hpp" + #include #include diff --git a/firmware/c_board/app/src/gpio/gpio.hpp b/firmware/c_board/app/src/gpio/gpio.hpp new file mode 100644 index 0000000..4203239 --- /dev/null +++ b/firmware/c_board/app/src/gpio/gpio.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include + +#include +#include + +#include "core/include/librmcs/data/datas.hpp" +#include "core/src/utility/assert.hpp" +#include "core/src/utility/immovable.hpp" +#include "firmware/c_board/app/src/utility/lazy.hpp" + +namespace librmcs::firmware::gpio { + +class Gpio : private core::utility::Immovable { +public: + using Lazy = utility::Lazy; + + Gpio() { + core::utility::assert_always(HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) == HAL_OK); + core::utility::assert_always(HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2) == HAL_OK); + core::utility::assert_always(HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3) == HAL_OK); + core::utility::assert_always(HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4) == HAL_OK); + core::utility::assert_always(HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1) == HAL_OK); + core::utility::assert_always(HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_2) == HAL_OK); + core::utility::assert_always(HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_3) == HAL_OK); + + set_compare(1, 0); + set_compare(2, 0); + set_compare(3, 0); + set_compare(4, 0); + set_compare(5, 0); + set_compare(6, 0); + set_compare(7, 0); + } + + void handle_digital_write(const data::GpioDigitalDataView& data) { + if (!is_supported_channel(data.channel)) + return; + + set_compare(data.channel, data.high ? kCounterPeriod : 0); + } + + void handle_analog_write(const data::GpioAnalogDataView& data) { + if (!is_supported_channel(data.channel)) + return; + + set_compare(data.channel, duty_to_compare(data.value)); + } + +private: + static constexpr uint32_t kCounterPeriod = 60000; + + static bool is_supported_channel(uint8_t channel) { return channel >= 1 && channel <= 7; } + + static uint32_t duty_to_compare(uint16_t duty) { + return ((static_cast(duty) * kCounterPeriod) + 32767U) / 65535U; + } + + void set_compare(uint8_t channel, uint32_t compare) { + core::utility::assert_debug_lazy([&]() noexcept { return is_supported_channel(channel); }); + *channel_compares_[channel - 1] = compare; + } + + volatile uint32_t* channel_compares_[7] = { + &htim1.Instance->CCR1, &htim1.Instance->CCR2, &htim1.Instance->CCR3, &htim1.Instance->CCR4, + &htim8.Instance->CCR1, &htim8.Instance->CCR2, &htim8.Instance->CCR3, + }; +}; + +inline constinit Gpio::Lazy gpio; + +} // namespace librmcs::firmware::gpio diff --git a/firmware/c_board/app/src/usb/vendor.hpp b/firmware/c_board/app/src/usb/vendor.hpp index de05346..256b5a8 100644 --- a/firmware/c_board/app/src/usb/vendor.hpp +++ b/firmware/c_board/app/src/usb/vendor.hpp @@ -16,6 +16,7 @@ #include "core/src/utility/assert.hpp" #include "core/src/utility/immovable.hpp" #include "firmware/c_board/app/src/can/can.hpp" +#include "firmware/c_board/app/src/gpio/gpio.hpp" #include "firmware/c_board/app/src/uart/uart.hpp" #include "firmware/c_board/app/src/usb/interrupt_safe_buffer.hpp" #include "firmware/c_board/app/src/usb/usb_descriptors.hpp" @@ -101,6 +102,14 @@ class Vendor } } + void gpio_digital_deserialized_callback(const data::GpioDigitalDataView& data) override { + gpio::gpio->handle_digital_write(data); + } + + void gpio_analog_deserialized_callback(const data::GpioAnalogDataView& data) override { + gpio::gpio->handle_analog_write(data); + } + void accelerometer_deserialized_callback(const data::AccelerometerDataView& data) override { (void)data; } diff --git a/firmware/c_board/bsp/cubemx/Core/Inc/main.h b/firmware/c_board/bsp/cubemx/Core/Inc/main.h index d21d030..046ce21 100644 --- a/firmware/c_board/bsp/cubemx/Core/Inc/main.h +++ b/firmware/c_board/bsp/cubemx/Core/Inc/main.h @@ -268,6 +268,12 @@ void SystemClock_Config(void); #define SPI1_MISO_GPIO_Port GPIOB #define SPI1_SCK_Pin GPIO_PIN_3 #define SPI1_SCK_GPIO_Port GPIOB +#define PWM7_Pin GPIO_PIN_7 +#define PWM7_GPIO_Port GPIOI +#define PWM6_Pin GPIO_PIN_6 +#define PWM6_GPIO_Port GPIOI +#define PWM5_Pin GPIO_PIN_6 +#define PWM5_GPIO_Port GPIOC #define LED_R_Pin GPIO_PIN_12 #define LED_R_GPIO_Port GPIOH #define LED_G_Pin GPIO_PIN_11 @@ -279,9 +285,17 @@ void SystemClock_Config(void); #define INT1_ACC_Pin GPIO_PIN_4 #define INT1_ACC_GPIO_Port GPIOC #define INT1_ACC_EXTI_IRQn EXTI4_IRQn +#define PWM3_Pin GPIO_PIN_13 +#define PWM3_GPIO_Port GPIOE #define INT1_GYRO_Pin GPIO_PIN_5 #define INT1_GYRO_GPIO_Port GPIOC #define INT1_GYRO_EXTI_IRQn EXTI9_5_IRQn +#define PWM1_Pin GPIO_PIN_9 +#define PWM1_GPIO_Port GPIOE +#define PWM2_Pin GPIO_PIN_11 +#define PWM2_GPIO_Port GPIOE +#define PWM4_Pin GPIO_PIN_14 +#define PWM4_GPIO_Port GPIOE #define SPI1_MOSI_Pin GPIO_PIN_7 #define SPI1_MOSI_GPIO_Port GPIOA #define CS1_GYRO_Pin GPIO_PIN_0 diff --git a/firmware/c_board/bsp/cubemx/Core/Inc/tim.h b/firmware/c_board/bsp/cubemx/Core/Inc/tim.h index 7ccb3fa..bca3676 100644 --- a/firmware/c_board/bsp/cubemx/Core/Inc/tim.h +++ b/firmware/c_board/bsp/cubemx/Core/Inc/tim.h @@ -32,18 +32,24 @@ extern "C" { #include "stm32f4xx_hal_tim.h" // IWYU pragma: export /* USER CODE END Includes */ +extern TIM_HandleTypeDef htim1; + extern TIM_HandleTypeDef htim2; extern TIM_HandleTypeDef htim5; +extern TIM_HandleTypeDef htim8; + extern TIM_HandleTypeDef htim9; /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ +void MX_TIM1_Init(void); void MX_TIM2_Init(void); void MX_TIM5_Init(void); +void MX_TIM8_Init(void); void MX_TIM9_Init(void); void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); diff --git a/firmware/c_board/bsp/cubemx/Core/Src/gpio.c b/firmware/c_board/bsp/cubemx/Core/Src/gpio.c index d5f5a2c..f26ae87 100644 --- a/firmware/c_board/bsp/cubemx/Core/Src/gpio.c +++ b/firmware/c_board/bsp/cubemx/Core/Src/gpio.c @@ -50,7 +50,9 @@ void MX_GPIO_Init(void) __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(CS1_ACCEL_GPIO_Port, CS1_ACCEL_Pin, GPIO_PIN_SET); diff --git a/firmware/c_board/bsp/cubemx/Core/Src/tim.c b/firmware/c_board/bsp/cubemx/Core/Src/tim.c index deee6ca..b77207c 100644 --- a/firmware/c_board/bsp/cubemx/Core/Src/tim.c +++ b/firmware/c_board/bsp/cubemx/Core/Src/tim.c @@ -24,10 +24,94 @@ /* USER CODE END 0 */ +TIM_HandleTypeDef htim1; TIM_HandleTypeDef htim2; TIM_HandleTypeDef htim5; +TIM_HandleTypeDef htim8; TIM_HandleTypeDef htim9; +/* TIM1 init function */ +void MX_TIM1_Init(void) +{ + + /* USER CODE BEGIN TIM1_Init 0 */ + + /* USER CODE END TIM1_Init 0 */ + + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_OC_InitTypeDef sConfigOC = {0}; + TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; + + /* USER CODE BEGIN TIM1_Init 1 */ + + /* USER CODE END TIM1_Init 1 */ + htim1.Instance = TIM1; + htim1.Init.Prescaler = 56 - 1; + htim1.Init.CounterMode = TIM_COUNTERMODE_UP; + htim1.Init.Period = 59999; + htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim1.Init.RepetitionCounter = 0; + htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(&htim1) != HAL_OK) + { + Error_Handler(); + } + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_Init(&htim1) != HAL_OK) + { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) + { + Error_Handler(); + } + sConfigOC.OCMode = TIM_OCMODE_PWM1; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; + sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; + if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) + { + Error_Handler(); + } + sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; + sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; + sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; + sBreakDeadTimeConfig.DeadTime = 0; + sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; + sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; + sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; + if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN TIM1_Init 2 */ + + /* USER CODE END TIM1_Init 2 */ + HAL_TIM_MspPostInit(&htim1); + +} /* TIM2 init function */ void MX_TIM2_Init(void) { @@ -129,6 +213,84 @@ void MX_TIM5_Init(void) /* USER CODE END TIM5_Init 2 */ HAL_TIM_MspPostInit(&htim5); +} +/* TIM8 init function */ +void MX_TIM8_Init(void) +{ + + /* USER CODE BEGIN TIM8_Init 0 */ + + /* USER CODE END TIM8_Init 0 */ + + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_OC_InitTypeDef sConfigOC = {0}; + TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; + + /* USER CODE BEGIN TIM8_Init 1 */ + + /* USER CODE END TIM8_Init 1 */ + htim8.Instance = TIM8; + htim8.Init.Prescaler = 56 - 1; + htim8.Init.CounterMode = TIM_COUNTERMODE_UP; + htim8.Init.Period = 59999; + htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim8.Init.RepetitionCounter = 0; + htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(&htim8) != HAL_OK) + { + Error_Handler(); + } + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_Init(&htim8) != HAL_OK) + { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK) + { + Error_Handler(); + } + sConfigOC.OCMode = TIM_OCMODE_PWM1; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; + sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; + if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) + { + Error_Handler(); + } + sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; + sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; + sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; + sBreakDeadTimeConfig.DeadTime = 0; + sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; + sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; + sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; + if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN TIM8_Init 2 */ + + /* USER CODE END TIM8_Init 2 */ + HAL_TIM_MspPostInit(&htim8); + } /* TIM9 init function */ void MX_TIM9_Init(void) @@ -168,7 +330,18 @@ void MX_TIM9_Init(void) void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) { - if(tim_baseHandle->Instance==TIM2) + if(tim_baseHandle->Instance==TIM1) + { + /* USER CODE BEGIN TIM1_MspInit 0 */ + + /* USER CODE END TIM1_MspInit 0 */ + /* TIM1 clock enable */ + __HAL_RCC_TIM1_CLK_ENABLE(); + /* USER CODE BEGIN TIM1_MspInit 1 */ + + /* USER CODE END TIM1_MspInit 1 */ + } + else if(tim_baseHandle->Instance==TIM2) { /* USER CODE BEGIN TIM2_MspInit 0 */ @@ -190,6 +363,17 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) /* USER CODE END TIM5_MspInit 1 */ } + else if(tim_baseHandle->Instance==TIM8) + { + /* USER CODE BEGIN TIM8_MspInit 0 */ + + /* USER CODE END TIM8_MspInit 0 */ + /* TIM8 clock enable */ + __HAL_RCC_TIM8_CLK_ENABLE(); + /* USER CODE BEGIN TIM8_MspInit 1 */ + + /* USER CODE END TIM8_MspInit 1 */ + } else if(tim_baseHandle->Instance==TIM9) { /* USER CODE BEGIN TIM9_MspInit 0 */ @@ -206,7 +390,30 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; - if(timHandle->Instance==TIM5) + if(timHandle->Instance==TIM1) + { + /* USER CODE BEGIN TIM1_MspPostInit 0 */ + + /* USER CODE END TIM1_MspPostInit 0 */ + __HAL_RCC_GPIOE_CLK_ENABLE(); + /**TIM1 GPIO Configuration + PE13 ------> TIM1_CH3 + PE9 ------> TIM1_CH1 + PE11 ------> TIM1_CH2 + PE14 ------> TIM1_CH4 + */ + GPIO_InitStruct.Pin = PWM3_Pin|PWM1_Pin|PWM2_Pin|PWM4_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; + HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); + + /* USER CODE BEGIN TIM1_MspPostInit 1 */ + + /* USER CODE END TIM1_MspPostInit 1 */ + } + else if(timHandle->Instance==TIM5) { /* USER CODE BEGIN TIM5_MspPostInit 0 */ @@ -229,13 +436,55 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle) /* USER CODE END TIM5_MspPostInit 1 */ } + else if(timHandle->Instance==TIM8) + { + /* USER CODE BEGIN TIM8_MspPostInit 0 */ + + /* USER CODE END TIM8_MspPostInit 0 */ + + __HAL_RCC_GPIOI_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + /**TIM8 GPIO Configuration + PI7 ------> TIM8_CH3 + PI6 ------> TIM8_CH2 + PC6 ------> TIM8_CH1 + */ + GPIO_InitStruct.Pin = PWM7_Pin|PWM6_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_TIM8; + HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = PWM5_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_TIM8; + HAL_GPIO_Init(PWM5_GPIO_Port, &GPIO_InitStruct); + + /* USER CODE BEGIN TIM8_MspPostInit 1 */ + + /* USER CODE END TIM8_MspPostInit 1 */ + } } void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle) { - if(tim_baseHandle->Instance==TIM2) + if(tim_baseHandle->Instance==TIM1) + { + /* USER CODE BEGIN TIM1_MspDeInit 0 */ + + /* USER CODE END TIM1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM1_CLK_DISABLE(); + /* USER CODE BEGIN TIM1_MspDeInit 1 */ + + /* USER CODE END TIM1_MspDeInit 1 */ + } + else if(tim_baseHandle->Instance==TIM2) { /* USER CODE BEGIN TIM2_MspDeInit 0 */ @@ -257,6 +506,17 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle) /* USER CODE END TIM5_MspDeInit 1 */ } + else if(tim_baseHandle->Instance==TIM8) + { + /* USER CODE BEGIN TIM8_MspDeInit 0 */ + + /* USER CODE END TIM8_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM8_CLK_DISABLE(); + /* USER CODE BEGIN TIM8_MspDeInit 1 */ + + /* USER CODE END TIM8_MspDeInit 1 */ + } else if(tim_baseHandle->Instance==TIM9) { /* USER CODE BEGIN TIM9_MspDeInit 0 */ diff --git a/firmware/c_board/bsp/cubemx/rmcs_slave.ioc b/firmware/c_board/bsp/cubemx/rmcs_slave.ioc index 8f2e7e3..99fe291 100644 --- a/firmware/c_board/bsp/cubemx/rmcs_slave.ioc +++ b/firmware/c_board/bsp/cubemx/rmcs_slave.ioc @@ -109,58 +109,69 @@ Dma.USART6_TX.7.Priority=DMA_PRIORITY_LOW Dma.USART6_TX.7.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode File.Version=6 GPIO.groupedBy=Group By Peripherals -KeepUserPlacement=false +KeepUserPlacement=true Mcu.CPN=STM32F407IGH6 Mcu.Family=STM32F4 Mcu.IP0=CAN1 Mcu.IP1=CAN2 -Mcu.IP10=USART1 -Mcu.IP11=USART3 -Mcu.IP12=USART6 -Mcu.IP13=USB_OTG_FS +Mcu.IP10=TIM8 +Mcu.IP11=TIM9 +Mcu.IP12=USART1 +Mcu.IP13=USART3 +Mcu.IP14=USART6 +Mcu.IP15=USB_OTG_FS Mcu.IP2=DMA Mcu.IP3=NVIC Mcu.IP4=RCC Mcu.IP5=SPI1 Mcu.IP6=SYS -Mcu.IP7=TIM2 -Mcu.IP8=TIM5 -Mcu.IP9=TIM9 -Mcu.IPNb=14 +Mcu.IP7=TIM1 +Mcu.IP8=TIM2 +Mcu.IP9=TIM5 +Mcu.IPNb=16 Mcu.Name=STM32F407I(E-G)Hx Mcu.Package=UFBGA176 Mcu.Pin0=PB5 Mcu.Pin1=PG14 Mcu.Pin10=PC10 Mcu.Pin11=PA12 -Mcu.Pin12=PG9 -Mcu.Pin13=PD1 -Mcu.Pin14=PA11 -Mcu.Pin15=PA9 -Mcu.Pin16=PH0-OSC_IN -Mcu.Pin17=PH1-OSC_OUT -Mcu.Pin18=PH12 -Mcu.Pin19=PH11 +Mcu.Pin12=PI7 +Mcu.Pin13=PI6 +Mcu.Pin14=PG9 +Mcu.Pin15=PD1 +Mcu.Pin16=PA11 +Mcu.Pin17=PA9 +Mcu.Pin18=PH0-OSC_IN +Mcu.Pin19=PH1-OSC_OUT Mcu.Pin2=PB4 -Mcu.Pin20=PH10 -Mcu.Pin21=PA4 -Mcu.Pin22=PC4 -Mcu.Pin23=PC5 -Mcu.Pin24=PA7 -Mcu.Pin25=PB0 -Mcu.Pin26=VP_SYS_VS_Systick -Mcu.Pin27=VP_TIM2_VS_ClockSourceINT -Mcu.Pin28=VP_TIM5_VS_ClockSourceINT -Mcu.Pin29=VP_TIM9_VS_ControllerModeClock +Mcu.Pin20=PC6 +Mcu.Pin21=PH12 +Mcu.Pin22=PH11 +Mcu.Pin23=PH10 +Mcu.Pin24=PA4 +Mcu.Pin25=PC4 +Mcu.Pin26=PE13 +Mcu.Pin27=PC5 +Mcu.Pin28=PE9 +Mcu.Pin29=PE11 Mcu.Pin3=PB3 -Mcu.Pin30=VP_TIM9_VS_ClockSourceITR +Mcu.Pin30=PE14 +Mcu.Pin31=PA7 +Mcu.Pin32=PB0 +Mcu.Pin33=VP_SYS_VS_Systick +Mcu.Pin34=VP_TIM1_VS_ClockSourceINT +Mcu.Pin35=VP_TIM2_VS_ClockSourceINT +Mcu.Pin36=VP_TIM5_VS_ClockSourceINT +Mcu.Pin37=VP_TIM8_VS_ClockSourceINT +Mcu.Pin38=VP_TIM9_VS_ControllerModeClock +Mcu.Pin39=VP_TIM9_VS_ClockSourceITR Mcu.Pin4=PA14 Mcu.Pin5=PA13 Mcu.Pin6=PB7 Mcu.Pin7=PB6 Mcu.Pin8=PD0 Mcu.Pin9=PC11 -Mcu.PinsNb=31 +Mcu.PinsNb=40 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32F407IGHx @@ -263,6 +274,10 @@ PC5.GPIO_Label=INT1_GYRO PC5.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING PC5.Locked=true PC5.Signal=GPXTI5 +PC6.GPIOParameters=GPIO_Label +PC6.GPIO_Label=PWM5 +PC6.Locked=true +PC6.Signal=S_TIM8_CH1 PCC.Checker=false PCC.Line=STM32F407/417 PCC.MCU=STM32F407I(E-G)Hx @@ -276,6 +291,22 @@ PD0.Signal=CAN1_RX PD1.Locked=true PD1.Mode=CAN_Activate PD1.Signal=CAN1_TX +PE11.GPIOParameters=GPIO_Label +PE11.GPIO_Label=PWM2 +PE11.Locked=true +PE11.Signal=S_TIM1_CH2 +PE13.GPIOParameters=GPIO_Label +PE13.GPIO_Label=PWM3 +PE13.Locked=true +PE13.Signal=S_TIM1_CH3 +PE14.GPIOParameters=GPIO_Label +PE14.GPIO_Label=PWM4 +PE14.Locked=true +PE14.Signal=S_TIM1_CH4 +PE9.GPIOParameters=GPIO_Label +PE9.GPIO_Label=PWM1 +PE9.Locked=true +PE9.Signal=S_TIM1_CH1 PG14.Locked=true PG14.Mode=Asynchronous PG14.Signal=USART6_TX @@ -300,6 +331,14 @@ PH12.GPIOParameters=GPIO_Label PH12.GPIO_Label=LED_R PH12.Locked=true PH12.Signal=S_TIM5_CH3 +PI6.GPIOParameters=GPIO_Label +PI6.GPIO_Label=PWM6 +PI6.Locked=true +PI6.Signal=S_TIM8_CH2 +PI7.GPIOParameters=GPIO_Label +PI7.GPIO_Label=PWM7 +PI7.Locked=true +PI7.Signal=S_TIM8_CH3 PinOutPanel.CurrentBGAView=Top PinOutPanel.RotationAngle=0 ProjectManager.AskForMigrate=true @@ -334,7 +373,7 @@ ProjectManager.ToolChainLocation= ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptBeforePath= ProjectManager.UnderRoot=false -ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_SPI1_Init-SPI1-false-HAL-true,5-MX_CAN1_Init-CAN1-false-HAL-true,6-MX_CAN2_Init-CAN2-false-HAL-true,7-MX_USART1_UART_Init-USART1-false-HAL-true,8-MX_USART3_UART_Init-USART3-false-HAL-true,9-MX_USART6_UART_Init-USART6-false-HAL-true,10-MX_TIM5_Init-TIM5-false-HAL-true,11-MX_USB_OTG_FS_PCD_Init-USB_OTG_FS-false-HAL-true,12-MX_TIM2_Init-TIM2-false-HAL-true,13-MX_TIM9_Init-TIM9-false-HAL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_SPI1_Init-SPI1-false-HAL-true,5-MX_CAN1_Init-CAN1-false-HAL-true,6-MX_CAN2_Init-CAN2-false-HAL-true,7-MX_USART1_UART_Init-USART1-false-HAL-true,8-MX_USART3_UART_Init-USART3-false-HAL-true,9-MX_USART6_UART_Init-USART6-false-HAL-true,10-MX_TIM5_Init-TIM5-false-HAL-true,11-MX_USB_OTG_FS_PCD_Init-USB_OTG_FS-false-HAL-true,12-MX_TIM2_Init-TIM2-false-HAL-true,13-MX_TIM9_Init-TIM9-false-HAL-true,14-MX_TIM1_Init-TIM1-false-HAL-true,15-MX_TIM8_Init-TIM8-false-HAL-true RCC.48MHZClocksFreq_Value=48000000 RCC.AHBFreq_Value=168000000 RCC.APB1CLKDivider=RCC_HCLK_DIV4 @@ -372,12 +411,26 @@ SH.GPXTI4.0=GPIO_EXTI4 SH.GPXTI4.ConfNb=1 SH.GPXTI5.0=GPIO_EXTI5 SH.GPXTI5.ConfNb=1 +SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1 +SH.S_TIM1_CH1.ConfNb=1 +SH.S_TIM1_CH2.0=TIM1_CH2,PWM Generation2 CH2 +SH.S_TIM1_CH2.ConfNb=1 +SH.S_TIM1_CH3.0=TIM1_CH3,PWM Generation3 CH3 +SH.S_TIM1_CH3.ConfNb=1 +SH.S_TIM1_CH4.0=TIM1_CH4,PWM Generation4 CH4 +SH.S_TIM1_CH4.ConfNb=1 SH.S_TIM5_CH1.0=TIM5_CH1,PWM Generation1 CH1 SH.S_TIM5_CH1.ConfNb=1 SH.S_TIM5_CH2.0=TIM5_CH2,PWM Generation2 CH2 SH.S_TIM5_CH2.ConfNb=1 SH.S_TIM5_CH3.0=TIM5_CH3,PWM Generation3 CH3 SH.S_TIM5_CH3.ConfNb=1 +SH.S_TIM8_CH1.0=TIM8_CH1,PWM Generation1 CH1 +SH.S_TIM8_CH1.ConfNb=1 +SH.S_TIM8_CH2.0=TIM8_CH2,PWM Generation2 CH2 +SH.S_TIM8_CH2.ConfNb=1 +SH.S_TIM8_CH3.0=TIM8_CH3,PWM Generation3 CH3 +SH.S_TIM8_CH3.ConfNb=1 SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_8 SPI1.CLKPhase=SPI_PHASE_2EDGE SPI1.CLKPolarity=SPI_POLARITY_HIGH @@ -386,6 +439,13 @@ SPI1.Direction=SPI_DIRECTION_2LINES SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler,CLKPhase,CLKPolarity SPI1.Mode=SPI_MODE_MASTER SPI1.VirtualType=VM_MASTER +TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 +TIM1.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2 +TIM1.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3 +TIM1.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4 +TIM1.IPParameters=Prescaler,Period,Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4 +TIM1.Period=59999 +TIM1.Prescaler=56 - 1 TIM2.IPParameters=TIM_MasterSlaveMode,TIM_MasterOutputTrigger,Prescaler TIM2.Prescaler=21 - 1 TIM2.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE @@ -396,6 +456,12 @@ TIM5.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3 TIM5.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Period,Prescaler,Channel-PWM Generation3 CH3 TIM5.Period=256-1 TIM5.Prescaler=84-1 +TIM8.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 +TIM8.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2 +TIM8.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3 +TIM8.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,Period,Prescaler +TIM8.Period=59999 +TIM8.Prescaler=56 - 1 TIM9.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_DISABLE TIM9.IPParameters=AutoReloadPreload USART1.IPParameters=VirtualMode @@ -412,10 +478,14 @@ USB_OTG_FS.IPParameters=VirtualMode USB_OTG_FS.VirtualMode=Device_Only VP_SYS_VS_Systick.Mode=SysTick VP_SYS_VS_Systick.Signal=SYS_VS_Systick +VP_TIM1_VS_ClockSourceINT.Mode=Internal +VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT VP_TIM2_VS_ClockSourceINT.Mode=Internal VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT VP_TIM5_VS_ClockSourceINT.Mode=Internal VP_TIM5_VS_ClockSourceINT.Signal=TIM5_VS_ClockSourceINT +VP_TIM8_VS_ClockSourceINT.Mode=Internal +VP_TIM8_VS_ClockSourceINT.Signal=TIM8_VS_ClockSourceINT VP_TIM9_VS_ClockSourceITR.Mode=TriggerSource_ITR0 VP_TIM9_VS_ClockSourceITR.Signal=TIM9_VS_ClockSourceITR VP_TIM9_VS_ControllerModeClock.Mode=Clock Mode diff --git a/firmware/rmcs_board/src/usb/vendor.hpp b/firmware/rmcs_board/src/usb/vendor.hpp index cbb77fc..4bbfbca 100644 --- a/firmware/rmcs_board/src/usb/vendor.hpp +++ b/firmware/rmcs_board/src/usb/vendor.hpp @@ -112,6 +112,14 @@ class Vendor } } + void gpio_digital_deserialized_callback(const data::GpioDigitalDataView& data) override { + (void)data; + } + + void gpio_analog_deserialized_callback(const data::GpioAnalogDataView& data) override { + (void)data; + } + void accelerometer_deserialized_callback(const data::AccelerometerDataView& data) override { (void)data; } diff --git a/host/include/librmcs/agent/c_board.hpp b/host/include/librmcs/agent/c_board.hpp index 1d48120..a9f7ce1 100644 --- a/host/include/librmcs/agent/c_board.hpp +++ b/host/include/librmcs/agent/c_board.hpp @@ -50,6 +50,19 @@ class CBoard : private data::DataCallback { return *this; } + PacketBuilder& gpio_digital_transmit(const librmcs::data::GpioDigitalDataView& data) { + if (data.channel < 1 || data.channel > 7 || !builder_.write_gpio_digital(data)) + [[unlikely]] + throw std::invalid_argument{"GPIO digital transmission failed: Invalid GPIO data"}; + return *this; + } + PacketBuilder& gpio_analog_transmit(const librmcs::data::GpioAnalogDataView& data) { + if (data.channel < 1 || data.channel > 7 || !builder_.write_gpio_analog(data)) + [[unlikely]] + throw std::invalid_argument{"GPIO analog transmission failed: Invalid GPIO data"}; + return *this; + } + private: explicit PacketBuilder(host::protocol::Handler& handler) noexcept : builder_(handler.start_transmit()) {} diff --git a/host/include/librmcs/protocol/handler.hpp b/host/include/librmcs/protocol/handler.hpp index 8beb836..2529cad 100644 --- a/host/include/librmcs/protocol/handler.hpp +++ b/host/include/librmcs/protocol/handler.hpp @@ -23,6 +23,10 @@ class LIBRMCS_API Handler { bool write_uart(data::DataId field_id, const data::UartDataView& view) noexcept; + bool write_gpio_digital(const data::GpioDigitalDataView& view) noexcept; + + bool write_gpio_analog(const data::GpioAnalogDataView& view) noexcept; + bool write_imu_accelerometer(const data::AccelerometerDataView& view) noexcept; bool write_imu_gyroscope(const data::GyroscopeDataView& view) noexcept; diff --git a/host/src/protocol/handler.cpp b/host/src/protocol/handler.cpp index 6186298..03a887c 100644 --- a/host/src/protocol/handler.cpp +++ b/host/src/protocol/handler.cpp @@ -47,6 +47,16 @@ class Handler::Impl : public core::protocol::DeserializeCallback { logging::get_logger().error("Unexpected uart field id: ", static_cast(id)); } + void gpio_digital_deserialized_callback(const data::GpioDigitalDataView& data) override { + (void)data; + logging::get_logger().error("Unexpected gpio digital field in uplink"); + } + + void gpio_analog_deserialized_callback(const data::GpioAnalogDataView& data) override { + (void)data; + logging::get_logger().error("Unexpected gpio analog field in uplink"); + } + void accelerometer_deserialized_callback(const data::AccelerometerDataView& data) override { callback_.accelerometer_receive_callback(data); } @@ -92,6 +102,14 @@ struct PacketBuilderImpl { return process_result(serializer_.write_uart(field_id, view)); } + [[nodiscard]] bool write_gpio_digital(const data::GpioDigitalDataView& view) noexcept { + return process_result(serializer_.write_gpio_digital(view)); + } + + [[nodiscard]] bool write_gpio_analog(const data::GpioAnalogDataView& view) noexcept { + return process_result(serializer_.write_gpio_analog(view)); + } + [[nodiscard]] bool write_imu_accelerometer(const data::AccelerometerDataView& view) noexcept { return process_result(serializer_.write_imu_accelerometer(view)); } @@ -143,6 +161,14 @@ bool Handler::PacketBuilder::write_uart( return std::launder(reinterpret_cast(storage_))->write_uart(field_id, view); } +bool Handler::PacketBuilder::write_gpio_digital(const data::GpioDigitalDataView& view) noexcept { + return std::launder(reinterpret_cast(storage_))->write_gpio_digital(view); +} + +bool Handler::PacketBuilder::write_gpio_analog(const data::GpioAnalogDataView& view) noexcept { + return std::launder(reinterpret_cast(storage_))->write_gpio_analog(view); +} + bool Handler::PacketBuilder::write_imu_accelerometer( const data::AccelerometerDataView& view) noexcept { return std::launder(reinterpret_cast(storage_)) From 1b3b6a0f83a4a663c7969fdd4341a2669346389a Mon Sep 17 00:00:00 2001 From: qzhhhi Date: Mon, 9 Mar 2026 15:07:26 +0000 Subject: [PATCH 2/2] fix --- firmware/c_board/app/src/gpio/gpio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/c_board/app/src/gpio/gpio.cpp b/firmware/c_board/app/src/gpio/gpio.cpp index 2aeefb6..cf37392 100644 --- a/firmware/c_board/app/src/gpio/gpio.cpp +++ b/firmware/c_board/app/src/gpio/gpio.cpp @@ -2,8 +2,8 @@ #include +#include #include -#include #include "firmware/c_board/app/src/spi/bmi088/accel.hpp" #include "firmware/c_board/app/src/spi/bmi088/gyro.hpp"