WINCE6.0+S3C6410串口驱动
********************************LoongEmbedded************************
作者:LoongEmbedded(kandi)
時間:2011.05.21
類別:WINCE驅動開發
********************************LoongEmbedded************************
WINCE串口驅動
?
備注:本博文基于Real6410+WINCE6.0的系統來學習的
?
1.????? 硬件設計
?
圖1
UART接口在此開發板中的應用如下:
UART0作為調試口來使用
?
圖2
UART1用于和GPRS模塊SIM900通信
?
圖3
UART2用于和GPS模塊COMPASS_EB818通信
?
圖4
UATR3用于和藍牙模塊通信
?
圖5
?
2.????? 軟件設計
?
2.1?? WINCE串口驅動的架構
在WINCE系統中,串口驅動是作為一個流驅動的形式存在,其驅動架構如下圖所示:
?
圖6
串口驅動分為MDD層和PDD層,DD層對上層的Device Manager(device.dll)提供了標準的流設備驅動接口(COM_xxx),PDD層實現了HWOBJ結構及結構中若干針對于串口硬件操作的函數指針,這些函數指針將指向PDD層中的串口操作函數。DDSI是指MDD層與PDD層的接口,在串口驅動中實際上就是指HWOBJ,PDD層會傳給MDD層一個HWOBJ結構的指針,這樣MDD層就可以調用PDD層的函數來操作串口。
?
2.2?? MDD層的導出接口函數
MDD層為系統提供流設備接口,這些接口微軟已經實現,但還是有必要學習一下
?
2.2.1???????? COM_Init
此函數始化串口設備,該函數通過讀取注冊表獲得串口設備號,并獲得相應的HWOBJ的結構指針,通過該指針調用PDD層的硬件初始化函數初始化串口。
Identifier:如果驅動被設備管理器加載,那么這個參數將包含一個注冊表鍵值在” HKEY_LOCAL_MACHINE/Drivers/Active”路徑下。如果驅動是通過調用RegisterDevice函數來加載的,那么這個值等于dwInfo的值。在COM_Init中,會先打開該鍵值,用返回的句柄來查詢DeviceArrayIndex值,并根據該值獲得PDD層的HWOBJ結構指針,下圖是COM_Init函數的一部分
?
圖7
?
?
2.2.2???????? COM_Deinit
卸載串口設備,該函數中主要做了一些釋放資源的操作。也可以被DeregisterDevice函數調用,而DeregisterDevice函數可以被應用程序調用。
?
2.2.3???????? COM_PreDeinit
?
2.2.4???????? COM_Open
打開串口設備,當應用程序調用CreateFile函數打開串口時,該函數會被調用來打開串口設備。
pContext:COM_Init函數返回的Handle。
AccessCode:設置訪問模式,比如共享讀或者是讀寫模式。
ShareMode:在參數從應用程序中的CreateFile函數中傳來,表示是否支持獨自占有。
?
2.2.5???????? COM_Close
關閉串口設備,當應用程序調用CloseHandle函數的時候會調用這個函數。
pContext:COM_Init函數返回的Handle。
?
2.2.6???????? COM_PreClose
?
2.2.7???????? COM_Read
讀串口數據,應用程序調用ReadFile函數讀串口的時候,會調用該函數。
pContext:COM_Open函數返回的Handle。
pTargetBuffer:指向一個用于存放讀到數據的Buffer。
BufferLength:pTargetBuffer指向的Buffer的大小。
pBytesRead:實際讀到的數據的大小。
?
2.2.8???????? COM_Write
寫串口數據。應用程序調用WriteFile函數寫串口的時候,該函數被調用。
pContext:COM_Open函數返回的Handle。
pSourceBytes:指向一個Buffer,該Buffer包含要寫入串口的數據。
NumberOfBytes:要寫入串口的數據的大小。
?
2.2.9???????? COM_Seek
?
2.2.10?????? COM_PowerDown
該函數主要用于串口設備從正常模式進入suspend狀態之前需要做的動作。
pContext:串口設備的Handle。
?
2.2.11?????? COM_PowerUp
該函數主要用于串口設備從suspend模式恢復到正常模式。
pContext:串口設備的Handle。
?
2.2.12?????? COM_IOControl
該函數主要實現了一些串口的IO控制,它會被應用層的一些串口函數調用來獲得或者設置串口的狀態。
dwOpenData:COM_Open函數返回的Handle。
dwCode:I/O控制操作碼。
pBufIn:傳入的Buffer。
dwLenIn:傳入的Buffer的大小。
pBufOut:傳出的Buffer。
dwLenOut:傳出的Buffer的大小。
pdwActualOut:實際傳出的數據的大小。
對于串口驅動來說,COM_IOControl函數非常有用,應用程序通過調用COM_IOControl函數并傳入不同的操作碼,實現了控制串口的功能。這里列舉一些操作碼如下:
操作碼 ? 解釋
IOCTL_SERIAL_CLR_DTR
設置串口的DTR管腳為低
IOCTL_SERIAL_CLR_RTS
設置串口的RTS管腳為低
IOCTL_SERIAL_DISABLE_IR
禁用串口的紅外模式
IOCTL_SERIAL_ENABLE_IR
啟用串口的紅外模式
IOCTL_SERIAL_GET_COMMSTATUS
清除串口設備的異常標記并返回當前狀態
IOCTL_SERIAL_GET_DCB
獲得串口的DCB結構
IOCTL_SERIAL_GET_MODEMSTATUS
獲得當前Modem的控制寄存器值
IOCTL_SERIAL_GET_PROPERTIES
重新獲得當前串口設備的硬件屬性
IOCTL_SERIAL_GET_TIMEOUTS
獲得串口設備的讀寫超時
IOCTL_SERIAL_GET_WAIT_MASK
獲得等待事件標記掩碼
IOCTL_SERIAL_IMMEDIATE_CHAR
在發送數據前,先發送一個特定的字符
IOCTL_SERIAL_PURGE
清除串口中的輸入輸出Buffer,也可以中止未進行的讀寫操作
IOCTL_SERIAL_SET_BREAK_OFF
串口通訊從中斷狀態恢復
IOCTL_SERIAL_SET_BREAK_ON
設置串口為中斷狀態,停止發送接收數據
IOCTL_SERIAL_SET_DCB
設置串口的DCB結構
IOCTL_SERIAL_SET_DTR
設置串口的DTR管腳為高
IOCTL_SERIAL_SET_QUEUE_SIZE
目前,在微軟的MDD層代碼中沒有支持
IOCTL_SERIAL_SET_RTS
設置串口的RTS管腳為高
IOCTL_SERIAL_SET_TIMEOUTS
設置串口的讀寫操作超時
IOCTL_SERIAL_SET_WAIT_MASK
設置等待事件標記掩碼
IOCTL_SERIAL_SET_XOFF
軟件流控模式下,終止數據傳輸
IOCTL_SERIAL_SET_XON
軟件流控模式下,啟動數據傳輸
IOCTL_SERIAL_WAIT_ON_MASK
等待一個與事件掩碼中匹配的事件
上述的操作碼,很多都會被應用程序調用,看看MDD層中的實現,其中一些也是調用了PDD層下的函數來完成對串口硬件的設置。
?
2.3?? PDD層為MDD層提供的接口
MDD層和PDD層交互的接口是結構體HWOBJ,在串口驅動中,HWOBJ結構中的函數實現了對串口硬件的操作,并在MDD層被調用,定義如下:
?
圖8
BindFlags:用于控制MDD層還是PDD層來啟動IST,具體值如下
?
圖9
dwInitID:系統的中斷號 ,此成員本來用于當BindFlags取值為THREAD_IN_MDD,也就是在MDD層啟動IST線程時記錄串口使用的邏輯中斷號,但是當前的串口驅動實在PDD層啟動IST,所以現在dwIntID成員的取值不是中斷號信息,而是借用來記錄與串口驅動程序的PDD層對應的串口的端口號。
?
pFuncTbl: 指向一個PHW_VTBL結構,該結構中包含一個函數指針列表,這些函數指針指向串口硬件操作函數,用于操作串口。
?
那么結構體HWOBJ的成員是在哪里賦值的呢?從圖7我們控制COM_Init函數調用函數GetSerialObject來獲取PDD層的創建并且初始化的串口對象,就是在該函數中初始化HWOBJ的結構體成員的,如下圖
?
圖10
下面我們來看HW_VTBL類型的全局變量IoVTbl的定義
?
圖11??????????????????
????????????? 圖12
下面來學習這些函數的功能
2.3.1???????? HWInit函數
結合圖7、11和12可知COM_Init函數在調用GetSerialObject函數來填充全局變量IoVTbl的成員函數指針后,就調用HWInit也就是SerInit函數來初始化PDD層,下面來看看這個函數的實現
?
圖13
下面就來看看CreateSerialObject函數體
?
圖14
?
2.3.2???????? HWPostInit函數
在MDD層COM_Init函數的末尾階段,在初始化所有的數據結構之后和準備IST開始處理中斷之前,會調用該函數來執行一些必要的操作。代表性地,可以在該函數中enable硬件中斷,但這里只是具體沒有做實質上的工作,只是
m_dwInterruptFlag = INTR_NONE;
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
?
?
?
2.3.3???????? HWDeinit函數
當卸載串口驅動的時候,MDD層會調用該函數來釋放一些資源。
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
圖15
2.3.4???????? HWOpen函數
MDD層調用該函數來打開一個串口設備,并且為此串口設備供電。
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
圖16
下面我們學習InitLine函數
?
圖17
下面看看EnableInterrupt函數
?
圖18
繼續深入看看Write_UINTSP函數,如下:
?
圖19
假如現在加載的是UART1對應的出口驅動,我們先來看下面調用關系m_pReg在哪里初始化的,
CreateSerialObject()->CPdd6410Serial1::()->CPdd6410Uart::Init()->CPdd6410Uart::MapHardware()+CPdd6410Uart::CreateHardwareAccess()下面就來看看這兩個函數體:
?
圖20
結合下圖
?
圖21
?
2.3.5???????? HWClose函數
關閉由HWInit函數初始化的設備。
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
2.3.6???????? HWGetIntrType函數
當中斷發生的時候,MDD層會調用該函數來獲取中斷類型,可能的中斷類型值有INTR_NONE、INTR_LINE、INTR_RX、INTR_TX和INTR_MODEM。
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
2.3.7???????? HWGetRxStart函數
返回硬件接收buffer的起始位置。
pContext:這個參數目前沒有使用。
?
2.3.8???????? HWGetBytes函數
當RX_INTR從HWGetIntrTypes函數返回時,MDD層會調用HWGetBytes函數來從UART中獲取接收到的數據。
?
2.3.9???????? HWRxIntrHandler函數
接收數據中斷處理函數。
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
pTargetBuffer:接收到的數據要存放的buffer的起始地址。
pByteNumber:接收到的數據的字節數。
該函數實際會調用ReceiveInterruptHandler函數,我們下面就來看此函數
?
圖22
2.3.10?????? HWLineIntrHandler函數
該函數調用LineInterruptHandler()->GetModemStatus()來收集串口的line狀態并且更新串口驅動狀態信息。
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
圖23
?
2.3.11?????? HWGetRxBufferSize函數
該函數返回硬件buffer能夠保持的最大字節數,確保要接收保存數據的buffer至少大于一個硬件buffer要保存的數據數。
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
2.3.12?????? HWTxIntrHandler函數
該函數處理串口數據發送中斷,該函數指針就是由XmitInterruptHandler來賦值的,下面來分析這個函數。
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
pSourceBuffer:發送數據Buffer。
pByteNumber:最大能夠發送的數據的大小。函數返回時,指向實際發送的數據的大小。
?
圖24
m_AutoFlowEnabled:用于表示是否支持自動流控。
fOutxCtsFlow:表示串口在發送數據時要檢測CTS(清除發送)引腳的信號狀態,如果該成員為TRUE并且對方將CTS的電平拉低,則發送數據;如果CTS引腳恢復為高電平時就暫停發送數據。
fOutxDsrFlow:成員表示串口在發送數據時要監視DSR(數據通信設備就緒,比如GPRS模塊SIM900)引腳的信號狀態,如果該成員為TRUE并且對方(這里假設是SIM900模塊)將DSR的電平拉低,則發送數據;如果DSR引腳恢復為高電平時才繼續發送數據。
IsCTSOff()和IsDSROff()函數分別用于判斷UMSTAT寄存器的第4和第5位的狀態值,見下圖
?
圖25
2.3.13?????? HWModemIntrHandler函數
該函數代替了HWOtherHandler函數,該函數實際會調用
ModemInterruptHandler函數,然后通過調用GetModemStatus函數來實現,下面來看此函數
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
圖26
2.3.14?????? HWPutBytes函數
該函數用于寫數據到硬件來直接發送數據。
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
pSrc:指向要發送的數據Buffer。
NumberOfBytes:要發送的數據長度。
pBytesSent:實際發送的數據長度。
?
?
?
?
2.3.15?????? HWPowerOff函數
在進入睡眠狀態前,MDD層調用該函數來通知PDD層對關閉PCLK對串口提供時鐘,以節省功耗,見下圖
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
?
?
2.3.16?????? HWPowerOn函數
在從睡眠狀態喚醒的時候,MDD層調用該函數來通知PDD層對關閉PCLK對串口提供時鐘,以節省功耗
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
圖27
?
2.3.17?????? HWClearDTR函數
該函數用于清除DTR(數據終端設備就緒)信號,通過調用SetDTR函數來實現
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
2.3.18?????? HWClearRTS函數
該函數用于清除RTS(請求發送)信號,通過調用SetRTS函數來實現
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
?
圖28
結合下圖可以更深刻去理解
?
圖29
?
?
2.3.19?????? HWSetDCB函數
該函數用于設置串口設備的信息,通過調用SetDCB函數來實現。
pContext:指向HWIint函數返回的設備上下文結構體,此結構體包含了對設備進行具體描述的數據信息。
pDCB:指向DCB結構,該結構描述相關的串口硬件設置信息。
?
圖30
2.3.20??????
?
?
2.4?? 流控的相關概念和方式
流控的“流”指進出串口的數據流,數據在串口之間傳輸時,如果接收方由于CPU負荷很重或者串口的中斷優先級很低而導致接收數據緩沖區被充滿,而發送方并不知情的情況下繼續發送的數據就會被接收方丟掉,為了解決這個問題,引進了串口的流控機制。這樣當接收方數據處理不過來時,就會發出“暫停接收”的信號,發送端就停止發送,直到收到“可以繼續發送”的信號再繼續發送數據。
流控的方式有硬件和軟件流控的方式,其中硬件流控有DTR/DSR和RTS/CTS另種不同的硬件流控方式;軟件流是通過向對方發送特殊的指示字符,這就是被稱為X-ON/X-OFF的軟件流控方式,下面主要學習硬件流控方式
?
⑴RTS/CTS流控方式
?
圖31
RTS/CTS流控方式的工作原理其實就是RTS和CTS兩個引腳的工作方式,我們以DTE(這里為UART1)和DCE(這里為SIM900)為例來說明。當UART1要發送數據時,就將nRTS的引腳拉低,表示UART1要向SIM900發送數據。nCTS信號時nRTS的響應信號,在SIM900準備好以后,就將引腳nCTS引腳信號拉低(結合圖25和29來理解),這就表示SIM900準備好接受UART1發來的數據,這時候UART1就可以從TX引腳給SIM900發送數據了。
?
⑵DTR/DSR流控方式
這種方式和RTS/CTS相似,DTR(data terminal ready,數據終端就緒)引腳置高表示數據終端設備處在有效的可使用狀態,DSR(data set ready,數據通信設備就緒)引腳置高則表示數據通信設備處于可使用的狀態。這兩個引腳為高電平僅表示對應的設備有效存在,并不表示它們之間的通信鏈路可以進行數據傳輸,這是它們和RTS/CTS的不同之處。在串口直接通信并且不使用DTR/DSR流控的情況下,通常將這兩個引腳直接接到電源上,串口一上電就拉高有效。
?
總結
以上是生活随笔為你收集整理的WINCE6.0+S3C6410串口驱动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Keyboard驱动中button中断的
- 下一篇: WINCE6.0+S3C6410下的DM