⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sl811.c

📁 基于ARM7的直流电机的驱动,还有FLASH驱动,LCD驱动等
💻 C
📖 第 1 页 / 共 3 页
字号:
//
#define	NC		128
typedef struct _BC {
	UINT		Ref : 31;
	UINT		Modified:1;
	ULONG		st;
	UCHAR		*Data;
} BC;


//
// 缓冲区
//
static BC		acc[NC];

//
// 初始化缓冲区
//
static void
BCInit(void) {
	int	i;
	
	for(i = 0; i < NC; i++) {
		acc[i].st = 0xFFFF00FF;
		acc[i].Modified = 0;
		acc[i].Ref = 0;
	}
}

//
// 引用被缓冲的扇区
//
static void
Refer(UINT b) {
	ULONG	i, max;
	
	max = acc[b].Ref;
	for(i = 0; i < NC; i++)
	if(acc[i].Ref > max)
		max = acc[i].Ref;
	acc[b].Ref = max + 1;
}

//
// 查找被缓冲的扇区
//
static int
Lookup(ULONG st) {
	UINT	b;
	
	for(b = 0; b < NC; b++)
	if(acc[b].st == st)
		return b;
	return -1;
}

//
// 回写缓冲取中被修改的扇区
//
static void
XX_Flush(UINT b) {
	
	acc[b].Modified = 0;
	__usbWriteBlock(&MassStor, acc[b].st, acc[b].Data);
}


//
// 新建一个扇区缓冲区
//
static int
NewEntry(ULONG lba) {
	UINT	i, b;
	
	b = 0;
	for(i = 0; i < NC; i++) {
		if(!acc[i].Data) {
			// 分配内存
			acc[i].Data = (UCHAR *)kmalloc(MassStor.BlockSize);
			b = i;
			break;
		}
		if(acc[i].Modified <= acc[b].Modified && acc[i].Ref < acc[b].Ref)
			b = i;
	}
	
	ASSERT(b < NC);
	
	// 回写被修改的扇区
	if(acc[b].Modified)
		XX_Flush(b);
	acc[b].st = lba;
	acc[b].Modified = 0;
	return b;
}

//
// 同步海量存储设备
//
void
UsbSync(void) {
	UINT	b;
	
	if(!UsbDsk.Connected)
		return;

	//LockDrive(&UsbDsk);
	
	for(b = 0; b < NC; b++)
	if(acc[b].Modified)
		XX_Flush(b);
	
	//UnlockDrive(&UsbDsk);
}

//
// 读海量存储设备扇区
//
// ms: 海量存储设备
// lba:扇区号
// buf:数据指针
//
int
usbReadBlock(MASS_STOR *ms, ULONG lba, void *buf) {
	struct us_cbw	cbw;
	struct us_csw	csw;
	int				b;
	
	if(lba >= ms->BlockNumber)
		return FALSE;

	// 缓冲命中
	b = Lookup(lba);
	if(b != -1)
		goto retOk;

	// 缓冲失败,申请一个缓冲区
	b = NewEntry(lba);
	
	//DBG2("usbReadBlock(%u, %08X)...\n", lba, buf);

	// 组"SCSI读扇区"命令包
	cbw.dSignature = CBW_SIGNATURE;
	cbw.dTag = 0x60a624de;
	cbw.dXferLength = ms->BlockSize;
	cbw.bFlags = 0x80;
	cbw.bLUN = 0;
	cbw.bCBDLength = 10;
	
	/////////////////////////////////
	cbw.aCmd[0] = 0x28;	// operation code
	cbw.aCmd[1] = 0;
	// LBA
	cbw.aCmd[2] = lba >> 24;
	cbw.aCmd[3] = lba >> 16;
	cbw.aCmd[4] = lba >> 8;
	cbw.aCmd[5] = lba;
	// Transfer Length
	cbw.aCmd[7] = 0;
	cbw.aCmd[8] = 1;
	cbw.aCmd[9] = 0;	// Control = 00h
	
	////////////////////////////////
	// 下发"SCSI读扇区"命令包
	if(BulkOut(ms, (UCHAR *)&cbw, sizeof(cbw)) != TRUE)
		return FALSE;
	
	// 读出数据
	if(BulkIn(ms, acc[b].Data, ms->BlockSize) != TRUE)
		return FALSE;
	
	// 读出命令操作状态
	if(BulkIn(ms, (UCHAR *)&csw, sizeof(csw)) != TRUE)
		return FALSE;
	
	if(csw.bStatus != CSW_STATUS_OK)
		return FALSE;
retOk:
	Refer(b);
	
	// 从缓冲区中读出数据
	Memcpy(buf, acc[b].Data, ms->BlockSize);
	return TRUE;
}


