@@ -29,6 +29,7 @@ LOG_MODULE_REGISTER(net_ppp, LOG_LEVEL);
2929#include <zephyr/net/net_core.h>
3030#include <zephyr/sys/ring_buffer.h>
3131#include <zephyr/sys/crc.h>
32+ #include <zephyr/drivers/gpio.h>
3233#include <zephyr/drivers/uart.h>
3334#include <zephyr/drivers/console/uart_mux.h>
3435#include <zephyr/random/random.h>
@@ -50,6 +51,8 @@ BUILD_ASSERT(UART_YIELD_INTERVAL_BYTES * 8 * 1000 /
5051 "current UART k_yield() interval & speed leads to blocking time > 5 ms" );
5152#endif
5253
54+ #define RX_RINGBUF_MIN_SPACE CONFIG_NET_PPP_RINGBUF_MIN_SPACE
55+
5356enum ppp_driver_state {
5457 STATE_HDLC_FRAME_START ,
5558 STATE_HDLC_FRAME_ADDRESS ,
@@ -59,6 +62,33 @@ enum ppp_driver_state {
5962#define PPP_WORKQ_PRIORITY CONFIG_NET_PPP_RX_PRIORITY
6063#define PPP_WORKQ_STACK_SIZE CONFIG_NET_PPP_RX_STACK_SIZE
6164
65+ #define UART_RTS_NODE DT_ALIAS(ppp_uart_rts)
66+
67+ /*
68+ * Note regarding synchronization: this variable is written both from a thread and an interrupt,
69+ * however since the interrupt only writes the variable when the ring buffer is (mostly) full and
70+ * the thread only when the ring buffer is empty, there is no issue in reality (there might be an
71+ * issue in case of the dongle, which uses USB CDC ACM instead of UART though).
72+ */
73+ static bool uart_ready_for_data = true;
74+
75+ static void flow_control_set_rts (const struct device * uart , const bool ready_for_data ) {
76+ if (uart_ready_for_data == ready_for_data ) {
77+ return ;
78+ }
79+ uart_ready_for_data = ready_for_data ;
80+
81+ #ifdef CONFIG_UART_LINE_CTRL
82+ uart_line_ctrl_set (uart , UART_LINE_CTRL_RTS , ready_for_data ? 1 : 0 );
83+ #else /* CONFIG_UART_LINE_CTRL */
84+ if (ready_for_data ) {
85+ uart_irq_rx_enable (uart );
86+ } else {
87+ uart_irq_rx_disable (uart );
88+ }
89+ #endif /* CONFIG_UART_LINE_CTRL */
90+ }
91+
6292K_KERNEL_STACK_DEFINE (ppp_workq , PPP_WORKQ_STACK_SIZE );
6393
6494struct ppp_driver_context {
@@ -888,6 +918,11 @@ static int ppp_consume_ringbuf(struct ppp_driver_context *ppp)
888918 LOG_DBG ("Cannot flush ring buffer (%d)" , ret );
889919 }
890920
921+ if (ring_buf_is_empty (& ppp -> rx_ringbuf )) {
922+ LOG_DBG ("ringbuf empty, enabling UART" );
923+ flow_control_set_rts (ppp -> dev , true);
924+ }
925+
891926 return - EAGAIN ;
892927}
893928
@@ -1029,6 +1064,11 @@ static void ppp_uart_isr(const struct device *uart, void *user_data)
10291064 break ;
10301065 }
10311066
1067+ if (ring_buf_space_get (& context -> rx_ringbuf ) < RX_RINGBUF_MIN_SPACE ) {
1068+ LOG_DBG ("ringbuf almost full, disabling UART" );
1069+ flow_control_set_rts (uart , false);
1070+ }
1071+
10321072 k_work_submit_to_queue (& context -> cb_workq , & context -> cb_work );
10331073 }
10341074}
0 commit comments