mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-25 14:33:52 +01:00
Merge pull request #9158 from aabadie/pr/periph/stm32_lpuart
cpu/stm32-common: add support for lpuart
This commit is contained in:
commit
a3864aa103
@ -81,7 +81,9 @@ static const uart_conf_t uart_config[] = {
|
||||
.rx_af = GPIO_AF4,
|
||||
.tx_af = GPIO_AF4,
|
||||
.bus = APB1,
|
||||
.irqn = USART2_IRQn
|
||||
.irqn = USART2_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
},
|
||||
{
|
||||
.dev = USART1,
|
||||
@ -91,7 +93,9 @@ static const uart_conf_t uart_config[] = {
|
||||
.rx_af = GPIO_AF4,
|
||||
.tx_af = GPIO_AF4,
|
||||
.bus = APB2,
|
||||
.irqn = USART1_IRQn
|
||||
.irqn = USART1_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -102,6 +102,8 @@ static const uart_conf_t uart_config[] = {
|
||||
.tx_af = GPIO_AF7,
|
||||
.bus = APB2,
|
||||
.irqn = USART1_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
#ifdef UART_USE_DMA
|
||||
.dma_stream = 6,
|
||||
.dma_chan = 4
|
||||
@ -116,6 +118,8 @@ static const uart_conf_t uart_config[] = {
|
||||
.tx_af = GPIO_AF8,
|
||||
.bus = APB1,
|
||||
.irqn = UART4_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
#ifdef UART_USE_DMA
|
||||
.dma_stream = 5,
|
||||
.dma_chan = 4
|
||||
|
||||
@ -85,7 +85,9 @@ static const uart_conf_t uart_config[] = {
|
||||
.rx_af = GPIO_AF4,
|
||||
.tx_af = GPIO_AF4,
|
||||
.bus = APB1,
|
||||
.irqn = USART2_IRQn
|
||||
.irqn = USART2_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -85,7 +85,9 @@ static const uart_conf_t uart_config[] = {
|
||||
.rx_af = GPIO_AF4,
|
||||
.tx_af = GPIO_AF4,
|
||||
.bus = APB1,
|
||||
.irqn = USART2_IRQn
|
||||
.irqn = USART2_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
},
|
||||
{
|
||||
.dev = USART1,
|
||||
@ -95,7 +97,9 @@ static const uart_conf_t uart_config[] = {
|
||||
.rx_af = GPIO_AF4,
|
||||
.tx_af = GPIO_AF4,
|
||||
.bus = APB2,
|
||||
.irqn = USART1_IRQn
|
||||
.irqn = USART1_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
FEATURES_PROVIDED += periph_adc
|
||||
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
|
||||
FEATURES_PROVIDED += periph_i2c
|
||||
FEATURES_PROVIDED += periph_lpuart
|
||||
FEATURES_PROVIDED += periph_pwm
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_spi
|
||||
|
||||
@ -85,7 +85,9 @@ static const uart_conf_t uart_config[] = {
|
||||
.rx_af = GPIO_AF4,
|
||||
.tx_af = GPIO_AF4,
|
||||
.bus = APB1,
|
||||
.irqn = USART2_IRQn
|
||||
.irqn = USART2_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
},
|
||||
{
|
||||
.dev = USART1,
|
||||
@ -95,23 +97,32 @@ static const uart_conf_t uart_config[] = {
|
||||
.rx_af = GPIO_AF4,
|
||||
.tx_af = GPIO_AF4,
|
||||
.bus = APB2,
|
||||
.irqn = USART1_IRQn
|
||||
.irqn = USART1_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
},
|
||||
#ifdef MODULE_PERIPH_LPUART
|
||||
{
|
||||
.dev = USART4,
|
||||
.rcc_mask = RCC_APB1ENR_USART4EN,
|
||||
.dev = LPUART1,
|
||||
.rcc_mask = RCC_APB1ENR_LPUART1EN,
|
||||
.rx_pin = GPIO_PIN(PORT_C, 11),
|
||||
.tx_pin = GPIO_PIN(PORT_C, 10),
|
||||
.rx_af = GPIO_AF6,
|
||||
.tx_af = GPIO_AF6,
|
||||
.rx_af = GPIO_AF0,
|
||||
.tx_af = GPIO_AF0,
|
||||
.bus = APB1,
|
||||
.irqn = USART4_5_IRQn
|
||||
.irqn = LPUART1_IRQn,
|
||||
.type = STM32_LPUART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
#define UART_0_ISR (isr_usart2)
|
||||
#define UART_1_ISR (isr_usart1)
|
||||
#define UART_2_ISR (isr_usart4_5)
|
||||
|
||||
#ifdef MODULE_PERIPH_LPUART
|
||||
#define UART_2_ISR (isr_rng_lpuart1)
|
||||
#endif
|
||||
|
||||
#define UART_NUMOF (sizeof(uart_config) / sizeof(uart_config[0]))
|
||||
/** @} */
|
||||
|
||||
@ -105,7 +105,9 @@ static const uart_conf_t uart_config[] = {
|
||||
.rx_af = GPIO_AF3,
|
||||
.tx_af = GPIO_AF7,
|
||||
.bus = APB1,
|
||||
.irqn = USART2_IRQn
|
||||
.irqn = USART2_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
},
|
||||
{
|
||||
.dev = USART1,
|
||||
@ -115,7 +117,9 @@ static const uart_conf_t uart_config[] = {
|
||||
.rx_af = GPIO_AF7,
|
||||
.tx_af = GPIO_AF7,
|
||||
.bus = APB2,
|
||||
.irqn = USART1_IRQn
|
||||
.irqn = USART1_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -1 +1,3 @@
|
||||
FEATURES_REQUIRED += periph_lpuart
|
||||
|
||||
include $(RIOTBOARD)/common/nucleo/Makefile.dep
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
# Put defined MCU peripherals here (in alphabetical order)
|
||||
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
|
||||
FEATURES_PROVIDED += periph_lpuart
|
||||
FEATURES_PROVIDED += periph_pwm
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_rtt
|
||||
|
||||
@ -2,10 +2,5 @@
|
||||
export CPU = stm32l4
|
||||
export CPU_MODEL = stm32l433rc
|
||||
|
||||
# stdio is not available over st-link but on the Arduino TX/RX pins
|
||||
# A serial to USB converter plugged to the host is required
|
||||
PORT_LINUX ?= /dev/ttyUSB0
|
||||
PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.usbmodem*)))
|
||||
|
||||
# load the common Makefile.include for Nucleo boards
|
||||
include $(RIOTBOARD)/common/nucleo64/Makefile.include
|
||||
|
||||
@ -106,6 +106,18 @@ static const timer_conf_t timer_config[] = {
|
||||
* @{
|
||||
*/
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{
|
||||
.dev = LPUART1,
|
||||
.rcc_mask = RCC_APB1ENR2_LPUART1EN,
|
||||
.rx_pin = GPIO_PIN(PORT_A, 3),
|
||||
.tx_pin = GPIO_PIN(PORT_A, 2),
|
||||
.rx_af = GPIO_AF8,
|
||||
.tx_af = GPIO_AF8,
|
||||
.bus = APB12,
|
||||
.irqn = LPUART1_IRQn,
|
||||
.type = STM32_LPUART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
},
|
||||
{
|
||||
.dev = USART1,
|
||||
.rcc_mask = RCC_APB2ENR_USART1EN,
|
||||
@ -115,6 +127,8 @@ static const uart_conf_t uart_config[] = {
|
||||
.tx_af = GPIO_AF7,
|
||||
.bus = APB2,
|
||||
.irqn = USART1_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
#ifdef UART_USE_DMA
|
||||
.dma_stream = 5,
|
||||
.dma_chan = 4
|
||||
@ -122,7 +136,8 @@ static const uart_conf_t uart_config[] = {
|
||||
}
|
||||
};
|
||||
|
||||
#define UART_0_ISR (isr_usart1)
|
||||
#define UART_0_ISR (isr_lpuart1)
|
||||
#define UART_1_ISR (isr_usart1)
|
||||
|
||||
#define UART_NUMOF (sizeof(uart_config) / sizeof(uart_config[0]))
|
||||
/** @} */
|
||||
|
||||
@ -118,6 +118,8 @@ static const uart_conf_t uart_config[] = {
|
||||
.tx_af = GPIO_AF7,
|
||||
.bus = APB1,
|
||||
.irqn = USART2_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
},
|
||||
{
|
||||
.dev = USART3,
|
||||
@ -128,6 +130,8 @@ static const uart_conf_t uart_config[] = {
|
||||
.tx_af = GPIO_AF7,
|
||||
.bus = APB1,
|
||||
.irqn = USART3_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -121,6 +121,8 @@ static const uart_conf_t uart_config[] = {
|
||||
.tx_af = GPIO_AF7,
|
||||
.bus = APB1,
|
||||
.irqn = USART2_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
#ifdef UART_USE_DMA
|
||||
.dma_stream = 6,
|
||||
.dma_chan = 4
|
||||
@ -135,6 +137,8 @@ static const uart_conf_t uart_config[] = {
|
||||
.tx_af = GPIO_AF7,
|
||||
.bus = APB1,
|
||||
.irqn = USART3_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
#ifdef UART_USE_DMA
|
||||
.dma_stream = 5,
|
||||
.dma_chan = 4
|
||||
@ -149,6 +153,8 @@ static const uart_conf_t uart_config[] = {
|
||||
.tx_af = GPIO_AF7,
|
||||
.bus = APB2,
|
||||
.irqn = USART1_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
#ifdef UART_USE_DMA
|
||||
.dma_stream = 4,
|
||||
.dma_chan = 4
|
||||
|
||||
@ -121,6 +121,8 @@ static const uart_conf_t uart_config[] = {
|
||||
.tx_af = GPIO_AF7,
|
||||
.bus = APB1,
|
||||
.irqn = USART3_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
#ifdef UART_USE_DMA
|
||||
.dma_stream = 5,
|
||||
.dma_chan = 4
|
||||
|
||||
@ -102,6 +102,8 @@ static const uart_conf_t uart_config[] = {
|
||||
.tx_af = GPIO_AF7,
|
||||
.bus = APB1,
|
||||
.irqn = USART2_IRQn,
|
||||
.type = STM32_USART,
|
||||
.clk_src = 0, /* Use APB clock */
|
||||
#ifdef UART_USE_DMA
|
||||
.dma_stream = 6,
|
||||
.dma_chan = 4
|
||||
|
||||
@ -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,19 +46,16 @@ 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 */
|
||||
/* configure TX pin */
|
||||
gpio_init(uart_config[uart].tx_pin, GPIO_OUT);
|
||||
/* set TX pin high to avoid garbage during further initialization */
|
||||
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
|
||||
}
|
||||
|
||||
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) \
|
||||
|
||||
@ -3,6 +3,7 @@ include ../Makefile.tests_common
|
||||
BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-uno nucleo-f031k6
|
||||
|
||||
FEATURES_REQUIRED = periph_uart
|
||||
FEATURES_OPTIONAL = periph_lpuart # STM32 L0 and L4 provides lpuart support
|
||||
|
||||
USEMODULE += shell
|
||||
USEMODULE += xtimer
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user