Skip to content

Commit 7185cbf

Browse files
committed
[nrf fromlist] drivers: serial: nrfx_uarte: Add support for frame timeout
Frame timeout is a hardware feature present in newer versions of UARTE (e.g. in NRF54X platforms) for detecting idle state on RX line and ending RX after configurable timeout. Upstream PR: zephyrproject-rtos/zephyr#78887 Signed-off-by: Krzysztof Chruściński <[email protected]>
1 parent 3256150 commit 7185cbf

File tree

2 files changed

+60
-6
lines changed

2 files changed

+60
-6
lines changed

drivers/serial/Kconfig.nrfx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,8 @@ config UART_NRFX_UARTE
3131
config UART_NRFX_UARTE_LEGACY_SHIM
3232
bool "Legacy UARTE shim"
3333
depends on UART_NRFX_UARTE
34-
depends on !SOC_SERIES_NRF54LX
3534
depends on !SOC_SERIES_NRF54HX || RISCV
3635
depends on !SOC_SERIES_NRF92X || RISCV
37-
# New shim takes more ROM. Until it is fixed use legacy shim.
3836
default y
3937

4038
config UART_NRFX_UARTE_ENHANCED_RX

drivers/serial/uart_nrfx_uarte.c

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, 0);
8686
#define UARTE_HAS_ENDTX_STOPTX_SHORT 1
8787
#endif
8888

89+
#if (UARTE_FOR_EACH_INSTANCE(INSTANCE_PROP, (+), (0), frame_timeout_supported)) == \
90+
(UARTE_FOR_EACH_INSTANCE(INSTANCE_PRESENT, (+), (0), frame_timeout_supported))
91+
#define UARTE_HAS_FRAME_TIMEOUT 1
92+
#endif
93+
8994
/*
9095
* RX timeout is divided into time slabs, this define tells how many divisions
9196
* should be made. More divisions - higher timeout accuracy and processor usage.
@@ -116,7 +121,9 @@ struct uarte_async_rx {
116121
uint8_t *next_buf;
117122
size_t next_buf_len;
118123
#ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX
124+
#if !defined(UARTE_HAS_FRAME_TIMEOUT)
119125
uint32_t idle_cnt;
126+
#endif
120127
k_timeout_t timeout;
121128
#else
122129
uint32_t total_byte_cnt; /* Total number of bytes received */
@@ -234,6 +241,9 @@ struct uarte_nrfx_config {
234241
uint32_t clock_freq;
235242
uint32_t baudrate_div;
236243
#else
244+
#ifdef UARTE_HAS_FRAME_TIMEOUT
245+
uint32_t baudrate;
246+
#endif
237247
nrf_uarte_baudrate_t nrf_baudrate;
238248
nrf_uarte_config_t hw_config;
239249
#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
@@ -440,6 +450,9 @@ static int uarte_nrfx_configure(const struct device *dev,
440450
return -ENOTSUP;
441451
}
442452

453+
#ifdef UARTE_HAS_FRAME_TIMEOUT
454+
uarte_cfg.frame_timeout = NRF_UARTE_FRAME_TIMEOUT_EN;
455+
#endif
443456
nrf_uarte_configure(get_uarte_instance(dev), &uarte_cfg);
444457

445458
data->uart_config = *cfg;
@@ -668,7 +681,8 @@ static int uarte_nrfx_init(const struct device *dev)
668681
NRF_UARTE_INT_RXSTARTED_MASK |
669682
NRF_UARTE_INT_ERROR_MASK |
670683
NRF_UARTE_INT_RXTO_MASK |
671-
(IS_ENABLED(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) ? NRF_UARTE_INT_RXDRDY_MASK : 0);
684+
((IS_ENABLED(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) &&
685+
!IS_ENABLED(UARTE_HAS_FRAME_TIMEOUT)) ? NRF_UARTE_INT_RXDRDY_MASK : 0);
672686

673687
#if !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX)
674688
int ret = uarte_nrfx_rx_counting_init(dev);
@@ -835,6 +849,16 @@ static void notify_rx_disable(const struct device *dev)
835849
user_callback(dev, (struct uart_event *)&evt);
836850
}
837851

852+
#ifdef UARTE_HAS_FRAME_TIMEOUT
853+
static uint32_t us_to_bauds(uint32_t baudrate, int32_t timeout)
854+
{
855+
uint32_t divisor = 1000000 / timeout;
856+
uint32_t bauds = baudrate / divisor;
857+
858+
return MIN(bauds, UARTE_FRAMETIMEOUT_COUNTERTOP_Msk);
859+
}
860+
#endif
861+
838862
static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf,
839863
size_t len,
840864
int32_t timeout)
@@ -858,9 +882,22 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf,
858882
}
859883

860884
#ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX
885+
#ifdef UARTE_HAS_FRAME_TIMEOUT
886+
if (timeout && (timeout != SYS_FOREVER_US)) {
887+
uint32_t baudrate = COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE,
888+
(data->uart_config.baudrate), (cfg->baudrate));
889+
890+
rdata->timeout = K_USEC(timeout);
891+
nrf_uarte_frame_timeout_set(uarte, us_to_bauds(baudrate, timeout));
892+
nrf_uarte_shorts_enable(uarte, NRF_UARTE_SHORT_FRAME_TIMEOUT_STOPRX);
893+
} else {
894+
rdata->timeout = K_NO_WAIT;
895+
}
896+
#else
861897
rdata->timeout = (timeout && timeout == SYS_FOREVER_US) ?
862898
K_NO_WAIT : K_USEC(timeout / RX_TIMEOUT_DIV);
863899
rdata->idle_cnt = RX_TIMEOUT_DIV - 1;
900+
#endif
864901
#else
865902
rdata->timeout = timeout;
866903
rdata->timeout_slab = timeout / RX_TIMEOUT_DIV;
@@ -1016,6 +1053,12 @@ static void rx_timeout(struct k_timer *timer)
10161053
#if CONFIG_UART_NRFX_UARTE_ENHANCED_RX
10171054
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
10181055

1056+
#ifdef UARTE_HAS_FRAME_TIMEOUT
1057+
if (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXDRDY)) {
1058+
nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPRX);
1059+
}
1060+
return;
1061+
#else /* UARTE_HAS_FRAME_TIMEOUT */
10191062
struct uarte_nrfx_data *data = dev->data;
10201063
struct uarte_async_rx *rdata = &data->async->rx;
10211064

@@ -1031,6 +1074,7 @@ static void rx_timeout(struct k_timer *timer)
10311074
}
10321075

10331076
k_timer_start(&rdata->timer, rdata->timeout, K_NO_WAIT);
1077+
#endif /* UARTE_HAS_FRAME_TIMEOUT */
10341078
#else /* CONFIG_UART_NRFX_UARTE_ENHANCED_RX */
10351079
const struct uarte_nrfx_config *cfg = dev->config;
10361080
struct uarte_nrfx_data *data = dev->data;
@@ -1144,6 +1188,7 @@ static void rxstarted_isr(const struct device *dev)
11441188
.type = UART_RX_BUF_REQUEST,
11451189
};
11461190

1191+
#ifndef UARTE_HAS_FRAME_TIMEOUT
11471192
struct uarte_nrfx_data *data = dev->data;
11481193
struct uarte_async_rx *rdata = &data->async->rx;
11491194

@@ -1161,6 +1206,7 @@ static void rxstarted_isr(const struct device *dev)
11611206
k_timer_start(&rdata->timer, timeout, timeout);
11621207
}
11631208
#endif /* CONFIG_UART_NRFX_UARTE_ENHANCED_RX */
1209+
#endif /* !UARTE_HAS_FRAME_TIMEOUT */
11641210
user_callback(dev, &evt);
11651211
}
11661212

@@ -1360,7 +1406,9 @@ static void rxto_isr(const struct device *dev)
13601406

13611407
#ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX
13621408
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
1363-
1409+
#ifdef UARTE_HAS_FRAME_TIMEOUT
1410+
nrf_uarte_shorts_disable(uarte, NRF_UARTE_SHORT_FRAME_TIMEOUT_STOPRX);
1411+
#endif
13641412
nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXDRDY);
13651413
#endif
13661414

@@ -1456,6 +1504,9 @@ static void txstopped_isr(const struct device *dev)
14561504

14571505
static void rxdrdy_isr(const struct device *dev)
14581506
{
1507+
#if !defined(UARTE_HAS_FRAME_TIMEOUT)
1508+
struct uarte_nrfx_data *data = dev->data;
1509+
14591510
#if defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX)
14601511
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
14611512

@@ -1465,6 +1516,7 @@ static void rxdrdy_isr(const struct device *dev)
14651516
#else
14661517
data->async->rx.cnt.cnt++;
14671518
#endif
1519+
#endif /* !UARTE_HAS_FRAME_TIMEOUT */
14681520
}
14691521

14701522
static bool event_check_clear(NRF_UARTE_Type *uarte, nrf_uarte_event_t event,
@@ -1487,7 +1539,7 @@ static void uarte_nrfx_isr_async(const void *arg)
14871539
struct uarte_async_rx *rdata = &data->async->rx;
14881540
uint32_t imask = nrf_uarte_int_enable_check(uarte, UINT32_MAX);
14891541

1490-
if (!HW_RX_COUNTING_ENABLED(config)
1542+
if (!(HW_RX_COUNTING_ENABLED(config) || IS_ENABLED(UARTE_HAS_FRAME_TIMEOUT))
14911543
&& event_check_clear(uarte, NRF_UARTE_EVENT_RXDRDY, NRF_UARTE_INT_RXDRDY_MASK, imask)) {
14921544
rxdrdy_isr(dev);
14931545

@@ -2130,6 +2182,8 @@ static int uarte_nrfx_pm_action(const struct device *dev,
21302182
IF_ENABLED(UARTE_HAS_STOP_CONFIG, (.stop = NRF_UARTE_STOP_ONE,))\
21312183
IF_ENABLED(UARTE_ODD_PARITY_ALLOWED, \
21322184
(.paritytype = NRF_UARTE_PARITYTYPE_EVEN,)) \
2185+
IF_ENABLED(UARTE_HAS_FRAME_TIMEOUT, \
2186+
(.frame_timeout = NRF_UARTE_FRAME_TIMEOUT_EN,)) \
21332187
}
21342188

21352189
/* Macro for setting zephyr specific configuration structures. */
@@ -2173,7 +2227,9 @@ static int uarte_nrfx_pm_action(const struct device *dev,
21732227
COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, \
21742228
(IF_ENABLED(DT_CLOCKS_HAS_IDX(UARTE(idx), 0), \
21752229
(.clock_freq = UARTE_GET_FREQ(idx),))), \
2176-
(.nrf_baudrate = UARTE_GET_BAUDRATE(idx), \
2230+
(IF_ENABLED(UARTE_HAS_FRAME_TIMEOUT, \
2231+
(.baudrate = UARTE_PROP(idx, current_speed),)) \
2232+
.nrf_baudrate = UARTE_GET_BAUDRATE(idx), \
21772233
.hw_config = UARTE_NRF_CONFIG(idx),)) \
21782234
.pcfg = PINCTRL_DT_DEV_CONFIG_GET(UARTE(idx)), \
21792235
.uarte_regs = _CONCAT(NRF_UARTE, idx), \

0 commit comments

Comments
 (0)