@@ -47,6 +47,154 @@ static struct stm32_i2c_config i2c_config[] =
47
47
48
48
static struct stm32_i2c i2c_objs [sizeof (i2c_config ) / sizeof (i2c_config [0 ])] = {0 };
49
49
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
+
50
198
static rt_err_t stm32_i2c_init (struct stm32_i2c * i2c_drv )
51
199
{
52
200
RT_ASSERT (i2c_drv != RT_NULL );
@@ -326,12 +474,8 @@ static rt_ssize_t stm32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
326
474
return ret ;
327
475
}
328
476
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 };
335
479
336
480
int RT_hw_i2c_bus_init (void )
337
481
{
0 commit comments