@@ -38,180 +38,215 @@ static const struct gd32_i2c_config i2c_configs[] =
3838
3939static struct gd32_i2c i2c_objs [sizeof (i2c_configs ) / sizeof (i2c_configs [0 ])];
4040
41+
42+ // 在 gd32_i2c_irq_handler 函数定义之前,加入以下辅助函数
43+
4144/**
42- * @brief I2C event interrupt handler. This is the core state machine for I2C transfers.
43- * @param i2c_obj: The I2C object context.
44- */
45- /**
46- * @brief I2C event interrupt handler. This is the core state machine for I2C transfers.
47- * @param i2c_obj: The I2C object context.
45+ * @brief 处理起始位已发送 (SBSEND) 事件
4846 */
47+ static inline void gd32_i2c_handle_sbsend (struct gd32_i2c * i2c_obj )
48+ {
49+ uint32_t i2c_periph = i2c_obj -> config -> i2c_periph ;
50+ uint8_t dir = (i2c_obj -> msg -> flags & RT_I2C_RD ) ? I2C_RECEIVER : I2C_TRANSMITTER ;
51+ i2c_master_addressing (i2c_periph , i2c_obj -> msg -> addr << 1 , dir );
52+ }
53+
4954/**
50- * @brief I2C event interrupt handler. This is the core state machine for I2C transfers.
51- * This implementation is heavily inspired by the robust state machine found
52- * in the Zephyr OS GD32 I2C driver.
53- * @param i2c_obj: The I2C object context.
55+ * @brief 处理地址已发送 (ADDSEND) 事件
5456 */
57+ static inline void gd32_i2c_handle_addsend (struct gd32_i2c * i2c_obj )
58+ {
59+ uint32_t i2c_periph = i2c_obj -> config -> i2c_periph ;
60+
61+ /* 清除 ADDSEND 标志位 (通过读取 STAT0 和 STAT1) */
62+ (void )I2C_STAT0 (i2c_periph );
63+ (void )I2C_STAT1 (i2c_periph );
64+
65+ if (i2c_obj -> msg -> flags & RT_I2C_RD ) /* Master Receiver */
66+ {
67+ if (i2c_obj -> msg -> len == 1 )
68+ {
69+ // 对于 N=1 的读取,此时必须禁用 ACK
70+ i2c_ack_config (i2c_periph , I2C_ACK_DISABLE );
71+ }
72+ // 对于 N=2 的读取,POS 位已在 xfer 中设置,ACK 在 BTC 中处理
73+ }
74+ }
75+
5576/**
56- * @brief I2C event interrupt handler. This is the core state machine for I2C transfers.
57- * This version is corrected to use macros compatible with the provided gd32e23x_i2c.h.
58- * @param i2c_obj: The I2C object context.
77+ * @brief 处理发送缓冲区为空 (TBE) 事件
5978 */
79+ static inline void gd32_i2c_handle_tbe (struct gd32_i2c * i2c_obj )
80+ {
81+ uint32_t i2c_periph = i2c_obj -> config -> i2c_periph ;
82+
83+ if (i2c_obj -> count < i2c_obj -> msg -> len )
84+ {
85+ i2c_data_transmit (i2c_periph , i2c_obj -> msg -> buf [i2c_obj -> count ++ ]);
86+ }
87+ else
88+ {
89+ // 所有数据已发送,等待 BTC 标志来确认传输完成
90+ // 此处不再发送数据,TBE 中断会在 BTC 置位后自动停止
91+ }
92+ }
93+
6094/**
61- * @brief I2C event interrupt handler. This is the core state machine for I2C transfers.
62- * This version corrects the BTC/RBNE logic for short (N<=2) vs long (N>2) reads.
63- * @param i2c_obj: The I2C object context.
95+ * @brief 处理接收缓冲区非空 (RBNE) 事件
6496 */
65- static void gd32_i2c_irq_handler (struct gd32_i2c * i2c_obj )
97+ static inline void gd32_i2c_handle_rbne (struct gd32_i2c * i2c_obj )
6698{
6799 uint32_t i2c_periph = i2c_obj -> config -> i2c_periph ;
68- uint32_t stat0 = I2C_STAT0 (i2c_periph );
69- uint32_t stat1 = I2C_STAT1 (i2c_periph );
70-
71- LOG_D ("IRQ handler: STAT0=0x%08x, STAT1=0x%08x" , stat0 , stat1 );
72100
73- if (stat0 & I2C_STAT0_SBSEND )
101+ // 只要 RBNE 置位,就读取数据
102+ if (i2c_obj -> count < i2c_obj -> msg -> len )
74103 {
75- uint8_t dir = (i2c_obj -> msg -> flags & RT_I2C_RD ) ? I2C_RECEIVER : I2C_TRANSMITTER ;
76- i2c_master_addressing (i2c_periph , i2c_obj -> msg -> addr << 1 , dir );
104+ i2c_obj -> msg -> buf [i2c_obj -> count ++ ] = i2c_data_receive (i2c_periph );
77105 }
78- else if ( stat0 & I2C_STAT0_ADDSEND )
106+ else
79107 {
80- /* 清除 ADDSEND 标志 */
81- (void )stat1 ;
108+ // 意外接收到数据,丢弃
109+ (void )i2c_data_receive (i2c_periph );
110+ }
111+ }
82112
83- if (i2c_obj -> msg -> flags & RT_I2C_RD ) /* Master Receiver */
113+ /**
114+ * @brief 处理字节传输完成 (BTC) 事件
115+ */
116+ static inline void gd32_i2c_handle_btc (struct gd32_i2c * i2c_obj )
117+ {
118+ uint32_t i2c_periph = i2c_obj -> config -> i2c_periph ;
119+
120+ if (i2c_obj -> msg -> flags & RT_I2C_RD ) /* Master Receiver */
121+ {
122+ /*
123+ * BTC 在接收模式下的处理逻辑非常关键
124+ * 它用于处理 N>2 时的最后3个字节 和 N=2 的情况
125+ */
126+ if (i2c_obj -> msg -> len > 2 && i2c_obj -> count == i2c_obj -> msg -> len - 3 )
84127 {
85- if (i2c_obj -> msg -> len == 1 )
86- {
87- // N=1: 清除ACK位, 然后立即发送STOP
88- i2c_ack_config (i2c_periph , I2C_ACK_DISABLE );
89- if (!(i2c_obj -> msg -> flags & RT_I2C_NO_STOP ))
90- {
91- i2c_stop_on_bus (i2c_periph );
92- }
93- }
94- else if (i2c_obj -> msg -> len == 2 )
95- {
96- // N=2: 在ADDSEND之后, 必须立即清除ACK位
97- i2c_ack_config (i2c_periph , I2C_ACK_DISABLE );
98- }
128+ // 场景:还剩最后3个字节时,我们收到了 BTC
129+ // 1. 关闭 BUF 中断,切换到 BTC 驱动的接收模式
130+ i2c_interrupt_disable (i2c_periph , I2C_INT_BUF );
131+ // 2. 读取当前数据
132+ i2c_obj -> msg -> buf [i2c_obj -> count ++ ] = i2c_data_receive (i2c_periph );
99133 }
100- }
101- else if ((stat1 & I2C_STAT1_MASTER ) && (stat1 & I2C_STAT1_TR )) /* Master Transmitter */
102- {
103- if (stat0 & I2C_STAT0_TBE )
134+ else if (i2c_obj -> count == i2c_obj -> msg -> len - 2 )
104135 {
105- if (i2c_obj -> count < i2c_obj -> msg -> len )
136+ // 场景:还剩最后2个字节时,收到了 BTC
137+ // 1. 关闭 ACK
138+ i2c_ack_config (i2c_periph , I2C_ACK_DISABLE );
139+ // 2. 读取倒数第二个字节
140+ i2c_obj -> msg -> buf [i2c_obj -> count ++ ] = i2c_data_receive (i2c_periph );
141+ // 3. 发送 STOP
142+ if (!(i2c_obj -> msg -> flags & RT_I2C_NO_STOP ))
106143 {
107- i2c_data_transmit (i2c_periph , i2c_obj -> msg -> buf [i2c_obj -> count ++ ]);
108- }
109- else
110- {
111- i2c_interrupt_disable (i2c_periph , I2C_INT_BUF );
144+ i2c_stop_on_bus (i2c_periph );
112145 }
146+ // 4. 读取最后一个字节 (它已经在移位寄存器里了)
147+ i2c_obj -> msg -> buf [i2c_obj -> count ++ ] = i2c_data_receive (i2c_periph );
148+
149+ // 5. 传输完成
150+ i2c_interrupt_disable (i2c_periph , I2C_INT_EV );
151+ i2c_interrupt_disable (i2c_periph , I2C_INT_ERR );
152+ i2c_interrupt_disable (i2c_periph , I2C_INT_BUF );
153+ i2c_obj -> result = RT_EOK ;
154+ rt_completion_done (& i2c_obj -> completion );
113155 }
114- if (stat0 & I2C_STAT0_BTC )
156+ }
157+ else /* Master Transmitter */
158+ {
159+ // 发送模式下,BTC 表示最后一个字节已发送完成
160+ if (i2c_obj -> count >= i2c_obj -> msg -> len )
115161 {
116- if (i2c_obj -> count >= i2c_obj -> msg -> len )
162+ if (!( i2c_obj -> msg -> flags & RT_I2C_NO_STOP ) )
117163 {
118- if (!(i2c_obj -> msg -> flags & RT_I2C_NO_STOP ))
119- {
120- i2c_stop_on_bus (i2c_periph );
121- }
122- i2c_interrupt_disable (i2c_periph , I2C_INT_EV );
123- i2c_interrupt_disable (i2c_periph , I2C_INT_ERR );
124- i2c_interrupt_disable (i2c_periph , I2C_INT_BUF );
125- i2c_obj -> result = RT_EOK ;
126- rt_completion_done (& i2c_obj -> completion );
164+ i2c_stop_on_bus (i2c_periph );
127165 }
166+ i2c_interrupt_disable (i2c_periph , I2C_INT_EV );
167+ i2c_interrupt_disable (i2c_periph , I2C_INT_ERR );
168+ i2c_interrupt_disable (i2c_periph , I2C_INT_BUF );
169+ i2c_obj -> result = RT_EOK ;
170+ rt_completion_done (& i2c_obj -> completion );
128171 }
129172 }
130- else if ((stat1 & I2C_STAT1_MASTER ) && !(stat1 & I2C_STAT1_TR )) /* Master Receiver */
131- {
132- /*
133- * 关键点: 必须优先处理 BTC,因为 BTC 标志是 TBE/RBNE 的超集。
134- * 在接收的最后阶段,BTC 和 RBNE 可能会同时置位。
135- */
173+ }
136174
137- if (stat0 & I2C_STAT0_BTC )
175+ /**
176+ * @brief I2C event interrupt handler. This is the core state machine for I2C transfers.
177+ * This version is refactored to be cleaner and more robust, inspired by Zephyr OS.
178+ * @param i2c_obj: The I2C object context.
179+ */
180+ /**
181+ * @brief I2C event interrupt handler. This is the core state machine for I2C transfers.
182+ * This version is refactored to be cleaner and more robust.
183+ * @param i2c_obj: The I2C object context.
184+ */
185+ static void gd32_i2c_irq_handler (struct gd32_i2c * i2c_obj )
186+ {
187+ uint32_t i2c_periph = i2c_obj -> config -> i2c_periph ;
188+ uint32_t stat0 , stat1 ;
189+
190+ stat0 = I2C_STAT0 (i2c_periph );
191+ stat1 = I2C_STAT1 (i2c_periph ); // 读取STAT1用于清除某些标志位,如ADDSEND
192+
193+ LOG_D ("IRQ handler: STAT0=0x%08x, STAT1=0x%08x" , stat0 , stat1 );
194+
195+ // --- Master Mode Event Handling ---
196+ if (stat1 & I2C_STAT1_MASTER )
197+ {
198+ if (stat0 & I2C_STAT0_SBSEND )
138199 {
139- /*
140- * BTC 表示字节传输完成。在接收模式下,这通常用于处理传输的最后几个字节。
141- * 这是处理 N=2 和 N>3 场景下最后阶段的地方。
142- */
143- if (i2c_obj -> msg -> len == 2 ) // N=2 的特殊情况
144- {
145- // 1. 发送STOP信号
146- if (!(i2c_obj -> msg -> flags & RT_I2C_NO_STOP ))
147- {
148- i2c_stop_on_bus (i2c_periph );
149- }
150- // 2. 连续读取两个字节
151- i2c_obj -> msg -> buf [i2c_obj -> count ++ ] = i2c_data_receive (i2c_periph );
152- i2c_obj -> msg -> buf [i2c_obj -> count ++ ] = i2c_data_receive (i2c_periph );
200+ gd32_i2c_handle_sbsend (i2c_obj );
201+ return ; // SBSEND 是独立的起始事件
202+ }
153203
154- // 3. 结束传输
155- i2c_interrupt_disable (i2c_periph , I2C_INT_EV );
156- i2c_interrupt_disable (i2c_periph , I2C_INT_ERR );
157- i2c_interrupt_disable (i2c_periph , I2C_INT_BUF );
204+ if (stat0 & I2C_STAT0_ADDSEND )
205+ {
206+ gd32_i2c_handle_addsend (i2c_obj );
207+ // 对于发送器,地址发送后TBE会置位,需要继续处理
208+ // 对于接收器,地址发送后需要等待RBNE,所以可以不立即返回
209+ }
158210
159- i2c_obj -> result = RT_EOK ;
160- rt_completion_done (& i2c_obj -> completion );
211+ if (i2c_obj -> msg -> flags & RT_I2C_RD ) /* Master Receiver */
212+ {
213+ /* 接收器逻辑: BTC优先,因为它用于处理N>1接收的结束阶段 */
214+ if (stat0 & I2C_STAT0_BTC )
215+ {
216+ gd32_i2c_handle_btc (i2c_obj );
161217 }
162- else // N > 2 场景下的最后阶段 (接收最后两个字节 )
218+ else if ( stat0 & I2C_STAT0_RBNE )
163219 {
164- i2c_interrupt_disable (i2c_periph , I2C_INT_BUF ); // 关闭缓冲区中断
165-
166- // 1. 禁用ACK
167- i2c_ack_config (i2c_periph , I2C_ACK_DISABLE );
168- // 2. 读取倒数第二个字节
169- i2c_obj -> msg -> buf [i2c_obj -> count ++ ] = i2c_data_receive (i2c_periph );
170- // 3. 发送STOP信号
171- if (!(i2c_obj -> msg -> flags & RT_I2C_NO_STOP ))
172- {
173- i2c_stop_on_bus (i2c_periph );
174- }
175- // 4. 读取最后一个字节
176- i2c_obj -> msg -> buf [i2c_obj -> count ++ ] = i2c_data_receive (i2c_periph );
177-
178- // 5. 结束传输
179- i2c_interrupt_disable (i2c_periph , I2C_INT_EV );
180- i2c_interrupt_disable (i2c_periph , I2C_INT_ERR );
181-
182- i2c_obj -> result = RT_EOK ;
183- rt_completion_done (& i2c_obj -> completion );
220+ gd32_i2c_handle_rbne (i2c_obj );
184221 }
185222 }
186- else if ( stat0 & I2C_STAT0_RBNE )
223+ else /* Master Transmitter */
187224 {
188- if ((i2c_obj -> msg -> len > 2 ) && (i2c_obj -> count == i2c_obj -> msg -> len - 3 ))
225+ /*
226+ * 发送器逻辑:
227+ * 当TBE置位时,我们就可以发送数据。
228+ * 当BTC也置位时,表示前一个字节已经完整发送出去。
229+ * 我们只在所有数据都发送完毕后,才关心BTC,用它来触发STOP。
230+ */
231+ if (i2c_obj -> count < i2c_obj -> msg -> len )
189232 {
190- /* 剩下最后3个字节时,等待BTC来处理,不再响应RBNE */
191- i2c_interrupt_disable (i2c_periph , I2C_INT_BUF );
192- i2c_obj -> msg -> buf [i2c_obj -> count ++ ] = i2c_data_receive (i2c_periph );
233+ // 如果还有数据要发送,并且发送缓冲区为空
234+ if (stat0 & I2C_STAT0_TBE )
235+ {
236+ gd32_i2c_handle_tbe (i2c_obj ); // 发送下一个字节
237+ }
193238 }
194- else // 处理 N=1 和 N>3 场景下的普通字节
239+ else
195240 {
196- i2c_obj -> msg -> buf [i2c_obj -> count ++ ] = i2c_data_receive (i2c_periph );
197-
198- if (i2c_obj -> count == i2c_obj -> msg -> len )
241+ // 所有数据已写入缓冲区,等待最后一个字节发送完成
242+ if (stat0 & I2C_STAT0_BTC )
199243 {
200- // 仅用于 N=1 的场景
201- if (!(i2c_obj -> msg -> flags & RT_I2C_NO_STOP ))
202- {
203- i2c_stop_on_bus (i2c_periph ); // 注意: 对于N=1, STOP应在ADDSEND后就发送
204- }
205- i2c_interrupt_disable (i2c_periph , I2C_INT_EV );
206- i2c_interrupt_disable (i2c_periph , I2C_INT_ERR );
207- i2c_interrupt_disable (i2c_periph , I2C_INT_BUF );
208-
209- i2c_obj -> result = RT_EOK ;
210- rt_completion_done (& i2c_obj -> completion );
244+ gd32_i2c_handle_btc (i2c_obj ); // 调用它来发送STOP并完成传输
211245 }
212246 }
213247 }
214248 }
249+ // --- Slave Mode event handling would go here (if implemented) ---
215250}
216251
217252/**
@@ -370,28 +405,47 @@ static rt_ssize_t gd32_i2c_master_xfer(struct rt_i2c_bus_device *bus, struct rt_
370405 i2c_obj -> result = - RT_ERROR ;
371406 rt_completion_init (& i2c_obj -> completion );
372407
408+ /* 默认开启ACK */
373409 i2c_ack_config (i2c_periph , I2C_ACK_ENABLE );
410+ /* 默认ACK当前字节 */
374411 i2c_ackpos_config (i2c_periph , I2C_ACKPOS_CURRENT );
375412
376- if ((i2c_obj -> msg -> flags & RT_I2C_RD ) && (i2c_obj -> msg -> len == 2 ))
413+ /* 针对特定长度读取的预处理 */
414+ if (i2c_obj -> msg -> flags & RT_I2C_RD )
377415 {
378- i2c_ackpos_config (i2c_periph , I2C_ACKPOS_NEXT );
416+ if (i2c_obj -> msg -> len == 1 )
417+ {
418+ // N=1: ADDSEND之后会关闭ACK, 此处无需操作
419+ }
420+ else if (i2c_obj -> msg -> len == 2 )
421+ {
422+ // N=2: 设置POS位,让硬件在接收第2个字节时准备NACK
423+ i2c_ackpos_config (i2c_periph , I2C_ACKPOS_NEXT );
424+ }
379425 }
380-
426+
427+ /* 使能所有需要的 I2C 中断 */
381428 i2c_interrupt_enable (i2c_periph , I2C_INT_EV );
382429 i2c_interrupt_enable (i2c_periph , I2C_INT_ERR );
383430 i2c_interrupt_enable (i2c_periph , I2C_INT_BUF );
384431
432+ /* 发送起始位,启动传输 */
385433 i2c_start_on_bus (i2c_periph );
434+
386435 ret = rt_completion_wait (& i2c_obj -> completion , bus -> timeout );
387436
437+ /* 后续的超时和错误处理... (保持不变) */
388438 if (ret != RT_EOK )
389439 {
390440 LOG_E ("I2C msg %d timeout. Forcing cleanup." , i );
391441 i2c_interrupt_disable (i2c_periph , I2C_INT_EV );
392442 i2c_interrupt_disable (i2c_periph , I2C_INT_ERR );
393443 i2c_interrupt_disable (i2c_periph , I2C_INT_BUF );
394- i2c_stop_on_bus (i2c_periph );
444+ // 尝试发送一个STOP位来释放总线
445+ if (!(msgs [i ].flags & RT_I2C_NO_STOP ))
446+ {
447+ i2c_stop_on_bus (i2c_periph );
448+ }
395449 return - RT_ETIMEOUT ;
396450 }
397451
0 commit comments