AWorks 框架下 USB 设备模式的编程与应用
时间:2019-05-10 15:33来源:ZLG致远电子
摘要:USB是英文UniversalSerialBus(通用串行总线的缩写),是一种快速、灵活的总线接口。USB对所有的USB外设提供了单一的易于使用的标准的连接类型,简化了USB外设的设计。
USB是英文Universal Serial Bus(通用串行总线的缩写),是一种快速、灵活的总线接口。USB对所有的USB外设提供了单一的易于使用的标准的连接类型,简化了USB外设的设计。USB接口支持热插拔,计算机系统可以动态地检测外设的插拔,并且动态地加载驱动程序。另外,USB还具有很灵活的扩展性,一个USB端口接上一个USB HUB(集线器)就可以扩展多个USB端口。USB广泛的应用于PC机中的人机接口、音频、存储等功能,随着嵌入式系统在各个领域上广泛应用,USB也在嵌入式系统中被广泛的使用。
一、USB简介
USB是在1994年底由英特尔、康柏、IBM、Microsoft等多家公司联合提出。ISB1.1是较为普遍的USB规范,其高速方式的传输速率是12Mbps,低速模式的传输速率为1.5Mbps(b是bit的意思,12Mbps=1.5MB/s),USB2.0规范是由USB1.1规范演变而来,它的传输速率达到了480Mbps,足以满足大多数外设的速率要求。USB2.0中的EHCI(增强主机控制器接口)定义了一个与USB1.1相兼容的结构。它可以用USB2.0的驱动程序驱动USB1.1的设备,也就是说所有支持USB1.1的设备都可以直接在USB2.0的接口上使用而不必担心兼容性问题。USB采用四线电缆,其中两根是用来传送数据的串行通道,另两根为下游设备提供电源,对于任何已经成功连接且相互识别的外设,将以对方设备均能够支持的最高速率传输数据。USB总线会根据外设情况在所兼容的传输模式中自动地由高速向低速动态转换且匹配锁定在合适的速率。USB系统采用级联星型拓扑,该拓扑由三个基本部分组成:主机,集线器和功能设备。
主机包含有主控制器和根集线器,控制着USB总线上的数据和控制信息的流动,每个USB系统只能有一个根集线器,它连接在主控制器上。
集线器是USB结构中的特定成分,它可以对原有的USB端口在数量上进行扩展以获得更多的USB端口(集线器只能扩展出更多的USB端口,而不能扩展出更多的带宽),设备通过端口连接到USB总线上,同时检测连接在总线上的设备,并为这些设备提供电源管理,负责总线的故障检测和恢复。集线可为总线提供能源,亦可为自身提供能源。
功能设备通过端口与总线连接。
本文章以M1052平台为例,主要讲解在AWorks平台中如何创建一个自定义的USB设备。
二、AWorks工程配置
在AWorks工程中,用户可以通过aw_prj_params.h配置文件进行设备添加与删除,aw_prj_params.h在工程目录user_config中。
在aw_prj_params.h文件中,有效定义设备的使能宏,才表示一个有效的硬件设备,在本文章中我们需要使能USB Device,所以在aw_prj_params.h中添加AW_DEV_IMX1050_USBD设备宏。
在aw_prj_params.h中添加AW_DEV_IMX1050_USBD设备宏之后,在aw_prj_param_auto_cfg.h文件中会自动添加AW_COM_USBD的定义,AW_COM_USBD代表的是USB Device协议栈组件。此处要注意AW_DEV_IMX1050_USBD与AW_DEV_IMX1050_USBH1有冲突(一个USB控制器不能同时出现主机设备模式),两个只能使能一个。AW_DRV_IMX1050_USBD表示加载USB Device的驱动:
三、AWorks中USB Device的硬件配置
在AWorks中所有设备集中由AWbus_lite进行管理,在使用一个硬件设备前,必须将其添加到系统硬件设备列表(在awbus_lite_hwconf_usrcfg.c中定义),各个硬件设备的类型为struct awbl_devhcf。USB设备相关硬件配置可以查阅工程目录下的\user_config\awbl_hwconf_usrcfg\awbl_hwconf_imx1050_usbd.h文件,USB设备模式的设备信息详见程序清单2.1。
其中"/dev/usbd" 是USB Device外设的设备名字,在实际的应用中需要通过该名字来使用USB Device
AWBL_USBD_CFG_SELF_POWERED 表示本设备为自行供电设备。__imx1050_usbd_plfm_init函数是用来初始化与USB Device平台相关的信息,在这里是初始化USB Device时钟,详见程序清单2.2。
四、与USB Device操作函数相关重要结构体介绍
USB设备类回调函数列表,这个结构体用于提供USB枚举以及USB通信过程中的事件回调接口,方便用户接入应用代码:
USB设备信息结构体,此结构体用于配置USB设备的基础信息(具体信息详见结构体定义),当设备连接到PC端后,可以在PC端查看到这些信息:
USB设备接口信息结构体,这个结构体是用来描述当前USB设备接口的信息:
五、USB Device操作接口
Aworks提供了一系列的USB Device操作相关的标准接口,包括初始化一个USB设备、USB功能初始化、启动USB设备和USB数据传输等,用户在使用Aworks开发USB Device的应用程序时,使用上述标准接口就能方便快捷的开发出源代码。详见表4.1
• struct aw_usbd 为USB Device对象
• struct aw_usbd_fun 为功能接口对象
• struct aw_usbd_pipe 为端点管道对象
六、应用案例代码详解
这里基于M1052平台,展示如何创建一个自定义的USB设备。本例子会初始化一个USB设备,为USB设备创建一个OUT管道和一个IN管道用于接收和发送数据(IN和OUT的概念是相对于USB主机而言),并在这个USB设备添加接口功能。通过USB设备与PC机的连接,实现与PC的通讯,当PC机上位机软件发送数据时,USB设备通过OUT管道接收数据,并通过IN管道把收到的数据发送回PC端上位机。这里只对部分关键的代码进行讲解,完整的代码请自行下载查看,本例程所在目录位于\examples\peripheral\common\usb\ demo_usbd_vendor.c
定义数据接收缓冲区的大小和等待超时时间:
11 #define __BUF_SIZE 512 /** 数据缓冲区大小*/
12 #define __WAIT_TIMEOUT 5000 /** 等待超时时间*/
定义USB Device的信息,当USB Device与PC端连接时,PC端会对其进行枚举从而获取USB Device的设备信息,,这些信息都可以在PC端进行查看:
14 /** \brief 定义全局usb设备实例和usb设备信息结构体 */
15 static struct aw_usbd __g_usbd_obj;
16 const static struct aw_usbd_info __g_usbd_info = {
17 0, /**< \brief 类代码 */
18 0, /**< \brief 子类代码 */
19 0, /**< \brief 协议代码 */
20 64, /**< \brief 端点0包最大尺寸 */
21 0x0100, /**< \brief 设备版本号 */
22 0x3068, /**< \brief 厂商ID */
23 0x0003, /**< \brief 产品ID */
24 "ZLG", /**< \brief 制造商字符串描述 */
25 "AWorks", /**< \brief 产品字符串描述 */
26 "20160824" /**< \brief 序列号字符串描述 */
27 };
USB Device接口信息结构体:
48 /** \brief 接口信息 */
49 static const struct aw_usbd_fun_info __g_info = {
50 AW_USB_CLASS_VENDOR_SPEC, /**< \brief 类代码-厂商自定义设备 */
51 0x00, /**< \brief 子类代码 */
52 0x00, /**< \brief 协议代码 */
53 __custom_alt_set, /**< \brief 替代设置回调 */
54 NULL /**< \brief 控制传输回调 */
55 };
USB Device例程入口函数,这里主要是初始化USB Device对象,并为这个USB Device对象添加自定义功能,最后通过调用aw_usbd_start函数启动配置好的USB Device。
174 /**
175 * \brief 自定义USB设备 demo
176 * \return 无
177 */
178 void demo_usbd_vendor_entry (void)
179 {
180 int ret;
181
182 /*
183 * USB device 初始化
184 * "/dev/usbd" 在awbl_hwconf_xxxxxx_usbd.h 中定义
185 */
186 /* 初始化一个USB设备对象*/
187 ret = aw_usbd_init(&__g_usbd_obj,
188 &__g_usbd_info,
189 NULL,
190 "/dev/usbd");
191 if (ret != AW_OK) {
192 AW_ERRF(("__g_usbd_obj init failed: %d\n", ret));
193 }
194 /* 对USB设备添加自定义功能*/
195 __demo_usbd_vendor();
196 /* 启动USB设备*/
197 ret = aw_usbd_start(&__g_usbd_obj);
198 if (ret != AW_OK) {
199 AW_ERRF(("__g_usbd_obj start failed: %d\n", ret));
200 }
201
202 return ;
203 }
创建USB Device自定义功能,在本例程中,调用aw_usbd_pipe_create函数为USB Devie的自定义功能创建两个管道,一个OUT管道和一个IN管道用于接收和发送数据,然后把这个功能添加进上文中初始化好的USB Device对象,最后创建一个任务用于接收数据并把数据发送回去。
126 /**
127 * \brief 自定义类例程入口
128 */
129 aw_local int __demo_usbd_vendor (void)
130 {
131 int ret;
132
133 /* initialize function */
134 /* 初始化一个USB设备功能*/
135 ret = aw_usbd_fun_init(&__g_ufun,
136 "AWORKS-USB",
137 &__g_info);
138 if (ret != AW_OK) {
139 return ret;
140 }
141
142 /* 创建一个IN管道 */
143 ret = aw_usbd_pipe_create(&__g_ufun, &__g_in, &__g_in_info);
144 if (ret != AW_OK) {
145 return ret;
146 }
147
148 /* 创建一个OUT管道 */
149 ret = aw_usbd_pipe_create(&__g_ufun, &__g_out, &__g_out_info);
150 if (ret != AW_OK) {
151 return ret;
152 }
153
154 /* 把功能添加到创建的USB设备实例中*/
155 ret = aw_usbd_fun_add(&__g_usbd_obj, 0, &__g_ufun);
156 if (ret != AW_OK) {
157 return ret;
158 }
159
160 AW_SEMB_INIT(__g_semb, 0, AW_SEM_Q_PRIORITY);
161 /* 创建一个USB设备任务*/
162 AW_TASK_INIT(__g_task,
163 "CUSTOM-USB",
164 10,
165 2048,
166 __custom_task,
167 &__g_ufun);
168
169 AW_TASK_STARTUP(__g_task);
170
171 return AW_OK;
172 }
USB Device接收发送任务,当USB Device连接到PC端后,PC端检测到USB Device的设备信息和设置功能接口后,就会调用USB Device接口信息的回调函数__custom_alt_set,__custom_alt_set会发送信号量,通知USB Device接收发送任务USB Device已连接到PC端,然后进入等待数据接收状态,当收到数据后会取消阻塞状态,然后把收到的数据通过IN管道再发送出去:
74 /* 回调函数*/
75 static int __custom_alt_set (struct aw_usbd_fun *p_fun,
76 bool_t set)
77 {
78 if (set) {
79 AW_SEMB_GIVE(__g_semb);
80 } else {
81 aw_usbd_pipe_reset(p_fun->p_obj, &__g_in);
82 aw_usbd_pipe_reset(p_fun->p_obj, &__g_out);
83 }
84 return AW_OK;
85 }
87 static void __custom_task (void *arg)
88 {
89 int ret;
90 void *p_buf;
91
92 p_buf = aw_usb_mem_alloc(__BUF_SIZE);
93 if (p_buf == NULL){
94 aw_kprintf("aw_usb_mem_alloc error!");
95 return ;
96 }
97
98 AW_FOREVER {
99 /* 等待USB设备连接*/
100 while (!aw_fun_valid(&__g_ufun)) {
101 AW_INFOF(("custom usb wait for connect.\n"));
102 AW_SEMB_TAKE(__g_semb, AW_SEM_WAIT_FOREVER);
103 }
104
105 memset(p_buf,0,__BUF_SIZE);
106 /* 等待接收数据*/
107 ret = aw_usbd_trans_sync(__g_ufun.p_obj,
108 &__g_out,
109 p_buf,
110 __BUF_SIZE,
111 0,
112 AW_SEM_WAIT_FOREVER);
113 if (ret > 0) {
114 aw_kprintf("[recv]:%s\n", (char *)p_buf);
115 }
116
117 /* 把收到的数据发送回去 */
118 ret = aw_usbd_trans_sync(__g_ufun.p_obj,
119 &__g_in,
120 p_buf,
121 ret,
122 0,
123 __WAIT_TIMEOUT);
124 }
125 }
七、应用案例演示
把完整的例程拷贝到工程的user_code目录,并把USB Device入口函数demo_usbd_vendor_entry添加到main.c文件中:
1 #include "aworks.h"
2 #include "aw_vdebug.h"
3 #include "aw_led.h"
4 #include "aw_delay.h"
5
6 #define LED 0
7 extern void demo_usbd_vendor_entry (void);
8
9 int aw_main()
10 {
11 aw_kprintf("\r\nApplication Start. \r\n");
12
13 demo_usbd_vendor_entry();
14
15 while (1) {
16 aw_led_toggle(LED);
17 aw_mdelay(500);
18 }
19
20 return 0;
21 }
编译程序并把程序烧写进M1052开发板后,通过USB线连接开发板上的USB HOST1 和PC机,这时PC即会检测到有USB设备插入,在PC机上安装对应的驱动后,PC机识别到我们的自定义USB设备。
打开PC端串口打印:
PC端上检测到USB Device的插入,此时因为PC端没有相应的驱动,所以检测到是未知设备:
在PC机上安装相应的驱动后,PC机识别到我们的自定义USB设备:
打开专用的USB通讯软件,选择要操作的端点,因为在本例程中创建了两个管道,一个IN管道一个OUT管道,所以在软件中会看到本USB设备有两个端点,选择后会出现两个窗口,一个是接收一个是发送。
在发送窗口输入想要发送的数据,点击发送,接收窗口就会收到响应的数据。
一、USB简介
USB是在1994年底由英特尔、康柏、IBM、Microsoft等多家公司联合提出。ISB1.1是较为普遍的USB规范,其高速方式的传输速率是12Mbps,低速模式的传输速率为1.5Mbps(b是bit的意思,12Mbps=1.5MB/s),USB2.0规范是由USB1.1规范演变而来,它的传输速率达到了480Mbps,足以满足大多数外设的速率要求。USB2.0中的EHCI(增强主机控制器接口)定义了一个与USB1.1相兼容的结构。它可以用USB2.0的驱动程序驱动USB1.1的设备,也就是说所有支持USB1.1的设备都可以直接在USB2.0的接口上使用而不必担心兼容性问题。USB采用四线电缆,其中两根是用来传送数据的串行通道,另两根为下游设备提供电源,对于任何已经成功连接且相互识别的外设,将以对方设备均能够支持的最高速率传输数据。USB总线会根据外设情况在所兼容的传输模式中自动地由高速向低速动态转换且匹配锁定在合适的速率。USB系统采用级联星型拓扑,该拓扑由三个基本部分组成:主机,集线器和功能设备。
主机包含有主控制器和根集线器,控制着USB总线上的数据和控制信息的流动,每个USB系统只能有一个根集线器,它连接在主控制器上。
集线器是USB结构中的特定成分,它可以对原有的USB端口在数量上进行扩展以获得更多的USB端口(集线器只能扩展出更多的USB端口,而不能扩展出更多的带宽),设备通过端口连接到USB总线上,同时检测连接在总线上的设备,并为这些设备提供电源管理,负责总线的故障检测和恢复。集线可为总线提供能源,亦可为自身提供能源。
功能设备通过端口与总线连接。
本文章以M1052平台为例,主要讲解在AWorks平台中如何创建一个自定义的USB设备。
二、AWorks工程配置
在AWorks工程中,用户可以通过aw_prj_params.h配置文件进行设备添加与删除,aw_prj_params.h在工程目录user_config中。
在aw_prj_params.h文件中,有效定义设备的使能宏,才表示一个有效的硬件设备,在本文章中我们需要使能USB Device,所以在aw_prj_params.h中添加AW_DEV_IMX1050_USBD设备宏。
#define AW_DEV_IMX1050_USBD /**< \brief USB Device */ |
在aw_prj_params.h中添加AW_DEV_IMX1050_USBD设备宏之后,在aw_prj_param_auto_cfg.h文件中会自动添加AW_COM_USBD的定义,AW_COM_USBD代表的是USB Device协议栈组件。此处要注意AW_DEV_IMX1050_USBD与AW_DEV_IMX1050_USBH1有冲突(一个USB控制器不能同时出现主机设备模式),两个只能使能一个。AW_DRV_IMX1050_USBD表示加载USB Device的驱动:
/** * \name 内部USB Device控制器 * @{ */ #ifdef AW_DEV_IMX1050_USBD #ifndef AW_COM_USBD #define AW_COM_USBD #endif #define AW_DRV_IMX1050_USBD #endif |
三、AWorks中USB Device的硬件配置
在AWorks中所有设备集中由AWbus_lite进行管理,在使用一个硬件设备前,必须将其添加到系统硬件设备列表(在awbus_lite_hwconf_usrcfg.c中定义),各个硬件设备的类型为struct awbl_devhcf。USB设备相关硬件配置可以查阅工程目录下的\user_config\awbl_hwconf_usrcfg\awbl_hwconf_imx1050_usbd.h文件,USB设备模式的设备信息详见程序清单2.1。
程序清单2.1 USB设备模式的设备信息类型定义
1 | aw_local aw_const struct awbl_imx1050_usbd_info __g_imx1050_usbd_info = { |
2 | { |
3 | "/dev/usbd", /**< 控制器名字 */ |
4 | AWBL_USBD_CFG_SELF_POWERED /**< 控制器配置信息*/ |
5 | }, |
6 | |
7 | IMX1050_USB1_BASE_ADDR, /**< 寄存器基地址 */ |
8 | IMX1050_USBPHY1_BASE_ADDR, /**< USB PHY寄存器基地址 */ |
9 | INUM_USB_OTG1, /**< USB 中断号*/ |
10 | 5, /**< 处理usb中断业务的任务优先级 */ |
11 | 32, |
12 | __imx1050_usbd_plfm_init /**< 平台相关初始化:初始化时钟 */ |
13 | }; |
14 |
AWBL_USBD_CFG_SELF_POWERED 表示本设备为自行供电设备。__imx1050_usbd_plfm_init函数是用来初始化与USB Device平台相关的信息,在这里是初始化USB Device时钟,详见程序清单2.2。
程序清单2.2 USB设备模式的平台初始化函数
1 | aw_local void __imx1050_usbd_plfm_init (void) { |
2 | /* 配置USB Device时钟 */ |
3 | usbd_clk_init(); |
4 | }; |
USB设备类回调函数列表,这个结构体用于提供USB枚举以及USB通信过程中的事件回调接口,方便用户接入应用代码:
/** \brief USB设备类回调函数列表 */ struct aw_usbd_cb { /** \brief 控制器链接到设备 */ int (*pfn_link) (struct aw_usbd *p_obj); /** \brief 控制器和设备断开链接 */ int (*pfn_unlink) (struct aw_usbd *p_obj); /** \brief 接收到SETUP包 */ int (*pfn_ctrl_setup) (struct aw_usbd *p_obj, struct aw_usb_ctrlreq *p_setup, void *p_buf, int buf_len); /** \brief 设置或清除配置 */ int (*pfn_config_set) (struct aw_usbd *p_obj, struct aw_usbd_cfg *p_cfg, bool_t set); /** \brief 总线挂起 */ void (*pfn_suspend) (struct aw_usbd *p_obj); /** \brief 总线恢复 */ void (*pfn_resume) (struct aw_usbd *p_obj); /** \brief 总线断开连接 */ void (*pfn_disconnect) (struct aw_usbd *p_obj); }; |
/** \brief USBD信息结构定义 */ struct aw_usbd_info { uint8_t clss; /**< \brief 类代码 */ uint8_t sub_clss; /**< \brief 子类代码 */ uint8_t protocol; /**< \brief 协议代码 */ uint8_t mps0; /**< \brief 端点0包最大尺寸 */ uint16_t bcd; /**< \brief 设备版本号 */ uint16_t vid; /**< \brief 厂商ID */ uint16_t pid; /**< \brief 产品ID */ const char *manufacturer; /**< \brief 制造商字符串描述 */ const char *product; /**< \brief 产品字符串描述 */ const char *serial; /**< \brief 序列号字符串描述 */ }; |
/** \brief USBD接口信息 */ struct aw_usbd_fun_info { uint8_t clss; /**< \brief 类代码 */ uint8_t sub_clss; /**< \brief 子类代码 */ uint8_t protocol; /**< \brief 协议代码 */ /** \brief 替代设置回调 */ int (*pfn_alt_set) (struct aw_usbd_fun *p_fun, bool_t set); /** \brief setup控制传输回调 */ int (*pfn_ctrl_setup) (struct aw_usbd_fun *p_fun, struct aw_usb_ctrlreq *p_setup, void *p_buf, int buf_len); }; |
Aworks提供了一系列的USB Device操作相关的标准接口,包括初始化一个USB设备、USB功能初始化、启动USB设备和USB数据传输等,用户在使用Aworks开发USB Device的应用程序时,使用上述标准接口就能方便快捷的开发出源代码。详见表4.1
表4.1 USB设备模式操作接口函数
函数原型 | 功能简介 |
int aw_usbd_init (struct aw_usbd *p_obj, const struct aw_usbd_info *p_info, const struct aw_usbd_cb *p_cb, const char *controller); |
初始化USB设备对象 |
int aw_usbd_fun_init (struct aw_usbd_fun *p_fun, const char *name, const struct aw_usbd_fun_info *p_info); |
USB device初始化接口功能 |
int aw_usbd_fun_add (struct aw_usbd *p_obj, uint8_t value, struct aw_usbd_fun *p_fun); |
添加接口到指定配置 |
int aw_usbd_pipe_create (struct aw_usbd_fun *p_fun, struct aw_usbd_pipe *p_pipe, const struct aw_usbd_pipe_info*p_info); |
创建并添加一个管道到指定接口 |
int aw_usbd_pipe_reset (struct aw_usbd *p_obj, struct aw_usbd_pipe *p_pipe); |
USB管道复位 |
int aw_usbd_trans_sync (struct aw_usbd *p_obj, struct aw_usbd_pipe *p_pipe, void *p_buf, size_t len, int flag, int timeout); |
USB数据阻塞传输 |
int aw_usbd_trans_async (struct aw_usbd *p_obj, struct aw_usbd_trans *p_trans); |
USB数据非阻塞传输 |
int aw_usbd_start (struct aw_usbd *p_obj); | 启动USB设备 |
int aw_usbd_stop (struct aw_usbd *p_obj); | 停止USB设备 |
• struct aw_usbd_fun 为功能接口对象
• struct aw_usbd_pipe 为端点管道对象
六、应用案例代码详解
这里基于M1052平台,展示如何创建一个自定义的USB设备。本例子会初始化一个USB设备,为USB设备创建一个OUT管道和一个IN管道用于接收和发送数据(IN和OUT的概念是相对于USB主机而言),并在这个USB设备添加接口功能。通过USB设备与PC机的连接,实现与PC的通讯,当PC机上位机软件发送数据时,USB设备通过OUT管道接收数据,并通过IN管道把收到的数据发送回PC端上位机。这里只对部分关键的代码进行讲解,完整的代码请自行下载查看,本例程所在目录位于\examples\peripheral\common\usb\ demo_usbd_vendor.c
定义数据接收缓冲区的大小和等待超时时间:
11 #define __BUF_SIZE 512 /** 数据缓冲区大小*/
12 #define __WAIT_TIMEOUT 5000 /** 等待超时时间*/
定义USB Device的信息,当USB Device与PC端连接时,PC端会对其进行枚举从而获取USB Device的设备信息,,这些信息都可以在PC端进行查看:
14 /** \brief 定义全局usb设备实例和usb设备信息结构体 */
15 static struct aw_usbd __g_usbd_obj;
16 const static struct aw_usbd_info __g_usbd_info = {
17 0, /**< \brief 类代码 */
18 0, /**< \brief 子类代码 */
19 0, /**< \brief 协议代码 */
20 64, /**< \brief 端点0包最大尺寸 */
21 0x0100, /**< \brief 设备版本号 */
22 0x3068, /**< \brief 厂商ID */
23 0x0003, /**< \brief 产品ID */
24 "ZLG", /**< \brief 制造商字符串描述 */
25 "AWorks", /**< \brief 产品字符串描述 */
26 "20160824" /**< \brief 序列号字符串描述 */
27 };
USB Device接口信息结构体:
48 /** \brief 接口信息 */
49 static const struct aw_usbd_fun_info __g_info = {
50 AW_USB_CLASS_VENDOR_SPEC, /**< \brief 类代码-厂商自定义设备 */
51 0x00, /**< \brief 子类代码 */
52 0x00, /**< \brief 协议代码 */
53 __custom_alt_set, /**< \brief 替代设置回调 */
54 NULL /**< \brief 控制传输回调 */
55 };
USB Device例程入口函数,这里主要是初始化USB Device对象,并为这个USB Device对象添加自定义功能,最后通过调用aw_usbd_start函数启动配置好的USB Device。
174 /**
175 * \brief 自定义USB设备 demo
176 * \return 无
177 */
178 void demo_usbd_vendor_entry (void)
179 {
180 int ret;
181
182 /*
183 * USB device 初始化
184 * "/dev/usbd" 在awbl_hwconf_xxxxxx_usbd.h 中定义
185 */
186 /* 初始化一个USB设备对象*/
187 ret = aw_usbd_init(&__g_usbd_obj,
188 &__g_usbd_info,
189 NULL,
190 "/dev/usbd");
191 if (ret != AW_OK) {
192 AW_ERRF(("__g_usbd_obj init failed: %d\n", ret));
193 }
194 /* 对USB设备添加自定义功能*/
195 __demo_usbd_vendor();
196 /* 启动USB设备*/
197 ret = aw_usbd_start(&__g_usbd_obj);
198 if (ret != AW_OK) {
199 AW_ERRF(("__g_usbd_obj start failed: %d\n", ret));
200 }
201
202 return ;
203 }
创建USB Device自定义功能,在本例程中,调用aw_usbd_pipe_create函数为USB Devie的自定义功能创建两个管道,一个OUT管道和一个IN管道用于接收和发送数据,然后把这个功能添加进上文中初始化好的USB Device对象,最后创建一个任务用于接收数据并把数据发送回去。
126 /**
127 * \brief 自定义类例程入口
128 */
129 aw_local int __demo_usbd_vendor (void)
130 {
131 int ret;
132
133 /* initialize function */
134 /* 初始化一个USB设备功能*/
135 ret = aw_usbd_fun_init(&__g_ufun,
136 "AWORKS-USB",
137 &__g_info);
138 if (ret != AW_OK) {
139 return ret;
140 }
141
142 /* 创建一个IN管道 */
143 ret = aw_usbd_pipe_create(&__g_ufun, &__g_in, &__g_in_info);
144 if (ret != AW_OK) {
145 return ret;
146 }
147
148 /* 创建一个OUT管道 */
149 ret = aw_usbd_pipe_create(&__g_ufun, &__g_out, &__g_out_info);
150 if (ret != AW_OK) {
151 return ret;
152 }
153
154 /* 把功能添加到创建的USB设备实例中*/
155 ret = aw_usbd_fun_add(&__g_usbd_obj, 0, &__g_ufun);
156 if (ret != AW_OK) {
157 return ret;
158 }
159
160 AW_SEMB_INIT(__g_semb, 0, AW_SEM_Q_PRIORITY);
161 /* 创建一个USB设备任务*/
162 AW_TASK_INIT(__g_task,
163 "CUSTOM-USB",
164 10,
165 2048,
166 __custom_task,
167 &__g_ufun);
168
169 AW_TASK_STARTUP(__g_task);
170
171 return AW_OK;
172 }
USB Device接收发送任务,当USB Device连接到PC端后,PC端检测到USB Device的设备信息和设置功能接口后,就会调用USB Device接口信息的回调函数__custom_alt_set,__custom_alt_set会发送信号量,通知USB Device接收发送任务USB Device已连接到PC端,然后进入等待数据接收状态,当收到数据后会取消阻塞状态,然后把收到的数据通过IN管道再发送出去:
74 /* 回调函数*/
75 static int __custom_alt_set (struct aw_usbd_fun *p_fun,
76 bool_t set)
77 {
78 if (set) {
79 AW_SEMB_GIVE(__g_semb);
80 } else {
81 aw_usbd_pipe_reset(p_fun->p_obj, &__g_in);
82 aw_usbd_pipe_reset(p_fun->p_obj, &__g_out);
83 }
84 return AW_OK;
85 }
87 static void __custom_task (void *arg)
88 {
89 int ret;
90 void *p_buf;
91
92 p_buf = aw_usb_mem_alloc(__BUF_SIZE);
93 if (p_buf == NULL){
94 aw_kprintf("aw_usb_mem_alloc error!");
95 return ;
96 }
97
98 AW_FOREVER {
99 /* 等待USB设备连接*/
100 while (!aw_fun_valid(&__g_ufun)) {
101 AW_INFOF(("custom usb wait for connect.\n"));
102 AW_SEMB_TAKE(__g_semb, AW_SEM_WAIT_FOREVER);
103 }
104
105 memset(p_buf,0,__BUF_SIZE);
106 /* 等待接收数据*/
107 ret = aw_usbd_trans_sync(__g_ufun.p_obj,
108 &__g_out,
109 p_buf,
110 __BUF_SIZE,
111 0,
112 AW_SEM_WAIT_FOREVER);
113 if (ret > 0) {
114 aw_kprintf("[recv]:%s\n", (char *)p_buf);
115 }
116
117 /* 把收到的数据发送回去 */
118 ret = aw_usbd_trans_sync(__g_ufun.p_obj,
119 &__g_in,
120 p_buf,
121 ret,
122 0,
123 __WAIT_TIMEOUT);
124 }
125 }
七、应用案例演示
把完整的例程拷贝到工程的user_code目录,并把USB Device入口函数demo_usbd_vendor_entry添加到main.c文件中:
1 #include "aworks.h"
2 #include "aw_vdebug.h"
3 #include "aw_led.h"
4 #include "aw_delay.h"
5
6 #define LED 0
7 extern void demo_usbd_vendor_entry (void);
8
9 int aw_main()
10 {
11 aw_kprintf("\r\nApplication Start. \r\n");
12
13 demo_usbd_vendor_entry();
14
15 while (1) {
16 aw_led_toggle(LED);
17 aw_mdelay(500);
18 }
19
20 return 0;
21 }
编译程序并把程序烧写进M1052开发板后,通过USB线连接开发板上的USB HOST1 和PC机,这时PC即会检测到有USB设备插入,在PC机上安装对应的驱动后,PC机识别到我们的自定义USB设备。
打开PC端串口打印:
在发送窗口输入想要发送的数据,点击发送,接收窗口就会收到响应的数据。
免责声明:本文若是转载新闻稿,转载此文目的是在于传递更多的信息,版权归原作者所有。文章所用文字、图片、视频等素材如涉及作品版权问题,请联系本网编辑予以删除。
下一篇:输入滤波器的简单设计
我要投稿
近期活动
- 安森美汽车&能源基础设施白皮书下载活动时间:2024年04月01日 - 2024年10月31日[立即参与]
- 2023年安森美(onsemi)在线答题活动时间:2023年09月01日 - 2023年09月30日[查看回顾]
- 2023年安森美(onsemi)在线答题活动时间:2023年08月01日 - 2023年08月31日[查看回顾]
- 【在线答题活动】PI 智能家居热门产品,带您领略科技智慧家庭时间:2023年06月15日 - 2023年07月15日[查看回顾]
- 2023年安森美(onsemi)在线答题活动时间:2023年06月01日 - 2023年06月30日[查看回顾]
分类排行榜
- 汽车电子电源行业可靠性要求,你了解多少?
- 内置可编程模拟功能的新型 Renesas Synergy™ 低功耗 S1JA 微控制器
- Vishay 推出高集成度且符合 IrDA® 标准的红外收发器模块
- ROHM 发布全新车载升降压电源芯片组
- 艾迈斯半导体推出行业超薄的接近/颜色传感器模块,助力实现无边框智能手机设计
- 艾迈斯半导体与 Qualcomm Technologies 集中工程优势开发适用于手机 3D 应用的主动式立体视觉解决方案
- 维谛技术(Vertiv)同时亮相南北两大高端峰会,精彩亮点不容错过
- 缤特力推出全新商务系列耳机 助力解决开放式办公的噪音难题
- CISSOID 和泰科天润(GPT)达成战略合作协议,携手推动碳化硅功率器件的广泛应用
- 瑞萨电子推出 R-Car E3 SoC,为汽车大显示屏仪表盘带来高端3D 图形处理性能
编辑推荐
小型化和稳定性如何兼得?ROHM 推出超小型高输出线性 LED 驱动器 IC,为插座型 LED 驱动 IC 装上一颗强有力的 “心脏”
众所周知,LED的驱动IC担负着在输入电压不稳定的情况下,为LED提供恒定的电流,并控制恒定(可调)亮度的作用。无论是室内照明,还是车载应用,都肩负着极为重要的使命。
- 关于反激电源效率的一个疑问
时间:2022-07-12 浏览量:10151
- 面对热拔插阐述的瞬间大电流怎么解决
时间:2022-07-11 浏览量:8910
- PFC电路对N线进行电压采样的目的是什么
时间:2022-07-08 浏览量:9552
- RCD中的C对反激稳定性有何影响
时间:2022-07-07 浏览量:7173
- 36W单反激 传导7~10M 热机5分钟后超标 不知道哪里出了问题
时间:2022-07-07 浏览量:5950
- PFC电感计算
时间:2022-07-06 浏览量:4158
- 多相同步BUCK
时间:2010-10-03 浏览量:37860
- 大家来讨论 系列之二:开机浪涌电流究竟多大?
时间:2016-01-12 浏览量:43153
- 目前世界超NB的65W适配器
时间:2016-09-28 浏览量:60016
- 精讲双管正激电源
时间:2016-11-25 浏览量:128064
- 利用ANSYS Maxwell深入探究软磁体之----电感变压器
时间:2016-09-20 浏览量:107543
- 【文原创】认真的写了一篇基于SG3525的推挽,附有详细..
时间:2015-08-27 浏览量:100260