summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter van der Burg <vdb_peter@hotmail.com>2021-05-21 10:02:01 +1000
committerDamien George <damien@micropython.org>2021-11-19 11:42:47 +1100
commit4c132614e136970cbd12d927bc6c52e2a7f0f070 (patch)
treeaa3e9e880e7d19b38d8f56a6e9c899171c409b63
parentcd2223b8fe5b242304016f2e160eca59a7cb81f9 (diff)
samd/samd_soc: Allow a board to configure the low-level MCU config.
The board specific #defines will be moved to individual boards.
-rw-r--r--ports/samd/samd_soc.c95
-rw-r--r--ports/samd/samd_soc.h12
2 files changed, 53 insertions, 54 deletions
diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c
index a08d0de26..7f4df1bb1 100644
--- a/ports/samd/samd_soc.c
+++ b/ports/samd/samd_soc.c
@@ -1,6 +1,12 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
+ * This file initialises the USB (tinyUSB) and USART (SERCOM). Board USART settings
+ * are set in 'boards/<board>/mpconfigboard.h.
+ *
+ * IMPORTANT: Please refer to "I/O Multiplexing and Considerations" chapters
+ * in device datasheets for I/O Pin functions and assignments.
+ *
* The MIT License (MIT)
*
* Copyright (c) 2019 Damien P. George
@@ -24,56 +30,53 @@
* THE SOFTWARE.
*/
+#include "py/runtime.h"
+#include "modmachine.h"
#include "samd_soc.h"
#include "tusb.h"
-static void uart0_init(void) {
- #if defined(MCU_SAMD21)
+// "MP" macros defined in "boards/$(BOARD)/mpconfigboard.h"
+mp_obj_t machine_uart_init(void) {
+ // Firstly, assign alternate function SERCOM PADs to GPIO pins.
+ PORT->Group[MP_PIN_GRP].PINCFG[MP_TX_PIN].bit.PMUXEN = 1; // Enable
+ PORT->Group[MP_PIN_GRP].PINCFG[MP_RX_PIN].bit.PMUXEN = 1; // Enable
+ PORT->Group[MP_PIN_GRP].PMUX[MP_PERIPHERAL_MUX].reg = MP_PORT_FUNC; // Sets PMUXE & PMUXO in 1 hit.
+ uint32_t rxpo = MP_RXPO_PAD; // 1=Pad1,3=Pad3 Rx data
+ uint32_t txpo = MP_TXPO_PAD; // 0=pad0,1=Pad2 Tx data
- // SERCOM0, TX=PA06=PAD2, RX=PA07=PAD3, ALT-D
- PORT->Group[0].PMUX[3].reg = 0x33;
- PORT->Group[0].PINCFG[6].reg = 1;
- PORT->Group[0].PINCFG[7].reg = 1;
-
- PM->APBCMASK.bit.SERCOM0_ = 1;
- GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_SERCOM0_CORE;
+ // Initialise the clocks
+ #if defined(MCU_SAMD21)
+ PM->APBCMASK.bit.MP_SERCOMx = 1; // Enable synchronous clock
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | MP_SERCOM_GCLK_ID_x_CORE; // Select multiplexer generic clock source and enable.
+ // Wait while it updates synchronously.
while (GCLK->STATUS.bit.SYNCBUSY) {
}
-
- uint32_t rxpo = 3;
- uint32_t txpo = 1;
-
#elif defined(MCU_SAMD51)
-
- // SERCOM3, TX=PA17=PAD0, RX=PA16=PAD1, ALT-D
- PORT->Group[0].PMUX[8].reg = 0x33;
- PORT->Group[0].PINCFG[16].reg = 1;
- PORT->Group[0].PINCFG[17].reg = 1;
-
- // Use Generator 0 which is already enabled and switched to DFLL @ 48MHz
- GCLK->PCHCTRL[SERCOM3_GCLK_ID_CORE].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0;
- MCLK->APBBMASK.bit.SERCOM3_ = 1;
-
- uint32_t rxpo = 1;
- uint32_t txpo = 2;
-
+ GCLK->PCHCTRL[MP_SERCOM_GCLK_ID_x_CORE].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0;
+ MCLK->APBBMASK.bit.MP_SERCOMx = 1;
#endif
+ // Setup the Peripheral.
+ // Reset (clear) the peripheral registers.
while (USARTx->USART.SYNCBUSY.bit.SWRST) {
}
- USARTx->USART.CTRLA.bit.SWRST = 1;
+ USARTx->USART.CTRLA.bit.SWRST = 1; // Reset all Registers, disable peripheral
while (USARTx->USART.SYNCBUSY.bit.SWRST) {
}
- USARTx->USART.CTRLA.reg =
- SERCOM_USART_CTRLA_DORD
- | SERCOM_USART_CTRLA_RXPO(rxpo)
- | SERCOM_USART_CTRLA_TXPO(txpo)
- | SERCOM_USART_CTRLA_MODE(1)
+ // Set the register bits as needed
+ // (CMODE (async),CHSIZE (8),FORM (no parity),SBMODE (1 stop) already 0).
+ USARTx->USART.CTRLA.reg = // USARTx = SERCOMx set in "boards/$(BOARD)/mpconfigboard.h"
+ SERCOM_USART_CTRLA_DORD // Data order
+ | SERCOM_USART_CTRLA_RXPO(rxpo) // Set Pad#
+ | SERCOM_USART_CTRLA_TXPO(txpo) // Set Pad#
+ | SERCOM_USART_CTRLA_MODE(1) // USART with internal clock
;
- USARTx->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN;
+ USARTx->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN; // Enable Rx & Tx
while (USARTx->USART.SYNCBUSY.bit.CTRLB) {
}
+
+ // Baud rate is clock dependant.
#if CPU_FREQ == 8000000
uint32_t baud = 50437; // 115200 baud; 65536*(1 - 16 * 115200/8e6)
#elif CPU_FREQ == 48000000
@@ -81,12 +84,26 @@ static void uart0_init(void) {
#elif CPU_FREQ == 120000000
uint32_t baud = 64529; // 115200 baud; 65536*(1 - 16 * 115200/120e6)
#endif
- USARTx->USART.BAUD.bit.BAUD = baud;
- USARTx->USART.CTRLA.bit.ENABLE = 1;
+ USARTx->USART.BAUD.bit.BAUD = baud; // Set Baud
+ USARTx->USART.CTRLA.bit.ENABLE = 1; // Enable the peripheral
+ // Wait for the Registers to update.
while (USARTx->USART.SYNCBUSY.bit.ENABLE) {
}
+
+ return mp_const_none;
}
+// Disconnect SERCOM from GPIO pins. (Can't SWRST, as that will totally kill USART).
+mp_obj_t machine_uart_deinit(void) {
+ // Reset
+ printf("Disabling the Alt-Funct, releasing the USART pins for GPIO... \n");
+ PORT->Group[MP_PIN_GRP].PINCFG[MP_TX_PIN].bit.PMUXEN = 0; // Disable
+ PORT->Group[MP_PIN_GRP].PINCFG[MP_RX_PIN].bit.PMUXEN = 0; // Disable
+
+ return mp_const_none;
+}
+
+
static void usb_init(void) {
// Init USB clock
#if defined(MCU_SAMD21)
@@ -142,21 +159,15 @@ void samd_init(void) {
while (GCLK->STATUS.bit.SYNCBUSY) {
}
- // Configure PA10 as output for LED
- PORT->Group[0].DIRSET.reg = 1 << 10;
-
#elif defined(MCU_SAMD51)
GCLK->GENCTRL[1].reg = 1 << GCLK_GENCTRL_DIV_Pos | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;
while (GCLK->SYNCBUSY.bit.GENCTRL1) {
}
- // Configure PA22 as output for LED
- PORT->Group[0].DIRSET.reg = 1 << 22;
-
#endif
SysTick_Config(CPU_FREQ / 1000);
- uart0_init();
+ machine_uart_init();
usb_init();
}
diff --git a/ports/samd/samd_soc.h b/ports/samd/samd_soc.h
index 5f68610e4..a07e68dbe 100644
--- a/ports/samd/samd_soc.h
+++ b/ports/samd/samd_soc.h
@@ -29,18 +29,6 @@
#include <stdint.h>
#include "sam.h"
-#if defined(MCU_SAMD21)
-
-#define CPU_FREQ (48000000)
-#define USARTx SERCOM0
-
-#elif defined(MCU_SAMD51)
-
-#define CPU_FREQ (48000000)
-#define USARTx SERCOM3
-
-#endif
-
void samd_init(void);
void samd_main(void);