方 明 林建中
[摘要]給出利用FPGA上實現(xiàn)的UART IP核,實現(xiàn)在微處理器S3C2440A總線上動態(tài)擴展多串口電路,論述基于發(fā)送和接收FIFO下的UART接口模塊設(shè)計以及各主要功能模塊實現(xiàn)。另外,給出節(jié)省中斷資源的用于實現(xiàn)串口動態(tài)擴展的電路。最后,給出WINCE5.0下多串口設(shè)備驅(qū)動程序的實現(xiàn)框架。
[關(guān)鍵詞]UART S3C2440A WINCE 5.0
中圖分類號:TP3文獻標(biāo)識碼:A文章編號:16717597(2009)0310015-03
一、引言
由于基于FPGA/CPLD實現(xiàn)的電路在靈活性,體積,成本方面都有其優(yōu)勢。本文從實際應(yīng)用的角度出發(fā),為了滿足高速數(shù)據(jù)傳輸要求,利用FPGA實現(xiàn)了分別擁有512字節(jié)的發(fā)送和接收FIFO的UART接口模塊,并采用接口電路動態(tài)擴展UART,以實現(xiàn)微處理器S3C2440A上實現(xiàn)擴展多串口的目的,在最少改動電路下滿足要求高速傳輸?shù)亩啻趫龊?。同時,本文還給出了在嵌入式操作系統(tǒng)WINCE5.0下的多串口驅(qū)動實現(xiàn)過程。
二、硬件電路總體設(shè)計
硬件電路實現(xiàn)如圖(1)所示,主要有微處理器S3C2440A,兩片緩沖器74LVTH162245分別用于地址總線/片選和數(shù)據(jù)總線的緩沖,以及一塊FPGA模塊組成。微處理器是三星32bit ARM920T內(nèi)核的S3C2440A,其主頻在400MHZ,最高可達533MHZ,可擴展外部存器,具有豐富的I2C,SPI,CAN,以太網(wǎng),USB等控制接口,還可通過總線擴展其他接口電路,應(yīng)用層面非常廣泛。而FPGA模塊的功能是使用VHDL實現(xiàn)了UART IP核以及多串口擴展控制電路,該控制電路通過產(chǎn)生多個串口的片選以及通過微處理器的1個GPIO口作為中斷使能信號來高效管理多個串口中斷共用一個中斷的有效方法來實現(xiàn)多串口的擴展,通過這不僅節(jié)約了中斷資源,同時,也保證了多個串口中斷的無漏檢測和服務(wù)。另外,通過電平轉(zhuǎn)換芯片,如MAX232,MAX485,MAX491它們可以分別實現(xiàn)RS232,RS485以及RS422接口串口。
(一)微處理器S3C2440A資源分配
S3C2440A中的內(nèi)存控制器提供了要求外部內(nèi)存訪問的內(nèi)存控制信號,總共有8個塊,地址從0x0000_000~0x4000_0000,每個塊的大小為128MB,6個塊可以用于擴展ROM,SRAM,其他兩個用于ROM,SDRAM。每個塊都有一個片選信號nGs0~nGs7,當(dāng)某塊的片選信號有效時,就可以通過讀寫信號訪問該塊數(shù)據(jù)。在擴展多串口的電路,我們采用了第6塊內(nèi)存塊,地址從0x2800_0000~0x3000_0000,片選信號為nGs5,來作為訪問多串口數(shù)據(jù)的區(qū)域。
(二)UART IP核的設(shè)計
采用硬件描述語言VHDL,在ALTERA公司的現(xiàn)場可編程門陣列(FPGA)上實現(xiàn)了擁有512字節(jié)接收和發(fā)送FIFO的軟件上兼容16550的UART核。在UART IP核中主要由讀寫控制模塊,寄存器和發(fā)送/接收FIFO模塊,接收模塊,發(fā)送模塊,波特率發(fā)生器以及中斷控制產(chǎn)生模塊組成。圖(2)顯示了UART的數(shù)據(jù)發(fā)送/接收的格式,從CPU端和設(shè)備端看,UART接收部分實現(xiàn)在設(shè)定波特率下將設(shè)備端的串行數(shù)據(jù)轉(zhuǎn)換成并行數(shù)據(jù)給CPU,而發(fā)送部分實現(xiàn)將CPU端的并行數(shù)據(jù)轉(zhuǎn)換成串行數(shù)據(jù)再以設(shè)定的波特率發(fā)送給設(shè)備。其中,在設(shè)備端的數(shù)據(jù)幀格式中,起始位為兩個比特寬度,用于在UART接收時的辨別一幀數(shù)據(jù)開始的判斷;通過對UART內(nèi)部寄存器的配置,可以將配置數(shù)據(jù)位數(shù)5~8位,是否有校驗位和校驗類型,以及停止位的位數(shù)為1或1.5或2。
1.UART實現(xiàn)的各功能描述
(1)讀寫控制模塊主要負責(zé)處理與系統(tǒng)處理器那邊的通信,所有內(nèi)部寄存器的讀和寫通過這個模塊完成。
(2)UART寄存器模塊處理所有內(nèi)部寄存器,其他模塊的寄存器信息在這個模塊中被匯集并且對所有塊都可得到。
(3)接收模塊接收串行數(shù)據(jù),通過預(yù)先設(shè)置可以識別數(shù)據(jù)寬度諸如5,6,7,8比特,不同的校驗設(shè)置比如寄校驗,偶校驗或無校驗,以及不同的停止位諸如1,1.5,2比特。該模塊還對接收數(shù)據(jù)流進行錯誤檢測諸如溢出錯誤,幀錯誤,校驗錯誤以及超時錯誤。如果接收數(shù)據(jù)沒有錯誤,將其數(shù)據(jù)放入接收FIFO中。
(4)中斷控制模塊依賴發(fā)送FIFO的狀態(tài)和它的發(fā)送的和接收的數(shù)據(jù)的狀態(tài)來發(fā)送一個中斷信號給處理器。
(5)波特率發(fā)生器將輸入的時鐘信號除以一個可編程的數(shù)值,再將其接口除以16就得到了發(fā)送和接收用的波特率。
(6)發(fā)送模塊處理將發(fā)送的數(shù)據(jù)寫入到發(fā)送FIFO中,并且按照UART的數(shù)據(jù)格式再數(shù)據(jù)發(fā)送的時候加上開始位,校驗位以及停止位,這樣保證接收設(shè)備可以做適當(dāng)錯誤處理和接收。
2.發(fā)送模塊實現(xiàn)
由于微處理器在較高時鐘頻率上發(fā)送數(shù)據(jù)給UART,為了保證UART在發(fā)送保持寄存器(THR)中的數(shù)據(jù)不被后一幀數(shù)據(jù)給覆蓋,在UART中設(shè)計了容量為512字節(jié)的發(fā)送FIFO,基于FIFO設(shè)計的發(fā)送數(shù)據(jù)有限狀態(tài)機如圖(3)所示,一開始,發(fā)送FIFO處于空的狀態(tài),通過使能FIFO寫入信號將數(shù)據(jù)先放入FIFO(只要FIFO處于非全滿狀態(tài)將一直可以接收來自CPU的數(shù)據(jù))。然后,通過地址、片選和寫控制信號讀取發(fā)送保持寄存器的狀態(tài),當(dāng)判斷其為空時,在第一時鐘周期先使能FIFO讀取信號,將FIFO中的一個數(shù)據(jù)先放在總線上,然后在后面的時鐘周期里產(chǎn)生UART的寫控制信號,將放在總線上的數(shù)據(jù)寫入到UART的發(fā)送保持寄存器,再通過移位寄存器將數(shù)據(jù)按波特率發(fā)送到設(shè)備接收端。這樣做即可保證發(fā)送數(shù)據(jù)的完整性,同時提高了數(shù)據(jù)的發(fā)送速度。
3.接收模塊實現(xiàn)
當(dāng)處理器由于某種原因,導(dǎo)致在接收來自外部串行設(shè)備的數(shù)據(jù)不被后面的數(shù)據(jù)給覆蓋,在設(shè)計中采用了一個512字節(jié)的接收FIFO來緩沖接收數(shù)據(jù)。圖(4)顯示了基于接收FIFO的接收模塊的狀態(tài)機,當(dāng)UART檢測到起始數(shù)據(jù)位并將接收到的一幀完整數(shù)據(jù)去除開始位,校驗位和停止位后放入接收緩沖寄存器(RBR),然后,發(fā)出接收數(shù)據(jù)準(zhǔn)備信號(TXRDY置位),接著在第一時鐘周期產(chǎn)生訪問UART的讀信號(RDn)將其RBR中的數(shù)據(jù)讀到接收FIFO輸入數(shù)據(jù)線上,在隨后時鐘周期里再使能接收FIFO寫入信號,將FIFO輸入數(shù)據(jù)線上的數(shù)據(jù)存到FIFO中。當(dāng)接收FIFO中的數(shù)據(jù)達到FIFO觸發(fā)等級(在FIFO控制器中預(yù)先設(shè)置了觸發(fā)中斷數(shù),通常是1,4,8,14個字節(jié))時發(fā)送中斷信號給處理器請求接收數(shù)據(jù),這時當(dāng)接收到處理器的讀信號有效時,就產(chǎn)生接收FIFO的讀取使能信號,將FIFO中的數(shù)據(jù)按照先入先出的方式放到外部數(shù)據(jù)總線上以讓處理器讀取。
(三)多串口擴展控制電路
該電路主要負責(zé)對擴展的UART進行片選控制,以及通過微處理器的1個GPIO口作為中斷使能信號來高效管理多個串口中斷共用一個中斷。為了選種擴展的UART,通過處理器的地址訪問片選信號nGs5以及地址線addr[15..3]來譯碼器產(chǎn)生UART的片選信號。對擴展四個UART來說,其地址依次為0x001x,0x002x,0x003x,0x004x。另外中斷使能信號(inten)的地址為0x0100。各UART中斷采用或運算合并產(chǎn)生一個中斷,當(dāng)中斷使能信號有效時,發(fā)送中斷給處理器。在硬件驅(qū)動層處理器響應(yīng)中斷并進入中斷服務(wù)程序,在中斷服務(wù)過程中,處理器按順序逐個檢查多個擴展口的串口中斷源,有中斷請求的就給予服務(wù),并置中斷使能信號(inten)無效。當(dāng)剛剛檢測過的中斷又出現(xiàn)時,一方面靠擴展控制電路中的移位寄存器將INTR鎖存,另一方面,擴展控制電路中的8位狀態(tài)機保證了一定的延時,使得上一中斷服務(wù)順利完成,完成后再將中斷使能信號(inten)變?yōu)橛行б越邮蘸罄m(xù)的中斷。在延時中,中斷控制程序把堆棧中的內(nèi)容返回給處理器的寄存器,恢復(fù)能獲得的響應(yīng)。這樣,即使在多個串口中斷密集發(fā)生的環(huán)境下,擴展的多個串口仍可獲得實時性和可靠性較高的中斷。具體VHDL實現(xiàn)代碼如下:
con_pro : process(nreset,clk)
begin
if ngcs5='0' and a(15 downto 3)="0000000000010" then cs(0)<='1'; else cs(0)<='0';
end if;--片選UART1
if ngcs5='0' and a(15 downto 3)="0000000000100" then cs(1)<='1'; else cs(1)<='0';
end if;-- 片選UART2
if ngcs5='0' and a(15 downto 3)="0000000000110" then cs(2)<='1'; else cs(2)<='0';
end if;-- 片選UART3
if ngcs5='0' and a(15 downto 3)="0000000001000" then cs(3)<='1'; else cs(3)<='0';
end if;-- 片選UART4
add<=a(2 downto 0);--訪問UART內(nèi)部寄存器地址
reset<=not(nreset);--復(fù)位UART信號
if ngcs5='0' and a="0000000100000000" then
lck_sel<='1';
else lck_sel<='0'; end if;--中斷使能信號
if nreset='0' then LCK<='0';
elsif rising_edge(nwe) then if lck_sel='1' then dffin<=data(0);-- 數(shù)據(jù)輸入到中斷鎖存寄存器 LCK<='1';-- 中斷鎖存寄存器時鐘信號
elseLCK<='0'; end if; end if;
if rising_edge(clk) then
if(inten='1') then
intr<= not(inta or intb or intc or intd );--中斷(inta,intb,intc,intd 分別為四個UART的中斷信號)
elseinter<='1'; end if; end if;
end process con_pro;
// 中斷有限狀態(tài)機
Interput_Proc: process(nreset,clk10k)
begin
if (nreset='0') then State <= s0;
elsif rising_edge(clk10k) then
case State is
when s0 =>
if (inten='1') and (intr='0') then
State <= s1;--產(chǎn)生中斷
else State <= s0; end if;
when s1 =>
if (inten='0') then
State <= s2; --中斷使能無效
else State <= s1; end if;
when s2 =>
if (inten='1') then--中斷服務(wù)完成,置中斷使能有效
State <= s3;
else State <= s2; end if;
// 延時50US保證中斷服務(wù)程序完全退出
when s3 => State <= s4;--10us
when s4 => State <= s5;--10us
when s5 => State <= s5;--10us
when s6 => State <= s7;--10us
when s7 => State <= s0;--10us
when others => State <= s0;
end case; end if;
end processInterput_Proc;
end beha;
三、WINCE5.0下實現(xiàn)多串口驅(qū)動
在WINCE 5.0下開發(fā)的設(shè)備驅(qū)動有兩種模式:本機設(shè)備驅(qū)動和流接口設(shè)備驅(qū)動。而本系統(tǒng)的多串口設(shè)備驅(qū)動采用流接口設(shè)備驅(qū)動方式,它以動態(tài)鏈接庫(DLL)即文件系統(tǒng)的一個特殊文件形式來實現(xiàn)把外設(shè)使用傳遞給應(yīng)用程序。圖(5)顯示了其設(shè)備驅(qū)動如何下WINCE5.0操作系統(tǒng)中集成的,其中,設(shè)備驅(qū)動程序分為兩層,上層是模型設(shè)備驅(qū)動驅(qū)動程序(MDD),該層驅(qū)動對平臺和函數(shù)來講是通用的,即是源代碼也是庫,負責(zé)鏈接PDD層并定義它希望調(diào)用的函數(shù)以及把不同的函數(shù)集提供給設(shè)備管理器來統(tǒng)一加載、管理和卸載,這些函數(shù)集叫流接口函數(shù);而下層是依賴平臺的設(shè)備驅(qū)動程序(PDD),它是直接訪問硬件的驅(qū)動程序,同時通過設(shè)備驅(qū)動程序提供器接口(DDIS)接口提供給MDD層調(diào)用。
每一個流接口驅(qū)動程序必須實現(xiàn)一組標(biāo)準(zhǔn)的函數(shù),用來完成標(biāo)準(zhǔn)的文件I/O函數(shù)和電源管理函數(shù),這些函數(shù)提供給WINCE操作系統(tǒng)內(nèi)核使用,由于篇幅的限制這里只列出多串口流接口驅(qū)動程序要實現(xiàn)的DLL接口:COM_Close它是在串口驅(qū)動關(guān)閉是應(yīng)用程序通過CloseHandle( )函數(shù)調(diào)用這個函數(shù);COM_Init它完成串口的初始化;COM_Open在打開一個串口驅(qū)動程序時應(yīng)用程序可以通過CreatFile( )函數(shù)調(diào)用這個函數(shù);COM_Deinit該函數(shù)完成串口驅(qū)動程序的卸載;COM_IOControl該函數(shù)用于向串口設(shè)備發(fā)送命令,應(yīng)用層可以通過DeviceIOControl函數(shù)來通知操作系統(tǒng)調(diào)用這個函數(shù);COM_Read()在串口處于打開狀態(tài)時應(yīng)用程序通過ReadFile( )函數(shù)調(diào)用這個函數(shù)來讀取串口數(shù)據(jù);COM_Write()在串口處于打開狀態(tài)時應(yīng)用程序通過WriteFile( )函數(shù)調(diào)用這個函數(shù)來向串口寫入數(shù)據(jù);COM_PowerDown由COM_Init創(chuàng)建時生產(chǎn)的句柄,系統(tǒng)掛起前調(diào)用這個函數(shù);COM_PowerUp由COM_Init創(chuàng)建時生產(chǎn)的句柄,系統(tǒng)重新啟動前調(diào)用這個函數(shù)。
四、總結(jié)
在FPGA上實現(xiàn)UART IP核,占用700個宏單元,共1萬5千門系統(tǒng)設(shè)計,通過接口模塊化設(shè)計的UART核來實現(xiàn)嵌入式微處理器動態(tài)擴展多串口電路的方法,有利于通過電路的最小更改來實現(xiàn)多串口的擴展,同時也減小開發(fā)周期和成本,該設(shè)計方法也可以作為其他電路設(shè)計的參考。
參考文獻:
[1]邰銘、于洪濤,Windows CE.Net內(nèi)核定制及應(yīng)用開發(fā),電子工業(yè)出版社,2004.
[2]董長富、郭超平、宋渝,基于FPGA的多串口模塊的設(shè)計和實現(xiàn),設(shè)計參考,2006,Vol.8 No.11.
[3]姜寧、范多旺,基于FPGA/CPLD的通用異步通信接口UART的設(shè)計,信息系統(tǒng)與信息化,2006年第1期.
作者簡介:
方明,男,碩士,主研方向:嵌入式系統(tǒng)開發(fā),集成電路設(shè)計;林建中,男,高級工程師,主研方向:計算機系統(tǒng)開發(fā),集成電路設(shè)計。