|
首先找到DriverEntry函数,看到MrvDrvNMC.InitializeHandler = MrvDrvInitialize;
先从初始化函数入手吧,在MrvDrvInitialize函数中,一直到 If_Initialize 才是需要移植的。If_Initialize 的函数原型是Spi_Init,然后再Spi_Init中要修改的就是 pxa_gspi_Init。
pxa_gspi_init中主要做两件事:
1。ssp_init_hw(pHC)
2。ssp_read_register((DWORD)pHC, ®val, 0x02); 读出的值如果是0x000b就OK了
接下来看ssp_init_hw
首先是映射寄存器地址空间(从物理地址映射到逻辑地址,gpio/intr/clk等寄存器)。例如:
PHYSICAL_ADDRESS pa;
RETAILMSG(1,(TEXT("entering ssp_init_hw!!!\r\n")));
pa.QuadPart = GPIO_BASE;
pHC->pGPIORegs = (GPIO_REGS_T*)MmMapIoSpace(pa, sizeof(GPIO_REGS_T), FALSE);
然后就是设置ssp的寄存器了,我的代码是这样的
pHC->pGPIORegs->pio_mux2_set |= (0x03<<9)|(0x01<<12); //设置管脚为SSP功能
pHC->pGPIORegs->pio_mux_clr |= (1<<5); //设置片选脚为输出(GPO5)
pHC->pGPIORegs->pio_dir_set |= (1<<30);
pHC->pCLKRegs->clkpwr_ssp_blk_ctrl = 0x01; //使能SSP时钟
pHC->pSSPRegs->cr1 |= (1<<1); //使能SSP控制器
pHC->pSSPRegs->cr0 = (15<<0) | //16位
(0<<4)|
(0<<6)|
(0<<7)|
(2<<8);
pHC->pSSPRegs->cpsr = 0x20;
pHC->pSSPRegs->imsc = 0x00; //禁止SPI中断
pHC->pSSPRegs->dmacr = 0x00; //禁止DMA方式
之后调用intr_init(pHC)来初始化中断。
再看intr_init(pHC)
首先是初始化中断控制器
pHC->pINTCRegs->er |= (1<<22);
pHC->pINTCRegs->atr |= (1<<22); //GPI00 边沿触发 (edge trigger)
pHC->pINTCRegs->apr &= ~(1<<22); //GPI00 下边沿出发(falling edge)
然后填充一些数据
pHC->DevIntrInfo.irq = OAL_INTR_IRQ_GPI_00; //物理中断号
pHC->DevIntrInfo.dwSysIntr = SYSINTR_UNDEFINED; //逻辑中断号
pHC->DevIntrInfo.pIstFunc = (MYISTFUNC) dev_ist; //中断ist
pHC->DevIntrInfo.param = (LPVOID)pHC;
然后调用setupInterrupt进一步初始化中断
进入setupInterrupt函数再来看看
首先映射逻辑中断号
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &pMyIntrInfo->irq, sizeof(DWORD),
&pMyIntrInfo->dwSysIntr, sizeof(pMyIntrInfo->dwSysIntr), NULL))
{
DEBUGMSG(1, (TEXT("Error obtaining SYSINTR value!\n")));
goto errFuncRet;
}
原本代码中把这一段注释掉了,我没明白为什么要注释掉,感觉应该是不可缺少的,有谁知道请指教一下。
然后是映射事件,创建线程
if (! InterruptInitialize(pMyIntrInfo->dwSysIntr, pMyIntrInfo->hIntrEvent, NULL, 0))
{
RETAILMSG(1, (TEXT("%s - InterruptInitialize(%d,%08x) Failed\r\n"),
TEXT(____), pMyIntrInfo->dwSysIntr, pMyIntrInfo->hISTHandle));
goto errFuncRet;
pMyIntrInfo->hISTHandle = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
0,
myIST,
pMyIntrInfo,
CREATE_SUSPENDED,
&threadID);
这些都不用改。
这样,ssp_init_hw函数就完成了。