diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index 4182c86513868..4ac1f340c6f6b 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -46,19 +46,21 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, uint32_t sda_pinmux = 0; uint32_t scl_pinmux = 0; for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { - Sercom* potential_sercom = sda->sercom[i].sercom; - if (potential_sercom == NULL || - potential_sercom->I2CM.CTRLA.bit.ENABLE != 0 || + sercom_index = sda->sercom[i].index; + if (sercom_index >= SERCOM_INST_NUM) { + continue; + } + Sercom* potential_sercom = sercom_insts[sercom_index]; + if (potential_sercom->I2CM.CTRLA.bit.ENABLE != 0 || sda->sercom[i].pad != 0) { continue; } sda_pinmux = PINMUX(sda->pin, (i == 0) ? MUX_C : MUX_D); for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { - if (potential_sercom == scl->sercom[j].sercom && + if (sercom_index == scl->sercom[j].index && scl->sercom[j].pad == 1) { scl_pinmux = PINMUX(scl->pin, (j == 0) ? MUX_C : MUX_D); sercom = potential_sercom; - sercom_index = scl->sercom[j].index; // 2 for SERCOM2, etc. break; } } @@ -77,7 +79,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, if (i2c_m_sync_init(&self->i2c_desc, sercom) != ERR_NONE) { mp_raise_OSError(MP_EIO); } - + gpio_set_pin_pull_mode(sda->pin, GPIO_PULL_OFF); gpio_set_pin_function(sda->pin, sda_pinmux); @@ -85,7 +87,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, gpio_set_pin_function(scl->pin, scl_pinmux); // clkrate is always 0. baud_rate is in kHz. - + // Frequency must be set before the I2C device is enabled. if (i2c_m_sync_set_baudrate(&self->i2c_desc, 0, frequency / 1000) != ERR_NONE) { mp_raise_ValueError("Unsupported baudrate"); @@ -113,7 +115,7 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { i2c_m_sync_disable(&self->i2c_desc); i2c_m_sync_deinit(&self->i2c_desc); - + reset_pin(self->sda_pin); reset_pin(self->scl_pin); self->sda_pin = NO_PIN; diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index eca73be78a460..a2bf30f054f5a 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -55,9 +55,12 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, uint8_t miso_pad = 0; uint8_t dopo = 255; for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { - Sercom* potential_sercom = clock->sercom[i].sercom; sercom_index = clock->sercom[i].index; // 2 for SERCOM2, etc. - if (potential_sercom == NULL || + if (sercom_index >= SERCOM_INST_NUM) { + continue; + } + Sercom* potential_sercom = sercom_insts[sercom_index]; + if ( #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102) (potential_sercom->SPI.CTRLA.bit.ENABLE != 0 && potential_sercom != status_apa102.spi_desc.dev.prvt && @@ -74,7 +77,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { if (!mosi_none) { - if(potential_sercom == mosi->sercom[j].sercom) { + if (sercom_index == mosi->sercom[j].index) { mosi_pinmux = PINMUX(mosi->pin, (j == 0) ? MUX_C : MUX_D); mosi_pad = mosi->sercom[j].pad; dopo = samd_peripherals_get_spi_dopo(clock_pad, mosi_pad); @@ -91,7 +94,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } if (!miso_none) { for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) { - if (potential_sercom == miso->sercom[k].sercom) { + if (sercom_index == miso->sercom[k].index) { miso_pinmux = PINMUX(miso->pin, (k == 0) ? MUX_C : MUX_D); miso_pad = miso->sercom[k].pad; sercom = potential_sercom; diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 292e01e60ebc3..4cb7db2033987 100644 --- a/ports/atmel-samd/common-hal/busio/UART.c +++ b/ports/atmel-samd/common-hal/busio/UART.c @@ -71,7 +71,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, if (!have_tx && !have_rx) { mp_raise_ValueError("tx and rx cannot both be None"); } - + self->baudrate = baudrate; self->character_bits = bits; self->timeout_ms = timeout; @@ -82,10 +82,12 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { Sercom* potential_sercom = NULL; if (have_tx) { - potential_sercom = tx->sercom[i].sercom; sercom_index = tx->sercom[i].index; - if (potential_sercom == NULL || - potential_sercom->USART.CTRLA.bit.ENABLE != 0 || + if (sercom_index >= SERCOM_INST_NUM) { + continue; + } + potential_sercom = sercom_insts[sercom_index]; + if (potential_sercom->USART.CTRLA.bit.ENABLE != 0 || !(tx->sercom[i].pad == 0 || tx->sercom[i].pad == 2)) { continue; @@ -98,12 +100,13 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, } } for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { - if (((!have_tx && rx->sercom[j].sercom->USART.CTRLA.bit.ENABLE == 0) || - potential_sercom == rx->sercom[j].sercom) && + if (((!have_tx && rx->sercom[j].index < SERCOM_INST_NUM && + sercom_insts[rx->sercom[j].index]->USART.CTRLA.bit.ENABLE == 0) || + sercom_index == rx->sercom[j].index) && rx->sercom[j].pad != tx_pad) { rx_pinmux = PINMUX(rx->pin, (j == 0) ? MUX_C : MUX_D); rx_pad = rx->sercom[j].pad; - sercom = rx->sercom[j].sercom; + sercom = sercom_insts[rx->sercom[j].index]; sercom_index = rx->sercom[j].index; break; } @@ -147,7 +150,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, // usart_async_init() sets a number of defaults based on a prototypical SERCOM // which don't necessarily match what we need. After calling it, set the values // specific to this instantiation of UART. - + // Set pads computed for this SERCOM. // TXPO: // 0x0: TX pad 0; no RTS/CTS @@ -182,7 +185,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, // http://start.atmel.com/static/help/index.html?GUID-79201A5A-226F-4FBB-B0B8-AB0BE0554836 // Look at the ASFv4 code example for async USART. usart_async_register_callback(usart_desc_p, USART_ASYNC_RXC_CB, usart_async_rxc_callback); - + if (have_tx) { gpio_set_pin_direction(tx->pin, GPIO_DIRECTION_OUT); @@ -193,7 +196,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, } else { self->tx_pin = NO_PIN; } - + if (have_rx) { gpio_set_pin_direction(rx->pin, GPIO_DIRECTION_IN); gpio_set_pin_pull_mode(rx->pin, GPIO_PULL_OFF); @@ -238,7 +241,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t // Nothing to read. return 0; } - + struct io_descriptor *io; usart_async_get_io_descriptor(usart_desc_p, &io); @@ -266,7 +269,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t MICROPY_VM_HOOK_LOOP #endif } - + return total_read; } @@ -305,7 +308,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } - + struct usart_async_status async_status; // Could return ERR_BUSY, but if that's true there's already a problem. usart_async_get_status(usart_desc_p, &async_status); diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.h b/ports/atmel-samd/common-hal/microcontroller/Pin.h index ca639eb849a62..4e21a14cd860d 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.h +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.h @@ -34,9 +34,8 @@ #include "include/component/sercom.h" typedef struct { - Sercom *const sercom; // SERCOM0, SERCOM1, etc. - uint8_t index; // 0, 1, etc. corresponding to SERCOM. - uint8_t pad; // which of the four SERCOM pads to use + uint8_t index:6; // 0, 1, etc. corresponding to SERCOM. + uint8_t pad:2; // which of the four SERCOM pads to use } pin_sercom_t; typedef struct { diff --git a/ports/atmel-samd/peripherals.h b/ports/atmel-samd/peripherals.h index bb01bc1acd277..18c7f44d5c278 100644 --- a/ports/atmel-samd/peripherals.h +++ b/ports/atmel-samd/peripherals.h @@ -35,6 +35,8 @@ uint8_t samd_peripherals_spi_baudrate_to_baud_reg_value(const uint32_t baudrate); uint32_t samd_peripherals_spi_baud_reg_value_to_baudrate(const uint8_t baud_reg_value); +Sercom* sercom_insts[SERCOM_INST_NUM]; + #ifdef SAMD21 #include "samd21_peripherals.h" #endif diff --git a/ports/atmel-samd/samd21_peripherals.c b/ports/atmel-samd/samd21_peripherals.c index 484c787cb030c..a27e49e0e5e99 100644 --- a/ports/atmel-samd/samd21_peripherals.c +++ b/ports/atmel-samd/samd21_peripherals.c @@ -56,7 +56,8 @@ static const uint8_t SERCOMx_GCLK_ID_SLOW[] = { #endif }; - +Sercom* sercom_insts[SERCOM_INST_NUM] = SERCOM_INSTS; + // Clock initialization as done in Atmel START. void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) { _pm_enable_bus_clock(PM_BUS_APBC, sercom); diff --git a/ports/atmel-samd/samd21_pins.c b/ports/atmel-samd/samd21_pins.c index f1d006de8bf0f..eafc4b5fb692b 100644 --- a/ports/atmel-samd/samd21_pins.c +++ b/ports/atmel-samd/samd21_pins.c @@ -30,15 +30,13 @@ #define SERCOM(sercom_index, p_pad) \ { \ - .sercom = SERCOM## sercom_index, \ .index = sercom_index, \ .pad = p_pad \ } #define NO_SERCOM \ { \ - .sercom = 0, \ - .index = 0, \ + .index = 0x3f, \ .pad = 0 \ } @@ -57,7 +55,7 @@ .wave_output = p_wave_output \ } -#define NO_TIMER TCC(0, 0) +#define NO_TIMER TCC(0xff, 0) #define TOUCH(y_line) \ .has_touch = true, \ @@ -92,8 +90,6 @@ const mcu_pin_obj_t pin_## p_name = { \ .sercom = {p_primary_sercom, p_secondary_sercom}, \ } -#define NO_ADC_INPUT (0) - // Pins in datasheet order. // NOTE(tannewt): TC wave out 0 is commented out because the first channel is // used to vary the 16 bit timer's frequency. diff --git a/ports/atmel-samd/samd51_peripherals.c b/ports/atmel-samd/samd51_peripherals.c index e06f7f9df0596..8f37bdfd115d8 100644 --- a/ports/atmel-samd/samd51_peripherals.c +++ b/ports/atmel-samd/samd51_peripherals.c @@ -60,7 +60,8 @@ static const uint8_t SERCOMx_GCLK_ID_SLOW[] = { #endif }; - +Sercom* sercom_insts[SERCOM_INST_NUM] = SERCOM_INSTS; + // Clock initialization as done in Atmel START. void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) { hri_gclk_write_PCHCTRL_reg(GCLK, diff --git a/ports/atmel-samd/samd51_pins.c b/ports/atmel-samd/samd51_pins.c index 78bdf0553c701..6d597b6e1a0d6 100644 --- a/ports/atmel-samd/samd51_pins.c +++ b/ports/atmel-samd/samd51_pins.c @@ -30,15 +30,13 @@ #define SERCOM(sercom_index, p_pad) \ { \ - .sercom = SERCOM## sercom_index, \ .index = sercom_index, \ .pad = p_pad \ } #define NO_SERCOM \ { \ - .sercom = 0, \ - .index = 0, \ + .index = 0x3f, \ .pad = 0 \ } @@ -91,8 +89,6 @@ const mcu_pin_obj_t pin_## p_name = { \ .sercom = {p_primary_sercom, p_secondary_sercom}, \ } -#define NO_ADC_INPUT (0) - // Pins in datasheet order. // NOTE(tannewt): TC wave out 0 is commented out because the first channel is // used to vary the 16 bit timer's frequency. @@ -1139,7 +1135,7 @@ PIN(PA31, EXTINT_CHANNEL(15), NO_ADC, NO_ADC, NO_TOUCH, #else NO_SERCOM, #endif - SERCOM(1, 23), + SERCOM(1, 3), #ifdef TC6 TC(6, 1), #else