Skip to content

Commit 76495df

Browse files
nordic-krchnordicjm
authored andcommitted
[nrf fromtree] drivers: serial: nrfx_uarte: Add support for DMM and cache
Add support for DMM which manages cache and dedicated memory spaces. Added support for data cache for buffers which are not DMM managed. Signed-off-by: Krzysztof Chruściński <[email protected]> (cherry picked from commit 9517106)
1 parent f80b608 commit 76495df

File tree

1 file changed

+115
-11
lines changed

1 file changed

+115
-11
lines changed

drivers/serial/uart_nrfx_uarte.c

Lines changed: 115 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
#include <nrfx_timer.h>
1616
#include <zephyr/sys/util.h>
1717
#include <zephyr/kernel.h>
18+
#include <zephyr/cache.h>
1819
#include <soc.h>
20+
#include <dmm.h>
1921
#include <helpers/nrfx_gppi.h>
2022
#include <zephyr/linker/devicetree_regions.h>
2123
#include <zephyr/irq.h>
@@ -28,6 +30,8 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL);
2830
#define UARTE_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(UARTE(idx), prop)
2931
#define UARTE_PROP(idx, prop) DT_PROP(UARTE(idx), prop)
3032

33+
#define UARTE_IS_CACHEABLE(idx) DMM_IS_REG_CACHEABLE(DT_PHANDLE(UARTE(idx), memory_regions))
34+
3135
/* Execute macro f(x) for all instances. */
3236
#define UARTE_FOR_EACH_INSTANCE(f, sep, off_code, ...) \
3337
NRFX_FOREACH_PRESENT(UARTE, f, sep, off_code, __VA_ARGS__)
@@ -88,6 +92,12 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL);
8892
#define UARTE_HAS_FRAME_TIMEOUT 1
8993
#endif
9094

95+
#define INSTANCE_NEEDS_CACHE_MGMT(unused, prefix, i, prop) UARTE_IS_CACHEABLE(prefix##i)
96+
97+
#if UARTE_FOR_EACH_INSTANCE(INSTANCE_NEEDS_CACHE_MGMT, (+), (0), _)
98+
#define UARTE_ANY_CACHE 1
99+
#endif
100+
91101
/*
92102
* RX timeout is divided into time slabs, this define tells how many divisions
93103
* should be made. More divisions - higher timeout accuracy and processor usage.
@@ -112,6 +122,10 @@ struct uarte_async_tx {
112122

113123
struct uarte_async_rx {
114124
struct k_timer timer;
125+
#ifdef CONFIG_HAS_NORDIC_DMM
126+
uint8_t *usr_buf;
127+
uint8_t *next_usr_buf;
128+
#endif
115129
uint8_t *buf;
116130
size_t buf_len;
117131
size_t offset;
@@ -197,6 +211,9 @@ struct uarte_nrfx_data {
197211
*/
198212
#define UARTE_CFG_FLAG_LOW_POWER BIT(2)
199213

214+
/* If enabled then UARTE peripheral is using memory which is cacheable. */
215+
#define UARTE_CFG_FLAG_CACHEABLE BIT(3)
216+
200217
/* Macro for converting numerical baudrate to register value. It is convenient
201218
* to use this approach because for constant input it can calculate nrf setting
202219
* at compile time.
@@ -230,6 +247,9 @@ struct uarte_nrfx_config {
230247
uint32_t flags;
231248
bool disable_rx;
232249
const struct pinctrl_dev_config *pcfg;
250+
#ifdef CONFIG_HAS_NORDIC_DMM
251+
void *mem_reg;
252+
#endif
233253
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
234254
/* None-zero in case of high speed instances. Baudrate is adjusted by that ratio. */
235255
uint32_t clock_freq;
@@ -571,6 +591,10 @@ static void tx_start(const struct device *dev, const uint8_t *buf, size_t len)
571591
}
572592
#endif
573593

594+
if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) {
595+
sys_cache_data_flush_range((void *)buf, len);
596+
}
597+
574598
nrf_uarte_tx_buffer_set(uarte, buf, len);
575599
nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDTX);
576600
nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_TXSTOPPED);
@@ -877,6 +901,19 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf,
877901
return -EBUSY;
878902
}
879903

