Skip to content

Commit fabe564

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

File tree

2 files changed

+153
-6
lines changed

2 files changed

+153
-6
lines changed

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

Lines changed: 150 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,154 @@ static struct stm32_i2c_config i2c_config[] =
4747

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

50+
static rt_err_t stm32_i2c_set_speed(struct rt_i2c_bus_device *bus, uint32_t speed)
51+
{
52+
struct stm32_i2c *i2c_drv = rt_container_of(bus, struct stm32_i2c, i2c_bus);
53+
I2C_HandleTypeDef *i2c_handle = &i2c_drv->handle;
54+
rt_err_t ret = RT_EOK;
55+
56+
RT_ASSERT(bus != RT_NULL);
57+
RT_ASSERT(speed > 0);
58+
59+
LOG_D("Setting I2C speed to %d Hz", speed);
60+
61+
/* De-initialize before reconfigure */
62+
if (HAL_I2C_DeInit(i2c_handle) != HAL_OK)
63+
{
64+
LOG_E("Failed to deinit I2C for speed change");
65+
return -RT_ERROR;
66+
}
67+
68+
/* Reconfigure base parameters */
69+
rt_memset(i2c_handle, 0, sizeof(I2C_HandleTypeDef));
70+
i2c_handle->Instance = i2c_drv->config->Instance;
71+
72+
#if defined(SOC_SERIES_STM32H7)
73+
/* H7 uses Timing field */
74+
i2c_handle->Init.Timing = i2c_drv->config->timing;
75+
#elif defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F4)
76+
/* F1/F4 uses ClockSpeed field */
77+
i2c_handle->Init.ClockSpeed = speed;
78+
i2c_handle->Init.DutyCycle = I2C_DUTYCYCLE_2;
79+
#endif
80+
81+
i2c_handle->Init.OwnAddress1 = 0;
82+
i2c_handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
83+
i2c_handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
84+
i2c_handle->Init.OwnAddress2 = 0;
85+
i2c_handle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
86+
i2c_handle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
87+
88+
if (HAL_I2C_Init(i2c_handle) != HAL_OK)
89+
{
90+
LOG_E("Failed to reinit I2C with new speed");
91+
return -RT_ERROR;
92+
}
93+
94+
#if defined(SOC_SERIES_STM32H7)
95+
/* Optional analog/digital filter settings */
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+
/* If DMA is enabled, reconfigure DMA and NVIC similar to boot init path */
110+
if (i2c_drv->i2c_dma_flag & I2C_USING_RX_DMA_FLAG)
111+
{
112+
i2c_drv->dma.handle_rx.Instance = i2c_drv->config->dma_rx->Instance;
113+
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7)
114+
i2c_drv->dma.handle_rx.Init.Channel = i2c_drv->config->dma_rx->channel;
115+
#elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7)
116+
i2c_drv->dma.handle_rx.Init.Request = i2c_drv->config->dma_rx->request;
117+
#endif
118+
#ifndef SOC_SERIES_STM32U5
119+
i2c_drv->dma.handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
120+
i2c_drv->dma.handle_rx.Init.PeriphInc = DMA_PINC_DISABLE;
121+
i2c_drv->dma.handle_rx.Init.MemInc = DMA_MINC_ENABLE;
122+
i2c_drv->dma.handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
123+
i2c_drv->dma.handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
124+
i2c_drv->dma.handle_rx.Init.Mode = DMA_NORMAL;
125+
i2c_drv->dma.handle_rx.Init.Priority = DMA_PRIORITY_LOW;
126+
#endif
127+
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7)
128+
i2c_drv->dma.handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
129+
#endif
130+
HAL_DMA_DeInit(&i2c_drv->dma.handle_rx);
131+
HAL_DMA_Init(&i2c_drv->dma.handle_rx);
132+
__HAL_LINKDMA(&i2c_drv->handle, hdmarx, i2c_drv->dma.handle_rx);
133+
HAL_NVIC_SetPriority(i2c_drv->config->dma_rx->dma_irq, 0, 0);
134+
HAL_NVIC_EnableIRQ(i2c_drv->config->dma_rx->dma_irq);
135+
}
136+
137+
if (i2c_drv->i2c_dma_flag & I2C_USING_TX_DMA_FLAG)
138+
{
139+
i2c_drv->dma.handle_tx.Instance = i2c_drv->config->dma_tx->Instance;
140+
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7)
141+
i2c_drv->dma.handle_tx.Init.Channel = i2c_drv->config->dma_tx->channel;
142+
#elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7)
143+
i2c_drv->dma.handle_tx.Init.Request = i2c_drv->config->dma_tx->request;
144+
#endif
145+
#ifndef SOC_SERIES_STM32U5
146+
i2c_drv->dma.handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
147+
i2c_drv->dma.handle_tx.Init.PeriphInc = DMA_PINC_DISABLE;
148+
i2c_drv->dma.handle_tx.Init.MemInc = DMA_MINC_ENABLE;
149+
i2c_drv->dma.handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
150+
i2c_drv->dma.handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
151+
i2c_drv->dma.handle_tx.Init.Mode = DMA_NORMAL;
152+
i2c_drv->dma.handle_tx.Init.Priority = DMA_PRIORITY_LOW;
153+
#endif
154+
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7)
155+
i2c_drv->dma.handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
156+
i2c_drv->dma.handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
157+
i2c_drv->dma.handle_tx.Init.MemBurst = DMA_MBURST_INC4;
158+
i2c_drv->dma.handle_tx.Init.PeriphBurst = DMA_PBURST_INC4;
159+
#endif
160+
HAL_DMA_DeInit(&i2c_drv->dma.handle_tx);
161+
HAL_DMA_Init(&i2c_drv->dma.handle_tx);
162+
__HAL_LINKDMA(&i2c_drv->handle, hdmatx, i2c_drv->dma.handle_tx);
163+
HAL_NVIC_SetPriority(i2c_drv->config->dma_tx->dma_irq, 1, 0);
164+
HAL_NVIC_EnableIRQ(i2c_drv->config->dma_tx->dma_irq);
165+
}
166+
167+
/* Ensure I2C event IRQ is enabled (needed even without DMA) */
168+
HAL_NVIC_SetPriority(i2c_drv->config->evirq_type, 2, 0);
169+
HAL_NVIC_EnableIRQ(i2c_drv->config->evirq_type);
170+
171+
if (ret == RT_EOK)
172+
{
173+
LOG_D("I2C speed changed to %d Hz successfully (DMA/IRQ reconfigured)", speed);
174+
}
175+
176+
return ret;
177+
}
178+
179+
static rt_err_t stm32_i2c_control(struct rt_i2c_bus_device *bus, int cmd, void *args)
180+
{
181+
RT_ASSERT(bus != RT_NULL);
182+
183+
switch (cmd)
184+
{
185+
case I2C_CTRL_SET_SPEED:
186+
if (args != RT_NULL)
187+
{
188+
uint32_t speed = *(uint32_t*)args;
189+
return stm32_i2c_set_speed(bus, speed);
190+
}
191+
return -RT_EINVAL;
192+
193+
default:
194+
return -RT_ENOSYS;
195+
}
196+
}
197+
50198
static rt_err_t stm32_i2c_init(struct stm32_i2c *i2c_drv)
51199
{
52200
RT_ASSERT(i2c_drv != RT_NULL);
@@ -326,12 +474,8 @@ static rt_ssize_t stm32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
326474
return ret;
327475
}
328476

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-
};
477+
static const struct rt_i2c_bus_device_ops stm32_i2c_ops = {
478+
.master_xfer = stm32_i2c_master_xfer, .slave_xfer = RT_NULL, .i2c_bus_control = stm32_i2c_control};
335479

336480
int RT_hw_i2c_bus_init(void)
337481
{

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ extern "C"
2222
{
2323
#endif
2424

25+
/* I2C bus control command ids */
26+
#define I2C_CTRL_SET_SPEED (0x01U)
27+
2528
struct stm32_i2c_config
2629
{
2730
const char *name;

0 commit comments

Comments
 (0)