📄 usb.c
字号:
r=clbst_error;
break;
//5.同步帧请求
case USBRQ_SYNCH_FRAME:
//6.设置特性请求
case USBRQ_SET_FEATURE:
//7.清除特性请求
case USBRQ_CLEAR_FEATURE:
//8.读取状态请求
case USBRQ_GET_STATUS:
//9.设置描述符请求
case USBRQ_SET_DESCRIPTOR:
//10.读取接口请求
case USBRQ_GET_INTERFACE:
//11.设置接口请求
case USBRQ_SET_INTERFACE:
default: //未知请求
goto call_usercb;
}
call_usercb:
return(r);
}
//usb_it_handler:中断处理--------------------------------------------------*
//功 能: *
// USB模块中断处理 *
//参 数:无 *
//返 回:无 *
//说 明: *
// (1)缓冲区描述符字段 *
// BD[5:2]为当前令牌的PID *
// BD[5:2]=0x01 OUT *
// BD[5:2]=0x09 IN *
// BD[5:2]=0x0d SETUP *
// (2)控制传输的阶段 *
// 建立阶段主机发出SETUP包和8字节数据(data0),从机给出握手包 *
// 数据阶段主机发出IN令牌,从机以DATA1响应,主机给出握手包 *
// 状态阶段主机发出OUT令牌,从机以0长度数据包响应,主机给出握手包 *
//-------------------------------------------------------------------------*
__declspec(interrupt)
void usb_it_handler(void)
{
hcc_u8 istr;
istr=MCF_USB_INT_STAT;
//1.非令牌完成中断,清除相应的中断标识位
if(istr & ~MCF_USB_INT_STAT_TOK_DNE)
{
uart_putch(0x65);
if (istr & MCF_USB_INT_STAT_USB_RST)
{
MCF_USB_INT_STAT = MCF_USB_INT_STAT_USB_RST;
enter_default_state();
usb_reset_event();
goto it_exit;
}
if (istr & MCF_USB_INT_STAT_ERROR)
{
MCF_USB_INT_STAT = MCF_USB_INT_STAT_ERROR;
usb_bus_error_event();
}
if (istr & MCF_USB_INT_STAT_RESUME)
{
MCF_USB_INT_STAT = MCF_USB_INT_STAT_RESUME;
MCF_USB_INT_ENB &= ~MCF_USB_INT_ENB_RESUME;
usb_wakeup_event();
}
if (istr & MCF_USB_INT_STAT_SLEEP)
{
MCF_USB_INT_STAT = MCF_USB_INT_STAT_SLEEP;
MCF_USB_INT_ENB |= MCF_USB_INT_ENB_RESUME;
usb_suspend_event();
}
if (istr & MCF_USB_INT_STAT_SOF_TOK)
{
MCF_USB_INT_STAT = MCF_USB_INT_STAT_SOF_TOK;
}
if (istr & MCF_USB_INT_STAT_STALL)
{
hcc_u8 ep=(hcc_u8)(MCF_USB_STAT >> 4);
MCF_USB_INT_STAT = MCF_USB_INT_STAT_STALL;
/* Remove stall for control endpoints. ??*/
if ((MCF_USB_ENDPT(ep) & MCF_USB_ENDPT_EP_CTL_DIS) == 0)
{
WR_LE32(&BDT_CTL_RX(ep, 0), 0);
WR_LE32(&BDT_CTL_RX(ep, 1), 0);
WR_LE32(&BDT_CTL_TX(ep, 0), 0);
WR_LE32(&BDT_CTL_TX(ep, 1), 0);
ready_ep_rx(ep, ep_info[ep].next_rx);
}
}
}
//2.令牌完成中断
if (istr & MCF_USB_INT_STAT_TOK_DNE)
{
hcc_u8 ep=(hcc_u8)(MCF_USB_STAT >> 4);
int is_rx;
int is_stp;
hcc_u8 this_buf=(hcc_u8)(MCF_USB_STAT & MCF_USB_STAT_ODD ? 1 : 0);
uart_putch(0x66);
//TX包
if (MCF_USB_STAT & MCF_USB_STAT_TX)
{
is_rx=0;
is_stp=0;
//将该端点的BD的STALL位和OWN位清0
WR_LE32(&BDT_CTL_TX(ep, this_buf),
RD_LE32(&BDT_CTL_TX(ep, this_buf)) & ~(BDT_CTL_STALL|BDT_CTL_OWN));
ep_info[ep].next_tx = (hcc_u8)(this_buf ? 0u : 1u);
}
else
{//RX包
is_rx=1;
ep_info[ep].next_rx=(hcc_u8)(this_buf ? 0u : 1u);
//判断当前的令牌是否为SETUP
is_stp=(hcc_u8)(RD_LE32(&BDT_CTL_RX(ep, this_buf)) & 0x3f) == (SOF_PID_VALUE<<2) ? 1 : 0;
//将该端点的BD的STALL位和OWN位清0
WR_LE32(&BDT_CTL_RX(ep, this_buf),
RD_LE32(&BDT_CTL_RX(ep, this_buf)) & ~(BDT_CTL_STALL|BDT_CTL_OWN));
}
//判断是否为控制端点
if ((MCF_USB_ENDPT(ep) & MCF_USB_ENDPT_EP_CTL_DIS) == 0)
{/* then use a special state machine. */
switch(ep_info[ep].state)
{
default:
CMX_ASSERT(0);
break;
case EPST_IDLE:
idle:
//1如果为SETUP包
if (is_stp)
{
callback_state_t r;
/* Reset the endpoint state. */
/* Since TOKBUSY is still set, this is a safe point to disable
packet buffers (NAK in and out direction). */
//将该控制端点的所有BD全部清0
WR_LE32(&BDT_CTL_TX(ep, 0), 0);
WR_LE32(&BDT_CTL_TX(ep, 1), 0);
WR_LE32(&BDT_CTL_RX(ep, 0), 0);
WR_LE32(&BDT_CTL_RX(ep, 1), 0);
/* Danger: if a setup frame will be received not in idle
state, then the TOKBUSY will not be cleared,
and the whole USB will not answer any more.*/
/* This flag shall be cleared after each setup packet. Note:
it seems it shall be cleared before trying to use endpoint
buffers. */
MCF_USB_CTL &= ~MCF_USB_CTL_TXDSUSPEND_TOKBUSY; //将该位清0以允许SIE继续处理令牌
/* remove any callback */
ep_info[ep].data_func = (void*)0;
/* clear flags*/
ep_info[ep].flags=0;
/* clear user error indicator */
ep_info[ep].error=USBEPERR_NONE;
ep_info[ep].data0_tx = BDT_CTL_DATA;
ep_info[ep].data0_rx = BDT_CTL_DATA;
/* Remove stall condition. */
if (ep == 0)
{
r=usb_stm_ctrl0(); //对SETUP包进行解包
}
else
{//只支持一个控制通道
r=clbst_error;
}
switch(r)
{
case clbst_error:
usb_stop_ep_tx(ep);
usb_stop_ep_rx(ep);
ep_info[ep].state = EPST_IDLE;
ep_info[ep].error = USBEPERR_USER_ABORT;
break;
case clbst_not_ready:
/* Nothing to do. */
break;
case clbst_in:
ready_ep_rx(ep, ep_info[ep].next_rx);
break;
case clbst_out:
if (ep_info[ep].state == EPST_IDLE)
{
goto send_status;
}
break;
default:
break;
}
}
else
{/* This is not a setup packet, and we encountered a protocol error.
Possible reasons:
-spurious package on the bus (not our fault)
-we ended the transfer before the host.
- host and device transfer length was not the same
- driver error miscounted packages
*/
/* Stall endpoint to make error visible to the host. */
ep_info[ep].error = USBEPERR_TO_MANY_DATA;
usb_stop_ep_rx(ep);
usb_stop_ep_tx(ep);
}
break;
//2数据阶段(IN令牌)
case EPST_DATA_TX:
case EPST_DATA_TX_LAST:
case EPST_TX_STOP:
_usb_send(ep);
/* If transfer is ended, then we shall receive a handshake from the host. */
if (ep_info[ep].state == EPST_IDLE)
{
ep_info[ep].state=EPST_STATUS_TX;
}
break;
//3状态阶段
case EPST_STATUS_TX:
/* We may have some TX interrupt events on the USB module event stack. These
events are already handled, but wi may get dome dummy interrupts.
So simply dropp such events to keep the state machine synchron to the USB. */
if (!is_rx)
{
break;
}
/* In the IN transfer status stage we received a 0 byte long DATA 1 packet. */
ep_info[ep].state=EPST_IDLE;
/* Tell application transfer ended. */
if (ep_info[ep].data_func != (void *) 0)
{
/* We don't care about the return value at this point, since we already
sent the status, and the transfer is already ended. */
(void)(*ep_info[ep].data_func)();
/* Disable callbacks. */
ep_info[ep].data_func = (void *)0;
}
ready_ep_rx(ep, ep_info[ep].next_rx);
break;
//2数据阶段(OUT令牌)
case EPST_DATA_RX:
_usb_receive(ep);
/* Was this the last packet to receive? */
send_status:
if(ep_info[ep].state == EPST_IDLE)
{
//如果有错误则返回STALL的握手包
if (ep_info[ep].flags & EPFL_ERROR)
{
usb_stop_ep_tx(ep);
}
else
{
ep_info[ep].data0_tx = BDT_CTL_DATA;
ep_info[ep].state=EPST_STATUS_RX;
//控制OUT传输,如果设备OK则在控制传输的状态阶段返回0长度的数据包
send_zero_packet(ep);
}
}
break;
//3状态阶段
case EPST_STATUS_RX:
/* In the OUT transfer status stage we sent a 0 byte long DATA 0 packet. */
ep_info[ep].state=EPST_IDLE;
/* Tell application transfer ended. */
if (ep_info[ep].data_func != (void *) 0)
{
/* We don't care about the return value at this point, since we already
sent the status, and the transfer is already ended. */
(void)(*ep_info[ep].data_func)();
/* Disable callbacks. */
ep_info[ep].data_func = (void *)0;
}
ready_ep_rx(ep, ep_info[ep].next_rx);
break;
}
}
else
{
//如果刚完成的事务为OUT,则将BDT中端点缓冲区的内容复制到端点的用户缓冲区中
if(is_rx)
{
_usb_receive(ep);
}
//如果刚完成的事务为IN,则要将TX缓冲区的内容发送出去
else
{
_usb_send(ep);
if (ep_info[ep].state==EPST_IDLE)
{
/* Inform user application. */
if (ep_info[ep].data_func != (void *)0)
{
(*ep_info[ep].data_func)();
/* Disable futher callbacks. */
ep_info[ep].data_func = (void *)0;
}
}
}
}
//清除中断标志位
MCF_USB_INT_STAT=MCF_USB_INT_STAT_TOK_DNE;
}
it_exit:
;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -