summaryrefslogtreecommitdiff
path: root/bsp/hc32/tests/test_usbd.c
blob: be867a3bfe7212525d3dcbffe77f88a7246a2575 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
/*
 * Copyright (c) 2022-2024, Xiaohua Semiconductor Co., Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-12-30     CDT          first version
 * 2026-05-27     CDT          Support HC32F4A2
 * 2026-06-03     CDT          Support HC32F467
 */

#include <rtthread.h>
#include <rtdevice.h>

#ifdef RT_USB_DEVICE_CDC
/* menuconfig:
  1.Hardware Drivers Config--->On-Chip Peripheral Driver--->Enable USB--->
                                                            [*]Use USBFS Core
                                                                Select USB Mode(USB Device Mode)
                                                            [*]Enable VBUS Sensing for Device
  2.RT-Thread Components--->
        Using USB legacy version--->
            Using USB device--->Device type--->
                [*]Enable to use device as CDC device
*/
/*
 * 程序清单:这是一个 usb device 设备使用例程
 * 例程导出了 cdc_sample 命令到控制终端
 * PC上需要使用串口助手以DTR[√]方式打开USB的虚拟串口(比如 SSCOM 有这个功能)
 * 命令调用格式:cdc_sample
 * 程序功能:首先会打印三次str_write字符串内容,同时虚拟串口可输入发送任意小于255个字符的字符串,
 * 发送内容可在Finsh串口显示。
 */

#define USBD_DEV_NAME "vcom"     /* 名称 */
static rt_uint8_t cdc_str_read[256];

static rt_err_t cdc_rx_handle(rt_device_t dev, rt_size_t size)
{
    if (size >= sizeof(cdc_str_read))
    {
        size = sizeof(cdc_str_read) - 1;
    }
    /* 读取虚拟串口接收内容 */
    rt_device_read(dev, 0, cdc_str_read, size);
    cdc_str_read[size] = '\0';
    rt_kprintf("Read message:  %s\n", cdc_str_read);

    return RT_EOK;
}

static int cdc_sample(void)
{
    rt_uint8_t i;
    rt_err_t ret = RT_EOK;
    rt_device_t cdc_dev = RT_NULL;                           /* usb device设备句柄 */
    rt_uint8_t str_write[] = "This is a usb cdc device test!\r\n";
    rt_size_t str_len = rt_strlen((const char *)str_write);

    /* 查找USB虚拟串口设备 */
    cdc_dev = rt_device_find(USBD_DEV_NAME);
    if (cdc_dev == RT_NULL)
    {
        rt_kprintf("cdc sample run failed! can't find %s device!\n", USBD_DEV_NAME);
        return -RT_ERROR;
    }

    /* 以读写方式打开设备 */
    ret = rt_device_open(cdc_dev, RT_DEVICE_FLAG_INT_RX);
    if (ret != RT_EOK)
    {
        rt_kprintf("open %s device failed!\n", USBD_DEV_NAME);
        return ret;
    }
    rt_device_set_rx_indicate(cdc_dev, cdc_rx_handle);

    for (i = 1; i < 4; i++)
    {
        rt_kprintf("Start to send test message 3 timers :%d.\n", i);
        if (rt_device_write(cdc_dev, 0, str_write, str_len) != str_len)
        {
            rt_kprintf("send test message failed\n");
            return -RT_ERROR;
        }
        /* 延时1000ms */
        rt_thread_mdelay(1000);
    }

    // for (;;);
    return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(cdc_sample, usbd cdc sample);
#endif


#if defined(RT_USB_DEVICE_MSTORAGE)

/* F4A0/F4A2/HC32F467 only FS can used with spi flash */
#if ((defined(HC32F4A0) || defined(HC32F4A2) || defined(HC32F467)) && defined(BSP_USING_USBFS)) || \
    defined(HC32F460) || defined(HC32F472)

/* Enable spibus1, SFUD, usb msc */
/* menuconfig:
1. Hardware Drivers Config--->On-Chip Peripheral Driver--->Enable SPI BUS--->Enable SPI1 BUS
2. Hardware Drivers Config--->On-Chip Peripheral Driver--->Enable USB--->
                                                            [*]Use USBFS Core
                                                                Select USB Mode(USB Device Mode)
                                                            [*]Enable VBUS Sensing for Device
3. RT-Thread Components--->Device Drivers--->Using SPI Bus/Device device drivers
                                                [*]Using Serial Flash Universal Driver
                                                    [*]Using auto probe flash JEDEC SFDP parameters
                                                    [*]Using defined supported flash chip information table
                                                    (50000000)Default spi maximum speed(HZ)
4. RT-Thread Components--->Using USB legacy version
                                                [*]Using USB device--->
                                                    [*]Device type---> Enable to use device as Mass Storage device
                                                (spiflash)msc class disk name

*/
#include "drv_gpio.h"
#include "drv_spi.h"
#include "dev_spi_flash_sfud.h"

#define SPI_FLASH_CHIP RT_USB_MSTORAGE_DISK_NAME /* msc class disk name */
#if defined(HC32F4A0) || defined(HC32F4A2) || defined(HC32F4A8) || defined(HC32F467)
#define SPI_FLASH_SS_PORT     GPIO_PORT_C
#define SPI_FLASH_SS_PIN      GPIO_PIN_07
#define SPI_BUS_NAME          "spi1"
#define SPI_FLASH_DEVICE_NAME "spi10"
#elif defined(HC32F460)
#define SPI_FLASH_SS_PORT     GPIO_PORT_C
#define SPI_FLASH_SS_PIN      GPIO_PIN_07
#define SPI_BUS_NAME          "spi3"
#define SPI_FLASH_DEVICE_NAME "spi30"
#elif defined(HC32F472)
#define SPI_FLASH_SS_PORT     GPIO_PORT_B
#define SPI_FLASH_SS_PIN      GPIO_PIN_12
#define SPI_BUS_NAME          "spi1"
#define SPI_FLASH_DEVICE_NAME "spi10"
#endif

static void rt_hw_spi_flash_reset(char *spi_dev_name)
{
    struct rt_spi_device *spi_dev_w25;
    rt_uint8_t w25_en_reset = 0x66;
    rt_uint8_t w25_reset_dev = 0x99;

    spi_dev_w25 = (struct rt_spi_device *)rt_device_find(spi_dev_name);
    if (!spi_dev_w25)
    {
        rt_kprintf("Can't find %s device!\n", spi_dev_name);
    }
    else
    {
        rt_spi_send(spi_dev_w25, &w25_en_reset, 1U);
        rt_spi_send(spi_dev_w25, &w25_reset_dev, 1U);
        DDL_DelayMS(1U);
        rt_kprintf("Reset ext flash!\n");
    }
}


static int rt_hw_spi_flash_with_sfud_init(void)
{
#if defined(HC32F4A0) || defined(HC32F4A2) || defined(HC32F460) || defined(HC32F4A8) || \
    defined(HC32F467)
    rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_FLASH_DEVICE_NAME, GET_PIN(C, 7));
#elif defined(HC32F472)
    rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_FLASH_DEVICE_NAME, GET_PIN(B, 12));
#endif
    if (RT_NULL == rt_sfud_flash_probe(SPI_FLASH_CHIP, SPI_FLASH_DEVICE_NAME))
    {
        rt_hw_spi_flash_reset(SPI_FLASH_DEVICE_NAME);
        if (RT_NULL == rt_sfud_flash_probe(SPI_FLASH_CHIP, SPI_FLASH_DEVICE_NAME))
        {
            return -RT_ERROR;
        }
    }

    return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_with_sfud_init);
#endif

#endif

#ifdef RT_USB_DEVICE_HID
#include "drv_gpio.h"

/* menuconfig:
1. Hardware Drivers Config--->On-Chip Peripheral Driver--->Enable USB--->
                                                            [*]Use USBFS Core
                                                                Select USB Mode(USB Device Mode)
                                                            [*]Enable VBUS Sensing for Device
2. RT-Thread Components--->
    Using USB legacy version--->
        Using USB device--->Device type--->
            [*]Enable to use device as HID device
*/
/*
 * 程序清单:这是一个 usb hid device 设备使用例程
 * 例程导出了 hid_sample 命令到控制终端
 * 命令调用格式:hid_sample
 * 程序功能:首先会打印str_write[0]字符串内容,然后按下按键WKUP,hid设备将发送按键keyn,n是按下次数,可
 * 通过bus hound查看数据。
 * 发送内容可在Finsh串口显示。
*/

#define USBD_DEV_NAME "hidd"     /* 名称 */
#if defined(HC32F4A0) || defined(HC32F4A2) || defined(HC32F4A8) || defined(HC32F467)
#define KEY_PIN_NUM GET_PIN(A, 0)          /* PA0 */
#elif defined(HC32F460)
#define KEY_PIN_NUM GET_PIN(B, 1)          /* PB1 */
#elif defined(HC32F472)
#define KEY_PIN_NUM GET_PIN(B, 5)          /* PB5 */
#endif

static int hid_sample(void)
{
    rt_err_t ret = RT_EOK;
    rt_device_t hid_dev = RT_NULL;                           /* usb device设备句柄 */
    char str_write[2][5] = { "test", "Key0" };


    /* 查找设备 */
    hid_dev = rt_device_find(USBD_DEV_NAME);
    if (hid_dev == RT_NULL)
    {
        rt_kprintf("hid sample run failed! can't find %s device!\n", USBD_DEV_NAME);
        return -RT_ERROR;
    }

    /* 以收中断方式打开设备 */
    ret = rt_device_open(hid_dev, RT_DEVICE_OFLAG_RDWR);
    if (ret != RT_EOK)
    {
        rt_kprintf("open %s device failed!\n", USBD_DEV_NAME);
        return ret;
    }

    rt_kprintf("This is a usb hid device test!\r\n");
    rt_device_write(hid_dev, 0, str_write[0], sizeof(str_write[0]));
    rt_pin_mode(KEY_PIN_NUM, PIN_MODE_INPUT);

    for (;;)
    {
        rt_thread_mdelay(200);
        if (PIN_LOW == rt_pin_read(KEY_PIN_NUM))
        {
            rt_device_write(hid_dev, 0, str_write[1], sizeof(str_write[1]));
            str_write[1][3] += 0x01;
        }
    }

    /* unreachable, but keeps static analyzers happy */
    return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(hid_sample, usbd hid sample);
#endif

#ifdef RT_USB_DEVICE_WINUSB
/* menuconfig:
1. Hardware Drivers Config--->On-Chip Peripheral Driver--->Enable USB--->
                                                            [*]Use USBFS Core
                                                                Select USB Mode(USB Device Mode)
                                                            [*]Enable VBUS Sensing for Device
2. RT-Thread Components--->
    Using USB legacy version--->
        Using USB device--->Device type--->
            [*]Enable to use device as winusb device
*/
/*
 * 程序清单:这是一个 usb WINUSB device 设备使用例程
 * RTT 的WINUSB Windows无法免驱,需要使用zadig安装winusb驱动程序(如设备管理器-通用串行总线设备-RTT Win USB已识别则不需要安装)。
 * 例程导出了 winusb_sample 命令到控制终端
 * 命令调用格式:winusb_sample
 * 软件:llcom.exe
 * 程序功能:MSH命令发送winusb_sample,运行测试程序。
 * 打开llcom.exe软件,选择小工具-WinUSB设备-选择对应RTT Win USB设备-打开-勾选Hex发送-发送数据(注意:每次发送数据长度为4的整数倍)。
 * 通过llcom.exe可发送bulk数据(100字符以内)到设备,设备收到后会回发给主机(llcom.exe),同时通过MSH终端显示收到的HEX数据。
 * 注意:1、llcom.exe中的GUID与驱动程序中设定保持一致(通过设备管理器选择RTT Win USB设备的属性来查看);
 *       2、win_usb_read()函数中的UIO_REQUEST_READ_FULL改为UIO_REQUEST_READ_BEST,实现数据即读即取;
 *          否则需要接满传入的sizeof(winusb_str_read)数量的数据,才会回调接收函数。
 *
 */
#define WINUSB_DEV_NAME "winusb"     /* 名称 */
static rt_uint8_t winusb_str_read[100];

static rt_err_t winusb_rx_handle(rt_device_t dev, rt_size_t size)
{
    uint8_t i;
    if (size > sizeof(winusb_str_read))
    {
        size = sizeof(winusb_str_read);
    }
    /* 读取定时器当前值 */
    rt_kprintf("Rx:");
    for (i = 0; i < size; i++)
    {
        rt_kprintf("%x", winusb_str_read[i]);
    }
    rt_kprintf("\r\n");
    rt_device_write(dev, 0, winusb_str_read, size);
    /* prepare read config */
    rt_device_read(dev, 0, winusb_str_read, sizeof(winusb_str_read));
    return RT_EOK;
}

static int winusb_sample(void)
{
    rt_err_t ret = RT_EOK;
    rt_device_t winusb_dev = RT_NULL;                       /* usb device设备句柄 */

    /* 查找设备 */
    winusb_dev = rt_device_find(WINUSB_DEV_NAME);
    if (winusb_dev == RT_NULL)
    {
        rt_kprintf("winusb sample run failed! can't find %s device!\n", WINUSB_DEV_NAME);
        return -RT_ERROR;
    }

    /* 以读写方式打开设备 */
    ret = rt_device_open(winusb_dev, RT_DEVICE_OFLAG_RDWR);
    if (ret != RT_EOK)
    {
        rt_kprintf("open %s device failed!\n", WINUSB_DEV_NAME);
        return ret;
    }
    rt_kprintf("Found and open success %s device!\n", WINUSB_DEV_NAME);

    ret = rt_device_set_rx_indicate(winusb_dev, winusb_rx_handle);
    if (ret == RT_EOK)
    {
        /* prepare read config,set once,read once, */
        rt_device_read(winusb_dev, 0, winusb_str_read, sizeof(winusb_str_read));
    }
    return ret;
}

/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(winusb_sample, usbd winusb sample);
#endif