📄 usb_processor.c
字号:
#include "usb_processor.h"
//-------------------------------------------------------------------------*
// 子函数名:USB_ModuleInit(void) *
// 功能描述:USB模块的初始化. *
// 入口参数:无 *
// 返 回:无 *
//-------------------------------------------------------------------------*
void USB_ModuleInit(void)
{
UMCR = 0x4000; //使能模块时钟
// bit 11-Normal PHY operation
// UMCR = 0x00;
// bit 4:SET_DESCRIPTOR不支持
// bit 3:高速
// bit 2:支持过程唤醒
// bit 1:自供电
// bit 0:SYNC_FRAME命令不支持
UIMR = 0x2801;
// bit0:使能SETUPIE
// bit1:使能SETOVRIE
// bit2:使能SOFIE
// bit11:使能URSCIE
// bit12:使能USSCIE
// bit13:使能SETECRIE
UIMR &= 0xbfff; // 确认resume中断标志关
};
void IQUE_Module_Init(void)
{
// 使能IQUE模块, 复位, 3,4通道使用block base
IQUECR = IQUECR_IQUEEN_MASK | IQUECR_QC34DBE_MASK | IQUECR_IQUERST_MASK;
// 使能 force handshake
QC34DSHR = QC34DSHR_DTHE_34_MASK | QC34DSHR_DRHE_34_MASK;
}
//-------------------------------------------------------------------------*
// 子函数名:USB_InitBulkOnlyTransport(void) *
// 功能描述:USB批量传输初始化 -配置1x64字节BULK in 和1x64字节BULK out. *
// 入口参数:无 *
// 返 回:无 *
//-------------------------------------------------------------------------*
void USB_InitBulkOnlyTransport(void)
{
// 选择只有一个配置和一个接口
UEPCSELR = 0x0810;
UUCFGR = 0x00000011;
// 不支持交互
UEPCSELR = 0x0910;
UUCFGR = 0x00000000;
// 配置物理端点1 - 为控制端点
UEPCSELR = 0x0110;
UUCFGR = 0x02000000;
//包的大小为:64字节
//交互为0
//接口为0
//配置为0
//类型为:control
//方向为:IO
//端点数为0
// 清端点1发送和接受DVALID(数据无效)位,
// 清传输完成标志(TFRC),允许传送完成中断(TCIE)
UEPCSR0 = 0x3000;
UEPCSR1 = 0x3000;
if(gUSBFullSpeed)
{
// 配置端点5
UEPCSELR = 0x0510;
UUCFGR = 0x820000D1;
// 包的大小:64字节
// 交互为0
// 接口为0
// 配置为1
// 类型为:BULK
// 方向:IN
// 端点号为1
// 使能通道3,小包,16位访问, 复位
QC3CR = QC3CR_Q3EN_MASK | QC3CR_Q3PRST_MASK;
// 64字节大小,地址 0x20F0 - 0x2130
QC3SZB = 0x3F;
// 配置端点4
UEPCSELR = 0x0410;
// 包的大小:64字节
// 交互为0
// 接口为0
// 配置为1
// 类型为:BULK
// 方向:OUT
// 端点号为1
UUCFGR = 0x820000C1;
// 使能通道1,小包,8位访问, 复位
QC1CR = QC1CR_Q1EN_MASK | QC1CR_Q1PRST_MASK;
// 64字节大小,地址 0x2000 - 0x2040
QC1SZB = 0x30;
}
else
{
// 配置端点5
UEPCSELR = 0x0510;
UUCFGR = 0x900000D1;
// 包的大小:512字节
// 交互为0
// 接口为0
// 配置为1
// 类型为:BULK
// 方向:IN
// 端点号为1
// 512字节大小,地址 0x2200 - 0x2400
QC3SZB = 0x12;
// 使能通道3,大包,16位访问, 复位
QC3CR = QC3CR_Q3EN_MASK | QC3CR_Q316EN_MASK;
// 配置端点4
UEPCSELR = 0x0410;
// 包的大小:512字节
// 交互为0
// 接口为0
// 配置为1
// 类型为:BULK
// 方向:OUT
// 端点号为1
UUCFGR = 0x900000C1;
// 512字节大小,地址 0x2000 - 0x2200
QC1SZB = 0x10;
// 使能通道1,小包,8位访问, 复位
QC1CR = QC1CR_Q1EN_MASK| QC1CR_Q116EN_MASK;
}
//清完成标志位,使能中断
//UEPCSR5A = 0x7800;
do
UEPCSR5A = 0x7800 ;
while(!(UEPCSR5A & 0x4000));
UEPCSR5B = 0x0000;
// 请标志位,开中断
UEPCSR4A = 0x3800;
UEPCSR4B = 0x0000;
// 通道3为USB Rx
QC3REQ = 0x01;
// 通道1为USB Tx
QC1REQ = 0x00;
};
//------------------------------------------------------------------------*
// 子函数名:USB_InitBulkOnlyTransport(void) *
// 功能描述:USB批量传输初始化 -配置1x64字节BULK in 和1x64字节BULK out. *
// 入口参数:无 *
// 返 回:无 *
//------------------------------------------------------------------------*
/*备用
void USB_InitBulkOnlyTransport(void)
{
//选择只有一个配置和一个接口
UEPCSELR_h = 0x08;
UNCIR_h = 0x0000;
UNCIR_l = 0x0011;
// 不支持交互
UEPCSELR_h = 0x09;
UNASR_h = 0x0000;
UNASR_l = 0x0000;
// 配置物理端点1 - 为控制端点
UEPCSELR_h = 0x01;
UEPCSELR_l = 0x10;
UPECFGR_h = 0x0200; //包的大小为:64字节
UPECFGR_l = 0x0000; //交互为0
//接口为0
//配置为0
//类型为:control
//方向为:IO
//端点数为0
// 清端点1发送DVALID(数据无效)位, 清传输完成标志(TFRC),允许传送完成中断(TCIE)
UEPCSR0 = 0x3000;
// 清端点1接受DVALID(数据无效)位, 清传输完成标志(TFRC),允许传送完成中断(TCIE)
UEPCSR1 = 0x3000;
// 配置物理端点2 - 为接受端点
UEPCSELR_h = 0x02;
UPECFGR_h = 0x0200; // 包的大小:64字节
UPECFGR_l = 0x00D1; // 交互为0
// 接口为0
// 配置为1
// 类型为:BULK
// 方向:IN
// 端点号为1
//端点2采用缓冲区UEPLB0, 端点3采用缓冲区UEPLB1
UEPCSELR_l = 0x32;
//清端点2接受DVALID(数据无效)位, 清传输完成标志(TFRC),允许传送完成中断(TCIE)
UEPCSR2 = 0x3000;
//配置物理端点3 - 为发送端点,除了为OUT类型,其余同2端点
UEPCSELR_h = 0x03; // 物理端点3(OUT)
UPECFGR_h = 0x0200; // 包的大小:64字节
UPECFGR_l = 0x00C1; // 交互为0
// 接口为0
// 配置为1
// 类型为BULK
// 方向:OUT
// 端点数为1
//端点2采用缓冲区UEPLB0, 端点3采用缓冲区UEPLB1
UEPCSELR_l = 0x32;
UEPCSR3 = 0x3000;
};
*/
//-------------------------------------------------------------------------*
// 子函数名:USB_DecodeSETUP(volatile UINT8 *p_Packet) *
// 功能描述:解析setup包,根据请求类型,返回相应的描述符 *
// 入口参数:USTB(USB2.0 SETUP数据缓冲区首地址) *
// 返回: 无 *
// 调用方法:USB_DecodeSETUP(&USTB) *
//-------------------------------------------------------------------------*
void USB_DecodeSETUP(volatile UINT8 *p_Packet) {
UINT8 Type;
UINT8 Index;
UINT16 Length, ThisLen;
// 获取包长
Length = (UINT16)(*(p_Packet+wLength_h) <<8) + *(p_Packet+wLength_l);
switch (p_Packet[bRequest])
// 判断请求命令代码(0:GET_STATUS,1:CLEAR_FEATURE,3:SET_FEATURE,
// 5:SET_ADDRESS,6:GET_DESCRIPTOR,7:SET_DESCRIPTOR,
// 8:GET_CONFIGURATION,9:SET_CONFIGURATION,10:GET_INTERFACE,
// 11:SET_INTERFACE,12:SYNCH_FRAME,0xFE:Mass Storage)
{
case GET_DESCRIPTOR:
Type = p_Packet[wValue_h];
Index = p_Packet[wValue_l];
switch (Type)
{
case DEVICE:
ThisLen = USB_GetMin(Device_Descriptor[0],Length);
USB_Move2LocalBuffer((UINT8*) Device_Descriptor,(UINT8*)USB_SetBufferPtr(PHY1IN),ThisLen);
break;
case CONFIGURATION:
ThisLen = USB_GetMin(((UINT16) Configuration_DescriptorHS[3] << 8) | Configuration_DescriptorHS[2],Length);
USB_Move2LocalBuffer((UINT8*)Configuration_Table[gUSBFullSpeed][Index],(UINT8*)USB_SetBufferPtr(PHY1IN),ThisLen);
break;
case STRING:
ThisLen = USB_GetMin(String_Table[Index][0],Length);
USB_Move2LocalBuffer((UINT8*)String_Table[Index],(UINT8*)USB_SetBufferPtr(PHY1IN),ThisLen);
break;
case INTERFACE:
ThisLen = USB_GetMin(Interface_Table[Index-1][0],Length);
USB_Move2LocalBuffer((UINT8*)Interface_Table[Index-1],(UINT8*)USB_SetBufferPtr(PHY1IN),ThisLen);
break;
case ENDPOINT:
ThisLen = USB_GetMin(Endpoint_Table[gUSBFullSpeed][Index-1][0],Length);
USB_Move2LocalBuffer((UINT8*)Endpoint_Table[gUSBFullSpeed][Index-1],(UINT8*)USB_SetBufferPtr(PHY1IN),ThisLen);
SCISendNByte((UINT8*) Endpoint_Table[gUSBFullSpeed][Index-1], ThisLen);
break;
};
do
{
UEPCSR0 = 0x5000 | ThisLen;
}
while (!(UEPCSR0 & 0x4000));
break;
case SET_DESCRIPTOR:
break;
case SYNCH_FRAME:
break;
case SET_ADDRESS:
break;
case GET_STATUS:
break;
case GET_CONFIGURATION:
break;
case SET_CONFIGURATION:
break;
case GET_INTERFACE:
break;
case SET_INTERFACE:
break;
default:
break;
}
}
//-------------------------------------------------------------------------*
// 子函数名:*USB_SetBufferPtr(UINT8 PhyEPNo) *
// 功能描述:使能6个端点的Buffer区指针,返回相应端点对应的当前缓冲区首址 *
// 入口参数:PhyEPNo(端点号) *
// 返回: 当前缓冲区首址 *
// 调用方法:USB_SetBufferPtr(1) *
//-------------------------------------------------------------------------*
volatile UINT8 *USB_SetBufferPtr(UINT8 PhyEPNo) {
switch (PhyEPNo) {
case PHY1IN:
UEPCSELR_l = 0x10; // Select acessing through UEPLB0
return &UEPLB0;
break;
case PHY1OUT:
UEPCSELR_l = 0x10; // Select acessing through UEPLB1
return &UEPLB1;
break;
case PHY2:
UEPCSELR_l = 0x32; // Select acessing through UEPLB0
return &UEPLB0;
break;
case PHY3:
UEPCSELR_l = 0x32; // Select acessing through UEPLB1
return &UEPLB1;
break;
case PHY4:
return &QC1DR_H; // Select QUE channel 1
break;
case PHY5:
return &QC2DR_H; // Select QUE channel 2
break;
case PHY6:
UEPCSELR_l = 0x16; // Select acessing through UEPLB0
return &UEPLB0;
break;
default:
UEPCSELR_l = 0x10; // PHY1IN default to UEPLB0
return &UEPLB0; // PHY1OUT default to UEPLB1
break;
};
};
//-------------------------------------------------------------------------*
// 子函数名:USB_Move2LocalBuffer(*FR_ptr,*TO_ptr,Len) *
// 功能描述:从指针FR_ptr所指向的位置移动长度为len数据到TO_ptr指针所指 *
// 向的当前缓冲区中去,在端点0向PC方发数据时用该函数 *
// 入口参数:FR_ptr:数据原首址,TO_ptr:目的地首址,Len:移动的字数 *
// 返回: 无 *
// 调用方法:USB_Move2LocalBuffer((UINT8*)Configuration_Table *
// [gUSBFullSpeed][Index], *
// (UINT8*)USB_SetBufferPtr(PHY1IN),ThisLen) *
//-------------------------------------------------------------------------*
void USB_Move2LocalBuffer(UINT8 *FR_ptr, UINT8 *TO_ptr, UINT16 Len) {
UINT16 i=0;
for (i=0; i<Len; i=i+2)
{
#ifdef _kUF32isMPW_
*(TO_ptr+i+1) = *(FR_ptr+i);
*(TO_ptr+i) = *(FR_ptr+i+1); // 高位和低位字节交换
#else
*(TO_ptr+i) = *(FR_ptr+i);
*(TO_ptr+i+1) = *(FR_ptr+i+1);
#endif
}
}
//-------------------------------------------------------------------------*
// 子函数名:USB_GetMin(UINT16 Value1, UINT16 Value2) *
// 功能描述:取长度较小的值 *
// 入口参数:Value1和Value2为比较的长度值 *
// 返回: 长度较小的值 *
// 调用方法:USB_GetMin(0x001f, 0x0022),返回值?x001f *
//-------------------------------------------------------------------------*
UINT16 USB_GetMin(UINT16 Value1, UINT16 Value2)
{
if (Value1 > Value2)
return(Value2);
else
return(Value1);
}
void USB_Move2QUE3(UINT8 *FR_ptr, UINT16 Len)
{
UINT16 i=0;
for (i=0; i<Len; i=i+2) {
QC3DR = ( (UINT16) *(FR_ptr+i) << 8) | *(FR_ptr+i+1);
}
}
void USBMS_SetPhyEP5Int(UINT16 Length)
{
do
{
//清发送完成标志位、出错仍然发送、下次发送长度
UEPCSR5A = (1<<TFRC)|(1<<USBTCIE)|(1<<CTERR)|Length;
//UEPCSR5A &= ~(1<<15);
}
//When this bit is set,NAKhandshake will be generated for all transactions assocated with this endpoint.
//It is also recommended to set this bit and NAK all incoming USB traffic addressed to this endpoint
//when the RXSIZ or the associated IQUE channel need to be manipulated by software. When STALL
//is also set, STALL handshake will be sent instead
while (mCheckBit(SNAK,UEPCSR5A));
//This control bit acknowledges the data transmitted from queue channel is consumed. Buffer status
//registers advance when this bit asserts. This bit will be deserted in next cycle automatically.
//Transmitted data of last buffer will be flushed and overrided by next write cycle.
//数据已经准备好,可以发送
mSetBit(RXDA,QC34DTR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -