I2C函数之中断处理函数(四)

 函数来源于来源于Linux设备驱动开发详解.pdf。

// 1. 定义中断处理函数`s3c24xx_i2c_irq`,该函数用于处理S3C2410 I2C适配器的中断。
//   参数包括:
//   - `irq`: 中断号。
//   - `void *dev_id`: 传递给请求中断处理函数的设备标识符。
//   - `struct pt_regs *regs`: 指向程序状态寄存器的指针,包含中断发生时的上下文信息。
static irqreturn_t s3c24xx_i2c_irq(int irq, void *dev_id, struct pt_regs *regs)

{
    // 3. 声明一个指向`s3c24xx_i2c`结构的指针`i2c`,用于访问I2C设备的私有数据。
    struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)dev_id;

    // 5-7. 声明两个无符号长整型变量`status`和`tmp`,用于存储从寄存器读取的状态信息。
    unsigned long status;
    unsigned long tmp;

    // 8-9. 读取I2C状态寄存器的值,并存储到`status`变量中。
    //       `S3C2410_IICSCON`是I2C状态寄存器的偏移。
    status = readl(i2c->regs + S3C2410_IICSCON);

    // 10-11. 检查状态寄存器中的仲裁丢失位。
    //         `S3C24XX_I2CSTAT_ARBITR`是仲裁丢失的状态位掩码。
    if (status & S3C24XX_I2CSTAT_ARBITR)

    // 12-13. 如果发生仲裁丢失,处理相关逻辑。
        // `STATE_TX_RX`可能是用于标识I2C总线状态的一个宏。
        if (i2c->state == STATE_TX_RX)

    // 14-16. 清除I2C控制寄存器中的低功耗模式和中断挂起位。
    //         `S3C2410_IICCON`是I2C控制寄存器的偏移。
        // `tmp`变量用于临时存储控制寄存器的值。
        tmp = readl(i2c->regs + S3C2410_IICCON);
        tmp &= ~S3C2410_TICCON_LPENPEND;
        writel(tmp, i2c->regs + S3C2410_IICCON);

    // 17. 跳转到标签`out`,结束中断处理。
        goto out;

    // 18-24. 这部分代码似乎是一个条件执行块,用于在特定条件下调用`s3c_i2c_nextbyte`函数
    //         以推进传输工作。但代码不完整,无法提供准确的注释。

    // 23. 如果满足某个条件,则返回`IRQ_HANDLED`,表示中断已被处理。
    //       `IRQ_HANDLED`是一个宏,用于标识中断处理成功。
    return IRQ_HANDLED;

    // 24. 标签`out`,用于结束中断处理函数。
out:
    return 0;
}
// 26. 定义一个名为`i2s_s3c_irq_nextbyte`的静态函数,用于处理I2C中断并推进数据传输。
// 参数包括:
// - `struct s3c24xx_i2c *i2c`: 指向I2C控制器私有数据的指针。
// - `unsigned long cstat`: 当前I2C的状态。
static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long cstat)

{
    // 28-29. 声明局部变量`tmp`(无符号长整型),`byte`(无符号字符型),`ret`(整型)。
    unsigned long tmp;
    unsigned char byte;
    int ret = 0;

    // 32. 使用`switch`语句根据`i2c`结构中的`state`成员来处理不同的I2C状态。
    switch (i2c->state)
    {
        // 33-35. 如果状态是`STATE_IDLE`(空闲状态),直接跳到函数末尾结束。
        case STATE_IDLE:
            goto out;
            break;

        // 37-39. 如果状态是`STATE_STOP`(停止状态),禁用I2C中断,然后跳到末尾。
        case STATE_STOP:
            s3c24xx_i2c_disable_irq(i2c);
            goto out_ack;
            break;

        // 40-42. 如果状态是`STATE_START`(开始状态),检查是否需要启动新的消息。
        // 如果收到的最后一个位是开始位,并且没有收到ACK,则发送停止条件。
        case STATE_START:
            if (cstat & S3C2410_IICSTAT_LASTBIT &
                i2c->flags & I2C_M_RD)
            {
                // 没有收到ACK,发送远程I/O错误并停止。
                s3c24xx_i2c_stop(i2c, -EREMOTEIO);
                goto out_ack;
            }

            // 48-53. 根据消息的读取/写入标志设置状态为读或写。
            if (i2c->msg->flags & I2C_M_RD)
                i2c->state = STATE_READ;
            else
                i2c->state = STATE_WRITE;

            // 54-56. 如果是最后一条消息,发送停止条件。
            if (is_lastmsg(i2c))
                s3c24xx_i2c_stop(i2c, 0);
            break;

        // 59-85. 处理读和写状态,包括发送数据、接收数据、处理ACK等。
        case STATE_WRITE:
            // 64-66. 发送当前消息缓冲区的第一个字节。
            byte = i2c->msg->buf[i2c->msg_ptr++];
            writeb(byte, i2c->regs + S3C2410_IICDS);

            // 68-85. 如果是当前消息的最后,检查是否需要发送停止条件或继续。
            if (is_lastmsg(i2c))
            {
                // 处理停止条件或继续到下一条消息的逻辑。
            }
            break;

        case STATE_READ:
            // 90-123. 处理读取一个字节的情况,包括检查ACK、读取数据、处理消息结束等。
            if (/* 条件 */)
            {
                // 处理读取的逻辑。
            }
            break;

        // 其他状态和默认情况的处理...
    }

    // 125-128. 在退出前,清除中断挂起位并写回控制寄存器。
    tmp = readl(i2c->regs + S3C2410_IICCON);
    tmp &= ~S3C2410_IICCON_IROPEND;
    writel(tmp, i2c->regs + S3C2410_IICCON);

    // 129. 返回函数的返回值。
out:
    return ret;

    // 其他标签用于不同退出点...
out_ack:
    // 处理ACK的退出逻辑。
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值