Skip to content

Commit 8de6397

Browse files
committed
add all
1 parent d748c84 commit 8de6397

File tree

1 file changed

+267
-11
lines changed

1 file changed

+267
-11
lines changed

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

Lines changed: 267 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -116,31 +116,287 @@ static inline void i2c_log_error(struct gd32_i2c *i2c_dev)
116116
if (i2c_dev->errs & I2C_GD32_ERR_BUSY) LOG_E("I2C bus is busy");
117117
}
118118

119+
static inline void gd32_i2c_xfer_read(struct gd32_i2c *i2c_obj)
120+
{
121+
const struct gd32_i2c_config *cfg = i2c_obj->config;
122+
123+
i2c_obj->current->len--;
124+
*i2c_obj->current->buf = I2C_DATA(cfg->i2c_periph);
125+
i2c_obj->current->buf++;
119126

120-
static inline void i2c_xfer_read(struct gd32_i2c *i2c_obj)
127+
/* 如果当前 msg 读完,但总传输长度 > 0,则切换到下一个 msg */
128+
if ((i2c_obj->xfer_len > 0U) && (i2c_obj->current->len == 0U))
129+
{
130+
i2c_obj->current++;
131+
}
132+
}
133+
134+
/**
135+
* @brief 将当前消息缓冲区的一个字节写入 I2C_DATA 寄存器
136+
*/
137+
static inline void gd32_i2c_xfer_write(struct gd32_i2c *i2c_obj)
121138
{
122-
139+
const struct gd32_i2c_config *cfg = i2c_obj->config;
140+
141+
i2c_obj->current->len--;
142+
I2C_DATA(cfg->i2c_periph) = *i2c_obj->current->buf;
143+
i2c_obj->current->buf++;
144+
145+
/* 如果当前 msg 写完,但总传输长度 > 0,则切换到下一个 msg */
146+
if ((i2c_obj->xfer_len > 0U) && (i2c_obj->current->len == 0U))
147+
{
148+
i2c_obj->current++;
149+
}
123150
}
124151

125-
static inline void i2c_xfer_write(struct gd32_i2c *i2c_obj)
152+
/**
153+
* @brief 处理 TBE (发送缓冲区为空) 事件
154+
*/
155+
static void gd32_i2c_handle_tbe(struct gd32_i2c *i2c_obj)
126156
{
127-
157+
const struct gd32_i2c_config *cfg = i2c_obj->config;
158+
159+
if (i2c_obj->xfer_len > 0U)
160+
{
161+
i2c_obj->xfer_len--;
162+
if (i2c_obj->xfer_len == 0U)
163+
{
164+
/* 这是最后一个要发送的数据,关闭缓冲区中断,等待 BTC 中断来确认发送完成 */
165+
I2C_CTL1(cfg->i2c_periph) &= ~I2C_CTL1_BUFIE;
166+
}
167+
gd32_i2c_xfer_write(i2c_obj);
168+
}
169+
else
170+
{
171+
/* 所有数据都已发送,且 BTC 事件触发了此函数 */
172+
/* 产生 STOP 信号并唤醒等待的线程 */
173+
I2C_CTL0(cfg->i2c_periph) |= I2C_CTL0_STOP;
174+
rt_completion_done(&i2c_obj->sync_sem);
175+
}
128176
}
129177

130-
static void gd32_i2c_event_handler(struct gd32_i2c *i2c_obj)
178+
/**
179+
* @brief 处理 RBNE (接收缓冲区非空) 事件
180+
*/
181+
static void gd32_i2c_handle_rbne(struct gd32_i2c *i2c_obj)
131182
{
132-
183+
const struct gd32_i2c_config *cfg = i2c_obj->config;
184+
185+
switch (i2c_obj->xfer_len)
186+
{
187+
case 0:
188+
/* 不应该发生,但如果发生了,直接唤醒线程 */
189+
rt_completion_done(&i2c_obj->sync_sem);
190+
break;
191+
case 1:
192+
/* 如果总共只读1个字节,在这里读取并唤醒线程 */
193+
i2c_obj->xfer_len--;
194+
gd32_i2c_xfer_read(i2c_obj);
195+
rt_completion_done(&i2c_obj->sync_sem);
196+
break;
197+
case 2:
198+
case 3:
199+
/*
200+
* 如果总读取长度为2,或总长度>3且剩下3个字节时,
201+
* 关闭缓冲区中断,等待 BTC 中断来处理最后几个字节的特殊读取序列。
202+
*/
203+
I2C_CTL1(cfg->i2c_periph) &= ~I2C_CTL1_BUFIE;
204+
break;
205+
default:
206+
/* 正常情况,直接读取数据 */
207+
i2c_obj->xfer_len--;
208+
gd32_i2c_xfer_read(i2c_obj);
209+
break;
210+
}
133211
}
134212

