• 基于MicroC/OSII 的TCP/IP Socket Server


      整理一下这几天学习的一些知识,就当是一些知识概念的整理,免得以后忘记了。

    一、内容  

      在NiosII IDE建立基于uC/OS操作系统的TCP/IP Socket Server工程,该应用工程能够初始化LwIP(Light weight IP)stack,运行简单的TCP Server。PC机可以通过Ethernet与开发板通信。硬件系统要求有lan91c111 Ethernet MAC。软件有MicroC/OS-II和LwIP。把配置有Ethernet控制器的硬件系统配置到FPGA中,然后编译运行应用程序。PC机通过Ethernet访问开发板进行通信。

      这里所用的平台是:博创UP-AR2000    Quartus II 7.2    Nios II 7.2


    二、uC/OS II

      uC/OS-II只是一个实时操作系统内核,它仅仅包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能。没有提供输入输出管理,文件系统,网络等额外的服务。但由于uC/OS-II良好的可扩展性和源码开放,这些非必须的功能完全可以由用户自己根据需要分别实现。

      Altera的uCOS2本质上是Nios II HAL的一个超集,是uCOS2任务调度器和相关API函数在HAL环境上的扩展。在uCOS2 Project中,所有Nios II本身的HAL API都可以被调用。


       

    三、LwIP协议栈 和 NicheStack TCP/IP协议栈

    3.1 LwIP协议栈

      LWIP是TCP/IP协议栈的一种实现。主要目的是减少存储器利用量和代码尺寸,几十K字节的程序空间和几十K字节的数据RAM空间就可以实现。很适合应用于小的、资源有限的处理器如嵌入式系统。可以移植到操作系统上,也可以在无操作系统的情况下独立运行。

      要实现嵌入式TCP/IP协议栈,最关键的一个问题就是,如何结合系统资源有限的嵌入式系统软硬件环境以及具体的嵌入式Internet应用对标准的TCP/IP协议栈进行简化, 从而实现一种“轻量级”的TCP/IP协议栈。这就是所谓的Light-weight IP。由瑞典计算机科学院的Adam Dunkels创建。

      LwIP提供了完成的TCP/IP协议功能,支持IP,ICMP,UDP,TCP,DHCP,ARP。

      Altera在Nios II上的LwIP移植基于uCOS2的多任务环境,在Nios IDE中开发LwIP应用程序需要工程首先配置为支持uCOS2。

      Nios II上LwIP支持的网络芯片为SMSC的LAN91C111。

    3.2 LwIP的进程模型

      协议实现的进程模型以把系统划分成为不同的进程的方法进行描述。先看下普通的TCP/IP协议的模型。

      这种方法有其诸多优势,如协议能在运行时被增加,代码一般容易理解和调试。但也有不利因素,严格的分层并不总是实现协议的最好方法。

      数据跨层传递时将不得不产生进程切换(context switch)。对于接收一个TCP段来说,将会引起三次进程切换,从网络设备驱动层进程到IP进程,从IP进程到TCP进程,最终到应用层进程。对于大部分操作系统来说,进程切换的代价可是相当昂贵的。

      

      lwIP所使用的进程模型是:把所有协议封装到一个单一的进程中,从而与操作系统内核分开。

      应用程序可能也驻留在lwIP处理过程中,或者在单独的过程中。

      TCP/IP栈和应用程序之间的通信可以通过函数调用实现,也可以通过更为抽象的API。

      有些学者把这种方法称为零拷贝技术。所谓“零拷贝”,是指TCP/IP协议栈没有用于各层数据传输的缓冲区,协议栈各层之间传递的都是数据指针。

      只有当数据最终要被驱动程序发送出去或者是被应用程序取走时,才进行真正的数据搬移。这样就大大减少了系统开销,从而提高系统性能。

    3.3 NicheStack与LwIP一脉相承,技术上并无本质区别,在作产品时可能有区别。前者需要授权,后者则不需要。


    四、代码中的一些分析

    (1)网络接口的初始化

    在启动OSStart()函数进入多任务状态之前,调用如下两个函数完成网络接口的初始化:

      1)lwip_stack_init()

    函数原型为:void lwip_stack_init(int thread_prio, void (* init_done_func)(void *), void *arg)
    thread_prio:主TCP/IP线程的优先级
    init_done_func():lwip_stack_init函数执行完成后就转向执行这个指针指向的函数
    arg:传递给init_done_func的参数,视init_done_func()而定,通常置为0
    功能:创建一个TCPIP协议栈主线程,完成TCP/IP协议栈的初始化并转向init_done_func

      2)lwip_devices_init()

    函数原型为:int lwip_devices_init(int rx_thread_prio)
    Lwip_devices_init从system.h中遍历所有安装的网络设备驱动并注册。成功后返回一个非零值,此时如果TCPIP栈准备就绪,就可以为应用程序创建任务。
    此函数创建了一个接收线程,其优先级由参数rx_thread_prio给定
    此函数会调用get_mac_addr和get_ip_addr二函数,这两个函数必须由用户编写。

    (2)get_mac_addr和get_ip_addr

      LwIP系统代码必须根据此二函数设置网络设备的MAC和IP地址。

      通过写这两个函数,系统可以灵活地将MAC和IP地址存放在任意位置,而不是设备驱动的某个固定位置。如可以存放在FLASH中,也可存放在片内RAM中。

      两个函数都使用了LwIP内部使用的结构体。用户无需知道结构体的细节,只需知道如何填充MAC和IP地址。

    (3)应用程序创建四个任务

      1)SSSInitialTask()

      SSSInitialTask创建了两个软件组件层任务:
         NicheStack TCP/IP Stack main task:在netmain()中创建
         time-keeping task:在netmain()中创建

      SSSInitialTask在创建两个任务后删除本任务。

     1 alt_iniche_init(); //执行NicheStack网络栈的预初始化
    2 netmain(); //初始化并开始NicheStack网络栈
    3 //iniche_net_ready标明TCP/IP栈准备好,IP地址已获取
    4 while (!iniche_net_ready) TK_SLEEP(1);
    5 //协议栈已开始运行,应用程序初始化, 开始应用相关的任务加载代码块
    6 printf("\nSimple Socket Server starting up\n");
    7 TK_NEWTASK(&ssstask); //创建simple socket server任务
    8 SSSCreateOSDataStructs();//创建OS数据结构:队列信号量等
    9 SSSCreateTasks(); //创建其它任务
    10 error_code = OSTaskDel(OS_PRIO_SELF);

      2)SSSSimpleSocketServerTask()

      其完成的功能为:

        创建一个socket实现TCP/IP连接,绑定到socket上,侦听客户端的TCP/IP连接请求。

        到来TCP/IP连接时,调用sss_handle_accept()。

        调用sss_handle_receive()处理TCP/IP连接。如果需要多个TCP/IP连接,需要创建更多任务。

        调用sss_reset_connection(), sss_send_menu()和sss_exec_command()。

        当收到数据包后,LED命令被提取并通过SSSLEDCommandQ队列送到LEDManagementTask()。

      3)LEDManagementTask()

      响应SSSLEDCommandQ队列中的命令。如果命令给7段数码管的则更改SSSLEDLightshowSem信号量。如果命令给LED灯,则修改SSSLEDEventFlag值,从而控制不同的LED灯显
    示。

      4)LED7SegLightshowTask()

      根据SSSLEDLightshowSem的值,在7段LED上闪烁随机图案或停止闪烁。


     五、实验过程与结果

      实验中自己修改的内容不算多,只要设置好MAC地址和IP地址。IP地址是要和PC机的IP地址在一个局域网中,然后用交叉线连接。需要注意的是:有的电脑上有2个网口,当需要做实验时,需要将另外一个网口关闭,否则远程控制会无效。关键还是要理解其中运行的机理。主要实现的是从PC机上远程控制开发板上的操作。

      当.sof文件下载后,运行软件,可以在输出窗口看到自己所设置的IP地址。

      从“开始”中打开“运行”。

     输入命令和IP、端口号“telnet 192.168.0.250 30”。

     只要能连接上,就能远程控制LED灯与数码管了。

  • 相关阅读:
    【LeetCode-树】找树左下角的值
    【LeetCode-贪心】合并区间
    MongoDB3.6版本新增特性
    MongoDB initial sync过程
    MongoDB3.4版本新增特性
    保险配置原则
    MongoDB批量操作时字段为null时没有入库
    Kafka消费者没有收到通知的分析
    Git分支的管理
    NoSQLBooster如何MongoDB的部分文档从一个集合拷贝到另外一个集合中
  • 原文地址:https://www.cnblogs.com/kongtiao/p/2319678.html
Copyright © 2020-2023  润新知