//
// 写海量存储设备扇区(缓冲)
//
// ms: 海量存储设备
// lba:扇区号
// buf:数据指针
//
int
usbWriteBlock(MASS_STOR *ms, ULONG lba, void *buf) {
	int				b;
	
	if(lba >= ms->BlockNumber)
		return FALSE;

	// 缓冲命中
	b = Lookup(lba);
	if(b == -1)
		b = NewEntry(lba);	// 缓冲失败,申请一个缓冲区
	
	Refer(b);
	
	// 写入缓冲区
	Memcpy(acc[b].Data, buf, ms->BlockSize);
		
	acc[b].Modified = TRUE;
	return TRUE;
}

//
// 读驱动器扇区
//
static int
cb_rdsect(DRIVE *d, ULONG st, UCHAR *buf) {
	
	return usbReadBlock(d->ms, st, buf);
}

//
// 写驱动器扇区
//
static int
cb_wrsect(DRIVE *d, ULONG st, UCHAR *buf) {
	
	return usbWriteBlock(d->ms, st, buf);
}

//
// 同步驱动器
//
static void
cb_sync(DRIVE *d) {

	UsbSync();
}

//
// 同步驱动器单个扇区
//
static void
cb_sync2(DRIVE *d, UINT st) {
	int b;
	
	b = Lookup(st);

	ASSERT(b < NC);

	if(b != -1) {
		acc[b].Ref = 0;
		XX_Flush(b);
	}
}

////////////////////////////////////////////////////////
// USB主机控制器复位
//
void
hc_reset(HC *hc) {
	PSW
	UCHAR	t;
	
	// 假定没有设备接入
	UsbDsk.Connected = FALSE;
	
	hc->reset = FALSE;
	hc->enumed = FALSE;
	hc->devfound = FALSE;
	
	DISABLE;

	/* 禁止中断
     */
    hc_write(hc, SL_INTEN, 0);

    /* 停止传输,复位控制器
     */
    hc_write(hc, SL_HCR_A, 0);
    hc_write(hc, SL_HCR_B, 0);
    hc_write(hc, SL_SOF_HI, SL_SOFH_Master);
    
    ENABLE;

    /* 延时等待 
     */
    tm_delay(50);
    
    DISABLE;
    
    /* 清除中断
     */
    hc_write(hc, SL_ISTATUS, 0xFF);

    /* 检查总线连接状态
     */
    t = hc_read(hc, SL_ISTATUS);
    
    ENABLE;
	
	if(t & 0x40) {
		hc->connected = FALSE;
		//DBG("SL811HS: No device or no power\n");
	} else {
		hc->connected = TRUE;
		hc->reset = TRUE;
		
		if (!(t & 0x80 )) {	
			//
			// 慢速设备接入
			//
			hc->lowSpeed = TRUE;
			//DBG("SL811HS: Low speed device connected\n");
		} else {
			//
			// 全速设备接入
			//
			hc->lowSpeed = FALSE;
			
			DISABLE;
			
            hc_write(hc, SL_SOF_HI,SL_SOFH_1ms|SL_SOFH_Master);
            hc_write(hc, SL_SOF_LOW, SL_SOFL_1ms);
            hc_write(hc, SL_CTRL1,SL_CTRL1_SOF_en|SL_CTRL1_Reset|SL_CTRL1_EOF2);
            
            ENABLE;
            
            tm_delay(50);
            
            DISABLE;
            hc_write(hc, SL_CTRL1,SL_CTRL1_SOF_en|SL_CTRL1_EOF2);
            ENABLE;
			
			//DBG("SL811HS: Full speed device connected\n");
		}

		DISABLE;
		/* start the SOF or EOP */
        hc_write(hc, SL_HPID_A, SL_MAKE_HPID(SL_HPID_SOF,0));
        hc_write(hc, SL_HDA_A, 0);
        hc_write(hc, SL_HCR_A, SL_HCR_Arm);
        ENABLE;
	}
	
	// 延时
	tm_delay(10);
	
	DISABLE;

	/* 清除USB中断
     */
	hc_write(hc, SL_ISTATUS, 0xFF);
	
	/* 设置USB中断允许寄存器,允许某些中断
     */
	hc_write(hc, SL_INTEN, INTS);
	
	ENABLE;
}

////////////////////////////////////////////////////////
// USB主机控制器初始化
//
static void
hc_init(HC *hc) {
	//
	// 初始化变量
	//
	Memset(hc, 0, sizeof(HC));
	hc->AddrPort = SL811_ADDR_PORT;
	hc->DataPort = SL811_DATA_PORT;
	
	// 创建信号量
	(void)sm_create("SLSM", 0, 0, &hc->sm);
	
	/* 设置中断向量
	 */
	IntConnect(ISR_SL811, (UINT)SL811Handler);
	
	ASSERT(rINTMSK & BIT_SL811);
	
	// 允许USB中断
	rINTMSK &= ~(BIT_SL811);
	
	//
	// 需要复位USB控制器
	//
	hc->reset = TRUE;
}

////////////////////////////////////////////////////
// USB任务入口
//
void
usbMain(void *args) {
	HC	*hc = &SL811;
	
	Memset(acc, 0, sizeof(acc));
	UsbDsk.Connected = FALSE;

	//DBG("Usb testing...\n");
	hc_init(hc);
	
	
	while(1) {
		// 等待U盘插入
		sm_p(smSL811, FOREVER);
		
		// 需要复位USB控制器
		if(hc->reset) {
			(void)hc_reset(hc);
			
			if(!hc->connected) {
				UsbDsk.Connected = FALSE;
				
				// U盘拔出,卸载U盘驱动器
				if(UsbDsk.Flags & DRIVE_MOUNT)
					FatUnmount(&UsbDsk);
				continue;
			}
		}

		// USB设备插入,但是未枚举
		if(hc->connected && !hc->enumed) {
			struct usb_device_descriptor *dev;

			hc->ep0.Payload = 16;
			hc->ep0.Endpoint = 0;
			hc->ep0.Toggle = 0;
			hc->enumed = TRUE;
			
			// 取得设备描述符
			Memset(&MassStor, 0, sizeof(MassStor));
			MassStor.hc = hc;
			if(!GetDevDesc(&MassStor)) {
				//DBG("GET DEVICE DESCRIPTOR FAILED!\n");
				continue;
			}
			
			dev = &hc->dev;
			//DBG("USB Device %x.%x\n", dev->bcdUSB >> 8, (dev->bcdUSB & 0xF0)>>4);
			//DBG("bMaxPacketSize0 %u Bytes\n", dev->bMaxPacketSize0);
			
			// 设置设备地址
			if(!SetAddress(&MassStor)) {
				//DBG("SET ADDRESS FAILED!\n");
				hc->reset = TRUE;
				continue;
			}
			
			MassStor.DeviceAddress = USB_ADDR;
			
			// 检测海量存储设备
			if(!UsbMassDetect(&MassStor)) {
				//DBG("Usb Mass Storage detect FAILED!\n");
				hc->reset = TRUE;
				continue;
			}
			
			DBG("USB Mass Storage Device found!\n");
			
			// 质询USB设备
			if(!Inquiry(&MassStor)) {
				//DBG("Inquiry FAILED!\n");
				hc->reset = TRUE;
				continue;
			}
			
			// 获取USB设备参数
			if(!ReadCapacity(&MassStor)) {
				//DBG("ReadCapacity FAILED!\n");
				hc->reset = TRUE;
				continue;
			}
			
			// 缓冲区初始化
			BCInit();
			
			
			// 挂载USB驱动器
			Memset(&UsbDsk, 0, sizeof(UsbDsk));
			UsbDsk.ms = &MassStor;
			UsbDsk.Sectors = MassStor.BlockNumber;
			UsbDsk.BytesPerSector = MassStor.BlockSize;
			UsbDsk.BytesPerSectorShift = MassStor.BlockSizeShift;
			UsbDsk.ReadSector = (CALLBACK)cb_rdsect;
			UsbDsk.WriteSector = (CALLBACK)cb_wrsect;
			UsbDsk.Sync = cb_sync;
			UsbDsk.Sync2 = cb_sync2;
			
			if(!FatMount(&UsbDsk, "USBd"))
				continue;
			
			UsbDsk.Connected = TRUE;
		}
		//tm_delay(20);
		//DBG(">");
	}
}

/*
	     USB任务
	|----------------|
	|  设置中断向量  |
	|----------------|
	        | <-----------|
	|----------------|    |
	|等待U盘插入,拔出|    |
	|----------------|    |
            |             |
    |----------------|    |
    |   复位USB总线  |    |
    |----------------|    |
            |             |
    |----------------| 是 |
    |    U盘拔出?    |----+
    |----------------|    |
            |(否,U盘插入)|
    |----------------|    |
	| 取得设备描述符 |    |
	|----------------|    |
            |             |
    |----------------|    |
	|  设置设备地址  |    |
	|----------------|    |
	        |             |
    |----------------|    |
	|   获取配置描述 |    |
	|----------------|    |
	        |             |
    |----------------|    |
	|获取接口,端点描述|   |
	|----------------|    |
	        |             |
    |----------------|    |
	|    设置配置    |    |
	|----------------|    |
	        |             |
    |----------------|    |
	|   质询USB设备  |    |
	|----------------|    |
	        |             |
    |----------------|    |
	|   获取U盘参数  |    |
	|----------------|    |
	        |             |
    |----------------|    |
	|  缓冲区初始化  |    |
	|----------------|    |
	        |             |
    |----------------|    |
	|  挂载U盘驱动器 |    |
	|----------------|    |
	        |             |
	        +-------------|
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -