cpu/stm32_common: add support for lpuart
This commit is contained in:
parent
e0997b4fc7
commit
133968ce8a
@ -51,6 +51,11 @@ uint32_t periph_apb_clk(uint8_t bus)
|
||||
if (bus == APB1) {
|
||||
return CLOCK_APB1;
|
||||
}
|
||||
#if defined (CPU_FAM_STM32L4)
|
||||
else if (bus == APB12) {
|
||||
return CLOCK_APB1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return CLOCK_APB2;
|
||||
}
|
||||
@ -74,6 +79,11 @@ void periph_clk_en(bus_t bus, uint32_t mask)
|
||||
case APB2:
|
||||
RCC->APB2ENR |= mask;
|
||||
break;
|
||||
#if defined(CPU_FAM_STM32L4)
|
||||
case APB12:
|
||||
RCC->APB1ENR2 |= mask;
|
||||
break;
|
||||
#endif
|
||||
#if defined(CPU_FAM_STM32L0)
|
||||
case AHB:
|
||||
RCC->AHBENR |= mask;
|
||||
@ -122,6 +132,11 @@ void periph_clk_dis(bus_t bus, uint32_t mask)
|
||||
case APB2:
|
||||
RCC->APB2ENR &= ~(mask);
|
||||
break;
|
||||
#if defined(CPU_FAM_STM32L4)
|
||||
case APB12:
|
||||
RCC->APB1ENR2 &= ~(mask);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CPU_FAM_STM32L0)
|
||||
case AHB:
|
||||
RCC->AHBENR &= ~(mask);
|
||||
|
||||
@ -96,6 +96,9 @@ extern "C" {
|
||||
typedef enum {
|
||||
APB1, /**< APB1 bus */
|
||||
APB2, /**< APB2 bus */
|
||||
#if defined(CPU_FAM_STM32L4)
|
||||
APB12, /**< AHB1 bus, second register */
|
||||
#endif
|
||||
#if defined(CPU_FAM_STM32L0)
|
||||
AHB, /**< AHB bus */
|
||||
IOP, /**< IOP bus */
|
||||
@ -332,6 +335,14 @@ typedef struct {
|
||||
uint8_t irqn; /**< global IRQ channel */
|
||||
} qdec_conf_t;
|
||||
|
||||
/**
|
||||
* @brief UART hardware module types
|
||||
*/
|
||||
typedef enum {
|
||||
STM32_USART, /**< STM32 USART module type */
|
||||
STM32_LPUART, /**< STM32 Low-power UART (LPUART) module type */
|
||||
} uart_type_t;
|
||||
|
||||
/**
|
||||
* @brief Structure for UART configuration data
|
||||
*/
|
||||
@ -358,6 +369,10 @@ typedef struct {
|
||||
gpio_af_t rts_af; /**< alternate function for RTS pin */
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4)
|
||||
uart_type_t type; /**< hardware module type (USART or LPUART) */
|
||||
uint32_t clk_src; /**< clock source used for UART */
|
||||
#endif
|
||||
} uart_conf_t;
|
||||
|
||||
/**
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2017 Freie Universität Berlin
|
||||
* Copyright (C) 2016 OTA keys
|
||||
* Copyright (C) 2018 Inria
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -20,6 +21,7 @@
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
* @author Hermann Lelong <hermann@otakeys.com>
|
||||
* @author Toon Stegen <toon.stegen@altran.com>
|
||||
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -44,18 +46,15 @@ static inline USART_TypeDef *dev(uart_t uart)
|
||||
return uart_config[uart].dev;
|
||||
}
|
||||
|
||||
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
static inline void uart_init_usart(uart_t uart, uint32_t baudrate);
|
||||
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4)
|
||||
#ifdef MODULE_PERIPH_LPUART
|
||||
static inline void uart_init_lpuart(uart_t uart, uint32_t baudrate);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline void uart_init_pins(uart_t uart, uart_rx_cb_t rx_cb)
|
||||
{
|
||||
uint16_t mantissa;
|
||||
uint8_t fraction;
|
||||
uint32_t clk;
|
||||
|
||||
assert(uart < UART_NUMOF);
|
||||
|
||||
/* save ISR context */
|
||||
isr_ctx[uart].rx_cb = rx_cb;
|
||||
isr_ctx[uart].arg = arg;
|
||||
|
||||
/* configure TX pin */
|
||||
gpio_init(uart_config[uart].tx_pin, GPIO_OUT);
|
||||
/* set TX pin high to avoid garbage during further initialization */
|
||||
@ -84,6 +83,17 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
{
|
||||
assert(uart < UART_NUMOF);
|
||||
|
||||
/* save ISR context */
|
||||
isr_ctx[uart].rx_cb = rx_cb;
|
||||
isr_ctx[uart].arg = arg;
|
||||
|
||||
uart_init_pins(uart, rx_cb);
|
||||
|
||||
/* enable the clock */
|
||||
uart_poweron(uart);
|
||||
@ -93,11 +103,22 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
dev(uart)->CR2 = 0;
|
||||
dev(uart)->CR3 = 0;
|
||||
|
||||
/* calculate and apply baudrate */
|
||||
clk = periph_apb_clk(uart_config[uart].bus) / baudrate;
|
||||
mantissa = (uint16_t)(clk / 16);
|
||||
fraction = (uint8_t)(clk - (mantissa * 16));
|
||||
dev(uart)->BRR = ((mantissa & 0x0fff) << 4) | (fraction & 0x0f);
|
||||
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4)
|
||||
switch (uart_config[uart].type) {
|
||||
case STM32_USART:
|
||||
uart_init_usart(uart, baudrate);
|
||||
break;
|
||||
#ifdef MODULE_PERIPH_LPUART
|
||||
case STM32_LPUART:
|
||||
uart_init_lpuart(uart, baudrate);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return UART_NODEV;
|
||||
}
|
||||
#else
|
||||
uart_init_usart(uart, baudrate);
|
||||
#endif
|
||||
|
||||
/* enable RX interrupt if applicable */
|
||||
if (rx_cb) {
|
||||
@ -118,6 +139,54 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
return UART_OK;
|
||||
}
|
||||
|
||||
static inline void uart_init_usart(uart_t uart, uint32_t baudrate)
|
||||
{
|
||||
uint16_t mantissa;
|
||||
uint8_t fraction;
|
||||
uint32_t clk;
|
||||
|
||||
/* calculate and apply baudrate */
|
||||
clk = periph_apb_clk(uart_config[uart].bus) / baudrate;
|
||||
mantissa = (uint16_t)(clk / 16);
|
||||
fraction = (uint8_t)(clk - (mantissa * 16));
|
||||
dev(uart)->BRR = ((mantissa & 0x0fff) << 4) | (fraction & 0x0f);
|
||||
}
|
||||
|
||||
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4)
|
||||
#ifdef MODULE_PERIPH_LPUART
|
||||
static inline void uart_init_lpuart(uart_t uart, uint32_t baudrate)
|
||||
{
|
||||
uint32_t clk;
|
||||
|
||||
switch (uart_config[uart].clk_src) {
|
||||
case 0:
|
||||
clk = periph_apb_clk(uart_config[uart].bus);
|
||||
break;
|
||||
case RCC_CCIPR_LPUART1SEL_0:
|
||||
clk = CLOCK_CORECLOCK;
|
||||
break;
|
||||
case (RCC_CCIPR_LPUART1SEL_0 | RCC_CCIPR_LPUART1SEL_1):
|
||||
clk = 32768;
|
||||
break;
|
||||
default: /* HSI is not supported */
|
||||
return;
|
||||
}
|
||||
|
||||
RCC->CCIPR |= uart_config[uart].clk_src;
|
||||
|
||||
/* LSE can only be used with baudrate <= 9600 */
|
||||
if ( (clk < (3 * baudrate)) || (clk > (4096 * baudrate))) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* LPUARTDIV = f_clk * 256 / baudrate */
|
||||
uint32_t brr = (uint32_t)(((uint64_t)clk << 8) / baudrate);
|
||||
|
||||
dev(uart)->BRR = brr;
|
||||
}
|
||||
#endif /* MODULE_PERIPH_LPUART */
|
||||
#endif /* STM32L0 || STM32L4 */
|
||||
|
||||
static inline void send_byte(uart_t uart, uint8_t byte)
|
||||
{
|
||||
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L0) \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user