Просмотр исходного кода

Merge pull request #8 from xfan1024/devel

Rewrite ppp_recv thread
朱天龙 (Armink) 6 лет назад
Родитель
Сommit
bbb30fea55

+ 3 - 17
class/air720/ppp_device_air720.c

@@ -31,29 +31,15 @@ static const struct modem_chat_data mcd[] =
     {PPP_DAIL_CMD,   MODEM_CHAT_RESP_CONNECT,         2, 30, RT_FALSE},
 };
 
-/*
- * Get into PPP modem,using uart
- *
- * @param NULL
- *
- * @return  0: execute successful
- *         -1: send AT commands error
- *         -5: no memory
- */
-static rt_err_t ppp_air720_open(struct ppp_device *device, rt_uint16_t oflag)
+static rt_err_t ppp_air720_prepare(struct ppp_device *device)
 {
-    RT_ASSERT(device != RT_NULL);
-
-    return modem_chat(device->uart_name, mcd, sizeof(mcd) / sizeof(mcd[0]));
+    return modem_chat(device->uart, mcd, sizeof(mcd) / sizeof(mcd[0]));
 }
 
 /* ppp_air720_ops for ppp_device_ops , a common interface */
 static struct ppp_device_ops air720_ops =
 {
-    RT_NULL,
-    ppp_air720_open,
-    RT_NULL,
-    RT_NULL,
+    .prepare = ppp_air720_prepare,
 };
 
 /*

+ 36 - 20
class/m6312/ppp_device_m6312.c

@@ -10,6 +10,7 @@
 
 #include <ppp_device_m6312.h>
 #include <ppp_chat.h>
+#include <rtdevice.h>
 
 #define DBG_TAG    "ppp.m6312"
 
@@ -19,42 +20,52 @@
 #define DBG_LVL   DBG_INFO
 #endif
 
+#define M6312_POWER_ON  PIN_HIGH
+#define M6312_POWER_OFF PIN_LOW
+#ifndef M6312_POWER_PIN
+#define M6312_POWER_PIN -1
+#endif
+
 #include <rtdbg.h>
 
-static const struct modem_chat_data mcd[] =
+static const struct modem_chat_data rst_mcd[] =
 {
     {"+++",          MODEM_CHAT_RESP_OK,        10, 1, RT_FALSE},
     {"ATH",          MODEM_CHAT_RESP_OK,        1,  1, RT_FALSE},
     {"AT+CMRESET",   MODEM_CHAT_RESP_NOT_NEED,  1,  1, RT_FALSE},
+};
+
+static const struct modem_chat_data mcd[] =
+{
     {"AT",           MODEM_CHAT_RESP_OK,        10, 1, RT_FALSE},
     {"ATE0",         MODEM_CHAT_RESP_OK,        1,  1, RT_FALSE},
     {PPP_APN_CMD,    MODEM_CHAT_RESP_OK,        1,  5, RT_FALSE},
     {PPP_DAIL_CMD,   MODEM_CHAT_RESP_CONNECT,   2, 30, RT_FALSE},
 };
 
-/*
- * Get into PPP modem,using uart
- *
- * @param NULL
- *
- * @return  0: execute successful
- *         -1: send AT commands error
- *         -5: no memory
- */
-static rt_err_t ppp_m6312_open(struct ppp_device *device, rt_uint16_t oflag)
+static rt_err_t ppp_m6312_prepare(struct ppp_device *device)
 {
-    RT_ASSERT(device != RT_NULL);
-
-    return modem_chat(device->uart_name, mcd, sizeof(mcd) / sizeof(mcd[0]));
+    struct ppp_m6312 *m6312 = (struct ppp_m6312*)device;
+    if (m6312->power_pin >= 0)
+    {
+        rt_pin_write(m6312->power_pin, M6312_POWER_OFF);
+        rt_thread_mdelay(500);
+        rt_pin_write(m6312->power_pin, M6312_POWER_ON);
+    }
+    else
+    {
+        rt_err_t err;
+        err = modem_chat(device->uart, rst_mcd, sizeof(rst_mcd) / sizeof(rst_mcd[0]));
+        if (err)
+            return err;
+    }
+    return modem_chat(device->uart, mcd, sizeof(mcd) / sizeof(mcd[0]));
 }
 
 /* ppp_m6312_ops for ppp_device_ops , a common interface */
 static struct ppp_device_ops m6312_ops =
 {
-    RT_NULL,
-    ppp_m6312_open,
-    RT_NULL,
-    RT_NULL,
+    .prepare = ppp_m6312_prepare,
 };
 
 /*
@@ -79,11 +90,16 @@ int ppp_m6312_register(void)
         return -RT_ENOMEM;
     }
 
+    m6312->power_pin = M6312_POWER_PIN;
+    if (m6312->power_pin >= 0)
+    {
+        rt_pin_mode(m6312->power_pin, PIN_MODE_OUTPUT);
+        rt_pin_write(m6312->power_pin, M6312_POWER_OFF);
+    }
+
     ppp_device = &(m6312->device);
     ppp_device->ops = &m6312_ops;
-
     LOG_D("ppp m6312 is registering ppp_device");
-
     return ppp_device_register(ppp_device, PPP_DEVICE_NAME, RT_NULL, RT_NULL);
 }
 INIT_COMPONENT_EXPORT(ppp_m6312_register);

+ 1 - 0
class/m6312/ppp_device_m6312.h

@@ -18,6 +18,7 @@ struct ppp_m6312
 {
     struct ppp_device  device;          /* ppp_device struct in ppp_m6312 */
     enum ppp_trans_type type;           /* the type is used to establish a ppp connection */
