2016-03-03 15:33:20 +01:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016 Open-RnD Sp. z o.o.
|
|
|
|
*
|
2017-01-19 02:01:01 +01:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2016-03-03 15:33:20 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2016-11-17 17:00:49 +01:00
|
|
|
* @brief Driver for UART port on STM32 family processor.
|
2016-03-03 15:33:20 +01:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2018-09-14 19:43:44 +02:00
|
|
|
#ifndef ZEPHYR_DRIVERS_SERIAL_UART_STM32_H_
|
|
|
|
#define ZEPHYR_DRIVERS_SERIAL_UART_STM32_H_
|
2016-03-03 15:33:20 +01:00
|
|
|
|
2020-06-05 10:57:52 +02:00
|
|
|
#include <drivers/pinmux.h>
|
|
|
|
|
2016-03-03 15:33:20 +01:00
|
|
|
/* device config */
|
|
|
|
struct uart_stm32_config {
|
|
|
|
struct uart_device_config uconf;
|
|
|
|
/* clock subsystem driving this peripheral */
|
2017-01-23 17:55:57 +01:00
|
|
|
struct stm32_pclken pclken;
|
2019-02-08 18:39:35 +01:00
|
|
|
/* initial hardware flow control, 1 for RTS/CTS */
|
|
|
|
bool hw_flow_control;
|
2020-03-18 12:40:21 +01:00
|
|
|
/* initial parity, 0 for none, 1 for odd, 2 for even */
|
|
|
|
int parity;
|
2020-06-05 10:57:52 +02:00
|
|
|
const struct soc_gpio_pinctrl *pinctrl_list;
|
|
|
|
size_t pinctrl_list_size;
|
drivers: serial: stm32: use PM constraints to prevent suspension
In the current implementation the STM32 UART driver required to enable
`CONFIG_PM_DEVICE` when `CONFIG_PM=y` to function properly. The main
reason is that in some situations, like in polling mode, transmissions
are not fully synchronous. That is, a byte is pushed to the _queue_ if
it is empty and then the function returns without waiting for it to be
transmitted to the wire. This makes sense to make things like per-byte
transmission efficient. However, this introduces a problem: the system
may reach idle state, and so enter low power modes before the UART has
actually finished the last data in the queue. If this happens,
communications can be interrupted or garbage data may be put into the
UART line.
The proposed solution in this patch uses PM constraints to solve this
problem. For the IRQ/DMA case it is easy since we can set the constraint
before transmission start, and when the completion (TC) interrupt is
received we can clear it. However, the polling mode did not have the
capability to signal the completion. For this case, a simpler IRQ
routine is provided to just release the constraint. As a result, the PM
hooks are not required and so system can operate with just `CONFIG_PM`.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
2021-09-09 22:41:35 +02:00
|
|
|
#if defined(CONFIG_PM) \
|
|
|
|
&& !defined(CONFIG_UART_INTERRUPT_DRIVEN) \
|
|
|
|
&& !defined(CONFIG_UART_ASYNC_API)
|
|
|
|
uart_irq_config_func_t irq_config_func;
|
|
|
|
#endif
|
2016-03-03 15:33:20 +01:00
|
|
|
};
|
|
|
|
|
2021-01-16 17:44:24 +01:00
|
|
|
#ifdef CONFIG_UART_ASYNC_API
|
|
|
|
struct uart_dma_stream {
|
2021-03-01 11:59:57 +01:00
|
|
|
const struct device *dma_dev;
|
2021-01-16 17:44:24 +01:00
|
|
|
uint32_t dma_channel;
|
|
|
|
struct dma_config dma_cfg;
|
|
|
|
uint8_t priority;
|
|
|
|
bool src_addr_increment;
|
|
|
|
bool dst_addr_increment;
|
|
|
|
int fifo_threshold;
|
|
|
|
struct dma_block_config blk_cfg;
|
|
|
|
uint8_t *buffer;
|
|
|
|
size_t buffer_length;
|
|
|
|
size_t offset;
|
|
|
|
volatile size_t counter;
|
|
|
|
int32_t timeout;
|
2021-04-08 12:09:58 +02:00
|
|
|
struct k_work_delayable timeout_work;
|
2021-01-16 17:44:24 +01:00
|
|
|
bool enabled;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2016-03-03 15:33:20 +01:00
|
|
|
/* driver data */
|
|
|
|
struct uart_stm32_data {
|
2019-01-07 22:52:24 +01:00
|
|
|
/* Baud rate */
|
2020-05-27 18:26:57 +02:00
|
|
|
uint32_t baud_rate;
|
2016-03-03 15:33:20 +01:00
|
|
|
/* clock device */
|
2020-04-30 20:33:38 +02:00
|
|
|
const struct device *clock;
|
2016-03-13 19:37:25 +01:00
|
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
2018-07-16 20:12:26 +02:00
|
|
|
uart_irq_callback_user_data_t user_cb;
|
|
|
|
void *user_data;
|
2016-03-13 19:37:25 +01:00
|
|
|
#endif
|
2021-01-16 17:44:24 +01:00
|
|
|
|
|
|
|
#ifdef CONFIG_UART_ASYNC_API
|
|
|
|
const struct device *uart_dev;
|
|
|
|
uart_callback_t async_cb;
|
|
|
|
void *async_user_data;
|
|
|
|
struct uart_dma_stream dma_rx;
|
|
|
|
struct uart_dma_stream dma_tx;
|
|
|
|
uint8_t *rx_next_buffer;
|
|
|
|
size_t rx_next_buffer_len;
|
|
|
|
#endif
|
drivers/uart: stm32: Fix pm_constraint handling
Introduce new logic to set/release pm_constraint during serial TX
transactions.
First change is to introduce an internal flag and utility functions
to control the set/release constraint balancing per uart device.
This way, whatever the mix of transactions or API calls, we
ensure a single uart device can only do 1 or 0 to the PM state
constraint. Constraint can't then be set more than once, released w/o
having been set or released more than it was set.
The last part of the change reworks the triggers for constraints
set/release operations.
In order not to disturb driver operations, if irq driven mode or PM is
enabled, don't enable TC interrupt handling by default.
Instead, map the pm_constraint setting to the way TC flag is handled
in normal mode of operations (irq driven or async).
As a consequence, in irq driven mode, pm_constraint is set/released on
tx_enable/tx_disable api calls, which gives API user full control
on transaction protection vs low power operations.
Finally, we emulate the same behavior on TX poll transaction, by
enabling TC irq at the start of a stream and disabling TC irq once
stream is completed. This is controlled with a dedicated device flag.
Signed-off-by: Erwan Gouriou <erwan.gouriou@linaro.org>
2021-09-14 09:27:56 +02:00
|
|
|
#ifdef CONFIG_PM
|
|
|
|
bool tx_poll_stream_on;
|
|
|
|
bool pm_constraint_on;
|
|
|
|
#endif
|
2016-03-03 15:33:20 +01:00
|
|
|
};
|
|
|
|
|
2018-09-14 19:43:44 +02:00
|
|
|
#endif /* ZEPHYR_DRIVERS_SERIAL_UART_STM32_H_ */
|