Skip to content

Commit

Permalink
samd: Avoid under-/overflow in I2C and SPI baudrate calculations.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
robert-hh authored and dpgeorge committed Dec 14, 2022
1 parent 43fc133 commit fcd1788
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 3 deletions.
11 changes: 9 additions & 2 deletions ports/samd/machine_i2c.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 7 additions & 1 deletion ports/samd/machine_spi.c
Expand Up @@ -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
Expand Down

0 comments on commit fcd1788

Please sign in to comment.