+    rt_base_t power_pin;
 };
 
 extern int ppp_m6312_register(void);

+ 3 - 17
class/sim800/ppp_device_sim800.c

@@ -31,29 +31,15 @@ static const struct modem_chat_data mcd[] =
     {PPP_DAIL_CMD,   MODEM_CHAT_RESP_CONNECT,         1, 30, RT_FALSE},
 };
 
-/*
- * Get into PPP modem,using uart
- *
- * @param NULL
- *
- * @return  0: execute successful
- *         -1: send AT commands error
- *         -5: no memory
- */
-static rt_err_t ppp_sim800_open(struct ppp_device *device, rt_uint16_t oflag)
+static rt_err_t ppp_sim800_prepare(struct ppp_device *device)
 {
-    RT_ASSERT(device != RT_NULL);
-
-    return modem_chat(device->uart_name, mcd, sizeof(mcd) / sizeof(mcd[0]));
+    return modem_chat(device->uart, mcd, sizeof(mcd) / sizeof(mcd[0]));
 }
 
 /* ppp_sim800_ops for ppp_device_ops , a common interface */
 static struct ppp_device_ops sim800_ops =
 {
-    RT_NULL,
-    ppp_sim800_open,
-    RT_NULL,
-    RT_NULL,
+    .prepare = ppp_sim800_prepare,
 };
 
 /*

+ 1 - 1
inc/ppp_chat.h

@@ -38,6 +38,6 @@ struct modem_chat_data {
     rt_bool_t  ignore_cr;   // ignore CR character if it is RT_TRUE
 };
 
-rt_err_t modem_chat(char *uart_name, const struct modem_chat_data *data, rt_size_t len);
+rt_err_t modem_chat(rt_device_t serial, const struct modem_chat_data *data, rt_size_t len);
 
 #endif  /* __MODEM_CHAT_H__ */

+ 17 - 12
inc/ppp_device.h

@@ -36,6 +36,10 @@
 #define PPP_CTL_GET_CSQ      1
 #define PPP_CTL_GET_IEMI     2
 #define PPP_CTL_GET_TYPE     3
+#define PPP_CTL_PREPARE      10
+
+#define PPP_FRAME_MAX       1550
+#define PPP_DROP_BUF        PPP_FRAME_MAX
 
 enum ppp_trans_type
 {
@@ -56,31 +60,32 @@ enum ppp_conn_type
 struct ppp_device
 {
     struct rt_device parent;                    /* join rt_device frame */
-    char *uart_name;                            /* the name of the low-level driver device */
+    rt_device_t uart;                           /* low-level uart device object */
     const struct ppp_device_ops *ops;           /* ppp device ops interface */
     enum ppp_conn_type conn_type;               /* using usb or uart */
 
     ppp_pcb *pcb;                               /* ppp protocol control block */
     struct netif pppif;
 
-    char *recv_line_buf;                        /* the current received one line data buffer */
-    rt_size_t recv_line_len;                    /* The length of the currently received one line data */
-    rt_size_t recv_bufsz;                       /* The maximum supported receive data length */
+#ifdef PPP_DEVICE_DEBUG_DROP
+    rt_size_t  dropcnt;                         /* counter of drop bytes */
+    rt_size_t  droppos;                         /* valid size of drop buffer */
+    rt_uint8_t dropbuf[PPP_DROP_BUF];           /* drop buffer */
+#endif
+
+    rt_size_t  rxpos;                           /* valid size of receive frame buffer */
+    rt_uint8_t rxbuf[PPP_FRAME_MAX];            /* receive frame buffer */
+    rt_uint8_t state;                           /* internal state */
 
-    rt_sem_t rx_notice;                         /* attention uart to recieve data delivery to tcpip */
-    rt_mutex_t lock;                            /* protect uart */
+    struct rt_event event;                      /* interthread communication */
 
     rt_thread_t recv_tid;                       /* recieve thread point */
-    rt_bool_t ppp_link_status;                  /* if ppp link is shut down, close recieve thread and shut down */
     void *user_data;                            /* reserve */
 };
 
 struct ppp_device_ops
 {
-    rt_err_t  (*init)   (struct ppp_device *dev);
-    rt_err_t  (*open)   (struct ppp_device *dev, rt_uint16_t oflag);
-    rt_err_t  (*close)  (struct ppp_device *dev);
-    rt_err_t  (*control)(struct ppp_device *dev, int cmd, void *args);
+    rt_err_t  (*prepare)   (struct ppp_device *dev);
 };
 
 enum ppp_reci_status
@@ -95,7 +100,7 @@ typedef  rt_err_t (*uart_rx_cb)(rt_device_t dev, rt_size_t size);
 
 /* offer register funciton to user */
 int ppp_device_register(struct ppp_device *ppp_device, const char *dev_name, const char *uart_name, void *user_data);
-int ppp_device_attach(struct ppp_device *ppp_device, char *uart_name, void *user_data);
+int ppp_device_attach(struct ppp_device *ppp_device, const char *uart_name, void *user_data);
 int ppp_device_detach(struct ppp_device *ppp_device);
 
 #endif /* __PPP_DEVICE_H__ */

+ 19 - 0
samples/ppp_sample.c

@@ -60,3 +60,22 @@ int ppp_sample_stop(void)
     return RT_EOK;
 }
 MSH_CMD_EXPORT_ALIAS(ppp_sample_stop, ppp_stop, a sample of ppp device for turning off network);
+
+#ifdef PPP_DEVICE_DEBUG_DROP
+static int ppp_drop(void)
+{
+    rt_device_t device = RT_NULL;
+    struct ppp_device *ppp_device;
+    device = rt_device_find(PPP_DEVICE_NAME);
+    if(device == RT_NULL)
+    {
+        LOG_E("Can't find device (%s).", PPP_DEVICE_NAME);
+        return -RT_ERROR;
+    }
+    ppp_device = (struct ppp_device*)device;
+    LOG_I("%ld", (unsigned long)(ppp_device->dropcnt + ppp_device->droppos));
+    return RT_EOK;
+ }
+
+MSH_CMD_EXPORT_ALIAS(ppp_drop, ppp_drop, show drop statistics);
+#endif

+ 1 - 28
src/ppp_chat.c

@@ -230,36 +230,11 @@ static rt_err_t modem_chat_internal(rt_device_t serial, const struct modem_chat_
  * @return  0: execute successful
  *
  */
-rt_err_t modem_chat(char *uart_name, const struct modem_chat_data *data, rt_size_t len)
+rt_err_t modem_chat(rt_device_t serial, const struct modem_chat_data *data, rt_size_t len)
 {
     rt_err_t (*old_rx_ind)(rt_device_t dev, rt_size_t size) = RT_NULL;
 
     rt_err_t err = RT_EOK;
-    rt_device_t serial = RT_NULL;
-    rt_uint16_t oflag = 0;
-
-    serial = rt_device_find(uart_name);
-    if (serial == RT_NULL)
-    {
-        LOG_E("Can't find uart device %s.", uart_name);
-        return -RT_ERROR;
-    }
-
-    oflag = RT_DEVICE_OFLAG_RDWR;
-
-    if (serial->flag & RT_DEVICE_FLAG_DMA_RX)
-        oflag |= RT_DEVICE_FLAG_DMA_RX;
-    else if (serial->flag & RT_DEVICE_FLAG_INT_RX)
-        oflag |= RT_DEVICE_FLAG_INT_RX;
-
-    if (serial->flag & RT_DEVICE_FLAG_DMA_TX)
-        oflag |= RT_DEVICE_FLAG_DMA_TX;
-
-    if (rt_device_open(serial, oflag) != RT_EOK)
-    {
-        LOG_E("(%s) open failed.", uart_name);
-        return -RT_ERROR;
-    }
 
     rt_completion_init(&rx_comp_p);
     old_rx_ind = serial->rx_indicate;
@@ -270,10 +245,8 @@ rt_err_t modem_chat(char *uart_name, const struct modem_chat_data *data, rt_size
     if (err != RT_EOK)
     {
         LOG_E("chat failed");
-        goto __exit;
     }
 
     serial->rx_indicate = old_rx_ind;
-__exit:
     return err;
 }

+ 284 - 227
src/ppp_device.c

@@ -6,6 +6,7 @@
  * Change Logs:
  * Date           Author          Notes
  * 2019-08-15     xiangxistu      the first version
+ * 2019-10-01     xiaofan         rewrite ppp_recv thread
  */
 
 #include <ppp_device.h>
@@ -21,10 +22,23 @@
 
 #include <rtdbg.h>
 
+enum {
+    PPP_STATE_PREPARE,
+    PPP_STATE_WAIT_HEAD,
+    PPP_STATE_RECV_DATA,
+};
+
 #define PPP_DATA_BEGIN_END       0x7e
 #define DATA_EFFECTIVE_FLAG      0x00
 #define RECON_ERR_COUNTS         0x02
 #define PPP_RECONNECT_TIME       2500
+#define PPP_RECV_READ_MAX        32
+
+
+#define PPP_EVENT_RX_NOTIFY 1   // serial incoming a byte
+#define PPP_EVENT_LOST      2   // PPP connection is lost
+#define PPP_EVENT_CLOSE_REQ 4   // user want close ppp_device
+#define PPP_EVENT_CLOSED    8   // ppp_recv thread will send CLOSED event when ppp_recv thread is safe exit
 
 #if RT_LWIP_TCPTHREAD_STACKSIZE < 2048
 #error "tcpip stack is too small, should greater than 2048."
@@ -33,6 +47,42 @@
 
 static struct ppp_device *_g_ppp_device = RT_NULL;
 
+static void ppp_debug_hexdump(const void *data, size_t len)
+{
+#ifdef PPP_DEVICE_DEBUG
+    const size_t maxlen = 16;
+    rt_uint32_t offset = 0;
+    size_t curlen;
+    char line[maxlen*4+3];
+    char *p;
+    const unsigned char *src = data;
+
+    while (len > 0)
+    {
+        curlen = len < maxlen ? len : maxlen;
+        p = line;
+        for (size_t i = 0; i < curlen; i++)
+        {
+            rt_sprintf(p, "%02x ", (unsigned char)src[i]);
+            p += 3;
+        }
+        memset(p, ' ', (maxlen - curlen) * 3);
+        p += (maxlen - curlen) * 3;
+        *p++ = '|';
+        *p++ = ' ';
+        for (size_t i = 0; i < curlen; i++)
+        {
+            *p++ = (0x20 < src[i] && src[i] < 0x7e) ? src[i] : '.';
+        }
+        *p++ = '\0';
+        LOG_D("[%04x] %s", offset, line);
+        len -= curlen;
+        src += curlen;
+        offset += curlen;
+    }
+#endif
+}
+
 /*
  * Receive callback function , release rx_notice when uart acquire data
  *
@@ -48,25 +98,8 @@ static rt_err_t ppp_device_rx_ind(rt_device_t dev, rt_size_t size)
     struct ppp_device *ppp_dev = _g_ppp_device;
 
     /* when recieve data from uart , release semphone to wake up recieve thread */
-    rt_sem_release(ppp_dev->rx_notice);
-
-    return RT_EOK;
-}
-
-static rt_err_t ppp_device_getchar(rt_device_t recv_dev,rt_sem_t rx_notice, char *ch, rt_int32_t timeout)
-{
-    rt_err_t result = RT_EOK;
-
-    while (rt_device_read(recv_dev, 0, ch, 1) == 0)
-    {
-        rt_sem_control(rx_notice, RT_IPC_CMD_RESET, RT_NULL);
+    rt_event_send(&ppp_dev->event, PPP_EVENT_RX_NOTIFY);
 
-        result = rt_sem_take(rx_notice, rt_tick_from_millisecond(timeout));
-        if (result != RT_EOK)
-        {
-            return result;
-        }
-    }
     return RT_EOK;
 }
 
@@ -86,33 +119,17 @@ static uint32_t ppp_data_send(ppp_pcb *pcb, uint8_t *data, uint32_t len, void *p
     RT_ASSERT(pcb != RT_NULL);
     RT_ASSERT(ppp_device != RT_NULL);
 
-    int result = RT_EOK;
     struct ppp_device *device = (struct ppp_device *)ppp_device;
-    rt_device_t recv_device = RT_NULL;
 
-    RT_ASSERT(device != RT_NULL);
-
-    if(device->ppp_link_status != RT_TRUE)
-        goto __exit;
-
-    /* recv_device is rt_device , find recv_device through device name */
-    recv_device = rt_device_find(device->uart_name);
-    if (recv_device == RT_NULL)
-    {
-        LOG_E("Can find device (%s), ppp send data execute failed.",device->uart_name);
-        result = -RT_ERROR;
-        goto __exit;
-    }
+    if (device->state == PPP_STATE_PREPARE)
+        return 0;
 
+#ifdef PPP_DEVICE_DEBUG_TX
+    LOG_D("TX:");
+    ppp_debug_hexdump(data, len);
+#endif
     /* the return data is the actually written size on successful */
-    len = rt_device_write(recv_device,0,data,len);
-
-    /* must be return data length , or will get warning like "pppos_write[0]: output failed len=24" */
-    return len;
-
-__exit:
-
-    return result;
+    return rt_device_write(device->uart, 0, data, len);
 }
 
 /*
@@ -129,16 +146,10 @@ static void ppp_status_changed(ppp_pcb *pcb, int err_code, void *ctx)
 {
     struct ppp_device *pppdev = (struct ppp_device *)ctx;
     struct netif *pppif = ppp_netif(pcb);
-    static uint8_t re_count = 0;
     switch (err_code)
     {
     case PPPERR_NONE:                /* Connected */
         pppdev->pppif.mtu = pppif->mtu;
-        if (pppdev->ppp_link_status == 1)
-        {
-            ppp_netdev_add(&pppdev->pppif);
-        }
-        re_count = 0;
         LOG_I("ppp connect successful.");
         break;
     case PPPERR_PARAM:
@@ -154,12 +165,10 @@ static void ppp_status_changed(ppp_pcb *pcb, int err_code, void *ctx)
         LOG_E("Unable to allocate resources.");
         break;
     case PPPERR_USER:
-        pppapi_free(pcb);           /* Free the PPP control block */
+        LOG_D("User interrupt");
         break;
     case PPPERR_CONNECT:            /* Connection lost */
         LOG_E("ppp connect lost.");
-        pppapi_connect(pcb, 0);
-        LOG_I("Reconnection.");
         break;
     case PPPERR_AUTHFAIL:
         LOG_E("Failed authentication challenge.");
@@ -169,20 +178,6 @@ static void ppp_status_changed(ppp_pcb *pcb, int err_code, void *ctx)
         break;
     case PPPERR_PEERDEAD:
         LOG_E("Connection timeout.");
-        pppapi_connect(pcb, 0);
-        if (re_count++ == RECON_ERR_COUNTS)
-        {
-            re_count = 0;
-            pppdev->ppp_link_status = 0;
-            if (!(pppdev->parent.close && pppdev->parent.close((rt_device_t)pppdev)))
-            {
-                LOG_E("ppp_device close failed.");
-            }
-        }
-        else
-        {
-             LOG_I("Reconnection.");
-        }
         break;
     case PPPERR_IDLETIMEOUT:
         LOG_E("Idle Timeout.");
@@ -197,110 +192,216 @@ static void ppp_status_changed(ppp_pcb *pcb, int err_code, void *ctx)
         LOG_E("Unknown error code %d.", err_code);
         break;
     }
