Skip to content

Commit 17d0449

Browse files
committed
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 <[email protected]>
1 parent a4ca42f commit 17d0449

File tree

3 files changed

+38
-12
lines changed

3 files changed

+38
-12
lines changed

ports/stm32/i2cslave.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@ void i2c_slave_irq_handler(i2c_slave_t *i2c) {
4545
i2c_slave_process_addr_match(i2c, (sr2 >> I2C_SR2_TRA_Pos) & 1);
4646
}
4747
if (sr1 & I2C_SR1_TXE) {
48-
i2c->DR = i2c_slave_process_tx_byte(i2c);
48+
// This callback must call i2c_slave_write_byte.
49+
i2c_slave_process_tx_byte(i2c);
4950
}
5051
if (sr1 & I2C_SR1_RXNE) {
51-
i2c_slave_process_rx_byte(i2c, i2c->DR);
52+
// This callback must call i2c_slave_read_byte.
53+
i2c_slave_process_rx_byte(i2c);
5254
}
5355
if (sr1 & I2C_SR1_STOPF) {
5456
// 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) {
8082
i2c_slave_process_addr_match(i2c, (i2c->ISR >> I2C_ISR_DIR_Pos) & 1);
8183
}
8284
if (isr & I2C_ISR_TXIS) {
83-
i2c->TXDR = i2c_slave_process_tx_byte(i2c);
85+
// This callback must call i2c_slave_write_byte.
86+
i2c_slave_process_tx_byte(i2c);
8487
}
8588
if (isr & I2C_ISR_RXNE) {
86-
i2c_slave_process_rx_byte(i2c, i2c->RXDR);
89+
// This callback must call i2c_slave_read_byte.
90+
i2c_slave_process_rx_byte(i2c);
8791
}
8892
if (isr & I2C_ISR_STOPF) {
8993
// STOPF only set for STOP condition, not a repeated START

ports/stm32/i2cslave.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
#include STM32_HAL_H
3030

31+
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32WB)
32+
3133
#if !defined(I2C2_BASE)
3234
// This MCU doesn't have I2C2_BASE, define it so that the i2c_idx calculation works.
3335
#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) {
7880
NVIC_DisableIRQ(irqn);
7981
}
8082

83+
static inline void i2c_slave_write_byte(i2c_slave_t *i2c, uint8_t value) {
84+
#if defined(STM32F4)
85+
i2c->DR = value;
86+
#else
87+
i2c->TXDR = value;
88+
#endif
89+
}
90+
91+
static inline uint8_t i2c_slave_read_byte(i2c_slave_t *i2c) {
92+
#if defined(STM32F4)
93+
return i2c->DR;
94+
#else
95+
return i2c->RXDR;
96+
#endif
97+
}
98+
8199
void i2c_slave_irq_handler(i2c_slave_t *i2c);
82100

83101
// These should be provided externally
84102
int i2c_slave_process_addr_match(i2c_slave_t *i2c, int rw);
85-
int i2c_slave_process_rx_byte(i2c_slave_t *i2c, uint8_t val);
103+
int i2c_slave_process_rx_byte(i2c_slave_t *i2c);
86104
void i2c_slave_process_rx_end(i2c_slave_t *i2c);
87-
uint8_t i2c_slave_process_tx_byte(i2c_slave_t *i2c);
105+
void i2c_slave_process_tx_byte(i2c_slave_t *i2c);
88106
void i2c_slave_process_tx_end(i2c_slave_t *i2c);
89107

108+
#endif
109+
90110
#endif // MICROPY_INCLUDED_STM32_I2CSLAVE_H

ports/stm32/mboot/main.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -805,9 +805,9 @@ int i2c_slave_process_addr_match(i2c_slave_t *i2c, int rw) {
805805
return 0; // ACK
806806
}
807807

808-
int i2c_slave_process_rx_byte(i2c_slave_t *i2c, uint8_t val) {
808+
int i2c_slave_process_rx_byte(i2c_slave_t *i2c) {
809809
if (i2c_obj.cmd_buf_pos < sizeof(i2c_obj.cmd_buf)) {
810-
i2c_obj.cmd_buf[i2c_obj.cmd_buf_pos++] = val;
810+
i2c_obj.cmd_buf[i2c_obj.cmd_buf_pos++] = i2c_slave_read_byte(i2c);
811811
}
812812
return 0; // ACK
813813
}
@@ -909,15 +909,17 @@ void i2c_slave_process_rx_end(i2c_slave_t *i2c) {
909909
i2c_obj.cmd_arg_sent = false;
910910
}
911911

912-
uint8_t i2c_slave_process_tx_byte(i2c_slave_t *i2c) {
912+
void i2c_slave_process_tx_byte(i2c_slave_t *i2c) {
913+
uint8_t value;
913914
if (i2c_obj.cmd_send_arg) {
914915
i2c_obj.cmd_arg_sent = true;
915-
return i2c_obj.cmd_arg;
916+
value = i2c_obj.cmd_arg;
916917
} else if (i2c_obj.cmd_buf_pos < sizeof(i2c_obj.cmd_buf)) {
917-
return i2c_obj.cmd_buf[i2c_obj.cmd_buf_pos++];
918+
value = i2c_obj.cmd_buf[i2c_obj.cmd_buf_pos++];
918919
} else {
919-
return 0;
920+
value = 0;
920921
}
922+
i2c_slave_write_byte(i2c, value);
921923
}
922924

923925
void i2c_slave_process_tx_end(i2c_slave_t *i2c) {

0 commit comments

Comments
 (0)