在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<s id="cmphk"><label id="cmphk"></label></s>
    <span id="cmphk"><var id="cmphk"></var></span>
    <dfn id="cmphk"><var id="cmphk"></var></dfn>
    <menu id="cmphk"><thead id="cmphk"></thead></menu>

    <address id="cmphk"></address>

      <dfn id="cmphk"></dfn>
      
      
      <span id="cmphk"></span>

      <object id="cmphk"><tt id="cmphk"></tt></object>
      1. 新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > U-Boot 在44B0X 開(kāi)發(fā)板上的移植以及代碼分析

        U-Boot 在44B0X 開(kāi)發(fā)板上的移植以及代碼分析

        作者: 時(shí)間:2016-11-11 來(lái)源:網(wǎng)絡(luò) 收藏
        1. u-boot 介紹
        u-boot 是一個(gè)open source 的bootloader,目前版本是1.1.2。u-boot 是在ppcboot 以及armboot 的基礎(chǔ)上發(fā)展而來(lái),相當(dāng)?shù)某墒旌头€(wěn)定,已經(jīng)在許多嵌入式系統(tǒng)開(kāi)發(fā)過(guò)程中被采用。由于其開(kāi)發(fā)源代碼,其支持的開(kāi)發(fā)板眾多。
        為什么我們需要u-boot?顯然可以將uClinux 直接燒入flash,從而不需要額外的引導(dǎo)裝載程序(bootloader)。但是從軟件升級(jí)的角度以及程序修補(bǔ)的來(lái)說(shuō),軟件的自動(dòng)更新非常重要。事實(shí)上,引導(dǎo)裝載程序(bootloader)的用途不僅如此,但僅從軟件的自動(dòng)更新的需要就說(shuō)明我們的開(kāi)發(fā)是必要的。同時(shí),u-boot 移植的過(guò)程也是一個(gè)對(duì)嵌入式系統(tǒng)包括軟硬件以及操作系統(tǒng)加深理解的一個(gè)過(guò)程。

        2. u-boot 移植的框架
        移植u-boot 到新的開(kāi)發(fā)板上僅需要修改和硬件相關(guān)的部分。在代碼結(jié)構(gòu)上:
        1) 在board 目錄下創(chuàng)建gold44b 目錄,創(chuàng)建gold44b.c 以及flash.c,memsetup.S,u-boot.lds等。不需要從零開(kāi)始,可選擇一個(gè)相似的目錄,直接復(fù)制過(guò)來(lái),修改文件名以及內(nèi)容。我在移植u-boot 過(guò)程中,選擇的是Dave/B2目錄。由于u-boot 已經(jīng)包含基于s3c24b0 的開(kāi)發(fā)板目錄,作為參考,也可以復(fù)制相應(yīng)的目錄。
        2) 在cpu 目錄下創(chuàng)建s3c44b0x 目錄,主要包含start.S,interrupts.c 以及cpu.c,serial.c幾個(gè)文件。同樣不需要從零開(kāi)始建立文件,直接從arm720t 復(fù)制,然后修改相應(yīng)內(nèi)容。
        3) 在include/configs 目錄下添加gold44b.h,在這里放上全局的宏定義等。
        4) 找到u-boot 根目錄下Makefile 修改加入
        gold44b_config : unconfig
        @./mkconfig $(@:_config=) arm s3c44b0 gold44b
        5) 運(yùn)行make ev44bii_config,如果沒(méi)有錯(cuò)誤就可以開(kāi)始硬件相關(guān)代碼移植的工作

        3. u-boot 的體系結(jié)構(gòu)
        1) 總體結(jié)構(gòu)
        u-boot 是一個(gè)層次式結(jié)構(gòu)。做移植工作的軟件人員應(yīng)當(dāng)提供串口驅(qū)動(dòng)(UART Driver),以太網(wǎng)驅(qū)動(dòng)(Ethernet Driver),Flash 驅(qū)動(dòng)(Flash 驅(qū)動(dòng)),USB 驅(qū)動(dòng)(USB Driver)。目前,通過(guò)USB 口下載程序顯得不是十分必要,而且開(kāi)發(fā)板上也沒(méi)有USB接口,所以暫時(shí)沒(méi)有移植USB 驅(qū)動(dòng)。驅(qū)動(dòng)層之上是u-boot 的應(yīng)用,command 通過(guò)串口提供人機(jī)界面。我們可以使用一些命令做一些常用的工作,比如內(nèi)存查看命令md。
        Kermit 應(yīng)用主要用來(lái)支持使用串口通過(guò)超級(jí)終端下載應(yīng)用程序。TFTP 則是通過(guò)網(wǎng)絡(luò)方式來(lái)下載應(yīng)用程序,例如uClinux 操作系統(tǒng)。
        2) 內(nèi)存分布
        gold44b 的flash 大小2M(8bits),現(xiàn)在將0-40000 共256k 作為u-boot 的存儲(chǔ)空間。由于u-boot 中有一些環(huán)境變量,例如ip 地址,引導(dǎo)文件名等,可在命令行通過(guò)setenv 配置好,通過(guò)saveenv 保存在40000-50000(共64k)這段空間里。如果存在保存好的環(huán)境變量,u-boot 引導(dǎo)將直接使用這些環(huán)境變量。正如從代碼分析中可以看到,我們會(huì)把flash 引導(dǎo)代碼搬移到DRAM 中運(yùn)行。u-boot 的代碼在DRAM中的位置在u-boot-1.1.2/board/gold44b/config.mk配置如下:TEXT_BASE = 0x0C700000。這樣,引導(dǎo)代碼u-boot將從0x0000 0000 處搬移到0x0C700000 處。特別注意的由于gold44b uClinux 中斷向量程序地址在0x0c000 0000 處,所以不能將程序下載到0x0c000 0000 出,通常下載到0x0c008 0000 處。

        4. start.S 代碼結(jié)構(gòu)
        1) 定義入口
        一個(gè)可執(zhí)行的Image 必須有一個(gè)入口點(diǎn)并且只能有一個(gè)唯一的全局入口,通常這個(gè)入口放在Rom(flash)的0x0 地址。例如start.S 中的
        .globl _start
        _start:
        值得注意的是你必須告訴編譯器知道這個(gè)入口,這個(gè)工作主要是修改連接器腳本文件(lds)。
        開(kāi)發(fā)板上的u-boot.lds如下:

        OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
        OUTPUT_ARCH(arm)
        ENTRY(_start)
        SECTIONS
        {
        . = 0x00000000;

        . = ALIGN(4);
        .text :
        {
        cpu/s3c44b0/start.o (.text)
        *(.text)
        }

        . = ALIGN(4);
        .rodata : { *(.rodata) }

        . = ALIGN(4);
        .data : { *(.data) }

        . = ALIGN(4);
        .got : { *(.got) }

        __u_boot_cmd_start = .;
        .u_boot_cmd : { *(.u_boot_cmd) }
        __u_boot_cmd_end = .;

        armboot_end_data = .;

        . = ALIGN(4);
        __bss_start = .;
        .bss : { *(.bss) }
        _end = .;
        }

        2) 設(shè)置異常向量(Exception Vector)
        異常中斷矢量表(Exception Vector Table)是u-boot與uClinux內(nèi)核發(fā)生聯(lián)系關(guān)鍵的地方之一。即使uClinux內(nèi)核已經(jīng)得到處理器的控制權(quán)運(yùn)行,一旦發(fā)生中斷,處理器還是會(huì)自動(dòng)跳轉(zhuǎn)到從0x0地址開(kāi)始的第一級(jí)異常中斷矢量表中的某個(gè)表項(xiàng)(依據(jù)于中斷類型)處讀取指令運(yùn)行。
        異常中斷矢量表必須是從0 地址開(kāi)始,連續(xù)的存放。如下面的就包括了復(fù)位(reset),未定義處理(undef),軟件中斷(SWI),預(yù)去指令錯(cuò)誤(Pabort),數(shù)據(jù)錯(cuò)誤 (Dabort),保留,以及IRQ,FIQ 等。注意這里的值必須與uClinux 的vector_base 一致。這就是說(shuō)如果uClinux 中vector_base(include/armnommu/proc-armv/system.h)定義為0x0c00 0000,則HandleUndef 應(yīng)該在
        0x0c00 0004。
        .globl _start
        _start: b reset
        /*Modfied by zl 2005-2-21 */
        /* add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000
        */
        ldr pc, =0x0c000004
        ldr pc, =0x0c000008
        ldr pc, =0x0c00000c
        ldr pc, =0x0c000010
        ldr pc, =0x0c000014
        ldr pc, =0x0c000018
        ldr pc, =0x0c00001c

        .balignl 16,0xdeadbeef
        這里,地址0x0處的一級(jí)異常中斷矢量表只簡(jiǎn)單地包含向二級(jí)異常中斷矢量表的跳轉(zhuǎn)指令就可以。這樣,就能夠正確地將發(fā)生的事件交給uClinux的中斷處理程序來(lái)處理。這樣設(shè)計(jì)是因?yàn)樵诒緐-boot移植里不使用中斷,8019和Timer都是輪詢中斷的,如果u-boot要使用中斷(如要用到USB設(shè)備),就需要建立二級(jí)異常中斷矢量表了。代碼如下(沒(méi)有調(diào)試通過(guò)):
        .globl _start
        _start: b reset
        add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000
        add pc, pc, #0x0c000000

        .balignl 16,0xdeadbeef
        ....
        在Reset是復(fù)制中斷矢量表
        /*
        now copy to sram the interrupt vector
        */
        adr r0, real_vectors
        add r2, r0, #1024
        ldr r1, =0x0c000000
        add r1, r1, #0x08
        vector_copy_loop:
        ldmia r0!, {r3-r10}
        stmia r1!, {r3-r10}
        cmp r0, r2
        ble vector_copy_loop

        ....
        建立三級(jí)中斷跳轉(zhuǎn)
        /*************************************************/
        /* interrupt vectors */
        /*************************************************/
        /*
        real_vectors:
        b reset
        b undefined_instruction
        b software_interrupt
        b prefetch_abort
        b data_abort
        b not_used
        b irq
        b fiq
        */

        /*************************************************/
        undefined_instruction:
        mov r6, #3
        b reset

        software_interrupt:
        mov r6, #4
        b reset

        prefetch_abort:
        mov r6, #5
        b reset

        data_abort:
        mov r6, #6
        b reset

        not_used:
        /* we *should* never reach this */
        mov r6, #7
        b reset

        irq:
        mov r6, #8
        b reset

        fiq:
        mov r6, #9
        b reset

        3) 初始化CPU 相關(guān)的pll,clock,中斷控制寄存器
        依次為關(guān)閉watch dog timer,關(guān)閉中斷,設(shè)置LockTime,PLL(phase lock loop),以及時(shí)鐘。
        這些值(除了LOCKTIME)都可從Samsung 44b0 的手冊(cè)中查到。
        /*
        *************************************************************************
        *
        * CPU_init_critical registers
        *
        * setup important registers
        * setup memory timing
        *
        *************************************************************************
        */

        #define INTCON (0x01c00000+0x200000)
        #define INTMSK (0x01c00000+0x20000c)
        #define LOCKTIME (0x01c00000+0x18000c)
        #define PLLCON (0x01c00000+0x180000)
        #define CLKCON (0x01c00000+0x180004)
        #define WTCON (0x01c00000+0x130000)
        cpu_init_crit:
        /* disable watch dog */
        ldr r0, =WTCON
        ldr r1, =0x0
        str r1, [r0]

        /*
        * mask all IRQs by clearing all bits in the INTMRs
        */
        ldr r1,=INTMSK
        ldr r0, =0x03fffeff
        str r0, [r1]

        ldr r1, =INTCON
        ldr r0, =0x05
        str r0, [r1]

        /* Set Clock Control Register */
        ldr r1, =LOCKTIME
        ldrb r0, =800
        strb r0, [r1]

        ldr r1, =PLLCON

        #if CONFIG_S3C44B0_CLOCK_SPEED==64
        ldr r0, =0x38021 /* smdk4110: Xtal=8MHz Fclk=64MHz */
        #elif CONFIG_S3C44B0_CLOCK_SPEED==66
        ldr r0, =0x34031 /* 66MHz (Quartz=11MHz) */
        #elif CONFIG_S3C44B0_CLOCK_SPEED==75
        ldr r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz */
        #else
        # error CONFIG_S3C44B0_CLOCK_SPEED undefined
        #endif

        str r0, [r1]

        ldr r1,=CLKCON
        ldr r0, =0x7ff8
        str r0, [r1]

        mov pc, lr

        4) 初始化SDRAM控制器
        內(nèi)存控制器(主要是SDRAM控制器),主要通過(guò)設(shè)置13 個(gè)從1c80000 開(kāi)始的寄存器來(lái)設(shè)置,包括總線寬度,8 個(gè)內(nèi)存bank,bank 大小,sclk,以及兩個(gè)bank mode。
        #ifdef CONFIG_INIT_CRITICAL
        bl cpu_init_crit
        /*
        * before relocating, we have to setup RAM timing
        * because memory timing is board-dependend, you will
        * find a memsetup.S in your board directory.
        */
        bl memsetup
        #endif
        初始化內(nèi)存控制器的代碼存放在u-boot-1.1.2/board/gold44b/memsetup.S中
        與ADS或者SDT下的boot代碼(memcfg.s和44binit.s)一致,只是匯編格式有點(diǎn)不一樣。
        5) 將rom 中的程序復(fù)制到RAM 中
        首先利用PC 取得bootloader 在flash 的起始地址,再通過(guò)標(biāo)號(hào)之差計(jì)算出這個(gè)程序代
        碼的大小。這些標(biāo)號(hào),編譯器會(huì)在連接(link)的時(shí)候生成正確的分布的值。取得正
        確信息后,通過(guò)寄存器(r3 到r10)做為復(fù)制的中間媒介,將代碼復(fù)制到RAM 中。

        relocate: /* relocate U-Boot to RAM */
        adr r0, _start /* r0 <- current position of code */
        ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
        cmp r0, r1 /* dont reloc during debug */
        beq stack_setup

        ldr r2, _armboot_start
        ldr r3, _bss_start
        sub r2, r3, r2 /* r2 <- size of armboot */
        add r2, r0, r2 /* r2 <- source end address */

        copy_loop:
        ldmia r0!, {r3-r10} /* copy from source address [r0] */
        stmia r1!, {r3-r10} /* copy to target address [r1] */
        cmp r0, r2 /* until source end addreee [r2] */
        ble copy_loop
        6) 初始化堆棧
        進(jìn)入各種模式設(shè)置相應(yīng)模式的堆棧.
        /* Set up the stack */
        stack_setup:
        ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
        sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
        sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
        #ifdef CONFIG_USE_IRQ
        sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
        #endif
        sub sp, r0, #12 /* leave 3 words for abort-stack */

        7) 轉(zhuǎn)到RAM 中執(zhí)行
        使用指令ldr,pc,RAM 中C 函數(shù)地址就可以轉(zhuǎn)到RAM 中去執(zhí)行。
        ldr pc, _start_armboot

        5. 系統(tǒng)初始化部分
        1) 串口部分(u-boot-1.1.2/cpu/s3c44b0/serial.c)
        串口的設(shè)置主要包括初始化串口部分,值得注意的串口的Baudrate 與時(shí)鐘MCLK 有很大關(guān)系,是通過(guò):rUBRDIV0=( (int)(MCLK/16./(gd ->baudrate) + 0.5) -1 )計(jì)算得出。這可以在手冊(cè)中查到。由于u-boot支持可變的波特率,所以采用宏定義設(shè)置默認(rèn)波特率(64Mhz,115200bps)和其他波特率。代碼如下:
        void serial_setbrg (void)
        {
        DECLARE_GLOBAL_DATA_PTR;

        u32 divisor = 0;

        /* get correct divisor */
        switch(gd->baudrate) {

        case 1200:
        #if CONFIG_S3C44B0_CLOCK_SPEED==66
        divisor = 3124;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==75
        divisor = 3905;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默認(rèn)
        divisor = 3332;
        #else
        # error CONFIG_S3C44B0_CLOCK_SPEED undefined
        #endif
        break;

        case 9600:
        #if CONFIG_S3C44B0_CLOCK_SPEED==66
        divisor = 390;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==75
        divisor = 487;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默認(rèn)
        divisor = 416;
        #else
        # error CONFIG_S3C44B0_CLOCK_SPEED undefined
        #endif
        break;

        case 19200:
        #if CONFIG_S3C44B0_CLOCK_SPEED==66
        divisor = 194;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==75
        divisor = 243;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默認(rèn)
        divisor = 207;
        #else
        # error CONFIG_S3C44B0_CLOCK_SPEED undefined
        #endif
        break;

        case 38400:
        #if CONFIG_S3C44B0_CLOCK_SPEED==66
        divisor = 97;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==75
        divisor = 121;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默認(rèn)
        divisor = 103;
        #else
        # error CONFIG_S3C44B0_CLOCK_SPEED undefined
        #endif break;

        case 57600:
        #if CONFIG_S3C44B0_CLOCK_SPEED==66
        divisor = 64;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==75
        divisor = 80;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默認(rèn)
        divisor = 68;
        #else
        # error CONFIG_S3C44B0_CLOCK_SPEED undefined
        #endif break;

        case 115200:
        #if CONFIG_S3C44B0_CLOCK_SPEED==66
        divisor = 32;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==64
        divisor = 34;
        #elif CONFIG_S3C44B0_CLOCK_SPEED==75 /默認(rèn)
        divisor = 40;
        #else
        # error CONFIG_S3C44B0_CLOCK_SPEED undefined
        #endif break;
        }

        serial_flush_output();
        serial_flush_input();
        UFCON0 = 0x0;
        ULCON0 = 0x03;
        UCON0 = 0x05;
        UBRDIV0 = divisor;

        UFCON1 = 0x0;
        ULCON1 = 0x03;
        UCON1 = 0x05;
        UBRDIV1 = divisor;

        for(divisor=0; divisor<100; divisor++) {
        /* NOP */
        }
        }
        其他的函數(shù)包括發(fā)送,接收。這個(gè)時(shí)候沒(méi)有中斷,是通過(guò)循環(huán)等待來(lái)判斷是否動(dòng)作完成。
        例如,接收函數(shù):
        static int serial_flush_input(void)
        {
        volatile u32 tmp;

        /* keep on reading as long as the receiver is not empty */
        while(UTRSTAT0&0x01) {
        tmp = REGB(URXH0);
        }

        return 0;
        }
        2) 時(shí)鐘部分(u-boot-1.1.2/cpu/s3c44b0/interrupt.c)
        實(shí)現(xiàn)了延時(shí)函數(shù)udelay。
        這里的get_timer 由于沒(méi)有使用中斷,是使用全局變量來(lái)累加的。
        void udelay (unsigned long usec)
        {
        ulong tmo;

        tmo = usec / 1000;
        tmo *= CFG_HZ;
        tmo /= 8;

        tmo += get_timer (0);

        while (get_timer_masked () < tmo)
        /*NOP*/;
        }

        3) flash 部分(u-boot-1.1.2/board/gold44b.c)
        flash 作為內(nèi)存的一部分,讀肯定沒(méi)有問(wèn)題,關(guān)鍵是flash 的寫(xiě)部分。
        Flash 的寫(xiě)必須先擦除,然后再寫(xiě)。
        flash_init 完成初始化部分,這里的主要目的是檢驗(yàn)flash 的型號(hào)是否正確。

        unsigned long flash_init (void)
        {
        #ifdef __DEBUG_START_FROM_SRAM__
        return CFG_DUMMY_FLASH_SIZE;
        #else
        unsigned long size_b0;
        int i;

        /* Init: no FLASHes known */
        for (i=0; iflash_info[i].flash_id = FLASH_UNKNOWN;
        }

        /* Static FLASH Bank configuration here - FIXME XXX */

        size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);

        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
        printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MBn",
        size_b0, size_b0<<20);
        }

        /* Setup offsets */
        flash_get_offsets (0, &flash_info[0]);

        /* Monitor protection ON by default */
        (void)flash_protect(FLAG_PROTECT_SET,
        -CFG_MONITOR_LEN,
        0xffffffff,
        &flash_info[0]);

        flash_info[0].size = size_b0;

        return (size_b0);
        #endif
        }


        flash_erase 擦除flash,BlankCheck 則檢查該部分內(nèi)容是否擦除成功。

        int flash_erase (flash_info_t *info, int s_first, int s_last)
        {
        volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
        volatile CFG_FLASH_WORD_SIZE *addr2;
        int flag, prot, sect, l_sect;
        ulong start, now, last;
        int i;

        if ((s_first < 0) || (s_first > s_last)) {
        if (info->flash_id == FLASH_UNKNOWN) {
        printf ("- missingn");
        } else {
        printf ("- no sectors to erasen");
        }
        return 1;
        }

        if (info->flash_id == FLASH_UNKNOWN) {
        printf ("Cant erase unknown flash type - abortedn");
        return 1;
        }

        prot = 0;
        for (sect=s_first; sect<=s_last; ++sect) {
        if (info->protect[sect]) {
        prot++;
        }
        }

        if (prot) {
        printf ("- Warning: %d protected sectors will not be erased!n",
        prot);
        } else {
        printf ("n");
        }

        l_sect = -1;

        /* Disable interrupts which might cause a timeout here */
        flag = disable_interrupts();

        /* Start erase on unprotected sectors */
        for (sect = s_first; sect<=s_last; sect++) {
        if (info->protect[sect] == 0) { /* not protected */
        addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[sect]);
        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
        addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
        addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
        addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
        addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
        addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
        addr2[0] = (CFG_FLASH_WORD_SIZE)0x00500050; /* block erase */
        for (i=0; i<50; i++)
        udelay(1000); /* wait 1 ms */
        } else {
        if (sect == s_first) {
        addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
        addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
        addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
        addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
        addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
        }
        addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030; /* sector erase */
        }
        l_sect = sect;
        }
        }

        /* re-enable interrupts if necessary */
        if (flag)
        enable_interrupts();

        /* wait at least 80us - lets wait 1 ms */
        udelay (1000);

        /*
        * We wait for the last triggered sector
        */
        if (l_sect < 0)
        goto DONE;

        start = get_timer (0);
        last = start;
        addr = (CFG_FLASH_WORD_SIZE *)(info->start[l_sect]);
        while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_FLASH_WORD_SIZE)0x00800080) {
        if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
        printf ("Timeoutn");
        return 1;
        }
        /* show that were waiting */
        if ((now - last) > 50000000) { /* every second */
        putc (.);
        last = now;
        }
        }

        DONE:
        /* reset to read mode */
        addr = (CFG_FLASH_WORD_SIZE *)info->start[0];
        addr[0] = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */

        printf (" donen");
        return 0;
        }


        wirte_word 則想flash 里面寫(xiě)入unsigned long 類型的data,因?yàn)閒lash 一次只能寫(xiě)入16bits,所以這里分兩次寫(xiě)入。
        /*-----------------------------------------------------------------------
        * Write a word to Flash, returns:
        * 0 - OK
        * 1 - write timeout
        * 2 - Flash not erased
        */
        static int write_word (flash_info_t *info, ulong dest, ulong data)
        {
        volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
        volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest;
        volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)&data;
        ulong start;
        int flag;
        int i;

        /* Check if Flash is (sufficiently) erased */
        if ((*((volatile ulong *)dest) & data) != data) {
        return (2);
        }
        /* Disable interrupts which might cause a timeout here */
        flag = disable_interrupts();

        for (i=0; i<4/sizeof(CFG_FLASH_WORD_SIZE); i++)
        {
        addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
        addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
        addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00A000A0;

        dest2[i] = data2[i];

        /* re-enable interrupts if necessary */
        if (flag)
        enable_interrupts();

        /* data polling for D7 */
        start = get_timer (0);
        while ((dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) !=
        (data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080)) {
        if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
        return (1);
        }
        }
        }

        return (0);
        }


        評(píng)論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        ×

        “芯”朋友见面大会
        珠海|11.14|泰克“芯”朋友见面大会珠海站|泰克带您从测试角度看半导体的整条产业链,快来报名抢位吧>>