SylixOS热插拔概述

  • 1. 热插拔系统简介

  • 1.1 热插拔系统

    热插拔设备指支持带电操作的一类设备,允许用户不关闭系统、不切断电源情况下取出或更换设备。热插拔系统用于管理系统中所有热插拔设备的插入、拔出状态,从而能够让系统内部自动完成此类设备的创建、删除工作而无需用户手动处理。同时,热插拔系统还会收集热插拔相关信息,供应用程序使用。SylixOS热插拔系统结构如图 1-1所示。

    图 1-1热插拔系统结构

    如图 1-1所示,SylixOS 中有一个名称为"t_hotplug"的内核线程,设备的热插拔状态通过事件的方式报告给该线程。系统中还有一个名为"/dev/hotplug"的虚拟设备,它负责收集相关热插拔消息,应用程序可通过读取"/dev/hotplug"设备,获得自己关心的热插拔消息。

  • 1.2 实现原理

    在 SylixOS 中,可以使用如下两种方法获得热插拔事件:

    1.中断产生,例如"mini2440"开发板上SD卡热插拔操作,当SD卡插入或者拔出时会触发引脚中断,中断服务程序中会根据读取的引脚状态,产生相应的热插拔事件,将需要处理的事件加入到热插拔工作处理队列,等待内核线程处理。

    2. 轮询检测,当有些热插拔设备不产生中断(没有插拔中断功能的设备),则需要轮询检测某些事件标志。设备驱动程序需要将检测函数和参数注册到"hotplug"循环检测链表中,"t_hotplug"内核线程会定时调用检测函数,轮询检测函数会产生相应事件,等待内核线程处理。

    如图 1-1所示,当设备热插拔操作结束时,会产生一条热插拔消息存入缓存区,应用层程序可以通过读取虚拟设备"/dev/hotplug"(热插拔设备驱动创建),从缓存区中获取热插拔消息。

  • 2 读取热插拔消息

    前文提到,热插拔事件产生后会产生热插拔消息,存放在"/dev/hotplug"设备的缓存区中,则应用层可以对"/dev/hotplug"设备进行读取,获得应用层需要的热插拔消息。由于"/dev/hotplug"设备是字符设备,所以应用层可以对设备进行open、read、write、ioctl、close等操作,获得应用层所需的热插拔消息。

  • 2.1 获取热插拔消息实例

    SylixOS 中定义了当前常见的热插拔设备消息,如 USB、SD卡、PCI等,用户也可以自定义添加。此外,还有网卡的连接与断开等与热插拔行为相似的消息。

    下面举例说明如何获取网卡热插拔消息(本例程序是在mini2440开发板上测试运行),测试代码代码清单2-1所示。

    代码清单 2-1 读取热插拔消息

    #include <stdio.h>
    #include <string.h>
    
    #define      MSG_LEN_MAX                (534)
    
    int main (int  argc, char  *argv[])
    {
        UINT8   pucMsgBuff[MSG_LEN_MAX];
        INT     iFd;
        INT32   iMsgType;
        BOOL    bInsert;
        ssize_t sstReadLen;
    
        CHAR   *pcDevName = NULL;
        UINT8  *pucArg    = NULL;
        UINT8  *pucTemp   = NULL;
    
        iFd = open("/dev/hotplug", O_RDONLY);                             /*  打开hotplug虚拟设备         */
        if (iFd < 0) {
            fprintf(stderr, "open /dev/hotplug failed.\n");
            return (-1);
        }
    
        ioctl(iFd, LW_HOTPLUG_FIOSETMSG, LW_HOTPLUG_MSG_NETLINK_CHANGE);  /* ioctl 设置关心网卡热插拔事件 */
        while (1) {
            sstReadLen = read(iFd, pucMsgBuff, MSG_LEN_MAX);              /* 读取热插拔消息               */
            if (sstReadLen < 0) {
                fprintf(stderr, "read hotplug message error.\n");
                close(iFd);
                return (-1);
            }
            if (sstReadLen < 5) {
                continue;
            }
    
            /*
             * 解析热插拔消息
             */
            pucTemp   = pucMsgBuff;
            iMsgType  = (pucTemp[0] << 24) | (pucTemp[1] << 16) | (pucTemp[2] << 8) | (pucTemp[3]);
            pucTemp  += 4;
            bInsert   = *pucTemp ? TRUE : FALSE;
            pucTemp  += 1;
            pcDevName = (CHAR *) pucTemp;
            pucArg    = pucTemp + strlen(pcDevName) + 1;
    
            printf("get new hotplug message >>\n"                         /*  打印热插拔消息             */
                    " message type: %d\n"
                    "device status: %s\n"
                    " device name: %s\n"
                    " arg0: 0x%01x%01x%01x%01x\n"
                    " arg1: 0x%01x%01x%01x%01x\n"
                    " arg2: 0x%01x%01x%01x%01x\n"
                    " arg3: 0x%01x%01x%01x%01x\n", iMsgType,
                    bInsert ? "insert" : "remove", pcDevName, pucArg[0], pucArg[1],
                    pucArg[2], pucArg[3], pucArg[4], pucArg[5], pucArg[6],
                    pucArg[7], pucArg[8], pucArg[9], pucArg[10], pucArg[11],
                    pucArg[12], pucArg[13], pucArg[14], pucArg[15]);
        }
    
        close(iFd);
    
        return (0);
    }

    如代码清单2-1所示,程序实现了应用层读取网卡热插拔消息的功能,在开发板上运行该程序,当发生网卡热插拔操作时,会得到网卡热插拔消息,实验现象如图 2-1所示。

    图 2-1网卡热插拔消息

    通过分析代码清单2-1所示代码,用户在读取设备热插拔消息时应注意以下几点:

    1.以只读方式打开"/dev/hotplug"设备,SylixOS中热插拔消息在热插拔设备创建时产生,并且写入到设备中缓存区中。

    2.代码清单2-1中程序通过ioctl函数实现单独监听网卡热插拔消息的功能,应用程序可以根据需要设置ioctl函数中的参数来获取对应的消息。默认情况下是读取所有类型热插拔消息。

    3.代码清单2-1中read函数实现读取网卡热插拔消息的功能,读取消息后对获得的热插拔消息进行解析,然后输出打印。根据程序图 2-1输出结果可知,SylixOS中对热插拔消息格式进行特殊规定,格式分析参照2.2节。

  • 2.2 热插拔消息格式

    由2.1节中读取网卡热插拔消息实例可知,在SylixOS中热插拔消息有规定的格式。下面对SylixOS热插拔消息格式进行分析,如图 2-2所示。

    图 2-2热插拔消息格式

    参照图 2-2可知,消息的前4个字节标识了消息的类型。SylixOS中已经定义了USB键盘、USB鼠标、SD存储卡、SDIO无线网卡等热插拔类型。在实际的硬件平台上,设备驱动也可以定义自己的热插拔消息类型。

    第5个字节为设备状态,0表示拔出,1表示插入。

    从第 6 个字节开始,表示设备的名称,其内容为一个以‘\0‘结束的字符串,应用程序应该以此为结束符得到完整的名称。该名称为一个设备的完整路径名称,如"/dev/ttyUSB0"、"/media/sdcard0"等。由于SylixOS中,一个完整路径名称的最大长度为512,加上结束字符‘\0‘,因此,dev name字段的最大长度为513。

    紧跟着设备名称(‘\0‘字符结尾)的是 4 个可用于灵活扩展的参数,均为4字节长度。这4个参数可适应不同设备消息的特殊处理。SylixOS未规定每个参数的具体用法和存储格式(大端或小端),完全由设备驱动定义。

    综上论述,一个热插拔消息的最大长度为:4 + 1 + 513 + 4 + 4 + 4 + 4 = 534字节。

  • 3 热插拔消息产生

  • 3.1 网卡热插拔消息

    前文已经介绍了应用层如何获取热插拔消息,本章介绍SylixOS热插拔消息的产生流程。SylixOS中,热插拔消息在热插拔事件产生时产生,由热插拔设备驱动实现。

    下面以网卡热插拔为例,介绍网卡热插拔消息产生流程,如图 3-1所示(图中以网卡连接为例,网卡断开流程与此基本一致)。

    图 3-1网卡热插拔消息产生流程

    如图 3-1所示,在对网口进行必要的初始化后,将循环检测函数dm9000_watchdog注册到循环检测链表中,检测函数会根据网卡状态产生不同的热插拔消息,然后将热插拔消息存入缓存区。

  • 3.2 模拟热插拔实现

    下面通过信号模拟热插拔事件,用信号SIGALRM模拟设备插入,用信号SIGUSR1模拟设备拔出。示例代码清单3-1所示:

    代码清单3-1 信号模拟热插拔

    #define __SYLIXOS_KERNEL
    #include <SylixOS.h>
    #include <stdio.h>
    #include <string.h>
    #include <signal.h>
    #include <pthread.h>
    #include <unistd.h>
    
    static char      *msg = "Dev";
    
    void send_event (void  *arg)
    {
        int signum = (int)arg;
    
        if (signum == SIGALRM) {
            API_HotplugEventMessage(LW_HOTPLUG_MSG_ALL, 1, msg, 0, 0, 0, 0);
        } else if (signum == SIGUSR1){
            API_HotplugEventMessage(LW_HOTPLUG_MSG_ALL, 0, msg, 0, 0, 0, 0);
        }
    }
    
    void pullout_handler (int  signum)
    {
        API_HotplugEvent((VOIDFUNCPTR)send_event, (void *)signum, 0, 0, 0, 0, 0);
    }
    
    void insert_handler (int  signum)
    {
        API_HotplugEvent((VOIDFUNCPTR)send_event, (void *)signum, 0, 0, 0, 0, 0);
    }
    
    int main (int argc, char *argv[])
    {
        int   i;
    
        if (signal(SIGALRM, insert_handler) == SIG_ERR) {
            fprintf(stderr, "Install signal handler failed.\n");
            return -1;
        }
        if (signal(SIGUSR1, pullout_handler) == SIG_ERR) {
            fprintf(stderr, "Install signal handler failed.\n");
            return -1;
        }
    
        for (i = 0; i < 8; ++i) {
            alarm(2);
            pause();
            kill(getpid(), SIGUSR1);
        }
    
        return  0;
    }

    本例利用信号模拟热插拔事件,运行2.1节中程序(注释掉ioctl函数,获取所有类型的热插拔消息),再执行代码清单3-1所示程序,会得到图 3-2所示结果。

    图 3-2模拟热插拔模拟结果

  • 4 小结

    本文档介绍了SylixOS下热插拔系统实现原理,以网卡热插拔为例,分析热插拔消息产生流程。最后通过信号模拟热插拔事件,打印出模拟的热插拔消息。

