看下这种写法:
void I2C1_IRQHandler(void)
{
if (i2c_ctrl[1].enable == 0)
goto error;
if (I2C1->TOCTL & I2C_TOCTL_TOIF_Msk)
{
goto error;
}
else if (I2C1->CTL & I2C_CON_I2C_STS)
{
uint32_t status = I2C1->STATUS;
if (i2c_ctrl[1].rw) // read phase
{
if ((status == 0x08) || (status == 0x10))
{
I2C1->DAT = (i2c_ctrl[1].chip_addr << 1) + 1;
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS);
}
else if (status == 0x40)
{
if (i2c_ctrl[1].read_len > 1)
{
// host reply ack
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_ACK);
}
else if (i2c_ctrl[1].read_len == 1)
{
// host reply nack
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS);
}
else
{
goto error;
}
}
else if (status == 0x50)
{
if (i2c_ctrl[1].read_prt < i2c_ctrl[1].read_len)
i2c_ctrl[1].read[i2c_ctrl[1].read_prt++] = I2C1->DAT;
if (i2c_ctrl[1].read_prt < i2c_ctrl[1].read_len - 1)
{
// host reply ack
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_ACK);
}
else
{
// host reply nack
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS);
}
}
else if (status == 0x58)
{
if (i2c_ctrl[1].read_prt < i2c_ctrl[1].read_len)
i2c_ctrl[1].read[i2c_ctrl[1].read_prt++] = I2C1->DAT;
i2c_ctrl[1].read = NULL;
if (i2c_ctrl[1].write != NULL)
{
i2c_ctrl[1].rw = 0;
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_START);
}
else
{
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_STOP);
I2C1->TOCTL = 0;
if (m45x_i2c_callback[1] != NULL &&
i2c_ctrl[1].callback_enable)
{
i2c_ctrl[1].enable = 0;
i2c_ctrl[1].callback_enable = 0;
m45x_i2c_callback[1](m45x_i2c_param[1],
i2c_ctrl[1].read_prt,
i2c_ctrl[1].write_prt);
}
}
}
else
{
goto error;
}
}
else // write phase
{
if ((status == 0x08) || (status == 0x10)) // start send finish
{
I2C1->DAT = i2c_ctrl[1].chip_addr << 1;
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS);
}
else if ((status == 0x18) || (status == 0x28)) // addr/data send finish and ACK received
{
if (i2c_ctrl[1].write_prt < i2c_ctrl[1].write_len)
{
I2C1->DAT = i2c_ctrl[1].write[i2c_ctrl[1].write_prt++];
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS);
}
else
{
i2c_ctrl[1].write = NULL;
if (i2c_ctrl[1].read != NULL)
{
i2c_ctrl[1].rw = 1;
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_START);
}
else
{
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_STOP);
I2C1->TOCTL = 0;
if (m45x_i2c_callback[1] != NULL &&
i2c_ctrl[1].callback_enable)
{
i2c_ctrl[1].enable = 0;
i2c_ctrl[1].callback_enable = 0;
m45x_i2c_callback[1](m45x_i2c_param[1],
i2c_ctrl[1].read_prt,
i2c_ctrl[1].write_prt);
}
}
}
}
else
{
goto error;
}
}
}
return;
error:
I2C1->TOCTL = I2C_TOCTL_TOIF_Msk;
I2C_SET_CONTROL_REG(I2C1, I2C_CON_I2C_STS | I2C_CON_STOP);
i2c_ctrl[1].enable = 0;
if (m45x_i2c_callback[1] != NULL && i2c_ctrl[1].callback_enable)
{
i2c_ctrl[1].callback_enable = 0;
m45x_i2c_callback[1](m45x_i2c_param[1], -1, -1);
}
}
类似linux的驱动,通过msg将单次需传输的信息全部交友驱动层,驱动通过中断不断访问IIC,直到操作完成,回调高层。
这是最高效的。 |