+    if (err_code != PPPERR_NONE)
+        rt_event_send(&pppdev->event, PPP_EVENT_LOST);
 }
 
-/*
- * Receive thread , store uart data and transform tcpip stack
- *
- * @param ppp_device *device
- *
- *
- * @return  0: execute successful
- *
- */
-static int ppp_recv_entry(struct ppp_device *device)
+static inline void ppp_start_receive_frame(struct ppp_device *device)
 {
-    RT_ASSERT(device != RT_NULL);
+    device->rxpos = 0;
+    device->state = PPP_STATE_WAIT_HEAD;
+}
 
-    char ch = 0, old_ch = 0;
-    int result = RT_EOK;
-    static char thrans_flag = 0;
-    rt_device_t recv_dev = RT_NULL;
-    device->recv_line_len = 0;
+#ifdef PPP_DEVICE_DEBUG_DROP
+static inline void ppp_show_dropbuf(struct ppp_device *device)
+{
+    if (!device->droppos)
+        return;
+    LOG_D("DROP: ");
+    ppp_debug_hexdump(device->dropbuf, device->droppos);
+    device->dropcnt += device->droppos;
+    device->droppos = 0;
+}
 
-    /* alloc buff to store uart data */
-    device->recv_line_buf = (char *)rt_calloc(1, 1550);
-    if (device->recv_line_buf == RT_NULL)
-    {
-        LOG_E("ppp_recv_line_buff alloc memory failed! No memory for receive buffer.");
-        result = -RT_ENOMEM;
-        goto __exit;
-    }
+static inline void ppp_show_rxbuf_as_drop(struct ppp_device *device)
+{
+    if (!device->rxpos)
+        return;
+    LOG_D("DROP: ");
+    ppp_debug_hexdump(device->rxbuf, device->rxpos);
+    device->dropcnt += device->rxpos;
+    device->rxpos = 0;
+}
 
