소스 검색

Don't get stuck in requestFrom if bus busy or long clock stretch

main
PaulStoffregen 8 년 전
부모
커밋
c084466c3a
2개의 변경된 파일49개의 추가작업 그리고 8개의 파일을 삭제
  1. +49
    -4
      WireKinetis.cpp
  2. +0
    -4
      WireKinetis.h

+ 49
- 4
WireKinetis.cpp 파일 보기

{ {
uint8_t tmp __attribute__((unused)); uint8_t tmp __attribute__((unused));
uint8_t status, count=0; uint8_t status, count=0;
uint32_t wait_begin;


rxBufferIndex = 0; rxBufferIndex = 0;
rxBufferLength = 0; rxBufferLength = 0;
port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_RSTA | I2C_C1_TX; port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_RSTA | I2C_C1_TX;
} else { } else {
// we are not currently the bus master, so wait for bus ready // we are not currently the bus master, so wait for bus ready
while (i2c_status() & I2C_S_BUSY) ;
wait_begin = millis();
while (i2c_status() & I2C_S_BUSY) {
if (millis() - wait_begin > 15) {
// bus stuck busy too long
port.C1 = 0;
port.C1 = I2C_C1_IICEN;
return 0; // timeout waiting for bus
}
}
// become the bus master in transmit mode (send start) // become the bus master in transmit mode (send start)
slave_mode = 0; slave_mode = 0;
port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX;
} }

// wait until start condition establishes control of the bus
wait_begin = millis();
while (1) {
status = i2c_status();
if ((status & I2C_S_BUSY)) break;
if (millis() - wait_begin > 4) {
port.C1 = 0;
port.C1 = I2C_C1_IICEN;
return 0; // error generating start condition
}
}
// send the address // send the address
port.D = (address << 1) | 1; port.D = (address << 1) | 1;
i2c_wait();
wait_begin = millis();
while (!(port.S & I2C_S_IICIF)) {
if (millis() - wait_begin > 5) {
port.C1 = 0;
port.C1 = I2C_C1_IICEN;
return 0; // clock stretch too long (during address)
}
}
port.S = I2C_S_IICIF;
status = i2c_status(); status = i2c_status();
if ((status & I2C_S_RXAK) || (status & I2C_S_ARBL)) { if ((status & I2C_S_RXAK) || (status & I2C_S_ARBL)) {
// the slave device did not acknowledge // the slave device did not acknowledge
} }
tmp = port.D; // initiate the first receive tmp = port.D; // initiate the first receive
while (length > 1) { while (length > 1) {
i2c_wait();
wait_begin = millis();
while (!(port.S & I2C_S_IICIF)) {
if (millis() - wait_begin > 5) {
port.C1 = 0;
port.C1 = I2C_C1_IICEN;
return count; // clock stretch too long (during data)
}
}
port.S = I2C_S_IICIF;
length--; length--;
if (length == 1) port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TXAK; if (length == 1) port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TXAK;
if (count < BUFFER_LENGTH) { if (count < BUFFER_LENGTH) {
tmp = port.D; tmp = port.D;
} }
} }
i2c_wait();
wait_begin = millis();
while (!(port.S & I2C_S_IICIF)) {
if (millis() - wait_begin > 5) {
port.C1 = 0;
port.C1 = I2C_C1_IICEN;
return count; // clock stretch too long (during data)
}
}
port.S = I2C_S_IICIF;
port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; port.C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX;
if (count < BUFFER_LENGTH) { if (count < BUFFER_LENGTH) {
rxBuffer[count++] = port.D; rxBuffer[count++] = port.D;

+ 0
- 4
WireKinetis.h 파일 보기

uint8_t i2c_status(void) { uint8_t i2c_status(void) {
return port.S; return port.S;
} }
void i2c_wait(void) {
while (!(port.S & I2C_S_IICIF)) ; // wait (TODO: timeout)
port.S = I2C_S_IICIF;
}
void isr(void); void isr(void);
KINETIS_I2C_t &port; KINETIS_I2C_t &port;
const I2C_Hardware_t &hardware; const I2C_Hardware_t &hardware;

Loading…
취소
저장