2017-05-10 17:12:12 -07:00
|
|
|
/*
|
2019-08-21 23:54:00 +02:00
|
|
|
* Copyright (c) 2019 Mohamed ElShahawi (extremegtx@hotmail.com)
|
2017-05-10 17:12:12 -07:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2020-03-24 16:00:26 -05:00
|
|
|
#define DT_DRV_COMPAT espressif_esp32_uart
|
|
|
|
|
2017-08-18 15:15:47 -07:00
|
|
|
/* Include esp-idf headers first to avoid redefining BIT() macro */
|
2020-08-03 20:23:18 +05:30
|
|
|
#include <esp32/rom/ets_sys.h>
|
2019-08-21 23:54:00 +02:00
|
|
|
#include <soc/dport_reg.h>
|
2017-08-18 15:15:47 -07:00
|
|
|
|
2020-08-03 20:23:18 +05:30
|
|
|
#include <esp32/rom/gpio.h>
|
2019-08-21 23:54:00 +02:00
|
|
|
|
|
|
|
#include <soc/gpio_sig_map.h>
|
2021-05-06 13:40:44 -03:00
|
|
|
#include <soc/uart_reg.h>
|
2019-08-21 23:54:00 +02:00
|
|
|
|
|
|
|
#include <device.h>
|
2017-09-15 16:52:36 -07:00
|
|
|
#include <soc.h>
|
2019-06-25 15:54:01 -04:00
|
|
|
#include <drivers/uart.h>
|
2021-06-09 19:52:31 -03:00
|
|
|
#include <drivers/interrupt_controller/intc_esp32.h>
|
2020-05-28 21:01:49 +02:00
|
|
|
#include <drivers/clock_control.h>
|
2017-05-10 17:12:12 -07:00
|
|
|
#include <errno.h>
|
2019-08-21 23:54:00 +02:00
|
|
|
#include <sys/util.h>
|
2021-01-15 12:03:57 +05:30
|
|
|
#include <esp_attr.h>
|
2019-08-21 23:54:00 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ESP32 UARTx register map structure
|
|
|
|
*/
|
|
|
|
struct uart_esp32_regs_t {
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t fifo;
|
|
|
|
uint32_t int_raw;
|
|
|
|
uint32_t int_st;
|
|
|
|
uint32_t int_ena;
|
|
|
|
uint32_t int_clr;
|
|
|
|
uint32_t clk_div;
|
|
|
|
uint32_t auto_baud;
|
|
|
|
uint32_t status;
|
|
|
|
uint32_t conf0;
|
|
|
|
uint32_t conf1;
|
|
|
|
uint32_t lowpulse;
|
|
|
|
uint32_t highpulse;
|
|
|
|
uint32_t rxd_cnt;
|
|
|
|
uint32_t flow_conf;
|
|
|
|
uint32_t sleep_conf;
|
|
|
|
uint32_t swfc_conf;
|
|
|
|
uint32_t idle_conf;
|
|
|
|
uint32_t rs485_conf;
|
|
|
|
uint32_t at_cmd_precnt;
|
|
|
|
uint32_t at_cmd_postcnt;
|
|
|
|
uint32_t at_cmd_gaptout;
|
|
|
|
uint32_t at_cmd_char;
|
|
|
|
uint32_t mem_conf;
|
|
|
|
uint32_t mem_tx_status;
|
|
|
|
uint32_t mem_rx_status;
|
|
|
|
uint32_t mem_cnt_status;
|
|
|
|
uint32_t pospulse;
|
|
|
|
uint32_t negpulse;
|
|
|
|
uint32_t reserved_0;
|
|
|
|
uint32_t reserved_1;
|
|
|
|
uint32_t date;
|
|
|
|
uint32_t id;
|
2019-08-21 23:54:00 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct uart_esp32_config {
|
|
|
|
|
|
|
|
struct uart_device_config dev_conf;
|
2021-02-11 19:21:32 -06:00
|
|
|
const struct device *clock_dev;
|
2019-08-21 23:54:00 +02:00
|
|
|
|
|
|
|
const struct {
|
|
|
|
int tx_out;
|
|
|
|
int rx_in;
|
|
|
|
int rts_out;
|
|
|
|
int cts_in;
|
|
|
|
} signals;
|
|
|
|
|
|
|
|
const struct {
|
|
|
|
int tx;
|
|
|
|
int rx;
|
|
|
|
int rts;
|
|
|
|
int cts;
|
|
|
|
} pins;
|
|
|
|
|
2021-05-12 08:06:20 -03:00
|
|
|
const clock_control_subsys_t clock_subsys;
|
2019-08-21 23:54:00 +02:00
|
|
|
|
2021-06-09 19:52:31 -03:00
|
|
|
int irq_source;
|
2019-08-21 23:54:00 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/* driver data */
|
|
|
|
struct uart_esp32_data {
|
|
|
|
struct uart_config uart_config;
|
|
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
|
|
|
uart_irq_callback_user_data_t irq_cb;
|
|
|
|
void *irq_cb_data;
|
|
|
|
#endif
|
2021-06-09 19:52:31 -03:00
|
|
|
int irq_line;
|
2019-08-21 23:54:00 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#define DEV_CFG(dev) \
|
2020-05-28 20:44:16 +02:00
|
|
|
((const struct uart_esp32_config *const)(dev)->config)
|
2019-08-21 23:54:00 +02:00
|
|
|
#define DEV_DATA(dev) \
|
2020-05-28 21:23:02 +02:00
|
|
|
((struct uart_esp32_data *)(dev)->data)
|
2019-08-21 23:54:00 +02:00
|
|
|
#define DEV_BASE(dev) \
|
|
|
|
((volatile struct uart_esp32_regs_t *)(DEV_CFG(dev))->dev_conf.base)
|
|
|
|
|
|
|
|
#define UART_TXFIFO_COUNT(status_reg) ((status_reg >> 16) & 0xFF)
|
|
|
|
#define UART_RXFIFO_COUNT(status_reg) ((status_reg >> 0) & 0xFF)
|
|
|
|
|
|
|
|
#define UART_FIFO_LIMIT 127U
|
|
|
|
#define UART_TX_FIFO_THRESH 0x1
|
|
|
|
#define UART_RX_FIFO_THRESH 0x1
|
2017-05-10 17:12:12 -07:00
|
|
|
|
2019-08-21 23:54:00 +02:00
|
|
|
#define UART_GET_PARITY_ERR(reg) ((reg >> 2) & 0x1)
|
|
|
|
#define UART_GET_FRAME_ERR(reg) ((reg >> 3) & 0x1)
|
|
|
|
|
|
|
|
#define UART_GET_PARITY(conf0_reg) ((conf0_reg >> 0) & 0x1)
|
|
|
|
#define UART_GET_PARITY_EN(conf0_reg) ((conf0_reg >> 1) & 0x1)
|
|
|
|
#define UART_GET_DATA_BITS(conf0_reg) ((conf0_reg >> 2) & 0x3)
|
|
|
|
#define UART_GET_STOP_BITS(conf0_reg) ((conf0_reg >> 4) & 0x3)
|
|
|
|
#define UART_GET_TX_FLOW(conf0_reg) ((conf0_reg >> 15) & 0x1)
|
|
|
|
#define UART_GET_RX_FLOW(conf1_reg) ((conf1_reg >> 23) & 0x1)
|
|
|
|
|
|
|
|
/* FIXME: This should be removed when interrupt support added to ESP32 dts */
|
2020-03-24 19:37:52 -05:00
|
|
|
#define INST_0_ESPRESSIF_ESP32_UART_IRQ_0 12
|
|
|
|
#define INST_1_ESPRESSIF_ESP32_UART_IRQ_0 17
|
|
|
|
#define INST_2_ESPRESSIF_ESP32_UART_IRQ_0 18
|
2019-08-21 23:54:00 +02:00
|
|
|
|
|
|
|
/* ESP-IDF Naming is not consistent for UART0 with UART1/2 */
|
|
|
|
#define DPORT_UART0_CLK_EN DPORT_UART_CLK_EN
|
|
|
|
#define DPORT_UART0_RST DPORT_UART_RST
|
|
|
|
|
2021-06-09 19:52:31 -03:00
|
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
|
|
|
void uart_esp32_isr(void *arg);
|
|
|
|
#endif
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_poll_in(const struct device *dev, unsigned char *p_char)
|
2017-05-10 17:12:12 -07:00
|
|
|
{
|
|
|
|
|
2019-08-21 23:54:00 +02:00
|
|
|
if (UART_RXFIFO_COUNT(DEV_BASE(dev)->status) == 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*p_char = DEV_BASE(dev)->fifo;
|
|
|
|
return 0;
|
2017-05-10 17:12:12 -07:00
|
|
|
}
|
|
|
|
|
2021-01-15 12:03:57 +05:30
|
|
|
static IRAM_ATTR void uart_esp32_poll_out(const struct device *dev,
|
2019-08-21 23:54:00 +02:00
|
|
|
unsigned char c)
|
2017-05-10 17:12:12 -07:00
|
|
|
{
|
2019-08-21 23:54:00 +02:00
|
|
|
/* Wait for space in FIFO */
|
|
|
|
while (UART_TXFIFO_COUNT(DEV_BASE(dev)->status) >= UART_FIFO_LIMIT) {
|
|
|
|
; /* Wait */
|
|
|
|
}
|
2017-05-10 17:12:12 -07:00
|
|
|
|
2019-08-21 23:54:00 +02:00
|
|
|
/* Send a character */
|
2020-05-27 11:26:57 -05:00
|
|
|
DEV_BASE(dev)->fifo = (uint32_t)c;
|
2019-08-21 23:54:00 +02:00
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_err_check(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t err = UART_GET_PARITY_ERR(DEV_BASE(dev)->int_st)
|
2019-08-21 23:54:00 +02:00
|
|
|
| UART_GET_FRAME_ERR(DEV_BASE(dev)->int_st);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-05-26 12:33:37 -07:00
|
|
|
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_config_get(const struct device *dev,
|
|
|
|
struct uart_config *cfg)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
struct uart_esp32_data *data = DEV_DATA(dev);
|
|
|
|
|
|
|
|
cfg->baudrate = data->uart_config.baudrate;
|
|
|
|
|
|
|
|
if (UART_GET_PARITY_EN(DEV_BASE(dev)->conf0)) {
|
|
|
|
cfg->parity = UART_GET_PARITY(DEV_BASE(dev)->conf0);
|
|
|
|
} else {
|
|
|
|
cfg->parity = UART_CFG_PARITY_NONE;
|
2017-05-10 17:12:12 -07:00
|
|
|
}
|
2019-08-21 23:54:00 +02:00
|
|
|
|
|
|
|
cfg->stop_bits = UART_GET_STOP_BITS(DEV_BASE(dev)->conf0);
|
|
|
|
cfg->data_bits = UART_GET_DATA_BITS(DEV_BASE(dev)->conf0);
|
|
|
|
|
|
|
|
if (UART_GET_TX_FLOW(DEV_BASE(dev)->conf0)) {
|
|
|
|
cfg->flow_ctrl = UART_CFG_FLOW_CTRL_RTS_CTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UART_GET_RX_FLOW(DEV_BASE(dev)->conf1)) {
|
|
|
|
cfg->flow_ctrl = UART_CFG_FLOW_CTRL_DTR_DSR;
|
|
|
|
}
|
|
|
|
return 0;
|
2017-05-10 17:12:12 -07:00
|
|
|
}
|
2021-05-26 12:33:37 -07:00
|
|
|
#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
|
2017-05-10 17:12:12 -07:00
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_set_baudrate(const struct device *dev, int baudrate)
|
2017-05-10 17:12:12 -07:00
|
|
|
{
|
2020-05-28 21:01:49 +02:00
|
|
|
uint32_t sys_clk_freq = 0;
|
|
|
|
|
2021-02-11 19:21:32 -06:00
|
|
|
if (clock_control_get_rate(DEV_CFG(dev)->clock_dev,
|
2021-05-12 08:06:20 -03:00
|
|
|
DEV_CFG(dev)->clock_subsys,
|
2020-05-28 21:01:49 +02:00
|
|
|
&sys_clk_freq)) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t clk_div = (((sys_clk_freq) << 4) / baudrate);
|
2017-05-10 17:12:12 -07:00
|
|
|
|
2019-08-21 23:54:00 +02:00
|
|
|
while (UART_TXFIFO_COUNT(DEV_BASE(dev)->status)) {
|
|
|
|
; /* Wait */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (clk_div < 16) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEV_BASE(dev)->clk_div = ((clk_div >> 4) | (clk_div & 0xf));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_configure_pins(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
const struct uart_esp32_config *const cfg = DEV_CFG(dev);
|
|
|
|
|
2021-10-03 19:30:02 -03:00
|
|
|
esp_rom_gpio_matrix_out(cfg->pins.tx,
|
2019-08-21 23:54:00 +02:00
|
|
|
cfg->signals.tx_out,
|
|
|
|
false,
|
|
|
|
false);
|
|
|
|
|
2021-10-03 19:30:02 -03:00
|
|
|
esp_rom_gpio_matrix_in(cfg->pins.rx,
|
2019-08-21 23:54:00 +02:00
|
|
|
cfg->signals.rx_in,
|
|
|
|
false);
|
|
|
|
|
2019-08-23 00:53:22 +02:00
|
|
|
if (cfg->pins.cts) {
|
2021-10-03 19:30:02 -03:00
|
|
|
esp_rom_gpio_matrix_out(cfg->pins.cts,
|
2019-08-23 00:53:22 +02:00
|
|
|
cfg->signals.cts_in,
|
|
|
|
false,
|
|
|
|
false);
|
|
|
|
}
|
2019-08-21 23:54:00 +02:00
|
|
|
|
2019-08-23 00:53:22 +02:00
|
|
|
if (cfg->pins.rts) {
|
2021-10-03 19:30:02 -03:00
|
|
|
esp_rom_gpio_matrix_in(cfg->pins.rts,
|
2019-08-23 00:53:22 +02:00
|
|
|
cfg->signals.rts_out,
|
|
|
|
false);
|
|
|
|
}
|
2017-05-17 18:22:43 +08:00
|
|
|
|
2017-05-10 17:12:12 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_configure(const struct device *dev,
|
2019-08-21 23:54:00 +02:00
|
|
|
const struct uart_config *cfg)
|
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t conf0 = UART_TICK_REF_ALWAYS_ON;
|
|
|
|
uint32_t conf1 = (UART_RX_FIFO_THRESH << UART_RXFIFO_FULL_THRHD_S)
|
2019-08-21 23:54:00 +02:00
|
|
|
| (UART_TX_FIFO_THRESH << UART_TXFIFO_EMPTY_THRHD_S);
|
|
|
|
|
|
|
|
uart_esp32_configure_pins(dev);
|
2021-05-12 08:06:20 -03:00
|
|
|
clock_control_on(DEV_CFG(dev)->clock_dev, DEV_CFG(dev)->clock_subsys);
|
2019-08-21 23:54:00 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset RX Buffer by reading all received bytes
|
|
|
|
* Hardware Reset functionality can't be used with UART 1/2
|
|
|
|
*/
|
|
|
|
while (UART_RXFIFO_COUNT(DEV_BASE(dev)->status) != 0) {
|
|
|
|
(void) DEV_BASE(dev)->fifo;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (cfg->parity) {
|
|
|
|
case UART_CFG_PARITY_NONE:
|
|
|
|
conf0 &= ~(UART_PARITY_EN);
|
|
|
|
conf0 &= ~(UART_PARITY);
|
|
|
|
break;
|
|
|
|
case UART_CFG_PARITY_EVEN:
|
|
|
|
conf0 &= ~(UART_PARITY);
|
|
|
|
break;
|
|
|
|
case UART_CFG_PARITY_ODD:
|
|
|
|
conf0 |= UART_PARITY;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (cfg->stop_bits) {
|
|
|
|
case UART_CFG_STOP_BITS_1:
|
|
|
|
case UART_CFG_STOP_BITS_1_5:
|
|
|
|
case UART_CFG_STOP_BITS_2:
|
|
|
|
conf0 |= cfg->stop_bits << UART_STOP_BIT_NUM_S;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cfg->data_bits <= UART_CFG_DATA_BITS_8) {
|
|
|
|
conf0 |= cfg->data_bits << UART_BIT_NUM_S;
|
|
|
|
} else {
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (cfg->flow_ctrl) {
|
|
|
|
case UART_CFG_FLOW_CTRL_NONE:
|
|
|
|
conf0 &= ~(UART_TX_FLOW_EN);
|
|
|
|
conf1 &= ~(UART_RX_FLOW_EN);
|
|
|
|
break;
|
|
|
|
case UART_CFG_FLOW_CTRL_RTS_CTS:
|
|
|
|
conf0 |= UART_TX_FLOW_EN;
|
|
|
|
conf1 |= UART_RX_FLOW_EN;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uart_esp32_set_baudrate(dev, cfg->baudrate)) {
|
|
|
|
DEV_DATA(dev)->uart_config.baudrate = cfg->baudrate;
|
|
|
|
} else {
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEV_BASE(dev)->conf0 = conf0;
|
|
|
|
DEV_BASE(dev)->conf1 = conf1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_init(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
uart_esp32_configure(dev, &DEV_DATA(dev)->uart_config);
|
|
|
|
|
|
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
2021-06-09 19:52:31 -03:00
|
|
|
DEV_DATA(dev)->irq_line =
|
|
|
|
esp_intr_alloc(DEV_CFG(dev)->irq_source, 0, uart_esp32_isr, (void *)dev, NULL);
|
2019-08-21 23:54:00 +02:00
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_fifo_fill(const struct device *dev,
|
2020-05-27 11:26:57 -05:00
|
|
|
const uint8_t *tx_data, int len)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t num_tx = 0U;
|
2019-08-21 23:54:00 +02:00
|
|
|
|
|
|
|
while ((len - num_tx > 0) &&
|
|
|
|
UART_TXFIFO_COUNT(DEV_BASE(dev)->status) < UART_FIFO_LIMIT) {
|
2020-05-27 11:26:57 -05:00
|
|
|
DEV_BASE(dev)->fifo = (uint32_t)tx_data[num_tx++];
|
2019-08-21 23:54:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return num_tx;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_fifo_read(const struct device *dev,
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t *rx_data, const int len)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t num_rx = 0U;
|
2019-08-21 23:54:00 +02:00
|
|
|
|
|
|
|
while ((len - num_rx > 0) &&
|
|
|
|
(UART_RXFIFO_COUNT(DEV_BASE(dev)->status) != 0)) {
|
|
|
|
rx_data[num_rx++] = DEV_BASE(dev)->fifo;
|
|
|
|
}
|
|
|
|
|
|
|
|
return num_rx;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static void uart_esp32_irq_tx_enable(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
DEV_BASE(dev)->int_clr |= UART_TXFIFO_EMPTY_INT_ENA;
|
|
|
|
DEV_BASE(dev)->int_ena |= UART_TXFIFO_EMPTY_INT_ENA;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static void uart_esp32_irq_tx_disable(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
DEV_BASE(dev)->int_ena &= ~(UART_TXFIFO_EMPTY_INT_ENA);
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_irq_tx_ready(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
return (UART_TXFIFO_COUNT(DEV_BASE(dev)->status) < UART_FIFO_LIMIT);
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static void uart_esp32_irq_rx_enable(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
DEV_BASE(dev)->int_clr |= UART_RXFIFO_FULL_INT_ENA;
|
|
|
|
DEV_BASE(dev)->int_ena |= UART_RXFIFO_FULL_INT_ENA;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static void uart_esp32_irq_rx_disable(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
DEV_BASE(dev)->int_ena &= ~(UART_RXFIFO_FULL_INT_ENA);
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_irq_tx_complete(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
/* check if TX FIFO is empty */
|
|
|
|
return (UART_TXFIFO_COUNT(DEV_BASE(dev)->status) == 0 ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_irq_rx_ready(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
return (UART_RXFIFO_COUNT(DEV_BASE(dev)->status) > 0);
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static void uart_esp32_irq_err_enable(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
/* enable framing, parity */
|
|
|
|
DEV_BASE(dev)->int_ena |= UART_FRM_ERR_INT_ENA
|
|
|
|
| UART_PARITY_ERR_INT_ENA;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static void uart_esp32_irq_err_disable(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
DEV_BASE(dev)->int_ena &= ~(UART_FRM_ERR_INT_ENA);
|
|
|
|
DEV_BASE(dev)->int_ena &= ~(UART_PARITY_ERR_INT_ENA);
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_irq_is_pending(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
return uart_esp32_irq_rx_ready(dev) || uart_esp32_irq_tx_ready(dev);
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int uart_esp32_irq_update(const struct device *dev)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
|
|
|
DEV_BASE(dev)->int_clr |= UART_RXFIFO_FULL_INT_ENA;
|
|
|
|
DEV_BASE(dev)->int_clr |= UART_TXFIFO_EMPTY_INT_ENA;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static void uart_esp32_irq_callback_set(const struct device *dev,
|
2019-08-21 23:54:00 +02:00
|
|
|
uart_irq_callback_user_data_t cb,
|
|
|
|
void *cb_data)
|
|
|
|
{
|
|
|
|
DEV_DATA(dev)->irq_cb = cb;
|
|
|
|
DEV_DATA(dev)->irq_cb_data = cb_data;
|
|
|
|
}
|
|
|
|
|
2021-06-09 19:52:31 -03:00
|
|
|
void uart_esp32_isr(void *arg)
|
2019-08-21 23:54:00 +02:00
|
|
|
{
|
2021-06-09 19:52:31 -03:00
|
|
|
const struct device *dev = (const struct device *)arg;
|
2019-08-21 23:54:00 +02:00
|
|
|
struct uart_esp32_data *data = DEV_DATA(dev);
|
|
|
|
|
|
|
|
/* Verify if the callback has been registered */
|
|
|
|
if (data->irq_cb) {
|
2020-06-24 15:47:15 +02:00
|
|
|
data->irq_cb(dev, data->irq_cb_data);
|
2019-08-21 23:54:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
|
|
|
|
2021-01-15 12:03:57 +05:30
|
|
|
static const DRAM_ATTR struct uart_driver_api uart_esp32_api = {
|
2019-08-21 23:54:00 +02:00
|
|
|
.poll_in = uart_esp32_poll_in,
|
|
|
|
.poll_out = uart_esp32_poll_out,
|
|
|
|
.err_check = uart_esp32_err_check,
|
2021-05-26 12:33:37 -07:00
|
|
|
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
|
2019-08-21 23:54:00 +02:00
|
|
|
.configure = uart_esp32_configure,
|
|
|
|
.config_get = uart_esp32_config_get,
|
2021-05-26 12:33:37 -07:00
|
|
|
#endif
|
2019-08-21 23:54:00 +02:00
|
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
|
|
|
.fifo_fill = uart_esp32_fifo_fill,
|
|
|
|
.fifo_read = uart_esp32_fifo_read,
|
|
|
|
.irq_tx_enable = uart_esp32_irq_tx_enable,
|
|
|
|
.irq_tx_disable = uart_esp32_irq_tx_disable,
|
|
|
|
.irq_tx_ready = uart_esp32_irq_tx_ready,
|
|
|
|
.irq_rx_enable = uart_esp32_irq_rx_enable,
|
|
|
|
.irq_rx_disable = uart_esp32_irq_rx_disable,
|
|
|
|
.irq_tx_complete = uart_esp32_irq_tx_complete,
|
|
|
|
.irq_rx_ready = uart_esp32_irq_rx_ready,
|
|
|
|
.irq_err_enable = uart_esp32_irq_err_enable,
|
|
|
|
.irq_err_disable = uart_esp32_irq_err_disable,
|
|
|
|
.irq_is_pending = uart_esp32_irq_is_pending,
|
|
|
|
.irq_update = uart_esp32_irq_update,
|
|
|
|
.irq_callback_set = uart_esp32_irq_callback_set,
|
|
|
|
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
2017-05-10 17:12:12 -07:00
|
|
|
};
|
|
|
|
|
2019-12-17 09:59:57 +01:00
|
|
|
#define ESP32_UART_INIT(idx) \
|
2021-01-15 12:03:57 +05:30
|
|
|
static const DRAM_ATTR struct uart_esp32_config uart_esp32_cfg_port_##idx = { \
|
2019-12-17 09:59:57 +01:00
|
|
|
.dev_conf = { \
|
|
|
|
.base = \
|
2021-05-12 08:06:20 -03:00
|
|
|
(uint8_t *)DT_REG_ADDR(DT_NODELABEL(uart##idx)), \
|
2019-12-17 09:59:57 +01:00
|
|
|
}, \
|
2020-05-28 21:01:49 +02:00
|
|
|
\
|
2021-05-12 08:06:20 -03:00
|
|
|
.clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_NODELABEL(uart##idx))), \
|
2020-05-28 21:01:49 +02:00
|
|
|
\
|
2019-12-17 09:59:57 +01:00
|
|
|
.signals = { \
|
|
|
|
.tx_out = U##idx##TXD_OUT_IDX, \
|
|
|
|
.rx_in = U##idx##RXD_IN_IDX, \
|
|
|
|
.rts_out = U##idx##RTS_OUT_IDX, \
|
|
|
|
.cts_in = U##idx##CTS_IN_IDX, \
|
|
|
|
}, \
|
|
|
|
\
|
|
|
|
.pins = { \
|
2021-05-12 08:06:20 -03:00
|
|
|
.tx = DT_PROP(DT_NODELABEL(uart##idx), tx_pin), \
|
|
|
|
.rx = DT_PROP(DT_NODELABEL(uart##idx), rx_pin), \
|
2019-12-17 09:59:57 +01:00
|
|
|
IF_ENABLED( \
|
2021-05-12 08:06:20 -03:00
|
|
|
DT_PROP(DT_NODELABEL(uart##idx), hw_flow_control), \
|
|
|
|
(.rts = DT_PROP(DT_NODELABEL(uart##idx), rts_pin), \
|
|
|
|
.cts = DT_PROP(DT_NODELABEL(uart##idx), cts_pin), \
|
2019-12-17 09:59:57 +01:00
|
|
|
)) \
|
|
|
|
}, \
|
2020-05-28 21:01:49 +02:00
|
|
|
\
|
2021-05-12 08:06:20 -03:00
|
|
|
.clock_subsys = (clock_control_subsys_t)DT_CLOCKS_CELL(DT_NODELABEL(uart##idx), offset), \
|
2021-06-09 19:52:31 -03:00
|
|
|
.irq_source = DT_IRQN(DT_NODELABEL(uart##idx)) \
|
2019-12-17 09:59:57 +01:00
|
|
|
}; \
|
|
|
|
\
|
|
|
|
static struct uart_esp32_data uart_esp32_data_##idx = { \
|
|
|
|
.uart_config = { \
|
2021-05-12 08:06:20 -03:00
|
|
|
.baudrate = DT_PROP(DT_NODELABEL(uart##idx), current_speed),\
|
2019-12-17 09:59:57 +01:00
|
|
|
.parity = UART_CFG_PARITY_NONE, \
|
|
|
|
.stop_bits = UART_CFG_STOP_BITS_1, \
|
|
|
|
.data_bits = UART_CFG_DATA_BITS_8, \
|
|
|
|
.flow_ctrl = IS_ENABLED( \
|
2021-05-12 08:06:20 -03:00
|
|
|
DT_PROP(DT_NODELABEL(uart##idx), hw_flow_control)) ?\
|
2019-12-17 09:59:57 +01:00
|
|
|
UART_CFG_FLOW_CTRL_RTS_CTS : UART_CFG_FLOW_CTRL_NONE \
|
|
|
|
} \
|
|
|
|
}; \
|
|
|
|
\
|
2021-05-12 08:06:20 -03:00
|
|
|
DEVICE_DT_DEFINE(DT_NODELABEL(uart##idx), \
|
|
|
|
&uart_esp32_init, \
|
|
|
|
NULL, \
|
2019-12-17 09:59:57 +01:00
|
|
|
&uart_esp32_data_##idx, \
|
|
|
|
&uart_esp32_cfg_port_##idx, \
|
|
|
|
PRE_KERNEL_1, \
|
|
|
|
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
|
2021-06-09 19:52:31 -03:00
|
|
|
&uart_esp32_api);
|
2019-08-21 23:54:00 +02:00
|
|
|
|
2021-05-12 08:06:20 -03:00
|
|
|
#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart0), okay)
|
|
|
|
ESP32_UART_INIT(0);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart1), okay)
|
|
|
|
ESP32_UART_INIT(1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart2), okay)
|
|
|
|
ESP32_UART_INIT(2);
|
|
|
|
#endif
|