[opt]add i2c config in stm32 lib#10637
Conversation
|
|
📌 Code Review Assignment🏷️ Tag: bsp_stm32Reviewers: Liang1795 hamburger-os wdfk-prog Changed Files (Click to expand)
📊 Current Review Status (Last Updated: 2025-08-25 18:28 CST)
📝 Review Instructions
|
8f696f3 to
fabe564
Compare
| #endif | ||
|
|
||
| /* I2C bus control command ids */ | ||
| #define I2C_CTRL_SET_SPEED (0x01U) |
There was a problem hiding this comment.
这个标志位可以向上提到这里
rt-thread/components/drivers/include/drivers/dev_i2c.h
Lines 180 to 196 in af2c8ae
| struct stm32_i2c *i2c_drv = rt_container_of(bus, struct stm32_i2c, i2c_bus); | ||
| I2C_HandleTypeDef *i2c_handle = &i2c_drv->handle; | ||
| rt_err_t ret = RT_EOK; | ||
|
|
||
| RT_ASSERT(bus != RT_NULL); | ||
| RT_ASSERT(speed > 0); | ||
|
|
||
| LOG_D("Setting I2C speed to %d Hz", speed); | ||
|
|
||
| /* De-initialize before reconfigure */ | ||
| if (HAL_I2C_DeInit(i2c_handle) != HAL_OK) | ||
| { | ||
| LOG_E("Failed to deinit I2C for speed change"); | ||
| return -RT_ERROR; | ||
| } | ||
|
|
||
| /* Reconfigure base parameters */ | ||
| rt_memset(i2c_handle, 0, sizeof(I2C_HandleTypeDef)); | ||
| i2c_handle->Instance = i2c_drv->config->Instance; | ||
|
|
||
| #if defined(SOC_SERIES_STM32H7) | ||
| /* H7 uses Timing field */ | ||
| i2c_handle->Init.Timing = i2c_drv->config->timing; | ||
| #elif defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F4) | ||
| /* F1/F4 uses ClockSpeed field */ | ||
| i2c_handle->Init.ClockSpeed = speed; | ||
| i2c_handle->Init.DutyCycle = I2C_DUTYCYCLE_2; | ||
| #endif | ||
|
|
||
| i2c_handle->Init.OwnAddress1 = 0; | ||
| i2c_handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; | ||
| i2c_handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; | ||
| i2c_handle->Init.OwnAddress2 = 0; | ||
| i2c_handle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; | ||
| i2c_handle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; | ||
|
|
||
| if (HAL_I2C_Init(i2c_handle) != HAL_OK) | ||
| { | ||
| LOG_E("Failed to reinit I2C with new speed"); | ||
| return -RT_ERROR; | ||
| } | ||
|
|
||
| #if defined(SOC_SERIES_STM32H7) | ||
| /* Optional analog/digital filter settings */ | ||
| if (HAL_I2CEx_ConfigAnalogFilter(i2c_handle, I2C_ANALOGFILTER_ENABLE) != HAL_OK) | ||
| { | ||
| LOG_E("Failed to configure analog filter"); | ||
| ret = -RT_ERROR; | ||
| } | ||
|
|
||
| if (HAL_I2CEx_ConfigDigitalFilter(i2c_handle, 0) != HAL_OK) | ||
| { | ||
| LOG_E("Failed to configure digital filter"); | ||
| ret = -RT_ERROR; | ||
| } | ||
| #endif | ||
|
|
||
| /* If DMA is enabled, reconfigure DMA and NVIC similar to boot init path */ | ||
| if (i2c_drv->i2c_dma_flag & I2C_USING_RX_DMA_FLAG) | ||
| { | ||
| i2c_drv->dma.handle_rx.Instance = i2c_drv->config->dma_rx->Instance; | ||
| #if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) | ||
| i2c_drv->dma.handle_rx.Init.Channel = i2c_drv->config->dma_rx->channel; | ||
| #elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7) | ||
| i2c_drv->dma.handle_rx.Init.Request = i2c_drv->config->dma_rx->request; | ||
| #endif | ||
| #ifndef SOC_SERIES_STM32U5 | ||
| i2c_drv->dma.handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; | ||
| i2c_drv->dma.handle_rx.Init.PeriphInc = DMA_PINC_DISABLE; | ||
| i2c_drv->dma.handle_rx.Init.MemInc = DMA_MINC_ENABLE; | ||
| i2c_drv->dma.handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; | ||
| i2c_drv->dma.handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; | ||
| i2c_drv->dma.handle_rx.Init.Mode = DMA_NORMAL; | ||
| i2c_drv->dma.handle_rx.Init.Priority = DMA_PRIORITY_LOW; | ||
| #endif | ||
| #if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7) | ||
| i2c_drv->dma.handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; | ||
| #endif | ||
| HAL_DMA_DeInit(&i2c_drv->dma.handle_rx); | ||
| HAL_DMA_Init(&i2c_drv->dma.handle_rx); | ||
| __HAL_LINKDMA(&i2c_drv->handle, hdmarx, i2c_drv->dma.handle_rx); | ||
| HAL_NVIC_SetPriority(i2c_drv->config->dma_rx->dma_irq, 0, 0); | ||
| HAL_NVIC_EnableIRQ(i2c_drv->config->dma_rx->dma_irq); | ||
| } | ||
|
|
||
| if (i2c_drv->i2c_dma_flag & I2C_USING_TX_DMA_FLAG) | ||
| { | ||
| i2c_drv->dma.handle_tx.Instance = i2c_drv->config->dma_tx->Instance; | ||
| #if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) | ||
| i2c_drv->dma.handle_tx.Init.Channel = i2c_drv->config->dma_tx->channel; | ||
| #elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7) | ||
| i2c_drv->dma.handle_tx.Init.Request = i2c_drv->config->dma_tx->request; | ||
| #endif | ||
| #ifndef SOC_SERIES_STM32U5 | ||
| i2c_drv->dma.handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; | ||
| i2c_drv->dma.handle_tx.Init.PeriphInc = DMA_PINC_DISABLE; | ||
| i2c_drv->dma.handle_tx.Init.MemInc = DMA_MINC_ENABLE; | ||
| i2c_drv->dma.handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; | ||
| i2c_drv->dma.handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; | ||
| i2c_drv->dma.handle_tx.Init.Mode = DMA_NORMAL; | ||
| i2c_drv->dma.handle_tx.Init.Priority = DMA_PRIORITY_LOW; | ||
| #endif | ||
| #if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7) | ||
| i2c_drv->dma.handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; | ||
| i2c_drv->dma.handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; | ||
| i2c_drv->dma.handle_tx.Init.MemBurst = DMA_MBURST_INC4; | ||
| i2c_drv->dma.handle_tx.Init.PeriphBurst = DMA_PBURST_INC4; | ||
| #endif | ||
| HAL_DMA_DeInit(&i2c_drv->dma.handle_tx); | ||
| HAL_DMA_Init(&i2c_drv->dma.handle_tx); | ||
| __HAL_LINKDMA(&i2c_drv->handle, hdmatx, i2c_drv->dma.handle_tx); | ||
| HAL_NVIC_SetPriority(i2c_drv->config->dma_tx->dma_irq, 1, 0); | ||
| HAL_NVIC_EnableIRQ(i2c_drv->config->dma_tx->dma_irq); | ||
| } |
There was a problem hiding this comment.
这段代码跟stm32_i2c_init重复了吧?
修改stm32_i2c_init名称为stm32_i2c_config,然后进行调用吧?
|
|
||
| if (ret == RT_EOK) | ||
| { | ||
| LOG_D("I2C speed changed to %d Hz successfully (DMA/IRQ reconfigured)", speed); |
| switch (cmd) | ||
| { | ||
| case I2C_CTRL_SET_SPEED: | ||
| if (args != RT_NULL) | ||
| { | ||
| uint32_t speed = *(uint32_t*)args; | ||
| return stm32_i2c_set_speed(bus, speed); | ||
| } | ||
| return -RT_EINVAL; | ||
|
|
||
| default: | ||
| return -RT_ENOSYS; | ||
| } | ||
| } |
There was a problem hiding this comment.
rt-thread/components/drivers/i2c/dev_i2c_dev.c
Lines 63 to 95 in af2c8ae
- 建议参考这里的写法
| RT_NULL | ||
| }; | ||
| static const struct rt_i2c_bus_device_ops stm32_i2c_ops = { | ||
| .master_xfer = stm32_i2c_master_xfer, .slave_xfer = RT_NULL, .i2c_bus_control = stm32_i2c_control}; |
|
There was a problem hiding this comment.
Pull Request Overview
This PR enhances the STM32 hardware I2C driver by adding runtime speed configuration support through a bus control interface. The enhancement allows dynamic adjustment of I2C speed during runtime and properly handles DMA/interrupt reconfiguration when DMA is enabled.
Key Changes
- Added
I2C_CTRL_SET_SPEEDcontrol command for runtime I2C speed adjustment - Implemented
stm32_i2c_set_speed()function with complete DMA and interrupt reconfiguration - Added
stm32_i2c_control()interface to handle bus control commands
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
bsp/stm32/libraries/HAL_Drivers/drivers/drv_hard_i2c.h |
Added I2C control command macro definition |
bsp/stm32/libraries/HAL_Drivers/drivers/drv_hard_i2c.c |
Implemented runtime speed configuration with DMA/IRQ handling and updated ops structure |
| static const struct rt_i2c_bus_device_ops stm32_i2c_ops = { | ||
| .master_xfer = stm32_i2c_master_xfer, .slave_xfer = RT_NULL, .i2c_bus_control = stm32_i2c_control}; |
There was a problem hiding this comment.
[best_practices/最佳实践]: The structure initialization should follow RT-Thread coding standards with proper formatting.
English: The structure should be formatted with each field on a separate line for better readability and consistency with RT-Thread coding standards.
中文:结构体初始化应遵循RT-Thread编码标准,每个字段占单独一行以提高可读性和保持一致性。
Example/示例:
static const struct rt_i2c_bus_device_ops stm32_i2c_ops =
{
.master_xfer = stm32_i2c_master_xfer,
.slave_xfer = RT_NULL,
.i2c_bus_control = stm32_i2c_control
};| static const struct rt_i2c_bus_device_ops stm32_i2c_ops = { | |
| .master_xfer = stm32_i2c_master_xfer, .slave_xfer = RT_NULL, .i2c_bus_control = stm32_i2c_control}; | |
| static const struct rt_i2c_bus_device_ops stm32_i2c_ops = | |
| { | |
| .master_xfer = stm32_i2c_master_xfer, | |
| .slave_xfer = RT_NULL, | |
| .i2c_bus_control = stm32_i2c_control | |
| }; |
Resolves #10635
拉取/合并请求描述:(PR description)
[
本PR增强了STM32硬件I2C驱动(drv_hard_i2c),支持在运行时通过控制接口动态调整I2C速率,并在开启DMA的情况下安全地重建DMA与中断配置,避免通信异常。同时清理了无效/未实现的占空比设置项,统一英文注释,并将控制宏移动到头文件,整体风格与现有代码保持一致。
为什么提交这份PR (why to submit this PR)
你的解决方案是什么 (what is your solution)
i2c_bus->ops->i2c_bus_control(bus, I2C_CTRL_SET_SPEED, &speed)调整速率。HAL_I2C_Init之后,若启用DMA,按系统启动流程完整重建 DMA RX/TX 句柄、__HAL_LINKDMA、DMA NVIC 以及 I2C 事件中断 NVIC,保证DMA场景稳定。I2C_CTRL_SET_SPEED宏迁移至头文件drv_hard_i2c.h,便于外部调用与统一管理。主要变更点:
#define I2C_CTRL_SET_SPEED (0x01U)stm32_i2c_set_speed()(含DMA/IRQ重配置)stm32_i2c_control()仅支持I2C_CTRL_SET_SPEED请提供验证的bsp和config (provide the config and bsp)
BSP:
.config:
action:
]
当前拉取/合并请求的状态 Intent for your PR
必须选择一项 Choose one (Mandatory):
代码质量 Code Quality:
我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:
#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up