-    /* use name to find rt_devcie */
-    recv_dev = rt_device_find(device->uart_name);
-    if (recv_dev == RT_NULL)
+static inline void ppp_rxbuf_drop(struct ppp_device *device)
+{
+    // if we have no enough drop-buffer, we should display and clear drop-buffer
+    if (PPP_DROP_BUF - device->droppos < device->rxpos)
     {
-        LOG_E("Can find device (%s), ppp recv entry creat failed.",device->uart_name);
-        result = -RT_ERROR;
-        goto __exit;
+        ppp_show_dropbuf(device);
+        // if our drop-buffer size less than or equal current valid size of rx-buffer, we should display and clear rx-buffer
+        if (PPP_DROP_BUF <= device->rxpos)
+        {
+            ppp_show_rxbuf_as_drop(device);
+        }
     }
 
-    while (1)
+    if (device->rxpos)
     {
-        /* ppp link is closed, the recieve thread also need to exit */
-        if (device->ppp_link_status != RT_TRUE)
+        rt_memcpy(&device->dropbuf[device->droppos], device->rxbuf, device->rxpos);
+        device->droppos += device->rxpos;
+        device->rxpos = 0;
+
+        if (device->droppos == PPP_DROP_BUF)
         {
-            break;
+            ppp_show_dropbuf(device);
         }
+    }
 
-        /* waitting for get data, more secure way to deal information */
-        ppp_device_getchar(recv_dev, device->rx_notice, &ch, RT_WAITING_FOREVER);
+    ppp_start_receive_frame(device);
+}
+
+#else
+static inline void ppp_show_dropbuf(struct ppp_device *device) {}
+#define ppp_rxbuf_drop(device) ppp_start_receive_frame(device)
+#endif // !PPP_DEVICE_DEBUG_DROP
 
