Skip to content

Commit 214f65f

Browse files
committed
fix
1 parent fa8c95e commit 214f65f

File tree

1 file changed

+189
-135
lines changed

1 file changed

+189
-135
lines changed

bsp/gd32/arm/libraries/gd32_drivers/drv_hw_i2c.c

Lines changed: 189 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -38,180 +38,215 @@ static const struct gd32_i2c_config i2c_configs[] =
3838

3939
static 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

Comments
 (0)