stm32/i2cslave: Add functions to read/write I2C data.
Instead of requiring the callback to consume/provide the data. This allows the data to be consumed/provided later on, which will stretch the I2C clock until that occurs. Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
parent
a4ca42f094
commit
17d0449ac8
3 changed files with 38 additions and 12 deletions
|
|
@ -45,10 +45,12 @@ void i2c_slave_irq_handler(i2c_slave_t *i2c) {
|
|||
i2c_slave_process_addr_match(i2c, (sr2 >> I2C_SR2_TRA_Pos) & 1);
|
||||
}
|
||||
if (sr1 & I2C_SR1_TXE) {
|
||||
i2c->DR = i2c_slave_process_tx_byte(i2c);
|
||||
// This callback must call i2c_slave_write_byte.
|
||||
i2c_slave_process_tx_byte(i2c);
|
||||
}
|
||||
if (sr1 & I2C_SR1_RXNE) {
|
||||
i2c_slave_process_rx_byte(i2c, i2c->DR);
|
||||
// This callback must call i2c_slave_read_byte.
|
||||
i2c_slave_process_rx_byte(i2c);
|
||||
}
|
||||
if (sr1 & I2C_SR1_STOPF) {
|
||||
// STOPF only set at end of RX mode (in TX mode AF is set on NACK)
|
||||
|
|
@ -80,10 +82,12 @@ void i2c_slave_irq_handler(i2c_slave_t *i2c) {
|
|||
i2c_slave_process_addr_match(i2c, (i2c->ISR >> I2C_ISR_DIR_Pos) & 1);
|
||||
}
|
||||
if (isr & I2C_ISR_TXIS) {
|
||||
i2c->TXDR = i2c_slave_process_tx_byte(i2c);
|
||||
// This callback must call i2c_slave_write_byte.
|
||||
i2c_slave_process_tx_byte(i2c);
|
||||
}
|
||||
if (isr & I2C_ISR_RXNE) {
|
||||
i2c_slave_process_rx_byte(i2c, i2c->RXDR);
|
||||
// This callback must call i2c_slave_read_byte.
|
||||
i2c_slave_process_rx_byte(i2c);
|
||||
}
|
||||
if (isr & I2C_ISR_STOPF) {
|
||||
// STOPF only set for STOP condition, not a repeated START
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include STM32_HAL_H
|
||||
|
||||
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32WB)
|
||||
|
||||
#if !defined(I2C2_BASE)
|
||||
// This MCU doesn't have I2C2_BASE, define it so that the i2c_idx calculation works.
|
||||
#define I2C2_BASE (I2C1_BASE + ((I2C3_BASE - I2C1_BASE) / 2))
|
||||
|
|
@ -78,13 +80,31 @@ static inline void i2c_slave_shutdown(i2c_slave_t *i2c, int irqn) {
|
|||
NVIC_DisableIRQ(irqn);
|
||||
}
|
||||
|
||||
static inline void i2c_slave_write_byte(i2c_slave_t *i2c, uint8_t value) {
|
||||
#if defined(STM32F4)
|
||||
i2c->DR = value;
|
||||
#else
|
||||
i2c->TXDR = value;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint8_t i2c_slave_read_byte(i2c_slave_t *i2c) {
|
||||
#if defined(STM32F4)
|
||||
return i2c->DR;
|
||||
#else
|
||||
return i2c->RXDR;
|
||||
#endif
|
||||
}
|
||||
|
||||
void i2c_slave_irq_handler(i2c_slave_t *i2c);
|
||||
|
||||
// These should be provided externally
|
||||
int i2c_slave_process_addr_match(i2c_slave_t *i2c, int rw);
|
||||
int i2c_slave_process_rx_byte(i2c_slave_t *i2c, uint8_t val);
|
||||
int i2c_slave_process_rx_byte(i2c_slave_t *i2c);
|
||||
void i2c_slave_process_rx_end(i2c_slave_t *i2c);
|
||||
uint8_t i2c_slave_process_tx_byte(i2c_slave_t *i2c);
|
||||
void i2c_slave_process_tx_byte(i2c_slave_t *i2c);
|
||||
void i2c_slave_process_tx_end(i2c_slave_t *i2c);
|
||||
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_INCLUDED_STM32_I2CSLAVE_H
|
||||
|
|
|
|||
|
|
@ -805,9 +805,9 @@ int i2c_slave_process_addr_match(i2c_slave_t *i2c, int rw) {
|
|||
return 0; // ACK
|
||||
}
|
||||
|
||||
int i2c_slave_process_rx_byte(i2c_slave_t *i2c, uint8_t val) {
|
||||
int i2c_slave_process_rx_byte(i2c_slave_t *i2c) {
|
||||
if (i2c_obj.cmd_buf_pos < sizeof(i2c_obj.cmd_buf)) {
|
||||
i2c_obj.cmd_buf[i2c_obj.cmd_buf_pos++] = val;
|
||||
i2c_obj.cmd_buf[i2c_obj.cmd_buf_pos++] = i2c_slave_read_byte(i2c);
|
||||
}
|
||||
return 0; // ACK
|
||||
}
|
||||
|
|
@ -909,15 +909,17 @@ void i2c_slave_process_rx_end(i2c_slave_t *i2c) {
|
|||
i2c_obj.cmd_arg_sent = false;
|
||||
}
|
||||
|
||||
uint8_t i2c_slave_process_tx_byte(i2c_slave_t *i2c) {
|
||||
void i2c_slave_process_tx_byte(i2c_slave_t *i2c) {
|
||||
uint8_t value;
|
||||
if (i2c_obj.cmd_send_arg) {
|
||||
i2c_obj.cmd_arg_sent = true;
|
||||
return i2c_obj.cmd_arg;
|
||||
value = i2c_obj.cmd_arg;
|
||||
} else if (i2c_obj.cmd_buf_pos < sizeof(i2c_obj.cmd_buf)) {
|
||||
return i2c_obj.cmd_buf[i2c_obj.cmd_buf_pos++];
|
||||
value = i2c_obj.cmd_buf[i2c_obj.cmd_buf_pos++];
|
||||
} else {
|
||||
return 0;
|
||||
value = 0;
|
||||
}
|
||||
i2c_slave_write_byte(i2c, value);
|
||||
}
|
||||
|
||||
void i2c_slave_process_tx_end(i2c_slave_t *i2c) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue