summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrobert-hh <robert@hammelrath.com>2022-11-16 08:17:48 +0100
committerDamien George <damien@micropython.org>2022-12-14 12:41:42 +1100
commitfcd1788937c267da7eddea1925391b906a49e9e6 (patch)
tree76b6b76a720583e99e192c65e91dab4edc9cac6a
parent43fc133dbd976ece5c746d76b828260057060a6b (diff)
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.
-rw-r--r--ports/samd/machine_i2c.c11
-rw-r--r--ports/samd/machine_spi.c8
2 files changed, 16 insertions, 3 deletions
diff --git a/ports/samd/machine_i2c.c b/ports/samd/machine_i2c.c
index d943b6b2f..76d24674f 100644
--- a/ports/samd/machine_i2c.c
+++ b/ports/samd/machine_i2c.c
@@ -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);
diff --git a/ports/samd/machine_spi.c b/ports/samd/machine_spi.c
index 4ffc7095c..d2cdf2cd4 100644
--- a/ports/samd/machine_spi.c
+++ b/ports/samd/machine_spi.c
@@ -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