GithubHelp home page GithubHelp logo

rt-thread-packages / ppp_device Goto Github PK

View Code? Open in Web Editor NEW
38.0 11.0 32.0 235 KB

lwIP PPP porting for GSM modem (like sim800)

License: Apache License 2.0

Python 1.51% C 98.49%
ppp lwip gprs iot air720 sim800 m6312

ppp_device's Introduction

PPP Device

1. 简介

PPP Device 软件包,是 RT-Thread 针对不同模块的 lwIP PPP 功能实现的软件包。它使蜂窝模块不再需要发送 AT 命令,使用 PPP 方式即可实现网络数据传输。

PPP Device 软件包特点如下:

  • 支持多种蜂窝模块;
  • 无缝兼容多种应用层网络协议(HTTP、MQTT、TLS 等);
  • 支持数据差错检测,提供可靠数据传输;
  • 提供 CHAT 方式初始化功能,方便设备移植;

目前 PPP 功能支持 Luat Air720,Quectel EC20,China mobile M6312, SIMCOM SIM800 模块,后续会接入更多蜂窝模块。

对 PPP Device 有疑惑,或者对 PPP Device 感兴趣的开发者欢迎入群详细了解。

QQ群:749347156 <传送门>

移植文档地址:<移植文档>

1.1 框架图

  • ppp_device 软件包是 lwIP 协议栈中 ppp 功能针对不同设备的具体实现;
  • ppp_device 软件包中实现 netdev 网卡设备,并对接 SAL 抽象层,应用层可直接使用 BSD Socket API 进行网络编程;

1.2 目录结构

名称 说明
src PPP Device 实现源码目录
inc PPP Device 头文件目录
sample PPP 功能示例文件目录
class 不同设备针对 PPP 功能的移植适配目录

1.3 许可证

ppp_device 软件包遵循 Apache-2.0 许可,详见 LICENSE 文件。

1.4 依赖

  • RT-Thread 3.1.0+
  • lwIP 组件( ppp 功能)

2. 获取方式

PPP Device 软件包相关配置选项介绍

[*] PPP DEVICE: lwIP PPP porting for Cellular Module( 2G/3G/4G )
    [ ]   Enable debug log output
    [ ]   Enbale authorize connect feature
    [*]   Enable link status detect feature
    (10)     Link status detecct timeout
          Select Internet Service Provider (china mobile)  --->
          Select modem type (Luat Air720)  --->
    [*]    Enable ppp device sample
    (uart3) ppp device uart name
          Version (latest)  --->
  • Enable debug log output: 开启调试日志功能
  • Enbale authorize connect feature: 开启身份认证功能
  • Enable lin status detect feature: PPP链路连接监控,检测链路连接正常;设置为 0 则不开启链路监控;
  • Select modem type: 模块选择
  • Select Internet Service Provider: 网络运营商选择
  • Enable ppp device sample: 选择模块后会提示的模块使用示例
  • ppp device uart name: 模块使用的串口
  • Version: 软件包版本号

3. 使用方式

PPP Device 软件包初始化函数如下所示:

PPP 功能启动函数,该函数自动调用;没有调用停止函数前,不可再次调用

int ppp_sample_start(void)
{
    rt_device_t device = RT_NULL;
    device = rt_device_find(PPP_DEVICE_NAME);
    if(device == RT_NULL)
    {
        LOG_E("Can't find device (%s).", PPP_DEVICE_NAME);
        return -RT_ERROR;
    }
    if(ppp_device_attach((struct ppp_device *)device, PPP_CLIENT_NAME, RT_NULL) != RT_EOK)
    {
        LOG_E("ppp_device_attach execute failed.");
        return -RT_ERROR;
    }
    return RT_EOK;
}
// 自动初始化
INIT_APP_EXPORT(ppp_sample_start);
// 命令导出到MSH( ppp_sample_start 变更为ppp_start )
MSH_CMD_EXPORT_ALIAS(ppp_sample_start, ppp_start, a sample of ppp device  for dailing to network);
  • 模块拨号,模块进入 PPP 模式;
  • 注册 netdev 设备,接入标准网络框架;

PPP 功能停止函数,该函数可以退出 PPP 模式

int ppp_sample_stop(void)
{
    rt_device_t device = RT_NULL;
    device = rt_device_find(PPP_DEVICE_NAME);
    if(device == RT_NULL)
    {
        LOG_E("Can't find device (%s).", PPP_DEVICE_NAME);
        return -RT_ERROR;
    }
    if(ppp_device_detach((struct ppp_device *)device) != RT_EOK)
    {
        LOG_E("ppp_device_detach execute failed.");
        return -RT_ERROR;
    }
    return RT_EOK;
}
MSH_CMD_EXPORT_ALIAS(ppp_sample_stop, ppp_stop, a sample of ppp device for turning off network);
  • 退出 PPP 模式,模块退出拨号模式;
  • 解注册 netdev 设备;

模块上电后,自动初始化流程如下:

 \ | /
- RT -     Thread Operating System
 / | \     4.0.2 build Sep 23 2019
 2006 - 2019 Copyright by rt-thread team
lwIP-2.0.2 initialized!
[I/sal.skt] Socket Abstraction Layer initialize success.
[I/ppp.chat] (uart3) has control by modem_chat.
[I/ppp.dev] (uart3) is used by ppp_device.
msh />[I/ppp.dev] ppp connect successful.

设备上电初始化完成,模块提示拨号成功,然后可以在 FinSH 中输入命令 ifconfig 查看设备 IP 地址、MAC 地址等网络信息,如下所示:

msh />ifconfig
network interface device: pp (Default)           ## 设备名称
MTU: 1500                                        ## 网络最大传输单元
MAC: 95 45 68 39 68 52                           ## 设备 MAC 地址
FLAGS: UP LINK_UP INTERNET_DOWN DHCP_DISABLE     ## 设备标志
ip address: 10.32.76.151                         ## 设备 IP 地址
gw address: 10.64.64.64                          ## 设备网关地址
net mask  : 255.255.255.255                      ## 设备子网掩码
dns server #0: 114.114.114.114                   ## 域名解析服务器地址0
dns server #1: 120.196.165.7                     ## 域名解析服务器地址1

获取 IP 地址成功之后,如果开启 Ping 命令功能,可以在 FinSH 中输入命令 ping + 域名地址 测试网络连接状态, 如下所示:

msh />ping www.baidu.com
60 bytes from 183.232.231.172 icmp_seq=0 ttl=55 time=84 ms
60 bytes from 183.232.231.172 icmp_seq=1 ttl=55 time=78 ms
60 bytes from 183.232.231.172 icmp_seq=2 ttl=55 time=78 ms
60 bytes from 183.232.231.172 icmp_seq=3 ttl=55 time=78 ms

ping 命令测试正常说明 PPP Device 设备网络连接成功,之后可以使用 SAL(套接字抽象层) 抽象出来的标准 BSD Socket APIs 进行网络开发(MQTT、HTTP、MbedTLS、NTP、Iperf 等)。

4. 注意事项

  • 一般的 SIM 卡因为只能从运营商网络获取内网地址,所以一般不能实现服务器相关功能
  • 特殊的 SIM 卡可以从运营商获取公网地址,可是实现服务器功能
  • 目前只支持一个设备通过 PPP 连接网络
  • 建议不要打开 RT_DEVICE_FLAG_DMA_TX
  • 如果网络环境不好,建议关闭 Enable lin status detect feature 选项,或调整成大一点的时间
  • RT_LWIP_TCPTHREAD_STACKSIZE 需要配置为不小于 2048,及时在 network 组件中修改
  • 不要忘记打开串口
  • 对于开启模块电源控制引脚的开发者,要注意模块的启动时间;通常模块启动时间较长,这时会出现长时间拨号不成功的问题,一定要注意模块的启动时间,避免造成使用上的一些障碍。

5. 联系方式

联系人:xiangxistu

Email: [email protected]

6. 致谢

感谢网友 @xfan1024 的一些贡献及建议,在制作PPP DEVICE 时给与的帮助。提出了很多宝贵的意见来一同完善PPP DEVICE 软件包。

ppp_device's People

Contributors

armink avatar hellobyeall avatar lawlieta avatar majianjia avatar xfan1024 avatar xiangxistu avatar zhouchuanfu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ppp_device's Issues

建议添加异步发送数据功能

文档中说明建议不要打开RT_DEVICE_FLAG_DMA_TX,现实情况是一定不能打开该标志。原因是RTT串口发送时,是直接将数据地址传送给DMA(在打开DMA时并且开启RT_DEVICE_FLAG_DMA_TX),这样在DMA发送数据时,一定不能修改传给serial层的数据,如果是动态分配的内存更不能释放该内存,否则会导致发送数据出错或者崩溃。
但是,某些情况下,需要开启DMA以节省CPU资源,这时需要ppp_device能够保证数据不出错而且还能异步(DMA)发送,这就需要简单实现一下异步发送的功能。我简单写了一个串口异步发送数据的示例,你看是否可行或者是否有必要:

