用户工具

站点工具


icore3_arm_hal_19

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

后一修订版
前一修订版
icore3_arm_hal_19 [2020/04/17 11:58]
fmj 创建
icore3_arm_hal_19 [2022/03/18 15:08] (当前版本)
sean
行 2: 行 2:
 |技术支持电话|**0379-69926675-801** ​ ||| |技术支持电话|**0379-69926675-801** ​ |||
 |技术支持邮件|Gingko@vip.163.com ​ ||| |技术支持邮件|Gingko@vip.163.com ​ |||
-|技术论坛|http://​www.eeschool.org ​ ||| 
 ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^ ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^
 |  V1.0  |  2020-04-17 ​ |  gingko ​ |  初次建立 ​ | |  V1.0  |  2020-04-17 ​ |  gingko ​ |  初次建立 ​ |
行 63: 行 62:
 \\ \\
  
-===== 实验十USB_CDC实验——高速数据传输 =====+===== 实验十USB_HID实验——双向数据传输 =====
  
 ==== 一、 实验目的与意义 ==== ==== 一、 实验目的与意义 ====
  
-  - 了解STM32 USB 结构。 +  - 了解STM32 USB SLAVE结构。 
-  - 了解STM32 USB 特征。 +  - 了解STM32 USB SLAVE特征。 
-  - 掌握USB的使用方法。+  - 掌握USB ​SLAVE HID的使用方法。 
 +  - 掌握STM32 HAL库中USB_HID属性的配置方法
   - 掌握KEIL MDK 集成开发环境使用方法。   - 掌握KEIL MDK 集成开发环境使用方法。
 ==== 二、 实验设备及平台 ==== ==== 二、 实验设备及平台 ====
行 80: 行 80:
   - 装有WIN XP(及更高版本)系统的计算机。   - 装有WIN XP(及更高版本)系统的计算机。
 ==== 三、 实验原理 ==== ==== 三、 实验原理 ====
-=== 1、USB简介 === +=== 1、USB_HID设备简介 === 
-  * USB英文UniversalSerialBUS(通用串行总线)的缩写,中文简为“通串线,一个外部总线用于规范电脑与外部设备的连接和通讯。应用在PC领域的接口技术。USB接口支持设备的即插即用和热插拔功能。USB是在1994年底由英特尔、康柏、IBM、Microsoft等多家公司联合提出的。 +  * USB HIDHuman Interface Device的缩写,可以了解HID设备直接与人交互的设备,例如键盘、鼠与游戏杆等。不过HID设备并不一定要有人机接口只要符合HID类别规范设备HID设备。 
-  * USB发展到现已经有USB1.0/​1.1/​2.0/​3.0等多个版本。目前用最多就是USB1.1和USB2.0USB3.0目前已经开始普及STM32F407自带USB符合USB2.0规范。 +  * 交换的数据存储称为报表(report)结构内,设备固件必须支持HID报表的格式。主机在控制与中断传输中传送与要求报表来传送与接收数据报表格式非常有弹性,可以处理任何类别的数据。 
-  * 标准USB共四根线组成,​VCC/GND外,另外为D+和D-这两根数据线采用的是差分电压方式进行数据传输的USB主机上D-和D+都是了15K电阻到地,所以在没有设备接入的时候,D+、D-均是低电平USB设备如果是高速设备,则会D+上接一个1.5K电阻到VCC如果是低速设备,则会在D-上接一个1.5K电阻到VCC。这样当设备接入主机的时候主机就可以判断是否有设备接入并能判断设备是高速设备还是低速设备。+  * 设备了HID接口之外,它可能同时还包含有其他的USB接口。例如影像显示设备可能使用HID接口来做亮度对比,与更新率的软件控制,而使传统影 像接口来传送要显示的数据。USB扩音器可以使用实时传输来播放语音同时使用HID口来控制音量,震荡,与低音等。HID接口通常比传统控制接口来得便宜。 
 +  * Wndows操作系统最先支持HID设备。在windows98以及后来的版本中内置有HID设备的驱动程序应用程序可以直接使用这些驱动程序来与设备通信。 
 +  * 设计一个USB接口计算机外部设备时,如果HID类型的设备可以满足需要,可以将其设计为HID类型设备,这样可以省去比较复杂的USB驱动程序的编写,直接利用Windows操作系统对标准的HID类型USB设备的支持
  
