mirror of
https://github.com/andreili/klipper.git
synced 2025-08-23 19:34:06 +02:00
stm32: make i2c distinguish I2C NACKs
Signed-off-by: Timofey Titovets <nefelim4ag@gmail.com>
This commit is contained in:
parent
9323a5dfe2
commit
4e4a5c6336
@ -94,21 +94,21 @@ i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr)
|
|||||||
return (struct i2c_config){ .i2c=i2c, .addr=addr<<1 };
|
return (struct i2c_config){ .i2c=i2c, .addr=addr<<1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static int
|
||||||
i2c_wait(I2C_TypeDef *i2c, uint32_t set, uint32_t clear, uint32_t timeout)
|
i2c_wait(I2C_TypeDef *i2c, uint32_t set, uint32_t clear, uint32_t timeout)
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint32_t sr1 = i2c->SR1;
|
uint32_t sr1 = i2c->SR1;
|
||||||
if ((sr1 & set) == set && (sr1 & clear) == 0)
|
if ((sr1 & set) == set && (sr1 & clear) == 0)
|
||||||
return sr1;
|
return I2C_BUS_SUCCESS;
|
||||||
if (sr1 & I2C_SR1_AF)
|
if (sr1 & I2C_SR1_AF)
|
||||||
shutdown("I2C NACK error encountered");
|
return I2C_BUS_NACK;
|
||||||
if (!timer_is_before(timer_read_time(), timeout))
|
if (!timer_is_before(timer_read_time(), timeout))
|
||||||
shutdown("i2c timeout");
|
return I2C_BUS_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
i2c_start(I2C_TypeDef *i2c, uint8_t addr, uint8_t xfer_len,
|
i2c_start(I2C_TypeDef *i2c, uint8_t addr, uint8_t xfer_len,
|
||||||
uint32_t timeout)
|
uint32_t timeout)
|
||||||
{
|
{
|
||||||
@ -117,7 +117,7 @@ i2c_start(I2C_TypeDef *i2c, uint8_t addr, uint8_t xfer_len,
|
|||||||
i2c->DR = addr;
|
i2c->DR = addr;
|
||||||
if (addr & 0x01)
|
if (addr & 0x01)
|
||||||
i2c->CR1 |= I2C_CR1_ACK;
|
i2c->CR1 |= I2C_CR1_ACK;
|
||||||
i2c_wait(i2c, I2C_SR1_ADDR, 0, timeout);
|
int ret = i2c_wait(i2c, I2C_SR1_ADDR, 0, timeout);
|
||||||
irqstatus_t flag = irq_save();
|
irqstatus_t flag = irq_save();
|
||||||
uint32_t sr2 = i2c->SR2;
|
uint32_t sr2 = i2c->SR2;
|
||||||
if (addr & 0x01 && xfer_len == 1)
|
if (addr & 0x01 && xfer_len == 1)
|
||||||
@ -125,13 +125,14 @@ i2c_start(I2C_TypeDef *i2c, uint8_t addr, uint8_t xfer_len,
|
|||||||
irq_restore(flag);
|
irq_restore(flag);
|
||||||
if (!(sr2 & I2C_SR2_MSL))
|
if (!(sr2 & I2C_SR2_MSL))
|
||||||
shutdown("Failed to send i2c addr");
|
shutdown("Failed to send i2c addr");
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
i2c_send_byte(I2C_TypeDef *i2c, uint8_t b, uint32_t timeout)
|
i2c_send_byte(I2C_TypeDef *i2c, uint8_t b, uint32_t timeout)
|
||||||
{
|
{
|
||||||
i2c->DR = b;
|
i2c->DR = b;
|
||||||
i2c_wait(i2c, I2C_SR1_TXE, 0, timeout);
|
return i2c_wait(i2c, I2C_SR1_TXE, 0, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
@ -146,11 +147,11 @@ i2c_read_byte(I2C_TypeDef *i2c, uint32_t timeout, uint8_t remaining)
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
i2c_stop(I2C_TypeDef *i2c, uint32_t timeout)
|
i2c_stop(I2C_TypeDef *i2c, uint32_t timeout)
|
||||||
{
|
{
|
||||||
i2c->CR1 = I2C_CR1_STOP | I2C_CR1_PE;
|
i2c->CR1 = I2C_CR1_STOP | I2C_CR1_PE;
|
||||||
i2c_wait(i2c, 0, I2C_SR1_TXE, timeout);
|
return i2c_wait(i2c, 0, I2C_SR1_TXE, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -159,12 +160,16 @@ i2c_write(struct i2c_config config, uint8_t write_len, uint8_t *write)
|
|||||||
I2C_TypeDef *i2c = config.i2c;
|
I2C_TypeDef *i2c = config.i2c;
|
||||||
uint32_t timeout = timer_read_time() + timer_from_us(5000);
|
uint32_t timeout = timer_read_time() + timer_from_us(5000);
|
||||||
|
|
||||||
i2c_start(i2c, config.addr, write_len, timeout);
|
int ret = i2c_start(i2c, config.addr, write_len, timeout);
|
||||||
while (write_len--)
|
if (ret == I2C_BUS_NACK)
|
||||||
i2c_send_byte(i2c, *write++, timeout);
|
ret = I2C_BUS_START_NACK;
|
||||||
i2c_stop(i2c, timeout);
|
while (write_len-- && ret == I2C_BUS_SUCCESS)
|
||||||
|
ret = i2c_send_byte(i2c, *write++, timeout);
|
||||||
|
int timeout_err = i2c_stop(i2c, timeout);
|
||||||
|
|
||||||
return I2C_BUS_SUCCESS;
|
if (ret == I2C_BUS_SUCCESS && timeout_err != I2C_BUS_SUCCESS)
|
||||||
|
ret = timeout_err;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -174,20 +179,31 @@ i2c_read(struct i2c_config config, uint8_t reg_len, uint8_t *reg
|
|||||||
I2C_TypeDef *i2c = config.i2c;
|
I2C_TypeDef *i2c = config.i2c;
|
||||||
uint32_t timeout = timer_read_time() + timer_from_us(5000);
|
uint32_t timeout = timer_read_time() + timer_from_us(5000);
|
||||||
uint8_t addr = config.addr | 0x01;
|
uint8_t addr = config.addr | 0x01;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (reg_len) {
|
if (reg_len) {
|
||||||
// write the register
|
// write the register
|
||||||
i2c_start(i2c, config.addr, reg_len, timeout);
|
ret = i2c_start(i2c, config.addr, reg_len, timeout);
|
||||||
while(reg_len--)
|
if (ret == I2C_BUS_NACK)
|
||||||
i2c_send_byte(i2c, *reg++, timeout);
|
ret = I2C_BUS_START_NACK;
|
||||||
|
while(reg_len-- && ret == I2C_BUS_SUCCESS)
|
||||||
|
ret = i2c_send_byte(i2c, *reg++, timeout);
|
||||||
|
if (ret != I2C_BUS_SUCCESS)
|
||||||
|
goto abrt;
|
||||||
}
|
}
|
||||||
// start/re-start and read data
|
// start/re-start and read data
|
||||||
i2c_start(i2c, addr, read_len, timeout);
|
ret = i2c_start(i2c, addr, read_len, timeout);
|
||||||
|
if (ret == I2C_BUS_NACK)
|
||||||
|
ret = I2C_BUS_START_READ_NACK;
|
||||||
|
if (ret != I2C_BUS_SUCCESS)
|
||||||
|
goto abrt;
|
||||||
while(read_len--) {
|
while(read_len--) {
|
||||||
*read = i2c_read_byte(i2c, timeout, read_len);
|
*read = i2c_read_byte(i2c, timeout, read_len);
|
||||||
read++;
|
read++;
|
||||||
}
|
}
|
||||||
i2c_wait(i2c, 0, I2C_SR1_RXNE, timeout);
|
// covers read timeout
|
||||||
|
return i2c_wait(i2c, 0, I2C_SR1_RXNE, timeout);
|
||||||
return I2C_BUS_SUCCESS;
|
abrt:
|
||||||
|
i2c_stop(i2c, timeout);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user