Skip to content

Commit 8f696f3

Browse files
committed
[opt]add i2c config in stm32 lib
1 parent af2c8ae commit 8f696f3

File tree

1 file changed

+157
-6
lines changed

1 file changed

+157
-6
lines changed

bsp/stm32/libraries/HAL_Drivers/drivers/drv_hard_i2c.c

Lines changed: 157 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
#define LOG_TAG "drv.i2c.hw"
2020
#include <drv_log.h>
2121

22+
// 添加I2C速度设置命令定义
23+
#define I2C_CTRL_SET_SPEED 0x01
24+
#define I2C_CTRL_SET_DUTY 0x02
25+
2226
enum
2327
{
2428
#ifdef BSP_USING_HARD_I2C1
@@ -47,6 +51,157 @@ static struct stm32_i2c_config i2c_config[] =
4751

4852
static struct stm32_i2c i2c_objs[sizeof(i2c_config) / sizeof(i2c_config[0])] = {0};
4953

54+
// 添加I2C速度设置函数
55+
static rt_err_t stm32_i2c_set_speed(struct rt_i2c_bus_device *bus, uint32_t speed)
56+
{
57+
struct stm32_i2c *i2c_drv = rt_container_of(bus, struct stm32_i2c, i2c_bus);
58+
I2C_HandleTypeDef *i2c_handle = &i2c_drv->handle;
59+
rt_err_t ret = RT_EOK;
60+
61+
RT_ASSERT(bus != RT_NULL);
62+
RT_ASSERT(speed > 0);
63+
64+
LOG_D("Setting I2C speed to %d Hz", speed);
65+
66+
if (HAL_I2C_DeInit(i2c_handle) != HAL_OK)
67+
{
68+
LOG_E("Failed to deinit I2C for speed change");
69+
return -RT_ERROR;
70+
}
71+
72+
rt_memset(i2c_handle, 0, sizeof(I2C_HandleTypeDef));
73+
i2c_handle->Instance = i2c_drv->config->Instance;
74+
75+
#if defined(SOC_SERIES_STM32H7)
76+
i2c_handle->Init.Timing = i2c_drv->config->timing;
77+
#elif defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F4)
78+
i2c_handle->Init.ClockSpeed = speed;
79+
i2c_handle->Init.DutyCycle = I2C_DUTYCYCLE_2;
80+
#endif
81+
82+
i2c_handle->Init.OwnAddress1 = 0;
83+
i2c_handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
84+
i2c_handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
85+
i2c_handle->Init.OwnAddress2 = 0;
86+
i2c_handle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
87+
i2c_handle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
88+
89+
if (HAL_I2C_Init(i2c_handle) != HAL_OK)
90+
{
91+
LOG_E("Failed to reinit I2C with new speed");
92+
return -RT_ERROR;
93+
}
94+
95+
#if defined(SOC_SERIES_STM32H7)
96+
if (HAL_I2CEx_ConfigAnalogFilter(i2c_handle, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
97+
{
98+
LOG_E("Failed to configure analog filter");
99+
ret = -RT_ERROR;
100+
}
101+
102+
if (HAL_I2CEx_ConfigDigitalFilter(i2c_handle, 0) != HAL_OK)
103+
{
104+
LOG_E("Failed to configure digital filter");
105+
ret = -RT_ERROR;
106+
}
107+
#endif
108+
109+
/* 参考启动流程,若开启了 DMA,需要重新配置 DMA 和 NVIC,避免重新初始化后句柄失效 */
110+
if (i2c_drv->i2c_dma_flag & I2C_USING_RX_DMA_FLAG)
111+
{
112+
/* 重新设置 DMA RX 基本参数并初始化 */
113+
i2c_drv->dma.handle_rx.Instance = i2c_drv->config->dma_rx->Instance;
114+
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7)
115+
i2c_drv->dma.handle_rx.Init.Channel = i2c_drv->config->dma_rx->channel;
116+
#elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7)
117+
i2c_drv->dma.handle_rx.Init.Request = i2c_drv->config->dma_rx->request;
118+
#endif
119+
#ifndef SOC_SERIES_STM32U5
120+
i2c_drv->dma.handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
121+
i2c_drv->dma.handle_rx.Init.PeriphInc = DMA_PINC_DISABLE;
122+
i2c_drv->dma.handle_rx.Init.MemInc = DMA_MINC_ENABLE;
123+
i2c_drv->dma.handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
124+
i2c_drv->dma.handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
125+
i2c_drv->dma.handle_rx.Init.Mode = DMA_NORMAL;
126+
i2c_drv->dma.handle_rx.Init.Priority = DMA_PRIORITY_LOW;
127+
#endif
128+
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7)
129+
i2c_drv->dma.handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
130+
#endif
131+
HAL_DMA_DeInit(&i2c_drv->dma.handle_rx);
132+
HAL_DMA_Init(&i2c_drv->dma.handle_rx);
133+
__HAL_LINKDMA(&i2c_drv->handle, hdmarx, i2c_drv->dma.handle_rx);
134+
/* NVIC 配置 */
135+
HAL_NVIC_SetPriority(i2c_drv->config->dma_rx->dma_irq, 0, 0);
136+
HAL_NVIC_EnableIRQ(i2c_drv->config->dma_rx->dma_irq);
137+
}
138+
139+
if (i2c_drv->i2c_dma_flag & I2C_USING_TX_DMA_FLAG)
140+
{
141+
/* 重新设置 DMA TX 基本参数并初始化 */
142+
i2c_drv->dma.handle_tx.Instance = i2c_drv->config->dma_tx->Instance;
143+
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7)
144+
i2c_drv->dma.handle_tx.Init.Channel = i2c_drv->config->dma_tx->channel;
145+
#elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7)
146+
i2c_drv->dma.handle_tx.Init.Request = i2c_drv->config->dma_tx->request;
147+
#endif
148+
#ifndef SOC_SERIES_STM32U5
149+
i2c_drv->dma.handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
150+
i2c_drv->dma.handle_tx.Init.PeriphInc = DMA_PINC_DISABLE;
151+
i2c_drv->dma.handle_tx.Init.MemInc = DMA_MINC_ENABLE;
152+
i2c_drv->dma.handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
153+
i2c_drv->dma.handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
154+
i2c_drv->dma.handle_tx.Init.Mode = DMA_NORMAL;
155+
i2c_drv->dma.handle_tx.Init.Priority = DMA_PRIORITY_LOW;
156+
#endif
157+
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7)
158+
i2c_drv->dma.handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
159+
i2c_drv->dma.handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
160+
i2c_drv->dma.handle_tx.Init.MemBurst = DMA_MBURST_INC4;
161+
i2c_drv->dma.handle_tx.Init.PeriphBurst = DMA_PBURST_INC4;
162+
#endif
163+
HAL_DMA_DeInit(&i2c_drv->dma.handle_tx);
164+
HAL_DMA_Init(&i2c_drv->dma.handle_tx);
165+
__HAL_LINKDMA(&i2c_drv->handle, hdmatx, i2c_drv->dma.handle_tx);
166+
/* NVIC 配置 */
167+
HAL_NVIC_SetPriority(i2c_drv->config->dma_tx->dma_irq, 1, 0);
168+
HAL_NVIC_EnableIRQ(i2c_drv->config->dma_tx->dma_irq);
169+
}
170+
171+
/* 事件中断 NVIC 重新配置(IT 模式也需要) */
172+
HAL_NVIC_SetPriority(i2c_drv->config->evirq_type, 2, 0);
173+
HAL_NVIC_EnableIRQ(i2c_drv->config->evirq_type);
174+
175+
if (ret == RT_EOK)
176+
{
177+
LOG_D("I2C speed changed to %d Hz successfully (DMA/IRQ reconfigured)", speed);
178+
}
179+
180+
return ret;
181+
}
182+
183+
// 添加I2C控制函数
184+
static rt_err_t stm32_i2c_control(struct rt_i2c_bus_device *bus, int cmd, void *args) {
185+
RT_ASSERT(bus != RT_NULL);
186+
187+
switch (cmd) {
188+
case I2C_CTRL_SET_SPEED:
189+
if (args != RT_NULL) {
190+
uint32_t speed = *(uint32_t *)args;
191+
return stm32_i2c_set_speed(bus, speed);
192+
}
193+
return -RT_EINVAL;
194+
195+
case I2C_CTRL_SET_DUTY:
196+
// 占空比设置暂时不实现,因为需要重新计算时钟分频
197+
LOG_W("Duty cycle setting not implemented yet");
198+
return RT_EOK;
199+
200+
default:
201+
return -RT_ENOSYS;
202+
}
203+
}
204+
50205
static rt_err_t stm32_i2c_init(struct stm32_i2c *i2c_drv)
51206
{
52207
RT_ASSERT(i2c_drv != RT_NULL);
@@ -326,12 +481,8 @@ static rt_ssize_t stm32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
326481
return ret;
327482
}
328483

329-
static const struct rt_i2c_bus_device_ops stm32_i2c_ops =
330-
{
331-
.master_xfer = stm32_i2c_master_xfer,
332-
RT_NULL,
333-
RT_NULL
334-
};
484+
static const struct rt_i2c_bus_device_ops stm32_i2c_ops = {
485+
.master_xfer = stm32_i2c_master_xfer, .slave_xfer = RT_NULL, .i2c_bus_control = stm32_i2c_control};
335486

336487
int RT_hw_i2c_bus_init(void)
337488
{

0 commit comments

Comments
 (0)