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

📄 usbslave.c

📁 基于HMS7202的波形发生器源程序
💻 C
字号:
#include "usb.h"
#include "utils.h"
#include "reg7202.h"
#include "interrupt.h"

static USlaveBlock_t uslb;
int *usb_save_point;

static void uslave7202_start(USlaveBlock_t *us)
{
	int i;
	int val;
#if 0
	USL_PACKET_t data;

	memset(&data, 0, sizeof(data));
	data.u.pkt.Cmd = USLCMD_STATUS;
	data.u.pkt.nCmd = ~USLCMD_STATUS;
	data.u.pkt.Status = USL_STATUS_ADDRESS;
	data.u.pkt.Addr = address;
	data.u.pkt.Chksum4Cmd = 0;
	for(i=0; i<US_FIFO_SIZE-2; i++)
		data.u.pkt.Chksum4Cmd += data.u.buffer[i];

	unmaskInterrupt(USB_LEVEL);
	us->send(us, &data, sizeof(data));
#else		
	us->setTx(us);//mask all usb interrupt,EP1:OUT point,EP2:IN point
	uslb.unmask(us,US_MASK_TX);//(US_MASK_TX=0x40),unmask both ep1 full interrupt and ep2 empty interrupt
	
	val = _inw(US_DMAMASK);//USB_DMAMASK=0x80012014
	_outw(US_DMAMASK,(val | USBgctrlDMADis));  // CPU mode (== _outw(US_DMAMASK, 3))
                                               //USBgctrlDMAis=0x1
//	_outw(US_TIC, 3); // CPU Mode   !!! Obsolete !!!

	unmaskInterrupt(USB_LEVEL);
#endif
}

static void uslave7202_stop(USlaveBlock_t *us)
{
	maskInterrupt(USB_LEVEL);
}

static void uslave7202_setTx(USlaveBlock_t *us)
{
	us->mode = TXMode;
	_outw(US_MASKREG, USBintmaskMask);			// 0x3ff屏蔽所有USB中断
	_outw(US_MODEREG, US_MODE_RX | US_MODE_TX);	// 7202 needs to be set both RX/TX
	                                            //EP1:OUT point,EP2:IN point
}

static void uslave7202_setRx(USlaveBlock_t *us)
{
	us->mode = RXMode;
	_outw(US_MASKREG, USBintmaskMask);				// 0x3ff
	_outw(US_MODEREG, US_MODE_RX | US_MODE_TX);   // 7202 needs to be set both RX/TX, 
}

static void uslave7202_mask(USlaveBlock_t *us, int rxtx)
{
	int val = _inw(US_MASKREG);
//	_outw(US_MASKREG, val|rxtx);
	_outw(US_MASKREG, val|0x50);		// lupin want to test in RX/TX mask. -> fail
}

static void uslave7202_unmask(USlaveBlock_t *us, int rxtx)
{
	int val = _inw(US_MASKREG);
//	_outw(US_MASKREG, val&(~rxtx));
	_outw(US_MASKREG, val&(~0x50));		// lupin want to test in RX/TX unmask. -> fail
}

static int uslave7202_masked(USlaveBlock_t *us, int rxtx)
{
	int val = _inw(US_MASKREG);
	return (val & rxtx); 
}

/**********************************************************************/
/*   从接收循环队列中取元素
     size:要接收的数据大小   以字节为单位
     data:指向已接收数据的指针
*************************************************************************/     
static int uslave7202_receive(USlaveBlock_t *us, int *data, int size )
{
	int i;
	int val;
	int ret;
	IRingBuffer_t *ring = &us->rxb;

	us->setRx(us);//结构体us中mode=RXMode,屏蔽所有USB中断,EP1:OUT point,EP2:IN point
	us->unmask(us,US_MASK_RX);//不屏蔽EP1 full中断和EP2 empty中断

	// ReSize by word
	size = (size%4==0)? (size >>2) : (size >> 2) + 1;

	i = 0;
	do {
		while(ring->available(ring) <= 0)
		{
			if(us->masked(us, US_MASK_RX))
				us->unmask(us,US_MASK_RX);//确保不屏蔽EP1 full中断
		}//等待接收循环队列非空

		ret = ring->get(ring, &val);//将队尾元素出队,放入val变量中
		//assert(ret == OK);
		*(data + i ++) = val;

		if(us->masked(us, US_MASK_RX) && ring->empty(ring) >= (US_FIFO_SIZE<<8))//?
			us->unmask(us,US_MASK_RX);

	} while(i < size);

//	us->mask(us,US_MASK_RX | US_MASK_TX);
	us->setTx(us);
	us->unmask(us,US_MASK_TX);

	return OK;
}

static int uslave7202_send(USlaveBlock_t *us, int *data, int size )
{
	int i;
	int ret;
	int header;
	int N;
	IRingBuffer_t *ring = &us->txb;


	N = US_FIFO_SIZE;
	if(us->PktMode == O_US_PACKET) N --;

	if(size % (N<<2) != 0)
		return FAIL;

	us->setTx(us);

	i = 0;

	do {
		while(ring->empty(ring) < US_FIFO_SIZE);//等待发送循环队列有足够的空间来完成一次发送

		if( us->PktMode == O_US_PACKET ) {
			header = ((US_DATASYNC << 16)&0x0ffff0000) | ((uslb.NoTx << 8)&0x0ff00) | ((~uslb.NoTx)&0x0ff);
			ret = ring->put(ring, header);
			uslb.NoTx ++;
		}
		ret = ring->putData(ring, (data + i), N);
		i += N;

		if(us->masked(us, US_MASK_TX) && ring->available(ring) >= US_FIFO_SIZE)
			us->unmask(us,US_MASK_TX);

	} while( (i <<2 ) < size);

#if 1
	i=0x700000;
	while(  (ring->available(ring) > 0) && i-- );
	if (i==0) _outw(US_TXDATA, 0);
#else 
	while( ring->available(ring) > 0);
#endif	
//	us->mask(us,US_MASK_RX | US_MASK_TX);
	us->unmask(us,US_MASK_TX);

	return OK;

}

static void uslave7202_HeartBeat(USlaveBlock_t *us, int enable)
{
	if( enable == TRUE)  {
		us->HeartBeat = TRUE;
		us->setTx(us);
		us->unmask(us,US_MASK_TX);
	}
	else {
		us->HeartBeat = FALSE;
		us->mask(us,US_MASK_TX | US_MASK_RX);
	}
}

static void uslave7202_interrupt(int level)
{
	int status, mask;
	int i;
	int count;
	int data;
	USRawData_t usd;
	int ret;
	IRingBuffer_t *ring;

	status = _inw(US_STATUS);//读取USB中断状态寄存器
	mask = _inw(US_MASKREG);//读取USB中断屏蔽寄存器

#if 1
	*usb_save_point = status;usb_save_point++;//保存原USB中断状态寄存器和中断屏蔽寄存器的信息
	*usb_save_point = mask;usb_save_point++;
#endif
	if (status & 0x80) return;//若发生了USB Cable RESET Interrupt,则返回
	else if( (status & US_STATUS_RX) && !(mask & US_MASK_RX)) //若发生了ep1满中断且该中断不屏蔽
	{
		ring = &uslb.rxb;//ring指向uslb中的接收循环队列
		count = ring->empty(ring);//判断接收循环列表是否已满
		if(count < (US_FIFO_SIZE<<1)) 
		{
#if 0
			PANIC("PANIC: USlave RX Overflow\n");
#else
			uslb.mask(&uslb,US_MASK_RX);//若空间不够,则屏蔽接收中断(ep1满中断)
			uslb.rxoverflow ++;//将溢出次数加1
			return;//返回
#endif
		}

		if(uslb.PktMode == O_US_RAW) {//no
			for( i = 0; i<US_FIFO_SIZE; i++)
				ring->put(ring, _inw(US_RXDATA));
		}
		else {//PktMode=O_US_PACKET:Packet Filtering Mode
			for( i = 0; i<US_FIFO_SIZE; i++)
				usd.u.data[i] = _inw(US_RXDATA);//将ep1接收到的内容放入数组中

			if((usd.u.pkt.sync&0x0ffff) == (US_DATASYNC&0x0ffff) && usd.u.pkt.SeqNo == uslb.NoRx) {
				ring->putData(ring, &usd.u.data[1], US_FIFO_SIZE-1);
				uslb.NoRx ++;
			}
			else
				uslb.rxerror ++;
		}
	
	}
	else if( (status & US_STATUS_TX) && !(mask & US_MASK_TX)) //若发生了ep2空中断且该中断不屏蔽
	
	{
		ring = &uslb.txb;//ring指向uslb的发送循环队列
		count = ring->available(ring);//判断发送循环队列是否已有内容
		if( count < US_FIFO_SIZE) {
			if(uslb.HeartBeat) {
				_outw(US_TXDATA,((US_HEARTBEAT << 16)&0x0ffff0000) | (~US_HEARTBEAT & 0x0ffff) );
				_outw(US_TXDATA,US_HEARTBEAT_INTERVAL);
				for( i = 0; i<US_FIFO_SIZE-2; i++)
					_outw(US_TXDATA, 0);
				uslb.nHeartBeat ++;
			}
			else {
				uslb.mask(&uslb,US_MASK_TX);
				uslb.txunderflow ++;
			}
//			return;				 
		}
		else
			for( i = 0; i<US_FIFO_SIZE; i++) {
				ret = ring->get(ring, &data);
#if 1
				*usb_save_point = data;
				usb_save_point++;
#endif
				//assert(ret == MON_OK);
				_outw(US_TXDATA, data);
			}
		status = _inw(US_STATUS);	// kwon ordered to read status reg. after data-filling in FIFO. 
									//	To prevent continuous empty-interrupt arising.  	
	}
//	status = _inw(US_STATUS);	// kwon ordered to read status reg. after data-filling in FIFO. 
//								//	To prevent continuous empty-interrupt arising.  

}

USlaveBlock_t * uslave7202_setup(int PktMode, int HeartBeat)
{
	static int inited = 0;
	int ret;
	int val;
	unsigned int base, size;
	USlaveBlock_t *us = &uslb;

	if(inited != 0) {
		ser_printf("USB Slave already is setup\n");
		base = USB_BUFFER_BASE;
		size = USB_BUFFER_SIZE;
		if(size < 2*MIN_BUFFER_SIZE ) {
			ser_printf("Buffer is not enough\n");
			return NULL;
		}

		ser_printf("USL Buffer base=0x%08x, size=%d\n", base, size);

		IRingBufferInit(&us->rxb, "USL RX", base, (size/2) >> 2);
		IRingBufferInit(&us->txb, "USL TX", base + size/2, (size/2) >> 2);

		us->start = uslave7202_start;
		us->stop = uslave7202_stop;
		us->setTx = uslave7202_setTx;
		us->setRx = uslave7202_setRx;
		us->mask = uslave7202_mask;
		us->unmask = uslave7202_unmask;
		us->masked = uslave7202_masked;
		us->receive = uslave7202_receive;
		us->send = uslave7202_send;
		us->setHeartBeat = uslave7202_HeartBeat;

		us->nHeartBeat = 0;
		us->txunderflow = 0;
		us->rxoverflow = 0;

		us->PktMode = PktMode;
		us->HeartBeat = HeartBeat;
		us->NoTx = 0;
		us->NoRx = 0;
		us->rxerror = 0;


		return us;
	}

// S/W Disable USB PLL in USB Block  	
//	_outw(US_CLKEN, (!USBswresetPWR_MD1) | (!USBswresetPWR_MD0));    // == _outw(US_CLKEN, 0);
	_outw(US_CLKEN, 0);//disable BCLK to USB block,full power down
	_outw(US_STATUS, 0);//clear USB interrupt status register



	inited = 1;

	ser_printf("USB Slave setup");

	if(PktMode == O_US_PACKET) //yes
		ser_printf("(Packet Filtering Mode, ");
	else if(PktMode == O_US_RAW)
		ser_printf("(RAW Data Mode, \n");
	else {
		ser_printf("(Unknown Mode) --> FAIL\n");
		return NULL;
	}
	if(HeartBeat == O_US_HEARTBEAT) //yes
		ser_printf("HeartBeat Mode)\n");
	else if(HeartBeat == O_US_NOHEARTBEAT)
		ser_printf("No HeartBeat Mode)\n");
	else {
		ser_printf("(Error HeartBeat) --> FAIL\n");
		return NULL;
	}
	base = USB_BUFFER_BASE;
	size = USB_BUFFER_SIZE;	
	if(size < 2*MIN_BUFFER_SIZE ) {
		ser_printf("Buffer is not enough\n");
		return NULL;
	}

	ser_printf("USL Buffer base=0x%08x, size=%d\n", base, size);

	IRingBufferInit(&us->rxb, "USL RX", base, (size/2) >> 2);
	IRingBufferInit(&us->txb, "USL TX", base + size/2, (size/2) >> 2);

	us->start = uslave7202_start;
	us->stop = uslave7202_stop;
	us->setTx = uslave7202_setTx;
	us->setRx = uslave7202_setRx;
	us->mask = uslave7202_mask;
	us->unmask = uslave7202_unmask;
	us->masked = uslave7202_masked;
	us->receive = uslave7202_receive;
	us->send = uslave7202_send;
	us->setHeartBeat = uslave7202_HeartBeat;

	us->nHeartBeat = 0;
	us->txunderflow = 0;
	us->rxoverflow = 0;

	us->PktMode = PktMode;
	us->HeartBeat = HeartBeat;
	us->NoTx = 0;
	us->NoRx = 0;
	us->rxerror = 0;

	pISR_USB = (unsigned int)uslave7202_interrupt;


// S/W ENABLE USB PLL in USB Block
	_outw(US_CLKEN, USBswresetEnBCLK | USBswresetPWR_MD1 ); //enable BCLK,power down mode
	_outw(US_STATUS, 0);//clear USB interrupt status register

#if 0
	val = _inw(USBgctrl);
	_outw(USBgctrl, (val | USBgctrlTRANDis));  		// Ext. transceiver mode
#endif
	return us;
}


⌨️ 快捷键说明

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