时间: 2024-12-30 02:08:29

SylixOS热插拔概述的相关文章

SylixOS 启动浅析

1.SylixOS启动概述 每个操作系统的启动都是多种多样,各有不同,SylixOS亦是如此,本文将浅析SylixOS启动层次和启动步骤两大方面. 2.SylixOS启动层次 在专用的嵌入式开发板上运行嵌入式操作系统(如SylixOS.Linux等)已经变得越来越流行,通常从一个嵌入式操作系统的软件角度来看,引导加载程序和操作系统内核便是两个重要的层次,下面就简单介绍关于SylixOS这两大层次的关键点. 2.1 层次一:Boot过程 一个裸机可执行程序的运行方法有两种: 1. 将程序代码入口放

SylixOS基于Nuc970平台的SD驱动移植

1. 适用范围 本文档为实现Nuc970平台的SD驱动总结,提供一些SylixOS SD驱动移植方法的参考. 2. 原理概述 2.1 控制器类型 SD控制器有两种类型,分为SD标准控制器(SDHCI)和SD非标准控制器. SylixOS Base代码中实现了SDHCI的驱动,但Nuc970的SD控制器是非标准控制器,其功能都需要在BSP中单独实现. 2.2  命令.应答.数据 SD传输过程中会有命令.应答和数据三个概念存在. 命令和应答都是在CMD线上传输的,数据在DAT线上进行传输. 2.2.

