stm32: add support for i2c read
Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
2d4b520260
commit
72b3ab8b29
|
@ -10,6 +10,7 @@
|
|||
#include "gpio.h" // i2c_setup
|
||||
#include "internal.h" // GPIO
|
||||
#include "sched.h" // sched_shutdown
|
||||
#include "board/irq.h" //irq_disable
|
||||
|
||||
struct i2c_info {
|
||||
I2C_TypeDef *i2c;
|
||||
|
@ -81,13 +82,20 @@ i2c_wait(I2C_TypeDef *i2c, uint32_t set, uint32_t clear, uint32_t timeout)
|
|||
}
|
||||
|
||||
static void
|
||||
i2c_start(I2C_TypeDef *i2c, uint8_t addr, uint32_t timeout)
|
||||
i2c_start(I2C_TypeDef *i2c, uint8_t addr, uint8_t xfer_len,
|
||||
uint32_t timeout)
|
||||
{
|
||||
i2c->CR1 = I2C_CR1_START | I2C_CR1_PE;
|
||||
i2c_wait(i2c, I2C_SR1_SB, 0, timeout);
|
||||
i2c->DR = addr;
|
||||
if (addr & 0x01)
|
||||
i2c->CR1 |= I2C_CR1_ACK;
|
||||
i2c_wait(i2c, I2C_SR1_ADDR, 0, timeout);
|
||||
irqstatus_t flag = irq_save();
|
||||
uint32_t sr2 = i2c->SR2;
|
||||
if (addr & 0x01 && xfer_len == 1)
|
||||
i2c->CR1 = I2C_CR1_STOP | I2C_CR1_PE;
|
||||
irq_restore(flag);
|
||||
if (!(sr2 & I2C_SR2_MSL))
|
||||
shutdown("Failed to send i2c addr");
|
||||
}
|
||||
|
@ -99,6 +107,18 @@ i2c_send_byte(I2C_TypeDef *i2c, uint8_t b, uint32_t timeout)
|
|||
i2c_wait(i2c, I2C_SR1_TXE, 0, timeout);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
i2c_read_byte(I2C_TypeDef *i2c, uint32_t timeout, uint8_t remaining)
|
||||
{
|
||||
i2c_wait(i2c, I2C_SR1_RXNE, 0, timeout);
|
||||
irqstatus_t flag = irq_save();
|
||||
uint8_t b = i2c->DR;
|
||||
if (remaining == 1)
|
||||
i2c->CR1 = I2C_CR1_STOP | I2C_CR1_PE;
|
||||
irq_restore(flag);
|
||||
return b;
|
||||
}
|
||||
|
||||
static void
|
||||
i2c_stop(I2C_TypeDef *i2c, uint32_t timeout)
|
||||
{
|
||||
|
@ -112,7 +132,7 @@ i2c_write(struct i2c_config config, uint8_t write_len, uint8_t *write)
|
|||
I2C_TypeDef *i2c = config.i2c;
|
||||
uint32_t timeout = timer_read_time() + timer_from_us(5000);
|
||||
|
||||
i2c_start(i2c, config.addr, timeout);
|
||||
i2c_start(i2c, config.addr, write_len, timeout);
|
||||
while (write_len--)
|
||||
i2c_send_byte(i2c, *write++, timeout);
|
||||
i2c_stop(i2c, timeout);
|
||||
|
@ -122,5 +142,21 @@ void
|
|||
i2c_read(struct i2c_config config, uint8_t reg_len, uint8_t *reg
|
||||
, uint8_t read_len, uint8_t *read)
|
||||
{
|
||||
shutdown("i2c_read not supported on stm32");
|
||||
I2C_TypeDef *i2c = config.i2c;
|
||||
uint32_t timeout = timer_read_time() + timer_from_us(5000);
|
||||
uint8_t addr = config.addr | 0x01;
|
||||
|
||||
if (reg_len) {
|
||||
// write the register
|
||||
i2c_start(i2c, config.addr, reg_len, timeout);
|
||||
while(reg_len--)
|
||||
i2c_send_byte(i2c, *reg++, timeout);
|
||||
}
|
||||
// start/re-start and read data
|
||||
i2c_start(i2c, addr, read_len, timeout);
|
||||
while(read_len--) {
|
||||
*read = i2c_read_byte(i2c, timeout, read_len);
|
||||
read++;
|
||||
}
|
||||
i2c_wait(i2c, 0, I2C_SR1_RXNE, timeout);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue