YIE002开发探索06-串口(中断)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
(代码仓库地址:https://gitee.com/luobing4365/yie002-explorer
具体参考博客:YIE002开发探索-Gitee代码仓库说明)

用轮询的方式获取串口数据,是一种非常低效的方法。本篇尝试使用中断的方式,来实现串口的通信。

1 STM32的串口中断

在上一篇中,简单介绍过STM32的串口。轮询方式的编码中,只需要了解相关API的用法就可以了,编写相对简单。

对中断编程而言,这种程度的背景知识是不够的。STM32的Cube Library构建了完整的串口中断编程架构,也提供了相应的API函数供调用。不过,从我的角度来看,这个架构有点难以理解。需要使用者从原理上去了解,才可能自如的使用这些函数。

因此,建议开发人员对串口的寄存器、中断事件等,有了基本的了解后,仔细阅读Cube Library提供的串口函数的实现,再去构建代码较好。

1.1 STM32的中断事件和寄存器

以下的内容基本来自于《STM32参考手册》,详细的内容可以在原文档中查找,我主要是将需要的内容进行了整理。

STM32的USART中断请求事情比较丰富,如表1所示。

表1 USART中断请求

中断事件事件标志使能位
发送数据寄存器空TXETXEIE
CTS标志CTSCTSIE
发送完成TCTCIE
接收数据就绪可读TXNETXNEIE
检测到数据溢出OREIDELIE
检测到空闲线路IDLEIDELIE
奇偶检验错PEPEIE
断开标志LBDLBDIE
噪声标志,多缓冲通信中的溢出错误和帧错误NE或ORT或FEEIE

表中的EIE标志位,仅当使用DMA接收数据时,才会使用。

USART的各种中断事件,被连接到同一中断向量,表中的中断事件大致可分为发送期间产生的中断事件和接收期间发生的中断事件。也即:

1)发送期间:发送完成、清除发送、发送数据寄存器空。
2)接收期间:空闲总线检测、溢出错误、接收数据寄存器非空、校验错误、 LIN断开符号检测、噪音标志(仅在多缓冲器通信)和帧错误(仅在多缓冲器通信)。

在实际的编程中,大部分的中断事件,是不需要关注的。编程中,主要关注的是接收数据就绪可读(也即接收数据寄存器非空)、发送完成以及检测到空闲线路。

当然,为了熟悉这些中断事件,对USART的寄存器也必须了解。图1给出了我绘制的思维导图,只对我关系的寄存器位进行了整理,更详细的资料,请参考《STM32参考手册》。

图1 USART寄存器的思维导图
继续阅读“YIE002开发探索06-串口(中断)”

869 total views, no views today

YIE002开发探索05-串口(轮询)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
(代码仓库地址:https://gitee.com/luobing4365/yie002-explorer
具体参考博客:YIE002开发探索-Gitee代码仓库说明)

串口是相当的古老的接口,大概率比看这篇博客的读者早出生。常用的串口标准RS-232标准是EIA(美国电子工业联合会)和贝尔公司,于1969年公布的。它比较适合数据传输率在20000bit/s内的通讯,标准对信号线功能、电气特性都有明确规定。

常用的串口,包括RS232、TTL232、RS485和RS422标准。不过从软件协议上来看,RS232和TTL232是一样的 ,其区别主要在于硬件。

从硬件的电平上来看,TTL232使用+5V/+3.3V电平表示逻辑“1”,0V电平表示逻辑“0”;RS232则用-3V至-15V表示逻辑“1”,+3V至+15V表示逻辑“0”,也即采用负逻辑来表示。

如表1所示,给出了RS232、RS485和RS422的区别。

表1 串口标准

通信标准电平标准通信距离通信方式信号
RS232逻辑1: -15V至-3V
逻辑0: 3V至15V
15米全双工单端信号
RS485逻辑1: 2V至6V
逻辑0: -6V至-2V
1200米2线半双工差分信号
RS422逻辑1: 2V至6V
逻辑0: -6V至-2V
1200米4线全双工差分信号
继续阅读“YIE002开发探索05-串口(轮询)”

764 total views, 1 views today

YIE002开发探索04-定时器

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
(代码仓库地址:https://gitee.com/luobing4365/yie002-explorer
具体参考博客:YIE002开发探索-Gitee代码仓库说明)

定时器的最基本的功能是用来周期性的定时,当然,它还用来实现如下功能:
1) 输入捕获。脉冲计数,在上升沿或下降沿检测,已经PWM的输入检测;
2) 输出比较。脉冲输出和步进电机的控制;
3) PWM生成。电压输出控制、直流减速电机控制等;
4) 编码器接口、霍尔传感器接口等。

当然,根据所用芯片不同,定时器还能提供更多的功能,比如与DMA的配合等。本篇准备用定时器产生的时间中断,周期性地控制LED灯的亮灭,以期对定时器的编程有基本的理解。

1 STM32的定时器

YIE002-STM32所用的芯片为STM32F103C8T6,属于STM32F1系列,在此系列,STM32提供了大量的定时器:2个基本定时器(TIM6、TIM7)、4个通用定时器(TIM2、TIM3、TIM4、TIM5)、2个高级控制定时器(TIM1和TIM8),以及4个特定功能定时器(SysTick、IWDG、WWDG、RTC),共有12个。另外,超大容量系列的产品中,又增加了5个通用寄存器TIM9~TIM14。

从功能上来说,高级控制通用器的功能是通用定时器的超集、通用定时器的功能是基本定时器的超集。比较通用定时器和高级控制定时器,可知它们的功能非常接近,高级控制定时器只是针对电动机的控制增加了一些功能。

因此,本篇准备使用通用定时器TIM3,构建演示程序。

1.1 定时器的时钟

TIM1和TIM8是高级控制定时器,时钟由APB2输出产生;TIM2至于TIM5是通用定时器,TIM6和TIM7是基本定时器,时钟由APB1输出产生。

从前几篇中可以知道,F103C8T6的系统时钟为72MHZ。如图1所示的时钟树,给出了定时器的时钟频率。


图1 定时器的时钟树
继续阅读“YIE002开发探索04-定时器”

910 total views, 1 views today

YIE002开发探索03-外部中断

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
(代码仓库地址:https://gitee.com/luobing4365/yie002-explorer
具体参考博客:YIE002开发探索-Gitee代码仓库说明)

上一篇中,实现了按键的控制功能。本篇准备使用外部中断的方式,来实现对按键的控制。

1 STM32的外部中断

在跑马灯的实验中,简要的介绍过GPIO的设置。对于本篇来说,使用GPIO作为外部输入中断,所需要关注的知识点有两块:
1) 如何配置外部中断,以及与之相关的中断程序的编写;
2) 中断管理分组以及中断的优先级。

1.1 外部中断/事件控制器(EXTI)

STM32的每个IO都可以作为外部中断的中断输入口。STM32F103C8T6有19个能产生事件/中断请求的边沿检测器,每个输入线可以独立配置成输入类型和对应的触发事件(上升沿、下降沿或双边沿触发)。

这19个外部中断为:
线 0~15:对应外部 IO 口的输入中断。
线 16:连接到 PVD 输出。
线 17:连接到 RTC 闹钟事件。
线 18:连接到 USB 唤醒事件。

也就是说,供IO口使用的中断线只有16个。而STM32的IO口数目是超过16个的,因此,必然产生共用的问题。

在设计上,STM32的管脚GPIOx.0GPIOx.15(x=A/B/C/D/E/F/G)分别对应中断线015,也即每个中断线最多对应7个IO口。比如,线1对应GPIOA.1、GPIOB.1、GPIOC.1…GPIOG.1。中断线每次只能连接到1个IO口上,在平常编程中,需要通过配置决定中断线连接到哪个GPIO上。

如图1,给出了GPIO与中断线的映射关系图。

图1 外部中断通用I/O映像
继续阅读“YIE002开发探索03-外部中断”

914 total views, no views today

YIE002开发探索02-按键

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
(代码仓库地址:https://gitee.com/luobing4365/yie002-explorer
具体参考博客:YIE002开发探索-Gitee代码仓库说明)

按键实验中,使用GPIO的相关知识就可以了。在上一篇中,已经介绍了GPIO的基本用法,这一篇使用这些知识实现按键的功能。

1 在YIE002-STM32型上编程

在后续的实验中,没有必要每次都重新去配置工程。比如时钟树的配置、调试的配置等,每次都差不多。因此,可以直接在之前的工程上进行修改,添加需要的功能即可。本篇的工程,就是在上一篇的基础上进行修改的。

1.1 硬件资源

YIE002-STM32型上准备了三个按键,如图1所示。

图1 按键的硬件资源

开发板上提供的三个按键SW1、SW2和SW3,分别连接到PA6、PA5和PA1上。从图中可以看出,这三个按键都是低电平有效的。

继续阅读“YIE002开发探索02-按键”

865 total views, no views today

YIE002开发探索01-跑马灯

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
(代码仓库地址:https://gitee.com/luobing4365/yie002-explorer
具体参考博客:YIE002开发探索-Gitee代码仓库说明)

(YIE001和YIE002都是我平时为了嵌入式编程所做的开发板,特征在于:方便回家或出差携带、U盘大小。《UEFI编程实践》也使用它们,作为PCIE和USB程序的实验硬件。)

在YIE002上准备了5个LED灯,除去用来显示电源的灯,其余4个都可以用来做实验。这一篇中,我准备用这4个灯实现跑马灯的效果。

1 STM32的GPIO

STM32单片机的每个IO口可以自由编程,不过要求是按32位字进行访问。包括输入和输出,它们可以配置为8种模式。在输入时,包括模拟输入、浮空输入、下拉输入和上拉输入;通用输出时,包括推挽式和开漏式;复用功能输出时,也包括推挽式和开漏式。

为控制IO端口,STM32提供了7个寄存器来进行控制。对于这些寄存器的用法,不需要深入了解也可以编程。有兴趣的话,它们的具体用法,可以查看《STM32中文参考手册_V10.pdf》。

YIE002-STM32型开发板使用的是F103C8T6,其封装类型为LQFP48。当前我使用的版本,准备了5个LED灯,除了其中一个用来表示电源接通,其他4个都可以通过GPIO来控制。

STM32对于GPIO的编程,主要包括使能相应的时钟、设置相应的工作模式、置位或清位。在Cube Library中,主要包含以下可使用的API(参考UM1850《Description of STM32F1 HAL and low-layer drivers》):

1) 初始化函数

void HAL_GPIO_Init (GPIO_TypeDef * GPIOx, GPIO_InitTypeDef * GPIO_Init) ;
void HAL_GPIO_DeInit (GPIO_TypeDef * GPIOx, uint32_t GPIO_Pin) ;

2) IO操作函数

GPIO_PinState HAL_GPIO_ReadPin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin);
void HAL_GPIO_WritePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
void HAL_GPIO_TogglePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin);
HAL_StatusTypeDef HAL_GPIO_LockPin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin);
void HAL_GPIO_EXTI_IRQHandler (uint16_t GPIO_Pin);
void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin);

对于GPIO时钟的配置,一般在CubeMx图形化编程时,会自动生成代码。因此,对GPIO的操作,主要使用读、写、变换(也即上述的HAL_GPIO_ReadPin、HAL_GPIO_WritePin、HAL_GPIO_TogglePin)就可以了。

下面在YIE002-STM32型上,实现跑马灯的代码。

继续阅读“YIE002开发探索01-跑马灯”

907 total views, no views today

UEFI开发探索92 – 调试使用了StdLib的64位程序

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

昨天有位名为“sam bing”的网友,提到用VS2015和EmulatorPkg调试UEFI程序。调试方法在之前的博客中讨论过,他是参照博客去操作的。

