diff --git a/boards/frdm-k64f/include/periph_conf.h b/boards/frdm-k64f/include/periph_conf.h index ae52351682..7c28ebf558 100644 --- a/boards/frdm-k64f/include/periph_conf.h +++ b/boards/frdm-k64f/include/periph_conf.h @@ -79,24 +79,19 @@ extern "C" * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -#define UART_0_EN 1 -#define UART_IRQ_PRIO 1 -#define UART_CLK CLOCK_CORECLOCK - -/* UART 0 device configuration */ -#define KINETIS_UART UART_Type -#define UART_0_DEV UART0 -#define UART_0_CLKEN() (SIM->SCGC4 |= (SIM_SCGC4_UART0_MASK)) -#define UART_0_CLK UART_CLK -#define UART_0_IRQ_CHAN UART0_RX_TX_IRQn -#define UART_0_ISR isr_uart0_rx_tx -/* UART 0 pin configuration */ -#define UART_0_PORT_CLKEN() (SIM->SCGC5 |= (SIM_SCGC5_PORTB_MASK)) -#define UART_0_PORT PORTB -#define UART_0_RX_PIN 16 -#define UART_0_TX_PIN 17 -#define UART_0_AF 3 +static const uart_conf_t uart_config[] = { + { + .dev = UART0, + .clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT)), + .freq = CLOCK_CORECLOCK, + .pin_rx = GPIO_PIN(PORT_B, 16), + .pin_tx = GPIO_PIN(PORT_B, 17), + .pcr_rx = PORT_PCR_MUX(3), + .pcr_tx = PORT_PCR_MUX(3), + .irqn = UART0_RX_TX_IRQn, + }, +}; +#define UART_NUMOF (sizeof(uart_config) / sizeof(uart_config[0])) /** @} */ /** diff --git a/boards/mulle/include/board.h b/boards/mulle/include/board.h index 6cb2e5c059..70f6efb4a3 100644 --- a/boards/mulle/include/board.h +++ b/boards/mulle/include/board.h @@ -34,6 +34,11 @@ /** Disable hardware watchdog, for debugging purposes, don't use this on production builds. */ #define DISABLE_WDOG 1 +/** + * @brief Use the UART1 for STDIO on this board + */ +#define UART_STDIO_DEV UART_DEV(1) + /** * @brief xtimer configuration * @{ diff --git a/boards/mulle/include/periph_conf.h b/boards/mulle/include/periph_conf.h index 12035939a6..dfcb4c42af 100644 --- a/boards/mulle/include/periph_conf.h +++ b/boards/mulle/include/periph_conf.h @@ -96,49 +96,29 @@ extern "C" * @name UART configuration * @{ */ -#define UART_NUMOF (2U) -#define UART_0_EN 1 -#define UART_1_EN 1 -#define UART_2_EN 0 -#define UART_3_EN 0 -#define UART_4_EN 0 -#define UART_IRQ_PRIO CPU_DEFAULT_IRQ_PRIO - -/* UART 0 device configuration */ -#define UART_0_DEV UART1 -#define UART_0_CLKEN() (BITBAND_REG32(SIM->SCGC4, SIM_SCGC4_UART1_SHIFT) = 1) -#define UART_0_CLKDIS() (BITBAND_REG32(SIM->SCGC4, SIM_SCGC4_UART1_SHIFT) = 0) -#define UART_0_CLK (CLOCK_CORECLOCK) -#define UART_0_IRQ_CHAN UART1_RX_TX_IRQn -#define UART_0_ISR isr_uart1_status -/* UART 0 pin configuration */ -#define UART_0_PORT_CLKEN() (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTC_SHIFT) = 1) -#define UART_0_PORT PORTC -#define UART_0_TX_PIN 4 -#define UART_0_RX_PIN 3 -/* Function number in pin multiplex, see K60 Sub-Family Reference Manual, - * section 10.3.1 K60 Signal Multiplexing and Pin Assignments */ -#define UART_0_AF 3 -#define UART_0_TX_PCR_MUX 3 -#define UART_0_RX_PCR_MUX 3 - -/* UART 1 device configuration */ -#define UART_1_DEV UART0 -#define UART_1_CLKEN() (BITBAND_REG32(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT) = 1) -#define UART_1_CLKDIS() (BITBAND_REG32(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT) = 0) -#define UART_1_CLK (CLOCK_CORECLOCK) -#define UART_1_IRQ_CHAN UART0_RX_TX_IRQn -#define UART_1_ISR isr_uart0_status -/* UART 1 pin configuration */ -#define UART_1_PORT_CLKEN() (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTA_SHIFT) = 1) -#define UART_1_PORT PORTA -#define UART_1_TX_PIN 14 -#define UART_1_RX_PIN 15 -/* Function number in pin multiplex, see K60 Sub-Family Reference Manual, - * section 10.3.1 K60 Signal Multiplexing and Pin Assignments */ -#define UART_1_AF 3 -#define UART_1_TX_PCR_MUX 3 -#define UART_1_RX_PCR_MUX 3 +static const uart_conf_t uart_config[] = { + { + .dev = UART0, + .clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT)), + .freq = CLOCK_CORECLOCK, + .pin_rx = GPIO_PIN(PORT_A, 14), + .pin_tx = GPIO_PIN(PORT_A, 15), + .pcr_rx = PORT_PCR_MUX(3), + .pcr_tx = PORT_PCR_MUX(3), + .irqn = UART0_RX_TX_IRQn, + }, + { + .dev = UART1, + .clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART1_SHIFT)), + .freq = CLOCK_CORECLOCK, + .pin_rx = GPIO_PIN(PORT_C, 3), + .pin_tx = GPIO_PIN(PORT_C, 4), + .pcr_rx = PORT_PCR_MUX(3), + .pcr_tx = PORT_PCR_MUX(3), + .irqn = UART1_RX_TX_IRQn, + }, +}; +#define UART_NUMOF (sizeof(uart_config) / sizeof(uart_config[0])) /** @} */ diff --git a/boards/pba-d-01-kw2x/include/board.h b/boards/pba-d-01-kw2x/include/board.h index e18b6c7c9f..3b0ec59b0e 100644 --- a/boards/pba-d-01-kw2x/include/board.h +++ b/boards/pba-d-01-kw2x/include/board.h @@ -30,6 +30,11 @@ extern "C" { #endif +/** + * @brief Use the UART2 for STDIO on this board + */ +#define UART_STDIO_DEV UART_DEV(2) + /** * @name LED pin definitions and handlers * @{ diff --git a/boards/pba-d-01-kw2x/include/periph_conf.h b/boards/pba-d-01-kw2x/include/periph_conf.h index 78a5864736..5d5b111a85 100644 --- a/boards/pba-d-01-kw2x/include/periph_conf.h +++ b/boards/pba-d-01-kw2x/include/periph_conf.h @@ -81,38 +81,39 @@ extern "C" * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -#define UART_0_EN 1 -#define UART_1_EN 0 -#define UART_IRQ_PRIO 1 -#define UART_CLK (48e6) - -/* UART 0 device configuration */ -#define KINETIS_UART UART_Type -#define UART_0_DEV UART2 -#define UART_0_CLKEN() (SIM->SCGC4 |= (SIM_SCGC4_UART2_MASK)) -#define UART_0_CLK UART_CLK -#define UART_0_IRQ_CHAN UART2_RX_TX_IRQn -#define UART_0_ISR isr_uart2_rx_tx -/* UART 0 pin configuration */ -#define UART_0_PORT_CLKEN() (SIM->SCGC5 |= (SIM_SCGC5_PORTD_MASK)) -#define UART_0_PORT PORTD -#define UART_0_RX_PIN 2 -#define UART_0_TX_PIN 3 -#define UART_0_AF 3 - -/* UART 1 device configuration */ -#define UART_1_DEV UART0 -#define UART_1_CLKEN() (SIM->SCGC4 |= (SIM_SCGC4_UART0_MASK)) -#define UART_1_CLK UART_CLK -#define UART_1_IRQ_CHAN UART0_RX_TX_IRQn -#define UART_1_ISR isr_uart0_rx_tx -/* UART 1 pin configuration */ -#define UART_1_PORT_CLKEN() (SIM->SCGC5 |= (SIM_SCGC5_PORTD_MASK)) -#define UART_1_PORT PORTD -#define UART_1_RX_PIN 6 -#define UART_1_TX_PIN 7 -#define UART_1_AF 3 +static const uart_conf_t uart_config[] = { + { + .dev = UART0, + .clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT)), + .freq = CLOCK_CORECLOCK, + .pin_rx = GPIO_PIN(PORT_D, 6), + .pin_tx = GPIO_PIN(PORT_D, 7), + .pcr_rx = PORT_PCR_MUX(3), + .pcr_tx = PORT_PCR_MUX(3), + .irqn = UART0_RX_TX_IRQn, + }, + { + .dev = UART1, + .clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART1_SHIFT)), + .freq = CLOCK_CORECLOCK, + .pin_rx = GPIO_UNDEF, + .pin_tx = GPIO_UNDEF, + .pcr_rx = PORT_PCR_MUX(3), + .pcr_tx = PORT_PCR_MUX(3), + .irqn = UART1_RX_TX_IRQn, + }, + { + .dev = UART2, + .clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART2_SHIFT)), + .freq = CLOCK_BUSCLOCK, + .pin_rx = GPIO_PIN(PORT_D, 2), + .pin_tx = GPIO_PIN(PORT_D, 3), + .pcr_rx = PORT_PCR_MUX(3), + .pcr_tx = PORT_PCR_MUX(3), + .irqn = UART2_RX_TX_IRQn, + }, +}; +#define UART_NUMOF (sizeof(uart_config) / sizeof(uart_config[0])) /** @} */ /** diff --git a/cpu/k60/include/cpu_conf.h b/cpu/k60/include/cpu_conf.h index 334b300afa..42d1583639 100644 --- a/cpu/k60/include/cpu_conf.h +++ b/cpu/k60/include/cpu_conf.h @@ -77,14 +77,6 @@ extern "C" #define PORTE_CLOCK_GATE (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTE_SHIFT)) /** @} */ -/** - * @name UART driver settings - */ -/** @{ */ -/** UART typedef from CPU header. */ -#define KINETIS_UART UART_Type -/** @} */ - /** * @name Clock settings for the LPTMR0 timer * @{ diff --git a/cpu/k60/vectors.c b/cpu/k60/vectors.c index a314be5957..9abce1384c 100644 --- a/cpu/k60/vectors.c +++ b/cpu/k60/vectors.c @@ -103,15 +103,15 @@ WEAK_DEFAULT void isr_can1_rx_warn(void); WEAK_DEFAULT void isr_can1_wake_up(void); /* void dummy_handler(void); */ WEAK_DEFAULT void isr_uart0_lon(void); -WEAK_DEFAULT void isr_uart0_status(void); +WEAK_DEFAULT void isr_uart0_rx_tx(void); WEAK_DEFAULT void isr_uart0_error(void); -WEAK_DEFAULT void isr_uart1_status(void); +WEAK_DEFAULT void isr_uart1_rx_tx(void); WEAK_DEFAULT void isr_uart1_error(void); -WEAK_DEFAULT void isr_uart2_status(void); +WEAK_DEFAULT void isr_uart2_rx_tx(void); WEAK_DEFAULT void isr_uart2_error(void); -WEAK_DEFAULT void isr_uart3_status(void); +WEAK_DEFAULT void isr_uart3_rx_tx(void); WEAK_DEFAULT void isr_uart3_error(void); -WEAK_DEFAULT void isr_uart4_status(void); +WEAK_DEFAULT void isr_uart4_rx_tx(void); WEAK_DEFAULT void isr_uart4_error(void); /* void dummy_handler(void); */ /* void dummy_handler(void); */ @@ -224,15 +224,15 @@ ISR_VECTORS const void *interrupt_vector[] = { (void*) isr_can1_wake_up, (void*) dummy_handler, (void*) isr_uart0_lon, - (void*) isr_uart0_status, + (void*) isr_uart0_rx_tx, (void*) isr_uart0_error, - (void*) isr_uart1_status, + (void*) isr_uart1_rx_tx, (void*) isr_uart1_error, - (void*) isr_uart2_status, + (void*) isr_uart2_rx_tx, (void*) isr_uart2_error, - (void*) isr_uart3_status, + (void*) isr_uart3_rx_tx, (void*) isr_uart3_error, - (void*) isr_uart4_status, + (void*) isr_uart4_rx_tx, (void*) isr_uart4_error, (void*) dummy_handler, (void*) dummy_handler, diff --git a/cpu/kinetis_common/doc.txt b/cpu/kinetis_common/doc.txt index dc5d13756d..aefacdb6c6 100644 --- a/cpu/kinetis_common/doc.txt +++ b/cpu/kinetis_common/doc.txt @@ -316,28 +316,33 @@ * The register UARTx_BDH to UARTx_C4 look almost the same. * We distinguish the type of the UART * using the BRFA field in the UART C4 register. - * Currently, only the base functionality is available. + * Currently, only the base TX/RX functionality is available. * * ### UART configuration Example (for periph_conf.h) ### * - * #define UART_NUMOF (1U) - * #define UART_0_EN 1 - * #define UART_IRQ_PRIO 1 - * #define UART_CLK (48e6) - * - * // UART 0 device configuration - * #define KINETIS_UART UART0_Type - * #define UART_0_DEV UART0 - * #define UART_0_CLKEN() (SIM->SCGC4 |= (SIM_SCGC4_UART0_MASK)) - * #define UART_0_CLK UART_CLK - * #define UART_0_IRQ_CHAN UART0_IRQn - * #define UART_0_ISR isr_uart0 - * // UART 0 pin configuration - * #define UART_0_PORT_CLKEN() (SIM->SCGC5 |= (SIM_SCGC5_PORTA_MASK)) - * #define UART_0_PORT PORTA - * #define UART_0_RX_PIN 1 - * #define UART_0_TX_PIN 2 - * #define UART_0_AF 2 + * static const uart_conf_t uart_config[] = { + * { + * .dev = UART0, + * .clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT)), + * .freq = CLOCK_CORECLOCK, + * .pin_rx = GPIO_PIN(PORT_A, 14), + * .pin_tx = GPIO_PIN(PORT_A, 15), + * .pcr_rx = PORT_PCR_MUX(3), + * .pcr_tx = PORT_PCR_MUX(3), + * .irqn = UART0_RX_TX_IRQn, + * }, + * { + * .dev = UART1, + * .clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART1_SHIFT)), + * .freq = CLOCK_CORECLOCK, + * .pin_rx = GPIO_PIN(PORT_C, 3), + * .pin_tx = GPIO_PIN(PORT_C, 4), + * .pcr_rx = PORT_PCR_MUX(3), + * .pcr_tx = PORT_PCR_MUX(3), + * .irqn = UART1_RX_TX_IRQn, + * }, + * }; + * #define UART_NUMOF (sizeof(uart_config) / sizeof(uart_config[0])) * * Optional settings: * diff --git a/cpu/kinetis_common/include/periph_cpu.h b/cpu/kinetis_common/include/periph_cpu.h index 76c5130982..69e0228f9a 100644 --- a/cpu/kinetis_common/include/periph_cpu.h +++ b/cpu/kinetis_common/include/periph_cpu.h @@ -298,6 +298,20 @@ enum { #define TIMER_LPTMR_DEV(x) (TIMER_DEV(PIT_NUMOF + (x))) /** @} */ +/** + * @brief UART module configuration options + */ +typedef struct { + UART_Type *dev; /**< Pointer to module hardware registers */ + volatile uint32_t *clken; /**< Clock enable bitband register address */ + uint32_t freq; /**< Module clock frequency, usually CLOCK_CORECLOCK or CLOCK_BUSCLOCK */ + gpio_t pin_rx; /**< RX pin, GPIO_UNDEF disables RX */ + gpio_t pin_tx; /**< TX pin */ + uint32_t pcr_rx; /**< Pin configuration register bits for RX */ + uint32_t pcr_tx; /**< Pin configuration register bits for TX */ + IRQn_Type irqn; /**< IRQ number for this module */ +} uart_conf_t; + /** * @brief CPU internal function for initializing PORTs * diff --git a/cpu/kinetis_common/periph/uart.c b/cpu/kinetis_common/periph/uart.c index e57c1dc798..02ff85ef19 100644 --- a/cpu/kinetis_common/periph/uart.c +++ b/cpu/kinetis_common/periph/uart.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2017 Eistec AB * Copyright (C) 2014 PHYTEC Messtechnik GmbH * Copyright (C) 2014 Freie UniversitÀt Berlin * @@ -17,6 +18,7 @@ * * @author Hauke Petersen * @author Johann Fischer + * @author Joakim NohlgÄrd * * @} */ @@ -42,7 +44,7 @@ */ static uart_isr_ctx_t config[UART_NUMOF]; -static inline void kinetis_set_brfa(KINETIS_UART *dev, uint32_t baudrate, uint32_t clk) +static inline void kinetis_set_brfa(UART_Type *dev, uint32_t baudrate, uint32_t clk) { #if KINETIS_UART_ADVANCED /* set baudrate fine adjust (brfa) */ @@ -55,87 +57,43 @@ static int init_base(uart_t uart, uint32_t baudrate); int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { + assert(uart < UART_NUMOF); /* do basic initialization */ int res = init_base(uart, baudrate); if (res != UART_OK) { return res; } + UART_Type *dev = uart_config[uart].dev; /* remember callback addresses */ config[uart].rx_cb = rx_cb; config[uart].arg = arg; /* enable receive interrupt */ - switch (uart) { -#if UART_0_EN - - case UART_0: - NVIC_SetPriority(UART_0_IRQ_CHAN, UART_IRQ_PRIO); - NVIC_EnableIRQ(UART_0_IRQ_CHAN); - UART_0_DEV->C2 |= (1 << UART_C2_RIE_SHIFT); - break; -#endif -#if UART_1_EN - - case UART_1: - NVIC_SetPriority(UART_1_IRQ_CHAN, UART_IRQ_PRIO); - NVIC_EnableIRQ(UART_1_IRQ_CHAN); - UART_1_DEV->C2 |= (1 << UART_C2_RIE_SHIFT); - break; -#endif - - default: - return UART_NODEV; - } + NVIC_EnableIRQ(uart_config[uart].irqn); + dev->C2 |= (1 << UART_C2_RIE_SHIFT); return UART_OK; } static int init_base(uart_t uart, uint32_t baudrate) { - KINETIS_UART *dev; - PORT_Type *port; + UART_Type *dev = uart_config[uart].dev; uint32_t clk; uint16_t ubd; - uint8_t tx_pin = 0; - uint8_t rx_pin = 0; - uint8_t af; - switch (uart) { -#if UART_0_EN + clk = uart_config[uart].freq; - case UART_0: - dev = UART_0_DEV; - port = UART_0_PORT; - clk = UART_0_CLK; - tx_pin = UART_0_TX_PIN; - rx_pin = UART_0_RX_PIN; - af = UART_0_AF; - UART_0_PORT_CLKEN(); - UART_0_CLKEN(); - break; -#endif -#if UART_1_EN - - case UART_1: - dev = UART_1_DEV; - port = UART_1_PORT; - clk = UART_1_CLK; - tx_pin = UART_1_TX_PIN; - rx_pin = UART_1_RX_PIN; - af = UART_1_AF; - UART_1_PORT_CLKEN(); - UART_1_CLKEN(); - break; -#endif - - default: - return UART_NODEV; + /* initialize pins */ + if (uart_config[uart].pin_rx != GPIO_UNDEF) { + gpio_init_port(uart_config[uart].pin_rx, uart_config[uart].pcr_rx); + } + if (uart_config[uart].pin_tx != GPIO_UNDEF) { + gpio_init_port(uart_config[uart].pin_tx, uart_config[uart].pcr_tx); } - /* configure RX and TX pins, set pin to use alternative function mode */ - port->PCR[rx_pin] = PORT_PCR_MUX(af); - port->PCR[tx_pin] = PORT_PCR_MUX(af); + /* Turn on module clock gate */ + *(uart_config[uart].clken) = 1; /* disable transmitter and receiver */ dev->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK); @@ -180,46 +138,33 @@ static int init_base(uart_t uart, uint32_t baudrate) void uart_write(uart_t uart, const uint8_t *data, size_t len) { - KINETIS_UART *dev; - - switch (uart) { -#if UART_0_EN - case UART_0: - dev = UART_0_DEV; - break; -#endif -#if UART_1_EN - case UART_1: - dev = UART_1_DEV; - break; -#endif - default: - return; - } + UART_Type *dev = uart_config[uart].dev; for (size_t i = 0; i < len; i++) { - while (!(dev->S1 & UART_S1_TDRE_MASK)); + while (!(dev->S1 & UART_S1_TDRE_MASK)) {} dev->D = data[i]; } } -static inline void irq_handler(uart_t uartnum, KINETIS_UART *dev) +static inline void irq_handler(uart_t uart) { + UART_Type *dev = uart_config[uart].dev; + /* - * On Cortex-M0, it happens that S1 is read with LDR - * instruction instead of LDRB. This will read the data register - * at the same time and arrived byte will be lost. Maybe it's a GCC bug. - * - * Observed with: arm-none-eabi-gcc (4.8.3-8+..) - * It does not happen with: arm-none-eabi-gcc (4.8.3-9+11) - */ + * On Cortex-M0, it happens that S1 is read with LDR + * instruction instead of LDRB. This will read the data register + * at the same time and arrived byte will be lost. Maybe it's a GCC bug. + * + * Observed with: arm-none-eabi-gcc (4.8.3-8+..) + * It does not happen with: arm-none-eabi-gcc (4.8.3-9+11) + */ if (dev->S1 & UART_S1_RDRF_MASK) { /* RDRF flag will be cleared when dev-D was read */ uint8_t data = dev->D; - if (config[uartnum].rx_cb != NULL) { - config[uartnum].rx_cb(config[uartnum].arg, data); + if (config[uart].rx_cb != NULL) { + config[uart].rx_cb(config[uart].arg, data); } } @@ -231,19 +176,29 @@ static inline void irq_handler(uart_t uartnum, KINETIS_UART *dev) #endif cortexm_isr_end(); - } -#if UART_0_EN -void UART_0_ISR(void) +void isr_uart0_rx_tx(void) { - irq_handler(UART_0, UART_0_DEV); + irq_handler(UART_DEV(0)); } -#endif -#if UART_1_EN -void UART_1_ISR(void) +void isr_uart1_rx_tx(void) { - irq_handler(UART_1, UART_1_DEV); + irq_handler(UART_DEV(1)); +} + +void isr_uart2_rx_tx(void) +{ + irq_handler(UART_DEV(2)); +} + +void isr_uart3_rx_tx(void) +{ + irq_handler(UART_DEV(3)); +} + +void isr_uart4_rx_tx(void) +{ + irq_handler(UART_DEV(4)); } -#endif