135-
// Error interrupt handler
136-
static void gd32_i2c_error_handler(struct gd32_i2c *i2c_obj)
213+
/**
214+
* @brief 处理 BTC (字节传输完成) 事件
215+
*/
216+
static void gd32_i2c_handle_btc(struct gd32_i2c *i2c_obj)
137217
{
138-
218+
const struct gd32_i2c_config *cfg = i2c_obj->config;
219+
220+
if (i2c_obj->current->flags & RT_I2C_RD)
221+
{
222+
/* 读模式下的 BTC */
223+
switch (i2c_obj->xfer_len)
224+
{
225+
case 2:
226+
/* 在读取最后两个字节之前,必须产生 STOP 信号 */
227+
I2C_CTL0(cfg->i2c_periph) |= I2C_CTL0_STOP;
228+
/* 读取最后两个字节 */
229+
i2c_obj->xfer_len -= 2;
230+
gd32_i2c_xfer_read(i2c_obj);
231+
gd32_i2c_xfer_read(i2c_obj);
232+
/* 唤醒线程 */
233+
rt_completion_done(&i2c_obj->sync_sem);
234+
break;
235+
case 3:
236+
/* 清除 ACKEN 位,这样在收到下一个字节后会回复 NACK */
237+
I2C_CTL0(cfg->i2c_periph) &= ~I2C_CTL0_ACKEN;
238+
/* 读取倒数第3个字节 */
239+
i2c_obj->xfer_len--;
240+
gd32_i2c_xfer_read(i2c_obj);
241+
/* 等待下一个 BTC 来处理最后两个字节 */
242+
break;
243+
default:
244+
/* 其他情况(不应该发生),按 RBNE 处理 */
245+
gd32_i2c_handle_rbne(i2c_obj);
246+
break;
247+
}
248+
}
249+
else
250+
{
251+
/* 写模式下的 BTC 表示最后一个字节已发送完成,可以发 STOP */
252+
gd32_i2c_handle_tbe(i2c_obj);
253+
}
139254
}
140255

