1+ /*
2+ * Copyright (c) 2006-2025, RT-Thread Development Team
3+ *
4+ * SPDX-License-Identifier: Apache-2.0
5+ */
6+
7+ #include "drv_hw_i2c.h"
8+
9+ #ifdef RT_USING_I2C
10+
11+ #define LOG_TAG "drv.hw_i2c"
12+ #include <rtdbg.h>
13+
14+ #if !defined(BSP_USING_HW_I2C0 ) && !defined(BSP_USING_HW_I2C1 )
15+ #error "Please define at least one BSP_USING_HW_I2Cx in board.h"
16+ #endif
17+
18+ static const struct gd32_i2c_config i2c_configs [] =
19+ {
20+ #ifdef BSP_USING_HW_I2C0
21+ {
22+ .i2c_periph = I2C0 ,
23+ .periph_clk = RCU_I2C0 ,
24+
25+ .scl_clk = RCU_GPIOA ,
26+ .scl_port = GPIOA ,
27+ .scl_pin = GPIO_PIN_9 ,
28+ .scl_af = GPIO_AF_1 ,
29+ .sda_clk = RCU_GPIOA ,
30+ .sda_port = GPIOA ,
31+ .sda_pin = GPIO_PIN_10 ,
32+ .sda_af = GPIO_AF_1 ,
33+
34+ .device_name = "i2c0" ,
35+ },
36+ #endif
37+ #ifdef BSP_USING_HW_I2C1
38+ {
39+ .i2c_periph = I2C1 ,
40+ .periph_clk = RCU_I2C1 ,
41+
42+ .scl_clk = RCU_GPIOB ,
43+ .scl_port = GPIOB ,
44+ .scl_pin = GPIO_PIN_10 ,
45+ .scl_af = GPIO_AF_1 ,
46+ .sda_clk = RCU_GPIOB ,
47+ .sda_port = GPIOB ,
48+ .sda_pin = GPIO_PIN_11 ,
49+ .sda_af = GPIO_AF_1 ,
50+ .device_name = "i2c1" ,
51+ },
52+ #endif
53+ };
54+ };
55+
56+ static struct gd32_i2c i2c_objs [sizeof (i2c_configs ) / sizeof (i2c_configs [0 ])];
57+
58+ static rt_ssize_t gd32_i2c_master_xfer (struct rt_i2c_bus_device * bus ,
59+ struct rt_i2c_msg msgs [],
60+ rt_uint32_t num )
61+ {
62+ struct gd32_i2c * i2c_dev = rt_container_of (bus , struct gd32_i2c , parent );
63+ const struct gd32_i2c_config * config = i2c_dev -> config ;
64+ rt_uint32_t i2c_periph = config -> i2c_periph ;
65+ rt_uint32_t i ;
66+ rt_err_t ret = RT_EOK ;
67+
68+ /* 等待总线空闲 */
69+ while (i2c_flag_get (i2c_periph , I2C_FLAG_I2CBSY ));
70+
71+ for (i = 0 ; i < num ; i ++ )
72+ {
73+ struct rt_i2c_msg * msg = & msgs [i ];
74+ rt_uint16_t slave_addr = msg -> addr ;
75+
76+ /* 发送起始信号 */
77+ i2c_start_on_bus (i2c_periph );
78+ while (!i2c_flag_get (i2c_periph , I2C_FLAG_SBSEND ));
79+
80+ if (msg -> flags & RT_I2C_RD ) /* 读操作 */
81+ {
82+ i2c_master_addressing (i2c_periph , slave_addr << 1 , I2C_RECEIVER );
83+ }
84+ else
85+ {
86+ i2c_master_addressing (i2c_periph , slave_addr << 1 , I2C_TRANSMITTER );
87+ }
88+
89+ while (!i2c_flag_get (i2c_periph , I2C_FLAG_ADDSEND ));
90+ i2c_flag_clear (i2c_periph , I2C_FLAG_ADDSEND );
91+
92+ if (msg -> flags & RT_I2C_RD ) /* 读数据 */
93+ {
94+ if (msg -> len == 1 )
95+ {
96+ i2c_ack_config (i2c_periph , I2C_ACK_DISABLE );
97+ }
98+ else
99+ {
100+ i2c_ack_config (i2c_periph , I2C_ACK_ENABLE );
101+ }
102+
103+ for (rt_uint32_t j = 0 ; j < msg -> len ; j ++ )
104+ {
105+ if (j == msg -> len - 1 )
106+ {
107+ i2c_ack_config (i2c_periph , I2C_ACK_DISABLE );
108+ }
109+ while (!i2c_flag_get (i2c_periph , I2C_FLAG_RBNE ));
110+ msg -> buf [j ] = i2c_data_receive (i2c_periph );
111+ }
112+ }
113+ else
114+ {
115+ for (rt_uint32_t j = 0 ; j < msg -> len ; j ++ )
116+ {
117+ while (!i2c_flag_get (i2c_periph , I2C_FLAG_TBE ));
118+ i2c_data_transmit (i2c_periph , msg -> buf [j ]);
119+ }
120+ while (!i2c_flag_get (i2c_periph , I2C_FLAG_BTC ));
121+ }
122+
123+ if (!(msg -> flags & RT_I2C_NO_STOP ))
124+ {
125+ i2c_stop_on_bus (i2c_periph );
126+ while (i2c_flag_get (i2c_periph , I2C_FLAG_STPDET ));
127+ }
128+ }
129+
130+ return (ret == RT_EOK ) ? i : ret ;
131+ }
132+
133+
134+ static const struct rt_i2c_bus_device_ops gd32_i2c_ops =
135+ {
136+ .master_xfer = gd32_i2c_master_xfer ,
137+ .slave_xfer = RT_NULL ,
138+ .i2c_bus_control = RT_NULL ,
139+ };
140+
141+ int rt_hw_i2c_init (void )
142+ {
143+ rt_size_t obj_num = sizeof (i2c_objs ) / sizeof (struct gd32_i2c );
144+ rt_err_t result ;
145+
146+ for (int i = 0 ; i < obj_num ; i ++ )
147+ {
148+ struct gd32_i2c * i2c_obj = & i2c_objs [i ];
149+ const struct gd32_i2c_config * config = & i2c_configs [i ];
150+
151+ i2c_obj -> config = config ;
152+
153+ /*
154+ * TODO: 从 board.h 获取时钟频率, 此处为示例
155+ * 您可以在板级配置中定义 I2C0_CLOCK_HZ, I2C1_CLOCK_HZ
156+ */
157+ i2c_obj -> i2c_clock_hz = 100000 ; // 默认为 100KHz
158+
159+ rcu_periph_clock_enable (config -> periph_clk );
160+ rcu_periph_clock_enable (config -> scl_clk );
161+ rcu_periph_clock_enable (config -> sda_clk );
162+
163+ gpio_af_set (config -> scl_port , config -> scl_af , config -> scl_pin );
164+ gpio_mode_set (config -> scl_port , GPIO_MODE_AF , GPIO_PUPD_PULLUP , config -> scl_pin );
165+ gpio_output_options_set (config -> scl_port , GPIO_OTYPE_OD , GPIO_OSPEED_50MHZ , config -> scl_pin );
166+
167+ gpio_af_set (config -> sda_port , config -> sda_af , config -> sda_pin );
168+ gpio_mode_set (config -> sda_port , GPIO_MODE_AF , GPIO_PUPD_PULLUP , config -> sda_pin );
169+ gpio_output_options_set (config -> sda_port , GPIO_OTYPE_OD , GPIO_OSPEED_50MHZ , config -> sda_pin );
170+
171+ i2c_deinit (config -> i2c_periph );
172+ i2c_clock_config (config -> i2c_periph , i2c_obj -> i2c_clock_hz , I2C_DTCY_2 );
173+ i2c_mode_addr_config (config -> i2c_periph , I2C_I2CMODE_ENABLE , I2C_ADDFORMAT_7BITS , 0x00 );
174+ i2c_enable (config -> i2c_periph );
175+ i2c_ack_config (config -> i2c_periph , I2C_ACK_ENABLE );
176+
177+ i2c_obj -> parent .ops = & gd32_i2c_ops ;
178+ result = rt_i2c_bus_device_register (& i2c_obj -> parent , config -> device_name );
179+ RT_ASSERT (result == RT_EOK );
180+
181+ LOG_D ("%s bus init success, clock %dHz." , config -> device_name , i2c_obj -> i2c_clock_hz );
182+ }
183+
184+ return RT_EOK ;
185+ }
186+
187+ INIT_BOARD_EXPORT (rt_hw_i2c_init );
188+
189+ #endif
0 commit comments