-=== 2、USB On-The-Go简介 ​=== +=== 2、HID主要能力 ​=== 
-  * OTG_HS 是一个双角色设备 ​(DRD) 控制器,同时支持机和主机功能并且完全符合 USB 2.0 规范的 On-The-Go 补充此外,该控制器也可配置为仅主机或仅从机控制器完全符合 USB 2.0 规范主机模式中,OTG_HS 支持高速(HS,480 Mbits/​s)、全速(FS12 Mbits/​s)和低(LS1.5 Mbits/s)传输,从机模式中仅支持高速(HS,480 Mbits/​s)和全速(FS、12 Mbits/s)传输。OTG_HS 还支持 HNP 和 SRPOTG 模式下需要的唯一外部设备是提供 VBUS 电荷泵+  * 交换的数据储存在称为报表(Report)的结构内,设备的固件必须支持HID报表的格式。主通过控制中断传输中的传送和请求报表来传送和接收数据。报表的格式非常灵活。 
 +  * 每一笔事务可以携带小量或中量的数据。低速设备每一笔事务最大是8B,全速设备每一笔事务最大是64B,高速设备每一笔事务最大是1024B。一个报表可以使用多笔事务。 
 +  * 设备可以在未预期的时间传送信息给主机,例如键盘按键或是鼠的移动所以主机会定时轮询设备以取得最新的数据。 
 +  * HID设备的最大传输速度有限制。主机可以保证低速的断端点每10ms内最多1笔事务每一秒最多是800B。保证全速端点每lms一笔事务每一秒最多是64000B。保证高端点每125us三笔事务每一秒最多是24.576MB。 
 +  * HID设备没有保证的传输速率。如果设备是设置在10ms的时距事务之间的时间可能等于或小于10ms。除非设备是设置全速时在每个帧传输数据或是在高速时在每个微帧传输数据这是最快的轮询速率,所以端点可以保证有正确的带宽可供使用 
 +  * HID设备除了传送数据给主机外,它也会从主机接收数据。只能够符合HID类别规范的设备都可以HID设备。 
 +  * 设备除了HID接口之外,它可能同时还包含有其他USB接口例如影像显示设备可能使用HID接口来做亮度、对比度的软件控制,而使用传统的影像接口来传送要显示的数据。USB扩音器可以使用实时传输来播放语音,同时使用HID接口来控制音量、低音等。 
 +  * HID类别设备的规范文件主要是以下两份: 
 +    * Device Class Definition for Human interface Devices 
 +    * HID Usabe Tables 
 +=== 3、实现原理 == 
 +{{ :​icore3:​icore3_arm_hal_19_1.png?​direct |}} 
 +{{ :​icore3:​icore3_arm_hal_19_2.png?​direct |}}
  
-  * OTG主要特性可分为三类:通特性、主机模式特性和从机模式特性。 +  * iCore3中使用的STM32F407IGTx芯片带有USB高速物理层,通过USB3300设芯片实现USB_HID设备物层搭建。 
- +  USB HID设备无需驱动程序,Windows系统自HID类的动程序。通过移植ST官方提供的代码来实现iCore3USB_HID双向数据传输点击测试软件灯控按钮iCore3上LED灯亮灭,实现上位向下位传输数据并解析相命令iCore3ARM-KEY按钮测试软件显ARM-KEY状态,实现了下位机向位机的数据传输
-  * 1、通用特性 +
-    * OTG_HS接口通用特性如下: +
-      * 经USB-IF认证,符合通用串行总线规范第2.0版 +
-      * OTGHS支持以下三个PHY接口: +
-        * 片上全速PHY +
-        * 连接外部全速PHY的I2C接口 +
-        * 连接外部高速PHY的ULPI接口 +
-      * 支持主机协商协议 (HNP) 和会话请求协议 (SRP) +
-        * 在 OTG 应用中允许主机关闭 VBUS 以节省功耗而不需要外部组件 +
-        * 允许使用内部比较器来监视 VBUS 电平 +
-        * 支持主机和从机之间的动态角色切换 +
-        * 可通过软件配置为以下角色: +
-          * 支持 SRP 的 USB HS/FS 从机(B 器件) +
-          * 支持 SRP 的 USB HS/FS/LS 主机(A 器件) +
-        * 支持 HS/FS SOF 以及低速 (LS)“Keep-alive”令牌并具有如下功能: +
-          * SOF 脉冲引脚输出功能 +
-          * SOF 脉冲与定时器 2 (TIM2) 的内部连 +
-          * 可配置的帧周期 +
-          * 可配置的帧结束中断 +
-        * 模块内嵌 DMA,并可软件配置 AHB 的突发传输类型 +
-        * 具省电功能,例如在 USB 挂起期间停止系统时钟,关闭数字模块内部时钟域、PHY 和DFIFO 电源管理 +
-        具有包含高级 FIFO 管理的专用 4K 字节数据 RAM: +
-          * 可以将存储区配置为不同 FIFO,以便灵活高效地使用 RAM +
-          * 每个FIFO 可包含多个数据包 +
-          * 动态地进行存储器分配 +
-          * FIFO 大小可配置为 2 的幂以外的值,以便连续使用存储区 +
-        * 一帧之内可以无需要应用程序干预以达到最大 USB 宽  +
- +
-  * 2、主机模式特性 +
-    * 主机模式下的 OTG_HS 接口特征如下: +
-      * 需要外部电荷泵来生成 VBUS +
-      * 具有多达 12 个主机通道(管道),每个通道可动态地进行重新配置,可支持任何 +
-    * USB 传输 +
-      * 内置硬件调度器: +
-        * 在周期性硬件队列中存储多达 8 个中断加同步传输请求 +
-        * 在非周期性硬件队列中存储多达 8 个控制加批量传输请求 +
-        * 管理一个共享 RX FIFO、一个周期性 TX FIFO 和一个非周期性 TX FIFO,以有效使用 +
-    * USB 数据 RAM +
-        * 在主机模式下具备对 SOF 帧周期进行态调校的功能 +
- +
-  * 3、从机模式特性 +
-    * OTG_HS 接口在从机模式下具有以下特性: +
-      * 具有 1 个双向控制端点 0 +
-      * 具有 5 个 IN 端点 (EP),可配置为支持批量、中断或同步传输 +
-      * 具有 5 个 OUT 端点,可配置为支持批量、中断或同步传输 +
-      * 管理一个共享 Rx FIFO 和一个 Tx-OUT FIFO,可高效使用 USB 数据 RAM +
-      * 管理多达 6 个专用 Tx-IN FIFO(每个 IN 配置的 EP 使用一个)以降低应用程序负载 +
-      * 具备软断开功能 +
-=== 3、高速OTG框图 === +
-  * USB OTG HS 模块嵌入了一个 ULPI 接口以连接外部 HS PHY +
-{{ :​icore3:​icore3_arm_hal_18_1.png?​direct |}} +
-=== 4、USB CLASS === +
-  * USB协议设计的时候,把鼠标,键盘,大容量存储,图像等,这些之前是通过其他接口所实现的,各种功能,都囊括进。并且在协议中有对应的规范定义,支持这些功能。因此,定了各种USBClas,即分类,根据功能而分出各种类别。不同的Class分类用于实现对应的功能,适用于相应的设备。 +
- +
-  * 常见的USB类设备: +
-    - 音频类 +
-    - 通信设备类 +
-    - 人接口设备类 +
-    - 物理设备 +
-    - 成像设备类 +
-    - 打印设备类 +
-    - 大容量存储类 +
-    - 数据接口类 +
-    - 智能卡设备类 +
-    - 内容安全设备类 +
-    - 视频设备类 +
-    - 个人医疗保健设备类 +
-    - USB音频/​视频(AV)设备类 +
-    - Billboard Device Class Specification +
-    - USB Type-C桥接器件类 +
-    - 无线控制类 +
-    - 其他设备 +
-    - 特定用 +
-    - 厂商自定义 +
-{{ :​icore3:​icore3_arm_hal_18_2.png?​direct |}} +
-=== 5、USB_CDC类简介 === +
-  * USB2.0标准下定义了很多子类,有音频类,CDC类,HID,打印,大容量存储类,HUB,智能卡等等,这些在usb.org官网上有具体的定义,这里主要介绍通信类CDCCDC(Communication Device Class)类是USB2.0标准下的一个子类定义了通信相关设备的抽象集合。它与USB2.0标准以及其下的子类的相互关系如下图所: +
-  * USB CDC类通信部分主要包含三部分:枚举过程、虚拟串口操作和数据通信。其中虚拟串口操作部分并不一定强制需要,因为若跳过这些虚拟串口的操作,实USB依然是可以通信的,这也就是为什么下图中,在操作虚拟串口之前会有两条数据通信的数据。之所以会有虚拟串口操作,主要是我们通常使用PC作为Host端,在PC端使用一个串口工具来与其进行通信,PC端的对应驱动将其虚拟成一个普通串口,这样一来,可以方便PC端软件通过操作串口的方式来与其进行通信,但实际上,Host端与Device端物理上是通过USB总线来进行通信的,与串口没有关系,这一虚拟化过程,起决定性作用的是对应驱动,包含如何将每一条具体的虚拟串口操作对应到实际上的USB操作。需要注意的是,Host端与Device端的USB通信速率并不受所谓的串口波特率影响,它就是标准的USB2.0全速(12Mbps)速度,实际速率取决于总线的实际使用率、驱动访问USB外设有效速率(两边)以及外部环境对通信本身造成的干扰率等因素组成。 +
-  * USB_CDC类详细内容可参考《USB_CDC类入门培训》。 +
-{{ :​icore3:​icore3_arm_hal_18_3.png?​direct&​700 |}} +
-{{ :​icore3:​icore3_arm_hal_18_4.png?​direct&​700 |}} +
- +
- +
-=== 6、USB_CDC类简介 === +
-  * **实现原理** +
-  * iCore3中使用的STM32F407IGTx芯片带有USB高速物理层,通过外部高速PHY的ULPI接口外接USB3300设备芯片实现USB_CDC设备物理层搭建。连接示意图如下: +
-{{ :​icore3:​icore3_arm_hal_18_5.png?​direct&​550 |}}+
  
 ==== 四、 实验程序 ==== ==== 四、 实验程序 ====
行 184: 行 111:
 int main(void)  ​ int main(void)  ​
 {  ​ {  ​
-    ​int i;   +  /* USER CODE BEGIN 1 */   
-    ​static ​unsigned char data_number = 0;   +  ​int i;   
-    ​HAL_Init();   +  unsigned char buffer[64];   
-    ​USBD_Init(&​USB_OTG_dev,​USB_OTG_HS_CORE_ID,&​USR_desc,&​USBD_CDC _cb,&​USR_cb);   +  ​unsigned char send_buffer[64];   
-    SystemClock_Config(); ​  +  ​static int counter; ​  
-    MX_GPIO_Init(); ​  +  RTC_DateTypeDef sDate; ​  
-    while(State==0);   +  RTC_TimeTypeDef sTime; ​  
-    ​LED_RED_ON;   +  /* USER CODE END 1 */   
-    while (1)   +  HAL_Init();   
-    {   +  SystemClock_Config(); ​  
-        if(USB_ReceivedCount > 0){   +  /* Initialize all configured peripherals */   
-            ​LED_RED_ON; ​   +  ​MX_GPIO_Init(); ​  
-            USB_ReceivedCount ​= 0;   +  ​MX_RTC_Init();   
-            ​data_number ​USB_Rx_Buffer[0]; ​  +  ​MX_USB_DEVICE_Init();   
-            do{   +  /* USER CODE BEGIN WHILE */   
-                ​USB_StatusDataSended = 0;   +  ​while (1)   
-                ​DCD_EP_Tx(&USB_OTG_dev,CDC_IN_EP,gImage_flower,sizeof(gImage_flower));   +    
-                ​while(USB_StatusDataSended ​== 0){   +    /* USER CODE END WHILE */   
-                    for(i = 0;i < 10000;i++)  +        if(systick.second_flag == 1){   
-                ​}   +            ​systick.second_flag ​= 0;   
-                data_number--;   +            ​if(hUsbDeviceHS.dev_state ​== USBD_STATE_CONFIGURED){ ​  
-            }while(data_number > 0);   +                ​if(counter ++ % 2){   
-            ​LED_RED_OFF;   +                    ​HAL_RTC_GetTime(&​hrtc,​ &sTime, RTC_FORMAT_BIN); ​  
-         ​  +                    HAL_RTC_GetDate(&​hrtc,​ &sDate, RTC_FORMAT_BIN); ​  
-    }+                    memset(send_buffer,​0,64) 
 +                    sprintf((char *)send_buffer,"​time:​%02d:​%02d:​%02d ​ %02d-%02d-%02d",​sTime.Hours,​sTime.Minutes,​sTime.Seconds,​sDate.Year,​sDate.Month,​sDate.Date);​ 
 +                    ​USBD_HID_SendReport(&hUsbDeviceHS,send_buffer,64);   
 +                }else{ ​  
 +                    memset(send_buffer,0,​64); ​  
 +                    if(ARM_KEY_STATE == KEY_DOWN  
 +                        sprintf((char *)send_buffer,"​key:​KEY PRESS");  ​ 
 +                    else   
 +                        sprintf((char *)send_buffer,"​key:"​); ​  
 +                    USBD_HID_SendReport(&​hUsbDeviceHS,​send_buffer,​64); ​ 
 +                ​}          
 +            }          
 +        }   
 +        //​接收命令处理 
 +        if(usb_receive_flag ​== 1){   
 +            ​usb_receive_flag = 0;   
 +            memcpy(buffer,​usb_receive_buffer,​usb_receive_counter); ​  
 +            memset(usb_receive_buffer,​0,​usb_receive_counter); ​  
 +            ​for(i = 0;i < 64;i++)  
 +                ​buffer[i] = tolower(buffer[i]);   
 +            }   
 +            ​command_process(buffer);   
 +                
 +   
 }  ​ }  ​
 +
 </​code>​ </​code>​
-=== 2. 中断函数 ===+  * 在主函数的while循环中通过定时器,定时向主机发送时间数据。再通过USB处理函数对主机发送过来的数据进行接收处理,并送入处理函数进行处理,实现相应的功能。 
 +=== 2. 时钟函数 ===
 <code c> <code c>
-void OTG_HS_IRQHandler(void)  ​+void HAL_SYSTICK_Callback(void)  ​
 {  ​ {  ​
-  USBD_OTG_ISR_Handler (&​USB_OTG_dev);   +    //​中断时间1ms,  
-}  ​ +static int counter = 0;   
-void OTG_HS_EP1_IN_IRQHandler(void  + 
-{   +    if((counter ++ % 250) == 0){   
-  ​USBD_OTG_EP1IN_ISR_Handler (&​USB_OTG_dev);   +        ​systick.second_flag = 1      
-}   +    }   
-void OTG_HS_EP1_OUT_IRQHandler(void)  ​+} 
 + 
 +</​code>​ 
 +  * 通过时钟函数计时,定时向主机发送数据 
 +=== 3. usb驱动文件修改 ===  
 +  * 因为hal库中的驱动没有对hid设备接收函数的处理,需要修改usbd_hid.c文件。主要是添加USBD_HID_DataOut函数,增加对从主机发送的数据接收功能。 
 +<code c> 
 +static uint8_t ​ USBD_HID_DataOut ​(USBD_HandleTypeDef *pdev, ​   
 +                              uint8_t epnum)  ​
 {  ​ {  ​
-  USBD_OTG_EP1OUT_ISR_Handler ​(&​USB_OTG_dev);  ​+    if(epnum == HID_EPOUT_ADDR){   
 +        usb_receive_counter = USBD_GetRxCount(pdev,​epnum); ​  
 +        if(pdev->​dev_state == USBD_STATE_CONFIGURED){ ​  
 +            usb_receive_flag = 1;   
 +  USBD_LL_PrepareReceive(pdev,​HID_EPOUT_ADDR,​usb_receive_buffer,​HID_EPOUT_SIZE); ​  
 +        }   
 +    }   
 +  return USBD_OK;  ​
  
  
 </​code>​ </​code>​
-=== 3. USB驱动移植 ===  +  * 修改USBD_HID_Init函数,增加USBD_LL_OpenEP函数语句与USBD_LL_PrepareReceive函数语句,保证相应功能的初始化。 
-  * 在CUBEMX中 无法配置USBDevice为CDC高速传输模式,需要将USB库的驱动文件移植到程序中去。建立好一个新工程后,打开此实验例程文件夹,找到USB文件夹,将文件夹拷贝到建立好工程中去。 +<code c> 
-{{  :​icore3:​icore3_arm_hal_18_6.png?​direct&​800 ​ |}} +/* Open Ep Out */   
 +    USBD_LL_OpenEP(pdev,​ HID_EPOUT_ADDR,​ USBD_EP_TYPE_INTR,​ HID_EPOUT_SIZE); ​   
 +    /* Prepare Out endpoint to receive next packet */   
 +    USBD_LL_PrepareReceive(pdev,​ HID_EPOUT_ADDR,​ usb_receive_buffer,​ HID_EPOUT_SIZE);​  
 +</​code>​ 
 +  * 在usbd_hid.h添加对EPOUT参数地址与大小的定义 
 +<code c> 
 +#define HID_EPOUT_ADDR ​                             0x01   
 +#define HID_EPOUT_SIZE ​                             0x40  
 +</​code>​ 
 +  * 利用上位机hid.exe与iCore3通讯,HID设备的描述符需要进行修改,以便可以与上位机软件进行通讯。主要是对usbd_desc.c 设备描述符与usbd_hid.c配置描述符进行修改。这些描述符决定了HID设备的类型与定义上位机需要根据这些描述符发出相应的指令控制。直接将程序中的usbd_hid.c文件替换为例程文件的usbd_hid.c。在usbd_desc.c中需要修改USBD_HS_DeviceDesc中的相应描述配置,将宏定义中一些参数进行修改,即可实现hid描述符修改。 
 +<code c> 
 +#define USBD_VID ​    ​0x483 ​  
 +#define USBD_LANGID_STRING ​    ​1033 ​  
 +#define USBD_MANUFACTURER_STRING ​    "​Gingko" ​  
 +#define USBD_PID_HS ​    ​0x5720 ​  
 +#define USBD_PRODUCT_STRING_HS ​    "​iCore3 in HS mode" ​  
 +#define USBD_SERIALNUMBER_STRING_HS ​    "​00000000001A" ​  
 +#define USBD_CONFIGURATION_STRING_HS ​    "​HID Config" ​  
 +#define USBD_INTERFACE_STRING_HS ​    "​HID Interface" ​  
 +#define USB_SIZ_BOS_DESC ​           0x0C  
 +</​code>​
 ==== 五、 实验步骤 ==== ==== 五、 实验步骤 ====
   - 把仿真器与iCore3的SWD调试口相连(直接相连或者通过转接器相连);   - 把仿真器与iCore3的SWD调试口相连(直接相连或者通过转接器相连);
行 237: 行 224:
   - 打开Keil MDK开发环境,并打开本实验工程;   - 打开Keil MDK开发环境,并打开本实验工程;
   - 烧写程序到iCore3;   - 烧写程序到iCore3;
 +  - 也可以进入Debug模式,单步运行或设置断点验证程序逻辑;
   - 打开usb_hid.exe进行验证。   - 打开usb_hid.exe进行验证。
  
 ==== 六、 实验现象 ==== ==== 六、 实验现象 ====
-  * 绿色LED亮,结果如下: +  * 点击测试软件的LED控制按钮,iCore3上的LED灯的颜色状态将发生变化,点击校准时间,将用电脑系统的时间校准iCore3的内部RTC按下iCore3上的ARM-KEY,​按键状态栏将显示按键状态(如下图所示)。 
-{{ :​icore3:​icore3_arm_hal_18_7.png?​direct |}} +{{ :icore3:icore3_arm_hal_19_3.png?direct |}}
-**附录:** +
-  * 1、打开设备管理器,并找到USB_CDC设备 +
-{{ :​icore3:​icore3_arm_hal_18_8.png?​direct |}} +
-  * 2、选中此设备并右选择更新驱动程序,选中浏览计算机以查找驱动程序软件 +
-{{ :​icore3:​icore3_arm_hal_18_9.png?​direct |}} +
-  * 3、找到例程文件夹下driver文件夹并选中此文件夹,点击下一步后驱动程序会自动安装。 +
-{{ :​icore3:​icore3_arm_hal_18_10.png?​direct |}} +
-  * 4、安装成功后设备管理器显示相对应设备。 +
-{{ :icore3:icore3_arm_hal_18_11.png?direct |}} +
  
icore3_arm_hal_19.1587095920.txt.gz · 最后更改: 2020/04/17 11:58 由 fmj