ADI Blackfin DSP处理器-BF533的开发详解25:USB接口设计(含源代码)

news2024/11/15 1:53:13

硬件准备

ADSP-EDU-BF533:BF533开发板
AD-HP530ICE:ADI DSP仿真器

软件准备

Visual DSP++软件

硬件链接

在这里插入图片描述

硬件设计原理图

在这里插入图片描述

功能介绍

跟网口一样,USB这个设计很勉强,因为BF533并不带USB口,当时是给一个大厂做MP4的方案,人家要求用BF533,我们没得选的情况下,弄了一个这样的设计,再去在裸核下移植USB协议,很是复杂费劲,当初做这个项目真是让我头发都白了三根!

这个设计就当原理看就行,纯属理论学习,放到现在已经没有啥实际意义了。现在让我做这个项目,我肯定就直接选带USB接口的IC啦。

ADSP-EDU-BF53x 板卡上设计了一个 USB1.1 标准的 USB 设备芯片,其型号为 PDIUSBD12,该芯片有 6 个数据传输断点,其控制命令简单,寄存器少,适合于广大初学者学习 USB 协议。ADSP-BF53x 处理器通过 EBIU 接口的 BANK3 连接 PDIUSBD12 芯片,通过 CPLD 为其分配访问地址,通过 CPLD 的 USB_DAT 寄存器和 USB_CMD

寄存器进行访问。

USB_DAT 寄存器(读写):
USB_DAT 寄存器地址:0x20300000
USB_DAT 寄存器:该寄存器用于发送和读出 PDIUSBD12 端点的数据。

USB_CMD 寄存器(写唯一):
USB_CMD 寄存器地址:0x20300040
USB_CMD 寄存器:该寄存器用于发送 PDIUSBD12 的指令。

硬件连接示意图

在这里插入图片描述

代码实现功能

代码实现了 USB 设备的枚举和大容量存储器盘符出现的功能。运行代码后,将 MINIUSB 连接线连接板卡的MINIUSB 接口,这时计算机端会出现有 USB 设备接入,板卡上的 USB GL 指示灯会不停的闪烁,待枚举完成后,
在计算机端会出现一个磁盘符号。由于代码还没有做完善,我们不能对该磁盘符号做任何的操作。

将串口设置波特率 9600,打开超级终端,可以看到 USB 与计算机通讯的数据信息。也可使用 USB 抓包工具抓举更详细的数据信息。

注意:必须先运行代码,然后再将 USB 线接入计算机,否则不会产生硬件响应。

在这里插入图片描述

调试步骤

1. 将仿真器(ICE)与 ADSP-EDU-BF53x 开发板和计算机连接好。
2. 先给 ADSP-EDU-BF53x 开发板上电,再为仿真器(ICE)上电。
3. 运行 VisualDSP++ 软件,选择合适的 BF533 的 session 将仿真器与软件连接。
4. 加载 VisualDSP++ 5.0 工程文件 BF53x_USB,编译并全速运行。
5. 采用 MINIUSB 线连接计算机和板卡。

调试结果

在计算机端能看到有 USB 设备接入的提示,等待片刻后能在计算机端看到有 USB 设备接入。
在这里插入图片描述

超级终端上打印的 USB 数据包信息

在这里插入图片描述

在这里插入图片描述

计算机端发现 USB 设备接入,识别出是一个磁盘驱动器。

在这里插入图片描述

设备管理器中大容量存储器被识别。

在这里插入图片描述

计算机端显示盘符。

程序源码

cpu.c

#include <cdefBF533.h>

void Set_PLL(unsigned int pmsel,unsigned int pssel)
{
unsigned int new_PLL_CTL;
*pPLL_DIV = pssel;
asm(“ssync;”);
new_PLL_CTL = (pmsel & 0x3f) << 9;
*pSIC_IWR |= 0xffffffff;
if (new_PLL_CTL != *pPLL_CTL)
{
*pPLL_CTL = new_PLL_CTL;
asm(“ssync;”);
asm(“idle;”);
}
}

void Init_EBIU(void)
{
*pEBIU_AMBCTL0 = 0x7bb07bb0;
*pEBIU_AMBCTL1 = 0xffc0ffc0;
*pEBIU_AMGCTL = 0x000f;
}

void delay(int count)
{
int i;
for(i=0;i<count;i++)
asm(“ssync;”);
}

d12int.c

#include <cdefBF533.h>
#include “DataType.h”
#include “D12Def.h”
#include “USBDesc.h”
#include “MASS.H”

void delay(int count);

static U8 usb_remote_wake;
static U8 usb_config;
static U8 UsbSendDescF;

static int send_remain;
static U32 send_ptr;

CBW cbw;
CSW csw;

U8 UsbInit()
{
UsbSendDescF = 0;

if(D12RdChipId()!=0x1210 )
	return STATUS_ERR;

D12SetDma(MyD12DmaCfg);
if(D12GetDma()!=MyD12DmaCfg)
	return STATUS_ERR;

D12SetMode(MyD12EpCfgOff, D12Pll24M);
delay(20000);
D12SetMode(MyD12EpCfgOn, D12Pll24M);

return STATUS_OK;

}

#define UsbDevDescType 1
#define UsbCfgDescType 2
#define UsbStrDescType 3
#define UsbItfDescType 4
#define UsbEndpDescType 5
#define UsbPwrDescType 6

#define UsbDevDescSize 18
#define UsbCfgDescSize 9
#define UsbItfDescSize 9
#define UsbEndpDescSize 7

//#define UsbStrDescSize 15

#define UsbEndpControl 0
#define UsbEndpIsochronous 1
#define UsbEndpBulk 2
#define UsbEndpInterrupt 3

#define UsbClassMassStorage 8

#define UsbSubClassRbc 1
#define UsbSubClassSff8020i 2
#define UsbSubClassQic157 3
#define UsbSubClassUfi 4
#define UsbSubClassSff8070i 5
#define UsbSubClassScsi 6

#define UsbProtocolCbi0 0
#define UsbProtocolCbi1 1
#define UsbProtocolBulk 0x50

#define UsbLanguage_ID 0 //语言ID描述符字符串索引
#define UsbManufacturer 2 //厂商描述符字符串索引
#define UsbProduct 3 //产品描述符字符串索引
#define UsbSerialNumber 4 //设备序列号字符串索引
#define UsbConfiguration 5 //配置字符串描述符索引
#define UsbInterface 6 //接口字符串描述符索引


#define Ep0PacketSize 16
#define Ep2PacketSize 64
#define EndpCnt 2
#define UsbTotalCfgDescSize UsbCfgDescSize+UsbItfDescSize+EndpCnt*UsbEndpDescSize//+15 //9 + 9 + 2 * 7
struct __packed {
UsbDevDesc DevDesc;
U8 CfgDesc[9];
U8 ItfDesc[9];
U8 Endp4Desc[7];
U8 Endp5Desc[7];
U8 Language_ID[4]; //字符串语言ID描述符字符串
U8 Manufacturer[18]; //厂商描述符字符串
U8 Product[28]; //产品描述符字符串
U8 SerialNumber[18]; //设备序列号字符串
U8 Configuration[24]; //配置字符串描述符
U8 Interface[24]; //接口字符串描述符
}ThisDevDesc =
{
{ //设备描述符
UsbDevDescSize, //18
UsbDevDescType, //1
0x0110, //版本号1.1
0, //设备类型
0, //设备子类型
0, //协议 见109页
Ep0PacketSize, //16
0x471,//0x7104, //供应商 ID
0xf0ff,// 0x222, //产品ID 决定计算机出现什么样的图标
0x113, //0x0100, //设备出厂编码
UsbManufacturer,// 100, //厂商描述符字符串索引
UsbProduct,//101, //产品描述符字符串索引
UsbSerialNumber,//102,// 0x02, // 0, //设备序列号字符串索引
1 //可能的配置数

				},
				{									//配置描述符
					UsbCfgDescSize,		//9			//描述符大小
					UsbCfgDescType,		//2			//配置描述符类型 2	
					UsbTotalCfgDescSize,	//32	//返回整个数据的长度 2个字节
					0,								//同上
					1,								//配置所支持的接口数
					1,								//set config 参数选择配置值
					UsbConfiguration,//103,			//用于描述该配置字符串描述符的索引
					0x80,							//配置特性为总线供电
					0x32							//总线供电最大电流
				},
				{									//接口描述符
					UsbItfDescSize,		//9			//接口描述符大小
					UsbItfDescType,		//4			//接口描述符类型  4
					0,								//接口编号
					0,								//用于为上一个字段选择可替换的位置
					EndpCnt,		//2				//使用的端点数目
					UsbClassMassStorage,	//8		//接口类型代码 8 大容量存储设备
					6,	//UsbSubClassUfi,		//4			//接口类型子代码		 ************************	
					UsbProtocolBulk,	//0x50		//协议代码  0x50 单批量传输协议
					UsbInterface//105	//	0								//字符串描述符索引
						
				},
				{									//端点4描述符
					UsbEndpDescSize,	//7			//端点描述符长度
					UsbEndpDescType,	//5			//端点描述符类型  5
					0x82,							//USB设备的端点地址   0x82代表为输入端点
					UsbEndpBulk,		//2			//端点属性  2为批量
					Ep2PacketSize,		//64		//端点大小 2字节
					0,								//端点大小
					0								//轮寻数据传出端点的时间
				},
				{									//端点5描述符
					UsbEndpDescSize,	//7
					UsbEndpDescType,	//5
					0x2,							//输出端点
					UsbEndpBulk,		//2
					Ep2PacketSize,		//64
					0,
					0
				},
				{									//字符串描述符 LANGUAGE_ID 
					4,		//4						//字符串描述符大小
					UsbStrDescType,		//3			//字符串描述符类型	
												//LANGUAGE_ID 
					0x04,
					0x09,	
				},
				{	
					18,								//厂商描述符字符串				
					UsbStrDescType,
					'A',0,'D',0,'S',0,'P',0,'B',0,'F',0,'5',0,'3',0
				},
				{	
					26,								//产品描述符字符串索引
					UsbStrDescType,
					'A',0,'N',0,'D',0,'Y',0,'R',0,'E',0,'N',0,'-',0,'U',0,'D',0,'a',0,'s',0,'k',0,
				},
				{									//设备序列号字符串
					18,		//18				//字符串描述符大小
					UsbStrDescType,		//3			//字符串描述符类型	
					0x32,0x00,0x30,0x00,0x37,0x00,0x31,0x00,0x30,0x00,0x39,0x00,0x38,0x00,0x32,0x00
				},	
				{	
					24,								///配置字符串描述符
					UsbStrDescType,
					'P',0,'H',0,'I',0,'L',0,'I',0,'S',0,'P',0,'-',0,'D',0,'1',0,'2',0
				},					
				{	
					24,								///接口字符串描述符
					UsbStrDescType,
					'U',0,'S',0,'B',0,'1',0,'.',0,'1',0,'-',0,'A',0,'D',0,'S',0,'P',0
				},	
			};

/****************** standard device request ****************/
U8 UsbGetStatus(U8 *SetupPkt)
{
if(SetupPkt[2]|SetupPkt[3]|SetupPkt[5]|SetupPkt[7])
return 1;
if(SetupPkt[6]!=2)
return 1;
if(SetupPkt[0]==0x80)
{
if(SetupPkt[4])
return 1;
SetupPkt[0] = usb_remote_wake?1:0;
SetupPkt[1] = 0;
}
else
if(SetupPkt[0]==0x81)
{
if(SetupPkt[4])
return 1;
SetupPkt[0] = 0;
SetupPkt[1] = 0;
}
else
if(SetupPkt[0]==0x82)
{
D12SelEp((SetupPkt[4]*2)|((SetupPkt[4]&0x80)?1:0));
SetupPkt[1] = (D12Dat&2)?1:0;
SetupPkt[0] = 0;
}
else
return 1;

D12WrEp(1, SetupPkt, 2);
	delay(100);
return 0;		

}

U8 UsbClrFeature(U8 *SetupPkt)
{

if(SetupPkt[0]&0x80)
	return STATUS_ERR;
if(SetupPkt[3]|SetupPkt[5]|SetupPkt[6]|SetupPkt[7])	
	return STATUS_ERR;
	
if(SetupPkt[0]&0x1f)
{
	if((SetupPkt[0]&0x1f)!=2)
		return STATUS_ERR;
	D12SetEpStat((SetupPkt[4]*2)|((SetupPkt[4]&0x80)?1:0),0);
}
else
{
	if(SetupPkt[4])
		return STATUS_ERR;
	usb_remote_wake = 0;
}

D12WrEp(1, SetupPkt, 0);
	delay(100);
return STATUS_OK;

}

U8 UsbSetFeature(U8 *SetupPkt)
{
if(!(SetupPkt[0]&0x80))
return STATUS_ERR;
if(SetupPkt[3]|SetupPkt[5]|SetupPkt[6]|SetupPkt[7])
return STATUS_ERR;

if(SetupPkt[0]&0x1f)
{
	if((SetupPkt[0]&0x1f)!=2)
		return STATUS_ERR;
	D12SetEpStat((SetupPkt[4]*2)|((SetupPkt[4]&0x80)?1:0),1);
}
else
{
	if(SetupPkt[4])
		return STATUS_ERR;
	usb_remote_wake = 1;
}

D12WrEp(1, SetupPkt, 0);
	delay(100);
return STATUS_OK;

}

U8 UsbSetAddress(U8 *SetupPkt)
{

if(SetupPkt[0]|SetupPkt[3]|SetupPkt[4]|SetupPkt[5]|SetupPkt[6]|SetupPkt[7])
	return STATUS_ERR;
	
D12SetAddr(SetupPkt[2]|0x80);
	delay(100);
D12WrEp(1, SetupPkt, 0);
	delay(100);
return STATUS_OK;	

}

void UsbSendDesc()
{
U8 i;

UsbSendDescF = send_remain>=Ep0PacketSize;	
D12WrEp(1, (U8 *)send_ptr, (send_remain>Ep0PacketSize)?Ep0PacketSize:send_remain);
	delay(100);
U_printf("SendDesc is:");	

for(i=0; i<((send_remain>Ep0PacketSize)?Ep0PacketSize:send_remain); i++)
	U_printf("%x,", *(U8 *)(send_ptr+i));	
	U_printf("\n\r");	
send_remain -= Ep0PacketSize;
send_ptr    += Ep0PacketSize;

}

U8 UsbGetDescriptor(U8 *SetupPkt)
{

if(SetupPkt[0]!=0x80)
	return STATUS_ERR;
	
switch	(SetupPkt[3])
{
case UsbDevDescType:						//
	send_ptr = (U32)&ThisDevDesc;
	send_remain = UsbDevDescSize;
	break;
case UsbCfgDescType:
	send_ptr = (U32)&ThisDevDesc.CfgDesc;
	send_remain = UsbTotalCfgDescSize;
	break;

case UsbStrDescType:	
	if(SetupPkt[2]==UsbLanguage_ID)
	{
		send_ptr = (U32)&ThisDevDesc.Language_ID;
		send_remain = 4;
	}
	else if(SetupPkt[2]==UsbManufacturer)
	{
		send_ptr = (U32)&ThisDevDesc.Manufacturer;
		send_remain = 18;
	}
	else if(SetupPkt[2]==UsbProduct)
	{
			send_ptr = (U32)&ThisDevDesc.Product;
			send_remain = 28;
	}
	else if(SetupPkt[2]==UsbSerialNumber)
	{
			send_ptr = (U32)&ThisDevDesc.SerialNumber;
			send_remain = 18;
	}
	else if(SetupPkt[2]==UsbConfiguration)
	{
			send_ptr = (U32)&ThisDevDesc.Configuration;
			send_remain = 24;
	}
	else if(SetupPkt[2]==UsbInterface)
	{
			send_ptr = (U32)&ThisDevDesc.Interface;
			send_remain = 24;
	}
	/*
	switch(SetupPkt[2])
	{
		case UsbLanguage_ID:
			send_ptr = (U32)&ThisDevDesc.Language_ID;
			send_remain = 4;
			break;
		case UsbManufacturer:
			send_ptr = (U32)&ThisDevDesc.Manufacturer;
			send_remain = 18;
			break;			
		case UsbProduct:
			send_ptr = (U32)&ThisDevDesc.Product;
			send_remain = 28;
			break;			
		case UsbSerialNumber:
			send_ptr = (U32)&ThisDevDesc.SerialNumber;
			send_remain = 18;
			break;		
		case UsbConfiguration:
			send_ptr = (U32)&ThisDevDesc.Configuration;
			send_remain = 24;
			break;			
		case UsbInterface:
			send_ptr = (U32)&ThisDevDesc.Interface;
			send_remain = 24;
			break;	
		default:
			break;			
	}	
	*/
	break;		
default:
	return STATUS_ERR;	
}

// U_printf(“send_ptr is %x\n”,send_ptr);
// U_printf(“send_remain is %x\n”,send_remain);

if(!SetupPkt[7]&&(SetupPkt[6]<send_remain))
	send_remain = SetupPkt[6];

UsbSendDesc();	
	delay(100);
return STATUS_OK;	

}

U8 UsbGetConfiguration(U8 *SetupPkt)
{
if(SetupPkt[0]!=0x80)
return STATUS_ERR;
if(SetupPkt[2]|SetupPkt[3]|SetupPkt[4]|SetupPkt[5]|SetupPkt[7])
return STATUS_ERR;
if(SetupPkt[6]!=1)
return STATUS_ERR;

SetupPkt[0] = usb_config?1:0;
D12WrEp(1, SetupPkt, 1);	
	delay(100);
return STATUS_OK;	

}

U8 UsbSetConfiguration(U8 *SetupPkt)
{
if(SetupPkt[0]|SetupPkt[3]|SetupPkt[4]|SetupPkt[5]|SetupPkt[6]|SetupPkt[7])
return STATUS_ERR;
if(SetupPkt[2]&0xfe)
return STATUS_ERR;

usb_config = SetupPkt[2]&1;
D12SetEp(usb_config);
	delay(100);
D12SetEpStat(4, usb_config^1);
	delay(100);
D12SetEpStat(5, usb_config^1);
	delay(100);
D12WrEp(1, SetupPkt, 0);
	delay(100);
return STATUS_OK;	

}

U8 UsbGetInterface(U8 *SetupPkt)
{
if(SetupPkt[0]!=0x81)
return STATUS_ERR;
if(SetupPkt[2]|SetupPkt[3]|SetupPkt[4]|SetupPkt[5]|SetupPkt[7])
return STATUS_ERR;
if(SetupPkt[6]!=1)
return STATUS_ERR;

SetupPkt[0] = 0;
D12WrEp(1, SetupPkt, 1);
return STATUS_OK;

}

U8 UsbSetInterface(U8 *SetupPkt)
{
return STATUS_ERR;
}

U8 UsbReserved(U8 *SetupPkt)
{
return STATUS_ERR;
}

U8 (*StdDevReq[])(U8 *SetupPkt) = {
UsbGetStatus, //0
UsbClrFeature, //1
UsbReserved, //2
UsbSetFeature, //3
UsbReserved, //4
UsbSetAddress, //5
UsbGetDescriptor, //6
UsbReserved, //7
UsbGetConfiguration,//8
UsbSetConfiguration,//9
UsbGetInterface, //A
UsbSetInterface, //B
UsbReserved, //C
UsbReserved, //D
UsbReserved, //E
UsbReserved //F
};

void mass_storage_reset(void) //USB大容量存储设备复位
{
D12WrEp(1,0,0);
// USB_usb_endp0_in=0;
//USB_setup_packet_out=0;
// SCSI_Command=1;
// SCSI_Data=0;
}

void Return_CSW(unsigned long int DataResidue,unsigned char status) //返回CSW数据包
{

csw.dCSWTag=cbw.dCBWTag; //将命令块封包中的标签
csw.dCSWDataResidue=DataResidue;//将长度差别传到命令状态封包
csw.bCSWStatus=status; //将状态送入命令状态封包

}

/********************** D12 interrupt process ******************/
void D12Ep0IntProc()
{
U8 SetupPkt[8];
U8 i;

UsbSendDescF = 0;

D12RdLastTrStat(0);
	delay(100);
if(D12Cmd&0x20)			
	if(D12RdEp(0, SetupPkt, 8)==8)
	{
			delay(100);
		D12AckEp(0);
			delay(100);
		D12AckEp(1);
			delay(100);
		U_printf("\n\r");
		U_printf("device request: ");
	//	putch('\n');
		for(i=0; i<8; i++)
			U_printf("%x,", SetupPkt[i]);
		U_printf("\n\r");	
		if(!StdDevReq[SetupPkt[1]&0xf](SetupPkt));	//UsbClrFeature
			return;
	}
				
D12SetEpStat(0, D12EpStall);
	delay(100);
D12SetEpStat(1, D12EpStall);
	delay(100);		

}

void D12Ep1IntProc()
{
U8 i;

i = D12RdLastTrStat(1);
	delay(100);
if(UsbSendDescF)
	UsbSendDesc();
		delay(100);

}

void D12Ep2IntProc()
{
D12SetEpStat(2, D12EpStall);
delay(100);
}

void D12Ep3IntProc()
{
D12SetEpStat(3, D12EpStall);
delay(100);
}

void D12Ep4IntProc() //PC向接口输出
{
U8 i;

U8 size;
U8 Ep2OutBuf[Ep2PacketSize];

D12RdLastTrStat(4);	
	delay(100);
BulkOut();

}

void D12Ep5IntProc() //接口向PC输入
{
BulkIn();
}

void D12BusRstProc()
{
}

void D12SuspChgProc()
{
}

d12op.c

#include “DataType.h”
#include “D12Def.h”

void D12SetEpStat(U8 Ep,U8 Stat)
{
delay(1000);
D12Cmd = Ep+0x40;
delay(1000);
D12Dat = Stat;
delay(1000);
}

void D12SetAddr(U8 Addr)
{
delay(1000);
D12Cmd = 0xd0;
delay(1000);
D12Dat = Addr;
delay(1000);
}

void D12SetEp(U8 Val)
{
delay(1000);
D12Cmd = 0xd8;
delay(1000);
D12Dat = Val;
delay(1000);
}

void D12SetDma(U8 Dma)
{
delay(1000);
D12Cmd = 0xfb;
delay(1000);
D12Dat = Dma;
delay(1000);
}

void D12SetMode(U8 Val1, U8 Val2)
{
delay(1000);
D12Cmd = 0xf3;
delay(1000);
D12Dat = Val1;
delay(1000);
D12Dat = Val2;
delay(1000);
}

void D12SendResume()
{
delay(1000);
D12Cmd = 0xf6;
delay(1000);
}

void D12AckEp(U8 Ep)
{
delay(1000);
D12Cmd = Ep;
delay(1000);
D12Cmd = 0xf1;
delay(1000);
if(!Ep)
D12Cmd = 0xf2;
}

U32 D12RdChipId()
{
U32 tmp;

D12Cmd = 0xfd;
delay(1000);

tmp = D12Dat;
delay(1000);

tmp = tmp<<8|D12Dat;		
return tmp;	

}

U8 D12GetDma()
{
delay(1000);
D12Cmd = 0xfb;
delay(1000);
return D12Cmd;
}

U8 D12RdEp(U8 Ep,U8 buf[],U8 cnt)
{
U8 tmp;
delay(1000);
D12SelEp(Ep);
delay(1000);
if(D12Cmd&1)
{
D12Cmd = 0xf0;
delay(1000);
tmp = D12Cmd;
delay(1000);
tmp = D12Cmd;
delay(1000);
if(tmp<cnt)
cnt = tmp;
tmp = cnt;
while(cnt)
{
*buf++ = D12Cmd;
delay(1000);
cnt–;
}
D12Cmd = 0xf2;
delay(1000);
return tmp;
}
else
return 0;
}

void D12WrEp(U8 Ep, U8 buf[], U8 cnt)
{
while(1)
{
D12SelEp(Ep);
delay(1000);
if(!(D12Cmd&1))
break;
}
delay(1000);
D12Cmd = 0xf0;
delay(1000);
D12Dat = 0;
delay(1000);
D12Dat = cnt;
delay(1000);
while(cnt)
{
D12Dat = *buf++;
delay(1000);
cnt–;
}
D12Cmd = 0xfa;
delay(1000);
}

U8 D12RdInt()
{
delay(1000);
D12Cmd = 0xf4;
delay(1000);
return D12Cmd;

}

ufi.c

#include <cdefbf53x.h>
#include “DataType.h”
#include “D12Def.h”
#include “USBDesc.h”

/Flash相关********/
#define DISK_ADDRESS 0x00040000 //模拟U盘位于Flash 512k处

#define READ_DISK(addr) ((U16)((DISK_ADDRESS+addr)<<1))
#define ERASE_SECTOR(addr) Erase_Sector(DISK_ADDRESS+addr)
#define PROGRAM_SECTOR(src,dst) Program_Sector(src,DISK_ADDRESS+dst)
#define DISK_BUFFER_SIZE SECTOR_SIZE_1601*2

//andy
/****************************************************************************/
#define FALSE 0
#define TRUE 1

#define SECTOR_SIZE_1601 2048
/*****************************************************************************/

//
#define MAX_PACKAGE_SIZE 64
#define ReadPipeBulkOut(DBuffer) D12RdEp(4,DBuffer,MAX_PACKAGE_SIZE)
#define WritePipeBulkIn(DBuffer,DSize) D12WrEp(5,DBuffer,DSize)
/
/

#define UFI_INQUIRY 0x12
#define UFI_READ_CAPACITY 0x25
#define UFI_READ_FORMAT_CAPACITY 0x23
#define UFI_READ 0x28
#define UFI_WRITE 0x2a
#define UFI_MODE_SENSE 0x1a
#define UFI_TEST_UNIT_READY 0x00
#define UFI_PREVENT_ALLOW_MEDIA_REMOVAL 0x1e
#define UFI_VERIFY 0x2f

#define MAX_PACKAGE_SIZE 64
#define ReadPipeBulkOut(DBuffer) D12RdEp(4,DBuffer,MAX_PACKAGE_SIZE)
#define WritePipeBulkIn(DBuffer,DSize) D12WrEp(5,DBuffer,DSize)

#define SECTOR_SIZE 512

#define MAX_LUN 0
#define BULKOUT_SIZE 64


unsigned char DISK_INF[36]= //磁盘信息
{
0x00,
0x00,
0x02,
0x02,
0x1F,
0x00,0x00,0x00,
0xB5,0xE7,0XC4,0xD4,0xC8,0xA6,0xC8,0xA6,
0xD7,0xD4,0xBC,0xBA,0xD7,0xF6,0xB5,0xC4,0xBC,0xD9,0x55,0xC5,0xCC,0x00,0x00,0x00,
0x31,0x2E,0x30,0x31
};

unsigned char DISK_CAPACITY[8]= //磁盘容量
{
0x00,0x01,0xff,0x00,
0x00,0x00,0x02,0x00
};

unsigned char SENSE[0x12]= //模式探测返回数据
{
0x70, 0x00, 0x05, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00
};

//unsigned char DBR[512]= //DOS引导记录
U8 DiskBuffer[DISK_BUFFER_SIZE]=
{
0xeb, 0x3e, 0x90, //跳转指令
0x4d, 0x53, 0x44, 0x4f, 0x53, 0x35, 0x2e, 0x30, //文件系统版本信息
0x00, 0x02, //扇区字节数
0x20, //每簇扇区数
0x01, 0x00, //保留扇区数
0x02, //该分区的FAT副本数
0xF0, 0x01, //根目录项数
0x00, 0x00, //小扇区数
0xf8, //媒体描述符
0x10, 0x00, //每FAT扇区数
0x20, 0x00, //每道扇区数
0x40, 0x00, //磁头数
0x00, 0x00, 0x00, 0x00, //隐藏扇区数
0x40, 0xff, 0x01, 0x00, //大扇区数
0x80, //磁盘驱动器参数,80表示硬盘
0x00, //保留
0x29, //扩展引导标记,0x29表示后三个区可用
0x88, 0x09, 0x71, 0x20, //标卷序列号
0xBC, 0xD9, 0x55, 0xC5, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //磁盘标卷
0x46, 0x41, 0x54, 0x31, 0x36, 0x20, 0x20, 0x20, //文件系统类型信息
0xf1, 0x7d,
0xfa, 0x33, 0xc9, 0x8e, 0xd1, 0xbc, 0xfc, 0x7b, 0x16, 0x07, 0xbd, 0x78, 0x00, 0xc5, 0x76, 0x00,
0x1e, 0x56, 0x16, 0x55, 0xbf, 0x22, 0x05, 0x89, 0x7e, 0x00, 0x89, 0x4e, 0x02, 0xb1, 0x0b, 0xfc,
0xf3, 0xa4, 0x06, 0x1f, 0xbd, 0x00, 0x7c, 0xc6, 0x45, 0xfe, 0x0f, 0x8b, 0x46, 0x18, 0x88, 0x45,
0xf9, 0xfb, 0x38, 0x66, 0x24, 0x7c, 0x04, 0xcd, 0x13, 0x72, 0x3c, 0x8a, 0x46, 0x10, 0x98, 0xf7,
0x66, 0x16, 0x03, 0x46, 0x1c, 0x13, 0x56, 0x1e, 0x03, 0x46, 0x0e, 0x13, 0xd1, 0x50, 0x52, 0x89,
0x46, 0xfc, 0x89, 0x56, 0xfe, 0xb8, 0x20, 0x00, 0x8b, 0x76, 0x11, 0xf7, 0xe6, 0x8b, 0x5e, 0x0b,
0x03, 0xc3, 0x48, 0xf7, 0xf3, 0x01, 0x46, 0xfc, 0x11, 0x4e, 0xfe, 0x5a, 0x58, 0xbb, 0x00, 0x07,
0x8b, 0xfb, 0xb1, 0x01, 0xe8, 0x94, 0x00, 0x72, 0x47, 0x38, 0x2d, 0x74, 0x19, 0xb1, 0x0b, 0x56,
0x8b, 0x76, 0x3e, 0xf3, 0xa6, 0x5e, 0x74, 0x4a, 0x4e, 0x74, 0x0b, 0x03, 0xf9, 0x83, 0xc7, 0x15,
0x3b, 0xfb, 0x72, 0xe5, 0xeb, 0xd7, 0x2b, 0xc9, 0xb8, 0xd8, 0x7d, 0x87, 0x46, 0x3e, 0x3c, 0xd8,
0x75, 0x99, 0xbe, 0x80, 0x7d, 0xac, 0x98, 0x03, 0xf0, 0xac, 0x84, 0xc0, 0x74, 0x17, 0x3c, 0xff,
0x74, 0x09, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0xeb, 0xee, 0xbe, 0x83, 0x7d, 0xeb, 0xe5,
0xbe, 0x81, 0x7d, 0xeb, 0xe0, 0x33, 0xc0, 0xcd, 0x16, 0x5e, 0x1f, 0x8f, 0x04, 0x8f, 0x44, 0x02,
0xcd, 0x19, 0xbe, 0x82, 0x7d, 0x8b, 0x7d, 0x0f, 0x83, 0xff, 0x02, 0x72, 0xc8, 0x8b, 0xc7, 0x48,
0x48, 0x8a, 0x4e, 0x0d, 0xf7, 0xe1, 0x03, 0x46, 0xfc, 0x13, 0x56, 0xfe, 0xbb, 0x00, 0x07, 0x53,
0xb1, 0x04, 0xe8, 0x16, 0x00, 0x5b, 0x72, 0xc8, 0x81, 0x3f, 0x4d, 0x5a, 0x75, 0xa7, 0x81, 0xbf,
0x00, 0x02, 0x42, 0x4a, 0x75, 0x9f, 0xea, 0x00, 0x02, 0x70, 0x00, 0x50, 0x52, 0x51, 0x91, 0x92,
0x33, 0xd2, 0xf7, 0x76, 0x18, 0x91, 0xf7, 0x76, 0x18, 0x42, 0x87, 0xca, 0xf7, 0x76, 0x1a, 0x8a,
0xf2, 0x8a, 0x56, 0x24, 0x8a, 0xe8, 0xd0, 0xcc, 0xd0, 0xcc, 0x0a, 0xcc, 0xb8, 0x01, 0x02, 0xcd,
0x13, 0x59, 0x5a, 0x58, 0x72, 0x09, 0x40, 0x75, 0x01, 0x42, 0x03, 0x5e, 0x0b, 0xe2, 0xcc, 0xc3,
0x03, 0x18, 0x01, 0x27, 0x0d, 0x0a, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x73, 0x79,
0x73, 0x74, 0x65, 0x6d, 0x20, 0x64, 0x69, 0x73, 0x6b, 0xff, 0x0d, 0x0a, 0x44, 0x69, 0x73, 0x6b,
0x20, 0x49, 0x2f, 0x4f, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0xff, 0x0d, 0x0a, 0x52, 0x65, 0x70,
0x6c, 0x61, 0x63, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x2c, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e,
0x79, 0x20, 0x6b, 0x65, 0x79, 0x0d, 0x0a, 0x00, 0x49, 0x4f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x53, 0x59, 0x53, 0x4d, 0x53, 0x44, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x53, 0x59, 0x53, 0x80, 0x01,
0x00, 0x57, 0x49, 0x4e, 0x42, 0x4f, 0x4f, 0x54, 0x20, 0x53, 0x59, 0x53, 0x00, 0x00, 0x55, 0xaa,
};

unsigned char FAT[64]= //模拟的文件分配表
{
0xF8, 0xFF, 0xFF, 0xFF, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

unsigned char ZERO[64]= //填充0
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

unsigned char ROOT_DIR[64]= //根目录
{
0xC2, 0xC3, 0xD3, 0xCE, 0xB5, 0xBC, 0xB2, 0xA5, 0xBB, 0xFA, 0x20, //磁盘标卷
0x08, //文件属性,表示磁盘标卷
0x00, //保留
0x00, //创建时间毫秒时间戳
0x00, 0x40, //文件创建时间
0x41, 0x31, //文件创建日期
0x42, 0x31, //最后访问日期
0x00, 0x00, //起始簇号高位字节,FAT12/16必须为0
0x00, 0x40, //最后写时间
0x42, 0x31, //最后写日期
0x00, 0x00, //起始簇低位字节
0x00, 0x00, 0x00, 0x00, //文件长度
‘T’, ‘E’, ‘S’, ‘T’, ’ ', ’ ', ’ ', ’ ', ‘T’, ‘X’, ‘T’, //文件名
0x01, //文件属性,表示磁盘标卷
0x00, //保留
0x00, //创建时间毫秒时间戳
0x00, 0x40, //文件创建时间
0x41, 0x31, //文件创建日期
0x42, 0x31, //最后访问日期
0x00, 0x00, //起始簇号高位字节,FAT12/16必须为0
0x00, 0x40, //最后写时间
0x42, 0x31, //最后写日期
0x02, 0x00, //起始簇低位字节
0xe9, 0x00, 0x00, 0x00, //文件长度
};

/!!!极其注意 int型 数据是字对齐的!!!/
typedef struct{
U8 OperationCode;
U8 LUN;

U8	LBA;
U8	LBA1;
U8	LBA2;
U8	LBA3;

U8	ReserveA;
U8  TransferLength;
U8  TransferLength1;
U8	ReserveB[3];

}UFI_TYPE;
/!!!极其注意 int型 数据是字对齐的!!!/

typedef struct{
U32 dCBWSignature;
U32 dCBWTag;
U32 dCBWDataTransferLength;
U8 bmCBWFlags;
U8 bCBWLUN;
U8 bCBWCBLength;
U8 CBWCB[16];
}CBW_TYPE;

typedef struct{
U32 dCSWSignature;
U32 dCSWTag;
U32 dCSWDataResidue;
U8 bCSWStatus;
}CSW_TYPE;

CSW_TYPE CSW;
//
U32 RemainSize;/及其注意当要求发送128扇区时值为65536,若为 U16 则溢出!!!!!!/
/
/
U8 CurSendSize;
U8 BulkOutDataBuffer[MAX_PACKAGE_SIZE];
U8 WriteDataBuffer[SECTOR_SIZE];
U8 TmpArray[MAX_PACKAGE_SIZE];
U8* pBulkInData;
U8* pWriteData;

//BOOL CSWSendFlag=TRUE;
int CSWSendFlag=TRUE;

//U8 DiskBuffer[DISK_BUFFER_SIZE];//4k Flash缓冲
U32 BulkOutDataSize,DiskSecIndex,CurDiskBufferDataAddr;

void UFIHandler(CBW_TYPE*);
void UFI_Inquiry(void);
void UFI_Read(UFI_TYPE*);
void UFI_ReadCapacity(void);
void UFI_ReadFormatCapacity(void);
void UFI_Write(UFI_TYPE* pUFI);
void UFI_ModeSense(void);
void UFI_TestUintReady(void);
void UFI_PreventAllowMediaRemoval(void);

void UFI_Init(void);
void UFI_Init(){}

void WriteToDisk(U8* pDataBuffer,int Size);
void UFI_Verify(void);
void ReadDisk(U8*,U32,U32);

U32 ConvertToU32(U8* pData){
U32 num;
num=pData[0]*16777216+pData[1]*65536+pData[2]*256+pData[3];
return num;
}

U16 ConvertToU16(U8* pData){
U16 num;
num=pData[0]*256+pData[1];
return num;
}

void BulkOut(){
int index,size;
CBW_TYPE* pCBW;
int i;

 size=ReadPipeBulkOut(BulkOutDataBuffer);
U_printf("\n\r");	
U_printf("CBW size is %x\n\r ",size);
U_printf("CBW Value is:\n\r");
for(i=0;i<size;i++)
{
	U_printf(" %x,", BulkOutDataBuffer[i]);
	if(i%8==0) U_printf("\n\r");
}
U_printf("\n");

if(size==31){
	pCBW=(CBW_TYPE*)BulkOutDataBuffer;
	
	
	if(pCBW->dCBWSignature==0x43425355){
		UFIHandler(pCBW);
	}
}else{
	if(size==0){
		//Uart_SendString("BulkOut zero");
		return;
	}
	if(size!=64)
//		Uart_Printf("Size=",size);
		
	for(index=0;index<size;index++){
		DiskBuffer[CurDiskBufferDataAddr+index]=BulkOutDataBuffer[index];
	}
	
	CurDiskBufferDataAddr+=size;
	BulkOutDataSize-=size;
	//Uart_Printf("\nBulkOutDataSize",BulkOutDataSize);
	//Uart_Printf("\nCurDiskBufferDataAddr",CurDiskBufferDataAddr);
	if(BulkOutDataSize==0){
		//PROGRAM_SECTOR((U16*)DiskBuffer,SECTOR_SIZE_1601*DiskSecIndex);
		
		//Uart_Printf("\nDiskSecIndex 1",DiskSecIndex);	
	}else if(CurDiskBufferDataAddr>=DISK_BUFFER_SIZE){
		
		//PROGRAM_SECTOR((U16*)DiskBuffer,SECTOR_SIZE_1601*DiskSecIndex);
		//Uart_Printf("\nDiskSecIndex 2",DiskSecIndex);	
		
		CurDiskBufferDataAddr=0;
		DiskSecIndex++;
		if(BulkOutDataSize<DISK_BUFFER_SIZE){
			ReadDisk(DiskBuffer,DiskSecIndex*SECTOR_SIZE_1601*2,DISK_BUFFER_SIZE);
		}
	
	}
	
}

}

void BulkIn(){

int i;

if(RemainSize>0){
	
	if(RemainSize>BULKOUT_SIZE){
		CurSendSize=BULKOUT_SIZE;
		RemainSize-=BULKOUT_SIZE;

		WritePipeBulkIn(pBulkInData,CurSendSize);
		pBulkInData+=BULKOUT_SIZE;
	}else{
		CurSendSize=RemainSize;
		RemainSize=0;	
		WritePipeBulkIn(pBulkInData,CurSendSize);
	}
}else{
	if(CSWSendFlag==FALSE){
	
		WritePipeBulkIn((U8*)(&CSW),13);
		CSWSendFlag=TRUE;
	}		
}

}

void UFIHandler(CBW_TYPE* pCBW){
UFI_TYPE* pUFI;
pUFI=(UFI_TYPE*)(&(pCBW->CBWCB));
//Uart_Printf(“\nCommand:”,pUFI->OperationCode);
CSW.dCSWSignature=0x53425355;
CSW.dCSWTag=pCBW->dCBWTag;

switch(pUFI->OperationCode){
	case UFI_INQUIRY:				UFI_Inquiry();				break;   //查询命令   0x12
	case UFI_READ:					UFI_Read(pUFI);				break;	 //读10       0x28
	case UFI_READ_CAPACITY:			UFI_ReadCapacity();			break;	 //读容量	  0x25
	case UFI_READ_FORMAT_CAPACITY:	UFI_ReadFormatCapacity();	break;	 //读格式容量 0x23
	case UFI_WRITE:					UFI_Write(pUFI);			break;	 //写10		  0x2a
	case UFI_MODE_SENSE:			UFI_ModeSense();			break;	 //模式感知   0x1a   找不到命令表,不知干什么
	case UFI_TEST_UNIT_READY:		UFI_TestUintReady();		break;	 //单元测试   0x00
	case UFI_VERIFY:				UFI_Verify();				break;	 //验证		  0x2f
	case UFI_PREVENT_ALLOW_MEDIA_REMOVAL:UFI_PreventAllowMediaRemoval();break;	//写并验证  0x2E
	default:
		//CSW.bCSWStatus=0x00;
		break;
			
}	

}
//
/
/

void UFI_Inquiry(void){

U8  InquiryData[36]={

	0x00,//外设类型 软磁盘设备
	0x80,//RMB 可移除介质
	0x00,//版本号
	0x01,//响应数据的格式
	0x1f,//附加数据长度
	0,0,0,//保留
	'B','F','5','3','x',0,0,0,//厂商信息
	'U','D','i','s','k',0,0,0,0,0,0,0,0,0,0,0,
	0,1,0,0//产品版本信息	

};

CSW.dCSWDataResidue=0;
CSW.bCSWStatus=0;


pBulkInData=InquiryData;
RemainSize=36;
CSWSendFlag=FALSE;

}

void UFI_ReadCapacity(){
U8 pd[8]={0x00,0x00,0x08,0x00,
0x00,0x00,0x02,0x00};

CSW.dCSWDataResidue=0;
CSW.bCSWStatus=0;

//pBulkInData=pd;

pBulkInData= DISK_CAPACITY;   //andy test modify

RemainSize=8;
CSWSendFlag=FALSE;

}

void UFI_ReadFormatCapacity(){

U8 bf[20]={0x00,0x00,0x00,0x10,
		   0x00,0x01,0xf4,0x00,
		   0x02,0x00,0x02,0x00,
		   0x00,0x01,0xf4,0x00,
		   0x00,0x00,0x02,0x00};

//CSW.dCSWDataResidue=0xe8;
CSW.bCSWStatus=0;

pBulkInData=bf;
RemainSize=20;
CSWSendFlag=FALSE;

}

void UFI_ModeSense(){

TmpArray[0]=0x03;
TmpArray[1]=0x00;
TmpArray[2]=0x00;
TmpArray[3]=0x00;



//pBulkInData=TmpArray;
//RemainSize=4;

pBulkInData=SENSE;
RemainSize=0x12;
CSWSendFlag=FALSE;

}

void UFI_TestUintReady(){
CSW.dCSWDataResidue=0;
CSW.bCSWStatus=0;

RemainSize=0;
CSWSendFlag=FALSE;

}

void UFI_Verify(){
CSW.dCSWDataResidue=0;
CSW.bCSWStatus=0;

RemainSize=0;
CSWSendFlag=FALSE;

}

void UFI_PreventAllowMediaRemoval(){
CSW.dCSWDataResidue=0;
CSW.bCSWStatus=0;

RemainSize=0;
CSWSendFlag=FALSE;

}

void UFI_Read(UFI_TYPE* pUFI){
U32 LBA;
U16 Length;

CSW.dCSWDataResidue=0;
CSW.bCSWStatus=0;
	
LBA=ConvertToU32(&pUFI->LBA);
Length=ConvertToU16(&pUFI->TransferLength);

//Uart_SendString("\nREAD");
U_printf("\n\r");("  LBA\n",LBA);
U_printf("\n\r");("  Length\n",Length);
U_printf("\n\r");

ReadDisk(DiskBuffer,SECTOR_SIZE*LBA,512*Length);
pBulkInData=DiskBuffer;
RemainSize=SECTOR_SIZE*Length;
CSWSendFlag=FALSE;

}

void UFI_Write(UFI_TYPE* pUFI){
U32 LBA;
U16 Length;

CSW.dCSWDataResidue=0;
CSW.bCSWStatus=0;



LBA=ConvertToU32(&pUFI->LBA);
Length=ConvertToU16(&pUFI->TransferLength);

//Uart_SendString("\nWrite");
//Uart_Printf("  LBA",LBA);
//Uart_Printf("  Length",Length);
BulkOutDataSize=Length*SECTOR_SIZE;
DiskSecIndex=(SECTOR_SIZE*LBA/2)/SECTOR_SIZE_1601;
CurDiskBufferDataAddr=SECTOR_SIZE*LBA-DiskSecIndex*SECTOR_SIZE_1601*2;



if(BulkOutDataSize<DISK_BUFFER_SIZE){
	ReadDisk(DiskBuffer,DiskSecIndex*SECTOR_SIZE_1601*2,DISK_BUFFER_SIZE);
}

RemainSize=0;
CSWSendFlag=FALSE;

}

void WriteToDisk(U8* pData,int size){

static int CurSize=0;
int i;

for(i=0;i<size;i++){
	WriteDataBuffer[CurSize+i]=pData[i];
}
CurSize+=size;
if(CurSize>=SECTOR_SIZE){
	for(i=0;i<CurSize;i++){
		pWriteData[i]=WriteDataBuffer[i];
	}
	pWriteData+=CurSize;
	CurSize=0;
}	

}

void ReadDisk(U8* pDataBuffer,U32 addr,U32 Size){

U32 Index,U16Size,U16Addr;

U16Size=Size>>1;
U16Addr=addr>>1;
for(Index=0;Index<U16Size;Index++){
	*((U16*)pDataBuffer+Index)=READ_DISK(U16Addr+Index);
}

}
//#endif

main.c

#include “datatype.h”
#include “D12Def.h”

int main(void)
{
int i;

Set_PLL(16,4);
Init_EBIU();
UART_setbaudrate(9600);
UART_init();			
U_printf("System Initialized.\n\r");		

if(UsbRdChipId()==0x1210)
{
	U_printf("Find Pdiusbd12, chip id = 0x1210\n\r");	
	UsbInit();		
	while(1)
	{
		i = UsbQueryInt();
		UsbIntProc(i);					
	}
}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/79947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

猿如意中的【UltraEdit】开发工具详情介绍

目录 一、工具名称 二、下载安装渠道 2.1 什么是猿如意&#xff1f; 2.2 如何下载猿如意&#xff1f; 2.3 如何在猿如意中下载UltraEdit&#xff1f; 三、UltraEdit介绍 四、软件安装过程 五、软件界面 六、UltraEdit功能特点介绍 七、UltraEdit使用/体验感受…

Python测试进阶(二)

文章目录简介selenium等待Web控件交互表单操作多窗口frame多浏览器处理用 js 操作文件上传弹窗pageObject复用浏览器简介 这部分主要介绍 web 自动化测试 selenium 专门测试 web 的工具&#xff0c;根据测试用例&#xff0c;直接在浏览器上执行对应动作还是在 pytest 框架中…

牛客网SQL入门复健小练

SQL3&#xff1a;distinct 查询结果去重&#xff0c;返回所有不同的university 方法一&#xff1a;distinct关键字。&#xff08;注意&#xff1a;这个关键字实际上是 select distinct&#xff0c;如果是多列&#xff0c;多列作为一个组合然后 distinct 去重&#xff09; 方…

[oeasy]python0028_直接运行_修改py文件执行权限_设置py文件打开方式

直接运行 回忆上次内容 我们把两个程序整合起来了 可以持续输出当前时间每秒都更新但是我想在 shell 里面 只输入文件名(./sleep.py)并回车就能不断输出时间可能吗&#xff1f;&#x1f914; import time while True:print(time.asctime())time.sleep(1) 尝试执行 第 1 句 根…

EXCEL基础:数据透视表(按月或月累计统计操作)

【按月统计数据】&#xff1a; 本操作实现的是原始数据是以日为单位&#xff0c;统计使用的时候&#xff0c;需要以月份或者季度、年份的形式进行&#xff0c;可以使用数据透视表的【组合】功能来 实现&#xff0c;如下所示&#xff1a; 如下所示&#xff0c;将日期字段放在行…

免费分享一套基于VuePress开发的markdown产品文档

vuepress-theme-jingli 文档 | 效果 | 本仓库的gitee镜像 &#xff08;进入赞助商扫码注册可为本项目作者充电~&#xff09; 介绍 这个主题的初衷是打造一个好用的、面向程序员的知识管理工具轻松构建一个结构化的知识库&#xff0c;让你的知识海洋像一本本书一样清晰易读。…

Mac 下设置VScode 背景图片失败解法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言解法一&#xff1a;直接修改VScode 的CSS解法二&#xff1a;还是想用插件总结前言 仓库推荐 C/C 每日一练小仓库&#xff0c;慢慢学习C 知识必备仓库 https://…

Java8:SPI机制

参考资料&#xff1a; 《双亲委派机制及其弊端》 《Java中SPI机制深入及源码解析》 《Java SPI思想梳理》 《深入理解 Java 中 SPI 机制》 写在开头&#xff1a;本文为学习后的总结&#xff0c;可能有不到位的地方&#xff0c;错误的地方&#xff0c;欢迎各位指正。 目录 …

MyBatis-Plus联表查询的短板,终于有一款工具补齐了

mybatis-plus作为mybatis的增强工具&#xff0c;它的出现极大的简化了开发中的数据库操作&#xff0c;但是长久以来&#xff0c;它的联表查询能力一直被大家所诟病。一旦遇到left join或right join的左右连接&#xff0c;你还是得老老实实的打开xml文件&#xff0c;手写上一大段…

10.泛型算法

文章目录*泛型算法**10.1概述**10.2初识泛型算法**10.2.1只读算法**算法和元素类型**操作两个序列的算法**10.2.2写容器元素的算法**算法不检查写操作**介绍back_inserter**拷贝算法**10.2.3重排容器元素的算法**消除重复单词**使用unique**10.3定制操作**10.3.1向算法传递函数…

【JavaSE】那些异常

目录 1. 何为异常 2. 异常的分类 2.1 运行异常 / 非受查异常 &#xff1a; 3. 异常的处理思想 4. 异常的抛出 5. 异常的捕获 5.1 异常声明 throws 5.2 try-catch 捕获异常并处理 6. finally 7. 异常的处理流程 8. 自定义异常 1. 何为异常 在Java中&#xff0c;将程序执…

LeetCode 1884. 鸡蛋掉落-两枚鸡蛋 -- 动态规划

鸡蛋掉落-两枚鸡蛋 中等 60 相关企业 给你 2 枚相同 的鸡蛋&#xff0c;和一栋从第 1 层到第 n 层共有 n 层楼的建筑。 已知存在楼层 f &#xff0c;满足 0 < f < n &#xff0c;任何从 高于 f 的楼层落下的鸡蛋都 会碎 &#xff0c;从 f 楼层或比它低 的楼层落下的鸡蛋…

Jedis解读与建议

1. Jedis是什么&#xff1f; 官网 Jedis 是官方推荐的java客户端&#xff01;SpringBoot的RedisTemplate的底层也是Jedis&#xff1b; 2. 为什么使用池化&#xff1f; 背景&#xff1a; Redis为单进程单线程模式&#xff0c;采用队列模式将并发访问变为串行访问。Redis本身没…

leetcode:合并两个有序数组

合并两个有序数组1、题目描述2、解决方案3、代码实现1、题目描述 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非…

mutex 锁的理解和思考

并发的影响 goroutine 并发对数据做读写操作&#xff0c;如果没有锁的保护&#xff0c;得到的结果也就是不确定的。我们通过 goroutine 做累加的例子来看一下&#xff0c;下面的情况&#xff0c;我们预期进行了10次循环&#xff0c;每次加1&#xff0c;但执行的结果却不一定的…

离开外包之后,花了10000小时,最后我走进字节跳动拿到了offer

前言&#xff1a; 没有绝对的天才&#xff0c;只有持续不断的付出。对于我们每一个平凡人来说&#xff0c;改变命运只能依靠努力幸运&#xff0c;但如果你不够幸运&#xff0c;那就只能拉高努力的占比。 2020年7月&#xff0c;我有幸成为了字节跳动的一名Java后端开发&#x…

全志A33移植openharmony3.1标准系统之添加产品编译

想玩openharmony很久了,苦于没有合适的板子能让我玩,已经适配好的开发板可真是太贵了啊,所以还是得自己动手啊,毕竟还能深入了解openharmony系统,之前有在A33上把主线uboot和主线内核跑起来,而且drm也是可以正常显示了,现在就基于此将openharmony移植到开发板上。 首先在…

【服务器】基本概念

服务器 文章目录服务器1.概览1.1.本质: **数据接受&传递**, **数据存储**, **数据处理**1.2.种类1.3.单位:1.4.标准1.5.扩展1.6.逻辑架构1.7.缓存Cache:1.8.内存DIMM1.9.DDR1.10.硬盘ref1.概览 1.1.本质: 数据接受&传递, 数据存储, 数据处理 1.2.种类 按应用分类WWW…

Snowflake Decoded基础教程

Snowflake Decoded基础教程 掌握基本的Snowflake概念并获得必要的技能以开始实施基于Snowflake的解决方案 应用程序 课程英文名&#xff1a;Snowflake Decoded Fundamentals and hands on Training 此视频教程共10.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印…

docker启动镜像失败后用日志logs查找失败原因

我用一个自己做的镜像上传到了dockerhub中&#xff0c;然后使用windows拉取pull下来之后&#xff0c;启动不成功&#xff1a; 可以看到&#xff0c;虽然启动了&#xff0c;但是docker ps 后没有看到正在运行的容器&#xff0c;所以我就怀疑启动失败了&#xff0c;但是我又不知道…