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:
parent
435d5d1a94
commit
6ab706913a
1 changed files with 105 additions and 6 deletions
|
@ -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 */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue