@@ -562,9 +562,6 @@ static void nordic_nrf5_uart_event_handler_rxdrdy(int instance)
562
562
*/
563
563
static void nordic_nrf5_uart_event_handler_endtx (int instance )
564
564
{
565
- /* Set Tx done. */
566
- nordic_nrf5_uart_state [instance ].tx_in_progress = 0 ;
567
-
568
565
/* Check if callback handler and Tx event mask is set. */
569
566
uart_irq_handler callback = (uart_irq_handler ) nordic_nrf5_uart_state [instance ].owner -> handler ;
570
567
uint32_t mask = nordic_nrf5_uart_state [instance ].owner -> mask ;
@@ -611,6 +608,12 @@ static void nordic_nrf5_uart_event_handler_endrx_asynch(int instance)
611
608
*/
612
609
static void nordic_nrf5_uart_event_handler_endtx_asynch (int instance )
613
610
{
611
+ /* Disable ENDTX interrupt. */
612
+ nordic_nrf5_uart_register [instance ]-> INTEN &= ~NRF_UARTE_INT_ENDTX_MASK ;
613
+
614
+ /* Clear ENDTX event. */
615
+ nrf_uarte_event_clear (nordic_nrf5_uart_register [instance ], NRF_UARTE_EVENT_ENDTX );
616
+
614
617
/* Set Tx done and reset Tx mode to be not asynchronous. */
615
618
nordic_nrf5_uart_state [instance ].tx_in_progress = 0 ;
616
619
nordic_nrf5_uart_state [instance ].tx_asynch = false;
@@ -673,21 +676,28 @@ static void nordic_nrf5_uart_event_handler(int instance)
673
676
nordic_nrf5_uart_event_handler_rxdrdy (instance );
674
677
}
675
678
679
+ /* Tx single character has been sent. */
680
+ if (nrf_uarte_event_check (nordic_nrf5_uart_register [instance ], NRF_UARTE_EVENT_TXDRDY )) {
681
+
682
+ nrf_uarte_event_clear (nordic_nrf5_uart_register [instance ], NRF_UARTE_EVENT_TXDRDY );
683
+
684
+ /* In non-async transfers this will generate and interrupt if callback and mask is set. */
685
+ if (!nordic_nrf5_uart_state [instance ].tx_asynch ) {
686
+
687
+ nordic_nrf5_uart_event_handler_endtx (instance );
688
+ }
689
+ }
690
+
676
691
/* Tx DMA buffer has been sent. */
677
692
if (nrf_uarte_event_check (nordic_nrf5_uart_register [instance ], NRF_UARTE_EVENT_ENDTX ))
678
693
{
679
- nrf_uarte_event_clear (nordic_nrf5_uart_register [instance ], NRF_UARTE_EVENT_ENDTX );
680
-
681
694
#if DEVICE_SERIAL_ASYNCH
682
- /* Call appropriate event handler based on current mode. */
695
+ /* Call async event handler in async mode. */
683
696
if (nordic_nrf5_uart_state [instance ].tx_asynch ) {
684
697
685
698
nordic_nrf5_uart_event_handler_endtx_asynch (instance );
686
- } else
687
- #endif
688
- {
689
- nordic_nrf5_uart_event_handler_endtx (instance );
690
699
}
700
+ #endif
691
701
}
692
702
}
693
703
@@ -895,10 +905,6 @@ static void nordic_nrf5_serial_configure(serial_t *obj)
895
905
/* Configure common setting. */
896
906
nordic_nrf5_uart_configure_object (obj );
897
907
898
- /* Clear Tx event and enable Tx interrupts. */
899
- nrf_uarte_event_clear (nordic_nrf5_uart_register [instance ], NRF_UARTE_EVENT_ENDTX );
900
- nordic_nrf5_uart_register [instance ]-> INTEN |= NRF_UARTE_INT_ENDTX_MASK ;
901
-
902
908
/* Set new owner. */
903
909
nordic_nrf5_uart_state [instance ].owner = uart_object ;
904
910
uart_object -> update = false;
@@ -1060,6 +1066,11 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
1060
1066
uart_object -> hwfc = NRF_UART_HWFC_DISABLED ;
1061
1067
}
1062
1068
1069
+ /* The STDIO object is stored in this file. Set the flag once initialized. */
1070
+ if (obj == & stdio_uart ) {
1071
+ stdio_uart_inited = 1 ;
1072
+ }
1073
+
1063
1074
/* Initializing the serial object does not make it the owner of an instance.
1064
1075
* Only when the serial object is being used will the object take ownership
1065
1076
* over the instance.
@@ -1335,6 +1346,21 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
1335
1346
1336
1347
uart_object -> mask &= ~type ;
1337
1348
}
1349
+
1350
+ /* Enable TXDRDY event. */
1351
+ if ((type == NORDIC_TX_IRQ ) && enable ) {
1352
+
1353
+ /* Clear Tx ready event and enable Tx ready interrupts. */
1354
+ nrf_uarte_event_clear (nordic_nrf5_uart_register [uart_object -> instance ], NRF_UARTE_EVENT_TXDRDY );
1355
+ nordic_nrf5_uart_register [uart_object -> instance ]-> INTEN |= NRF_UARTE_INT_TXDRDY_MASK ;
1356
+
1357
+ /* Disable TXDRDY event. */
1358
+ } else if ((type == NORDIC_TX_IRQ ) && !enable ) {
1359
+
1360
+ /* Disable Tx ready interrupts and clear Tx ready event. */
1361
+ nordic_nrf5_uart_register [uart_object -> instance ]-> INTEN &= ~NRF_UARTE_INT_TXDRDY_MASK ;
1362
+ nrf_uarte_event_clear (nordic_nrf5_uart_register [uart_object -> instance ], NRF_UARTE_EVENT_TXDRDY );
1363
+ }
1338
1364
}
1339
1365
1340
1366
/** Get character. This is a blocking call, waiting for a character
@@ -1412,15 +1438,41 @@ void serial_putc(serial_t *obj, int character)
1412
1438
/* Take ownership and configure UART if necessary. */
1413
1439
nordic_nrf5_serial_configure (obj );
1414
1440
1441
+ /**
1442
+ * The UARTE module can generate two different Tx events: TXDRDY when each character has
1443
+ * been transmitted and ENDTX when the entire buffer has been sent.
1444
+ *
1445
+ * For the blocking serial_putc, TXDRDY interrupts are enabled and only used for the
1446
+ * single character TX IRQ callback handler. The ENDTX event does not generate an interrupt
1447
+ * but is caught using a busy-wait loop. Once ENDTX has been generated we disable TXDRDY
1448
+ * interrupts again.
1449
+ */
1450
+
1415
1451
/* Arm Tx DMA buffer. */
1416
1452
nordic_nrf5_uart_state [instance ].tx_data = character ;
1417
1453
nrf_uarte_tx_buffer_set (nordic_nrf5_uart_register [instance ],
1418
1454
& nordic_nrf5_uart_state [instance ].tx_data ,
1419
1455
1 );
1420
1456
1457
+ /* Clear TXDRDY event and enable TXDRDY interrupts. */
1458
+ nrf_uarte_event_clear (nordic_nrf5_uart_register [instance ], NRF_UARTE_EVENT_TXDRDY );
1459
+ nordic_nrf5_uart_register [instance ]-> INTEN |= NRF_UARTE_INT_TXDRDY_MASK ;
1460
+
1461
+ /* Clear ENDTX event. */
1462
+ nrf_uarte_event_clear (nordic_nrf5_uart_register [instance ], NRF_UARTE_EVENT_ENDTX );
1463
+
1421
1464
/* Trigger DMA transfer. */
1422
1465
nrf_uarte_task_trigger (nordic_nrf5_uart_register [instance ],
1423
1466
NRF_UARTE_TASK_STARTTX );
1467
+
1468
+ /* Busy-wait until the ENDTX event occurs. */
1469
+ while (!nrf_uarte_event_check (nordic_nrf5_uart_register [instance ], NRF_UARTE_EVENT_ENDTX ));
1470
+
1471
+ /* Disable TXDRDY event again. */
1472
+ nordic_nrf5_uart_register [instance ]-> INTEN &= ~NRF_UARTE_INT_TXDRDY_MASK ;
1473
+
1474
+ /* Release mutex. As the owner this call is safe. */
1475
+ nordic_nrf5_uart_state [instance ].tx_in_progress = 0 ;
1424
1476
}
1425
1477
1426
1478
/** Check if the serial peripheral is readable
@@ -1574,6 +1626,20 @@ int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx
1574
1626
nordic_nrf5_uart_state [instance ].tx_asynch = true;
1575
1627
nordic_nrf5_serial_configure (obj );
1576
1628
1629
+ /**
1630
+ * The UARTE module can generate two different Tx events: TXDRDY when each
1631
+ * character has been transmitted and ENDTX when the entire buffer has been sent.
1632
+ *
1633
+ * For the async serial_tx_async, TXDRDY interrupts are disabled completely. ENDTX
1634
+ * interrupts are enabled and used to signal the completion of the async transfer.
1635
+ *
1636
+ * The ENDTX interrupt is diabled immediately after it is fired in the ISR.
1637
+ */
1638
+
1639
+ /* Clear Tx event and enable Tx interrupts. */
1640
+ nrf_uarte_event_clear (nordic_nrf5_uart_register [instance ], NRF_UARTE_EVENT_ENDTX );
1641
+ nordic_nrf5_uart_register [instance ]-> INTEN |= NRF_UARTE_INT_ENDTX_MASK ;
1642
+
1577
1643
/* Set Tx DMA buffer. */
1578
1644
nrf_uarte_tx_buffer_set (nordic_nrf5_uart_register [obj -> serial .instance ],
1579
1645
buffer ,
@@ -1708,16 +1774,24 @@ void serial_tx_abort_asynch(serial_t *obj)
1708
1774
/* Transmission might be in progress. Disable interrupts to prevent ISR from firing. */
1709
1775
core_util_critical_section_enter ();
1710
1776
1777
+ int instance = obj -> serial .instance ;
1778
+
1779
+ /* Disable ENDTX interrupts. */
1780
+ nordic_nrf5_uart_register [instance ]-> INTEN &= ~NRF_UARTE_INT_ENDTX_MASK ;
1781
+
1782
+ /* Clear ENDTX event. */
1783
+ nrf_uarte_event_clear (nordic_nrf5_uart_register [instance ], NRF_UARTE_EVENT_ENDTX );
1784
+
1711
1785
/* Reset Tx flags. */
1712
- nordic_nrf5_uart_state [obj -> serial . instance ].tx_in_progress = 0 ;
1713
- nordic_nrf5_uart_state [obj -> serial . instance ].tx_asynch = false;
1786
+ nordic_nrf5_uart_state [instance ].tx_in_progress = 0 ;
1787
+ nordic_nrf5_uart_state [instance ].tx_asynch = false;
1714
1788
1715
1789
/* Force reconfiguration. */
1716
1790
obj -> serial .update = true;
1717
1791
nordic_nrf5_serial_configure (obj );
1718
1792
1719
1793
/* Trigger STOP task. */
1720
- nrf_uarte_task_trigger (nordic_nrf5_uart_register [obj -> serial . instance ],
1794
+ nrf_uarte_task_trigger (nordic_nrf5_uart_register [instance ],
1721
1795
NRF_UARTE_TASK_STOPTX );
1722
1796
1723
1797
/* Enable interrupts again. */
0 commit comments