avr: Allow I2C bus speed to be set by Klipper (#6111)

Allow I2C bus speed to be set by appropriate Klipper commands.

Signed-off-by: Matthew Swabey <matthew@swabey.org>
This commit is contained in:
Dr. Matthew Swabey 2023-03-21 15:02:58 -04:00 committed by GitHub
parent e2d7c59812
commit 2466b7a2c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 28 deletions

View File

@ -4508,20 +4508,20 @@ SPI bus.
The following parameters are generally available for devices using an The following parameters are generally available for devices using an
I2C bus. I2C bus.
Note that Klipper's current micro-controller support for i2c is Note that Klipper's current micro-controller support for I2C is
generally not tolerant to line noise. Unexpected errors on the i2c generally not tolerant to line noise. Unexpected errors on the I2C
wires may result in Klipper raising a run-time error. Klipper's wires may result in Klipper raising a run-time error. Klipper's
support for error recovery varies between each micro-controller type. support for error recovery varies between each micro-controller type.
It is generally recommended to only use i2c devices that are on the It is generally recommended to only use I2C devices that are on the
same printed circuit board as the micro-controller. same printed circuit board as the micro-controller.
Most Klipper micro-controller implementations only support an Most Klipper micro-controller implementations only support an
`i2c_speed` of 100000. The Klipper "linux" micro-controller supports a `i2c_speed` of 100000 (*standard mode*, 100kbit/s). The Klipper "Linux"
400000 speed, but it must be micro-controller supports a 400000 speed (*fast mode*, 400kbit/s), but it must be
[set in the operating system](RPi_microcontroller.md#optional-enabling-i2c) [set in the operating system](RPi_microcontroller.md#optional-enabling-i2c)
and the `i2c_speed` parameter is otherwise ignored. The Klipper and the `i2c_speed` parameter is otherwise ignored. The Klipper
"rp2040" micro-controller supports a rate of 400000 via the "RP2040" micro-controller and ATmega AVR family support a rate of 400000
`i2c_speed` parameter. All other Klipper micro-controllers use a via the `i2c_speed` parameter. All other Klipper micro-controllers use a
100000 rate and ignore the `i2c_speed` parameter. 100000 rate and ignore the `i2c_speed` parameter.
``` ```
@ -4539,5 +4539,5 @@ and the `i2c_speed` parameter is otherwise ignored. The Klipper
# The I2C speed (in Hz) to use when communicating with the device. # The I2C speed (in Hz) to use when communicating with the device.
# The Klipper implementation on most micro-controllers is hard-coded # The Klipper implementation on most micro-controllers is hard-coded
# to 100000 and changing this value has no effect. The default is # to 100000 and changing this value has no effect. The default is
# 100000. # 100000. Linux, RP2040 and ATmega support 400000.
``` ```

View File

@ -27,31 +27,27 @@ static const uint8_t SCL = GPIO('D', 0), SDA = GPIO('D', 1);
DECL_CONSTANT_STR("BUS_PINS_twi", "PD0,PD1"); DECL_CONSTANT_STR("BUS_PINS_twi", "PD0,PD1");
#endif #endif
static void
i2c_init(void)
{
if (TWCR & (1<<TWEN))
// Already setup
return;
// Setup output pins and enable pullups
gpio_out_setup(SDA, 1);
gpio_out_setup(SCL, 1);
// Set 100Khz frequency
TWSR = 0;
TWBR = ((CONFIG_CLOCK_FREQ / 100000) - 16) / 2;
// Enable interface
TWCR = (1<<TWEN);
}
struct i2c_config struct i2c_config
i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr) i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr)
{ {
if (bus) if (bus)
shutdown("Unsupported i2c bus"); shutdown("Unsupported i2c bus");
i2c_init();
if (!(TWCR & (1<<TWEN))) {
// Setup output pins and enable pullups
gpio_out_setup(SDA, 1);
gpio_out_setup(SCL, 1);
// Set frequency avoiding pulling in integer divide
TWSR = 0;
if (rate >= 400000)
TWBR = ((CONFIG_CLOCK_FREQ / 400000) - 16) / 2;
else
TWBR = ((CONFIG_CLOCK_FREQ / 100000) - 16) / 2;
// Enable interface
TWCR = (1<<TWEN);
}
return (struct i2c_config){ .addr=addr<<1 }; return (struct i2c_config){ .addr=addr<<1 };
} }