在wince4.2下加载16C550串口驱动
系统是S3C2440,串口4是16C550外扩的,用于同GPRS通信。
一.注册中断
1、 在platform\\smdk2410\\inc\\Oalintr.h文件中添加
#define SYSINTR_SERIAL4 (SYSINTR_FIRMWARE+22)
同时注意修改MapIrq2SysIntr(DWORD _Irq)函数中_Irq判断条件,在我的系统中
if( _Irq<=23 )
//下面两处修改没有必要
2、 在 platform\\smdk2410\\inc\\Oalintr.inc添加
SYSINTR_SERIAL4: .equ SYSINTR_FIRMWARE+22
3、 在 platform\\smdk2410\\inc\\Oalintra.inc添加
SYSINTR_SERIAL4 EQU SYSINTR_FIRMWARE+22
二.修改注册表
物理地址:10000000,使用nGCS2
中断号0x16 = 22,物理中断Eint3
;UART3 (physical COM4) (Serial)
IF BSP_NOSERIAL !
;=============== 16c552 COM4 (Serial) ===============
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\SER24404]
"DeviceArrayIndex"=dword:3
"Irq"=dword:16
"IoBase"=dword:10000000
"IoLen"=dword:8
"Prefix"="COM"
"Dll"="SER2440.Dll"
"Order"=dword:0
"Index"=dword:4
"Priority"=dword:0
"Port"="COM4:"
"RegStride"=dword:1
"DeviceType"=dword:0
"FriendlyName"="Serial Cable on COM4:"
"Tsp"="Unimodem.dll"
"DevConfig"=hex: 10,00, 00,00, 05,00,00,00, 10,01,00,00, 00,4B,00,00, 00,00, 08, 00, 00, 00,00,00,00
ENDIF BSP_NOSERIAL !
三.修改cfw.c
1、OEMInterruptEnable()中:
case SYSINTR_SERIAL4: //16c552 Eint3
s2440INT->rSRCPND = BIT_EINT3; // to clear the previous pending states
if (s2440INT->rINTPND & BIT_EINT3)
s2440INT->rINTPND = BIT_EINT3;
s2440INT->rINTMSK &= ~BIT_EINT3;
break;
2、OEMInterruptDisable()中
case SYSINTR_SERIAL4:
s2440INT->rINTMSK |= BIT_EINT3;
break;
3、OEMInterruptDone()中
case SYSINTR_SERIAL4:
s2440INT->rINTMSK &= ~BIT_EINT3;
break;
四.修改文件armint.c
else if (IntPendVal == INTSRC_EINT3) // 16C552 int
{
s2440INT->rINTMSK |= BIT_EINT3;
s2440INT->rSRCPND = BIT_EINT3;
if (s2440INT->rINTPND & BIT_EINT3) s2440INT->rINTPND = BIT_EINT3;
//RETAILMSG(0,(TEXT("16C550 int generate\r\n")));
return(SYSINTR_SERIAL4);
}
五.修改2440_ser.c
添加如下函数,详细函数代码请看附件S2440_ser.c
//for 16C552
static
PVOID
Ser4Init(
ULONG Identifier, // @parm Device identifier.
PVOID pMddHead, // @parm First argument to mdd callbacks.
PHWOBJ pHWObj // @parm Pointer to our own HW OBJ for this device
)
static
BOOL
Ser4Open(
PVOID pHead /*@parm PVOID returned by Serinit. */
)
BOOL
Ser4PowerOn(
PVOID pHead // @parm PVOID returned by SerInit.
)
static
BOOL
Ser4EnableIR(
PVOID pHead, // @parm PVOID returned by Serinit.
ULONG BaudRate // @parm PVOID returned by HWinit.
)
static
BOOL
Ser4DisableIR(
PVOID pHead /*@parm PVOID returned by Serinit. */
)
static
BOOL
Ser4PowerOff(
PVOID pHead // @parm PVOID returned by SerInit.
)
static
BOOL
Ser4Deinit(
PVOID pHead // @parm PVOID returned by SerInit.
)
static
ULONG
Ser4Close(
PVOID pHead // @parm PVOID returned by SerInit.
)
static
VOID
Ser4GetCommProperties(
PVOID pHead, // @parm PVOID returned by SerInit.
LPCOMMPROP pCommProp // @parm Pointer to receive COMMPROP structure.
)
BOOL
Ser4_GetRegistryData(PSER_16552_INFO pHWHead, LPCTSTR regKeyPath)
增加:
const
HW_VTBL Io16552VTbl4 = {
Ser4Init,
SL_PostInitq,
Ser4Deinit,
Ser4Open,
Ser4Close,
SL_GetInterruptTypeq,
SL_RxIntrq,
SL_TxIntrExq,
SL_OtherIntrq,
SL_LineIntrq,
SL_GetRxBufferSizeq,
Ser4PowerOff,
Ser4PowerOn,
SL_ClearDTRq,
SL_SetDTRq,
SL_ClearRTSq,
SL_SetRTSq,
Ser4EnableIR,
Ser4DisableIR,
SL_ClearBreakq,
SL_SetBreakq,
SL_XmitComCharq,
SL_GetStatusq,
SL_Resetq,
SL_GetModemStatusq,
Ser4GetCommProperties,
SL_PurgeCommq,
SL_SetDCBq,
SL_SetCommTimeoutsq
};
再增加:
const HWOBJ Io16552Obj4 = {
THREAD_AT_INIT,
SYSINTR_SERIAL4,
(PHW_VTBL) &Io16552VTbl4
};
修改GetSerialObject
PHWOBJ
GetSerialObject(
DWORD DeviceArrayIndex
)
{
PHWOBJ pSerObj;
RETAILMSG(1,(TEXT("GetSerialObject%d\r\n"),DeviceArrayIndex));
IRDA = DeviceArrayIndex;
// Now return this structure to the MDD.
if ( DeviceArrayIndex == 0 )
pSerObj = (PHWOBJ)(&IoObj);
else if(DeviceArrayIndex == 1)
pSerObj = (PHWOBJ)(&IoObj2);
else if(DeviceArrayIndex == 2)
pSerObj = (PHWOBJ)(&IoObj3);
else if(DeviceArrayIndex == 3)
pSerObj = (PHWOBJ)(&Io16552Obj4);
else
pSerObj = (PHWOBJ)(&IoObj);
return (pSerObj);
}
六.SOURCE文件
修改2440串口驱动的SOURCE文件,添加ser16552.c,见附录。
SOURCES= \
ser2440_ser.c \
ser2440_hw.c \
ser16552.c
看源代码可以搞清楚整个流程,MDD也需要看一下,但不需要修改。
在OEMInitInterrupts对Eint3中断进行设置, 上升沿触发
//gerryzhou add ____ Configure EINT3(GPF3) for 16c552 com4 interrupt.
s2440IOP->rGPFCON = (s2440IOP->rGPFCON & ~(0x3<<6)) | (0x2<<6); //GPF3==EINT3
s2440IOP->rGPFUP = (s2440IOP->rGPFUP | (0x1<<3)); // Disable pull-up.
s2440IOP->rEXTINT0=(s2440IOP->rEXTINT0 & ~(0xf<<12)) | (0x4<<12); // Rising edge triggered triggered.