904+
#ifdef CONFIG_HAS_NORDIC_DMM
905+
uint8_t *dma_buf;
906+
int ret = 0;
907+
908+
ret = dmm_buffer_in_prepare(cfg->mem_reg, buf, len, (void **)&dma_buf);
909+
if (ret < 0) {
910+
return ret;
911+
}
912+
913+
async_rx->usr_buf = buf;
914+
buf = dma_buf;
915+
#endif
916+
880917
#ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX
881918
#ifdef UARTE_HAS_FRAME_TIMEOUT
882919
if (timeout != SYS_FOREVER_US) {
@@ -909,8 +946,18 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf,
909946
if (async_rx->flush_cnt) {
910947
int cpy_len = MIN(len, async_rx->flush_cnt);
911948

949+
if (IS_ENABLED(UARTE_ANY_CACHE) &&
950+
(cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) {
951+
sys_cache_data_invd_range(cfg->rx_flush_buf, cpy_len);
952+
}
953+
912954
memcpy(buf, cfg->rx_flush_buf, cpy_len);
913955

956+
if (IS_ENABLED(UARTE_ANY_CACHE) &&
957+
(cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) {
958+
sys_cache_data_flush_range(buf, cpy_len);
959+
}
960+
914961
buf += cpy_len;
915962
len -= cpy_len;
916963

@@ -921,6 +968,11 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf,
921968
async_rx->flush_cnt -= cpy_len;
922969
memmove(cfg->rx_flush_buf, &cfg->rx_flush_buf[cpy_len],
923970
async_rx->flush_cnt);
971+
if (IS_ENABLED(UARTE_ANY_CACHE) &&
972+
(cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) {
973+
sys_cache_data_flush_range(cfg->rx_flush_buf,
974+
async_rx->flush_cnt);
975+
}
924976
atomic_or(&data->flags, UARTE_FLAG_TRIG_RXTO);
925977
NRFX_IRQ_PENDING_SET(nrfx_get_irq_number(uarte));
926978
return 0;
@@ -966,6 +1018,17 @@ static int uarte_nrfx_rx_buf_rsp(const struct device *dev, uint8_t *buf,
9661018
if (async_rx->buf == NULL) {
9671019
err = -EACCES;
9681020
} else if (async_rx->next_buf == NULL) {
1021+
#ifdef CONFIG_HAS_NORDIC_DMM
1022+
uint8_t *dma_buf;
1023+
const struct uarte_nrfx_config *config = dev->config;
1024+
1025+
err = dmm_buffer_in_prepare(config->mem_reg, buf, len, (void **)&dma_buf);
1026+
if (err < 0) {
1027+
return err;
1028+
}
1029+
async_rx->next_usr_buf = buf;
1030+
buf = dma_buf;
1031+
#endif
9691032
async_rx->next_buf = buf;
9701033
async_rx->next_buf_len = len;
9711034
nrf_uarte_rx_buffer_set(uarte, buf, len);
@@ -1235,6 +1298,15 @@ static void endrx_isr(const struct device *dev)
12351298
*/
12361299
const int rx_amount = nrf_uarte_rx_amount_get(uarte) + async_rx->flush_cnt;
12371300

1301+
#ifdef CONFIG_HAS_NORDIC_DMM
1302+
const struct uarte_nrfx_config *config = dev->config;
1303+
int err =
1304+
dmm_buffer_in_release(config->mem_reg, async_rx->usr_buf, rx_amount, async_rx->buf);
1305+
1306+
(void)err;
1307+
__ASSERT_NO_MSG(err == 0);
1308+
async_rx->buf = async_rx->usr_buf;
1309+
#endif
12381310
async_rx->flush_cnt = 0;
12391311

12401312
/* The 'rx_offset' can be bigger than 'rx_amount', so it the length
@@ -1262,6 +1334,9 @@ static void endrx_isr(const struct device *dev)
12621334
rx_buf_release(dev, async_rx->buf);
12631335
async_rx->buf = async_rx->next_buf;
12641336
async_rx->buf_len = async_rx->next_buf_len;
1337+
#ifdef CONFIG_HAS_NORDIC_DMM
1338+
async_rx->usr_buf = async_rx->next_usr_buf;
1339+
#endif
12651340
async_rx->next_buf = NULL;
12661341
async_rx->next_buf_len = 0;
12671342
async_rx->offset = 0;
@@ -1325,11 +1400,15 @@ static uint8_t rx_flush(const struct device *dev, uint8_t *buf)
13251400
/* Flushing RX fifo requires buffer bigger than 4 bytes to empty fifo*/
13261401
static const uint8_t dirty = 0xAA;
13271402
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
1403+
const struct uarte_nrfx_config *config = dev->config;
13281404
uint32_t prev_rx_amount;
13291405
uint32_t rx_amount;
13301406

13311407
if (IS_ENABLED(RX_FLUSH_WORKAROUND)) {
13321408
memset(buf, dirty, UARTE_HW_RX_FIFO_SIZE);
1409+
if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) {
1410+
sys_cache_data_flush_range(buf, UARTE_HW_RX_FIFO_SIZE);
1411+
}
13331412
prev_rx_amount = nrf_uarte_rx_amount_get(uarte);
13341413
} else {
13351414
prev_rx_amount = 0;
@@ -1360,6 +1439,10 @@ static uint8_t rx_flush(const struct device *dev, uint8_t *buf)
13601439
return 0;
13611440
}
13621441

1442+
if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) {
1443+
sys_cache_data_invd_range(buf, UARTE_HW_RX_FIFO_SIZE);
1444+
}
1445+
13631446
for (int i = 0; i < rx_amount; i++) {
13641447
if (buf[i] != dirty) {
13651448
return rx_amount;
@@ -1379,6 +1462,10 @@ static void rxto_isr(const struct device *dev)
13791462
struct uarte_async_rx *async_rx = &data->async->rx;
13801463

13811464
if (async_rx->buf) {
1465+
#ifdef CONFIG_HAS_NORDIC_DMM
1466+
(void)dmm_buffer_in_release(config->mem_reg, async_rx->usr_buf, 0, async_rx->buf);
1467+
async_rx->buf = async_rx->usr_buf;
1468+
#endif
13821469
rx_buf_release(dev, async_rx->buf);
13831470
async_rx->buf = NULL;
13841471
}
@@ -1598,6 +1685,16 @@ static void uarte_nrfx_isr_async(const void *arg)
15981685
}
15991686

16001687
if (atomic_and(&data->flags, ~UARTE_FLAG_TRIG_RXTO) & UARTE_FLAG_TRIG_RXTO) {
1688+
#ifdef CONFIG_HAS_NORDIC_DMM
1689+
int ret;
1690+
1691+
ret = dmm_buffer_in_release(config->mem_reg, async_rx->usr_buf, async_rx->buf_len,
1692+
async_rx->buf);
1693+
1694+
(void)ret;
1695+
__ASSERT_NO_MSG(ret == 0);
1696+
async_rx->buf = async_rx->usr_buf;
1697+
#endif
16011698
notify_uart_rx_rdy(dev, async_rx->buf_len);
16021699
rx_buf_release(dev, async_rx->buf);
16031700
async_rx->buf_len = 0;
@@ -1633,6 +1730,10 @@ static int uarte_nrfx_poll_in(const struct device *dev, unsigned char *c)
16331730
return -1;
16341731
}
16351732

1733+
if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) {
1734+
sys_cache_data_invd_range(config->poll_in_byte, 1);
1735+
}
1736+
16361737
*c = *config->poll_in_byte;
16371738

16381739
/* clear the interrupt */
@@ -1727,6 +1828,10 @@ static int uarte_nrfx_fifo_read(const struct device *dev,
17271828
/* Clear the interrupt */
17281829
nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDRX);
17291830

1831+
if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) {
1832+
sys_cache_data_invd_range(config->poll_in_byte, 1);
1833+
}
1834+
17301835
/* Receive a character */
17311836
rx_data[num_rx++] = *config->poll_in_byte;
17321837

@@ -2200,12 +2305,12 @@ static int uarte_nrfx_pm_action(const struct device *dev,
22002305
IF_ENABLED(CONFIG_UART_##idx##_ASYNC, ( \
22012306
static uint8_t \
22022307
uarte##idx##_tx_cache[CONFIG_UART_ASYNC_TX_CACHE_SIZE] \
2203-
UARTE_MEMORY_SECTION(idx); \
2308+
DMM_MEMORY_SECTION(UARTE(idx)); \
22042309
static uint8_t uarte##idx##_flush_buf[UARTE_HW_RX_FIFO_SIZE] \
2205-
UARTE_MEMORY_SECTION(idx); \
2310+
DMM_MEMORY_SECTION(UARTE(idx)); \
22062311
struct uarte_async_cb uarte##idx##_async;)) \
2207-
static uint8_t uarte##idx##_poll_out_byte UARTE_MEMORY_SECTION(idx); \
2208-
static uint8_t uarte##idx##_poll_in_byte UARTE_MEMORY_SECTION(idx); \
2312+
static uint8_t uarte##idx##_poll_out_byte DMM_MEMORY_SECTION(UARTE(idx));\
2313+
static uint8_t uarte##idx##_poll_in_byte DMM_MEMORY_SECTION(UARTE(idx)); \
22092314
static struct uarte_nrfx_data uarte_##idx##_data = { \
22102315
IF_ENABLED(CONFIG_UART_USE_RUNTIME_CONFIGURE, \
22112316
(.uart_config = UARTE_CONFIG(idx),)) \
@@ -2227,11 +2332,16 @@ static int uarte_nrfx_pm_action(const struct device *dev,
22272332
.hw_config = UARTE_NRF_CONFIG(idx),)) \
22282333
.pcfg = PINCTRL_DT_DEV_CONFIG_GET(UARTE(idx)), \
22292334
.uarte_regs = _CONCAT(NRF_UARTE, idx), \
2335+
IF_ENABLED(CONFIG_HAS_NORDIC_DMM, \
2336+
(.mem_reg = DMM_DEV_TO_REG(UARTE(idx)),)) \
22302337
.flags = \
22312338
(IS_ENABLED(CONFIG_UART_##idx##_ENHANCED_POLL_OUT) ? \
22322339
UARTE_CFG_FLAG_PPI_ENDTX : 0) | \
22332340
(IS_ENABLED(CONFIG_UART_##idx##_NRF_HW_ASYNC) ? \
22342341
UARTE_CFG_FLAG_HW_BYTE_COUNTING : 0) | \
2342+
(!IS_ENABLED(CONFIG_HAS_NORDIC_DMM) ? 0 : \
2343+
(UARTE_IS_CACHEABLE(idx) ? \
2344+
UARTE_CFG_FLAG_CACHEABLE : 0)) | \
22352345
USE_LOW_POWER(idx), \
22362346
UARTE_DISABLE_RX_INIT(UARTE(idx)), \
22372347
.poll_out_byte = &uarte##idx##_poll_out_byte, \
@@ -2269,19 +2379,13 @@ static int uarte_nrfx_pm_action(const struct device *dev,
22692379
(static uint8_t uarte##idx##_tx_buffer \
22702380
[MIN(CONFIG_UART_##idx##_NRF_TX_BUFFER_SIZE, \
22712381
BIT_MASK(UARTE##idx##_EASYDMA_MAXCNT_SIZE))] \
2272-
UARTE_MEMORY_SECTION(idx); \
2382+
DMM_MEMORY_SECTION(UARTE(idx)); \
22732383
static struct uarte_nrfx_int_driven \
22742384
uarte##idx##_int_driven = { \
22752385
.tx_buffer = uarte##idx##_tx_buffer, \
22762386
.tx_buff_size = sizeof(uarte##idx##_tx_buffer),\
22772387
};))
22782388

2279-
#define UARTE_MEMORY_SECTION(idx) \
2280-
COND_CODE_1(UARTE_HAS_PROP(idx, memory_regions), \
2281-
(__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \
2282-
DT_PHANDLE(UARTE(idx), memory_regions)))))), \
2283-
())
2284-
22852389
#define COND_UART_NRF_UARTE_DEVICE(unused, prefix, i, _) \
22862390
IF_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##i, (UART_NRF_UARTE_DEVICE(prefix##i);))
22872391

0 commit comments

Comments
 (0)