📄 usbslave.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 + -