SylixOS中SD驱动实现流程

1.概述 本文档以imx6实验平台为例,介绍SD设备驱动实现流程. 2.SylixOS中SD系统框架 SylixOS中SD协议栈(以下称作SD Stack)结构如图 2.1所示. 图 2.1 SD 协议栈结构 1)Host层:硬件控制器抽象层,SD控制器在不同的硬件平台上可能有不同的实现,因此需要实现具体的传输处理操作.所有的控制器驱动都向上(Core层)提供统一的操作接口.SD Stack已经提供了符合SD规范的标准控制器SDHCI驱动,在此情况下,控制器驱动的编写将更加简单.当然也可使用SP

SylixOS周期定时抖动分析

1.概述 自动化与控制行业中有很多场景需要循环周期控制,而运动控制领域对循环周期控制的时间确定性要求尤为严格,周期抖动的时间确定性和周期控制的极限范围直接影响运动控制产品的质量和性能.SylixOS作为一款嵌入式实时操作系统,针对不同循环周期和不同程度的时间确定性要求均有对应的周期控制方式,其中就有为周期性任务解决多任务调度冲突并且时间确定性良好的速率单调调度(Rate Monotonic Scheduling RMS),还有传统的以硬件平台定时器作为中断源,以中断服务程序作为实时任务运行载体的

