|
25 | 25 | #include <zephyr/logging/log.h> |
26 | 26 | LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); |
27 | 27 |
|
| 28 | +#if !defined(CONFIG_ARCH_POSIX) |
28 | 29 | #define RX_FLUSH_WORKAROUND 1 |
| 30 | +#endif |
29 | 31 |
|
30 | 32 | #define UARTE(idx) DT_NODELABEL(uart##idx) |
31 | 33 | #define UARTE_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(UARTE(idx), prop) |
@@ -695,9 +697,6 @@ static void uarte_disable_locked(const struct device *dev, uint32_t dis_mask, ui |
695 | 697 |
|
696 | 698 | nrf_uarte_disable(get_uarte_instance(dev)); |
697 | 699 | } |
698 | | -#endif |
699 | | - |
700 | | -#ifdef UARTE_ANY_ASYNC |
701 | 700 |
|
702 | 701 | static void rx_timeout(struct k_timer *timer); |
703 | 702 | static void tx_timeout(struct k_timer *timer); |
@@ -1437,85 +1436,45 @@ static void endrx_isr(const struct device *dev) |
1437 | 1436 | #endif |
1438 | 1437 | } |
1439 | 1438 |
|
1440 | | -/* Function for flushing internal RX fifo. Function can be called in case |
1441 | | - * flushed data is discarded or when data is valid and needs to be retrieved. |
| 1439 | +/** @brief RX FIFO flushing |
1442 | 1440 | * |
1443 | | - * However, UARTE does not update RXAMOUNT register if fifo is empty. Old value |
1444 | | - * remains. In certain cases it makes it impossible to distinguish between |
1445 | | - * case when fifo was empty and not. Function is trying to minimize chances of |
1446 | | - * error with following measures: |
1447 | | - * - RXAMOUNT is read before flushing and compared against value after flushing |
1448 | | - * if they differ it indicates that data was flushed |
1449 | | - * - user buffer is dirtied and if RXAMOUNT did not changed it is checked if |
1450 | | - * it is still dirty. If not then it indicates that data was flushed |
1451 | | - * |
1452 | | - * In other cases function indicates that fifo was empty. It means that if |
1453 | | - * number of bytes in the fifo equal last rx transfer length and data is equal |
1454 | | - * to dirty marker it will be discarded. |
| 1441 | + * Due to the HW bug which does not update RX.AMOUNT register when FIFO was empty |
| 1442 | + * a workaround is applied which checks RXSTARTED event. If that event is set it |
| 1443 | + * means that FIFO was not empty. |
1455 | 1444 | * |
1456 | 1445 | * @param dev Device. |
1457 | | - * @param buf Buffer for flushed data, null indicates that flushed data can be |
1458 | | - * dropped but we still want to get amount of data flushed. |
1459 | | - * @param len Buffer size, not used if @p buf is null. |
1460 | 1446 | * |
1461 | 1447 | * @return number of bytes flushed from the fifo. |
1462 | 1448 | */ |
1463 | | - |
1464 | | -static uint8_t rx_flush(const struct device *dev, uint8_t *buf) |
| 1449 | +static uint8_t rx_flush(const struct device *dev) |
1465 | 1450 | { |
1466 | | - /* Flushing RX fifo requires buffer bigger than 4 bytes to empty fifo*/ |
1467 | | - static const uint8_t dirty = CONFIG_UART_NRFX_UARTE_RX_FLUSH_MAGIC_BYTE; |
1468 | 1451 | NRF_UARTE_Type *uarte = get_uarte_instance(dev); |
1469 | 1452 | const struct uarte_nrfx_config *config = dev->config; |
1470 | | - uint32_t prev_rx_amount; |
1471 | 1453 | uint32_t rx_amount; |
1472 | 1454 |
|
1473 | | - if (IS_ENABLED(RX_FLUSH_WORKAROUND)) { |
1474 | | - memset(buf, dirty, UARTE_HW_RX_FIFO_SIZE); |
1475 | | - if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) { |
1476 | | - sys_cache_data_flush_range(buf, UARTE_HW_RX_FIFO_SIZE); |
1477 | | - } |
1478 | | - prev_rx_amount = nrf_uarte_rx_amount_get(uarte); |
1479 | | - } else { |
1480 | | - prev_rx_amount = 0; |
1481 | | - } |
1482 | | - |
1483 | | - nrf_uarte_rx_buffer_set(uarte, buf, UARTE_HW_RX_FIFO_SIZE); |
1484 | | - /* Final part of handling RXTO event is in ENDRX interrupt |
1485 | | - * handler. ENDRX is generated as a result of FLUSHRX task. |
1486 | | - */ |
1487 | | - nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDRX); |
| 1455 | + nrf_uarte_rx_buffer_set(uarte, config->rx_flush_buf, UARTE_HW_RX_FIFO_SIZE); |
1488 | 1456 | nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_FLUSHRX); |
1489 | 1457 | while (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDRX)) { |
1490 | 1458 | /* empty */ |
1491 | 1459 | } |
1492 | 1460 | nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDRX); |
1493 | | - nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); |
1494 | 1461 |
|
1495 | | - rx_amount = nrf_uarte_rx_amount_get(uarte); |
1496 | | - if (!buf || !IS_ENABLED(RX_FLUSH_WORKAROUND)) { |
1497 | | - return rx_amount; |
1498 | | - } |
1499 | | - |
1500 | | - if (rx_amount != prev_rx_amount) { |
1501 | | - return rx_amount; |
1502 | | - } |
1503 | | - |
1504 | | - if (rx_amount > UARTE_HW_RX_FIFO_SIZE) { |
1505 | | - return 0; |
1506 | | - } |
1507 | | - |
1508 | | - if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) { |
1509 | | - sys_cache_data_invd_range(buf, UARTE_HW_RX_FIFO_SIZE); |
| 1462 | + if (!IS_ENABLED(RX_FLUSH_WORKAROUND)) { |
| 1463 | + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); |
| 1464 | + rx_amount = nrf_uarte_rx_amount_get(uarte); |
| 1465 | + } else if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXSTARTED)) { |
| 1466 | + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); |
| 1467 | + rx_amount = nrf_uarte_rx_amount_get(uarte); |
| 1468 | + } else { |
| 1469 | + rx_amount = 0; |
1510 | 1470 | } |
1511 | 1471 |
|
1512 | | - for (int i = 0; i < rx_amount; i++) { |
1513 | | - if (buf[i] != dirty) { |
1514 | | - return rx_amount; |
1515 | | - } |
| 1472 | + if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE) && |
| 1473 | + rx_amount) { |
| 1474 | + sys_cache_data_invd_range(config->rx_flush_buf, rx_amount); |
1516 | 1475 | } |
1517 | 1476 |
|
1518 | | - return 0; |
| 1477 | + return rx_amount; |
1519 | 1478 | } |
1520 | 1479 |
|
1521 | 1480 | /* This handler is called when the receiver is stopped. If rx was aborted |
@@ -1549,17 +1508,14 @@ static void rxto_isr(const struct device *dev) |
1549 | 1508 | async_rx->discard_fifo = false; |
1550 | 1509 | #if !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) |
1551 | 1510 | if (HW_RX_COUNTING_ENABLED(config)) { |
1552 | | - uint8_t buf[UARTE_HW_RX_FIFO_SIZE]; |
1553 | | - |
1554 | 1511 | /* It need to be included because TIMER+PPI got RXDRDY events |
1555 | 1512 | * and counted those flushed bytes. |
1556 | 1513 | */ |
1557 | | - async_rx->total_user_byte_cnt += rx_flush(dev, buf); |
1558 | | - (void)buf; |
| 1514 | + async_rx->total_user_byte_cnt += rx_flush(dev); |
1559 | 1515 | } |
1560 | 1516 | #endif |
1561 | 1517 | } else { |
1562 | | - async_rx->flush_cnt = rx_flush(dev, config->rx_flush_buf); |
| 1518 | + async_rx->flush_cnt = rx_flush(dev); |
1563 | 1519 | } |
1564 | 1520 |
|
1565 | 1521 | #ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX |
|
0 commit comments