-        /* begin to recieve data from uart */
-        if (thrans_flag == PPP_DATA_START)
+static inline void ppp_processdata_enter(struct ppp_device *device)
+{
+    ppp_start_receive_frame(device);
+#ifdef PPP_DEVICE_DEBUG_DROP
+    device->droppos = 0;
+#endif
+}
+
+static inline void ppp_processdata_leave(struct ppp_device *device)
+{
+    ppp_rxbuf_drop(device);
+    ppp_show_dropbuf(device);
+}
+
+static inline void ppp_savebyte(struct ppp_device *device, rt_uint8_t dat)
+{
+    RT_ASSERT(device->rxpos < sizeof(device->rxbuf));
+    device->rxbuf[device->rxpos++] = dat;
+}
+
+static void ppp_recv_processdata(struct ppp_device *device, const rt_uint8_t *buf, rt_size_t len)
+{
+    rt_uint8_t dat;
+
+    while (len--)
+    {
+        dat = *buf++;
+
+process_dat:
+        switch (device->state)
         {
-            /* if recieve 0x7e twice */
-            if (ch == PPP_DATA_BEGIN_END && old_ch == PPP_DATA_BEGIN_END)
+        case PPP_STATE_WAIT_HEAD:
+            ppp_savebyte(device, dat);
+            if (dat == PPP_DATA_BEGIN_END)
             {
-                /* choice the least 0x7e as frame head */
-                device->recv_line_buf[0] = ch;
-                device->recv_line_len = 1;
-
-                old_ch = ch;
+                ppp_show_dropbuf(device);
+                device->state = PPP_STATE_RECV_DATA;
             }
-            else if (ch == PPP_DATA_BEGIN_END && old_ch == DATA_EFFECTIVE_FLAG)
+            else
             {
-                thrans_flag = PPP_DATA_END;
-                device->recv_line_buf[device->recv_line_len] = ch;
+                ppp_rxbuf_drop(device);
             }
-            else
+            break;
+        case PPP_STATE_RECV_DATA:
+            if (dat == PPP_DATA_BEGIN_END && device->rxpos == 1)
             {
-                old_ch = DATA_EFFECTIVE_FLAG;
-                device->recv_line_buf[device->recv_line_len] = ch;
-                device->recv_line_len++;
+                LOG_D("found continuous 0x7e");
+                // start receive a new frame
+                ppp_rxbuf_drop(device);
+                goto process_dat;
             }
-
-            /* when a frame is end, put data into tcpip */
-            if (thrans_flag == PPP_DATA_END)
+            ppp_savebyte(device, dat);
+            if (dat == PPP_DATA_BEGIN_END)
             {
+#ifdef PPP_DEVICE_DEBUG_RX
+                LOG_D("RX:");
+                ppp_debug_hexdump(device->rxbuf, device->rxpos);
+#endif
                 rt_enter_critical();
-                pppos_input_tcpip(device->pcb, (u8_t *)device->recv_line_buf, device->recv_line_len + 1);
+                pppos_input_tcpip(device->pcb, (u8_t *)device->rxbuf, device->rxpos);
                 rt_exit_critical();
-
-                thrans_flag = PPP_DATA_VERIFY;
-                device->recv_line_len = 0;
+                ppp_start_receive_frame(device);
             }
+            break;
+        default:
+            LOG_E("BUG: unexpect state: %u", (unsigned int)device->state);
         }
-        else
+        if (device->rxpos == sizeof(device->rxbuf))
         {
-            /* if recieve 0x7e, begin to recieve data */
-            if (ch == PPP_DATA_BEGIN_END)
+            LOG_W("receive ppp frame is lagger than %u", (unsigned int)sizeof(device->rxbuf));
+            ppp_rxbuf_drop(device);
+        }
+    }
+}
+
+/*
+ * Receive thread , store uart data and transform tcpip stack
+ *
+ * @param ppp_device *device
+ *
+ *
+ * @return  0: execute successful
+ *
+ */
+static int ppp_recv_entry(struct ppp_device *device)
+{
+    const rt_uint32_t interested_event = PPP_EVENT_RX_NOTIFY | PPP_EVENT_LOST | PPP_EVENT_CLOSE_REQ;
+    rt_uint32_t event;
+    rt_size_t len;
+    rt_uint8_t buffer[PPP_RECV_READ_MAX];
+    rt_bool_t closing = RT_FALSE;
+
+    rt_event_control(&device->event, RT_IPC_CMD_RESET, RT_NULL);
+    device->state = PPP_STATE_PREPARE;
+
+    while (1)
+    {
+        if (device->state == PPP_STATE_PREPARE)
+        {
+            if (!device->ops->prepare || device->ops->prepare(device) == RT_EOK)
+            {
+                ppp_processdata_enter(device);
+                pppapi_connect(device->pcb, 0);
+            }
+            else
             {
-                thrans_flag = PPP_DATA_START;
-                old_ch = ch;
-                device->recv_line_buf[0] = ch;
-                device->recv_line_len = 1;
+                LOG_E("%s prepare fail, try again later", device->parent.parent.name);
+                rt_thread_mdelay(10*1000);
             }
+            continue;
         }
-    }
 
-__exit:
+        rt_event_recv(&device->event, interested_event, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &event);
 
-    rt_free(device->recv_line_buf);
-    rt_free(device->rx_notice);
+        if (event & PPP_EVENT_RX_NOTIFY)
+        {
+            do
+            {
+                len = rt_device_read(device->uart, 0, buffer, PPP_RECV_READ_MAX);
+                if (len)
+                    ppp_recv_processdata(device, buffer, len);
+            } while (len);
+        }
 
-    return result;
+        if (event & PPP_EVENT_CLOSE_REQ)
+        {
+            LOG_D("user request close ppp");
+            closing = RT_TRUE;
+            pppapi_close(device->pcb, 0);
+        }
+
+        if (event & PPP_EVENT_LOST)
+        {
+            ppp_processdata_leave(device);
+            if (closing)
+            {
+                LOG_W("ppp closing success");
+                rt_event_send(&device->event, PPP_EVENT_CLOSED);
+                break;
+            }
+            LOG_W("ppp lost, try reconnect");
+            device->state = PPP_STATE_PREPARE;
+        }
+    }
+
+    return RT_EOK;
 }
 
 /*
@@ -316,20 +417,11 @@ static int ppp_recv_entry_creat(struct ppp_device *device)
 {
     rt_int8_t result = RT_EOK;
 
-    /* when recieve rx_notice, come to recieve a data from uart */
-    device->rx_notice = rt_sem_create("sem_ppp_recv", 0, RT_IPC_FLAG_FIFO);
-    if (device->rx_notice == RT_NULL)
-    {
-        LOG_E("PPP device initialize failed! ppp_device_recv_notice create failed!");
-        result = -RT_ENOMEM;
-        goto __exit;
-    }
-
     /* dynamic creat a recv_thread */
     device->recv_tid = rt_thread_create("ppp_recv",
                                         (void (*)(void *parameter))ppp_recv_entry,
                                         device,
-                                        512,
+                                        768,
                                         8,
                                         20);
     if (device->recv_tid == RT_NULL)
