0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

TinyUSB基本介绍和移植例程

灵动MM32MCU 来源:灵动MM32MCU 2023-07-14 09:38 次阅读

1TinyUSB基本介绍

TinyUSB是一个用于嵌入式系统的开源的跨平台USB协议栈,协议栈中包含了主机端及设备端的协议栈,由于不使用动态内存分配以及采用阻塞所有中断事件,在非ISR任务功能中处理中断事件的设计方式,所以此协议栈的内存安全性及线程安全性极高。

源码是托管在GitHub上面,地址是:https://github.com/hathach/tinyusb。

fc2182cc-2163-11ee-962d-dac502259ad0.png

2TinyUSB基本移植介绍

MM32已基于TinyUSB开发完成相应的参考例程,并可以给客户提供参考,本次我们介绍的移植将基于此基础上进行。将TinyUSB从GitHub上克隆到本地,可以得到如下内容:

fc4f427a-2163-11ee-962d-dac502259ad0.png

图1 TinyUSB源码

移植TinyUSB到MM32F0160需要添加如下文件:

属于工程专用文件:

usb_descriptors.c

usb_dcd_port.c

tusb_config.h

usb_descriptors.h

属于库内文件:

tusb.c

usbd.c

usbd_control.c

*_device.c

tusb_fifo.c

将src 整个文件夹copy替换到例程components目录下的src。

将tinyusb 目录下example下的对应文件,以device uac2_headset为例,将tinyusbexamplesdeviceuac2_headsetsrc 四个文件copy到例程user文件夹里面。

fc723208-2163-11ee-962d-dac502259ad0.png

图2 源码的device文件

fc926ea6-2163-11ee-962d-dac502259ad0.png

图3 用户工程文件

USB时钟频率是48MHz,HSE可以经过PLL倍频到48MHz或96MHz,然后经过分频到48MHz,注意需要使用外部晶振,如果使用内部时钟HSI,需要使能时钟回馈系统CRS功能。

在main.c 增加USB时钟配置函数void USB_DeviceClockInit(void),同时将board_init();替换成usb时钟初始化函数,主频配置96MHz,USB选择PLL1输入二分频到USB。

有使用TU_LOG做串口输出,可以使能CFG_TUSB_DEBUG为需要的输出等级,同时将

#define tu_printf printf

改到串口输出,Keil Options->Target 勾选Use MicroLIB,并实现重定向函数。

//-------------clockinitial-------------//
voidUSB_DeviceClockInit(void)//HSE96M
{
/*SelectUSBCLKsource*/
RCC->CFGR&=~(1<< 19);           //USB CLK SEL PLL1

    RCC->CFGR&=~(0x03<< 22);
    RCC->CFGR|=0x01<< 22;

    RCC_AHBPeriphClockCmd(RCC_AHBENR_USB, ENABLE);
}

//------------- MAIN -------------//
int main(void)
{
    USB_DeviceClockInit();             //board_init();

    CONSOLE_Init(460800);              //enable printf debug

    //init device stack on configured roothub port
    tud_init(BOARD_TUD_RHPORT);

    TU_LOG1("Headset running
"); //CFG_TUSB_DEBUG for debugging #if CFG_TUSB_DEBUG

    //0 : no debug
    //1 : print error
    //2 : print warning
    //3 : print info
    while (1)
    {
        tud_task();                    //tinyusb device task
        led_blinking_task();
        audio_task();
    }
}

添加tud_dcd_port.c 接口函数文件,Keil下Options C/C++勾选C99和GNU externsions(tud_dcd_port.c 文件可以参考现有例程或者联系灵动技术支持)。

fcb29438-2163-11ee-962d-dac502259ad0.png

图4 工程设置

移植修改其他设备基本流程和上述一致,将tinyusb 目录exampledevice 里面将想要修改的设备src文件夹里面四个文件copy到例程user文件夹里面替换。

3修改一个uac2_headset Device设备

在克隆下来的的文件夹examplesdevice里面找到需要修改的device设备,本次修改uac2_headset。将里面的文件都copy到工程USER目录里面,然后Keil工程按如下文件树添加对应文件。

fcce3a76-2163-11ee-962d-dac502259ad0.png

图5 uac2_headset设备描述符文件

文件树:

1.TinyUSB_UAC

2. │

3. ├─USER

4. │ main.c

5. │ usb_descriptors.c

6. │ usb_dcd_port.c

7. │

8. └─TinyUSB

9. tusb.c

10. audio_device.c

11. tud_fifo.c

12. usbd.c

13. usb_control.c

在tusb_config.h文件里面CLASS将对应的设备define改成1 ( #define CFG_TUD_AUDIO 1 ) ,使能AUDIO设备。

//-------------CLASS-------------//
#defineCFG_TUD_CDC0
#defineCFG_TUD_MSC0
#defineCFG_TUD_HID0
#defineCFG_TUD_MIDI0
#defineCFG_TUD_AUDIO1
#defineCFG_TUD_VENDOR0

按照前面的移植步骤,只需要修改main.c 里面的时钟初始化部分即可,其他的device设备修改流程一致。

4新增一个设备变成复合设备

USB设备主要四个描述符,分别是设备描述符(Device Descriptors),配置描述符(Configuration Descriptor),报告描述符(Configuration Descriptor)和字符描述符(String Descriptors)。

添加复合设备device文件,本例程在上述3(修改一个uac2_headset Device设备)例程的基础上增加一个HID设备变成复合设备,首先将工程目录下的components inyusbsrcclasshidhid_device.c文件添加到工程。

fcfce4ac-2163-11ee-962d-dac502259ad0.png

图6 源码HID设备参考文件

fd266732-2163-11ee-962d-dac502259ad0.png

图7 添加device文件

在tusb_config.h 文件里面 CLASS 使能HID宏,本例程是复合设备(Audio+HID)所以两个宏都为1。

//-------------CLASS-------------//
#defineCFG_TUD_CDC0
#defineCFG_TUD_MSC0
#defineCFG_TUD_HID1
#defineCFG_TUD_MIDI0
#defineCFG_TUD_AUDIO1
#defineCFG_TUD_VENDOR0

在usb_descriptors.c 文件里面添加HID的描述符,增加HID Report Descriptor相关函数。

//--------------------------------------------------------------------+
//HIDReportDescriptor
//--------------------------------------------------------------------+
uint8_tconstdesc_hid_report[]=
{
TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE)
};

//InvokedwhenreceivedGETHIDREPORTDESCRIPTOR
//Applicationreturnpointertodescriptor
//Descriptorcontentsmustexistlongenoughfortransfertocomplete
uint8_tconst*tud_hid_descriptor_report_cb(uint8_titf)
{
(void)itf;
return(desc_hid_report);
}

在usb_descriptors.c 文件里面添加HID Descriptor length(注意:长度一定要和下面DESCRIPTOR对应,否则枚举会失败)。

#defineCONFIG_TOTAL_LEN(TUD_CONFIG_DESC_LEN+CFG_TUD_AUDIO*TUD_AUDIO_HEADSET_STEREO_DESC_LEN+TUD_HID_INOUT_DESC_LEN)

在usb_descriptors.c 文件里面添加HID描述符文件,例程使用的是TUD_HID_INOUT_DESCRIPTOR,和上述CONFIG_TOTAL_LEN里面的TUD_HID_INOUT_DESC_LEN对应,然后配置HID IN OUT通讯选择哪个端点。

#defineEPNUM_HID0x03

uint8_tconstdesc_configuration[]=
{
//Interfacecount,stringindex,totallength,attribute,powerinmA
TUD_CONFIG_DESCRIPTOR(1,ITF_NUM_TOTAL,0,CONFIG_TOTAL_LEN,TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP,100),

//Interfacenumber,stringindex,EPOut&EPInaddress,EPsize
TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2,EPNUM_AUDIO_OUT,EPNUM_AUDIO_IN|0x80),

//Interfacenumber,stringindex,protocol,reportdescriptorlen,EPOut&Inaddress,size&pollinginterval
TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID,6,HID_ITF_PROTOCOL_NONE,sizeof(desc_hid_report),EPNUM_HID,0x80|EPNUM_HID,CFG_TUD_HID_EP_BUFSIZE,10),
};

在usb_descriptors.c 文件里面添加 HID string字符串。

//arrayofpointertostringdescriptors
charconst*string_desc_arr[]=
{
(constchar[]){0x09,0x04},//0:issupportedlanguageisEnglish(0x0409)
"TinyUSB",//1:Manufacturer
"TinyUSBheadset",//2:Product
"000001",//3:Serials,shouldusechipID
"TinyUSBSpeakers",//4:AudioInterface
"TinyUSBMicrophone",//5:AudioInterface
"TinyUSBHID",//6:HIDInterface
};

在usb_descriptors.h 文件里面ITF_NUM_TOTAL 增加一个 ITF_NUM_HID。

enum
{
ITF_NUM_AUDIO_CONTROL=0,
ITF_NUM_AUDIO_STREAMING_SPK,
ITF_NUM_AUDIO_STREAMING_MIC,
ITF_NUM_HID,
ITF_NUM_TOTAL
};

在main.c 里面增加hid_task(); 然后将HID的其他处理函数添加到main.c。

/*-------------MAIN-------------*/
intmain(void)
{
USB_DeviceClockInit();//board_init();

CONSOLE_Init(460800);//enableprintfdebug

//initdevicestackonconfiguredroothubport
tud_init(BOARD_TUD_RHPORT);

TU_LOG1("UAC2Headset&HIDrunning
");///CFG_TUSB_DEBUGfordebugging#ifCFG_TUSB_DEBUG
  //0:nodebug
  //1:printerror
  //2:printwarning
  //3:printinfo

while(1)
{
tud_task();//TinyUSBdevicetask
audio_task();
hid_task();
}

return0;
}

在hid_task()函数中添加需要处理的用户程序。

//--------------------------------------------------------------------+
//USBHID
//--------------------------------------------------------------------+
uint8_thid_report_data[64];

staticvoidsend_hid_report(uint8_treport_id,uint32_tbtn)
{
//skipifhidisnotreadyyet
if(!tud_hid_ready())return;

switch(report_id)
{
caseREPORT_ID_MOUSE:
{
int8_tconstdelta=5;

//nobutton,right+down,noscroll,nopan
if(btn)
{
tud_hid_mouse_report(REPORT_ID_MOUSE,0x00,delta,delta,0,0);
}
}
break;

default:break;
}

}

//Every10ms,wewillsent1reportforeachHIDprofile(keyboard,mouseetc..)
//tud_hid_report_complete_cb()isusedtosendthenextreportafterpreviousoneiscomplete
voidhid_task(void)
{
uint32_tconstbtn=1u;

//Remotewakeup
if(tud_suspended()&&btn)
{
//Wakeuphostifweareinsuspendmode
//andREMOTE_WAKEUPfeatureisenabledbyhost
tud_remote_wakeup();
}else
{
//Sendthe1stofreportchain,therestwillbesentbytud_hid_report_complete_cb()
send_hid_report(REPORT_ID_MOUSE,btn);
}
}

5功能验证测试

完成上述移植,解决基本的编译问题后烧录测试能枚举正常。

fd580436-2163-11ee-962d-dac502259ad0.png

图8 枚举过程

fd93728c-2163-11ee-962d-dac502259ad0.png

图9 枚举成功

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式系统
    +关注

    关注

    41

    文章

    3575

    浏览量

    129287
  • 接口
    +关注

    关注

    33

    文章

    8537

    浏览量

    150906
  • usb
    usb
    +关注

    关注

    60

    文章

    7909

    浏览量

    264139
  • 串口
    +关注

    关注

    14

    文章

    1549

    浏览量

    76271
  • GitHub
    +关注

    关注

    3

    文章

    468

    浏览量

    16398

原文标题:灵动微课堂 (第263讲)|基于MM32F0163D7P的USB接口TinyUSB应用:移植和新增设备(一)

文章出处:【微信号:MindMotion-MMCU,微信公众号:灵动MM32MCU】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何在ESP32S3上使用TinyUSB,配置为Vendor Class设备?

    您好,请问如何再ESP32S3上使用TinyUSB,配置为Vendor Class设备,没找到参考例程
    发表于 06-17 06:43

    stm32103VB tinyusb使用异常,无法识别描述符是为什么?

    尝试STM32F103VB上使用tinyusb,完成配置之后开始没有反应。调试后发现这个上拉电阻的实现需要手动实现控制:dcd_disconnectdcd_connect之后调试发现设备还是无法识别
    发表于 05-30 11:08

    使用ESP32S3和TinyUSB如何配置为Vendor Class设备?

    您好,请问如何再ESP32S3上使用TinyUSB,配置为Vendor Class设备,没找到参考例程
    发表于 02-14 08:43

    UCOS扩展例程-UCOSII移植

    UCOS扩展例程-UCOSII移植
    发表于 12-14 17:24 30次下载

    UCOS扩展例程-UCOSIII移植

    UCOS扩展例程 - UCOSIII移植
    发表于 12-14 17:24 23次下载

    USB_DFU_IAP例程移植

    不同型号STM32的USB烧录程序移植介绍。通过USB对芯片下载程序的bootloader介绍
    发表于 04-21 11:00 17次下载

    基于STM32 HID例程生成不小于64字节传输的移植过程

    前言 本文简单介绍如何应用ST USB HID(MOUSE)例程生成一个可以输入和输出任何长度小于等于64字节的移植过程。 问题描述: HID的在USB的运用中是非常广泛的,但是很多应用并不是简单
    发表于 11-29 15:52 945次阅读
     基于STM32 HID<b class='flag-5'>例程</b>生成不小于64字节传输的<b class='flag-5'>移植</b>过程

    介绍摄像头采集显示的例程

    这一部分归纳了目前移植好的摄像头开发例程(后续也许还会再增加),包括OV7725/MT9V034/MT9M001/AR0144等Sensor,但不同的Sensor的例程规划都基本一致,因此以OV7725为例,来
    的头像 发表于 10-01 17:17 2900次阅读
    <b class='flag-5'>介绍</b>摄像头采集显示的<b class='flag-5'>例程</b>

    基于CubeMX-STM32F302_uCOSII例程移植

    基于CubeMX--STM32F302_uCOSII例程移植1、说明STM32F302的内核为Cortex-M4的,所以我们以官方的F4例程为基础移植。2、准备2.1、软件1、官方
    发表于 12-04 14:36 28次下载
    基于CubeMX-STM32F302_uCOSII<b class='flag-5'>例程</b><b class='flag-5'>移植</b>

    TinyUSB针对嵌入式系统的开源USB堆栈

    tinyusb.zip
    发表于 04-15 10:33 3次下载
    <b class='flag-5'>TinyUSB</b>针对嵌入式系统的开源USB堆栈

    W806单片机文件系统移植例程

    W806单片机,文件系统移植例程说明。
    发表于 05-05 14:57 8次下载

    如何对TinyUSB上游仓库进行移植

    TinyUSB 是一个用于嵌入式系统的开源跨平台 USB Host/Device 协议栈,其为了内存安全而设计,没有动态分配,同时也是线程安全的,所有中断事件都会被推迟,然后在非 ISR 任务函数中处理,支持多种 MCU。目前 TinyUSB 的源代码托管在 GitHub
    的头像 发表于 05-06 11:26 3615次阅读
    如何对<b class='flag-5'>TinyUSB</b>上游仓库进行<b class='flag-5'>移植</b>

    W806单片机移植LVGL库例程源码下载

    W806单片机移植LVGL库例程源码下载。
    发表于 05-11 15:11 15次下载

    如何移植FPGA的例程

    在完成EDA作业后,抽空分享一下如何移植FPGA的例程。我EDA作业用的板子型号是Zybo-Z7,然后移植的是原子哥的HDMI实现方块移动例程
    的头像 发表于 09-05 15:12 1876次阅读

    基于MM32F0163D7P的USB接口TinyUSB应用:移植和新增设备(二)

    如果用户想增加一个device设备但是在TinyUSB class里面又没有参考示例,本次我们一起来移植一个CDC+printer复合设备。操作步骤还是和上篇一样,先将TinyUSB 从GitHub上克隆下来,将src 整个文件
    的头像 发表于 07-20 17:05 1169次阅读
    基于MM32F0163D7P的USB接口<b class='flag-5'>TinyUSB</b>应用:<b class='flag-5'>移植</b>和新增设备(二)