Skip to content

feat(gpio): Add GPIO digital/analog read with configurable sampling modes#35

Merged
qzhhhi merged 1 commit intomainfrom
dev/gpio-read
Mar 21, 2026
Merged

feat(gpio): Add GPIO digital/analog read with configurable sampling modes#35
qzhhhi merged 1 commit intomainfrom
dev/gpio-read

Conversation

@qzhhhi
Copy link
Copy Markdown
Member

@qzhhhi qzhhhi commented Mar 17, 2026

Implement GPIO read functionality supporting multiple trigger modes:

  • ASAP (one-shot immediate read)
  • Periodic sampling (1Hz to 1kHz via timer polling)
  • Edge-triggered sampling (rising/falling/both edges via EXTI)

Protocol changes:

  • Add GpioReadConfigPayload bitfield (asap, rising_edge, falling_edge, period_ms)
  • Add digital/analog read config and result message types
  • Extend serializer/deserializer with read-specific methods

Firmware (c_board):

  • Implement dynamic pin reconfiguration (output <-> input modes)
  • Add periodic sampling via main loop polling with timer service
  • Add edge-triggered sampling via EXTI interrupt handlers
  • Handle EXTI line conflicts (channel 6 shares line with channel 5)

Host SDK:

  • Add gpio_digital_read() API to CBoard agent
  • Route read results to DataCallback for user consumption

Note: Protocol layer includes analog read support, but ADC sampling is not implemented in c_board firmware. Only digital read is functional.

GPIO数字/模拟读取功能实现(支持可配置采样模式)

概述

本 PR 在协议层、c_board 固件和主机 SDK(Agent/Handler/PacketBuilder)中添加了 GPIO 读取功能。支持触发模式:立即(ASAP)、周期采样(1 Hz–1 kHz,定时器轮询)和边缘触发(上升沿/下降沿/两者,EXTI 中断)。协议引入读取配置与结果消息,固件实现了数字读取(数字周期/边缘),主机 SDK 暴露读取 API 并将结果通过 DataCallback 回调向上转发。注意:协议包含模拟(ADC)读的支持,但 c_board 固件尚未实现 ADC 采样,当前仅数字读取可用。

主要变更

  • 协议层(protocol/serializer/deserializer)

    • GpioHeader 调整:Channel 字段缩至 6 位,新增 Pull(2 位,映射到 data::GpioPull)。
    • 新增 GpioReadConfigPayload(位字段):Asap、RisingEdge、FallingEdge、PeriodMs(13 位)。
    • 序列化器新增/重命名 API:
      • 新增:write_gpio_digital_read_config、write_gpio_analog_read_config、write_gpio_digital_read_result、write_gpio_analog_read_result
      • 重命名:write_gpio_digital → write_gpio_digital_data,write_gpio_analog → write_gpio_analog_data
      • 对 read-config 增加参数校验(period_ms 范围、edge 标志、pull 字段写入等)。
    • 反序列化器扩展:处理 kDigitalRead/kAnalogRead(构造 GpioReadConfigView 并调用相应回调)及 kDigitalReadResultLow/High/kAnalogReadResult(构造数据视图并回调)。
    • 回调接口变更/扩展:
      • 重命名:gpio_digital_deserialized_callback → gpio_digital_data_deserialized_callback(模拟同理)。
      • 新增:gpio_digital_read_config_deserialized_callback、gpio_analog_read_config_deserialized_callback。
      • DataCallback 新增用于上报读结果的回调签名:gpio_digital_read_result_callback、gpio_analog_read_result_callback。
  • 固件(firmware/c_board)

    • 引入 ChannelHardware、ChannelState、GpioMode 等结构,替代原先的 CCR 指针/简单写比较逻辑,实现按通道的模式与状态管理(输出/数字输入/模拟输入)。
    • 数字读取实现:
      • 周期采样:poll_periodic_input_samples()(在主循环 App::run() 中调用),基于 channel.state.period 与计时器服务发送采样结果。
      • 边缘触发:handle_input_edge_interrupt(),由 HAL_GPIO_EXTI_Callback 路由;新增 EXTI 中断处理(EXTI9_5 与 EXTI15_10 的处理扩展)。
      • EXTI 冲突处理:注意通道 6 与通道 5 共享 EXTI 线,主机侧对通道 6 的边缘配置有额外限制以避免冲突。
    • 输出写入调整:handle_digital_write/handle_analog_write 会在写入前将通道配置为输出模式(configure_output_mode),并使用新的 PWM 周期常量与比较值转换(kPwmCounterPeriod / duty16_to_pwm_compare)。
    • 初始化/IRQ:构造函数与初始化逻辑改为按 channel 表初始化 PWM 比较值与默认数字输入配置;启用并扩展 EXTI IRQ(EXTI9_5_IRQn、EXTI15_10_IRQn)。
    • BSP/引脚命名变化:将 PWM1..PWM7 宏与 IOC 标签重命名为 CHANNEL1..CHANNEL7,相关 tim/main.h 等 BSP 文件同步更新。
    • USB/厂商回调适配:vendor 层的回调名同步为 data 与新增的 read-config 回调,数字 read-config 转发到 gpio->handle_digital_read,模拟 read-config 目前为空实现。
  • 主机 SDK / Agent / Handler

    • PacketBuilder/Handler API 调整:
      • 增加 write_gpio_digital_data、write_gpio_analog_data、write_gpio_digital_read_config 等接口;移除/替换旧的 write_gpio_digital/write_gpio_analog。
      • CBoard agent 中增加 gpio_digital_read(GpioReadConfigView)(用于发起数字读取配置)与 gpio_analog_write(GpioAnalogDataView);对 channel 范围做校验,且禁止为 channel 6 配置边缘触发。
    • 反序列化结果路由:Handler::Impl 将反序列化的读取结果通过 callback_.gpio_digital_read_result_callback / gpio_analog_read_result_callback 转发到上层 DataCallback。
    • DataCallback 接口扩展:新增 gpio_digital_read_result_callback 与 gpio_analog_read_result_callback(两者为纯虚,需在实现中覆盖),以及在某些 Agent(RmcsBoard/CBoard)中提供了默认空实现/丢弃参数的覆盖。

已知限制与注意事项

  • ADC/模拟读取:协议与序列化层支持模拟读取,但 c_board 固件未实现 ADC 采样,模拟读结果不会由固件产生。
  • EXTI 共享限制:通道 6 与通道 5 共享 EXTI 线,主机端对 channel 6 的上/下沿配置做了禁止/校验以避免冲突;集成方需注意这一硬件限制。
  • 回调/接口命名改动较多(包含 data 后缀与新 read-config 回调),需要在集成处同步更新实现以避免编译错误。
  • Serializer/Deserializer 在处理 pull 字段与 period/edge 标志时加入了校验,调用端需遵循有效范围与组合规则(例如 period 范围、模拟读不允许边缘标志等)。

影响范围

  • 协议:新增位字段类型、消息载荷类型及相应序列化/反序列化路径,修改 header 位布局。
  • 固件:较大改动,包含 GPIO 驱动、EX TI 中断处理、PWM/比较值处理、通道映射与初始化、BSP/IOC 标签同步改名。
  • 主机 SDK:PacketBuilder/Handler/Agent 接口变化及新增回调,用户需实现或更新 DataCallback 接口以接收读结果。

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 17, 2026

Walkthrough

此PR在协议与数据层新增 GPIO 读配置与读结果路径,扩展回调接口并重命名若干 GPIO 写接口;固件引入通道化 GPIO 驱动、周期/边沿采样与中断路由;主机/USB 层调整对应序列化/反序列化与接口映射。

Changes

Cohort / File(s) Summary
数据定义与回调接口
core/include/librmcs/data/datas.hpp
新增 GpioPullGpioReadConfigView;在 DataCallback 中新增 gpio_digital_read_result_callbackgpio_analog_read_result_callback 两个纯虚回调。
协议位域与序列化/反序列化
core/src/protocol/protocol.hpp, core/src/protocol/serializer.hpp, core/src/protocol/deserializer.hpp, core/src/protocol/deserializer.cpp
GpioHeader 增加 Pull 字段并缩短 Channel 位宽;新增 GpioReadConfigPayload;重命名写回调为 data,新增 read-config 与 read-result 的序列化/反序列化处理与对应回调分发。
主机协议/代理接口
host/include/librmcs/protocol/handler.hpp, host/src/protocol/handler.cpp, host/include/librmcs/agent/c_board.hpp, host/include/librmcs/agent/rmcs_board.hpp
PacketBuilder/Handler API 重命名与新增:write_gpio_digital_datawrite_gpio_digital_read_configwrite_gpio_analog_data 等;主机侧新增/转发读结果回调与读配置写入方法,调整参数校验。
固件 GPIO 驱动重构
firmware/c_board/app/src/gpio/gpio.hpp, firmware/c_board/app/src/gpio/gpio.cpp, firmware/c_board/app/src/app.cpp
引入 ChannelHardware/ChannelState、模式与拉电阻映射,新增 handle_digital_readpoll_periodic_input_sampleshandle_input_edge_interrupt;写入流程改为 configure 输出后更新 PWM;在主循环加入周期采样调用。
固件 USB 与回调适配
firmware/c_board/app/src/usb/vendor.hpp, firmware/rmcs_board/src/usb/vendor.hpp
将反序列化回调重命名为 *_data_deserialized,并新增 gpio_*_read_config_deserialized_callback(部分为转发、部分为 no-op)。
中断/引脚宏与工程文件
firmware/c_board/bsp/cubemx/Core/Inc/main.h, .../Core/Src/stm32f4xx_it.c, .../Core/Src/tim.c, .../rmcs_slave.ioc, firmware/c_board/bsp/cubemx/Core/Inc/gpio.h
将 PWMx 宏与标签重命名为 CHANNELx;添加/扩展 EXTI 中断处理(新增 EXTI15_10_IRQHandler,扩展 EXTI9_5);添加 stm32f4xx_hal_gpio_ex.h 引入;更新 TIM 引脚引用。

Sequence Diagram

sequenceDiagram
    participant Host as Host
    participant PacketBuilder as PacketBuilder
    participant Serializer as Serializer
    participant USB as USB/Transport
    participant Deserializer as Deserializer
    participant DeserializeCb as DeserializeCallback
    participant FirmwareGPIO as Firmware GPIO
    participant Timer as Timer/EXTI

    Host->>PacketBuilder: gpio_digital_read(GpioReadConfigView)
    PacketBuilder->>Serializer: write_gpio_digital_read_config(config)
    Serializer->>USB: send packet (kDigitalRead)
    USB->>Deserializer: receive packet
    Deserializer->>DeserializeCb: gpio_digital_read_config_deserialized_callback(config)
    DeserializeCb->>FirmwareGPIO: handle_digital_read(config)

    alt 周期采样
        Timer->>FirmwareGPIO: poll_periodic_input_samples()
        FirmwareGPIO->>Serializer: write_gpio_digital_read_result(sample)
        Serializer->>USB: send result
        USB->>Host: gpio_digital_read_result_callback(result)
    else 边沿触发
        Timer->>FirmwareGPIO: EXTI interrupt -> handle_input_edge_interrupt(pin)
        FirmwareGPIO->>Serializer: write_gpio_digital_read_result(sample)
        Serializer->>USB: send result
        USB->>Host: gpio_digital_read_result_callback(result)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 风里数脚印,通道换新名,

边沿轻声敲,定时悄然听,
读写信封传,回调一一应,
小胡萝卜笑,系统更有灵。

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR title clearly and specifically describes the main feature addition: GPIO digital/analog read functionality with configurable sampling modes (ASAP, periodic, edge-triggered).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev/gpio-read

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
firmware/c_board/bsp/cubemx/Core/Src/stm32f4xx_it.c (1)

463-468: 建议在头文件中添加 EXTI15_10_IRQHandler 声明。

新增的 EXTI15_10_IRQHandler 函数实现在 stm32f4xx_it.c 中,但根据上下文 stm32f4xx_it.h 中缺少对应的函数声明。虽然启动文件中的弱符号机制确保链接能够正常工作,但为了代码一致性和可维护性,建议在头文件中补充声明。

📝 建议在 stm32f4xx_it.h 中添加

