USB (四)基于 STM32 USB的开发

官网demo
软件代码在官网是存在的:STSW-STM32046
开发板对应的是 		: en.stm32_f105-07_f2_f4_usb-host-device_lib\Project\USB_Device_Examples\AUDIO\readme.txt
基于官网demo考虑的事情
产品特性:
	usb标准
	全速?
	hid?
硬件设计
软件设计
	ST官网提供的usb代码的架构及接口
usb代码的架构及接口

我们在 USB (三)STM32 USB 代码库中写到了usb开发相关的文件,此次以 usb device 开发为例,考虑以下事情

文件为什么按照官方提供的文件夹分类(即ST的usb架构)
USB部分需要哪些文件,缺不缺文件
哪些文件需要修改,怎么改
上位机与下位机通信流程(抓出来) // 其中包括 上位机 对下位机的显示部分
上位机需不需要驱动
上位机有没有通用软件可以控 usb device?如果有,控一下
USB 数据流程
USB中断
// OUT 是 host -> device , 是以 host 为 目标 说的
// IN  是 host <- device
// 异常向量表中 有 一下 异常入口 需要实现
OTG_HS_EP1_OUT_IRQHandler	; USB OTG HS End Point 1 In  
	//当上位机发送数据时,中断产生
OTG_HS_EP1_IN_IRQHandler	; USB OTG HS End Point 1 Out 
	//当下位机发送数据时,中断产生
OTG_HS_WKUP_IRQHandler
	// 目前没有实现
OTG_HS_IRQHandler
	// 发生了很多次

STM32F40X的与OTG相关的异常向量表如下

OTG_FS_WKUP_IRQHandler		// USB OTG FS Wakeup through EXTI line interrupt  // stm32 官方库的例子有些会 enable
						// 参考 STM32_USB-Host-Device_Lib_V2.2.0/Project/USB_Device_Examples/Composite_Examples/MSC_HID_Composite/src/stm32fxxx_it.c
OTG_FS_IRQHandler 			// USB OTG FS global Interrupt

OTG_HS_WKUP_IRQHandler 		// USB OTG HS Wakeup through EXTI interrupt // stm32 官方库的例子有些会 enable
OTG_HS_IRQHandler			// USB OTG HS global interrupt
	// 参考 https://blog.csdn.net/sinat_20006769/article/details/79081244
--- 这两个 FS 和 HS 通用
OTG_HS_EP1_OUT_IRQHandler	// USB OTG HS End Point 1 Out global interrupt
OTG_HS_EP1_IN_IRQHandler	// USB OTG HS End Point 1 In global interrupt

所以 组合有两种
FS : OTG_FS_IRQHandler & OTG_FS_WKUP_IRQHandler & OTG_HS_EP1_OUT_IRQHandler & OTG_HS_EP1_IN_IRQHandler	
HS : OTG_HS_IRQHandler & OTG_HS_WKUP_IRQHandler & OTG_HS_EP1_OUT_IRQHandler & OTG_HS_EP1_IN_IRQHandler	

各个中断的发生时刻
	只要插上usb ,就会一直 有 OTG_HS_IRQHandler		 	会进入	 // 断开就没有了
	上位机发送数据给 下位机, OTG_HS_EP1_OUT_IRQHandler 	才会进入
	下位机发送数据给 上位机, OTG_HS_EP1_IN_IRQHandler 	才会进入

枚举 复位 挂起 唤醒
  • OTG_HS_WKUP_IRQHandler
唤醒应该在 	 	OTG_HS_WKUP_IRQHandler  // TODO
  • OTG_HS_IRQHandler
	
OTG_HS_IRQHandler -> 
USBD_OTG_ISR_Handler
	DCD_HandleUSBSuspend_ISR // 拔掉usb动作1
		USBD_DCD_INT_fops->Suspend (pdev);    // 即 USBD_DCD_INT_cb->Suspend // 即 USBD_Suspend
			pdev->dev.usr_cb->DeviceSuspended(); // 即 USR_cb-> DeviceSuspended // 即 USBD_USR_DeviceSuspended
				
	DCD_OTG_ISR				// 拔掉usb动作2
		USBD_DCD_INT_fops->DevDisconnected (pdev);
			USBD_USR_DeviceDisconnected
			
	DCD_SessionRequest_ISR	// 连接动作1
		USBD_DCD_INT_fops->DevConnected (pdev);
			USBD_USR_DeviceConnected
	
	DCD_HandleUsbReset_ISR	// 连接动作2
		USBD_DCD_INT_fops->Reset(pdev);
			USBD_USR_DeviceReset

	DCD_HandleOutEP_ISR		// 连接动作3
		USBD_DCD_INT_fops->SetupStage(pdev); // 即USBD_SetupStage
			USBD_StdDevReq
				USBD_GetDescriptor // 获取描述符
					pbuf = pdev->dev.usr_device->GetDeviceDescriptor(pdev->cfg.speed, &len);
					USBD_CtlSendData (pdev,pbuf,len);
				USBD_SetConfig
					USBD_SetCfg
						USBD_DCD_INT_fops->DeviceConfigured(pdev); 
							USBD_USR_DeviceConfigured
	DCD_HandleResume_ISR	// 没调用过
		...
			USBD_USR_DeviceResumed 

TODO : USBD_USR_DeviceResumed 在什么是时候 被调用 
usb device 收数据 以 MSC 为例
  • OTG_HS_EP1_OUT_IRQHandler
OTG_HS_EP1_OUT_IRQHandler
	USBD_OTG_EP1OUT_ISR_Handler
		USBD_DCD_INT_fops->DataOutStage(pdev , 1);   //即USBD_DataOutStage 
													 //usb device 库 中的 core  部分  usbd_core.c  决定了 这个 函数指针的值
			pdev->dev.class_cb->DataOut(pdev, epnum);//即USBD_MSC_DataOut  
													 //sb device 库 中的 class 部分 usbd_msc_core.c 提供了 USBD_MSC_DataOut
													 //在 USBD_Init 中被指定
				MSC_BOT_DataOut
					gUsbRecPacket.DataPtr = pdev->dev.out_ep[1].xfer_buff;
					gUsbRecPacket.Len = pdev->dev.out_ep[1].xfer_count;
					g_Req ++;
usb device 发数据 以 MSC 为例
  • OTG_HS_EP1_IN_IRQHandler
// 1. 产生中断(是发送完时产生的中断)
DCD_EP_Tx(&USB_OTG_dev, MSC_IN_EP, ptr, len); // ptr 为 数据起始地址, len 为长度
	USB_OTG_EPStartXfer(pdev, ep );
		USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPTSIZ, deptsiz.d32);
		
		USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, 0, fifoemptymsk);
		// 开启传输, 下面就会进入 OTG_HS_EP1_IN_IRQHandler 中断
		USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPCTL, depctl.d32);


// 2. 实际发送过程,
// 是硬件自己做的

// 3. 发送完成时的中断
OTG_HS_EP1_IN_IRQHandler
	USBD_OTG_EP1IN_ISR_Handler (&USB_OTG_dev);
		USBD_DCD_INT_fops->DataInStage(pdev , 1); // 即 USBD_DataInStage
			pdev->dev.class_cb->DataIn(pdev, epnum);  // 即USBD_MSC_DataIn
				MSC_BOT_DataIn
					gSentCount++;

应用处理流程
收 是 中断收的
发 是 拷贝数据到FIFO中,然后让硬件发的,硬件发完会产生中断

如果要 在 应用中 通过 usb 收发数据,怎么弄
	1. "中断收完了" 需要让应用知晓 , 然后 应用 去 处理 收到的 usb数据(在全局变量中)
	2. 发数据的时候, 直接 写 硬件寄存器 "驱使硬件自动发送" , 然后等待 "处理完成中断" 就行了

stm32f405 有 一个 端点 : EL1 , 有没有 EL0 ? // 好像EL1 是 默认可用的

端点,实际上是设备硬件上具有一定大小的数据缓冲区。
USB系统中,每一个端点都有唯一的地址,是有设备地址和端点号给出的。
	// TODO 默认设置端点0用作控制传输端点,其他端点必须在设备被主机配置后才能使用。

端点可以描述为数据源或接收器,并且仅存在于USB设备中。
可以从USB主机接收或等待将其存储在端点上的数据。
可以将端点配置为USB规范中定义的四种传输类型之一(控制传输,中断传输,同步传输和批量传输)。
在硬件限制内,可以使用USB协议栈配置端点(例如,将端点限制为某种传输类型)。
	例如
	EP0(控制传输,双向,0x00,0x80),
	EP1(批量传输,双向,0x01,0x81),
	EP2(同步传输,双向,0x02,0x82)。

端点充当一种缓冲区。
	设备收数据
	USB主机的客户端可以将数据发送到端点1。
	来自USB主机的数据将发送到OUT端点1。
	准备就绪后,微控制器上的程序将立即读取数据。
	
	设备发数据
	由于程序无法自由访问USB总线(USB总线由USB主机控制),因此必须将返回数据写入IN端点1。
	IN端点1中的数据将保留在那里,直到主机向端点1发送一个IN数据包以请求数据为止。


  一个设备最多可以有16个OUT和16个IN端点。// 端点的总数和每个端点支持的功能由硬件定义。
  每个端点只能有一个传输方向。// TODO?
  端点 0仅用于控制传输,不能分配任何其他功能。// TODO?
  OUT始终是指从主机指向设备的方向。
  IN始终指指向主机的方向。
其他
描述符
USBD_DEVICE USR_desc =
{
  USBD_USR_DeviceDescriptor, 		// 返回 VID和PID , 设备类在这里吗 ? TODO
  USBD_USR_LangIDStrDescriptor, 
  USBD_USR_ManufacturerStrDescriptor,
  USBD_USR_ProductStrDescriptor,	// 返回 设备名
  USBD_USR_SerialStrDescriptor,
  USBD_USR_ConfigStrDescriptor,
  USBD_USR_InterfaceStrDescriptor,
};

 USBD_Init(&USB_OTG_dev,USB_OTG_HS_CORE_ID,&USR_desc,&USBD_MSC_cb,&USR_cb);
	pdev->dev.class_cb = class_cb;
 	pdev->dev.usr_cb = usr_cb;  
  	pdev->dev.usr_device = pDevice;  

USBD_SetupStage
	USBD_StdDevReq
		USBD_GetDescriptor
			pbuf = pdev->dev.usr_device->GetDeviceDescriptor(pdev->cfg.speed, &len);
		    USBD_CtlSendData (pdev,pbuf,len);
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值