#define MIN(a,b)            (((a) > (b)) ? (b) : (a))
#define SEND_TIMEOUT 1000
uint8_t ppp_tx_buf[1500] = {0};
/*发送完成信号*/
rt_sem_t tx_sem;

rt_inline rt_err_t __send_complete_callback(rt_device_t dev, void *buffer)
{
    rt_sem_release(tx_sem);
    return RT_EOK;
}

int ppp_serial_write(rt_device_t dev, const uint8_t *data, int data_len)
{
    int ret = RT_EOK;

    if (!dev)
    {
        return -RT_EINVAL;
    }
    if (!data || data_len == 0)
    {
        log_w("Invalid data!");
        return 0;
    }
    
    ret = rt_sem_take(tx_sem, SEND_TIMEOUT);
    if (RT_EOK != ret)
    {
        log_e("Write %s failed,err: %d", uart->name, ret);
        return -RT_EBUSY;
    }
    ret = MIN(data_len,sizeof(ppp_tx_buf));
    memcpy(ppp_tx_buf, data, ret);
    
    ret = rt_device_write(dev, 0,tx_buf, ret);
    if (ret <= 0)
    {
        log_e("Write %s failed,err: %d", uart->name, ret);
    }
    else if (ret < data_len)
    {
       //待优化,连续发送大量数据可能导致栈溢出
        ret = ppp_serial_write(fd, data + ret, data_len - ret);
    }
    return ret;
}

problem using ppp+cmux

[W/ppp.dev] receive ppp frame is lagger than 1550
[W/ppp.dev] receive ppp frame is lagger than 1550
[W/ppp.dev] receive ppp frame is lagger than 1550
[W/ppp.dev] receive ppp frame is lagger than 1550
[W/ppp.dev] receive ppp frame is lagger than 1550
[W/ppp.dev] receive ppp frame is lagger than 1550
[W/ppp.dev] receive ppp frame is lagger than 1550
[W/ppp.dev] receive ppp frame is lagger than 1550
[W/ppp.dev] receive ppp frame is lagger than 1550
[W/ppp.dev] receive ppp frame is lagger than 1550
[W/ppp.dev] receive ppp frame is lagger than 1550
[W/ppp.dev] receive ppp frame is lagger than 1550
psr: 0x01070000
r00: 0x2000eb98
r01: 0x000000b4
r02: 0x20040001
r03: 0x20040000
r04: 0xdeadbeef
r05: 0xdeadbeef
r06: 0xdeadbeef
r07: 0x20011828
r08: 0xdeadbeef
r09: 0xdeadbeef
r10: 0xdeadbeef
r11: 0xdeadbeef
r12: 0xffffffff
 lr: 0x0802b3e7
 pc: 0x0802b388
hard fault on thread: ppp_recv

