From 4ad3313ae5f43ece4e6f69927b97496513ea71bf Mon Sep 17 00:00:00 2001 From: Kees Bakker <kees@sodaq.com> Date: Sun, 31 Jul 2016 22:20:58 +0200 Subject: [PATCH] cpu/sam21_common: add a few typedefs for SERCOM A generic function is added to initialize a SERCOM. Notice that uart_conf_t was expanded with pad settings, but it isn't used yet. --- cpu/sam21_common/include/periph_cpu_common.h | 73 +++++++++++++++++++- cpu/samd21/include/periph_cpu.h | 4 +- cpu/samd21/periph/gpio.c | 21 ++++++ 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/cpu/sam21_common/include/periph_cpu_common.h b/cpu/sam21_common/include/periph_cpu_common.h index 540d256947..7964ddb54d 100644 --- a/cpu/sam21_common/include/periph_cpu_common.h +++ b/cpu/sam21_common/include/periph_cpu_common.h @@ -86,13 +86,82 @@ typedef enum { GPIO_MUX_H = 0x7, /**< select peripheral function H */ } gpio_mux_t; +/** + * @brief Possible pad selections for SERCOM RX (inspired by Arduino) + */ +typedef enum { + SERCOM_RX_PAD_0 = 0x0, /**< select pad 0 */ + SERCOM_RX_PAD_1 = 0x1, /**< select pad 1 */ + SERCOM_RX_PAD_2 = 0x2, /**< select pad 2 */ + SERCOM_RX_PAD_3 = 0x3, /**< select pad 3 */ +} sercom_rxpad_t; + +/** + * @brief Possible pad selections for SERCOM UART TX (inspired by Arduino) + */ +typedef enum { + UART_TX_PAD_0 = 0x0, /**< select pad 0, only UART */ + UART_TX_PAD_2 = 0x1, /**< select pad 2, only UART */ + UART_TX_RTS_CTS_PAD_0_2_3 = 0x2, /**< select pad 0, 2 and 3, only UART, TX on PAD0, RTS on PAD2 and CTS on PAD3 */ +} sercom_uart_txpad_t; + +/** + * @brief Possible pad selections for SERCOM SPI output (inspired by Arduino) + */ +typedef enum { + SPI_PAD_0_SCK_1 = 0, /**< select pad 0, SCK pad1, only SPI */ + SPI_PAD_2_SCK_3 = 1, /**< select pad 2, SCK pad3, only SPI */ + SPI_PAD_3_SCK_1 = 2, /**< select pad 3, SCK pad1, only SPI */ + SPI_PAD_0_SCK_3 = 3, /**< select pad 0, SCK pad3, only SPI */ +} sercom_spi_txpad_t; + +/** + * @brief Possible selections for SERCOM SPI data size (inspired by Arduino) + */ +typedef enum +{ + SPI_CHAR_SIZE_8_BITS = 0x0ul, + SPI_CHAR_SIZE_9_BITS = 0x1ul, +} sercom_spi_charsize_t; + +/** + * @brief Possible selections for SERCOM data (bit) order (inspired by Arduino) + */ +typedef enum +{ + MSB_FIRST = 0, + LSB_FIRST = 1, +} sercom_data_order_t; + +/** + * @brief Possible selections for SERCOM SPI clock mode (inspired by Arduino) + */ +typedef enum +{ + SERCOM_SPI_MODE_0 = 0, // CPOL : 0 | CPHA : 0 + SERCOM_SPI_MODE_1 = 1, // CPOL : 0 | CPHA : 1 + SERCOM_SPI_MODE_2 = 2, // CPOL : 1 | CPHA : 0 + SERCOM_SPI_MODE_3 = 3, // CPOL : 1 | CPHA : 1 +} sercom_spi_clockmode_t; + /** * @brief Set up alternate function (PMUX setting) for a PORT pin * - * @param[in] dev Pin to set the multiplexing for + * @param[in] pin Pin to set the multiplexing for + * @param[in] mux Mux value + */ +void gpio_init_mux(gpio_t pin, gpio_mux_t mux); + +/** + * @brief Set up PORT pin for SERCOM usage + * + * This function initializes the pin for SERCOM usage. It is derived + * from Arduino's pinPeripheral() in wiring_private.c + * + * @param[in] pin Pin to set the multiplexing for * @param[in] mux Mux value */ -void gpio_init_mux(gpio_t dev, gpio_mux_t mux); +void gpio_init_sercom(gpio_t pin, gpio_mux_t mux); #ifdef __cplusplus } diff --git a/cpu/samd21/include/periph_cpu.h b/cpu/samd21/include/periph_cpu.h index 9efa4f213c..409a6a95d0 100644 --- a/cpu/samd21/include/periph_cpu.h +++ b/cpu/samd21/include/periph_cpu.h @@ -38,7 +38,7 @@ enum { * @brief Generate GPIO mode bitfields * * We use 3 bit to determine the pin functions: - * - bit 0: PU or PU + * - bit 0: PD(0) or PU(1) * - bit 1: input enable * - bit 2: pull enable */ @@ -86,6 +86,8 @@ typedef struct { gpio_t rx_pin; /**< pin used for RX */ gpio_t tx_pin; /**< pin used for TX */ gpio_mux_t mux; /**< alternative function for pins */ + sercom_rxpad_t rx_pad; /**< pad selection for RX */ + sercom_uart_txpad_t tx_pad; /**< pad selection for TX */ } uart_conf_t; /** diff --git a/cpu/samd21/periph/gpio.c b/cpu/samd21/periph/gpio.c index cf31d73060..78830c1a67 100644 --- a/cpu/samd21/periph/gpio.c +++ b/cpu/samd21/periph/gpio.c @@ -120,6 +120,27 @@ int gpio_init(gpio_t pin, gpio_mode_t mode) return 0; } +void gpio_init_sercom(gpio_t pin, gpio_mux_t mux) +{ + PortGroup* port = _port(pin); + int pin_pos = _pin_pos(pin); + uint32_t temp; + + if ( (pin_pos & 1) ) { // is pin odd? + // Get whole current setup for both odd and even pins and remove odd one + temp = port->PMUX[pin_pos >> 1].reg & PORT_PMUX_PMUXE(0xF); + // Set new muxing + port->PMUX[pin_pos >> 1].reg = temp | PORT_PMUX_PMUXO(mux); + } else { + // Get whole current setup for both odd and even pins and remove even one + temp = port->PMUX[pin_pos >> 1].reg & PORT_PMUX_PMUXO(0xF); + // Set new muxing + port->PMUX[pin_pos >> 1].reg = temp | PORT_PMUX_PMUXE(mux); + } + // Enable port mux + port->PINCFG[pin_pos].reg |= PORT_PINCFG_PMUXEN; +} + int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, gpio_cb_t cb, void *arg) { -- GitLab