SylixOS USB虚拟网卡框架

1. USB子系统简介 1.1      USB简介 USB,是英文Universal Serial Bus(通用串行总线)的缩写,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯.是应用在PC领域的接口技术.USB接口支持设备的即插即用和热插拔功能.USB是在1994年底由英特尔.康柏.IBM.Microsoft等多家公司联合提出的. 1.2      USB虚拟网卡框架 1.2.1   普通网卡与USB网卡框架对比 如图 11所示,普通网卡驱动与USB网卡驱动相比最大的区别是,USB网

SylixOS中GIC通用中断控制器(二)——GIC实现

1.概述 本篇文档主要介绍IMX6UL平台上基于SylixOS集成开发环境中GIC通用中断控制器的实现流程和方法. 2.GIC控制器基地址获取 GIC控制器基地址通过调用armPrivatePeriphBaseGet函数获得.如图 2.1所示,Ctrl+h局搜索armPrivatePeriphBaseGet函数,搜索结果如图 2.2所示. 图 2.1全局搜索armPrivatePeriphBaseGet函数 图 2.2 armPrivatePeriphBaseGet函数搜索结果 参考DDI046

设计模式-概述

设计模式概述 设计模式描述了软件设计过程中某一类常见问题的一般性的解决方案. 设计模式是一套被反复使用的.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了重用代码.让代码更容易被他人理解.保证代码可靠性. 面向对象设计模式 面向对象设计模式描述了类与相互通信的对象之间的组织关系.目的是应对变化.提高复用.减少改变. 对象 1.从概念层面讲,对象是某种拥有职责的抽象: 2.从规格层面讲,对象是一系列可以被其他对象使用的公共接口: 3.从语言实现层面来看,对象封装了代码和数据(也

SylixOS启动读取配置文件

1 概述 SylixOS启动时会加载环境变量配置文件profile,网络配置文件ifparam.ini以及系统启动脚本startup.sh. 2 环境变量配置文件profile SylixOS启动时会执行varload命令,该命令的作用是从系统/etc/profile文件中读取环境变量配置信息,加载到系统运行环境中,如果系统/etc路径下没有profile文件,系统启动则会有如图 21所示提示信息. 图21  加载profile失败 如果没有profile文件,可执行varsave命令将当前系统

SylixOS CAN总线初始化流程解析

概述 本文档是在AT91SAM9X25平台上进行SylixOS CAN总线驱动开发时,对CAN总线初始化流程的分析. 适用于正在学习CAN总线开发的技术工程师. 技术实现 CAN总线的初始化流程可以分成两个部分: 一部分是CAN总线通道资源初始化,主要工作是对通道相关的管脚和中断以及总线编程时需要的时钟等资源的初始化:另一部分是CAN总线的硬件初始化,主要工作是对总线的波特率的设置.接收和发送数据邮箱(相当于缓存区)的初始化以及接收中断和错误中断的使能. CAN总线通道资源初始化 在AT91SA