This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 8ba084329d59920d865130d5e31a43091b61798c Author: Bowen Wang <[email protected]> AuthorDate: Wed Dec 4 23:27:04 2024 +0800 rpmsg/rpmsg_port_uart: add wakeup feauture for rpmsg_port_uart Wakeup peer when peer is in low power mode Signed-off-by: Bowen Wang <[email protected]> --- drivers/rpmsg/rpmsg_port_uart.c | 143 ++++++++++++++++++++++++++++------------ 1 file changed, 102 insertions(+), 41 deletions(-) diff --git a/drivers/rpmsg/rpmsg_port_uart.c b/drivers/rpmsg/rpmsg_port_uart.c index cf49e05ab2f..1556ab71a58 100644 --- a/drivers/rpmsg/rpmsg_port_uart.c +++ b/drivers/rpmsg/rpmsg_port_uart.c @@ -31,10 +31,11 @@ #include <stdio.h> #include <nuttx/crc16.h> +#include <nuttx/fs/fs.h> #include <nuttx/kmalloc.h> #include <nuttx/kthread.h> #include <nuttx/mutex.h> -#include <nuttx/fs/fs.h> +#include <nuttx/semaphore.h> #include "rpmsg_port.h" @@ -43,10 +44,13 @@ ****************************************************************************/ #define RPMSG_PORT_UART_START 0x7f -#define RPMSG_PORT_UART_END 0x7e -#define RPMSG_PORT_UART_CONNREQ 0x7d -#define RPMSG_PORT_UART_CONNACK 0x7c -#define RPMSG_PORT_UART_ESCAPE 0x7b +#define RPMSG_PORT_UART_CONNREQ 0x7e +#define RPMSG_PORT_UART_CONNACK 0x7d +#define RPMSG_PORT_UART_ESCAPE 0x7c +#define RPMSG_PORT_UART_SUSPEND 0x7b +#define RPMSG_PORT_UART_RESUME 0x7a +#define RPMSG_PORT_UART_WAKEUP 0x79 +#define RPMSG_PORT_UART_END 0x78 #define RPMSG_PORT_UART_ESCAPE_MASK 0x20 #define RPMSG_PORT_UART_BUFLEN 256 @@ -55,6 +59,8 @@ #define RPMSG_PORT_UART_RX_RECV_NORMAL 2 #define RPMSG_PORT_UART_RX_RECV_ESCAPE 3 +#define RPMSG_PORT_UART_WAKEUP_TIMEOUT MSEC2TICK(100) + #ifdef CONFIG_RPMSG_PORT_UART_CRC # define rpmsg_port_uart_crc16(hdr) \ crc16ibm((FAR uint8_t *)&(hdr)->cmd, (hdr)->len - sizeof((hdr)->crc)) @@ -64,7 +70,7 @@ #ifdef CONFIG_RPMSG_PORT_UART_DEBUG # define rpmsgdump lib_dumpbuffer -# define rpmsgdbg rpmsginfo +# define rpmsgdbg rpmsgerr #else # define rpmsgdump(m,b,s) # define rpmsgdbg(fmt,...) @@ -80,6 +86,7 @@ struct rpmsg_port_uart_s struct file file; /* Indicate uart device */ char localcpu[RPMSG_NAME_SIZE]; rpmsg_port_rx_cb_t rx_cb; + sem_t wake; bool connected; }; @@ -108,6 +115,75 @@ static const struct rpmsg_port_ops_s g_rpmsg_port_uart_ops = * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: rpmsg_port_uart_send_one + ****************************************************************************/ + +static inline void +rpmsg_port_uart_send_one(FAR struct rpmsg_port_uart_s *rpuart, uint8_t ch) +{ + ssize_t ret = file_write(&rpuart->file, &ch, 1); + if (ret != 1) + { + rpmsgerr("Send ch %u failed, ret=%zd\n", ch, ret); + PANIC(); + } +} + +/**************************************************************************** + * Name: rpmsg_port_uart_send_command + ****************************************************************************/ + +static inline void +rpmsg_port_uart_send_command(FAR struct rpmsg_port_uart_s *rpuart, + uint8_t cmd) +{ + if (cmd != RPMSG_PORT_UART_WAKEUP) + { + rpmsg_port_uart_send_one(rpuart, RPMSG_PORT_UART_WAKEUP); + } + + rpmsg_port_uart_send_one(rpuart, cmd); +} + +/**************************************************************************** + * Name: rpmsg_port_uart_wakeup + * + * Description: + * Send wakeup data to peer if peer is suspended. + * + ****************************************************************************/ + +static inline void +rpmsg_port_uart_wakeup(FAR struct rpmsg_port_uart_s *rpuart) +{ + int ret; + + /* Try first, if peer is in suspend state, start send the wakeup byte */ + + ret = nxsem_trywait(&rpuart->wake); + if (ret >= 0) + { + nxsem_post(&rpuart->wake); + return; + } + + for (; ; ) + { + rpmsgdbg("Try to wakeup peer\n"); + rpmsg_port_uart_send_command(rpuart, RPMSG_PORT_UART_WAKEUP); + + ret = nxsem_tickwait(&rpuart->wake, RPMSG_PORT_UART_WAKEUP_TIMEOUT); + if (ret >= 0) + { + nxsem_post(&rpuart->wake); + break; + } + } + + rpmsgdbg("Wakeup peer success\n"); +} + /**************************************************************************** * Name: rpmsg_port_uart_send_packet * @@ -119,6 +195,8 @@ static const struct rpmsg_port_ops_s g_rpmsg_port_uart_ops = static void rpmsg_port_uart_send_packet(FAR struct rpmsg_port_uart_s *rpuart, FAR const void *data, size_t datalen) { + rpmsg_port_uart_wakeup(rpuart); + rpmsgdump("TX Packed Data", data, datalen); while (datalen > 0) @@ -157,7 +235,7 @@ static void rpmsg_port_uart_send_frame(FAR struct rpmsg_port_uart_s *rpuart, for (; datalen-- > 0; data = (FAR uint8_t *)data + 1) { ch = *(FAR uint8_t *)data; - if (ch >= RPMSG_PORT_UART_ESCAPE && ch <= RPMSG_PORT_UART_START) + if (ch >= RPMSG_PORT_UART_END && ch <= RPMSG_PORT_UART_START) { buf[next++] = RPMSG_PORT_UART_ESCAPE; buf[next++] = ch ^ RPMSG_PORT_UART_ESCAPE_MASK; @@ -203,38 +281,6 @@ static void rpmsg_port_uart_send_data(FAR struct rpmsg_port_uart_s *rpuart, rpmsg_port_uart_send_frame(rpuart, hdr, hdr->len); } -/**************************************************************************** - * Name: rpmsg_port_uart_send_connect_req - ****************************************************************************/ - -static void -rpmsg_port_uart_send_connect_req(FAR struct rpmsg_port_uart_s *rpuart) -{ - uint8_t ch = RPMSG_PORT_UART_CONNREQ; - ssize_t ret = file_write(&rpuart->file, &ch, 1); - if (ret != 1) - { - rpmsgerr("Send connect request failed, ret=%zd\n", ret); - PANIC(); - } -} - -/**************************************************************************** - * Name: rpmsg_port_uart_send_connect_ack - ****************************************************************************/ - -static void -rpmsg_port_uart_send_connect_ack(FAR struct rpmsg_port_uart_s *rpuart) -{ - uint8_t ch = RPMSG_PORT_UART_CONNACK; - ssize_t ret = file_write(&rpuart->file, &ch, 1); - if (ret != 1) - { - rpmsgerr("Send connect ack failed, ret=%zd\n", ret); - PANIC(); - } -} - /**************************************************************************** * Name: rpmsg_port_uart_register_callback ****************************************************************************/ @@ -268,7 +314,7 @@ rpmsg_port_uart_process_rx_conn(FAR struct rpmsg_port_uart_s *rpuart, rpuart->connected = true; } - rpmsg_port_uart_send_connect_ack(rpuart); + rpmsg_port_uart_send_command(rpuart, RPMSG_PORT_UART_CONNACK); rpmsg_port_register(&rpuart->port, rpuart->localcpu); } else if (ch == RPMSG_PORT_UART_CONNACK) @@ -325,6 +371,18 @@ static int rpmsg_port_uart_rx_thread(int argc, FAR char *argv[]) state = RPMSG_PORT_UART_RX_WAIT_START; continue; } + else if (buf[i] == RPMSG_PORT_UART_SUSPEND) + { + rpmsgdbg("Received suspend command\n"); + nxsem_wait(&rpuart->wake); + continue; + } + else if (buf[i] == RPMSG_PORT_UART_RESUME) + { + rpmsgdbg("Received resume command\n"); + nxsem_post(&rpuart->wake); + continue; + } if (rpuart->connected == false) { @@ -403,7 +461,7 @@ static int rpmsg_port_uart_tx_thread(int argc, FAR char *argv[]) FAR struct rpmsg_port_queue_s *txq = &rpuart->port.txq; FAR struct rpmsg_port_header_s *hdr; - rpmsg_port_uart_send_connect_req(rpuart); + rpmsg_port_uart_send_command(rpuart, RPMSG_PORT_UART_CONNREQ); for (; ; ) { @@ -456,6 +514,8 @@ int rpmsg_port_uart_initialize(FAR const struct rpmsg_port_config_s *cfg, return -ENOMEM; } + nxsem_init(&rpuart->wake, 0, 1); + /* Hardware initialize */ ret = file_open(&rpuart->file, uartpath, O_RDWR); @@ -515,6 +575,7 @@ err_rx_thread: err_rpmsg_port: file_close(&rpuart->file); err_file: + nxsem_destroy(&rpuart->wake); kmm_free(rpuart); return ret; }