thread   pri  status      sp     stack size max used left tick  error
-------- ---  ------- ---------- ----------  ------  ---------- ---
Sal_whil  19  suspend 0x0000009c 0x00001000    29%   0x00000004 OK
ppp_recv   9  running 0x000000ac 0x00000600    48%   0x00000005 **OK**
tshell    20  suspend 0x000000cc 0x00001000    10%   0x00000007 OK
cmuxrec1   8  suspend 0x000000d8 0x00000200    60%   0x0000000a OK
sys work  23  suspend 0x00000084 0x00000800    54%   0x00000004 OK
tcpip     10  ready   0x000000d0 0x00000800    83%   0x00000004 OK
etx       12  suspend 0x000000b0 0x00000400    17%   0x00000010 OK
erx       12  suspend 0x000000b8 0x00000400    17%   0x00000010 OK
tidle0    31  ready   0x00000060 0x00000100    56%   0x00000001 OK
timer      4  suspend 0x00000080 0x00000200    32%   0x00000009 OK
main      10  suspend 0x000000b8 0x00000800    26%   0x0000000c OK
bus fault:
SCB_CFSR_BFSR:0x82 PRECISERR SCB->BFAR:20040000`

i am using cmux and ppp-device 1.1.0. all setting and stack sizes are default just tcptack is increased to 2048. i am sending http request(using thread) every 2 second to a webserver which respond a very simple html page to GET request. after several http request by SAL functions i get above error in terminal.
i tested cmux(using thread) alone and ppp(using thread) alone all are ok but when i use them together this happens.
(edited) i changed ppp_recv priority to 3 (under everything) and it seems it's ok but it is not good as i know for RTOS.
(edited_2) if i use one channel of cmux(ppp) with lowering the priority of ppp_recv, it's working properly but when i use second virtual channel of cmux for another job+ppp it doesen't work properly and i get these non-sense data:

[D/Cmux_at] 0 ,Recieve  Úa»hF7½F½È
[D/Cmux_at] 0 ,Recieve  °
[D/Cmux_at] 0 ,Recieve
[D/Cmux_at] 0 ,Recieve  ðúúF+Ð@òªRGIHHð
[D/Cmux_at] 0 ,Recieve  Yý;h
[D/Cmux_at] 0 ,Recieve  §ø8a{hÚi;hC{hÚa?K
[D/Cmux_at] 0 ,Recieve
[D/Cmux_at] 0 ,Recieve  ÿ÷HùF
[D/Cmux_at] 0 ,Recieve  ;û`Oðÿ3»aûhø@0ð
[D/Cmux_at] 0 ,Recieve
[D/Cmux_at] 0 ,Recieve   Ñ
[D/Cmux_at] 0 ,Recieve  ÐûhÚk{hÛi@
[D/Cmux_at] 0 ,Recieve  {hÛi@ûhÚc
[D/Cmux_at] 0 ,Recieve  [øoð  (àûiûa»i
[D/Cmux_at] 0 ,Recieve  ûhø@0ð
[D/Cmux_at] 0 ,Recieve  ÛkÛC@{hÚaøhðù#{a
[D/Cmux_at] 0 ,Recieve  {hñûiB¨Ñ8iþ÷5ø{i
[D/Cmux_at] 0 ,Recieve  +Ñðþû
[D/Cmux_at] 0 ,Recieve 9ì
[D/Cmux_at] 0 ,Recieve
[D/Cmux_at] 0 ,Recieve  ÅbIHðµüûhFðIúF
[D/Cmux_at] 0 ,Recieve  +Ð@ò)b{I}Hð¨üý÷þÿ
[D/Cmux_at] 0 ,Recieve  øaðýF
[D/Cmux_at] 0 ,Recieve  @ò,brIvHðüý÷ìÿ¸að
[D/Cmux_at] 0 ,Recieve  ÉþF
[D/Cmux_at] 0 ,Recieve  iImHðüý÷Úÿxa
[D/Cmux_at] 0 ,Recieve
[D/Cmux_at] 0 ,Recieve  ðrüxiý÷Ëÿ¸iý÷Èÿøiý÷
[D/Cmux_at] 0 ,Recieve  Åÿ»h
[D/Cmux_at] 0 ,Recieve  ðþ8a;i

建议修改Kconfig文件中选择模块类型方式

目前只支持4种网卡的选择,而且必须选择一种。若用户使用自己的网卡如N720等,需要自己修改Kconfig文件。一旦更新了Kconfig文件,就会覆盖之前的设置,需要重新设置。建议可参考AT DEVICE的选项,即可使用列表中的网卡,也可自己在其他地方添加网卡。

对完整 PPP 数据帧的校验是否由 PPP_DEVICE 完成?

在查看 lwIP 代码时,ppp 数据包的解析,在 pppos.c 文件下 pppos_input 函数里已有实现

/** Pass received raw characters to PPPoS to be decoded.
 *
 * @param ppp PPP descriptor index, returned by pppos_create()
 * @param s received data
 * @param l length of received data
 */
void
pppos_input(ppp_pcb *ppp, u8_t *s, int l)
{
  pppos_pcb *pppos = (pppos_pcb *)ppp->link_ctx_cb;
  struct pbuf *next_pbuf;
  u8_t cur_char;
  u8_t escaped;
  PPPOS_DECL_PROTECT(lev);
#if !PPP_INPROC_IRQ_SAFE
  LWIP_ASSERT_CORE_LOCKED();
#endif

  PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l));
  while (l-- > 0) {
    cur_char = *s++;
···
···
}

ppp_recv_entry中的PPP_STATE_PREPARE下,丢掉脏数据的处理不合理

    if (device->state == PPP_STATE_PREPARE)
    {
            ......
            /* throw away the dirty data in the uart buffer */
            rt_device_read(device->uart, 0, buffer, PPP_RECV_READ_MAX);
            .....
    }

在ppp_recv_entry中,模块拨号成功后,加了清理脏数据处理。如果真有脏的数据,这样最多也只能清理掉PPP_RECV_READ_MAX(32字节)长度的数据吧,如果RT_SERIAL_RB_BUFSZ比PPP_RECV_READ_MAX大,是清理不干净的

webclient的问题

使用PPP拨号上网后,其他的通讯都没有问题
但是使用webclient Demo 中的 webclient_file.c webclient_get_file下载文件,ppp_device会提示:
D/ppp.dev ppp_recv: found continuous 0x7e

一直在这里死循环,无法下载文件

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.