Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
USBHOST 同步传输 PCM270X声卡驱动
发布于 2013-07-14 21:54:23 浏览:3202
订阅该版
例程里驱动没有同步传输,自己加了些代码,能正常使用 因同步传输需在1ms的轮询,系统tick设为10000(不知有没更好的办法,现在CPU占用有点高) 同步传输的传输过程不可被打断,线程优先级要尽量设高些 可以驱动USB PCM270X系列声卡 ```static int susb_iso_xfer(upipe_t pipe, void* buffer, int nbytes, int timeout) { URB_STATE state; rt_uint8_t channel; rt_uint8_t *ptr; rt_uint8_t poll_time; int left = nbytes; int send_bytes; RT_ASSERT(pipe != RT_NULL); RT_ASSERT(buffer != RT_NULL); if(!(root_hub.port_status[0] & PORT_CCS) || (root_hub.port_status[0] & PORT_CCSC)) return -1; ptr = (rt_uint8_t*)buffer; channel = (rt_uint32_t)pipe->user_data & 0xFF; rt_sem_take(&sem_lock, RT_WAITING_FOREVER); /* Sync with start of Even Frame */ while(USB_OTG_IsEvenFrame(&USB_OTG_Core) != TRUE); if(pipe->ep.bEndpointAddress & USB_DIR_IN) { } else { send_bytes = left / 10 + left % 10; while(left > 0) { USBH_IsocSendData(&USB_OTG_Core, ptr, send_bytes, channel); poll_time = HCD_GetCurrentFrame(&USB_OTG_Core); while(1) { state = HCD_GetURB_State(&USB_OTG_Core, channel); // 每个SOF 1ms发送一次,发送后返回 URB_DONE if(state == URB_DONE) break; rt_thread_delay(1); // 让出线程 } while(1) // 轮询时间间隔 { if( HCD_GetCurrentFrame(&USB_OTG_Core) - poll_time >= pipe->ep.bInterval) break; rt_thread_delay(1); // 让出线程 } ptr += send_bytes; left -= send_bytes; send_bytes = nbytes / 10; } } rt_sem_release(&sem_lock); return nbytes; }``` ``` static rt_err_t susb_alloc_pipe(upipe_t* pipe, uifinst_t ifinst, uep_desc_t ep, func_callback callback) { ... if((ep->bmAttributes & USB_EP_ATTR_TYPE_MASK) == USB_EP_ATTR_ISOC) ep_type = EP_TYPE_ISOC; else if((ep->bmAttributes & USB_EP_ATTR_TYPE_MASK) == USB_EP_ATTR_BULK) ep_type = EP_TYPE_BULK; else if((ep->bmAttributes & USB_EP_ATTR_TYPE_MASK) == USB_EP_ATTR_INT) ep_type = EP_TYPE_INTR; else rt_kprintf("unsupported endpoint type "); ... } ``` 这个是USBDAC 驱动 ```/* audio_pcm270x.c By Hover 2013.6.10 */ #include
#include "audio_pcm270x.h" #ifdef RT_USING_USB_HOST #ifdef RT_USB_CLASS_AUDIO_PCM270X static struct uclass_driver audio_pcm270x_driver; static uaudio_pcm270x_xfer_t pcm270x_xfer; /** * This function will open usb audio_pcm270x device * * @param ifinst the interface instance. * * @return the error code, RT_EOK on successfully. */ static rt_err_t rt_usb_audio_pcm270x_open(rt_device_t dev, rt_uint16_t oflag) { struct ureqest setup; uinst_t uinst; int timeout = 100; /* parameter check */ RT_ASSERT(dev != RT_NULL); uinst = ((uifinst_t)dev->user_data)->uinst; setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE; setup.request = USB_REQ_SET_INTERFACE; setup.index = 1; setup.length = 0; setup.value = 1; // pcm270x_xfer = rt_malloc(sizeof(struct uaudio_pcm270x_xfer)); pcm270x_xfer.buff = rt_malloc(PCM270X_MAX_XFER_SIZE); pcm270x_xfer.size = 44100 * (16 * 2 / 8) / 100; pcm270x_xfer.left = 0; rt_memset(pcm270x_xfer.buff, 0, PCM270X_MAX_XFER_SIZE); if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, 0, 0, timeout) == 0) return RT_EOK; else return -RT_FALSE; } /** * This function will close usb audio_pcm270x device * * @param ifinst the interface instance. * * @return the error code, RT_EOK on successfully. */ static rt_err_t rt_usb_audio_pcm270x_close(rt_device_t dev) { struct ureqest setup; uinst_t uinst; int timeout = 100; /* parameter check */ RT_ASSERT(dev != RT_NULL); uinst = ((uifinst_t)dev->user_data)->uinst; setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE; setup.request = USB_REQ_SET_INTERFACE; setup.index = 1; setup.length = 0; setup.value = 0; rt_free(pcm270x_xfer.buff); // rt_free(pcm270x_xfer); if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, 0, 0, timeout) == 0) return RT_EOK; else return -RT_FALSE; } /** * This function will read data from usb audio_pcm270x device * * @param ifinst the interface instance. * * @return the error code, RT_EOK on successfully. */ static rt_size_t rt_usb_audio_pcm270x_read(rt_device_t device, rt_off_t pos, void* buffer, rt_size_t size) { uaudio_pcm270xinst_t audio_pcm270xinst; rt_size_t length; uifinst_t ifinst; /* check parameter */ RT_ASSERT(device != RT_NULL); RT_ASSERT(buffer != RT_NULL); ifinst = (uifinst_t)device->user_data; audio_pcm270xinst = (uaudio_pcm270xinst_t)ifinst->user_data; length = rt_usb_hcd_isoc_xfer(ifinst->uinst->hcd, audio_pcm270xinst->pipe_in, buffer, size, 300); return length; } /** * This function will write data to usb audio_pcm270x device * * @param ifinst the interface instance. * * @return the error code, RT_EOK on successfully. */ static rt_size_t rt_usb_audio_pcm270x_write (rt_device_t device, rt_off_t pos, const void* buffer, rt_size_t size) { uaudio_pcm270xinst_t audio_pcm270xinst; uifinst_t ifinst; rt_uint8_t *ptr = (rt_uint8_t*)buffer; rt_size_t length = size; RT_ASSERT(buffer != RT_NULL); ifinst = (uifinst_t)device->user_data; audio_pcm270xinst = (uaudio_pcm270xinst_t)ifinst->user_data; while(1) { rt_memcpy(pcm270x_xfer.buff + pcm270x_xfer.left, ptr, pcm270x_xfer.size - pcm270x_xfer.left); rt_usb_hcd_isoc_xfer(ifinst->uinst->hcd, audio_pcm270xinst->pipe_out, pcm270x_xfer.buff, pcm270x_xfer.size, 300); ptr += pcm270x_xfer.size - pcm270x_xfer.left; length -= pcm270x_xfer.size - pcm270x_xfer.left; pcm270x_xfer.left = 0; if(length < pcm270x_xfer.size) { pcm270x_xfer.left = length; rt_memcpy(pcm270x_xfer.buff, ptr, pcm270x_xfer.left); break; } } return (size - pcm270x_xfer.left); } /** * This function will control audio_pcm270x device * * @param ifinst the interface instance. * * @return the error code, RT_EOK on successfully. */ static rt_err_t rt_usb_audio_pcm270x_control(rt_device_t dev, rt_uint8_t cmd, void *args) { rt_err_t result = RT_EOK; switch (cmd) { case CMD_PCM_SAMPLERATE: pcm270x_xfer.size = *((rt_uint16_t*) args) * (16 * 2 / 8) / 100; if(pcm270x_xfer.size > PCM270X_MAX_XFER_SIZE) pcm270x_xfer.size = PCM270X_MAX_XFER_SIZE; break; default: result = RT_ERROR; } return result; } /** * This function will run audio_pcm270x class driver when usb device is detected and identified * as a audio_pcm270x class device, it will continue the enumulate process. * * @param arg the argument. * * @return the error code, RT_EOK on successfully. */ static rt_err_t rt_usb_audio_pcm270x_run(void* arg) { int i = 0; uaudio_pcm270xinst_t audio_pcm270xinst; uifinst_t ifinst = (uifinst_t)arg; udev_desc_t dev_desc; rt_err_t ret; /* parameter check */ if(ifinst == RT_NULL) { rt_kprintf("the interface is not available "); return -RT_EIO; } RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_audio_pcm270x_run ")); dev_desc = &ifinst->uinst->dev_desc; if( dev_desc->idVendor == USB_AUDIO_PCM270X_VENDOR_ID && ( dev_desc->idProduct == USB_AUDIO_PCM2704_PRODUCT_ID || dev_desc->idProduct == USB_AUDIO_PCM2706_PRODUCT_ID)) { // if(ifinst->intf_desc->bInterfaceSubClass != 0x02) return -RT_ERROR; RT_DEBUG_LOG(RT_DEBUG_USB, ("found audio pcm%4x device ",dev_desc->idProduct)); } else { RT_DEBUG_LOG(RT_DEBUG_USB, ("not found audio device ")); return -RT_ERROR; } audio_pcm270xinst = rt_malloc(sizeof(struct uaudio_pcm270xinst)); RT_ASSERT(audio_pcm270xinst != RT_NULL); /* initilize the data structure */ rt_memset(audio_pcm270xinst, 0, sizeof(struct uaudio_pcm270xinst)); ifinst->user_data = (void*)audio_pcm270xinst; for(i=0; i
intf_desc->bNumEndpoints; i++) { uep_desc_t ep_desc; /* get endpoint descriptor from interface descriptor */ rt_usb_get_endpoint_descriptor(ifinst->intf_desc, i, &ep_desc); if(ep_desc == RT_NULL) { rt_kprintf("rt_usb_get_endpoint_descriptor error "); return -RT_ERROR; } /* the endpoint type of audio_pcm270x class should be ISOC */ if((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_ISOC) continue; /* allocate pipes according to the endpoint type */ if(ep_desc->bEndpointAddress & USB_DIR_IN) { /* allocate an in pipe for the audio_pcm270x instance */ ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &audio_pcm270xinst->pipe_in, ifinst, ep_desc, RT_NULL); if(ret != RT_EOK) return ret; } else { /* allocate an output pipe for the audio_pcm270x instance */ ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &audio_pcm270xinst->pipe_out, ifinst, ep_desc, RT_NULL); if(ret != RT_EOK) return ret; } } /* check pipes infomation */ if(audio_pcm270xinst->pipe_in == RT_NULL && audio_pcm270xinst->pipe_out == RT_NULL) { rt_kprintf("pipe error, unsupported device "); return -RT_ERROR; } /* set configuration */ ret = rt_usb_set_configure(ifinst->uinst, 1); if(ret != RT_EOK) return ret; /* register audio_pcm270x device */ audio_pcm270xinst->device.type = RT_Device_Class_Sound; audio_pcm270xinst->device.init = RT_NULL; audio_pcm270xinst->device.open = rt_usb_audio_pcm270x_open; audio_pcm270xinst->device.close = rt_usb_audio_pcm270x_close; audio_pcm270xinst->device.read = rt_usb_audio_pcm270x_read; audio_pcm270xinst->device.write = rt_usb_audio_pcm270x_write; audio_pcm270xinst->device.control = rt_usb_audio_pcm270x_control; audio_pcm270xinst->device.user_data = (void*)ifinst; rt_device_register(&audio_pcm270xinst->device, "pcm270xdev", RT_DEVICE_FLAG_RDWR); return RT_EOK; } /** * This function will be invoked when usb device plug out is detected and it would clean * and release all hub class related resources. * * @param arg the argument. * * @return the error code, RT_EOK on successfully. */ static rt_err_t rt_usb_audio_pcm270x_stop(void* arg) { uaudio_pcm270xinst_t audio_pcm270xinst; uifinst_t ifinst = (uifinst_t)arg; RT_ASSERT(ifinst != RT_NULL); RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_audio_pcm270x_stop ")); audio_pcm270xinst = (uaudio_pcm270xinst_t)ifinst->user_data; if(audio_pcm270xinst == RT_NULL) { rt_free(ifinst); return RT_EOK; } if(audio_pcm270xinst->pipe_in != RT_NULL) rt_usb_hcd_free_pipe(ifinst->uinst->hcd, audio_pcm270xinst->pipe_in); if(audio_pcm270xinst->pipe_out != RT_NULL) rt_usb_hcd_free_pipe(ifinst->uinst->hcd, audio_pcm270xinst->pipe_out); /* unregister audio_pcm270x device */ rt_device_unregister(&audio_pcm270xinst->device); /* free audio_pcm270x instance */ if(audio_pcm270xinst != RT_NULL) rt_free(audio_pcm270xinst); /* free interface instance */ rt_free(ifinst); return RT_EOK; } /** * This function will register audio_pcm270x class driver to the usb class driver manager. * and it should be invoked in the usb system initialization. * * @return the error code, RT_EOK on successfully. */ ucd_t rt_usb_class_driver_audio_pcm270x(void) { audio_pcm270x_driver.class_code = USB_CLASS_AUDIO; audio_pcm270x_driver.run = rt_usb_audio_pcm270x_run; audio_pcm270x_driver.stop = rt_usb_audio_pcm270x_stop; return &audio_pcm270x_driver; } #endif #endif ``` ```/* audio_pcm270x.h By Hover 2013.6.10 */ #ifndef __AUDIO_PCM270X_H__ #define __AUDIO_PCM270X_H__ #include
#include
#define PCM270X_MAX_XFER_SIZE 1920 struct uaudio_pcm270x_xfer { int size; int left; rt_uint8_t *buff; }; typedef struct uaudio_pcm270x_xfer uaudio_pcm270x_xfer_t; struct uaudio_pcm270xinst { upipe_t pipe_in; upipe_t pipe_out; struct rt_device device; }; typedef struct uaudio_pcm270xinst* uaudio_pcm270xinst_t; #define USB_AUDIO_PCM270X_VENDOR_ID 0x08BB #define USB_AUDIO_PCM2704_PRODUCT_ID 0x2704 #define USB_AUDIO_PCM2706_PRODUCT_ID 0x2706 #define CMD_PCM_SAMPLERATE 0x01 /* Audio Subclass Code Value SUBCLASS_UNDEFINED 0x00 AUDIOCONTROL 0x01 AUDIOSTREAMING 0x02 MIDISTREMING 0x03 */ #endif ```
查看更多
5
个回答
默认排序
按发布时间排序
aozima
2013-07-14
调网络不抓包,调I2C等时序不上逻辑分析仪,就像电工不用万用表!多用整理的好的文字,比截图更省流量,还能在整理过程中思考。
占位学习。
nongxiaoming
2013-07-15
rt-thread大师兄
不错呢,记得TI这个芯片还带有按键控制功能呢
jeffwei
2013-07-15
这家伙很懒,什么也没写!
这也行啊,一定是你嫌弃st的IIS太烂 [s:175]
bear1
2019-08-16
这家伙很懒,什么也没写!
音乐效果如何啊?
撰写答案
登录
注册新账号
关注者
0
被浏览
3.2k
关于作者
hoverxx
这家伙很懒,什么也没写!
提问
7
回答
5
被采纳
0
关注TA
发私信
相关问题
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
【NXP-MCXA153】 定时器驱动移植
2
GD32F450 看门狗驱动适配
3
【NXP-MCXA153】看门狗驱动移植
4
RT-Thread Studio V2.2.9 Release Note
5
CherryUSB的bootuf2配置
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
freemodbus
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
keil_MDK
msh
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
7
个答案
2
次被采纳
a1012112796
18
个答案
1
次被采纳
Ryan_CW
5
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
本月文章贡献
YZRD
3
篇文章
6
次点赞
catcatbing
3
篇文章
6
次点赞
lizimu
2
篇文章
9
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部