/* Exported functions prototypes */ 部分添加:

void EXTI15_10_IRQHandler(void);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@firmware/c_board/bsp/cubemx/Core/Src/stm32f4xx_it.c` around lines 463 - 468,
在 stm32f4xx_it.c 中新增了中断处理函数 EXTI15_10_IRQHandler,但头文件 stm32f4xx_it.h 中未声明该符号;请在
stm32f4xx_it.h 的 “Exported functions prototypes” 区块添加 void
EXTI15_10_IRQHandler(void); 的声明,以保持头/源一致性并提高可维护性(function name:
EXTI15_10_IRQHandler,file: stm32f4xx_it.c / stm32f4xx_it.h)。
host/include/librmcs/agent/c_board.hpp (1)

59-66: Channel 6 边沿触发限制的错误消息可以更具体

当前错误消息 "Invalid GPIO data" 未说明 channel 6 为何不支持边沿触发(EXTI 线与 channel 5 冲突)。建议在异常消息中提供更明确的原因,便于用户诊断问题。

💡 建议的改进
         PacketBuilder& gpio_digital_read(const librmcs::data::GpioReadConfigView& data) {
             if (data.channel < 1 || data.channel > 7
                 || (data.channel == 6 && (data.rising_edge || data.falling_edge))
                 || !builder_.write_gpio_digital_read_config(data)) [[unlikely]]
-                throw std::invalid_argument{
-                    "GPIO digital read configuration transmission failed: Invalid GPIO data"};
+                throw std::invalid_argument{
+                    data.channel == 6 && (data.rising_edge || data.falling_edge)
+                        ? "GPIO digital read configuration failed: Channel 6 does not support edge-triggered mode (EXTI conflict with channel 5)"
+                        : "GPIO digital read configuration transmission failed: Invalid GPIO data"};
             return *this;
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@host/include/librmcs/agent/c_board.hpp` around lines 59 - 66, The thrown
std::invalid_argument in gpio_digital_read should provide a specific reason for
the failure instead of the generic "Invalid GPIO data"; update the exception
message in gpio_digital_read (and where builder_.write_gpio_digital_read_config
is checked) to state that channel 6 does not support edge-triggered reads
because it shares the EXTI line with channel 5 (e.g., "GPIO digital read failed:
channel 6 cannot use rising/falling edge trigger due to EXTI line conflict with
channel 5"), so callers immediately see the cause.
firmware/c_board/bsp/cubemx/Core/Inc/main.h (1)

271-276: 记录 EXTI 线冲突约束。

CHANNEL5_Pin (PC6) 和 CHANNEL6_Pin (PI6) 共享同一 GPIO_PIN_6,在 STM32 上映射到相同的 EXTI6 中断线。PR 描述中提到固件层已处理此冲突,建议在此处添加注释说明该硬件约束,以便后续维护者了解。

 `#define` CHANNEL6_Pin GPIO_PIN_6
 `#define` CHANNEL6_GPIO_Port GPIOI
 `#define` CHANNEL5_Pin GPIO_PIN_6
 `#define` CHANNEL5_GPIO_Port GPIOC
+/* Note: CHANNEL5 (PC6) and CHANNEL6 (PI6) share EXTI6 line.
+   Edge-triggered sampling cannot be enabled on both channels simultaneously. */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@firmware/c_board/bsp/cubemx/Core/Inc/main.h` around lines 271 - 276,
CHANNEL5_Pin (PC6) and CHANNEL6_Pin (PI6) both map to GPIO_PIN_6 which shares
the same EXTI6 interrupt line on STM32; add a concise comment next to the
defines for CHANNEL5_Pin and CHANNEL6_Pin in main.h noting the EXTI6 conflict
and that the firmware/IRQ routing in the codebase already handles this overlap
to guide future maintainers (referencing SYMBOLS: CHANNEL5_Pin, CHANNEL6_Pin,
EXTI6).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@firmware/c_board/app/src/gpio/gpio.hpp`:
- Line 119: kPwmCounterPeriod is set to 60000 which exceeds the timer ARR
(59999) and can produce CCR writes outside the valid [0,ARR] range; change
kPwmCounterPeriod from 60000 to 59999 and update any code that computes or
clamps CCR values (e.g., functions that compute "digital high" or 100% analog
duty and any SetPwmDuty/WriteCompare helpers) to ensure they never write a value
> kPwmCounterPeriod (clamp to kPwmCounterPeriod where needed).

---

Nitpick comments:
In `@firmware/c_board/bsp/cubemx/Core/Inc/main.h`:
- Around line 271-276: CHANNEL5_Pin (PC6) and CHANNEL6_Pin (PI6) both map to
GPIO_PIN_6 which shares the same EXTI6 interrupt line on STM32; add a concise
comment next to the defines for CHANNEL5_Pin and CHANNEL6_Pin in main.h noting
the EXTI6 conflict and that the firmware/IRQ routing in the codebase already
handles this overlap to guide future maintainers (referencing SYMBOLS:
CHANNEL5_Pin, CHANNEL6_Pin, EXTI6).

In `@firmware/c_board/bsp/cubemx/Core/Src/stm32f4xx_it.c`:
- Around line 463-468: 在 stm32f4xx_it.c 中新增了中断处理函数 EXTI15_10_IRQHandler,但头文件
stm32f4xx_it.h 中未声明该符号;请在 stm32f4xx_it.h 的 “Exported functions prototypes” 区块添加
void EXTI15_10_IRQHandler(void); 的声明,以保持头/源一致性并提高可维护性(function name:
EXTI15_10_IRQHandler,file: stm32f4xx_it.c / stm32f4xx_it.h)。

In `@host/include/librmcs/agent/c_board.hpp`:
- Around line 59-66: The thrown std::invalid_argument in gpio_digital_read
should provide a specific reason for the failure instead of the generic "Invalid
GPIO data"; update the exception message in gpio_digital_read (and where
builder_.write_gpio_digital_read_config is checked) to state that channel 6 does
not support edge-triggered reads because it shares the EXTI line with channel 5
(e.g., "GPIO digital read failed: channel 6 cannot use rising/falling edge
trigger due to EXTI line conflict with channel 5"), so callers immediately see
the cause.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d3161f3c-28a2-41a5-a16f-54f5a376a07c

📥 Commits

Reviewing files that changed from the base of the PR and between eff14b7 and fa18f44.

📒 Files selected for processing (18)
  • core/include/librmcs/data/datas.hpp
  • core/src/protocol/deserializer.cpp
  • core/src/protocol/deserializer.hpp
  • core/src/protocol/protocol.hpp
  • core/src/protocol/serializer.hpp
  • firmware/c_board/app/src/app.cpp
  • firmware/c_board/app/src/gpio/gpio.cpp
  • firmware/c_board/app/src/gpio/gpio.hpp
  • firmware/c_board/app/src/usb/vendor.hpp
  • firmware/c_board/bsp/cubemx/Core/Inc/main.h
  • firmware/c_board/bsp/cubemx/Core/Src/stm32f4xx_it.c
  • firmware/c_board/bsp/cubemx/Core/Src/tim.c
  • firmware/c_board/bsp/cubemx/rmcs_slave.ioc
  • firmware/rmcs_board/src/usb/vendor.hpp
  • host/include/librmcs/agent/c_board.hpp
  • host/include/librmcs/agent/rmcs_board.hpp
  • host/include/librmcs/protocol/handler.hpp
  • host/src/protocol/handler.cpp

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
firmware/c_board/app/src/gpio/gpio.hpp (2)

202-210: 考虑处理缓冲区满的情况。

当前仅断言检查 kInvalidArgument,若序列化器返回 kBufferFull,采样会被静默丢弃。虽然非阻塞设计是合理的,但丢弃采样可能影响调试。可考虑添加计数器或日志记录丢弃次数。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@firmware/c_board/app/src/gpio/gpio.hpp` around lines 202 - 210,
publish_digital_input_sample 中只用断言忽略了序列化器可能返回的 kBufferFull,导致采样被静默丢弃;修改
publish_digital_input_sample 在调用
usb::get_serializer().write_gpio_digital_read_result(...) 后显式处理返回值:保留对
kInvalidArgument 的断言,但对 core::protocol::Serializer::SerializeResult::kBufferFull
增加处理逻辑(例如递增一个丢弃计数器或调用日志函数记录丢弃次数),以便后续可观察到缓冲区满的情况并且在必要时统计或上报。

143-147: EXTI 冲突处理正确。

Channel 5 (PC6) 和 Channel 6 (PI6) 共享 EXTI 线 6,代码正确地禁用了 Channel 6 的边沿触发以避免冲突。建议在此限制条件上添加日志或返回错误码,让上层知晓配置被修改。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@firmware/c_board/app/src/gpio/gpio.hpp` around lines 143 - 147, The code
disables edge triggers for channel 6 to avoid EXTI line 6 conflicts but does not
notify the caller; update the channel configuration routine (the function that
contains the if (channel == 6) check and sets rising_edge/falling_edge—e.g., the
channel configure/set_edge_trigger function) to surface this change: either emit
a diagnostic (call the project's logging/debug function with a clear message
that channel 6 was modified due to EXTI conflict) or change the function to
return a status/enum (e.g., SUCCESS vs ERROR_EXTI_CONFLICT or CONFIG_MODIFIED)
so callers can detect the modification; ensure you reference and preserve the
existing rising_edge and falling_edge assignments when adding the notification.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@firmware/c_board/app/src/gpio/gpio.hpp`:
- Around line 202-210: publish_digital_input_sample 中只用断言忽略了序列化器可能返回的
kBufferFull,导致采样被静默丢弃;修改 publish_digital_input_sample 在调用
usb::get_serializer().write_gpio_digital_read_result(...) 后显式处理返回值:保留对
kInvalidArgument 的断言,但对 core::protocol::Serializer::SerializeResult::kBufferFull
增加处理逻辑(例如递增一个丢弃计数器或调用日志函数记录丢弃次数),以便后续可观察到缓冲区满的情况并且在必要时统计或上报。
- Around line 143-147: The code disables edge triggers for channel 6 to avoid
EXTI line 6 conflicts but does not notify the caller; update the channel
configuration routine (the function that contains the if (channel == 6) check
and sets rising_edge/falling_edge—e.g., the channel configure/set_edge_trigger
function) to surface this change: either emit a diagnostic (call the project's
logging/debug function with a clear message that channel 6 was modified due to
EXTI conflict) or change the function to return a status/enum (e.g., SUCCESS vs
ERROR_EXTI_CONFLICT or CONFIG_MODIFIED) so callers can detect the modification;
ensure you reference and preserve the existing rising_edge and falling_edge
assignments when adding the notification.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 111cd515-60ad-4e6f-9087-c72a391399b7

📥 Commits

Reviewing files that changed from the base of the PR and between fa18f44 and 979a25d.

📒 Files selected for processing (1)
  • firmware/c_board/app/src/gpio/gpio.hpp

Implement GPIO read support with configurable sampling modes:
- ASAP one-shot sampling
- Periodic sampling via timer polling
- Edge-triggered sampling via EXTI
- Configurable pull mode for input channels

Extend the GPIO protocol with read config and read result messages:
- Add GpioPull and GpioReadConfigView
- Add GpioReadConfigPayload bitfield
- Add digital and analog read config and result payload types
- Extend serializer and deserializer with read-specific handling

Update c_board firmware to support GPIO input reads:
- Reconfigure GPIO pins dynamically between output and input modes
- Poll periodic samples in the main loop
- Publish edge-triggered samples from EXTI callbacks
- Handle the EXTI line conflict between channels 5 and 6

Update host-side APIs for GPIO read support:
- Add gpio_digital_read() to the CBoard agent
- Route GPIO read results through DataCallback
- Rename GPIO write APIs to explicit write-specific names

Analog read protocol support is included in the core layer, but c_board
firmware does not implement analog sampling yet.

BREAKING CHANGE: Rename GPIO transmit APIs to write-specific names and add
GPIO read result callbacks to the host callback interface.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
firmware/c_board/app/src/gpio/gpio.hpp (1)

73-86: 周期采样时间可能产生累积漂移。

当采样后将 next_sample_time 设置为当前时间 now(Line 84),如果主循环执行慢于采样周期,会导致时间漂移。若需要精确的采样频率,考虑使用累加方式:

             publish_digital_input_sample(channel);
-            state.next_sample_time = now;
+            state.next_sample_time += state.period;
         }

但如果当前行为("自上次采样以来至少经过 period")是预期的,则可以忽略此建议。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@firmware/c_board/app/src/gpio/gpio.hpp` around lines 73 - 86,
poll_periodic_input_samples updates state.next_sample_time to now which causes
cumulative drift when the loop runs late; instead, compute next_sample_time by
incrementing the previous next_sample_time by state.period (e.g.,
state.next_sample_time += state.period) in the poll_periodic_input_samples
function so samples stay on the fixed schedule, while still using
timer::timer->check_expired(state.next_sample_time, state.period) and
timer::timer->timepoint() for comparisons and calling
publish_digital_input_sample(channel) when due; keep the late-run handling by
advancing next_sample_time in a loop or by using integer multiples of
state.period to catch up if now > next_sample_time + period.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@firmware/c_board/app/src/gpio/gpio.hpp`:
- Around line 73-86: poll_periodic_input_samples updates state.next_sample_time
to now which causes cumulative drift when the loop runs late; instead, compute
next_sample_time by incrementing the previous next_sample_time by state.period
(e.g., state.next_sample_time += state.period) in the
poll_periodic_input_samples function so samples stay on the fixed schedule,
while still using timer::timer->check_expired(state.next_sample_time,
state.period) and timer::timer->timepoint() for comparisons and calling
publish_digital_input_sample(channel) when due; keep the late-run handling by
advancing next_sample_time in a loop or by using integer multiples of
state.period to catch up if now > next_sample_time + period.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1041f415-dafd-4e49-ada6-8683bef79370

📥 Commits

Reviewing files that changed from the base of the PR and between 979a25d and 63bbedc.

📒 Files selected for processing (19)
  • core/include/librmcs/data/datas.hpp
  • core/src/protocol/deserializer.cpp
  • core/src/protocol/deserializer.hpp
  • core/src/protocol/protocol.hpp
  • core/src/protocol/serializer.hpp
  • firmware/c_board/app/src/app.cpp
  • firmware/c_board/app/src/gpio/gpio.cpp
  • firmware/c_board/app/src/gpio/gpio.hpp
  • firmware/c_board/app/src/usb/vendor.hpp
  • firmware/c_board/bsp/cubemx/Core/Inc/gpio.h
  • firmware/c_board/bsp/cubemx/Core/Inc/main.h
  • firmware/c_board/bsp/cubemx/Core/Src/stm32f4xx_it.c
  • firmware/c_board/bsp/cubemx/Core/Src/tim.c
  • firmware/c_board/bsp/cubemx/rmcs_slave.ioc
  • firmware/rmcs_board/src/usb/vendor.hpp
  • host/include/librmcs/agent/c_board.hpp
  • host/include/librmcs/agent/rmcs_board.hpp
  • host/include/librmcs/protocol/handler.hpp
  • host/src/protocol/handler.cpp
✅ Files skipped from review due to trivial changes (3)
  • firmware/c_board/bsp/cubemx/Core/Inc/gpio.h
  • firmware/c_board/bsp/cubemx/Core/Src/tim.c
  • firmware/c_board/bsp/cubemx/rmcs_slave.ioc
🚧 Files skipped from review as they are similar to previous changes (8)
  • firmware/c_board/app/src/app.cpp
  • firmware/c_board/app/src/gpio/gpio.cpp
  • core/include/librmcs/data/datas.hpp
  • core/src/protocol/protocol.hpp
  • firmware/c_board/bsp/cubemx/Core/Inc/main.h
  • core/src/protocol/deserializer.hpp
  • host/include/librmcs/agent/c_board.hpp
  • core/src/protocol/serializer.hpp

@qzhhhi qzhhhi merged commit 940bc85 into main Mar 21, 2026
5 checks passed
@github-project-automation github-project-automation bot moved this from Todo to Done in RMCS Slave SDK Mar 21, 2026
@qzhhhi qzhhhi deleted the dev/gpio-read branch March 21, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant