📄 sx2usbdrv.c
字号:
*
* VOID hostSx2Wakeup(VOID);
*
* RETURNS: OK or ERROR.
*/
STATUS sx2Wakeup(VOID)
{
/* check if host specific wakeup function exists */
if (hostCpu._func_hostSx2Wakeup != NULL)
{
(*hostCpu._func_hostSx2Wakeup)();
return (OK);
}
return (ERROR);
}
/*******************************************************************************
*
* sx2Reset - Reset the SX2.
*
* The reset operation is completely determined by how the SX2 RESET pin is
* wired, e.g. if RESET is connected to a host CPU GPIO pin the wakeup function
* pointer should be initialized with a function that asserts the GPIO pin.
*
* The host CPU specific reset function has to be declared as follows:
*
* VOID hostSx2Reset(VOID);
*
* RETURNS: OK or ERROR.
*/
STATUS sx2Reset(VOID)
{
/* check if host specific reset function exists */
if (hostCpu._func_hostSx2Reset != NULL)
{
(*hostCpu._func_hostSx2Reset)();
return (OK);
}
return (ERROR);
}
/*******************************************************************************
*
* sx2SetIntHook - Set the ISR hook function pointer to the specified function.
* The hook can be cleared by passing NULL for hookFunc.
*
* The ISR hook has to be defined as follows:
*
* STATUS sx2IsrHook(UINT16 intCause)
*
* The main ISR calls this hook and passes the value of the IRQ register,
* indicating the type of interrupt that occurred.
*
* RETURNS: OK.
*/
STATUS sx2SetIntHook(STATUS (*hookFunc)(UINT16))
{
hostCpu._func_isrHook = hookFunc;
return (OK);
}
/*******************************************************************************
*
* sx2GetIntHook - Return the ISR hook function pointer.
*
* RETURNS: Hook function pointer.
*/
FUNCPTR sx2GetIntHook(VOID)
{
return (FUNCPTR)(hostCpu._func_isrHook);
}
/*******************************************************************************
*
* sx2SetNotifyHook - Set the specified notification hook function to the
* function pointer provided.
*
* This function allows the setting of different notification callbacks.
* The user can assign a callback function to be invoked when certain
* operations complete. This can be used to implement higher level
* blocking and non-blocking calls.
*
* The following notification hooks (hookType parameter) are supported:
*
* READ_REG_NOTIFY - notification upon register read completion
* WRITE_REG_NOTIFY - notification upon register write completion
* READ_FIFO_NOTIFY - notification upon fifo read completion
* WRITE_FIFO_NOTIFY - notification upon fifo write completion
*
* The notification hook functions have to be defined as follows:
*
* STATUS notifyHook(UINT32 param)
*
* Notes:
* - to clear a hook, call sx2SetNotifyHook with hookFunc=NULL
* - the hook is invoked with param=0 as this feature is not
* currently used.
*
* RETURNS: OK or ERROR if hookType invalid.
*/
STATUS sx2SetNotifyHook(UINT8 hookType, STATUS (*hookFunc)(UINT32 param))
{
/* assign hook function pointer */
switch (hookType)
{
case READ_REG_NOTIFY:
hostCpu._func_readRegNotifyHook = hookFunc;
break;
case WRITE_REG_NOTIFY:
hostCpu._func_writeRegNotifyHook = hookFunc;
break;
case READ_FIFO_NOTIFY:
hostCpu._func_readFifoNotifyHook = hookFunc;
break;
case WRITE_FIFO_NOTIFY:
hostCpu._func_writeFifoNotifyHook = hookFunc;
break;
default:
return (ERROR);
}
return (OK);
}
/*******************************************************************************
*
* sx2GetNotifyHook - Return the requested notification hook function pointer.
*
* RETURNS: Hook function pointer or ERROR if hookType invalid.
*/
FUNCPTR sx2GetNotifyHook(UINT8 hookType)
{
STATUS (*hookFunc)(UINT32);
/* retrieve hook function pointer */
switch (hookType)
{
case READ_REG_NOTIFY:
hookFunc = hostCpu._func_readRegNotifyHook;
break;
case WRITE_REG_NOTIFY:
hookFunc = hostCpu._func_writeRegNotifyHook;
break;
case READ_FIFO_NOTIFY:
hookFunc = hostCpu._func_readFifoNotifyHook;
break;
case WRITE_FIFO_NOTIFY:
hookFunc = hostCpu._func_writeFifoNotifyHook;
break;
default:
return (FUNCPTR)(ERROR);
}
return (hookFunc);
}
/* internal routines */
/*******************************************************************************
*
* sx2Isr - SX2 main interrupt service routine
*
* RETURNS: OK or ERROR.
*/
LOCAL VOID sx2Isr(UINT32 param)
{
UINT32 level;
/* We first have to check if someone has initiated a read request, in
which case the interrupt needs to be treated as a read interrupt */
/* lock interrupts */
level = intLock();
if (hostCpu.readSyncFlag != 0)
{
/* We're dealing with a read interrupt. Even though this interrupt
doesn't have a bit in the IRQ reg, we still have to acknowledge it
by reading the cmd reg, the data read is irrelevant */
(*hostCpu._func_hostCpuRead) (hostCpu.sx2Cmd);
/* Wake up the reader task. We only give the semaphore if the reader
is a task */
if ((hostCpu.readSyncFlag) & READER_IS_TASK)
{
/* clear read sync flag and unlock ints */
hostCpu.readSyncFlag = 0;
intUnlock (level);
semGive (hostCpu.readSyncSem);
}
else
{
/* clear read sync flag and unlock ints */
hostCpu.readSyncFlag = 0;
intUnlock (level);
}
}
else
{
/* unlock interrupts */
intUnlock (level);
/* it must be one of the six standard interrupts. Read IRQ reg to clear
the interrupt condition. Note that after an interrupt, the IRQ reg is
ready to be read, no register read request has to be issued. */
sx2IntCause = SX2_WORD_SWAP((*hostCpu._func_hostCpuRead) (hostCpu.sx2Cmd));
/* catch the READY interrupt */
if (sx2IntCause == READY_INT)
{
hostCpu.sx2Initialized = TRUE;
}
#ifdef SX2_DEBUG
logMsg("SX2 interrupt, cause = 0x%x\n", sx2IntCause,0,0,0,0,0);
#endif
/* The default action is to send a message to the service task along
with the type of interrupt that was received. The user has the option
to supply an interrupt hook if certain actions have to take place
at interrupt level. This hook is subject to all standard ISR
restrictions. If no hook is provided, or if the hook returns OK,
we send a message to the service task. If the hook returns ERROR
no message is sent. */
if (hostCpu._func_isrHook != NULL)
{
if ((*hostCpu._func_isrHook)(sx2IntCause) == OK)
{
/* wake up the service task */
if (msgQSend(hostCpu.svcQId, (UINT8 *)&sx2IntCause, SVC_Q_MSG_SIZE,
NO_WAIT, MSG_PRI_NORMAL) == ERROR)
{
logMsg("sx2Isr() - error sending msg to service task.\n",0,0,0,0,0,0);
}
}
}
else
{
/* wake up the service task */
if (msgQSend(hostCpu.svcQId, (UINT8 *)&sx2IntCause, SVC_Q_MSG_SIZE,
NO_WAIT, MSG_PRI_NORMAL) == ERROR)
{
logMsg("sx2Isr() - error sending msg to service task.\n",0,0,0,0,0,0);
}
}
}
}
/*******************************************************************************
*
* sx2WriteNibbles() - write a byte to the SX2, one nibble at a time
*
* RETURNS: OK or ERROR if timed out polling READY line.
*/
LOCAL STATUS sx2WriteNibbles (UINT8 data)
{
UINT8 upper = (data >> 4) & 0x0F;
UINT8 lower = data & 0x0F;
/* wait for READY to go high */
if ((*hostCpu._func_waitReady)() != OK)
return (ERROR);
/* write first nibble */
(*hostCpu._func_hostCpuWrite) (hostCpu.sx2Cmd,
SX2_WORD_SWAP(upper & SX2_CMD_DATA));
/* wait for READY to go high */
if ((*hostCpu._func_waitReady)() != OK)
return (ERROR);
/* write second nibble */
(*hostCpu._func_hostCpuWrite) (hostCpu.sx2Cmd,
SX2_WORD_SWAP(lower & SX2_CMD_DATA));
return (OK);
}
/*******************************************************************************
*
* sx2DrvCleanup() - clean up resources allocated by driver
*
* The host CPU specific cleanup function has to be defined as follows:
*
* STATUS hostSx2DrvCleanup(VOID)
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sx2DrvCleanup(VOID)
{
STATUS status = OK;
if (hostCpu._func_drvCleanup != NULL)
{
status = (*hostCpu._func_drvCleanup)();
}
hostCpu.sx2Initialized = FALSE;
return (status);
}
/*******************************************************************************
*
* sx2FlushFifos() - flush all SX2 FIFOs
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sx2FlushFifos(VOID)
{
if (sx2WriteReg(INPKTENDFLUSH,
FIFO2FLUSH|FIFO4FLUSH|FIFO6FLUSH|FIFO8FLUSH) == ERROR)
{
return (ERROR);
}
return (OK);
}
/*******************************************************************************
*
* sx2SetFifoWidth() - Set access width of FIFOs as defined by macros
* SX2_BUS_WIDTH and SX2_FIFO_WIDTH
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sx2SetFifoWidth(VOID)
{
UINT32 i;
UINT8 data;
UINT8 reg = EP2PKTLENH;
#if (SX2_BUS_WIDTH == SX2_BUS_16BIT)
/* walk through the 4 EPxPKTLENH registers and set/clear the WORDWIDE bit */
for (i=0; i<4; i++)
{
if (sx2ReadReg(reg, &data) == ERROR)
return (ERROR);
#if (SX2_FIFO_WIDTH == SX2_FIFO_16BIT)
data |= WORDWIDE;
#else
data &= ~WORDWIDE;
#endif
if (sx2WriteReg(reg, data) == ERROR)
return (ERROR);
reg += 2;
/* The delay is needed, determined through experimentation. If no delay
is inserted, the first read/write sequence completes ok. The second
time around, the SX2 will not generate any more read interrupts (or any
other interrupts for that matter). The task calling sx2SetFifoWidth()
will be pended on the read sync semaphore forever. This appears to
be a timing problem on the SX2, apparently caused when a write is
immediately followed by a read. Need clarification from Cypress. */
taskDelay (1);
}
#endif
return (OK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -