-
Notifications
You must be signed in to change notification settings - Fork 287
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
248 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,104 @@ | ||
usbd_cdc_acm | ||
=============== | ||
|
||
本 demo 主要用于演示 cdc acm 功能,包含收发测试,DTR 控制,ZLP 测试,性能测试。 | ||
|
||
- 开辟读写 buffer,用于收发数据,并且buffer需要用 nocache 修饰,这里我们读写都是用 2048字节,是为了后面的 ZLP 测试和性能测试使用。 | ||
|
||
.. code-block:: C | ||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048]; /* 2048 is only for test speed , please use CDC_MAX_MPS for common*/ | ||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048]; | ||
- 在协议栈事件回调中,我们需要在枚举完成后启动第一次传输,并清除相关 flag,可以在 reset 事件中清除,也可以在 configured 事件中清除。 | ||
|
||
.. code-block:: C | ||
static void usbd_event_handler(uint8_t busid, uint8_t event) | ||
{ | ||
switch (event) { | ||
case USBD_EVENT_RESET: | ||
break; | ||
case USBD_EVENT_CONNECTED: | ||
break; | ||
case USBD_EVENT_DISCONNECTED: | ||
break; | ||
case USBD_EVENT_RESUME: | ||
break; | ||
case USBD_EVENT_SUSPEND: | ||
break; | ||
case USBD_EVENT_CONFIGURED: | ||
ep_tx_busy_flag = false; | ||
/* setup first out ep read transfer */ | ||
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048); | ||
break; | ||
case USBD_EVENT_SET_REMOTE_WAKEUP: | ||
break; | ||
case USBD_EVENT_CLR_REMOTE_WAKEUP: | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
- 在接收完成中断中继续发起接收;在发送完成中断中判断是否需要发送 ZLP。 | ||
|
||
.. code-block:: C | ||
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) | ||
{ | ||
USB_LOG_RAW("actual out len:%d\r\n", nbytes); | ||
// for (int i = 0; i < 100; i++) { | ||
// printf("%02x ", read_buffer[i]); | ||
// } | ||
// printf("\r\n"); | ||
/* setup next out ep read transfer */ | ||
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048); | ||
} | ||
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) | ||
{ | ||
USB_LOG_RAW("actual in len:%d\r\n", nbytes); | ||
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) { | ||
/* send zlp */ | ||
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0); | ||
} else { | ||
ep_tx_busy_flag = false; | ||
} | ||
} | ||
- 以下是为了测试 DTR 功能并控制 USB 发送,DTR 和 RTS 只用于搭配 UART 使用,如果是纯 USB,没什么用,这里仅做测试。DTR 开关使用任意串口上位机并勾选 DTR。 | ||
|
||
.. code-block:: C | ||
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr) | ||
{ | ||
if (dtr) { | ||
dtr_enable = 1; | ||
} else { | ||
dtr_enable = 0; | ||
} | ||
} | ||
- 在主函数中一直调用发送即可 | ||
|
||
.. code-block:: C | ||
void cdc_acm_data_send_with_dtr_test(uint8_t busid) | ||
{ | ||
if (dtr_enable) { | ||
ep_tx_busy_flag = true; | ||
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048); | ||
while (ep_tx_busy_flag) { | ||
} | ||
} | ||
} | ||
- 上述我们需要注意,长度设置为 2048 是为了测试 ZLP 功能,通常实际使用时,接收长度应该使用 CDC_MAX_MPS 。具体原因参考 :ref:`usb_ext` | ||
- 如果需要做性能测试,使用 tools/test_srcipts/test_cdc_speed.py 进行测试,并在测试之前删除 `usbd_cdc_acm_bulk_out` 和 `usbd_cdc_acm_bulk_in` 中的打印,否则会影响测试结果。 | ||
|
||
|
||
此外,对于 CDC ACM 搭配 OS 的情况,通常我们 read 使用异步并将数据存储到 ringbuffer 中,write 使用同步搭配 sem 使用。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
usbd_hid | ||
=============== | ||
|
||
HID 功能比较简单,因此不作赘述,需要注意,使用 hid custom 例程时,需要搭配 `tools/test_srcipts/test_hid_inout.py` 使用。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,39 @@ | ||
usbd_msc | ||
=============== | ||
|
||
本节主要演示 USB 模拟 U 盘功能。默认使用RAM 作为存储介质模拟 U 盘。 | ||
|
||
- 实现 U 盘的读写和获取容量接口,注意,容量 block_num 为虚拟的,实际没有这么多 block,读写的数据超过 BLOCK_COUNT 会丢弃。 | ||
|
||
block_size 一般为 512/2048/4096。 | ||
|
||
.. code-block:: C | ||
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size) | ||
{ | ||
*block_num = 1000; //Pretend having so many buffer,not has actually. | ||
*block_size = BLOCK_SIZE; | ||
} | ||
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length) | ||
{ | ||
if (sector < BLOCK_COUNT) | ||
memcpy(buffer, mass_block[sector].BlockSpace, length); | ||
return 0; | ||
} | ||
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length) | ||
{ | ||
if (sector < BLOCK_COUNT) | ||
memcpy(mass_block[sector].BlockSpace, buffer, length); | ||
return 0; | ||
} | ||
- 默认上述 API 在中断中执行,如果需要在非中断中执行,可以选择如下: | ||
|
||
1,裸机下开启 `CONFIG_USBDEV_MSC_POLLING` 并在 while1 中调用 `usbd_msc_polling`,则读写函数在 while1 中执行。 | ||
|
||
2, OS 下开启 `CONFIG_USBDEV_MSC_THREAD`,则读写函数在线程中执行。 | ||
|
||
- 修改 `CONFIG_USBDEV_MSC_STACKSIZE` 会影响 U 盘的读写速度,必须是 block_size 的整数倍,当然,也会增加 RAM 的占用。 | ||
|
||
- 如果 RAM 例程可以用,但是介质更换成 SD 或者 FLASH 后不可用,则一定是介质驱动问题。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,83 @@ | ||
usbd_video | ||
=============== | ||
|
||
本节主要演示 USB UAC 功能,支持 YUYV, MJPEG, H264 格式。为了方便演示,都采用的静态图。 | ||
|
||
demo 包含 **video_static_yuyv_template**, **video_static_mjpeg_template**, **video_static_h264_template**, 仅描述符和图片数据不同。 | ||
|
||
- 在高速模式下,默认最大是1024字节,但是如果芯片支持 additional transcations,可以配置为最高 2048字节或者3072字节,这样可以提高传输效率。 | ||
|
||
.. code-block:: C | ||
#ifdef CONFIG_USB_HS | ||
#define MAX_PAYLOAD_SIZE 1024 // for high speed with one transcations every one micro frame | ||
#define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11)) | ||
// #define MAX_PAYLOAD_SIZE 2048 // for high speed with two transcations every one micro frame | ||
// #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 2)) | (0x01 << 11)) | ||
// #define MAX_PAYLOAD_SIZE 3072 // for high speed with three transcations every one micro frame | ||
// #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 3)) | (0x02 << 11)) | ||
#else | ||
#define MAX_PAYLOAD_SIZE 1020 | ||
#define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11)) | ||
#endif | ||
- 通常只需要修改 WIDTH 和 HEIGHT | ||
|
||
.. code-block:: C | ||
#define WIDTH (unsigned int)(640) | ||
#define HEIGHT (unsigned int)(480) | ||
#define CAM_FPS (30) | ||
#define INTERVAL (unsigned long)(10000000 / CAM_FPS) | ||
#define MIN_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS) //16 bit | ||
#define MAX_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS) | ||
#define MAX_FRAME_SIZE (unsigned long)(WIDTH * HEIGHT * 2) | ||
- USB 端点配置,默认 interval 为 1,也就是全速模式下 1ms,高速模式下 125us。同步类型使用异步模式。 | ||
|
||
.. code-block:: C | ||
/* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */ | ||
USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01), | ||
- 使用 `usbd_video_stream_start_write` 传输数据 | ||
|
||
1,传输采用双缓冲的形式, **MAX_PACKETS_IN_ONE_TRANSFER** 表示一次传输可以携带多少个 **MAX_PAYLOAD_SIZE**,通常 IP 只能为 1。 | ||
|
||
2,在中断完成中,调用 `usbd_video_stream_split_transfer` 继续下一次传输,直到返回为 true 表示传输完成。这边的分裂传输只是表示将图片数据拆成 **MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE** 份传输。 | ||
|
||
3,通常 IP 不支持一次传输非常大的数据,比如传输 1MB,因此需要做分裂传输,但是会增加中断次数。并且一次传输非常大数据也是需要足够的 RAM。 | ||
|
||
.. code-block:: C | ||
void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) | ||
{ | ||
if (usbd_video_stream_split_transfer(busid, ep)) { | ||
/* one frame has done */ | ||
iso_tx_busy = false; | ||
} | ||
} | ||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE]; | ||
void video_test(uint8_t busid) | ||
{ | ||
memset(packet_buffer, 0, sizeof(packet_buffer)); | ||
while (1) { | ||
if (tx_flag) { | ||
iso_tx_busy = true; | ||
usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg)); | ||
while (iso_tx_busy) { | ||
if (tx_flag == 0) { | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
.. _usb_ext: | ||
|
||
USB 知识点拓展 | ||
=========================== | ||
|
||
|