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) {
|
if (bus == APB1) {
|
||||||
return CLOCK_APB1;
|
return CLOCK_APB1;
|
||||||
}
|
}
|
||||||
|
#if defined (CPU_FAM_STM32L4)
|
||||||
|
else if (bus == APB12) {
|
||||||
|
return CLOCK_APB1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else {
|
else {
|
||||||
return CLOCK_APB2;
|
return CLOCK_APB2;
|
||||||
}
|
}
|
||||||
@ -74,6 +79,11 @@ void periph_clk_en(bus_t bus, uint32_t mask)
|
|||||||
case APB2:
|
case APB2:
|
||||||
RCC->APB2ENR |= mask;
|
RCC->APB2ENR |= mask;
|
||||||
break;
|
break;
|
||||||
|
#if defined(CPU_FAM_STM32L4)
|
||||||
|
case APB12:
|
||||||
|
RCC->APB1ENR2 |= mask;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#if defined(CPU_FAM_STM32L0)
|
#if defined(CPU_FAM_STM32L0)
|
||||||
case AHB:
|
case AHB:
|
||||||
RCC->AHBENR |= mask;
|
RCC->AHBENR |= mask;
|
||||||
@ -122,6 +132,11 @@ void periph_clk_dis(bus_t bus, uint32_t mask)
|
|||||||
case APB2:
|
case APB2:
|
||||||
RCC->APB2ENR &= ~(mask);
|
RCC->APB2ENR &= ~(mask);
|
||||||
break;
|
break;
|
||||||
|
#if defined(CPU_FAM_STM32L4)
|
||||||
|
case APB12:
|
||||||
|
RCC->APB1ENR2 &= ~(mask);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#if defined(CPU_FAM_STM32L0)
|
#if defined(CPU_FAM_STM32L0)
|
||||||
case AHB:
|
case AHB:
|
||||||
RCC->AHBENR &= ~(mask);
|
RCC->AHBENR &= ~(mask);
|
||||||
|
|||||||
@ -96,6 +96,9 @@ extern "C" {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
APB1, /**< APB1 bus */
|
APB1, /**< APB1 bus */
|
||||||
APB2, /**< APB2 bus */
|
APB2, /**< APB2 bus */
|
||||||
|
#if defined(CPU_FAM_STM32L4)
|
||||||
|
APB12, /**< AHB1 bus, second register */
|
||||||
|
#endif
|
||||||
#if defined(CPU_FAM_STM32L0)
|
#if defined(CPU_FAM_STM32L0)
|
||||||
AHB, /**< AHB bus */
|
AHB, /**< AHB bus */
|
||||||
IOP, /**< IOP bus */
|
IOP, /**< IOP bus */
|
||||||
@ -332,6 +335,14 @@ typedef struct {
|
|||||||
uint8_t irqn; /**< global IRQ channel */
|
uint8_t irqn; /**< global IRQ channel */
|
||||||
} qdec_conf_t;
|
} 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
|
* @brief Structure for UART configuration data
|
||||||
*/
|
*/
|
||||||
@ -358,6 +369,10 @@ typedef struct {
|
|||||||
gpio_af_t rts_af; /**< alternate function for RTS pin */
|
gpio_af_t rts_af; /**< alternate function for RTS pin */
|
||||||
#endif
|
#endif
|
||||||
#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;
|
} uart_conf_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2014-2017 Freie Universität Berlin
|
* Copyright (C) 2014-2017 Freie Universität Berlin
|
||||||
* Copyright (C) 2016 OTA keys
|
* Copyright (C) 2016 OTA keys
|
||||||
|
* Copyright (C) 2018 Inria
|
||||||
*
|
*
|
||||||
* This file is subject to the terms and conditions of the GNU Lesser
|
* 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
|
* 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 Fabian Nack <nack@inf.fu-berlin.de>
|
||||||
* @author Hermann Lelong <hermann@otakeys.com>
|
* @author Hermann Lelong <hermann@otakeys.com>
|
||||||
* @author Toon Stegen <toon.stegen@altran.com>
|
* @author Toon Stegen <toon.stegen@altran.com>
|
||||||
|
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
|
||||||
*
|
*
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
@ -44,19 +46,16 @@ static inline USART_TypeDef *dev(uart_t uart)
|
|||||||
return uart_config[uart].dev;
|
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;
|
/* configure TX pin */
|
||||||
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);
|
gpio_init(uart_config[uart].tx_pin, GPIO_OUT);
|
||||||
/* set TX pin high to avoid garbage during further initialization */
|
/* set TX pin high to avoid garbage during further initialization */
|
||||||
gpio_set(uart_config[uart].tx_pin);
|
gpio_set(uart_config[uart].tx_pin);
|
||||||
@ -84,6 +83,17 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#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 */
|
/* enable the clock */
|
||||||
uart_poweron(uart);
|
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)->CR2 = 0;
|
||||||
dev(uart)->CR3 = 0;
|
dev(uart)->CR3 = 0;
|
||||||
|
|
||||||
/* calculate and apply baudrate */
|
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4)
|
||||||
clk = periph_apb_clk(uart_config[uart].bus) / baudrate;
|
switch (uart_config[uart].type) {
|
||||||
mantissa = (uint16_t)(clk / 16);
|
case STM32_USART:
|
||||||
fraction = (uint8_t)(clk - (mantissa * 16));
|
uart_init_usart(uart, baudrate);
|
||||||
dev(uart)->BRR = ((mantissa & 0x0fff) << 4) | (fraction & 0x0f);
|
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 */
|
/* enable RX interrupt if applicable */
|
||||||
if (rx_cb) {
|
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;
|
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)
|
static inline void send_byte(uart_t uart, uint8_t byte)
|
||||||
{
|
{
|
||||||
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L0) \
|
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L0) \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user