I2C driver cleanup (#21273)
* remove i2c_start and i2c_stop from i2c drivers * remove static i2c_address variable from chibios i2c driver
This commit is contained in:
parent
2b0965944d
commit
e9bd7d7ad3
49 changed files with 280 additions and 603 deletions
|
@ -24,6 +24,7 @@
|
|||
#include "timer.h"
|
||||
#include "wait.h"
|
||||
#include "util.h"
|
||||
#include "progmem.h"
|
||||
|
||||
#ifndef F_SCL
|
||||
# define F_SCL 400000UL // SCL frequency
|
||||
|
@ -38,7 +39,7 @@
|
|||
|
||||
#define TWBR_val (((F_CPU / F_SCL) - 16) / 2)
|
||||
|
||||
void i2c_init(void) {
|
||||
__attribute__((weak)) void i2c_init(void) {
|
||||
TWSR = 0; /* no prescaler */
|
||||
TWBR = (uint8_t)TWBR_val;
|
||||
|
||||
|
@ -94,7 +95,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {
|
|||
return I2C_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
|
||||
__attribute__((always_inline)) static inline i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
|
||||
// Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled.
|
||||
uint16_t timeout_timer = timer_read();
|
||||
uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries
|
||||
|
@ -105,6 +106,11 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
|
|||
return status;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void i2c_stop(void) {
|
||||
// transmit STOP condition
|
||||
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
|
||||
}
|
||||
|
||||
i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
|
||||
// load data into data register
|
||||
TWDR = data;
|
||||
|
@ -167,6 +173,18 @@ i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length,
|
|||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_status_t status = i2c_start(address | I2C_ACTION_WRITE, timeout);
|
||||
|
||||
for (uint16_t i = 0; i < length && status >= 0; i++) {
|
||||
status = i2c_write(pgm_read_byte((const char*)data++), timeout);
|
||||
}
|
||||
|
||||
i2c_stop();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_status_t status = i2c_start(address | I2C_ACTION_READ, timeout);
|
||||
|
||||
|
@ -293,7 +311,8 @@ error:
|
|||
return (status < 0) ? status : I2C_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void i2c_stop(void) {
|
||||
// transmit STOP condition
|
||||
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
|
||||
}
|
||||
__attribute__((weak)) i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
|
||||
i2c_status_t status = i2c_start(address, timeout);
|
||||
i2c_stop();
|
||||
return status;
|
||||
}
|
|
@ -41,14 +41,11 @@ typedef int16_t i2c_status_t;
|
|||
#define I2C_TIMEOUT_INFINITE (0xFFFF)
|
||||
|
||||
void i2c_init(void);
|
||||
i2c_status_t i2c_start(uint8_t address, uint16_t timeout);
|
||||
i2c_status_t i2c_write(uint8_t data, uint16_t timeout);
|
||||
int16_t i2c_read_ack(uint16_t timeout);
|
||||
int16_t i2c_read_nack(uint16_t timeout);
|
||||
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
void i2c_stop(void);
|
||||
i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* Copyright 2018 Jack Humbert
|
||||
* Copyright 2018 Yiancar
|
||||
* Copyright 2023 customMK
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -90,8 +91,6 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
static uint8_t i2c_address;
|
||||
|
||||
static const I2CConfig i2cconfig = {
|
||||
#if defined(USE_I2CV1_CONTRIB)
|
||||
I2C1_CLOCK_SPEED,
|
||||
|
@ -125,7 +124,7 @@ static i2c_status_t i2c_epilogue(const msg_t status) {
|
|||
// 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();
|
||||
i2cStop(&I2C_DRIVER);
|
||||
|
||||
return status == MSG_TIMEOUT ? I2C_STATUS_TIMEOUT : I2C_STATUS_ERROR;
|
||||
}
|
||||
|
@ -150,28 +149,19 @@ __attribute__((weak)) void i2c_init(void) {
|
|||
}
|
||||
}
|
||||
|
||||
i2c_status_t i2c_start(uint8_t address) {
|
||||
i2c_address = address;
|
||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||
return I2C_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_address = address;
|
||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, TIME_MS2I(timeout));
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (address >> 1), data, length, 0, 0, TIME_MS2I(timeout));
|
||||
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));
|
||||
msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (address >> 1), data, length, TIME_MS2I(timeout));
|
||||
return i2c_epilogue(status);
|
||||
}
|
||||
|
||||
i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_address = devaddr;
|
||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||
|
||||
uint8_t complete_packet[length + 1];
|
||||
|
@ -180,12 +170,11 @@ i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t*
|
|||
}
|
||||
complete_packet[0] = regaddr;
|
||||
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout));
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout));
|
||||
return i2c_epilogue(status);
|
||||
}
|
||||
|
||||
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_address = devaddr;
|
||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||
|
||||
uint8_t complete_packet[length + 2];
|
||||
|
@ -195,25 +184,27 @@ i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8
|
|||
complete_packet[0] = regaddr >> 8;
|
||||
complete_packet[1] = regaddr & 0xFF;
|
||||
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout));
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout));
|
||||
return i2c_epilogue(status);
|
||||
}
|
||||
|
||||
i2c_status_t i2c_read_register(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));
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), ®addr, 1, data, length, TIME_MS2I(timeout));
|
||||
return i2c_epilogue(status);
|
||||
}
|
||||
|
||||
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_address = devaddr;
|
||||
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));
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), register_packet, 2, data, length, TIME_MS2I(timeout));
|
||||
return i2c_epilogue(status);
|
||||
}
|
||||
|
||||
void i2c_stop(void) {
|
||||
i2cStop(&I2C_DRIVER);
|
||||
}
|
||||
__attribute__((weak)) i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
|
||||
// ChibiOS does not provide low level enough control to check for an ack.
|
||||
// Best effort instead tries reading register 0 which will either succeed or timeout.
|
||||
// This approach may produce false negative results for I2C devices that do not respond to a register 0 read request.
|
||||
uint8_t data = 0;
|
||||
return i2c_readReg(address, 0, &data, sizeof(data), timeout);
|
||||
}
|
|
@ -40,11 +40,10 @@ typedef int16_t i2c_status_t;
|
|||
#define I2C_STATUS_TIMEOUT (-2)
|
||||
|
||||
void i2c_init(void);
|
||||
i2c_status_t i2c_start(uint8_t address);
|
||||
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
void i2c_stop(void);
|
||||
i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue