【轉】系統初始化過程(arm7TDMI 各模塊的簡單介紹)——44B0X

 

本文轉至:http://blogold.chinaunix.net/u/19573/index.php

 

 

禁止看門狗——》在中斷控制器中屏蔽所有中斷——》系統時鐘設置——》初始化端口——》DMA設置——》cashe和總線設置——》存儲器設置,初始化SDRAM——》初始化堆棧——》設置IRQFIQ的入口——》地址重映射

   

    通常系統初始化有兩個階段組成,分別爲彙編和C寫成。彙編應儘量簡單一些,把更多的任務交給C來做,這樣可增加整個程序的可讀性和靈活性。必須由彙編來完成的任務有:異常中斷向量表的設置、IRQ向量表(向量模式)或ISR初始化(非向量模式)、二級ISR地址表的定義、FlashSDRAM的設置(否則系統無法加載代碼)、堆棧設置和模式切換、拷貝RWZI代碼、設置系統時鐘等。而端口初始化、cashe和總線的設置、DMA配置以及其它控制器如LCDUARTSIOIP等可以在C中第二階段初始化程序完成,另外也可以繼續更改時鐘或存儲器配置等。下面是幾個關鍵步驟配置的注意事項。

 

看門狗設置

    watch dog即可以作爲普通的timer以產生週期性的中斷,也可以週期性的產生reset信號(如果每隔一定時間不被清除的話),以防治程序跑飛。

 

系統時鐘的初始化:

至少設置三個寄存器:LOCKTIME,PLLCON,LOCKCON

LOCKTIME,地址0x01D8000C。用於指定PLL的初始化時間,在PLL初始化時,系統時鐘爲晶振輸入或外部時鐘直接提供,即MCLK=Fin;初始化完成後,切換,MCLK=Fout。初始值爲0xfff4095個輸入時鐘週期。一般將其設爲初始值。

PLLCON,,地址0x01D80000。設置MDIV,PDIV,SDIV三個值,用於確定FoutFin的頻率分配比值:Fout = (m * Fin) / (p * 2s),其中

m = (MDIV + 8), p = (PDIV + 2), s = SDIV

典型的幾個值如下:

No.

Fin

Fout

MDIV

PDIV

SDIV

1

10Mhz

40Mhz

0x48

0x3

0x2

2

10

50

0x2a

0x3

0x1

3

10

60

0x34

0x3

0x1

4

4

60

0x34

0x0

0x1

5

3

60

0x48

0x0

0x1

6

10

75

0x3a

0x3

0x1

 

CLKCON,地址0x01D80004。用於設置是否向外設提供時鐘,一般設爲默認值0x7ff8,即所有外設提供時鐘。

 

存儲器初始化(尤其是SDRAM):

ARM7TDMI的地址映射如下:

(在ARM體制中,所有的各種內、外存儲器,外設,寄存器,cashewrite buffer,通用IO口等全都採用統一編址)

 

注:0x100000000x100047f0爲內部cashe/sram 及其TagLRU的地址。

 

BANK0~BANK5爲ROM/SRAM/FLASH,

BANK6~BANK7爲SDRAM/ROM/SRAM/FLASH

要設置的寄存器如下:

BWSCON:BANK0~BANK7的UB/LB使能、Wait信號使能、數據線寬度;

BANKCON0~BANKCON5:各bank(flash或Sram)的訪問時序控制。flash或Sram主要參數如下所示:

Tacs [14:13] Address set-up before nGCSn

Tcos [12:11] Chip selection set-up nOE

Tacc [10:8] Access cycle

Toch [7:6] Chip selection hold on nOE

Tcah [5:4] Address holding time after nGCSn

Tpac [3:2] Page mode access cycle @ Page mode

PMC [1:0] Page mode configuration

不同廠家、性能、速度的器件設置有所不同。

BANKCON6~BANKCON7:主要用於SDRAM,當然也可以是Flash或SRAM。SDRAM的時序控制稍微複雜,還有:

Trcd [3:2] RAS to CAS delay

    SCAN [1:0] Column address number

當然也可用於DRAM。

 

REFRESH 地址: 0x01C80024,DRAM/SDRAM的更新控制寄存器;

MRSRB6 ~MRSRB7:DRAM/SDRAM的模式控制寄存器,這個寄存器在系統初始時,即SDRAM使用前必須被有效地的設置。

    這幾個寄存器的設置比較複雜,應仔細閱讀Samsang(page168)的數據手冊和相關存儲器的資料。

一個典型的配置如下:

ldr r0, =SMRDATA

ldmia r0, {r1-r13}

ldr r0, =0x01c80000 ; BWSCON Address

stmia r0, {r1-r13}

SMRDATA DATA

DCD 0x11222220 ; BWSCON Bank0=OM[1:0],8bits寬 Bank1~Bank5=32bit,Bank6~Bank=16bit,不使用UB/LB信號,WAIT disable; 使用little Endian存儲格式

DCD 0x000056A8; GCS0 :Tacs=2clk;Tcos=2clk;Tacc=10clk;

Toch=2clk;Tcah=2clk;Tpac=4clk;PMC=normal(1data)

DCD 0x00000700 ; GCS1 除了Access cycle爲14個clk外,其它均爲0clk

DCD 0x00000700 ; GCS2

DCD 0x00000700 ; GCS3

DCD 0x00000700 ; GCS4

DCD 0x00000700 ; GCS5

DCD 0x00018005 ; GCS6, SDRAM;RAS to CAS delay 2 clk;Column address number:9bits

DCD 0x0001002a ; GCS7, EDO DRAM(Trcd=3, Tcas=2, Tcp=1, CAN=10bit)

DCD 0x00870441 ; Refresh enable;Auto Refresh; Trp=3, Trc=5, Tchr=3;

刷新計數:1019

DCD 0x17 ; SCLK power down mode enable;Bank6&7 Size, 16MB/16MB

DCD 0x20 ; MRSR 6:CAS Latency=2clk;burst type爲線性(不支持交織訪問);

burst number:1bit(不支持促發讀寫)

DCD 0x20 ; MRSR 7(CL=2)

 

注:三星的實驗板中在nGCS0外接Flash,型號爲SST39VF160,其datasheet中有其讀寫時序的詳細說明和各種時間值的最大或最小值,但均以ns爲單位,且各時間值的名稱也與寄存器的要求不完全相同。要使Flash達到最優設置,必須讀懂其時序並按其推薦值設置寄存器。顯然這並不是件容易的事情。在本次實驗板的boot程序中,其各時序值均是最大值給出。參見memcfg.h文件。

三星的實驗板中在nGCS6外接SDRAM,型號爲IC42S16800-7T,(4096ROW*512COLUM*4Bank*16bits=128Mbits=16MB)

由上面的例子可以看出需要設置的參數爲:1.Banksize,UB/LB,WAITenable/disable,large/little Endian;

2.RAS to CAS delay, Column address number;

3.Refresh enable/disable,Auto/self refresh, SDRAM RAS pre-charge Time, SDRAM RC minimum Time, Refresh Counter;

4.power down mode,banksize;

4.CAS Latency,burst type,burst number。

 

Refresh counter的設置Refresh period = (211-refresh_count+1)/MCLK

Ex) If refresh period is 16 us and MCLK is 60 MHz,

the refresh count is as follows;

refresh_count = 211 + 1 - 60x16 = 1089

 

上面的例子只是對FlashSDRAM的一個經驗設置值,可能不是最優的。最優設置還必須參考器件的數據手冊。尤其是對於SDRAMRAS to CAS delay、SDRAM RAS pre-charge Time、SDRAM RC minimum Time三個時序值。

 

特別注意:在線調試階段,在AXD軟件中必須引入對SDRAM初始化的seesion文件或ini文件,或者在command interface中敲入所需的配置命令(在load image之前完成),並且最後註釋掉reset彙編程序中的初始化SDRAM的命令。否則程序就可能跑飛。而生成要下載的flash程序代碼時,則系統reset時就必須完成此功能。

 

端口初始化

ARM的大部分信號在同一端口是功能複用的。爲此初始化時必須指定各PA~PG口的各管腳的功能。在實驗板根據外圍器件的選擇對各端口做如下配置:

PA(10bits):全部用作高端地址線;PCONA=0x3ff

PB(11bits):全部用作存儲器控制信號;PCONB=0x7ff

PC(16bits):4~7用於LCD的VD4~VD7;12,13用於UART的TXD1,RXD1(注意:這裏的UART沒有使用CTS、RTS信號,只用了TX、RX);其它全部用於通用IO口,GPC0~3用於IIS;GPC10和14用於NAND Flash;GPC15用於USB Device;GPC8、9用於LCD;GPC11暫時沒用。PCONC=0x5f55ff55.(這裏假定IO口全爲output,實際應用時再確認一下是In或是out)

PD(8bits):全部用於LCD的控制信號。PCOND=0xaaaa。

PE(9bits):8用於Endian,確定存儲器格式;1,2分別爲TXD0,RXD0;0,3~7用於通用IO口(暫定output),PE3用於蜂鳴器;PE4~7用於LED顯示。PCONE=0x05569。

PF(9bits):0、1用於IIC總線的SCK、SDA信號;其它均爲通用IO口(暫定output),其中GPF2~4用於IDE,GPF5~8用於觸摸屏。PCONF=0x09255a。

PG(8bits):全部用於外部中斷EXINT0~7。PCONG=0xffff。

注意:上述端口分配是S3C44b0x測試板(勤研電子)的分配情況。

 

另外還有下面幾個寄存器需要設置:

上拉電阻寄存器,包括一些端口和數據線;

EXTIN:設置8個外中斷的觸發方式,low,high,rising or falling edge等。

EXTINTPND:中斷待處理寄存器,用於解決EXTINT4~7共享一箇中斷源的問題。 

 

Cache&Bus設置

通過內部寄存器可以設置cashe mode(cashe和sram),write buffer,non-cashable area,以及bus的優先級等。

通常,在一般的用戶程序中不使用cashe(即全部用作Sram),禁用write buffer,bus優先級選擇默認就可以了,即1. DRAM refresh controller2. LCD_DMA3. ZDMA0,14. BDMA0,15. External bus master6. Write buffer7. Cache & CPU

只配置一下SYSCFG:0x0。 

 

DMA配置

ZDMA在系統總線上,完成系統總線上器件的數據傳送,如存儲器。BDMA也有2個,橋接系統總線和外設總線,即可以完成分別位於兩條總線上的器件的數據傳送,也可完成外設總線上器件如SIO、UART、TIMER等之間數據傳送。

DMA的四種數據傳送方式。

DMA的觸發選擇:XDREQ/XDACK、S/W、H/W等。

一般地,DMA的初始化只需完成BDMA的目標地址寄存器的初始化:BDIDES0,1=0x40000000,即傳送方向爲內部存儲器到外設,初始目的地址:0x0。 

 

 

中斷寄存器的配置和中斷向量表的設計

中斷有兩種IRQ和FIQ,後者優先級高於前者。另外,ARM系統還做了些特殊安排以使FIQ有更快的響應速度,如FIQ的ISR可以直接放在0x1c(緊跟FIQ)開始的地址單元中,免去了跳轉;屬於FIQ的中斷向量表可常駐cashe;FIQ較IRQ有更多的物理寄存器等。通常在簡單的用戶程序中,可以不使用FIQ,所有中斷都設爲IRQ(默認情況)。

ARM7有30箇中斷源,實際使用25個。其優先級如下所示:

 

 

一些重要的中斷設置寄存器如下:

INTCON  0x01E00000 :中斷控制。指定IRQ是否採用向量模式(一般採用非向量模式,這也是默認值)。指定CPU是否響應IRQFIQ

INTPND:只讀。指定中斷源是否有中斷請求,可以同時有多箇中斷請求。當對應的ISR結束時,通過向I_ISPCF-ISPC1來清除INTPND中對應的比特位,否則該中斷將連續執行。

INTMSK:各中斷源是否屏蔽。初始值時屏蔽。

INTMOD:指定各中斷源是IRQFIQ,默認值全爲IRQ

I_PSLV  0x01E00010   R/W    IRQ priority of slave register  0x1b1b1b1b

I_PMST  0x01E00014   R/W    IRQ priority of master register  0x00001f1b

I_CSLV  0x01E00018   R       Current IRQ priority of slave register  0x1b1b1b1b

I_CMST  0x01E0001C  R       Current IRQ priority of master register  0x0000xx1b

I_ISPR   0x01E00020   R      IRQ interrupt service pending register

I_ISPC   0x01E00024   W      IRQ interrupt service clear register

F_ISPC   0x01E00024   W      FIQ interrupt service clear register

優先級取默認值就可以了。

ISPR只讀,指示當前被響應的中斷源,沒有或只有一個被響應,儘管此時INTPND中可能有幾個中斷請求。ISR結束時,通過向ISPC對應位寫1來清除ISPR中的對應位。

ARM7TDMI中,中斷向量表的設置有兩種模式:向量模式和非向量模式。前者只適於全IRQ的設置。採用非向量模式時,通過分析ISPR(發生中斷時,其中只有一個位爲1,其它全爲0)找到要執行的ISR的入口地址。在向量模式中,當發生IRQ時,CPU自動產生跳轉地址,如同異常中斷的使用。各IRQ的一級ISR的跳轉地址如下:

 

中斷有異常中斷(如:DabortPabortUndef等)和IRQFIQ兩種。下面以向量模式下的IRQ爲例介紹一下中斷設置。

過程如下:IRQ中斷向量表設置——>寫一級ISR——>分配二級ISR的入口地址表——>寫二級ISR——>把二級ISR的入口地址放到二級ISR的入口地址表中。這樣在開中斷的情況下,一個ISR就可以正常執行了。一個ISR的執行過程如下。

首先要在系統初始化時開中斷:INTMSK各中斷位清零且INTCONIRQ位清零(使能)且CPSRI比特清零(使能),缺一不可。中斷髮生時,首先由模式SYSUser切換至IRQ,同時完成現場保護(工作指針入棧、保存CPSRPC>LR),然後PC直接跳到IRQ中斷向量表的相應地址(一級ISR的入口),緊接着跳到一級ISR並執行;一級ISR通常由彙編寫成,僅完成一個跳轉任務(有時也看一下寄存器ISPR,判斷該中斷是否被錯誤觸發,如果錯誤將直接返回),即從二級ISR的入口地址表中找到相應中斷的入口地址,其間工作現場沒有變化。二級ISR通常由c語言寫成,中斷的真正的響應程序就在此處。ISR結束時,要對INTMSK中的pending比特清零(通過置位ISPR中相應比特),否則將連續響應該中斷。然後CPU自動切換至中斷前的工作模式,並恢復現場。

 

C語言中關鍵字__irq的作用:當ISR定義時有此關鍵字,則ISR結束後CPU自動從棧中恢復中斷前模式的LR,並把它賦值給PC,完成ISR的正常返回。如果無此關鍵字,則CPU只能返回到二級ISR前的中斷狀態,此時仍爲IRQ工作模式。當然也能夠繼續執行用戶程序,只是工作模式不對,此模式下再不能響應其它IRQ中斷。

事實上,CPU響應中斷並執行ISR相當於一個程序調用過程。用戶程序不必干預CPU的模式切換、現場保護、程序返回。

 

中斷向量表的設置。一級中斷向量表緊跟異常中斷向量表,位於0x20~0xc0。只讀。由於S3C44b0x沒有MMU和地址映射功能,該中斷向量表必須和異常中斷向量表一起固化到系統地址空間的0x0處,即Flash的起始處。在線調試階段也必須保證該表存在於Flash中。二級ISR的地址表一般位於RAM空間的最後256個字節處,緊跟在堆棧後,在彙編語言中由MAP語句創建(8個異常中斷和25個IRQ,共33×4=132Byte),可讀寫。同時在c中定義一組指向相同地址空間的無符號型指針,當然指針名稱必須和彙編中的定義相同。這樣在C中的ISR初始化程序中,可直接把二級ISR的入口放到地址表中。如:pISR_EINT0=(unsigned)Isr_Eint0; pISR_EINT0爲地址表中的指針,而Isr_Eint0爲ISR的名稱,也是其入口地址。二級ISR地址表和一級表不同的是,其各中斷的順序可任定,但必須保證彙編和C中的定義一致。

對於非向量模式,不使用IRQ中斷向量表,但二級ISR地址表的設置是相同的。在本測試程序中boot.s同時包含了兩種格式的設置,只要設置好INTCON中的mode比特,兩種模式都可以用。注意非向量模式,在彙編中要設置IRQ和FIQ的入口地址。因爲在非向量模式要靠IsrIRQ和IsrFIQ來定位響應的中斷源位置。

    另外,爲了保證開中斷後,程序不至於跑飛,最好編寫所有的IRQ 的ISR,該ISR可以是個空函數,確保能正常返回就行了。

 

堆棧初始化和工作模式的切換

ARM7TDMI有7種工作模式,要用到6個stack,其中SYS和User共用一個Stack。堆棧設置採用流行的FD模式(full decresment)。通常放在RAM空間的次最高段(最高的256B爲ISR的地址表),在16M的SDRAM中,各stack設置如下:

0x0cff_f000~0x0cff_fa00: Uers and SYS stack,2560B,夠大了。

0x0cff_fa01~0x0cff_fb00: SVC stack, 256B;

0x0cff_fb01~0x0cff_fc00: Undef stack, 256B;

0x0cff_fc01~0x0cff_fd00: Abort stack, 256B;

0x0cff_fd01~0x0cff_fe00: IRQ stack, 256B;

0x0cff_fe01~0x0cff_ff00: FIQ stack, 256B;

0x0cff_ff01~0x0cff_ffff: ISR地址表, 256B;

 

CPU的模式切換通常由異常中斷產生,或者在SVC或SYS模式下完成。User模式中用戶程序不能改變工作模式(除了應用異常中斷,如SWI),當然也不能改變CPSR的值(也就不能開關中斷了!)。通常如果不用嵌入式OS,單任務的用戶程序工作在SYS或SVC模式下更好一些,這樣可以更方便的使用硬件資源。如果使用SVC模式,甚至可以不設置SYS and User stack。

系統加電重起時,首先進入SVC模式,完成初始化,在調用C的main函數之前再切換到SYS或User模式。因此可以把堆棧初始化放到最後執行,並最後設置SYS stack,這樣進入main之後可以直接工作在SYS模式下。本測試程序就是如此設置的。

 

 

 

分佈式加載

ADS1.2中的ARM linker支持分佈式加載,即加載域(load)和執行域(image)的各個輸出段(RO、RW、ZI)可以有不同的地址。可以很方便的生成供在線調試和下載的elf格式的文件。通常總線調試只需設置RO base=0x0c000000;而生成下載代碼則要設置RO base=0x0,RW base=0x0c000000,並且一定要把boot.o設成first section,否則程序入口不在0x0則無法完成異常中斷和普通中斷,包括reset。至於ropi、rwpi、split的應用參見linker的有關資料。

鏈接器同時產生一組符號,給出各個域或者各個輸出段的區間的長度,裝載地址和執行地址。由於鏈接器和C庫都沒有將代碼從它的裝載區間拷貝到執行區間,或創建一個零初始化區域的功能,所以要由應用程序員利用這組符號產生的信息完成這項工作,這是在呼叫C程序之前必須完成的,舉例如下:

LDR r0, = |Load$$DRAM$$Base|
LDR r1, = |Image$$DRAM$$Base|
CMP r0, r1  
檢查裝載地址和執行地址是否相同
BEQ do_zi_init  
相同,則不拷貝該區間,初始化零數據區
MOV r2, r1 
 不相同,將裝載區拷貝到執行區 
LDR r4, = |Image$$DRAM$$length|
ADD r2, r2, r4
BL copy
do_zi_init
LDR r1, = |Image$$DRAM$$ZI$$Base|
MOV r2, r1
LDR r4, = |Image$$DRAM$$ZI$$length|
ADD r2, r2, r4
MOV r3, #0
BL zi_init  
調用零初始化子程序

 

上例中使用了ARM Linker產生的與域有關的幾個符號,域名可以在scatter文件中指定。在本測試程序中,因爲只有一個load域和一個image域,因此可以使用ARM Linker產生的與輸出段有關的符號,如|Image$$RO$$Base|、|Image$$RO$$Limit|、|Image$$RW$$Base|、|Image$$ZI$$Base|、|Image$$ZI$$Limit|等。必須注CPU或系統本身都不能自動完成分佈式加載的任務,所以系統在第一階段初始化時(即彙編語言寫的初始化代碼),就必須編寫用戶程序根據上述幾個符號把代碼考到RAM區中。通常要把除了彙編寫的第一階段的初始化代碼以外的RO代碼、RW和ZI代碼都要拷到RAM中,這樣可以代碼的執行速度。RW和ZI是必須要拷到RAM中,否則程序無法運行。注意ZI是RW區中的位於最後的一段零初始化的RAM區,RW limit和ZI limit兩個值相等。在本程序中只拷貝了RW和ZI段。 

 

LCD設置

本系統所帶LCD沒有內置控制器、顯存、字符查找表等,需要靠ARM所帶LCD控制器進行顯示,在系統的SRAM中開闢一塊顯存區,本測試程序中顯存framebuffer開在ZI區之後,且能保證不進入RAM高端的堆棧區,實際上黑白字符的顯存爲14400Byte(前者分辨率爲480×240),彩色圖片的顯存115200B(分辨率爲320×240)。支持MONO、灰4,灰16、256色四種模式。面板模式有4bit single、8bit single、4bit dual scan三種。黑白字符顯示採用4bit dual scan,彩色圖片採用8bit single。

往顯存中寫入數據,系統會自動把數據代表的內容顯示在LCD的相應位置上,ASCII採用8×16點陣。圖片中每象素需8比特信息(紅3綠3蘭2),BMP圖片的顯示原理還沒搞清楚。

虛擬屏幕顯示。顯存的大小定義爲SCR_XSIZE*SCR_YSIZE,即可以放進這麼大的BMP圖片,而能顯示的範圍是LCD_XSIZE*LCD_YSIZE,只能顯示圖片的某個區域,設置好PAGEWITDH和OFFSIZE參數,改變光標的位置,就可移動顯示圖片的其它部分(Lcd_moveviewport函數),本測試程序中令SCR_SIZE=LCD_SIZE,即沒有使用虛擬屏幕顯示。

去抖動算法和AFC。灰4和灰16圖片的顯示根據的是AFC原理。去抖動算法是保證相鄰幀之間任一象素on/off的概率相當。這些是ARM中的LCD控制器自動完成。

彩色查找表。設定不同深度的顏色。紅和綠:16取8,蘭:16取4。 

 

PS/2鍵盤接口設計

鍵盤接口通常有掃描和中斷兩種方式。掃描方式的鍵盤製作簡單,但是要佔用過多的微處理器的端口資源,並且由於採用查詢方式接收鍵盤數據,導致CPU資源的浪費。中斷方式的鍵盤較爲複雜,但接口簡單,如採用5芯或6芯的PS/2接口,而且由於採用中斷方式接收鍵盤掃描碼,相應地也減少了CPU資源的佔用。目前標準PC機鍵盤技術已經很成熟,且成本也已經很低。本監控板將採用標準PC機鍵盤作爲人機命令的輸入接口。

PS/2接口信號線主要有兩根:CLK、DATA。鍵盤和主機間的通信是同步和異步方式的結合。按鍵時在DATA線上發送11位的掃描碼,起始位0、8個數據位(LSB在前)、1個校驗位和一個結束位0。放鍵時先發送放鍵標誌F0,接着再發送一遍掃描碼。CLK的上升沿觸發主機的中斷,主機執行ISR(ExINT4567)接收1bit數據。接收完完整的8bits數據後,ISR將判斷是否爲F0,若是,則把緊接着接收的下一個8bits數據譯碼,變爲ASCII或OEM碼或者Windows虛擬碼,放入64Byte的鍵盤緩衝區中,並通知主機上位程序進行相應的處理,如打印字符或處理特殊符號(ESC、Enter、F1之類)。

 

後來發現上述編程思路又問題:只實現了位同步,不能實現11bits的字節或幀同步,當發生干擾而產生INT0中斷時,一個錯誤比特被讀入,導致後續比特全錯。改進如下:每接收11bit對起始位、結束位、校驗位進行判斷,若發生錯誤,則失步,下一比特被捨棄,重新同步。結果有所改進,但仍不理想。

 

下表是部分按鍵的掃描碼、系統碼、ASCII、Windows虛擬碼的對應關係。 

 

SWI的使用

Swi.h 頭文件的定義;使用__swi僞操作對swi函數進行說明;在main中可直接調用該函數。SWI的兩級ISR設置基本同普通的IRQ,但要設置功能號。

現在的問題是無法返回sys mode, 調用功能號不對。 

 

UART設置

S3C44B0X有兩個獨立的UART,均採用RS232接口。每個UART有1個16B的Rx buffer 和一個Rx buffer(實際上可以不用,若通信雙方的時鐘精度足夠號的話)。本測試程序中使用non FIFO mode.

AFC 和 non AFC mode:所謂AFC就是利用握手信號RTS和CTS來自動控制雙方的通信,對端也必須是UART,若對端是modem,則只能用non AFC mode,即用軟件讀寫RTS和CTS。

中斷模式和DMA模式。本測試程序使用中斷模式,但ISR未作任何處理,實際上是查詢方式收發數據。發數據:通過UTRSTAT0中的狀態指示位看發送數據寄存器UTXH0是否空,不空則等待,空則把數據寫到該數據寄存器。然後Uart控制器會自動把數據串至RS232的Tx腳上。接收類同。這種方式適合發數據。接收數據時,CPU就不能幹其它事了,好在人機交互時,CPU也只是等待命令,不幹其它。若用於從主機快速接收大量數據,則必須取數據的函數放到UART的ISR中。 

 

以太網接口芯片的設置

RTL8019AS的三種工作模式:

跳線模式:這種模式與早期的網絡控制器兼容。RTL8019AS的端口基地址、中斷口等都

由開關或跳線器(或者由CPU的通用IO口模擬跳線器)決定。跳線模式簡單,但配置資源麻煩。

PnP模式:與微軟的PnP協議兼容(play and plug),適於PC機模式。在這種模式下,RTL8019AS的端口基地址、中斷口等都由EEPROM93C46設定,但需要進行PnP芯片的識別,不便與DSP接口。

RT模式:爲了避免PnP模式下的PnP芯片識別和配置過程,readlted公司提供RT模式。

Boot程序存於BROMFlash種。在RT模式下,RTL8019AS的端口基地址、中斷口等也是由EEPROM93C46決定的。SMEMR和SMEMW引腳接高電平,屏蔽了遠程自舉加載功能。

事實上,在嵌入式系統設計中,RTL8019AS固定於嵌入板上,而且單片機可以很方便的對其初始化和各種控制,因此可以使用跳線模式,但不用跳線器,也不用通用IO來模擬,直接把控制字寫入各配置寄存器就可以了,如PAR,CONFIG等。當然config可以不設置,按默認就可以了:

IO起始地址:0x300(即範圍:0x300~0x31f)

中斷:int0

接口選擇:10baseT

 

寄存器表(通過CR中的ps0,1來確定頁:這種安排太對調試太惡劣了!!)

 

初始化時必須設置號RCR TCR DCR三個有關接收、傳輸、數據格式的寄存器。ISR和IMR實現中斷功能。

注意:ISR寄存器不只和中斷有關,當接收緩衝溢出時,如果不清ISR(寫入FFH),芯片將一直停止接收。在流量較大時溢出經常發生,此時不清ISR,就會導致網卡芯片死機。另外,有時一些無法識別的包或沒有對該包作出應答包時,ISRRST位也會置1,導致8019死機。原因不祥。所以最好在每次中斷服務程序的結束處對ISRRST位清零。

18H1FH8個地址,爲復位端口。對該端口地址的讀或者寫入任何數,都會引起網卡的復位。

 

讓人遺憾的是,勤研電子的板子,8019與ARM的地址連線錯:8019A0—ARMA1,導致8019中的這些8位寄存器無法正常尋址,解決辦法是用16位地址模擬,CR的地址:0x300,CLDA0:0x302,…,CNTR2:0x31e。這樣寫入是正確的,但在AXD中從0x06000300中讀出的數頁必須按16位理解,即奇數地址忽略掉。  

 

以太網幀格式:

 

    PR 同步位 用於收發雙方的時鐘同步 同時也指明瞭傳輸的速率 10M和100M 的時鐘頻率不一樣 所以100M 網卡可以兼容10M 網卡 是56 位的二進制數101010101010.....

SD: 分隔位,表示下面跟着的是真正的數據,而不是同步時鐘,爲8位的10101011,跟同步位不同的是最後2位是11而不是10.

DA:目的地址,以太網的地址爲48位(6個字節)二進制地址,表明該幀傳輸給哪個網卡.如果爲FFFFFFFFFFFF,則是廣播地址,廣播地址的數據可以被任何網卡接收到.

SA:源地址,48 位,表明該幀的數據是哪個網卡發的,即發送端的網卡地址,同樣是6個字節.

TYPE 類型字段 表明該幀的數據是什麼類型的數據 不同的協議的類型字段不同 如 0800H 表示數據爲IP 包 0806H 表示數據爲ARP包 814CH 是SNMP包,8137H 爲IPX/SPX 包 小於0600H 的值是用於IEEE802 的 表示數據包的長度

DATA 數據段 該段數據不能超過1500 字節 因爲以太網規定整個傳輸包的最大長度不能超過1514字節 14 字節爲DA SA TYPE

RTL8019AS是ISA總線式網卡,速率爲10M。

 

    NIC幀格式(位於16KSRAM種的接受和待發送的幀結構)

值得注意的是,收到的數據包格式並不是802.3幀的真子集,而是如下圖所示。明顯地,8019自動添加了“接收狀態、下一頁指針、以太網幀長度(以字節爲單位)”三個數據成員(4字節)。這些數據成員的引入方便了驅動程序的設計,體現了軟硬件互相配合協同工作的設計思路。當然,發送數據包的格式是802.3幀的真子集,如圖3所示。

RTL8019AS接收幀結構,不爲Enthernet的真子集

接收狀態

下一頁指針

以太網幀長度

目的IP地址DA

IP地址SA

類型TYPE

數據域DATA

填充PAD

校驗CRC

8bits

8bits

16bits

48bits

48bits

16bits

<=1500B

可選

32bits

 

RTL8019AS發送幀結構,爲Enthernet的真子集

以太網幀長度

目的IP地址DA

IP地址SA

類型TYPE

數據域DATA

填充PAD

校驗CRC

 

 

16bits

48bits

48bits

16bits

<=1500B

可選

32bits

 

 

 

   16kSRAM地址:0x40000x7fff,對應頁地址:0x400x7f(每頁256B),其地址與IO(寄存器)、EEPROMBROM的地址是分開的,具體的我也不清楚。  

8019有兩個DMALocal DMARemote DMA,分別位於雙端口SRAM的兩邊,64SRAM分爲兩步分:58頁的Rx buffer6頁的Tx buffer6頁爲1536Byte,恰可容那一個TxRxNIC以太幀,其最大長度爲1500B)。Local DMA完成NICSRAM的數據傳輸,它是8019自動完成的,無需Host干預;Remot DMA完成SRAMHost RAM的數據傳送,需要host干預,即通過相關的有關傳輸數據起始、長度的寄存器的設定,並通過Readwrite等命令(位於CR寄存器)來完成傳輸。16KSRAM不能直接尋址,只有通過0x100x1f的寄存器來實現數據傳輸。主機設置好遠端DMA開始地址(RSAR0,1)和遠端DMA數據字節數 (RBCR0,1),並在CR中設置讀/寫,就可以從遠端DMA口寄存器裏讀出芯片RAM裏的數據/把數據寫入芯片RAM

 

    接收緩衝區構成一個循環FIFO隊列,PSTARTPSTOP兩個寄存器限定了循環隊列的開始和結束頁,CURR爲寫入指針,受芯片控制,BNRY爲讀出指針,由主機程序控制。根據CURR==BNRY+1?可以判斷是否收到新的數據包,新收到的數據包按Rx NIC格式存於以CURR指出的地址爲首址的RAM中。當CURR==BNRY時芯片停止接收數據包。

注意:很多時候一個網間通信連接(一對通信進程)往往使用不同的端口號,如TFTP的目標端口號:69,但源端口號可以不是(本程序是1124)。

 

網絡字節順序。其獨立於兩端的主機的字節順序。ARMWindows均使用little Endian格式;SUN則使用big endian格式。“互聯網聯網標準”要求採用“網絡字節順序”爲Big Endian。對於4Byte的字和2Byte 的半字在通信協議程序實現的兩端都必須進行字節順序的轉換,否則協議無法識別。對於以Byte爲單位的數據則無所謂。本程序使用函數:Swap_Word()Swap_HalfWord()來實現順序轉換功能。轉換是可逆的。 

校驗和的計算

IP頭部的校驗和計算:16字節對齊,check0,對每個16位二進制數反碼求和(也可先求和再取反,只是要注意16位溢出後的處理,見CheckSum()函數),結果放在check字段中;接收時對頭部再進行相同的計算,結果應爲全1,否則IP頭出錯。注意在上述算法中,IP頭時網絡字節順序。

UDP頭部的校驗和計算:不僅包含了UDP頭,還有一個12Bytes的僞頭部,包含一些IP包的信息(見NetConfig.h中的定義)。UDP頭中的check字段式兩步分校驗和之和,算法依然是反碼求和。接收時對頭部再進行相同的計算,結果應爲全1,否則UDP頭出錯。另外,UDP的校驗和是個可選項,也可以不進行校驗和計算,此時check0;接收時也應該做相應的判斷。

TCP頭部的校驗和計算:和UDP頭的計算完全相同,也需要一個12Bytes的僞頭部。有點區別是TCP頭部計算是個強制項,不能設僞零。

 

本程序的功能:實現IP層管理(即用ICMP)的ping命令的支持;實現簡單文件傳輸(TFTP)。TCP/IP協議處理流程圖如下:

 

 

TCP/IP協議棧設計

    C中用struct定義各協議的枕頭和分組,詳細的設計參見NetConfig.h文件;

    Host RAM中開闢一個以太分組的Buffer(能容納一個以太分組就可以了);

    分組封裝:高層—>四層—>三層—>二層(以太)—>NIC,解包反之,使用指針通過共享存儲空間來實現參數傳遞;

 

ARP分組格式

 

協議類型:ARP0x0806IP0x0800 

 

IP分組格式

 

IP頭採用標準的20Byte結構;

TOS通常不使用,即置零;

16位的標誌用於區分不同的IP包,從1計數至65536,循環往復;

IP包通常不進行分片,16位偏移置零,IP分組長度不大於以太幀最大長度就可以了(1500Byte);

TTL通常設爲128

8位協議:ICMP:1 TCP:6 UDP:17

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章