问题在于,他发现在工程中使用C标准库函数,也即StdLib后,在EmulatorPkg中无法编译通过,也就无法通过EmulatorPkg进行64位C标准库工程的调试了。

这个问题我也觉得奇怪,理论上不应该啊。

上午处理完项目相关的事情后,正好有点时间,就着手进行这个问题的分析了。

1 搭建开发环境

我日常都是在vUDK2018下进行开发,主要是因为它还支持Nt32Pkg,方便我随时使用模拟器进行调试。

为了分析这个问题,我得用一个相对较新的版本来测试。正好前段时间整理书稿的时候,搭建了一个开发环境,看了下版本:

robin@DESKTOP-083AISO:/mnt/c/srcEDKx/edk2$ git log
commit ca407c7246bf405da6d9b1b9d93e5e7f17b4b1f9 (HEAD, tag: edk2-stable202005)
Author: Ard Biesheuvel <ard.biesheuvel@arm.com>
Date:   Wed May 20 13:44:48 2020 +0200

ArmPkg/CompilerIntrinsicsLib: provide atomics intrinsics
…..//后略

robin@DESKTOP-083AISO:/mnt/c/srcEDKx/edk2$ ls
AppPkg          DynamicTablesPkg     License.txt      RobinPkg             StdLibPrivateInternalFiles
ArmPkg          EmbeddedPkg          Maintainers.txt  RobinPkg1            UefiCpuPkg
ArmPlatformPkg  EmulatorPkg          MdeModulePkg     SecurityPkg          UefiPayloadPkg
ArmVirtPkg      FatPkg               MdePkg           ShellPkg             UnitTestFrameworkPkg
BaseTools       FmpDevicePkg         NetworkPkg       SignedCapsulePkg     edksetup.bat
Build           IntelFsp2Pkg         OvmfPkg          SourceLevelDebugPkg  edksetup.sh
Conf            IntelFsp2WrapperPkg  PcAtChipsetPkg   StandaloneMmPkg      pip-requirements.txt
CryptoPkg       License-History.txt  ReadMe.rst       StdLib

使用的是2020年的5月版,为了方便使用,我把StdLib、AppPkg等包,以及我自己的包RobinPkg一股脑都放在了edk2的同一目录下了。

继续阅读“UEFI开发探索92 – 调试使用了StdLib的64位程序”

3,704 total views, no views today

UEFI开发探索91- 类型强制转换引起的问题

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

最近有个项目开发,我需要构建几个UEFI图形对话框,用来接受用户的密码修改和输入。大致的样子是这样的:

图1 UEFI下的密码对话框

开发过程中,发现使用VS编译和GCC编译的结果不同。一番折腾后,了解到是强制转换引起的问题。

之前有个问题集的博客,本想把这个问题也扔到那边去,不过在寻找问题原因的过程中,使用了各种调试手段,我觉得有必要记录下来,作为未来开发的参考。

因此有了这篇博客。

继续阅读“UEFI开发探索91- 类型强制转换引起的问题”

1,518 total views, 1 views today

UEFI开发探索90- YIE002USB开发板(13 Linux编程)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

上一篇使用hidapi的hidraw方式,实现了Linux上位机与USB HID设备通信的测试程序。不过,只实现了三种通信方式中的两种。本篇将使用hidapi的libusb方式,将三种通信方式全部实现。

1 建立开发目录

与上一篇一样,首先建立开发用的目录。新建文件夹hidlibusb,将以下文件拷贝进去:

libusb/hid.c
hidapi/hidapi.h
hidtest/test.c

为目前的代码编写Makefile,内容如下:

继续阅读“UEFI开发探索90- YIE002USB开发板(13 Linux编程)”

1,094 total views, no views today

UEFI开发探索89- YIE002USB开发板(12 Linux编程)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

对于USB HID的编程,在YIE002USB开篇时,就已经讨论过:

  1. 下位机是使用YIE002制作的USB HID设备,这是嵌入式开发;
  2. 上位机包括了Windows系统、UEFI系统和Linux系统。

上位机软件中,没有把Mac OSX包含进来,主要是因为我较少在苹果的系统上开发,而且也可以将其等同于Linux系统看待(同属于类Unix系)。

至今为止,Windows系统和UEFI系统,我们都已经完成了上位机的软件编写,下面该进入Linux的USB HID上位机软件开发了。

1 概述

对于Linux下的HID,网站“The Linux Kernel”上有非常详细的描述,值得仔细阅读,网址为:
https://www.kernel.org/doc/html/latest/hid/index.html。

我们所要访问的设备,是USB HID设备。在Linux系统中,常用的USB开源库,是libusb。这是一个用C语言开发的,跨平台的USB设备访问接口库。

在Github上找到这个开源库后,通读了一遍其文档。理论上使用它,可以完整地实现我们所需要的功能。不过,文档中也建议,如果是访问HID设备的话,可以使用hidapi。

hidapi是一个开源的操作HID设备的C语言库,适用于Windows、Linux和Mac OSX平台。它是针对HID设备的,对于其他USB设备不合适。

其源码仓库为:https://github.com/libusb/hidapi,主要目录如下:

hidapi: 头文件(所有平台共用一份头文件)hidapi.h
libusb:Linux系统实现源码文件hid.c,使用libusb库实现的方式
linux:Linux系统实现源码文件hid.c,使用内核接口(hidraw)实现方式
windows:Windows系统实现源码文件hid.c
mac:Mac OSX 系统实现源码文件hid.c
hidtest:测试代码 test.c
继续阅读“UEFI开发探索89- YIE002USB开发板(12 Linux编程)”

1,119 total views, no views today

UEFI开发探索88- YIE002USB开发板(11 UEFI下访问HID设备)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

通过前面几个篇章的博客,制作好了USB HID设备,并使用Windows下的上位机工具UsbHID,测试了设备的工作状态。

终于,可以在UEFI系统下构建访问USB HID设备的工程了。

我们所制作的USB HID设备,在Windows系统下可以成功通信,这也意味着,在UEFI环境下,我们也可以与之通信。

首先,使用linux下的lsusb工具,查看下我们之前实现的USB HID设备:

robin@robin-virtual-machine:~$ sudo lsusb -v -d 0x8765:4321
Bus 002 Device 004: ID 8765:4321  
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x8765 
  idProduct          0x4321 
  bcdDevice            2.00
  iManufacturer           1 Robin
  iProduct                2 Robin's UEFI Explorer
  iSerial                 3 My123
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           41
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xe0
      Self Powered
      Remote Wakeup
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      33
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              32
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              32
Device Status:     0x0003
  Self Powered
  Remote Wakeup Enabled

从中可以看出,自制的USB HID设备,端点1可以使用中断传输的方式进行通信。另外,在上述的信息中没有列出报表描述符,此设备支持通过Output report& Input report、Feature report的方式进行通信,传输字节为16字节。

本篇介绍如何在UEFI系统下,实现对应这三种通信方式的代码,主要实现步骤如下。

继续阅读“UEFI开发探索88- YIE002USB开发板(11 UEFI下访问HID设备)”

1,539 total views, 1 views today

UEFI开发探索87- YIE002USB开发板(10 UEFI对USB的支持2)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

3 EFI_USB_IO_PROTOCOL

EFI_USB_IO_PROTOCOL由USB总线驱动产生,可由UEFI应用和驱动使用,用来访问各种USB设备,比如USB键盘、鼠标和大容量存储设备等。EFI_USB_IO_PROTOCOL所提供的接口,可提供四种类型的传输方式与USB设备通信,即之前介绍过的控制传输、中断传输、批量传输和实时传输。

EFI_USB_IO_PROTOCOL的函数接口如下所示:

typedef struct _EFI_USB_IO_PROTOCOL {
  EFI_USB_IO_CONTROL_TRANSFER UsbControlTransfer;   //控制传输
  EFI_USB_IO_BULK_TRANSFER UsbBulkTransfer;          //批量传输
  EFI_USB_IO_ASYNC_INTERRUPT_TRANSFER  \
                          UsbAsyncInterruptTransfer;   //异步中断传输
  EFI_USB_IO_SYNC_INTERRPUT_TRANSFER UsbSyncInterruptTransfer //同步中断传输
  EFI_USB_IO_ISOCHRONOUS_TRANSFER UsbIsochronousTransfer;      //实时传输
  EFI_USB_IO_ASYNC_ISOCHRONOUS_TRANSFER \
                          UsbAsyncIsochronousTransfer; //异步实时传输
  EFI_USB_IO_GET_DEVICE_DESCRIPTOR UsbGetDeviceDescriptor; //获取设备描述符
  EFI_USB_IO_GET_CONFIG_DESCRIPTOR UsbGetConfigDescriptor; //获取配置描述符
  EFI_USB_IO_GET_INTERFACE_DESCRIPTOR \
                        UsbGetInterfaceDescriptor;               //获取接口描述符
EFI_USB_IO_GET_ENDPOINT_DESCRIPTOR UsbGetEndpointDescriptor;
//获取端点描述符
  EFI_USB_IO_GET_STRING_DESCRIPTOR UsbGetStringDescriptor;//获取字符串描述符
  EFI_USB_IO_GET_SUPPORTED_LANGUAGES UsbGetSupportedLanguages;//获取支持语言
  EFI_USB_IO_PORT_RESET UsbPortReset;                        //重启USB控制器
} EFI_USB_IO_PROTOCOL;

对照之前介绍过的USB协议的知识,很容易理解EFI_USB_IO_PROTOCOL所提供的各类接口函数。下面主要介绍下常用的两个接口函数,UsbGetDeviceDescriptor()和UsbControlTransfer(),其他接口函数的说明,请查询UEFI Spec。

继续阅读“UEFI开发探索87- YIE002USB开发板(10 UEFI对USB的支持2)”

845 total views, no views today

UEFI开发探索86- YIE002USB开发板(09 UEFI对USB的支持1)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

通过前面几篇博客,我们制作了具备通信能力的USB HID设备。使用之前写的Windows下的测试工具,设备工作得很好。

同样的,UEFI环境下,也可以编写上位机程序,访问USB HID设备。本篇主要介绍UEFI对USB的支持,包括UEFI的USB驱动架构和提供的USB Protocol。

1 UEFI下的USB驱动协议架构

在UEFI系统中,包含USB主控制器驱动、USB总线驱动和USB设备驱动,它们共同工作构建了UEFI平台的USB驱动协议栈。USB驱动协议栈的模型如图1所示,图中演示了USB驱动的关系和使用的Protocol。

图1 UEFI中的USB驱动协议栈

平台硬件的PCI总线上,提供了一个单独的USB控制器。PCI总线驱动为USB主控制器句柄安装Protocol,包括EFI_DEVICE_PATH_PROTOCOL和EFI_PCI_IO_PROTOCOL。而USB主控制器则使用EFI_PCI_IO_PROTOCOL,在其句柄上安装EFI_USB2_HC_PROTOCOL。

继续阅读“UEFI开发探索86- YIE002USB开发板(09 UEFI对USB的支持1)”

1,081 total views, no views today

UEFI开发探索85- YIE002USB开发板(08 制作HID设备)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

在介绍完所有背景知识后,终于可以进入实质的嵌入式编程了。

本篇拟使用YIE002开发板,制作一个USB HID设备,支持三种通信方式,以对应UEFI开发探索73和74所讨论的三种上位机通信。

这个系列的博客,主要还是偏向UEFI编程的探索,对于嵌入式的编程,不想讨论过多。对于YIE002的嵌入式开发,请移步我另外一个专栏“嵌入式开发”,在其中我开了一个新坑,用来探索YIE002的编程。

1 YIE002-STM32的USB编程

这款开发板的主芯片是STM32F103C8T6,是我出差最常带的版型。本篇所写的代码,适用于所有F1系列作为主芯片的开发板,比如正点原子的战舰开发板。

从意法的官方资料可知,STM32 MCU有如下USB IP:

  1. USB IP 可作为全速USB设备,存在于STM32F102、STM32F103;
  2. USB+ IP 可作为全速USB设备,存在于STM32F0x2;
  3. FS OTG IP 可作为全速和低速USB主机、全速USB设备,存在于STM32F105、STM32F107、STM32F2、STM32F4;
  4. HS OTG IP 可作为高速、全速和低速USB主机,可作为高速和全速USB设备,存在于STM32F2、STM32F4。

官方也提供了不同的USB库,以适应开发需求。比如针对USB IP和USB+ IP,提供的库如图1所示。

图1 USB(+) IP对应的USB库
继续阅读“UEFI开发探索85- YIE002USB开发板(08 制作HID设备)”

750 total views, no views today

UEFI开发探索84- YIE002USB开发板(07 制作HID设备)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

在之前的博客中,曾经谈到制作USB HID需要掌握的背景知识。包括USB软件架构、USB描述符和USB命令。前两个已经讨论过了,本篇介绍USB命令。

1 USB命令(USB Device Request)

USB规范定义了设备请求(USB Device Request),以更好地完成USB主机对总线上所有USB设备的统一控制。此设备请求由USB主机发往USB设备,为方便理解USB主机和设备间的主从关系,后续行文中一律称为“USB命令”。

USB命令包括USB标准命令、类命令和厂商命令。这些命令的格式都是相同的,如表1所示。

表1 USB命令的结构

偏移字段 长度数值描述
0  bmRequesType1位图D7:数据的传输方向
  0=主机->设备
  1=设备->主机
D6…5:命令的类型
 0=标准命令 1=类命令
 2=厂商命令 3=保留
D4…0:接收对象
 0=设备 1=接口 2=端点
 3=其他  4…31=保留
1  bRequest1命令的序号
2  wValue2根据不同的命令,含义也不同
4  wIndex2索引或偏移根据不同的命令,含义不同,主要用于传送索引或者偏移
6  wLength2如果有数据阶段,此字段为数据的字节数

标准命令是每种USB设备都要支持的,类命令则与USB设备所述类有关,比如USB HID设备有HID类特有的命令,如Get_Report、SetReport等。

继续阅读“UEFI开发探索84- YIE002USB开发板(07 制作HID设备)”

799 total views, 2 views today

UEFI开发探索83- YIE002USB开发板(06 制作HID设备)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

我们所要开发用来通信的USB设备,是HID类设备。HID(Human Interface Devices)为人机接口设备,是USB规范中最早提出并支持的一种设备类。我们日常使用的键盘、鼠标等,都属于HID设备,这是一种使用非常广泛的USB设备。

USB规范中,HID类设备的规范为Device Definiton for Human Interface Devices,每个HID设备都必须符合该规范中对描述符、传输类型等的定义。另外,USB-IF还提供了HID的用例规范,名为HID Usage Tables,定义了HID设备和USB主机之间通信的HID数据。所有的 HID 传输都是使用默认控制管道或是一个中断管道, HID 设备必须有一个中断输入端点来传送数据到主机,中断输出端点则不是必需的。

HID设备的标准描述符同样遵循上一篇所介绍的内容,也即拥有各种标准描述符。对于HID设备,其设备描述符的类代码、子类代码和协议代码都需要设置为0;接口描述符的类代码设为0x03,子类代码为0或者0x01,协议码为0、0x01或0x02。

当然,作为类设备,HID也有自己的描述符,也即人机接口类描述符,本篇介绍这些内容。

HID设备支持3种类描述符:HID描述符、报告描述符和物理描述符。一个USB设备只能包含一个HID描述符,可以支持多个报告描述符,而物理描述符是可选的。在本章的示例中,只用到了HID描述符和报告描述符,没有使用物理描述符,一般的HID设备也不使用该描述符,就不再进行介绍了。

继续阅读“UEFI开发探索83- YIE002USB开发板(06 制作HID设备)”

921 total views, no views today