drivers: serial: stm32: add wide data support

Add wide data support to STM32.
Validated interrupt driven code on an STM32H743.

Signed-off-by: Jeroen van Dooren <jeroen.van.dooren@nobleo.nl>
This commit is contained in:
Jeroen van Dooren 2023-02-06 09:54:20 +01:00 committed by Carles Cufí
commit 6ab706913a

View file

@ -645,26 +645,50 @@ static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, pol
irq_unlock(key);
}
static void uart_stm32_poll_in_u8(const struct uart_stm32_config *config, void *in)
static void poll_in_u8(const struct uart_stm32_config *config, void *in)
{
*((unsigned char *)in) = (unsigned char)LL_USART_ReceiveData8(config->usart);
}
static void uart_stm32_poll_out_u8(const struct uart_stm32_config *config, void *out)
static void poll_out_u8(const struct uart_stm32_config *config, void *out)
{
LL_USART_TransmitData8(config->usart, *((uint8_t *)out));
}
static int uart_stm32_poll_in(const struct device *dev, unsigned char *c)
{
return uart_stm32_poll_in_visitor(dev, (void *)c, uart_stm32_poll_in_u8);
return uart_stm32_poll_in_visitor(dev, (void *)c, poll_in_u8);
}
static void uart_stm32_poll_out(const struct device *dev, unsigned char c)
{
uart_stm32_poll_out_visitor(dev, (void *)&c, uart_stm32_poll_out_u8);
uart_stm32_poll_out_visitor(dev, (void *)&c, poll_out_u8);
}
#ifdef CONFIG_UART_WIDE_DATA
static void poll_out_u9(const struct uart_stm32_config *config, void *out)
{
LL_USART_TransmitData9(config->usart, *((uint16_t *)out));
}
static void poll_in_u9(const struct uart_stm32_config *config, void *in)
{
*((uint16_t *)in) = LL_USART_ReceiveData9(config->usart);
}
static int uart_stm32_poll_in_u16(const struct device *dev, uint16_t *in_u16)
{
return uart_stm32_poll_in_visitor(dev, (void *)in_u16, poll_in_u9);
}
static void uart_stm32_poll_out_u16(const struct device *dev, uint16_t out_u16)
{
uart_stm32_poll_out_visitor(dev, (void *)&out_u16, poll_out_u9);
}
#endif
static int uart_stm32_err_check(const struct device *dev)
{
const struct uart_stm32_config *config = dev->config;
@ -828,6 +852,47 @@ static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data, cons
fifo_read_with_u8);
}
#ifdef CONFIG_UART_WIDE_DATA
static void fifo_fill_with_u16(const struct uart_stm32_config *config,
const void *tx_data, const uint8_t offset)
{
const uint16_t *data = (const uint16_t *)tx_data;
/* Send a character (9bit) */
LL_USART_TransmitData9(config->usart, data[offset]);
}
static int uart_stm32_fifo_fill_u16(const struct device *dev, const uint16_t *tx_data, int size)
{
if (uart_stm32_ll2cfg_databits(uart_stm32_get_databits(dev), uart_stm32_get_parity(dev)) !=
UART_CFG_DATA_BITS_9) {
return -ENOTSUP;
}
return uart_stm32_fifo_fill_visitor(dev, (const void *)tx_data, size,
fifo_fill_with_u16);
}
static void fifo_read_with_u16(const struct uart_stm32_config *config, void *rx_data,
const uint8_t offset)
{
uint16_t *data = (uint16_t *)rx_data;
data[offset] = LL_USART_ReceiveData9(config->usart);
}
static int uart_stm32_fifo_read_u16(const struct device *dev, uint16_t *rx_data, const int size)
{
if (uart_stm32_ll2cfg_databits(uart_stm32_get_databits(dev), uart_stm32_get_parity(dev)) !=
UART_CFG_DATA_BITS_9) {
return -ENOTSUP;
}
return uart_stm32_fifo_read_visitor(dev, (void *)rx_data, size,
fifo_read_with_u16);
}
#endif
static void uart_stm32_irq_tx_enable(const struct device *dev)
{
const struct uart_stm32_config *config = dev->config;
@ -1670,11 +1735,36 @@ static int uart_stm32_async_init(const struct device *dev)
return 0;
}
#ifdef CONFIG_UART_WIDE_DATA
static int uart_stm32_async_tx_u16(const struct device *dev, const uint16_t *tx_data,
size_t buf_size, int32_t timeout)
{
return uart_stm32_async_tx(dev, (const uint8_t *)tx_data, buf_size * 2, timeout);
}
static int uart_stm32_async_rx_enable_u16(const struct device *dev, uint16_t *buf, size_t len,
int32_t timeout)
{
return uart_stm32_async_rx_enable(dev, (uint8_t *)buf, len * 2, timeout);
}
static int uart_stm32_async_rx_buf_rsp_u16(const struct device *dev, uint16_t *buf, size_t len)
{
return uart_stm32_async_rx_buf_rsp(dev, (uint8_t *)buf, len * 2);
}
#endif
#endif /* CONFIG_UART_ASYNC_API */
static const struct uart_driver_api uart_stm32_driver_api = {
.poll_in = uart_stm32_poll_in,
.poll_out = uart_stm32_poll_out,
#ifdef CONFIG_UART_WIDE_DATA
.poll_in_u16 = uart_stm32_poll_in_u16,
.poll_out_u16 = uart_stm32_poll_out_u16,
#endif
.err_check = uart_stm32_err_check,
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
.configure = uart_stm32_configure,
@ -1683,6 +1773,10 @@ static const struct uart_driver_api uart_stm32_driver_api = {
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
.fifo_fill = uart_stm32_fifo_fill,
.fifo_read = uart_stm32_fifo_read,
#ifdef CONFIG_UART_WIDE_DATA
.fifo_fill_u16 = uart_stm32_fifo_fill_u16,
.fifo_read_u16 = uart_stm32_fifo_read_u16,
#endif
.irq_tx_enable = uart_stm32_irq_tx_enable,
.irq_tx_disable = uart_stm32_irq_tx_disable,
.irq_tx_ready = uart_stm32_irq_tx_ready,
@ -1695,7 +1789,7 @@ static const struct uart_driver_api uart_stm32_driver_api = {
.irq_is_pending = uart_stm32_irq_is_pending,
.irq_update = uart_stm32_irq_update,
.irq_callback_set = uart_stm32_irq_callback_set,
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
#ifdef CONFIG_UART_ASYNC_API
.callback_set = uart_stm32_async_callback_set,
.tx = uart_stm32_async_tx,
@ -1703,7 +1797,12 @@ static const struct uart_driver_api uart_stm32_driver_api = {
.rx_enable = uart_stm32_async_rx_enable,
.rx_disable = uart_stm32_async_rx_disable,
.rx_buf_rsp = uart_stm32_async_rx_buf_rsp,
#endif /* CONFIG_UART_ASYNC_API */
#ifdef CONFIG_UART_WIDE_DATA
.tx_u16 = uart_stm32_async_tx_u16,
.rx_enable_u16 = uart_stm32_async_rx_enable_u16,
.rx_buf_rsp_u16 = uart_stm32_async_rx_buf_rsp_u16,
#endif
#endif /* CONFIG_UART_ASYNC_API */
};
/**