diff options
Diffstat (limited to 'platforms/chibios/drivers/i2c_master.c')
| -rw-r--r-- | platforms/chibios/drivers/i2c_master.c | 39 | 
1 files changed, 24 insertions, 15 deletions
diff --git a/platforms/chibios/drivers/i2c_master.c b/platforms/chibios/drivers/i2c_master.c index 21e064b1dc..4c7a5daa17 100644 --- a/platforms/chibios/drivers/i2c_master.c +++ b/platforms/chibios/drivers/i2c_master.c @@ -107,16 +107,25 @@ static const I2CConfig i2cconfig = {  #endif  }; -static i2c_status_t chibios_to_qmk(const msg_t* status) { -    switch (*status) { -        case I2C_NO_ERROR: -            return I2C_STATUS_SUCCESS; -        case I2C_TIMEOUT: -            return I2C_STATUS_TIMEOUT; -        // I2C_BUS_ERROR, I2C_ARBITRATION_LOST, I2C_ACK_FAILURE, I2C_OVERRUN, I2C_PEC_ERROR, I2C_SMB_ALERT -        default: -            return I2C_STATUS_ERROR; +/** + * @brief Handles any I2C error condition by stopping the I2C peripheral and + * aborting any ongoing transactions. Furthermore ChibiOS status codes are + * converted into QMK codes. + * + * @param status ChibiOS specific I2C status code + * @return i2c_status_t QMK specific I2C status code + */ +static i2c_status_t i2c_epilogue(const msg_t status) { +    if (status == MSG_OK) { +        return I2C_STATUS_SUCCESS;      } + +    // From ChibiOS HAL: "After a timeout the driver must be stopped and +    // restarted because the bus is in an uncertain state." We also issue that +    // hard stop in case of any error. +    i2c_stop(); + +    return status == MSG_TIMEOUT ? I2C_STATUS_TIMEOUT : I2C_STATUS_ERROR;  }  __attribute__((weak)) void i2c_init(void) { @@ -149,14 +158,14 @@ i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length,      i2c_address = address;      i2cStart(&I2C_DRIVER, &i2cconfig);      msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, TIME_MS2I(timeout)); -    return chibios_to_qmk(&status); +    return i2c_epilogue(status);  }  i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {      i2c_address = address;      i2cStart(&I2C_DRIVER, &i2cconfig);      msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, TIME_MS2I(timeout)); -    return chibios_to_qmk(&status); +    return i2c_epilogue(status);  }  i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { @@ -170,7 +179,7 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data,      complete_packet[0] = regaddr;      msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout)); -    return chibios_to_qmk(&status); +    return i2c_epilogue(status);  }  i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { @@ -185,14 +194,14 @@ i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* da      complete_packet[1] = regaddr & 0xFF;      msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout)); -    return chibios_to_qmk(&status); +    return i2c_epilogue(status);  }  i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {      i2c_address = devaddr;      i2cStart(&I2C_DRIVER, &i2cconfig);      msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), ®addr, 1, data, length, TIME_MS2I(timeout)); -    return chibios_to_qmk(&status); +    return i2c_epilogue(status);  }  i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { @@ -200,7 +209,7 @@ i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uin      i2cStart(&I2C_DRIVER, &i2cconfig);      uint8_t register_packet[2] = {regaddr >> 8, regaddr & 0xFF};      msg_t   status             = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), register_packet, 2, data, length, TIME_MS2I(timeout)); -    return chibios_to_qmk(&status); +    return i2c_epilogue(status);  }  void i2c_stop(void) {  | 
