本篇進入代碼實現層:OHCI 硬體初始化、關鍵寄存器配置、中斷控制器 (AIC) 接線、關鍵常量定義來源。代碼基於 AT91 官方例程 AT91RM9200-BasicUHP 改造,新增中斷向量初始化。
ohciHardInit()short ohciHardInit(void) {
unsigned int reg;
// 1. 開啟 USB Host 時鐘
AT91F_UHP_CfgPMC();
AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_UHP;
// 2. 強制 OHCI 控制器複位
pUhp->UHP_HcControl = 0;
// 3. 設定 HCCA (Host Controller Communication Area) 位址
pUhp->UHP_HcHCCA = (unsigned int)&HCCA;
// 4. 啟用列表處理(控制/批量/周期性)
pUhp->UHP_HcControl = 0; // 先清零再逐位啟用
// 5. 設定幀間隔與周期性啟動閾值
pUhp->UHP_HcFmInterval = AT91C_FMINTERVAL; // 12000 (1ms 幀)
pUhp->UHP_HcPeriodicStart = AT91C_PRDSTRT; // 90% 幀長度
// 6. 初始化 Done Head 指標
pUhp->UHP_HcBulkDoneHead = 0x00;
HCCA.UHP_HccaDoneHead = 0x0000;
// 7. 進入 Operational 狀態
reg = pUhp->UHP_HcControl;
pUhp->UHP_HcControl = 0x80; // HCFS = Operational
// 8. 開啟兩個 Root Hub 埠電源
pUhp->UHP_HcRhPortStatus[0] = 0x00000100; // LPS = 1
pUhp->UHP_HcRhPortStatus[1] = 0x00000100;
// 9. Root Hub 描述符 A:無電源切換、無過流保護
pUhp->UHP_HcRhDescriptorA = OHCI_HC_RHDESCRIPTORA_NPS;
pUhp->UHP_HcRhStatus = 0x00010000; // CRWE = 1
// 10. UDP 上拉電阻(調試發現必須設定,否則數據異常)
AT91F_PIO_SetOutput(AT91C_BASE_PIOD, AT91C_PIO_PD5);
// 11. 啟用 OHCI 中斷源
pUhp->UHP_HcInterruptEnable =
OHCI_HC_INTR_MIE | // Master Interrupt Enable
OHCI_HC_INTR_RHSC | // Root Hub Status Change
OHCI_HC_INTR_UE | // Unrecoverable Error
OHCI_HC_INTR_WDH | // Writeback Done Head (關鍵:TD 完成)
OHCI_HC_INTR_FNO; // Frame Number Overflow
// 清除待處理中斷狀態
pUhp->UHP_HcInterruptStatus =
OHCI_HC_INTR_RHSC | OHCI_HC_INTR_UE |
OHCI_HC_INTR_WDH | OHCI_HC_INTR_FNO;
// 12. 配置 AIC 中斷控制器
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
AT91C_ID_UHP,
AT91C_AIC_PRIOR_HIGHEST,
AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED,
AT91F_ASM_UHP_Handler); // 彙編包裝的 ISR 入口
AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_UHP);
return 0;
}
| 寄存器 | 作用 | 關鍵值 |
|---|---|---|
HcControl | 控制器狀態機 (Reset/Resume/Operational)、列表啟用位 | 0x80 = Operational |
HcHCCA | 主機控制器通訊區物理地址 (256-byte 對齊) | &HCCA |
HcFmInterval | 幀長度 (12000 = 1ms @ 12MHz) | AT91C_FMINTERVAL |
HcPeriodicStart | 周期性列表最晚啟動時間 (佔幀 90%) | AT91C_PRDSTRT |
HcInterruptEnable | 中斷源啟用位圖 | MIE|RHSC|UE|WDH|FNO |
HcRhPortStatus | Root Hub 埠狀態/控制 | LPS (Port Power) = 1 |