• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 網絡與存儲 > 學習方法與實踐 > ARM S3C2410硬件手冊重點

    ARM S3C2410硬件手冊重點

    ——
    作者: 時間:2007-12-11 來源:電子開發網 收藏

    a.Memory Controller
    b.Nand Flash
    c.UART
    d.Interrupt
    e.Timer

    Memory Controller
    SDRAM:
      提供了外接ROM、SRAM、SDRAM、NOR Flash、NAND Flash的接口。外接存儲器的空間被分為8 BANKS,每BANK容量為128M:當訪問BANKx(x從0到7)所對應的地址范圍x*128M到(x+1)*128M-1
      SDRAM使用BANK6,它的物理起始地址為6*128M=0x30000000。

    SDRAM(刷新):
      之所以稱為DRAM,就是因為它要不斷進行刷新(Refresh)才能保留住數據,因此它是DRAM最重要的操作。
    那么要隔多長時間重復一次刷新呢?目前公認的標準是,存儲體中電容的數據有效保存期上限是64ms(毫秒,1/1000秒),也就是說每一行刷新的循環周期是64ms。這樣刷新速度就是:行數量/64ms
    刷新操作分為兩種:自動刷新(Auto Refresh,簡稱AR)與自刷新(Self Refresh,簡稱SR)。不論是何種刷新方式,都不需要外部提供行地址信息,因為這是一個內部的自動操作。對于AR, SDRAM內部有一個行地址生成器(也稱刷新計數器)用來自動的依次生成行地址。
        由于刷新涉及到所有L-Bank,因此在刷新過程中,所有L-Bank都停止工作,而每次刷新所占用的時間為9個時鐘周期(PC133標準),之后就可進入正常的工作狀態,也就是說在這9 個時鐘期間內,所有工作指令只能等待而無法執行。
        SR則主要用于休眠模式低功耗狀態下的數據保存,這方面最著名的應用就是STR(Suspend to RAM,休眠掛起于內存)。在發出AR命令時,將CKE置于無效狀態,就進入了SR模式,此時不再依靠系統時鐘工作,而是根據內部的時鐘進行刷新操作。

    SDRAM(寄存器設置):
    本實驗介紹如何使用SDRAM,這需要設置13個寄存器。由于我們只使用了BANK6,大部分的寄存器我們不必理會:
    1.BWSCON:對應BANK0-BANK7,每BANK使用4位。這4位分別表示:
    a.STx:啟動/禁止SDRAM的數據掩碼引腳,對于SDRAM,此位為0;對于SRAM,此位為1。
    b.WSx:是否使用存儲器的WAIT信號,通常設為0
    c.DWx:使用兩位來設置存儲器的位寬:00-8位,01-16位,10-32位,11-保留。
    d.比較特殊的是BANK0對應的4位,它們由跳線決定,只讀。
    對于本開發板,使用兩片容量為32Mbyte、位寬為16的SDRAM組成容量為64Mbyte、位寬為32的存儲器,所以其BWSCON相應位為: 0010。對于本開發板,BWSCON可設為0x22111110:其實我們只需要將BANK6對應的4位設為0010即可,其它的是什么值沒什么影響,這個值是參考上給出的。
    2.BANKCON0-BANKCON5:我們沒用到,使用默認值0x00000700即
    3. BANKCON6-BANKCON7:設為0x00018005 在8個BANK中,只有BANK6和BANK7可以使用SRAM或SDRAM,所以BANKCON6-7與BANKCON0-5有點不同: a.MT([16:15]):用于設置本BANK外接的是SRAM還是SDRAM:SRAM-0b00,SDRAM-0b11
    b.當MT=0b11時,還需要設置兩個參數: Trcd([3:2]):RAS to CAS delay,設為推薦值0b01 SCAN([1:0]):
    SDRAM的列地址位數,對于本開發板使用的SDRAM HY57V561620CT-H,列地址位數為9,所以SCAN=0b01。如果使用其他型號的SDRAM,您需要查看它的數據來決定SCAN的取值:00-8位,01-9位,10-10位
    4. REFRESH(SDRAM refresh control register):設為0x008e0000+ R_CNT 其中R_CNT用于控制SDRAM的刷新周期,占用REFRESH寄存器的[10:0]位,它的取值可如下計算(SDRAM時鐘頻率就是HCLK):
    R_CNT = 2^11 + 1 – SDRAM時鐘頻率(MHz) * SDRAM刷新周期(uS)
    在未使用PLL時,SDRAM時鐘頻率等于晶振頻率12MHz;
    SDRAM 的刷新周期在SDRAM的數據上有標明,在本開發板使用的SDRAM HY57V561620CT-H的數據手冊上,可看見這么一行“8192 refresh cycles / 64ms”:所以,刷新周期=64ms/8192 = 7.8125 uS。
    對于本實驗,R_CNT = 2^11 + 1 – 12 * 7.8125 = 1955, REFRESH=0x008e0000 + 1955 = 0x008e07a3
    5.BANKSIZE:0x000000b2
    位[7]=1:Enable burst operation
    位[5]=1:SDRAM power down mode enable
    位[4]=1:SCLK is active only during the access (recommended) 位[2:1]=010:BANK6、BANK7對應的地址空間與BANK0-5不同。BANK0-5的地址空間都是固定的128M,地址范圍是 (x*128M)到(x+1)*128M-1,x表示0到5。但是BANK7的起始地址是可變的,您可以從數據手冊第5章“Table 5-1. Bank 6/7 Addresses”中了解到BANK6、7的地址范圍與地址空間的關系。
    本開發板僅使用BANK6的64M空間,我們可以令位[2:1]=010(128M/128M)或001(64M/64M):這沒關系,多出來的空間程序會檢測出來,不會發生使用不存在的內存的情況——后面介紹到的bootloader和linux內核都會作內存檢測。 位[6]、位[3]沒有使用
    6.MRSRB6、MRSRB7:0x00000030
    能讓我們修改的只有位[6:4](CL),SDRAM HY57V561620CT-H不支持CL=1的情況,所以位[6:4]取值為010(CL=2)或011(CL=3)。

    Nand Flash
    當OM1、OM0都是低電平——即開發板插上BOOT SEL跳線時,S3C2410從NAND Flash啟動:NAND Flash的開始4k代碼會被自動地復制到內部SRAM中。我們需要使用這4k代碼來把更多的代碼從NAND Flash中讀到SDRAM中去。
    NAND Flash的操作通過NFCONF、NFCMD、NFADDR、NFDATA、NFSTAT和NFECC六個寄存器來完成。在開始下面內容前,請打開S3C2410數據手冊和NAND Flash K9F1208U0M的數據手冊。

    在S3C2410數據手冊218頁,我們可以看到讀寫NAND Flash的操作次序:
    1.Set NAND flash configuration by NFCONF register.
    2.Write NAND flash command onto NFCMD register.
    3.Write NAND flash address onto NFADDR register.
    4.Read/Write data while checking NAND flash status by NFSTAT register. R/nB signal should be checked before read operation or after program operation.

    1、NFCONF:設為0xf830——
    使能NAND Flash控制器、初始化ECC、NAND Flash片選信號nFCE=1(inactive,真正使用時再讓它等于0)

    設置TACLS、TWRPH0、TWRPH1。
    需要指出的是TACLS、TWRPH0和TWRPH1,請打開S3C2410數據手冊218頁,可以看到這三個參數控制的是NAND Flash信號線CLE/ALE與寫控制信號nWE的時序關系。
    我們設的值為TACLS=0,TWRPH0=3,TWRPH1=0,其含義為:TACLS=1個HCLK時鐘,TWRPH0=4個HCLK時鐘,TWRPH1=1個HCLK時鐘。

    請打開K9F1208U0M數據手冊第13頁,在表“AC Timing Characteristics for Command / Address / Data Input”中可以看到: CLE setup Time = 0 ns,CLE Hold Time = 10 ns, ALE setup Time = 0 ns,ALE Hold Time = 10 ns, WE Pulse Width = 25 ns 可以計算,即使在HCLK=100MHz的情況下,TACLS+TWRPH0+TWRPH1=6/100 uS=60 ns,也是可以滿足NAND Flash K9F1208U0M的時序要求的。

    2、NFCMD: 對于不同型號的Flash,操作命令一般不一樣。對于本板使用的K9F1208U0M,請打開其數據手冊第8頁“Table 1. Command Sets”
    3、NFADDR:地址
    4、NFDATA:數據,只用到低8位
    5、NFSTAT:狀態,只用到位0,0-busy,1-ready
    6、NFECC:校驗

    現在來看一下如何從NAND Flash中讀出數據:
    1、NFCONF = 0xf830
    2、在第一次操作NAND Flash前,通常復位一下:
    NFCONF &= ~0x800 (使能NAND Flash)
    NFCMD = 0xff (reset命令)
    循環查詢NFSTAT位0,直到它等于1
    3、NFCMD = 0 (讀命令)
    4、這步得稍微注意一下,請打開K9F1208U0M數據手冊第7頁,那個表格列出了在地址操作的4個步驟對應的地址線,A8沒用到:
    NFADDR = addr & 0xff
    NFADDR = (addr>>9) & 0xff (注意了,左移9位,不是8位)
    NFADDR = (addr>>17) & 0xff (左移17位,不是16位)
    NFADDR = (addr>>25) & 0xff (左移25位,不是24位)
    5、循環查詢NFSTAT位0,直到它等于1
    6、連續讀NFDATA寄存器512次,得到一頁數據(512字節)
    7、NFCONF |= 0x800 (禁止NAND Flash)

    {{分頁}}

    UART
    UART的寄存器有11X3個(3個UART)之多,我選最簡單的方法來進行本實驗,用到的寄存器也有8個。不過初始化就用去了5個寄存器,剩下的3個用于接收、發送數據。

    1、初始化:
    a.把使用到的引腳GPH2、GPH3定義為TXD0、RXD0:
    GPHCON |= 0xa0 GPHUP |= 0x0c (上拉)
    b.ULCON0 ( UART channel 0 line control register ):設為0x03 此值含義為:8個數據位,1個停止位,無校驗,正常操作模式(與之相對的是Infra-Red Mode,此模式表示0、1的方式比較特殊)。
    c.UCON0 (UART channel 0 control register ):設為0x05 除了位[3:0],其他位都使用默認值。位[3:0]=0b0101表示:發送、接收都
    使用“中斷或查詢方式”——本實驗使用查詢查詢方式。
    d.UFCON0 (UART channel 0 FIFO control register ):設為0x00 每個UART內部都有一個16字節的發送FIFO和接收FIFO,但是本實驗不使用FIFO,設為默認值0
    e.UMCON0 (UART channel 0 Modem control register ):設為0x00 本實驗不使用流控,設為默認值0
    f.UBRDIV0 ( R/W Baud rate divisior register 0 ):設為12 本實驗未使用PLL, PCLK=12MHz,設置波特率為57600,則由公式 UBRDIVn = (int)(PCLK / (bps x 16) ) –1 可以計算得UBRDIV0 = 12,請使用S3C2410數據手冊第314頁的誤差公式驗算一下此波特率是否在可容忍的誤差范圍之內,如果不在,則需要更換另一個波特率(本實驗使用的 57600是符合的)。
    void init_uart( )
    {//初始化UART
    GPHCON |= 0xa0; //GPH2,GPH3 used as TXD0,RXD0
    GPHUP = 0x0c; //GPH2,GPH3內部上拉
    ULCON0 = 0x03; //8N1(8個數據位,無校驗位,1個停止位)
    UCON0 = 0x05; //查詢方式
    UFCON0 = 0x00; //不使用FIFO
    UMCON0 = 0x00; //不使用流控
    UBRDIV0 = 12; //波特率為57600 10 }

    2、發送數據:
    a.UTRSTAT0 ( UART channel 0 Tx/Rx status register ):位[2]:無數據發送時,自動設為1。當我們要使用串口發送數據時,先讀此位以判斷是否有數據正在占用發送口。位[1]:發送FIFO是否為空,本實驗未用此位位[0]:接收緩沖區是否有數據,若有,此位設為1。本實驗中,需要不斷查詢此位一判斷是否有數據已經被接收。
    b.UTXH0 (UART channel 0 transmit buffer register ): 把要發送的數據寫入此寄存器。
    void putc(unsigned char c)
    {
    while( ! (UTRSTAT0 & TXD0READY) ); //不斷查詢,直到可以發送數據
    UTXH0 = c; //發送數據
    }
    3、接收數據:
    a.UTRSTAT0:如同上述“2、發送數據”所列,我們用到位[0]
    b.URXH0 (UART channel 0 receive buffer register ): 當查詢到UTRSTAT0 位[0]=1時,讀此寄存器獲得串口接收到的數據。
    unsigned char getc( )
    {
    while( ! (UTRSTAT0 & RXD0READY) ); //不斷查詢,直到接收到了數據
    return URXH0; //返回接收到的數據
    }

    中斷 Interrrupt
    SUBSRCPND和SRCPND寄存器表明有哪些中斷被觸發了,正在等待處理(pending);
    SUBMASK(INTSUBMSK寄存器)和MASK(INTMSK寄存器)用于屏蔽某些中斷。
    1、“Request sources(without sub -register)”中的中斷源被觸發之后,SRCPND寄存器中相應位被置1,如果此中斷沒有被INTMSK寄存器屏蔽、或者是快中斷(FIQ)的話,它將被進一步處理
    2、對于“Request sources(with sub -register)”中的中斷源被觸發之后,SUBSRCPND寄存器中的相應位被置1,如果此中斷沒有被INTSUBMSK寄存器屏蔽的話,它在 SRCPND寄存器中的相應位也被置1,之后的處理過程就和“Request sources(without sub -register)”一樣了
    請打開S3C2410數據手冊357頁,“Figure 14-2. Priority Generating Block”顯示了各中斷源先經過6個一級優先級仲裁器選出各自優先級最高的中斷,然后再經過二級優先級仲裁器選從中選出優先級最高的中斷。IRQ的中斷優先級由RIORITY寄存器設定,請參考數據手冊365頁,RIORITY寄存器中ARB_SELn(n從0到6)用于設定仲裁器n各輸入信號的中斷優先級,例如ARB_SEL6[20:19](0最高,其后各項依次降低):
    00 = REQ 0-1-2-3-4-5 01 = REQ 0-2-3-4-1-5
    10 = REQ 0-3-4-1-2-5 11 = REQ 0-4-1-2-3-5
    RIORITY寄存器還有一項比較特殊的功能,如果ARB_MODEn設為1,則仲裁器n中輸入的中斷信號的優先級別將會輪換。例如ARB_MODE6設為1,則仲裁器6的6個輸入信號的優先級將如下輪換(見數據手冊358頁)

    使用中斷的步驟:
    1、當發生中斷IRQ時,CPU進入“中斷模式”,這時使用“中斷模式”下的堆棧;當發生快中斷FIQ時,CPU進入“快中斷模式”,這時使用“快中斷模式”下的堆棧。所以在使用中斷前,先設置好相應模式下的堆棧。
    2、對于“Request sources(without sub -register)”中的中斷,將INTSUBMSK寄存器中相應位設為0
    3、將INTMSK寄存器中相應位設為0
    4、確定使用此的方式:是FIQ還是IRQ。
    a.如果是FIQ,則在INTMOD寄存器設置相應位為1
    b.如果是IRQ,則在RIORITY寄存器中設置優先級

    使用中斷的步驟:
    5、準備好中斷處理函數,
    a.中斷向量: 在中斷向量設置好當FIQ或IRQ被觸發時的跳轉函數, IRQ、FIQ的中斷向量地址分別為0x00000018、0x0000001c
    b.對于IRQ,在跳轉函數中讀取INTPND寄存器或INTOFFSET寄存器的值來確定中斷源,然后調用具體的處理函數
    c.對于FIQ,因為只有一個中斷可以設為FIQ,無須判斷中斷源
    d.中斷處理函數進入和返回

    6、設置CPSR寄存器中的F-bit(對于FIQ)或I-bit(對于IRQ)為0,開中斷
    使用中斷的步驟:
    IRQ進入和返回
    sub lr, lr, #4 @計算返回地址
    stmdb sp!, { r0-r12,lr } @保存使用到的寄存器…… 
    ldmia sp!, { r0-r12,pc }^ @中斷返回 @^表示將spsr的值賦給cpsr

    對于FIQ,進入和返回的代碼如下:
    sub lr, lr, #4 @計算返回地址
    stmdb sp!, { r0-r7,lr } @保存使用到的寄存器……
    ldmia sp!, { r0-r7,pc }^ @快中斷返回, @^表示將spsr的值賦給cpsr
    中斷返回之前需要清中斷:往SUBSRCPND(用到的話)、SRCPND、INTPND中相應位寫1即可。對于INTPND,最簡單的方法就是“INTPND=INTPND”

    Timer幾個重要寄存器介紹
    1、TCFG0和TCFG1:分別設為119和0x03
    這連個寄存器用于設置“Control Logic”的時鐘,計算公式如下:
    Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}
    對于TIMER0,prescaler value = TCFG0[7:0],divider value由TCFG1[3:0]確定(0b000:2,0b001:4,0b010:8,0b0011:16,0b01xx:使用外部TCLK0)。
    對于本實驗,TIMER0時鐘 = 12MHz/(119+1)/(16) = 6250Hz
    2、TCNTB0:設為3125
    在6250Hz的頻率下,此值對應的時間為0.5S
    3、TCON:
    TIMER0對應bit[3:0]:
    bit[3]用于確定在TCNT0計數到0時,是否自動將TCMPB0和TCNTB0寄存器的值裝入TCMP0和TCNT0寄存器中
    bit[2]用于確定TOUT0是否反轉輸出(本實驗未用)
    bit[1]用于手動更新TCMP0和TCNT0寄存器:在第一次使用定時器前,此位需要設為1,此時TCMPB0和TCNTB0寄存器的值裝入TCMP0和TCNT0寄存器中
    bit[0]用于啟動TIMER0
    4、TCONO0:只讀寄存器,用于讀取當前TCON0寄存器的值

    linux操作系統文章專題:linux操作系統詳解(linux不再難懂)


    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 河源市| 晋江市| 浠水县| 金华市| 泌阳县| 保德县| 公安县| 广灵县| 米脂县| 衡水市| 连山| 阿拉善盟| 宜黄县| 惠安县| 买车| 巴马| 延安市| 阿拉善右旗| 潜山县| 泰顺县| 东阿县| 辽阳市| 望城县| 祁东县| 靖江市| 柏乡县| 休宁县| 茂名市| 南靖县| 朝阳区| 徐州市| 武宁县| 聂拉木县| 军事| 孝感市| 深泽县| 青阳县| 衡山县| 大悟县| 富蕴县| 定边县|