精华内容
下载资源
问答
  • Foundation在介绍USB虚拟化之前,我们先了解下关于USB的基础知识。USB,即通用串行总线。作为一种计算机外设,是一种外部总线的标准,用于规范主机与设备之间的通信与连接。USB系统架构分为三个部分,USB主机控制器...

    Ⅰ. Foundation

    在介绍USB虚拟化之前,我们先了解下关于USB的基础知识。

    USB,即通用串行总线。作为一种计算机外设,是一种外部总线的标准,用于规范主机与设备之间的通信与连接。USB系统架构分为三个部分,USB主机控制器/根集线器(又名,USB总线接口),USB集线器,USB设备。

    USB主机控制器接在PCI/PCIe 总线

    Ⅱ. USB的枚举和传输

    主机通过USB设备枚举的过程来判断和管理设备的连接和断开。1、USB设备连接至集线器的USB端口后,即就是我们笔记本上面的USB接口,集线器会使用其中断IN管道向主机报告设备的插入事件。

    2、主机知道设备接入集线器后,向集线器发出查询请求以了解更多信息。当确认有设备接入总线,主机发出查询请求复位设备,在这期间集线器会确定设备的传输速率并向主机报告。复位结束后USB设备进入缺省状态,并可使用缺省设各地址对管道0的控制事务做出响应。

    3、主机向设备发送USB协议规定的请求描述符命令,读取该描述符的前8个字节,以取得却缺省控制管道所支持的最大数据包长度。

    4、主机发送配置地址命令分配一个唯一的地址给设备。设备读取这个请求,返回一个确认,并保存新的地址。从此开始所有通信都使用这个新地址。

    5、主机向新地址设备重新发送请求描述符命令,读取其设备描述符,以了解该设备的总体信息。

    6、主机向设备循环发送请求配置命令,以读取全部配置信息。获得字符串描述比如厂商、产品描述、型号等。

    7、主机根据Device 和应答信息,为设备选择一个合适的USB设备驱动程序。

    8、加载USB设备驱动后,主机将发出SetConfiguration(x)请求为该设备选择配置。如果配置成功,USB设备进入设备配置状态,可以和主机进行数据通信。

    当USB设备连接到USB总线后,设备便可以和主机进行通信。通信的过程中,自上而下要经过四个部分:主机应用程序

    USB总线驱动程序(Bus Driver)

    USB主控制器驱动程序(Host Driver)

    USB功能设备(Device Driver)

    主机应用程序--->发送数据传输请求(IRP)--->USB总线驱动程序--->响应IRP,数据转化具有USB协议格式的事务处理--->USB主控制器驱动程序--->将这些事务处理建立成事务列表,同时要求不能超过USB带宽--->USB主控制器读取到事务列表并将事务转化为信息包,发送到USB总线接口--->根集线器--->USB设备收到这些信息后,由USB的SIE引擎自动解码信息包--->将其解包后放入指定端点的接收缓冲区内,由芯片固件对其进行处理。

    参考^PCI总线有独立的地址空间,它与处理器地址空间是隔离的

    展开全文
  • 在上一篇文章实现USB虚拟U盘之后,项目需要用同一个USB口同时实现MSC和CDC功能,既能进行串口通信又能读取片外FLASH虚拟U盘。

    前言

    在上一篇文章实现USB虚拟U盘之后,项目需要用同一个USB口同时实现MSC和CDC功能,既能进行串口通信又能读取片外FLASH虚拟U盘。对于USB通用串行总线如果要真正搞明白这个协议还是比较困难的,需要用不少时间来了解驱动原代码,但是如果仅仅会用USB串行通信或者大容量存储这些功能还是相对容易。

    一、硬件

    STM32F407ZGTX,板子上包含一片片外FLASH(w25q128)芯片
    另外,USB_CDC 工程文件,USB_MSC 工程文件准备好。

    二、实现功能

    对于USB复合设备,同一个USB串口实现MSC+CDC功能
    在实现此功能之前,确保对于这两个功能MSC和CDC均已单独完成并测试可行。USB复合设备实现,即对这两个工程的相关文件进行整合,最关键的是对于描述符的修改。配置描述符,接口描述符,端点描述符等。一个设备仅有一个设备描述符,可以有一个或多个配置描述符

    三、Cube MX配置

    前面文章详细介绍了USBMSC虚拟U盘实现,不懂的可以翻看上一篇文章。
    对于CDC虚拟串口的配置,也比较简单,在Cube MX选择Communication Device Class(Virtual Port Com)其他默认即可,这里不详细介绍。
    然后分别对这两个工程进行实验测试均可行,下面开始介绍MSC+CDC双设备实现过程。

    四、文件移植

    1.打开USB_MSC和USB_CDC这两个工程文件夹
    注意:由于CDC工程文件相对较少,我们就把需要的CDC工程的相关文件复制到MSC工程中去。

    左边为CDC工程文件,右边为MSC工程文件
    请添加图片描述
    2.拷贝CDC工程所需的C文件和H文件
    usb_cdc.if.c
    usb_cdc.if.h
    注意,找到这几个文件所在路径,若发现文件中已经包含以上C文件和H文件,便不需要拷贝到MSC工程中。

    请添加图片描述

    将CDC整个文件拷贝到MSC工程对应路径下,注意看图中文件所在位置
    请添加图片描述
    3.创建usbd_msccdc.c文件和usbd_msccdc.h文件
    请添加图片描述
    注意文件所在位置,USB_DEVICE 文件夹—>App文件夹中
    3.打开Keil MSC工程,添加文件
    C文件

    请添加图片描述
    请添加图片描述
    添加H文件路径
    请添加图片描述
    添加完之后工程文件结构如图
    请添加图片描述
    编译无错误然后进行下一步

    五、代码修改

    1.usbd_msccdc.c

    /**
     * @file        usbd_msccdc.c
     * @author      Pzkkkkkk
     * @version     V0.1
     * @date        2021.12.5
     * @brief       MSC + CDC
     * @note
     * @attention   COYPRIGHT Pzkkkkkk
     */
    
    #include "usbd_msccdc.h"
    #include "usbd_def.h"
    #include "usbd_msc.h"
    #include "usbd_cdc.h"
    #include "usbd_storage_if.h"
    #include "usbd_cdc_if.h"
    
    /** @defgroup MC_CORE_Private_FunctionPrototypes
      * @{
      */
    
    USBD_CDC_HandleTypeDef *pCDCData;
    USBD_MSC_BOT_HandleTypeDef *pMSCData;
    
    uint8_t USBD_MC_Init(USBD_HandleTypeDef *pdev,
                         uint8_t cfgidx);
    
    uint8_t USBD_MC_DeInit(USBD_HandleTypeDef *pdev,
                           uint8_t cfgidx);
    
    uint8_t USBD_MC_Setup(USBD_HandleTypeDef *pdev,
                          USBD_SetupReqTypedef *req);
    
    uint8_t USBD_MC_DataIn(USBD_HandleTypeDef *pdev,
                           uint8_t epnum);
    
    uint8_t USBD_MC_DataOut(USBD_HandleTypeDef *pdev,
                            uint8_t epnum);
    
    uint8_t *USBD_MC_GetHSCfgDesc(uint16_t *length);
    
    uint8_t *USBD_MC_GetFSCfgDesc(uint16_t *length);
    
    uint8_t *USBD_MC_GetOtherSpeedCfgDesc(uint16_t *length);
    
    uint8_t *USBD_MC_GetDeviceQualifierDescriptor(uint16_t *length);
    
    static uint8_t USBD_MC_RxReady(USBD_HandleTypeDef *pdev);
    static void MC_Switch_MSC(USBD_HandleTypeDef *pdev);
    static void MC_Switch_CDC(USBD_HandleTypeDef *pdev);
    
    /**
      * @}
      */
    extern USBD_HandleTypeDef hUsbDeviceFS;
    
    /** @defgroup MC_CORE_Private_Variables
      * @{
      */
    USBD_ClassTypeDef USBD_COMPOSITE =
        {
            USBD_MC_Init,
            USBD_MC_DeInit,
            USBD_MC_Setup,
            NULL,            /*EP0_TxSent*/
            USBD_MC_RxReady, /*EP0_RxReady*/
            USBD_MC_DataIn,
            USBD_MC_DataOut,
            NULL, /*SOF */
            NULL,
            NULL,
            USBD_MC_GetHSCfgDesc,
            USBD_MC_GetFSCfgDesc,
            USBD_MC_GetOtherSpeedCfgDesc,
            USBD_MC_GetDeviceQualifierDescriptor,
    };
    
    /* USB Mass storage device Configuration Descriptor */
    /*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
    uint8_t USBD_MC_CfgDesc[USB_MC_CONFIG_DESC_SIZ] =
        {
            /*Configuration Descriptor*/
            0x09,                        /* bLength: Configuration Descriptor size */
            USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
            USB_MC_CONFIG_DESC_SIZ,      /* wTotalLength:no of returned bytes */
            0x00,
            0x03, /* bNumInterfaces: 3 interface */
            0x01, /* bConfigurationValue: Configuration value */
            0x00, /* iConfiguration: Index of string descriptor describing the configuration */
            0xC0, /* bmAttributes: self powered */
            0x32, /* MaxPower 100 mA */
    
            /****************************MSC************************************/
            /* Interface Association Descriptor */
            0x08, // bLength
            0x0B, // bDescriptorType
            0x00, // bFirstInterface
            0x02, // bInterfaceCount
            0x02, // bFunctionClass: CDC Class
            0x02, // bFunctionSubClass
            0x01, // bFunctionProtocol
            0x00, // iFunction
    
            /*Interface Descriptor */
            0x09,                    /* bLength: Interface Descriptor size */
            USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
            /* Interface descriptor type */
            0x00, /* bInterfaceNumber: Number of Interface */
            0x00, /* bAlternateSetting: Alternate setting */
            0x01, /* bNumEndpoints: One endpoints used */
            0x02, /* bInterfaceClass: Communication Interface Class */
            0x02, /* bInterfaceSubClass: Abstract Control Model */
            0x01, /* bInterfaceProtocol: Common AT commands */
            0x00, /* iInterface: */
    
            /*Header Functional Descriptor*/
            0x05, /* bLength: Endpoint Descriptor size */
            0x24, /* bDescriptorType: CS_INTERFACE */
            0x00, /* bDescriptorSubtype: Header Func Desc */
            0x10, /* bcdCDC: spec release number */
            0x01,
    
            /*Call Management Functional Descriptor*/
            0x05, /* bFunctionLength */
            0x24, /* bDescriptorType: CS_INTERFACE */
            0x01, /* bDescriptorSubtype: Call Management Func Desc */
            0x00, /* bmCapabilities: D0+D1 */
            0x01, /* bDataInterface: 1 */
    
            /*ACM Functional Descriptor*/
            0x04, /* bFunctionLength */
            0x24, /* bDescriptorType: CS_INTERFACE */
            0x02, /* bDescriptorSubtype: Abstract Control Management desc */
            0x02, /* bmCapabilities */
    
            /*Union Functional Descriptor*/
            0x05, /* bFunctionLength */
            0x24, /* bDescriptorType: CS_INTERFACE */
            0x06, /* bDescriptorSubtype: Union func desc */
            0x00, /* bMasterInterface: Communication class interface */
            0x01, /* bSlaveInterface0: Data Class Interface */
    
            /*Endpoint 2 Descriptor*/
            0x07,                        /* bLength: Endpoint Descriptor size */
            USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
            MC_CDC_CMD_EP,               /* bEndpointAddress */
            0x03,                        /* bmAttributes: Interrupt */
            LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
            HIBYTE(CDC_CMD_PACKET_SIZE),
            0x10, /* bInterval: */
    
            /*Data class interface descriptor*/
            0x09,                    /* bLength: Endpoint Descriptor size */
            USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
            0x01,                    /* bInterfaceNumber: Number of Interface */
            0x00,                    /* bAlternateSetting: Alternate setting */
            0x02,                    /* bNumEndpoints: Two endpoints used */
            0x0A,                    /* bInterfaceClass: CDC */
            0x00,                    /* bInterfaceSubClass: */
            0x00,                    /* bInterfaceProtocol: */
            0x00,                    /* iInterface: */
    
            /*Endpoint OUT Descriptor*/
            0x07,                     /* bLength: Endpoint Descriptor size */
            USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
            MC_CDC_OUT_EP,            /* bEndpointAddress */
            0x02,                     /* bmAttributes: Bulk */
            LOBYTE(MC_MAX_FS_PACKET), /* wMaxPacketSize: */
            HIBYTE(MC_MAX_FS_PACKET),
            0x00, /* bInterval: ignore for Bulk transfer */
    
            /*Endpoint IN Descriptor*/
            0x07,                     /* bLength: Endpoint Descriptor size */
            USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
            MC_CDC_IN_EP,             /* bEndpointAddress */
            0x02,                     /* bmAttributes: Bulk */
            LOBYTE(MC_MAX_FS_PACKET), /* wMaxPacketSize: */
            HIBYTE(MC_MAX_FS_PACKET),
            0x00, /* bInterval: ignore for Bulk transfer */
    
            /****************************MSC**********************************/
            /* Interface Association Descriptor */
            0x08, // bLength
            0x0B, // bDescriptorType
            0x02, // bFirstInterface
            0x01, // bInterfaceCount
            0x08, // bFunctionClass: MASS STORAGE Class
            0x06, // bFunctionSubClass
            0x50, // bFunctionProtocol
            0x01, // iFunction
    
            /********************  Mass Storage interface ********************/
            0x09, /* bLength: Interface Descriptor size */
            0x04, /* bDescriptorType: */
            0x02, /* bInterfaceNumber: Number of Interface */
            0x00, /* bAlternateSetting: Alternate setting */
            0x02, /* bNumEndpoints*/
            0x08, /* bInterfaceClass: MSC Class */
            0x06, /* bInterfaceSubClass : SCSI transparent*/
            0x50, /* nInterfaceProtocol */
            0x05, /* iInterface: */
            /********************  Mass Storage Endpoints ********************/
            0x07,             /*Endpoint descriptor length = 7*/
            0x05,             /*Endpoint descriptor type */
            MC_MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */
            0x02,             /*Bulk endpoint type */
            LOBYTE(MC_MAX_FS_PACKET),
            HIBYTE(MC_MAX_FS_PACKET),
            0x00, /*Polling interval in milliseconds */
    
            0x07,              /*Endpoint descriptor length = 7 */
            0x05,              /*Endpoint descriptor type */
            MC_MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */
            0x02,              /*Bulk endpoint type */
            LOBYTE(MC_MAX_FS_PACKET),
            HIBYTE(MC_MAX_FS_PACKET),
            0x00 /*Polling interval in milliseconds*/
    };
    
    uint8_t USBD_MC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] =
        {
            USB_LEN_DEV_QUALIFIER_DESC,
            USB_DESC_TYPE_DEVICE_QUALIFIER,
            0x00,
            0x02,
            0x00,
            0x00,
            0x00,
            MC_MAX_FS_PACKET,
            0x01,
            0x00,
    };
    
    /**
      * @brief  USBD_MC_Init
      *         Initialize  the mass storage configuration
      * @param  pdev: device instance
      * @param  cfgidx: configuration index
      * @retval status
      */
    uint8_t USBD_MC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
    {
      uint8_t ret = 0U;
    
      USBD_CDC_HandleTypeDef *hcdc;
    
      MC_Switch_CDC(pdev);
    
      USBD_LL_OpenEP(pdev,
                     MC_CDC_IN_EP,
                     USBD_EP_TYPE_BULK,
                     MC_MAX_FS_PACKET);
    
      USBD_LL_OpenEP(pdev,
                     MC_CDC_OUT_EP,
                     USBD_EP_TYPE_BULK,
                     MC_MAX_FS_PACKET);
    
      USBD_LL_OpenEP(pdev,
                     MC_CDC_CMD_EP,
                     USBD_EP_TYPE_INTR,
                     CDC_CMD_PACKET_SIZE);
    
      hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData;
    
      ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init();
    
      hcdc->TxState = 0;
      hcdc->RxState = 0;
    
      USBD_LL_PrepareReceive(pdev,
                             MC_CDC_OUT_EP,
                             hcdc->RxBuffer,
                             MC_MAX_FS_PACKET);
    
      pCDCData = pdev->pClassData;
    
      MC_Switch_MSC(pdev);
    
      USBD_LL_OpenEP(pdev,
                     MC_MSC_EPOUT_ADDR,
                     USBD_EP_TYPE_BULK,
                     MC_MAX_FS_PACKET);
    
      USBD_LL_OpenEP(pdev,
                     MC_MSC_EPIN_ADDR,
                     USBD_EP_TYPE_BULK,
                     MC_MAX_FS_PACKET);
    
      MSC_BOT_Init(pdev);
    
      pMSCData = pdev->pClassData;
    
      if (pdev->pClassData == NULL)
      {
        ret = USBD_FAIL;
      }
    
      return ret;
    }
    
    /**
      * @brief  USBD_MC_DeInit
      *         DeInitilaize  the mass storage configuration
      * @param  pdev: device instance
      * @param  cfgidx: configuration index
      * @retval status
      */
    uint8_t USBD_MC_DeInit(USBD_HandleTypeDef *pdev,
                           uint8_t cfgidx)
    {
      return USBD_OK;
    }
    /**
    * @brief  USBD_MC_Setup
    *         Handle the MC specific requests
    * @param  pdev: device instance
    * @param  req: USB request
    * @retval status
    */
    uint8_t USBD_MC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
    {
      if (req->wIndex == 0x0002)
      {
        MC_Switch_MSC(pdev);
        USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData;
    
        switch (req->bmRequest & USB_REQ_TYPE_MASK)
        {
    
        /* Class request */
        case USB_REQ_TYPE_CLASS:
          switch (req->bRequest)
          {
          case BOT_GET_MAX_LUN:
    
            if ((req->wValue == 0) &&
                (req->wLength == 1) &&
                ((req->bmRequest & 0x80) == 0x80))
            {
              hmsc->max_lun = ((USBD_StorageTypeDef *)pdev->pUserData)->GetMaxLun();
              USBD_CtlSendData(pdev,
                               (uint8_t *)&hmsc->max_lun,
                               1);
            }
            else
            {
              USBD_CtlError(pdev, req);
              return USBD_FAIL;
            }
            break;
    
          case BOT_RESET:
            if ((req->wValue == 0) &&
                (req->wLength == 0) &&
                ((req->bmRequest & 0x80) != 0x80))
            {
              MSC_BOT_Reset(pdev);
            }
            else
            {
              USBD_CtlError(pdev, req);
              return USBD_FAIL;
            }
            break;
    
          default:
            USBD_CtlError(pdev, req);
            return USBD_FAIL;
          }
          break;
        /* Interface & Endpoint request */
        case USB_REQ_TYPE_STANDARD:
          switch (req->bRequest)
          {
          case USB_REQ_GET_INTERFACE:
            USBD_CtlSendData(pdev,
                             (uint8_t *)&hmsc->interface,
                             1);
            break;
    
          case USB_REQ_SET_INTERFACE:
            hmsc->interface = (uint8_t)(req->wValue);
            break;
    
          case USB_REQ_CLEAR_FEATURE:
    
            /* Flush the FIFO and Clear the stall status */
            USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex);
    
            /* Reactivate the EP */
            USBD_LL_CloseEP(pdev, (uint8_t)req->wIndex);
            if ((((uint8_t)req->wIndex) & 0x80) == 0x80)
            {
              if (pdev->dev_speed == USBD_SPEED_HIGH)
              {
                /* Open EP IN */
                USBD_LL_OpenEP(pdev,
                               MC_MSC_EPIN_ADDR,
                               USBD_EP_TYPE_BULK,
                               MSC_MAX_HS_PACKET);
              }
              else
              {
                /* Open EP IN */
                USBD_LL_OpenEP(pdev,
                               MC_MSC_EPIN_ADDR,
                               USBD_EP_TYPE_BULK,
                               MSC_MAX_FS_PACKET);
              }
            }
            else
            {
              if (pdev->dev_speed == USBD_SPEED_HIGH)
              {
                /* Open EP IN */
                USBD_LL_OpenEP(pdev,
                               MC_MSC_EPOUT_ADDR,
                               USBD_EP_TYPE_BULK,
                               MSC_MAX_HS_PACKET);
              }
              else
              {
                /* Open EP IN */
                USBD_LL_OpenEP(pdev,
                               MC_MSC_EPOUT_ADDR,
                               USBD_EP_TYPE_BULK,
                               MSC_MAX_FS_PACKET);
              }
            }
    
            /* Handle BOT error */
            MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex);
            break;
          }
          break;
    
        default:
          break;
        }
      }
      else
      {
        MC_Switch_CDC(pdev);
        static uint8_t ifalt = 0;
        USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData;
    
        switch (req->bmRequest & USB_REQ_TYPE_MASK)
        {
        case USB_REQ_TYPE_CLASS:
          if (req->wLength)
          {
            if (req->bmRequest & 0x80)
            {
              ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest, (uint8_t *)hcdc->data, req->wLength);
              USBD_CtlSendData(pdev,
                               (uint8_t *)hcdc->data,
                               req->wLength);
            }
            else
            {
              hcdc->CmdOpCode = req->bRequest;
              hcdc->CmdLength = req->wLength;
    
              USBD_CtlPrepareRx(pdev,
                                (uint8_t *)hcdc->data,
                                req->wLength);
            }
          }
          else
          {
            ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest, (uint8_t *)req, 0);
          }
          break;
    
        case USB_REQ_TYPE_STANDARD:
          switch (req->bRequest)
          {
          case USB_REQ_GET_INTERFACE:
            USBD_CtlSendData(pdev,
                             &ifalt,
                             1);
            break;
    
          case USB_REQ_SET_INTERFACE:
            break;
          }
    
        default:
          break;
        }
      }
    
      return USBD_OK;
    }
    
    /**
    * @brief  USBD_MC_DataIn
    *         handle data IN Stage
    * @param  pdev: device instance
    * @param  epnum: endpoint index
    * @retval status
    */
    uint8_t USBD_MC_DataIn(USBD_HandleTypeDef *pdev,
                           uint8_t epnum)
    {
      if (epnum == (MC_MSC_EPIN_ADDR & 0x7f))
      {
        MC_Switch_MSC(pdev);
        MSC_BOT_DataIn(pdev, epnum);
      }
      else if (epnum == (MC_CDC_IN_EP & 0x7f))
      {
        USBD_CDC_HandleTypeDef *hcdc;
    
        MC_Switch_CDC(pdev);
        hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData;
        hcdc->TxState = 0;
      }
    
      return USBD_OK;
    }
    
    /**
    * @brief  USBD_MC_DataOut
    *         handle data OUT Stage
    * @param  pdev: device instance
    * @param  epnum: endpoint index
    * @retval status
    */
    uint8_t USBD_MC_DataOut(USBD_HandleTypeDef *pdev,
                            uint8_t epnum)
    {
      if (epnum == MC_MSC_EPOUT_ADDR)
      {
        MC_Switch_MSC(pdev);
        MSC_BOT_DataOut(pdev, epnum);
      }
      else if (epnum == MC_CDC_OUT_EP)
      {
        USBD_CDC_HandleTypeDef *hcdc;
    
        MC_Switch_CDC(pdev);
        hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData;
    
        hcdc->RxLength = USBD_LL_GetRxDataSize(pdev, epnum);
        ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength);
      }
    
      return USBD_OK;
    }
    
    /**
    * @brief  USBD_MC_GetHSCfgDesc 
    *         return configuration descriptor
    * @param  length : pointer data length
    * @retval pointer to descriptor buffer
    */
    uint8_t *USBD_MC_GetHSCfgDesc(uint16_t *length)
    {
      *length = sizeof(USBD_MC_CfgDesc);
      return USBD_MC_CfgDesc;
    }
    
    /**
    * @brief  USBD_MC_GetFSCfgDesc 
    *         return configuration descriptor
    * @param  length : pointer data length
    * @retval pointer to descriptor buffer
    */
    uint8_t *USBD_MC_GetFSCfgDesc(uint16_t *length)
    {
      *length = sizeof(USBD_MC_CfgDesc);
      return USBD_MC_CfgDesc;
    }
    
    /**
    * @brief  USBD_MC_GetOtherSpeedCfgDesc 
    *         return other speed configuration descriptor
    * @param  length : pointer data length
    * @retval pointer to descriptor buffer
    */
    uint8_t *USBD_MC_GetOtherSpeedCfgDesc(uint16_t *length)
    {
      *length = sizeof(USBD_MC_CfgDesc);
      return USBD_MC_CfgDesc;
    }
    /**
    * @brief  DeviceQualifierDescriptor 
    *         return Device Qualifier descriptor
    * @param  length : pointer data length
    * @retval pointer to descriptor buffer
    */
    uint8_t *USBD_MC_GetDeviceQualifierDescriptor(uint16_t *length)
    {
      *length = sizeof(USBD_MC_DeviceQualifierDesc);
      return USBD_MC_DeviceQualifierDesc;
    }
    
    /**
    * @brief  USBD_MC_RegisterStorage
    * @param  fops: storage callback
    * @retval status
    */
    
    static uint8_t USBD_MC_RxReady(USBD_HandleTypeDef *pdev)
    {
      USBD_CDC_HandleTypeDef *hcdc;
    
      MC_Switch_CDC(pdev);
      hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData;
    
      if ((pdev->pUserData != NULL) && (hcdc->CmdOpCode != 0xFF))
      {
        ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(hcdc->CmdOpCode, (uint8_t *)hcdc->data, hcdc->CmdLength);
        hcdc->CmdOpCode = 0xFF;
      }
    
      return USBD_OK;
    }
    
    static void MC_Switch_MSC(USBD_HandleTypeDef *pdev)
    {
      static USBD_MSC_BOT_HandleTypeDef msc_handle;
    
      USBD_MSC_RegisterStorage(pdev, &USBD_Storage_Interface_fops_FS);
      pdev->pClassData = &msc_handle;
    }
    
    static void MC_Switch_CDC(USBD_HandleTypeDef *pdev)
    {
      static USBD_CDC_HandleTypeDef cdc_handle;
    
      USBD_CDC_RegisterInterface(pdev, &USBD_CDC_Interface_fops_FS);
      pdev->pClassData = &cdc_handle;
    }
    
    /**
      * @}
      */
    
    /**
      * @}
      */
    
    /**
      * @}
      */
    
    /************************ (C) COPYRIGHT PZKKKKKK *****END OF FILE****/
    

    注意:我在usbd_msccdc.c文件中将原来自动生成的结构体变量名USBD_Interface_fops_FS更改为USBD_CDC_Interface_fops_FS ,不修改问题应该也不大,记得在usbd_cdc_if.c和usbd_cdc_if.h定义中修改。主要为了将两个变量区分开,防止出现编译报错。
    2.usbd_msccdc.h

    /**
     * @file        usbd_msccdc.h
     * @author      Pzkkkkkk
     * @version     V0.1
     * @date        2021.12.5
     * @brief       MSC + CDC 
     * @note
     * @attention   COYPRIGHT PZkkkkkk
     */
     
    /* Define to prevent recursive inclusion -------------------------------------*/
    #ifndef __USBD_MSCCDC_H
    #define __USBD_MSCCDC_H
     
    #ifdef __cplusplus
     extern "C" {
    #endif
     
    /* Includes ------------------------------------------------------------------*/
    #include  "usbd_ioreq.h"
    #include 	"usbd_cdc.h"
    #include 	"usbd_msc.h"
    
    #define MC_MAX_FS_PACKET            0x40
    
    #define USB_MC_CONFIG_DESC_SIZ      106 
    
    #define MC_MSC_EPIN_ADDR                MSC_EPIN_ADDR 
    #define MC_MSC_EPOUT_ADDR               MSC_EPOUT_ADDR 
    
    #define MC_CDC_IN_EP                   CDC_IN_EP 
    #define MC_CDC_OUT_EP                  CDC_OUT_EP  
    #define MC_CDC_CMD_EP                  CDC_CMD_EP 
    
    extern USBD_ClassTypeDef  USBD_COMPOSITE;
     
    /**
      * @}
      */
     
    /**
      * @}
      */
     
    #ifdef __cplusplus
    }
    #endif
     
    #endif  /* __USBD_MSCCDC_H */
    /**
      * @}
      */
     
    /************************ (C) COPYRIGHT PZKKKKKK *****END OF FILE****/
    

    3.usbd_cdc.h
    重新分配端点号,否则会冲突

    /** @defgroup usbd_cdc_Exported_Defines
      * @{
      */
    #define CDC_IN_EP                                   0x83U  /* EP1 for data IN */
    #define CDC_OUT_EP                                  0x02U  /* EP1 for data OUT */
    #define CDC_CMD_EP                                  0x82U  /* EP2 for CDC commands */
    

    4.usbd_msc.h

    #define MSC_EPIN_ADDR                0x81U
    #define MSC_EPOUT_ADDR               0x01U
    

    5.usbd_conf.h
    把USBD_MAX_NUM_INTERFACES的值1修改为3

    /*---------- -----------*/
    #define USBD_MAX_NUM_INTERFACES     3U  //1U
    /*---------- -----------*/
    

    6.usbd_conf.c
    函数USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)中进行修改

    /*******************************************************************************
                           LL Driver Interface (USB Device Library --> PCD)
    *******************************************************************************/
    
    /**
      * @brief  Initializes the low level portion of the device driver.
      * @param  pdev: Device handle
      * @retval USBD status
      */
    USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
    {
      /* Init USB Ip. */
      if (pdev->id == DEVICE_FS) {
      /* Link the driver to the stack. */
      hpcd_USB_OTG_FS.pData = pdev;
      pdev->pData = &hpcd_USB_OTG_FS;
    
      hpcd_USB_OTG_FS.Instance = USB_OTG_FS;
      hpcd_USB_OTG_FS.Init.dev_endpoints = 4;
      hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
      hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
      hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
      hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
      hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
      hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
      hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
      hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
      if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK)
      {
        Error_Handler( );
      }
    
    #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
      /* Register USB PCD CallBacks */
      HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
      HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
      HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
      HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
      HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
      HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
      HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
    
      HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_OTG_FS, PCD_DataOutStageCallback);
      HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_OTG_FS, PCD_DataInStageCallback);
      HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback);
      HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback);
    #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
      HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x80);
      HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x40);
    //  HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x80);
      //添加下面两行程序
      HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x40);
      HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x40);
      }
      return USBD_OK;
    }
    

    7.usb_device.c

    /**
      * Init USB device Library, add supported class and start the library
      * @retval None
      */
    void MX_USB_DEVICE_Init(void)
    {
      /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
    
      /* USER CODE END USB_DEVICE_Init_PreTreatment */
    
      /* Init Device Library, add supported class and start the library. */
      if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
      {
        Error_Handler();
      }
      if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_COMPOSITE) != USBD_OK)
      {
        Error_Handler();
      }
    // if (USBD_MSC_RegisterStorage(&hUsbDeviceFS, &USBD_Storage_Interface_fops_FS) != USBD_OK)
    //{
    //    Error_Handler();
    //  }
      if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
      {
        Error_Handler();
      }
    
      /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */
    
      /* USER CODE END USB_DEVICE_Init_PostTreatment */
    }
    

    8.至此,USB双设备MSC+CDC代码修改完毕,最后添加USB串口收发测试代码进行功能测试。

    static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
    {
      /* USER CODE BEGIN 6 */
      USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
      USBD_CDC_ReceivePacket(&hUsbDeviceFS);
    	
    	CDC_Transmit_FS(UserRxBufferFS, *Len);      //将接受到的数据返回
    	
      return (USBD_OK);
      /* USER CODE END 6 */
    }
    

    六、功能测试

    编译无错误,使用USB数据线连接STM32F4开发板USB_SLAVE端口与PC端,下载程序到板子。

    1.MSC虚拟U盘功能

    打开Debug运行程序,立即弹出U盘(若第一次运行可能弹出U盘较慢因为需要建立文件系统格式化U盘)。
    请添加图片描述
    同时对U盘中文件读写功能正常
    请添加图片描述
    2.CDC虚拟串口

    打开串口调试助手,选择串口号(使用USB串口通信不需要设置波特率等其他选项),打开串口,实时返回发送的数据。
    请添加图片描述
    3.打开PC设备管理器
    请添加图片描述
    电脑端同时显示USB串行设备与磁盘驱动STM Product USB Device
    USBMSC+CDC复合设备测试完毕

    展开全文
  • USB SEVER产品不再单纯依赖本地主机,这打破了传统的远程...国内最大的虚拟化平台USB设备解决方案提供商。所有USB设备进行统一有效的管理,提供解决方案,实现共享加密狗,共享扫描仪,共享打印机。 适用环境: ...

    USB SEVER产品不再单纯依赖本地主机,这打破了传统的远程监控困难的桎梏。客户只需使用互联网便可以隨時隨地访问并监控设备,操作方便。使远程设备与主机进行通信,而无需更改现有的应用软件。通过一个IP地址从远程服务器或PC外围设备可以集中管理和监控。

     

    USB SEVER企业版设备有16个 USB 接口和一个以网线接口。加密狗和多种USB设备兼容。国内最大的虚拟化平台USB设备解决方案提供商。所有USB设备进行统一有效的管理,提供解决方案,实现共享加密狗,共享扫描仪,共享打印机。

     

    适用环境:

    虚拟化环境。USB Server  支持 vmware, hyper-v 等虚拟环境。

    支持各种 windows 系统平台。支持各种行业专业软件以及各大银行的Ukey。USB SEVER 使得 USB 认证密钥等 USB 设备在 VMware、Microsoft Virtual Server 和 Xen 等多数虚拟服务器上可以轻松地实现虚拟化并通过网络得到支持。

     

    USB Server客户端:

    USB Server使用的协议兼容FabulaTech公司的USB Over Network客户端,用户可以使用成熟的客户端,确保系统的稳定可靠。

     

    USB Server日志功能:

       系统提供了日志功能,可以根据用户的要求将发送到USB端口的数据包记录下来,并保存到数据库中,日志分为3级,连接记录、数据头、数据包,提供不同级别的记录细节,为需要监控使用的场所提供审核记录。

     

    USB Server与软件的USB的优势:

        同软件的USB共享解决方案相比,硬件方案更优势,每个USB端口能提供规范的750mA供电,使设备工作更稳定,而软件方案常因为多个设备共享时USB端口供电不足,Server free,无须单独配置服务器,节省服务器开支。

    USB Server产品:

    根据配置的不同,USB Server产品划分为、企业版(8口)、企业版(1U16口),金融版(4U24口)和云计算版(4U44口)以及专业定制版本。
    企业版:为安全要求较高的开发部门和对敏感数据有要求的政府部门,带来了USB 设备共享的硬件解决方案。可以通过usb hub 扩展到 127 端口设备使用,同时连接客户数1024
    云计算版:支持128个usb 设备使用,适用行业软件用户,使用加密狗作为软件保护的单机版软件不需要任何修改即可提供按需出租业务模式,后台管理系统提供完善的在线注册,计费,在线支付功能,支持试用,积分,折扣,套餐等促销功能;

    USB serve 产品型号和参数:

    型号:企业版(8口)USB3-BS8D

    产品优势: 小型机   千兆网口  适合办公室 不适合机房24小时工作 

     网络共享 USB 设备的硬件解决方案

     完整的TCP/IP协议支持

     通过网络远程使用加密狗等USB 设备

     WEB 管理界面                                   

     支持VMWare\Xen\Hyper-V等主流服务器虚拟环境

     协议兼容 USB over network 客户端

     1 个GBE 千兆网口

     1 个USB3.0端口

     7 个 USB2.0 Host 端口,每端口提供 750mA 供电

     

    型号:企业版(1u16口)USB3-GS16D 

    产品优势: 1U架构 千兆网口 机房专用,(用友财务软件等虚拟化专用设备)

     

     网络共享 USB 设备的硬件解决方案

     完整的TCP/IP协议支持

     通过网络远程使用加密狗等USB 设备

     WEB 管理界面

     支持VMWare\Xen\Hyper-V等主流服务器虚拟环境

     协议兼容 USB over network 客户端

     1U 机架式结构

     1 个GBE 千兆网口

     2 个USB3.1端口

     14个 USB2.0 Host 端口,每端口提供 750mA 供电

     支持通过vpn 方式连接远程办公室

     支持 snmp 网络管理协议

    型号:金融版(24口)USB3-RG24M

     产品优势:4U架构 千兆网口 机房专用 适用于加密狗数量较多,银企直连前置机虚拟化,故障隔离需求的客户。

     

     网络共享 USB 设备的硬件解决方案

     完整的TCP/IP协议支持

     通过网络远程使用加密狗等USB 设备

     WEB 管理界面

     支持VMWare\Xen\Hyper-V等主流服务器虚拟环境

     协议兼容 USB over network 客户端

     4U 机架式结构

     2 个千兆网口

     24 个 USB2.0 Host 端口,每端口提供 750mA 供电

     支持通过vpn 方式连接远程办公室

     支f持 snmp 网络管理协议

     

    型号:冗余电源版(16口)USB3-RG16M

    产品优势:  1U架构 2个千兆网口 机房专用 双电源配置双机热备、支持断电从启。(用友财务软件加密狗专用设备)

     

     网络共享 USB 设备的硬件解决方案

     完整的TCP/IP协议支持

     通过网络远程使用加密狗等USB 设备

     WEB 管理界面  全新系统

     支持VMWare\Xen\Hyper-V等主流服务器虚拟环境

     协议兼容 USB over network 客户端

     1U 机架式结构 双电源配置

     2 个千兆网口 高性能主板

     2 个USB3.1端口

     14 个 USB2.0 Host 端口,每端口提供 750mA 供电

     支持通过vpn 方式连接远程办公室

     支持 snmp 网络管理协议 解决用友u8和财务软件 各大银行U盾运行更加稳定

     支持断电重启功能

     

    型号:云计算版(44口)USB3-RG44M  

    产品优势: 4U架构  双千兆网口  每个usb口单独供电 每一块主板对应一组USB接口,实现某一组USB口出现故障的情况下别的USB口能正常使用;配有冗余电源实现双电源热备供电;同时连接客户数176; 支持通过vpn 方式连接远程办公室; 支持 snmp 网络管理协议

     

     网络共享 USB 设备的硬件解决方案

     完整的TCP/IP协议支持

     通过网络远程使用加密狗等USB 设备

     WEB 管理界面

     支持VMWare\Xen\Hyper-V等主流服务器虚拟环境

     协议兼容 USB over network 客户端 双客户端增加加密狗兼容性

     4U 机架式结构 双电源配置

     2个GBE 千兆网口

     44个 USB2.0 Host 端口,每端口提供 750mA 供电

     支持通过vpn 方式连接远程办公室

     支持 snmp 网络管理协议

     支持故障隔离

    北京盛讯美恒科技发展有限公司

    地址: 北京市海淀区北清路103号中科产业园3号楼2219室
    邮编: 100085
    QQ:1311205   手机:18611622922      座机010-82482839-8005

    联系人:翟林

    邮箱:1311205@qq.com

    展开全文
  • 一、虚拟化虚拟化,是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而...

    一、虚拟化

    虚拟化,是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。

    虚拟化使用软件的方法重新定义划分IT资源,可以实现IT资源的动态分配、灵活调度、跨域共享,提高IT资源利用率,使IT资源能够真正成为社会基础设施,服务于各行各业中灵活多变的应用需求。

    在计算机中,虚拟化(英语:Virtualization)是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以比原本的组态更好的方式来应用这些资源。这些资源的新虚拟部份是不受现有资源的架设方式,地域或物理组态所限制。一般所指的虚拟化资源包括计算能力和资料存储。

    在实际的生产环境中,虚拟化技术主要用来解决高性能的物理硬件产能过剩和老的旧的硬件产能过低的重组重用,透明化底层物理硬件,从而最大化的利用物理硬件

    二、cpu虚拟化

    1、模拟emulation

    软件方式实现,上层架构和底层可以不一样;需要模拟环0,1,2,3

    2、虚拟virtulization

    上层架构和底层要保持一致

    完全虚拟化(full-virtulization):宿主机完全虚拟出一个完整的平台,guest不清楚自己运行在虚拟环境中;只需要模拟环0,假设各guest的内核运行在环1(实际上不可能运行在环1,因为环1没有特权指令)

    BT:二进制翻译(软件)

    HVM:硬件辅助的虚拟化(硬件),模拟出环-1,host的内核运行在环-1,guest内核运行在环0上,此时环0上没有特权指令,guest运行特权时指令cpu会被触发,这个过程不需要hyper进行监控,提高性能

    半虚拟化(para-virtulization):各host知道自己运行在虚拟化环境中,当需要运行特权指令时,直接请求宿主机的内核

    vm monitor=hypervisor 虚拟化监视器相当于内核

    hypervisor运行在硬件平台上,对底层硬件(cpu和内存不包括io)使用分配过程虚拟成hyper call(hyper 调用),虚拟机的内核运行特权指令时,调用hyper call

    二、内存虚拟化

    进程视角看内存:线性地址空间 虚拟地址

    内核视角看内存:物理地址空间

    MMU将线性地址转化为物理地址

    1、MMU:memory management unit,称为内存管理单元,或者是存储器管理单元,

    MMU是硬件设备,它被保存在主存(main memory)的两级也表控制,并且是由协处理器CP15的寄存器1的M位来决定是enabled还是disabled。MMU的主要作用是负责从CPU内核发出的虚拟地址到物理地址的映射,并提供硬件机制的内存访问权限检查。MMU使得每个用户进程拥有自己的地址空间(对于WINCE5.0,每个进程是32MB;而对于WINCE6.0,每个进程的独占的虚拟空间是2GB),并通过内存访问权限的检查保护每个进程所用的内存不被其他进程破坏。

    VA:virtual address 称为虚拟地址

    PA:physical address称为物理地址

    CPU通过地址来访问内存中的单元,如果CPU没有MMU,或者有MMU但没有启动,那么CPU内核在取指令或者访问内存时发出的地址(此时必须是物理地址,假如是虚拟地址,那么当前的动作无效)将直接传到CPU芯片的外部地址引脚上,直接被内存芯片(物理内存)接收,这时候的地址就是物理地址。如果CPU启用了MMU(一般是在bootloader中的eboot阶段的进入main()函数的时候启用),CPU内核发出的地址将被MMU截获,这时候从CPU到MMU的地址称为虚拟地址,而MMU将这个VA翻译成为PA发到CPU芯片的外部地址引脚上,也就是将VA映射到PA中。MMU将VA映射到PA是以页(page)为单位的,对于32位的CPU,通常一页为4k,物理内存中的一个物理页面称页为一个页框(page frame)。

    虚拟地址空间划分成称为页(page)的单位,而相应的物理地址空间也被进行划分,单位是页框(frame).页和页框的大小必须相同。

    2、CPU访问内存时的硬件操作顺序

    1)CPU内核发出VA请求读数据,TLB(translation lookaside buffer)接收到该地址,那为什么是TLB先接收到该地址呢?

    因为TLB是MMU中的一块高速缓存(也是一种cache,是CPU内核和物理内存之间的cache),它缓存最近查找过的VA对应的页表项,如果TLB里缓存了当前VA的页表项就不必做translation table walk了,否则就去物理内存中读出页表项保存在TLB中,TLB缓存可以减少访问物理内存的次数。

    2)页表项中不仅保存着物理页面的基地址,还保存着权限和是否允许cache的标志。MMU首先检查权限位,如果没有访问权限,就引发一个异常给CPU内核。然后检查是否允许cache,如果允许cache就启动cache和CPU内核互操作。

    3)如果不允许cache,那直接发出PA从物理内存中读取数据到CPU内核。

    4) 如果允许cache,则以VA为索引到cache中查找是否缓存了要读取的数据

    ,如果cache中已经缓存了该数据(称为cache hit)则直接返回给CPU内核,如果cache中没有缓存该数据(称为cache miss),则发出PA从物理内存中读取数据并缓存到cache中,同时返回给CPU内核。但是cache并不是只去CPU内核所需要的数据,而是把相邻的数据都去上来缓存,这称为一个cache line。ARM920T的cache line是32个字节,例如CPU内核要读取地址0x30000134~0x3000137的4个字节数据,cache会把地址0x30000120~0x3000137(对齐到32字节地址边界)的32字节都取上来缓存。

    3、TLB:Translation Lookaside Buffer.

    根据功能可以译为快表,直译可以翻译为旁路转换缓冲,也可以把它理解成页表缓冲。里面存放的是一些页表文件(虚拟地址到物理地址的转换表)。当处理器要在主内存寻址时,不是直接在内存的物理地址里查找的,而是通过一组虚拟地址转换到主内存的物理地址,TLB就是负责将虚拟内存地址翻译成实际的物理内 存地址,而CPU寻址时会优先在TLB中进行寻址。处理器的性能就和寻址的命中率有很大的关系。

    由于CPU首先接到的是由程序传来的ee虚拟内存地址,所以CPU必须先到物理内存中取页表,然后对应程序传来的虚拟页面号,在表里找到对应的物理页面 号,最后才能访问实际的物理内存地址,也就是说整个过程中CPU必须访问两次物理内存(实际上访问的次数更多)。因此,为了减少CPU访问物理内存的次 数,引入TLB。

    MMU的虚拟化:

    INTEL:EPT,Extended Page Table

    AMD:NTP,Nested Page Table

    TLB的虚拟化:

    tagged TLB

    三、I/0虚拟化

    I/0:

    外存:

    硬盘、光盘、u盘

    网络设备:

    网卡

    显示设备:

    VGA:frame buffer机制,

    键盘鼠标:

    ps/2,usb:完全模拟实现,当前焦点捕获,将虚拟设备和物理设备建立关联关系

    I/O虚拟化的方式:

    模拟:完全使用软件来模拟真实硬件

    半虚拟化:

    IO-through:IO透传,让虚拟机直接使用物理设备,几乎接近于硬件性能,硬件必须要支持透传技术: Intel:VT-d   基于北桥的硬件辅助的虚拟化技术

    四、两种虚拟化的实现方式

    1、主机虚拟化技术的两种类型

    a8682ec83946d28a03f6e4fe577941a1.png

    Type-I(能等同于半虚拟化吗?):

    xen,vmware ESX/ESXi

    Type-II(能等同于完全虚拟化吗?):

    kvm,vmware workstation,virtualbox

    2、Intel硬件辅助的虚拟化

    cpu:vt-x,EPT,tagged-TLB

    i0/cpu:vt-d,IOV,VMDq

    3、虚拟化技术的分类

    模拟:Emulation

    上层的虚拟机架构和底层可以不一样,性能比较差

    著名的模拟器  PearPC,Bochs,QEMU

    完全虚拟化:Full Vitualization也称为native virtulization

    类似于模拟但不完全等同于模拟(模型相同)

    cpu和内存不做模拟,只作管理,i/o需要模拟。

    两种加速方式:BT,HVM

    著名软件实现:VMware Workstation,VMware Server,VirtuaBox,Parallels Desktop(实现虚拟化的方式灵活,轻量),KVM,Xen(HVM)

    半虚拟化:para-virtualization

    hyper将底层物理硬件平台略加修改后输出为虚拟机环境,虚拟机的架构和底层架构完全一样

    虚拟机上的操作系统内核需要做修改,让其明确知道自己运行在虚拟化环境中,其内核不能直接发起系统调用、而是发起hypercall来实现

    Xen,UML(user-mode linux)

    OS虚拟化:

    本身没有hyper,直接运行于物理硬件上,

    将操作系统的用户空间切割成多份,每份各自独立,互相隔离,每个用户空间当成一个虚拟机来用

    性能好,但隔离性,稳定性不好

    更多地被称为容器级虚拟化,OpenVZ,LXC(linux container),libcontainer, Solaris Containers,FreeBSD jails

    库虚拟化:

    虚拟化一个程序的运行环境

    wine,

    应用程序虚拟化:

    jvm,

    五、网络虚拟化

    1、网络虚拟化模型

    1)bridge 桥接

    把物理机上的网卡当作交换机,

    在桥接方式下,模拟一个虚拟的网卡给客户系统,主系统对于客户系统来说相当于是一个桥接器。客户系统好像是有自己的网卡一样,自己直接连上网络,也就是说客户系统对于外部直接可见。

    2)Host-Only 仅主机

    纯软件的方式虚拟出一个交换机,各虚拟机的虚拟网卡都连在虚拟交换机上,在物理机系统上虚拟出一个虚拟网卡连在虚拟交换机上。物理系统上的物理网卡和虚拟交换机没有任何关系,

    默认情况下,虚拟机只能到主机访问虚拟机之间也能互相通信而不能访问Internet。这也是hostonly的名字的意义。

    默认情况下,DHCP服务加载到vmnet1上。这样连接到vmnet1上的虚拟机仍然可以设置成dhcp,方便系统的配置。

    3)route 路由

    仅主机模式只要物理机打开网卡间转发功能就成了route模式

    4)NAT

    仅主机模式模型一样

    5)isolation 隔离

    各虚拟机虚拟网卡连在虚拟交换机上,虚拟机之间能互相通信,但虚拟机与主机和internet不能通信

    2、TUN与TAP

    在计算机网络中,TUN与TAP是操作系统内核中的虚拟网络设备。不同于普通靠硬件网路板卡实现的设备,这些虚拟的网络设备全部用软件实现,并向运行于操作系统上的软件提供与硬件的网络设备完全相同的功能。

    TAP等同于一个以太网设备,它操作第二层数据包如以太网数据帧。TUN模拟了网络层设备,操作第三层数据包比如IP数据封包。

    操作系统通过TUN/TAP设备向绑定该设备的用户空间的程序发送数据,反之,用户空间的程序也可以像操作硬件网络设备那样,通过TUN/TAP设备发送数据。在后种情况下,TUN/TAP设备向操作系统的网络栈投递(或“注入”)数据包,从而模拟从外部接受数据的过程。

    3、在linux主机上启动桥功能

    注意:桥功能不支持NetworkManager来管理网络服务,关闭NetworkManager和禁止其开机启动

    使用brctl的配置的过程示例:

    # brctl addbr br0

    # brctl stp br0 on

    # ifconfig eth0 0 up

    # brctl addif br0 eth0

    # ifconfig br0 IP/NETMASK up

    # route add default gw GW[root@BAIYU_179 ~]# rpm -ql bridge-utils

    /usr/sbin/brctl

    /usr/share/doc/bridge-utils-1.2

    /usr/share/doc/bridge-utils-1.2/AUTHORS

    /usr/share/doc/bridge-utils-1.2/COPYING

    /usr/share/doc/bridge-utils-1.2/FAQ

    /usr/share/doc/bridge-utils-1.2/HOWTO

    /usr/share/man/man8/brctl.8.gz

    [root@BAIYU_179 ~]# brctl show

    bridge namebridge idSTP enabledinterfaces

    [root@BAIYU_179 ~]# brctl addbr br0

    [root@BAIYU_179 ~]# brctl show

    bridge namebridge idSTP enabledinterfaces

    br08000.000000000000no

    [root@BAIYU_179 ~]# brctl stp br0 on

    [root@BAIYU_179 ~]# brctl show

    bridge namebridge idSTP enabledinterfaces

    br08000.000000000000yes

    [root@BAIYU_179 ~]# ifconfig eth0 0

    [root@BAIYU_179 ~]# brctl addif br0 eth0

    [root@BAIYU_179 ~]# brctl show

    bridge namebridge idSTP enabledinterfaces

    br08000.000c29566ef4yeseth0

    [root@BAIYU_179 ~]# ifconfig br0 192.168.100.179/24 up

    [root@BAIYU_179 ~]# ifconfig

    br0       Link encap:Ethernet  HWaddr 00:0C:29:56:6E:F4

    inet addr:192.168.100.179  Bcast:192.168.100.255  Mask:255.255.255.0

    inet6 addr: fe80::20c:29ff:fe56:6ef4/64 Scope:Link

    UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

    RX packets:0 errors:0 dropped:0 overruns:0 frame:0

    TX packets:3 errors:0 dropped:0 overruns:0 carrier:0

    collisions:0 txqueuelen:0

    RX bytes:0 (0.0 b)  TX bytes:238 (238.0 b)

    eth0      Link encap:Ethernet  HWaddr 00:0C:29:56:6E:F4

    inet6 addr: fe80::20c:29ff:fe56:6ef4/64 Scope:Link

    UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

    RX packets:1078699 errors:0 dropped:0 overruns:0 frame:0

    TX packets:198700 errors:0 dropped:0 overruns:0 carrier:0

    collisions:0 txqueuelen:1000

    RX bytes:101666119 (96.9 MiB)  TX bytes:15187221 (14.4 MiB)

    eth1      Link encap:Ethernet  HWaddr 00:0C:29:56:6E:FE

    inet addr:172.16.11.135  Bcast:172.16.11.255  Mask:255.255.255.0

    inet6 addr: fe80::20c:29ff:fe56:6efe/64 Scope:Link

    UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

    RX packets:2172706 errors:0 dropped:0 overruns:0 frame:0

    TX packets:126893 errors:0 dropped:0 overruns:0 carrier:0

    collisions:0 txqueuelen:1000

    RX bytes:216073459 (206.0 MiB)  TX bytes:10634543 (10.1 MiB)

    lo        Link encap:Local Loopback

    inet addr:127.0.0.1  Mask:255.0.0.0

    inet6 addr: ::1/128 Scope:Host

    UP LOOPBACK RUNNING  MTU:16436  Metric:1

    RX packets:11790 errors:0 dropped:0 overruns:0 frame:0

    TX packets:11790 errors:0 dropped:0 overruns:0 carrier:0

    collisions:0 txqueuelen:0

    RX bytes:759673 (741.8 KiB)  TX bytes:759673 (741.8 KiB)

    [root@BAIYU_179 ~]# route add default gw 192.168.100.1

    [root@BAIYU_179 ~]# brctl show br0

    bridge namebridge idSTP enabledinterfaces

    br08000.000c29566ef4yeseth0

    这种方法重启计算机将失效,下面再演示一下把配置写在配置文件中的方式:[root@BAIYU_179 ~]# brctl show

    bridge namebridge idSTP enabledinterfaces

    [root@BAIYU_179 ~]# cd /etc/sysconfig/network-scripts/

    [root@BAIYU_179 network-scripts]# ls

    ifcfg-eth0       ifdown-bnep  ifdown-ppp     ifup-bnep  ifup-plusb   ifup-wireless

    ifcfg-eth0.orig  ifdown-eth   ifdown-routes  ifup-eth   ifup-post    init.ipv6-global

    ifcfg-eth1       ifdown-ippp  ifdown-sit     ifup-ippp  ifup-ppp     net.hotplug

    ifcfg-eth1.orig  ifdown-ipv6  ifdown-tunnel  ifup-ipv6  ifup-routes  network-functions

    ifcfg-lo         ifdown-isdn  ifup           ifup-isdn  ifup-sit     network-functions-ipv6

    ifdown           ifdown-post  ifup-aliases   ifup-plip  ifup-tunnel

    [root@BAIYU_179 network-scripts]# vi ifcfg-br0

    [root@BAIYU_179 network-scripts]# vi ifcfg-eth0

    [root@BAIYU_179 network-scripts]# cat ifcfg-br0

    DEVICE=br0

    BOOTPROTO=static

    TYPE=Bridge         #注意这行一定要写而且Bridge的B一定要大写,其它的一定要小写

    #HWADDR=00:0C:29:53:F6:29

    IPADDR=192.168.100.179

    NETMASK=255.255.255.0

    GATEWAY=192.168.100.1

    ONBOOT=yes

    [root@BAIYU_179 network-scripts]# cat ifcfg-eth0

    DEVICE=eth0

    BOOTPROTO=static

    BRIDGE=br0

    #HWADDR=00:0C:29:53:F6:29

    #IPADDR=192.168.100.179

    #NETMASK=255.255.255.0

    #GATEWAY=192.168.100.1

    ONBOOT=yes

    [root@BAIYU_179 network-scripts]# service network restart

    [root@BAIYU_179 network-scripts]# ifconfig

    br0       Link encap:Ethernet  HWaddr 00:0C:29:56:6E:F4

    inet addr:192.168.100.179  Bcast:192.168.100.255  Mask:255.255.255.0

    UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

    RX packets:1280 errors:0 dropped:0 overruns:0 frame:0

    TX packets:1103 errors:0 dropped:0 overruns:0 carrier:0

    collisions:0 txqueuelen:0

    RX bytes:92815 (90.6 KiB)  TX bytes:70438 (68.7 KiB)

    eth0      Link encap:Ethernet  HWaddr 00:0C:29:56:6E:F4

    UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

    RX packets:6632 errors:0 dropped:0 overruns:0 frame:0

    TX packets:6319 errors:0 dropped:0 overruns:0 carrier:0

    collisions:0 txqueuelen:1000

    RX bytes:500126 (488.4 KiB)  TX bytes:390685 (381.5 KiB)

    [root@BAIYU_179 network-scripts]# brctl show

    bridge namebridge idSTP enabledinterfaces

    br08000.000c29566ef4yeseth0

    展开全文
  • USB Server如何加快金融企业虚拟化部署? 金融机构每天要与很多银行、其它金融机构进行频繁的银行账户收付款、数据交互等,因此每家金融企业可能会使用多台前置机作为完成交易的中间设备,而每次登录或交易,前置机...
  • VMWARE服务器虚拟化介绍利用虚拟化基础架构技术,可以不断整合工作负载,从而充分利用服务器并降低运营成本。该基础架构技术不但使系统管理员能够管理更多的服务器,而且在置备新的软件服务和维护现有软件服务时,...
  • FusionComputer是一套已在云计算环境中经过验证的企业级开放式服务器虚拟化解决方案,可以将静态、复杂的IT环境转变为更加动态、易于管理的虚拟数据中心,从而大大降低数据中心成本。同时,它可以提供先进的管理功能...
  • 手边有个项目要用到USB传数据到主机,虽然有很多种方式,但最后还是选择了USB虚拟串口模式,将数据上传至pc端;然而这就涉及到了移植问题,在keil下官方已经给出了一个完整的USB TO VCOM的demo,但在我的主机上装的...
  • 什么是虚拟化

    2021-06-20 01:04:09
    什么是虚拟化虚拟化是一个在从实际硬件中抽象出来的层中运行一个虚拟的计算机系统实例的进程。大多数情况下,它指代同时运行多个操作系统在一个计算机系统上。对于那些在虚拟机上运行的应用程序们,可以看起来像...
  • 宁波银行借助于EastFax USB Server,前置机正在摆脱硬件实体机,逐步向虚拟化超融合方向发展。 宁波银行成立于1997年4月10日,2007年7月19日成为国内首家在深圳证券交易所挂牌上市的城市商业银行。除了在宁波地区...
  • 源自企业一线运维工程师的实践经验,归纳总结虚拟化工程师应知必会六件事,系统讲解IT系统运维过程中必须掌握的虚拟化技术。包括:VMware服务器虚拟化、Citrix桌面/应用虚拟化、Veeam备份、Zabbix监控。本书详细介绍...
  • 虚拟化技术包括服务器虚拟化、桌面虚拟化和应用虚拟化等几个方面。桌面虚拟化技术实际上是在服务器虚拟化的基础上,通过各种通讯的手段,将桌面推送到远端 来实现的。简单地说,桌面虚拟化技术就是服务器虚拟化加上...
  • 虚拟化技术的分类及介绍

    万次阅读 多人点赞 2019-01-03 19:45:06
    本文首先介绍了不同抽象层次的虚拟化技术,之后对应用广泛的系统级虚拟化和操作系统级虚拟化进行了更详细的分类和描述,最后介绍了各种典型虚拟化方案的具体实现。   目录 摘要 1 目录 1 1 引言 2 2 虚拟化...
  • 从浅层面上看,虚拟化将提升企业应用低成本、高效率等关键指标,更深意义上看,虚拟化实现了云计算提供商五项特征中的四项,即:基于服务,可伸缩和弹性,共享以及按用计量。也就是说,虽然虚拟化不是实现云计算的唯...
  • By Falcon of TinyLab.org2015-12-07简介串口是嵌入式设备中常见的调试、...Serial Port Over Network通过网络虚拟化串口的基本需求很简单,首先要把串口虚拟化为网络端口,之后在网络中的另外一台主机上通过 tel...
  • kvm半虚拟化驱动

    2021-05-17 15:15:27
    虚拟化驱动host:宿主机(物理机),guest:客户机(虚拟机)1.使用virtio驱动linux中的virtio驱动linux内核一般都自带virtio模块内核配置文件与virtio相关配置[root@desktop0 ~]#grep VIRTIO_ /boot/config-3.10.0-123...
  • STM32利用STM32CUBEMX快速实现USB虚拟串口回环测试 目录STM32利用STM32CUBEMX快速实现USB虚拟串口回环测试1、配置时钟2、开启USB3、开启USB设备:虚拟串口4、生成工程5、修改代码实现回环收发数据测试 环境: STM...
  • 虚拟化软件解决方案

    2021-08-04 02:32:55
    1.背景随着涉密行业信息建设和IT业务的快速增长,涉密行业传统信息建设中对于服务器应用面临着如下困境:资源利用率低:传统服务器应用部署模式采用“烟囱式”架构,单个应用独享整个服务器资源,资源利用率低。...
  • 回复: 101在MINI STM32 板子上实现USB虚拟串口电梯直达发表于 2011-6-27 06:51:45|只看该作者|倒序浏览|阅读模式(原文件名:A6.jpg)实验内容:通过STM32的USB端口在PC上虚拟一个COM口,当虚拟成功后,可通过串口调试...
  • 虚拟化技术包括服务器虚拟化、桌面虚拟化和应用虚拟化等几个方面。桌面虚拟化技术实际上是在服务器虚拟化的基础上,通过各种通讯的手段,将桌面推送到远端来实现的。简单地说,桌面虚拟化技术就是服务器虚拟化加上...
  • 巨恒DataApp Cloud桌面虚拟化软件即操作系统虚拟化,是一种“桌面虚拟化解决方案”,桌面工作在裸金属架构下, 使得桌面数据可与硬件分离,用户桌面数据均集中存储于云桌面系统Server 上,实现了用户桌面数据的统一管理,...
  • 服务器 虚拟化 ip地址规划 内容精选换一换弹性公网IP是可以直接访问Internet的IP地址。一个弹性公网IP只能给一个裸金属服务器使用。私有IP是公有云内网所使用的IP地址,用于内网通信,私有IP不能访问Internet。虚拟...
  • 随着服务器虚拟化发展的步步深入和普及,伴随使用出现的一些问题也逐渐浮现出来,例如,不同应用环境下的的企业、行业用户除了关注性能之外,也在产品的安全、管理、便捷、产品定制以及服务等方面提出了本土化的需求...
  • ZDNet至顶网软件频道消息随着云计算时代的到来,作为搭建云计算基础架构的重要组件——虚拟化产品,也受到越来越多的关注。VMware凭借着国际品牌的影响力,在国内吸引了大部分的注意力,但与此同时,VMware产品高昂...
  • 虚拟化技术

    2020-12-26 11:18:54
    虚拟化技术前言一、虚拟化技术简介1、虚拟化技术的概念2.虚拟化技术的分类1.引入库2.读入数据总结 前言 近年来,计算机硬件与软件的性能比以往有了椰大的发展与进步,计算机硬件的入反为人们提供了极其强大的计算...
  • 应用虚拟化

    2021-08-02 07:06:40
    应用虚拟化是将应用程序与操作系统解耦合,为应用程序提供了一个虚拟的运行环境。在这个环境中,不仅包括应用程序的可执行文件,还包括它所需要的运行时环境。从本质上说,应用虚拟化是把应用对低层的系统和硬件的...
  • Intel的虚拟化技术主要有两个方面:一个是CPU的VT-x,一个是主板的VT-d。按照简单的理解,VT-x使得CPU的指令集支持虚拟化,使得虚拟机上CPU的计算能力不下降;VT-d使得主板可以把各类IO设备(比如显卡,阵列卡或USB...
  • 该楼层疑似违规已被系统折叠隐藏此楼查看此楼服务器虚拟化WinServer服务器虚拟化将服务器物理资源抽象成逻辑资源,让一台服务器变成几台甚至上百台相互隔离的虚拟服务器,不再受限于物理上的界限,而是让CPU、内存、...
  • 多核CPU带动虚拟化产品如果说虚拟化技术能够很大程度上改善任何规模的计算环境一点不为过。如今企业可以使用一台服务器运行多台虚拟服务器,进而减少运作成本,获得更多收益。这样来看,多核处理器的服务器会成为这...
  • STM32F407 USB虚拟双串口

    2021-08-16 13:54:53
    STM32F407 USB 虚拟双串口 文章目录STM32F407 USB 虚拟双串口准备工作代码修改端点配置修改描述符修改数据处理 准备工作 通过STM32CubeMX生成一份标准的USB VCP例程. 代码修改 端点配置修改 增加第二个虚拟串口...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,048
精华内容 14,419
热门标签
关键字:

usb虚拟化