@@ -342,19 +434,11 @@ static int ppp_recv_entry_creat(struct ppp_device *device)
     /* if you create a thread, never forget to start it */
     result = rt_thread_startup(device->recv_tid);
     if(result != RT_EOK)
-    {
         goto __exit;
-    }
 
     return result;
 
 __exit:
-
-    if (device->rx_notice)
-    {
-        rt_sem_delete(device->rx_notice);
-    }
-
     rt_memset(device, 0x00, sizeof(struct ppp_device));
     return result;
 }
@@ -374,12 +458,11 @@ static rt_err_t ppp_device_init(struct rt_device *device)
 
     struct ppp_device *ppp_device = (struct ppp_device *)device;
     RT_ASSERT(ppp_device != RT_NULL);
-
-    if(ppp_device->ops->init && ppp_device->ops->init(ppp_device) != RT_EOK)
-    {
-        LOG_E("ppp_device->ops->init failed.");
-        return -RT_ERROR;
-    }
+    device->flag |= RT_DEVICE_FLAG_STANDALONE;
+#ifdef PPP_DEVICE_DEBUG_DROP
+    ppp_device->dropcnt = 0;
+    ppp_device->droppos = 0;
+#endif
     return RT_EOK;
 }
 
@@ -395,46 +478,37 @@ static rt_err_t ppp_device_init(struct rt_device *device)
 static rt_err_t ppp_device_open(struct rt_device *device, rt_uint16_t oflag)
 {
     int result = RT_EOK;
+    rt_uint16_t uart_oflag;
     RT_ASSERT(device != RT_NULL);
 
     struct ppp_device *ppp_device = (struct ppp_device *)device;
-    static rt_device_t serial = RT_NULL;
 
-    ppp_device->ppp_link_status = RT_TRUE;
-    /* Creat a thread to creat ppp recieve function */
-    result = ppp_recv_entry_creat(ppp_device);
-    if (result != RT_EOK)
+    uart_oflag = RT_DEVICE_OFLAG_RDWR;
+    if (ppp_device->uart->flag & RT_DEVICE_FLAG_DMA_RX)
+        uart_oflag |= RT_DEVICE_FLAG_DMA_RX;
+    else if (ppp_device->uart->flag & RT_DEVICE_FLAG_INT_RX)
+        uart_oflag = RT_DEVICE_FLAG_INT_RX;
+    if (ppp_device->uart->flag & RT_DEVICE_FLAG_DMA_TX)
+        uart_oflag |= RT_DEVICE_FLAG_DMA_TX;
+    else if (ppp_device->uart->flag & RT_DEVICE_FLAG_INT_TX)
+        uart_oflag |= RT_DEVICE_FLAG_INT_TX;
+
+    if (rt_device_open(ppp_device->uart, uart_oflag) != RT_EOK)
     {
-        LOG_E("Creat a thread to creat ppp recieve function failed.");
+        LOG_E("ppp device open failed.");
         result = -RT_ERROR;
         goto __exit;
     }
-    LOG_D("Creat a thread to creat ppp recieve function successful.");
 
+    rt_event_init(&ppp_device->event, "pppev", RT_IPC_FLAG_FIFO);
     /* we can do nothing */
-    if (ppp_device->ops->open && ppp_device->ops->open(ppp_device, oflag) != RT_EOK)
-    {
-        LOG_E("ppp device open failed.");
-        result = -RT_ERROR;
-        goto __exit;
-    }
 
-    /* uart conversion into ppp device , find and open command device */
-    serial = rt_device_find(ppp_device->uart_name);
-    if (serial  != RT_NULL)
-    {
-        RT_ASSERT(serial->type == RT_Device_Class_Char);
+    RT_ASSERT(ppp_device->uart && ppp_device->uart->type == RT_Device_Class_Char);
+
+    /* uart transfer into tcpip protocol stack */
+    rt_device_set_rx_indicate(ppp_device->uart, ppp_device_rx_ind);
+    LOG_I("(%s) is used by ppp_device.", ppp_device->uart->parent.name);
 
-        /* uart transfer into tcpip protocol stack */
-        rt_device_set_rx_indicate(serial, ppp_device_rx_ind);
-        LOG_I("(%s) is used by ppp_device.", ppp_device->uart_name);
-    }
-    else
-    {
-        LOG_E("Cannot find %s device.", ppp_device->uart_name);
-        result = -RT_ERROR;
-        goto __exit;
-    }
 
     /* creat pppos */
     ppp_device->pcb = pppapi_pppos_create(&(ppp_device->pppif), ppp_data_send, ppp_status_changed, ppp_device);
@@ -445,6 +519,7 @@ static rt_err_t ppp_device_open(struct rt_device *device, rt_uint16_t oflag)
         goto __exit;
     }
     LOG_D("pppapi_pppos_create has created a protocol control block.");
+    ppp_netdev_add(&ppp_device->pppif);
 
     /* set netif name */
     ppp_device->pppif.name[0] = ppp_device->parent.parent.name[0];
@@ -476,15 +551,15 @@ static rt_err_t ppp_device_open(struct rt_device *device, rt_uint16_t oflag)
     LOG_D("ppp_set_auth has passed verification.");
  #endif /* PPP_AUTHORIZE */
 
-    /* ppp connect */
-    result = pppapi_connect(ppp_device->pcb, 0);
+    /* Creat a thread to creat ppp recieve function */
+    result = ppp_recv_entry_creat(ppp_device);
     if (result != RT_EOK)
     {
-        LOG_E("pppapi_connect execute failed.");
+        LOG_E("Creat a thread to creat ppp recieve function failed.");
         result = -RT_ERROR;
         goto __exit;
     }
-    LOG_D("pppapi_connect execute successful, waitting connect.");
+    LOG_D("Creat a thread to creat ppp recieve function successful.");
 
 __exit:
 
@@ -501,26 +576,23 @@ __exit:
  */
 static rt_err_t ppp_device_close(struct rt_device *device)
 {
+    rt_uint32_t event;
     RT_ASSERT(device != RT_NULL);
 	extern void ppp_netdev_del(struct netif *ppp_netif);
 
     struct ppp_device *ppp_device = (struct ppp_device *)device;
     RT_ASSERT(ppp_device != RT_NULL);
 
-    /* use pppapi_close to shutdown ppp link status */
-    pppapi_close(ppp_device->pcb, 0);
+    rt_event_send(&ppp_device->event, PPP_EVENT_CLOSE_REQ);
+    rt_event_recv(&ppp_device->event, PPP_EVENT_CLOSED, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &event);
 
-    ppp_device->ppp_link_status = RT_FALSE;
-
-    /* delete netdev from netdev frame */
+    rt_device_set_rx_indicate(ppp_device->uart, RT_NULL);
     ppp_netdev_del(&ppp_device->pppif);
+    ppp_free(ppp_device->pcb);
     LOG_D("ppp netdev has been detach.");
+    rt_event_detach(&ppp_device->event);
 
-    if (ppp_device->ops->close && ppp_device->ops->close(ppp_device) != RT_EOK)
-    {
-        LOG_E("ppp_device->ops->close failed.");
-        return -RT_ERROR;
-    }
+    rt_device_close(ppp_device->uart);
     /* cut down piont to piont at data link layer */
     LOG_I("ppp_device has been closed.");
     return RT_EOK;
@@ -539,16 +611,7 @@ static rt_err_t ppp_device_control(struct rt_device *device,int cmd, void *args)
 {
     RT_ASSERT(device != RT_NULL);
 
-    struct ppp_device *ppp_device = (struct ppp_device *)device;
-    RT_ASSERT(ppp_device != RT_NULL);
-
-    /* use ppp_device_control function */
-    if(ppp_device->ops->control && ppp_device->ops->control(ppp_device, cmd, args) != RT_EOK)
-    {
-        LOG_E("ppp_device->ops->control failed.");
-        return -RT_ERROR;
-    }
-    return RT_EOK;
+    return -RT_ENOSYS;
 }
 
 /*
@@ -611,17 +674,6 @@ int ppp_device_register(struct ppp_device *ppp_device, const char *dev_name, con
         LOG_I("ppp_device has registered rt_device frame successful.");
     }
 
-    /* when ppp device has register rt_device frame, start up it */
-    do
-    {
-        if (device->init && device->init((rt_device_t)ppp_device) != RT_EOK)
-        {
-            LOG_E("ppp device init failed.try it in %ds", PPP_RECONNECT_TIME / 100);
-            rt_thread_mdelay(PPP_RECONNECT_TIME);
-            result = -RT_ERROR;
-        }
-    } while (result != RT_EOK);
-
     return result;
 }
 
@@ -635,14 +687,19 @@ int ppp_device_register(struct ppp_device *ppp_device, const char *dev_name, con
  *         -1: error
  *
  */
-int ppp_device_attach(struct ppp_device *ppp_device, char *uart_name, void *user_data)
+int ppp_device_attach(struct ppp_device *ppp_device, const char *uart_name, void *user_data)
 {
     RT_ASSERT(ppp_device != RT_NULL);
 
-    ppp_device->uart_name = uart_name;
+    ppp_device->uart = rt_device_find(uart_name);
+    if (!ppp_device->uart)
+    {
+        LOG_E("ppp_device_attach, cannot found %s", uart_name);
+        return -RT_ERROR;
+    }
     ppp_device->user_data = user_data;
 
-    if (ppp_device->parent.open && ppp_device->parent.open((rt_device_t)ppp_device, RT_TRUE) != RT_EOK)
+    if (rt_device_open(&ppp_device->parent, 0) != RT_EOK)
     {
         LOG_E("ppp_device_attach failed. Can't open device(%d)");
         return -RT_ERROR;
@@ -664,13 +721,13 @@ int ppp_device_detach(struct ppp_device *ppp_device)
 {
     RT_ASSERT(ppp_device != RT_NULL);
 
-    if (ppp_device->parent.close && ppp_device->parent.close((rt_device_t)ppp_device) != RT_EOK)
+    if (rt_device_close(&ppp_device->parent) != RT_EOK)
     {
         LOG_E("ppp_device_detach failed. Can't open device.");
         return -RT_ERROR;
     }
 
-    ppp_device->uart_name = RT_NULL;
+    ppp_device->uart = RT_NULL;
     ppp_device->user_data = RT_NULL;
 
     return RT_EOK;