@@ -47,6 +47,154 @@ static struct stm32_i2c_config i2c_config[] =
4747
4848static 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+
50198static 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
336480int RT_hw_i2c_bus_init (void )
337481{
0 commit comments