bug at WireKinetis.cpp
fusa4 opened this issue · 0 comments
fusa4 commented
Hi Paul,
I thinks there's a bug at WireKinetis.cpp.
When there's more than one slave, the slave rise the receiving interrupt when the address is not it own address. So it can lock the bus causing timeout at master.
I suggest following patch, changing the interrupt to check if the slave is the address targeted.
You can reproduce the bug by sending data to another address than the slave one.
Regards,
Jesus.
__diff -u Wire-master-orig/WireKinetis.cpp Wire-master-update/WireKinetis.cpp
--- Wire-master-orig/WireKinetis.cpp 2021-11-14 12:32:30.000000000 +0100
+++ Wire-master-update/WireKinetis.cpp 2022-01-25 16:05:01.146916363 +0100
@@ -366,10 +366,37 @@
} else {
// Begin Slave Receive
//serial_print("R");
+
+
+// We are allready receiving 1. It must be a reSTART.
+ if (receiving && user_onReceive != NULL) {
+ rxBufferIndex = 0;
+ user_onReceive(rxBufferLength);
+ }
+
receiving = 1;
rxBufferLength = 0;
port().C1 = I2C_C1_IICEN | I2C_C1_IICIE;
data = port().D;
+
+// Activate onterrupt ONLY IF I AM THE TARGET
+ #ifdef WIRE_HAS_STOP_INTERRUPT
+ port().FLT |= I2C_FLT_STOPIE;
+ #else
+ irqcount = 0;
+ #if defined(WIRE_IMPLEMENT_WIRE) && !defined(WIRE_IMPLEMENT_WIRE1)
+ attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr0, RISING);
+ #elif !defined(WIRE_IMPLEMENT_WIRE) && defined(WIRE_IMPLEMENT_WIRE1)
+ attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr1, RISING);
+ #elif defined(WIRE_IMPLEMENT_WIRE) && defined(WIRE_IMPLEMENT_WIRE1)
+ if (this == &Wire) {
+ attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr0, RISING);
+ } else if (this == &Wire1) {
+ attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr1, RISING);
+ }
+ #endif
+ #endif // WIRE_HAS_STOP_INTERRUPT
+
}
port().S = I2C_S_IICIF;
return;
@@ -382,6 +409,9 @@
rxBufferIndex = 0;
user_onReceive(rxBufferLength);
}
+
+// Data received. Disable flag till new call as target
+ receiving=0;
}
#endif
c1 = port().C1;
@@ -405,27 +435,14 @@
}
} else {
// Continue Slave Receive
- irqcount = 0;
- #ifdef WIRE_HAS_STOP_INTERRUPT
- port().FLT |= I2C_FLT_STOPIE;
- #else
- #if defined(WIRE_IMPLEMENT_WIRE) && !defined(WIRE_IMPLEMENT_WIRE1)
- attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr0, RISING);
- #elif !defined(WIRE_IMPLEMENT_WIRE) && defined(WIRE_IMPLEMENT_WIRE1)
- attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr1, RISING);
- #elif defined(WIRE_IMPLEMENT_WIRE) && defined(WIRE_IMPLEMENT_WIRE1)
- if (this == &Wire) {
- attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr0, RISING);
- } else if (this == &Wire1) {
- attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr1, RISING);
- }
- #endif
- #endif // WIRE_HAS_STOP_INTERRUPT
+
//digitalWriteFast(4, HIGH);
- data = port().D;
+ if (receiving) {
+ data = port().D;
//serial_phex(data);
- if (rxBufferLength < BUFFER_LENGTH && receiving) {
- rxBuffer[rxBufferLength++] = data;
+ if (rxBufferLength < BUFFER_LENGTH ) {
+ rxBuffer[rxBufferLength++] = data;
+ }
}
//digitalWriteFast(4, LOW);
}