141-
static rt_err_t i2c_xfer_begin(struct gd32_i2c *i2c_obj)
256+
/**
257+
* @brief 处理 ADDSEND (地址已发送) 事件
258+
*/
259+
static void gd32_i2c_handle_addsend(struct gd32_i2c *i2c_obj)
142260
{
143-
261+
const struct gd32_i2c_config *cfg = i2c_obj->config;
262+
263+
/* 对于1字节读取,在地址发送后就要准备发送 NACK */
264+
if ((i2c_obj->current->flags & RT_I2C_RD) && (i2c_obj->xfer_len <= 1U))
265+
{
266+
I2C_CTL0(cfg->i2c_periph) &= ~I2C_CTL0_ACKEN;
267+
}
268+
269+
/* 清除 ADDSEND 标志位 (通过读取 STAT0 和 STAT1) */
270+
(void)I2C_STAT0(cfg->i2c_periph);
271+
(void)I2C_STAT1(cfg->i2c_periph);
272+
273+
/* 处理10位地址读操作的 RESTART */
274+
if (i2c_obj->is_restart)
275+
{
276+
i2c_obj->is_restart = RT_FALSE;
277+
i2c_obj->current->flags |= RT_I2C_RD; // 恢复读标志
278+
/* 产生 RESTART 信号 */
279+
I2C_CTL0(cfg->i2c_periph) |= I2C_CTL0_START;
280+
return; /* 提前返回,等待下一个 SBSEND 事件 */
281+
}
282+
283+
/* 对于1字节读取,在地址发送后就要准备发送 STOP */
284+
if ((i2c_obj->current->flags & RT_I2C_RD) && (i2c_obj->xfer_len == 1U))
285+
{
286+
I2C_CTL0(cfg->i2c_periph) |= I2C_CTL0_STOP;
287+
}
288+
}
289+
290+
static void gd32_i2c_event_handler(struct gd32_i2c *i2c_obj)
291+
{
292+
const struct gd32_i2c_config *cfg;
293+
uint32_t stat0;
294+
295+
RT_ASSERT(i2c_obj != RT_NULL);
296+
cfg = i2c_obj->config;
297+
298+
stat0 = I2C_STAT0(cfg->i2c_periph);
299+
300+
/*
301+
* 状态位检查的顺序至关重要,必须与 Zephyr 驱动保持一致,
302+
* 以正确处理各种复杂的传输序列。
303+
*/
304+
if (stat0 & I2C_STAT0_SBSEND)
305+
{
306+
/* 起始位已发送,下一步是发送从机地址 */
307+
if (i2c_obj->current->flags & RT_I2C_RD)
308+
{
309+
I2C_DATA(cfg->i2c_periph) = (i2c_obj->addr1 << 1) | 1;
310+
}
311+
else
312+
{
313+
I2C_DATA(cfg->i2c_periph) = (i2c_obj->addr1 << 1) | 0;
314+
}
315+
}
316+
else if (stat0 & I2C_STAT0_ADD10SEND)
317+
{
318+
/* 10位地址的第一个字节已发送,现在发送第二个字节 */
319+
I2C_DATA(cfg->i2c_periph) = i2c_obj->addr2;
320+
}
321+
else if (stat0 & I2C_STAT0_ADDSEND)
322+
{
323+
/* 从机地址已发送且收到 ACK */
324+
gd32_i2c_handle_addsend(i2c_obj);
325+
}
326+
/*
327+
* 必须先检查 BTC,因为 BTC 是 TBE 和 RBNE 的超集。
328+
* 在某些序列中(如读操作的结尾),硬件会同时置位 BTC 和 RBNE,
329+
* 此时必须由 BTC 的逻辑来处理。
330+
*/
331+
else if (stat0 & I2C_STAT0_BTC)
332+
{
333+
/* 字节传输完成 */
334+
gd32_i2c_handle_btc(i2c_obj);
335+
}
336+
else if (stat0 & I2C_STAT0_RBNE)
337+
{
338+
/* 接收缓冲区非空 */
339+
gd32_i2c_handle_rbne(i2c_obj);
340+
}
341+
else if (stat0 & I2C_STAT0_TBE)
342+
{
343+
/* 发送缓冲区为空 */
344+
gd32_i2c_handle_tbe(i2c_obj);
345+
}
346+
}
347+
348+
void gd32_i2c_error_handler(struct gd32_i2c *i2c_obj)
349+
{
350+
const struct gd32_i2c_config *cfg;
351+
uint32_t stat0;
352+
353+
RT_ASSERT(i2c_obj != RT_NULL);
354+
cfg = i2c_obj->config;
355+
356+
/* 读取状态寄存器以检查错误标志 */
357+
stat0 = I2C_STAT0(cfg->i2c_periph);
358+
359+
/* 1. 检查总线错误 (BERR) */
360+
if (stat0 & I2C_STAT0_BERR)
361+
{
362+
/* 清除 BERR 标志位 (通过写0) */
363+
I2C_STAT0(cfg->i2c_periph) &= ~I2C_STAT0_BERR;
364+
/* 在运行时对象中记录错误类型 */
365+
i2c_obj->errs |= I2C_GD32_ERR_BERR;
366+
}
367+
368+
/* 2. 检查仲裁丢失 (LOSTARB) */
369+
if (stat0 & I2C_STAT0_LOSTARB)
370+
{
371+
/* 清除 LOSTARB 标志位 */
372+
I2C_STAT0(cfg->i2c_periph) &= ~I2C_STAT0_LOSTARB;
373+
i2c_obj->errs |= I2C_GD32_ERR_LARB;
374+
}
375+
376+
/* 3. 检查应答失败 (AERR) */
377+
if (stat0 & I2C_STAT0_AERR)
378+
{
379+
/* 清除 AERR 标志位 */
380+
I2C_STAT0(cfg->i2c_periph) &= ~I2C_STAT0_AERR;
381+
i2c_obj->errs |= I2C_GD32_ERR_AERR;
382+
}
383+
384+
/* 4. 如果记录到了任何错误 */
385+
if (i2c_obj->errs != 0)
386+
{
387+
/*
388+
* 发生错误后,硬件可能处于不确定状态。
389+
* 发送一个 STOP 信号是让总线恢复到已知空闲状态的最佳方式。
390+
*/
391+
I2C_CTL0(cfg->i2c_periph) |= I2C_CTL0_STOP;
392+
393+
/*
394+
* 唤醒在 master_xfer 中等待的线程。
395+
* master_xfer 函数会检查 i2c_obj->errs,发现非零后,
396+
* 就会记录错误日志并向上层返回错误码。
397+
*/
398+
rt_completion_done(&i2c_obj->sync_sem);
399+
}
144400
}
145401

146402
static rt_ssize_t gd32_i2c_master_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)

0 commit comments

Comments
 (0)