samd: Avoid under-/overflow in I2C and SPI baudrate calculations.

Applies to both SPI and I2C.  The underflow caused high baudrate settings
resulting in the lowest possible baudrate.  The overflow resulted in
erratic baudrates, not just the lowest possible.
This commit is contained in:
robert-hh 2022-11-16 08:17:48 +01:00 committed by Damien George
parent 43fc133dbd
commit fcd1788937
2 changed files with 16 additions and 3 deletions

View File

@ -35,7 +35,7 @@
#include "clock_config.h"
#define DEFAULT_I2C_FREQ (400000)
#define RISETIME_NS (300)
#define RISETIME_NS (200)
#define I2C_TIMEOUT (100)
#define IS_BUS_BUSY (i2c->I2CM.STATUS.bit.BUSSTATE == 3)
@ -184,7 +184,14 @@ mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
// baud = peripheral_freq / (2 * baudrate) - 5 - (rise_time * peripheral_freq) / 2
// Just set the minimal configuration for standard and fast mode.
// Set Baud. Assume ~300ns rise time. Maybe set later by a keyword argument.
i2c->I2CM.BAUD.reg = get_peripheral_freq() / (2 * self->freq) - 5 - (get_peripheral_freq() / 1000000) * RISETIME_NS / 2000;
int32_t baud = get_peripheral_freq() / (2 * self->freq) - 5 - (get_peripheral_freq() / 1000000) * RISETIME_NS / 2000;
if (baud < 0) {
baud = 0;
}
if (baud > 255) {
baud = 255;
}
i2c->I2CM.BAUD.reg = baud;
// Enable interrupts
sercom_register_irq(self->id, &common_i2c_irq_handler);

View File

@ -208,7 +208,13 @@ STATIC void machine_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj
// SPI is driven by the clock of GCLK Generator 2, freq by get_peripheral_freq()
// baud = bus_freq / (2 * baudrate) - 1
uint32_t baud = get_peripheral_freq() / (2 * self->baudrate) - 1;
uint32_t baud = get_peripheral_freq() / (2 * self->baudrate);
if (baud > 0) { // Avoid underflow
baud -= 1;
}
if (baud > 255) { // Avoid overflow
baud = 255;
}
spi->SPI.BAUD.reg = baud; // Set Baud
// Enable RXC interrupt only if miso is defined