3.2 固件在USB設(shè)備設(shè)別階段的編程思路
一般地,USB設(shè)備接口芯片會(huì)產(chǎn)生一些中斷來(lái)通知程序員特定事件的發(fā)生。譬如說(shuō),EP0(缺省控制端點(diǎn)) SETUP包的到達(dá),EP
這個(gè)例子的思路是,在響應(yīng)USB產(chǎn)生的中斷時(shí),會(huì)用全局變量記錄下中斷的發(fā)生,然后在主循環(huán)里面進(jìn)行具體處理。
/* USB服務(wù)程序偽代碼 */
void USB_Service(void)
{
/*處理控制傳輸?shù)?/span>3個(gè)階段*/
switch (EP.EP0.Stage)
{
case C_STAGE_EP0_SETUP: /*處在建立階段*/
if (!USB_Setup ()) /*如果請(qǐng)求是被支持的*/
EP.EP0.Stage = C_STAGE_EP0_DATA; /*轉(zhuǎn)入數(shù)據(jù)階段*/
break;
case C_STAGE_EP0_DATA: /*處在數(shù)據(jù)階段*/
if (EP.EP0.Status == C_STATUS_EP0_IN_NACK) /*收到了IN令牌*/
{
USB_WriteEP0FIFO(); /*通過(guò)控制端點(diǎn)發(fā)送數(shù)據(jù)給主機(jī)*/
EP.EP0.Status = C_STATUS_RESET; /*已處理完畢,所以復(fù)位此狀態(tài)*/
EP.EP0.Stage = C_STAGE_EP0_STATUS; /*轉(zhuǎn)入狀態(tài)階段*/
重新使能EP0_IN_NACK中斷; /*在ISR中會(huì)關(guān)掉此中斷*/
}
break;
case C_STAGE_EP0_STATUS:
使能EP0_STATUS寄存器;
break;
default:
break;
}
}
/*USB中斷服務(wù)程序偽代碼(部分)*/
void USB_ISR(void)
{
if (SETUP包到達(dá))
{
清中斷;
EP.EP0.Stage = C_STAGE_EP0_SETUP;
EP.EP0.Status = C_STATUS_EP0_SETUP_ARRIVAL;
}
else if (EP
{
清中斷;
關(guān)閉此中斷;
EP.EP0.Status = C_STATUS_EP0_IN_NACK;
}
}
/*USB控制傳輸?shù)慕㈦A段處理程序偽代碼*/
int USB_Setup (void)
{
通過(guò)各寄存器的值來(lái)得到請(qǐng)求的類型和相關(guān)數(shù)據(jù);
if (請(qǐng)求類型是讀取描述符)
{
switch (描述符值)
{
case 設(shè)備描述符值:
將全局的發(fā)送數(shù)據(jù)的指針指向設(shè)備描述符buffer;
break;
......
default: break;
}
}
else if (設(shè)備還需處理的其他請(qǐng)求)
{
處理;
}
else /*不支持的請(qǐng)求*/
{
發(fā)送STALL信號(hào);
return 1; /*返回錯(cuò)誤*/
}
return 0; /*返回正確*/
}
/*通過(guò)端點(diǎn)0發(fā)送數(shù)據(jù)*/
void USB_WriteEP0FIFO(void)
{
取得全局的發(fā)送數(shù)據(jù)的指針;
利用指針讀取描述符的數(shù)據(jù)并填充至端點(diǎn)0的FIFO;
通知芯片EP
}
聯(lián)系客服