操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    恒N8PRO#e#

    推薦產品:中恒N8PRO

    中恒的全能型GPS一體機N8PRO,采用了市面上比較罕見的6英寸VGA超高清觸摸屏,在視覺效果方面是最好的,中恒N8Pro的CMMB功能目前僅僅支持移動電視和電臺接收,其他一些例如股票信息、交通路況等實時信息暫時缺席,有待升級。本機的CMMB信號接收能力不錯,能在室內拉出天線的情況下,達到信號滿格的狀態,畫面流暢自如。對數字電視情有獨鐘的朋友不妨了解一下!

    中恒N8PRO還有強大的全頻段雙向流動測速功能,能預警各種流動測速設備,及時提醒司機降低車速,從而避免超速罰款,在測速的距離上正向達到2000M,反向到達800M. 導航系統方面,中恒N8Pro同樣采用的是裝機量較高的凱立德C系列導航系統,操作簡單,容易上手,道路信息更加形象美觀,一年可免費進行數據升級,以確保與城市建設與時俱進,保證在導航和固定預警方面不會出現誤差。

    凱立德C系列導航系統的分屏效果在N8Pro上看起來也相對5寸或更加小尺寸的導航儀來的舒服,更容易看清顯示的內容,讓駕車者不再單純依靠語音提示。導航系統內置全國各地道路的限速及照相監控數據,在進入相關路段時,會以語音和屏幕圖標提示駕車者提早做好應對措施,非常實用。

    編輯點評:在其它功能方面,中恒N8PRO還有藍牙、FM、無線倒車后視等功能,同時擁有MP3、MP4、MP5影音播放功能,可欣賞FLASH動畫、查看照片、閱讀電子書,并擁有掃雷、中國象棋、連連看、斗地主、五子棋、麻將、軍棋、跳棋等經典游戲,可節約空間避免重復消費,喜歡的朋友不妨了解一下!

    任我游1300#e#

    推薦產品:任我游1300

    任我游1300車載GPS導航儀是一款采用4.3英寸屏幕的傳統導航產品,這款產品采用了正版的四維地圖數據,并對導航軟件部分做出了相當大的優化與改善整體的運行穩定性與速度都得到了非常大的提高,目前促銷報價為:1480元。

    任我游1300新品的模具還是很扎實的,黑亮鋼琴烤漆面板,流線型側翼輪廓充滿動感,4.3吋高清高亮屏,預裝了最新的四維圖新V8.0大陸地圖,地圖覆蓋市/縣2218個,POI數量1170萬(增加50萬),道路里程218萬公里(增加5萬),強大的地圖數據網讓您走到哪里都不怕。

    任我游1300車載GPS導航儀采用了正版四維地圖數據,并搭配有人性化的導航軟件,整體的運行速度非常不錯,內置2GB存儲空間能夠支持地圖軟件存儲,而多媒體功能則需要大家自己擴展SD卡,而高亮抗反射屏幕在使用的時候就能發現與目前市面上的其他產品有著很大的差別。

    任我游1300車載GPS導航儀

    任我游1300功能,路口實景放大圖、快速查詢目的地是非常實用的功能,路口實景放大功能就是可以在關鍵路口,比如主輔路口時導航儀給出提示,而這個提示是實際路口圖,以3D形式給出,比傳統2D提示更真實形象,甚至路邊的樹木建筑物都有標示,讓駕駛者從容駕駛;快速查詢目的地功能就是一種模糊輸入,跟電腦的輸入法類似,我們通常管它叫作“快拼輸入”,這種方法查找最快,所需時間最短。還有就是任我游新系列產品終于支持視頻和音頻的播放,這和之前的產品在功能多樣化上有很大的區別。

    編輯點評:任我游1300車載GPS導航儀是目前市面上剛剛上市的一款全新的導航產品,整體上來看,作為首款采用任我游品牌自主研發的新產品,在功能上與質量上都保持了非常高的水準,并且價格定位非常實在,給市面上的其他產品造成了不小的威脅。

    E路航E800#e#

    推薦產品:E路航E800

    e路航E800電視版車載GPS導航儀是一款新上市的6英寸導航產品,內置CMMB數字電視功能并且帶有4GB存儲空間,并且支持多媒體格式的文件播放。自帶CMMB半年資費,并有正版PaPaGO兩年免費升級服務。目前商家報價:1680元。

    E路航E800電視版車載GPS導航儀

    點擊導航圖標后,E800進入導航系統的速度相當快捷,而且在搜星的過程也比較快捷,但根據試用情況來看,鎖定的衛星不算多,當然全程導航并沒有任何影響。PAPAGO!趴趴走導航系統具備3D建筑物顯示功能,不過目前應該還是在不斷增加中,還有所欠缺,本次測試過程中經過的路段就沒有相關的建筑物顯示。除了3D建筑物外,趴趴走導航系統另一個亮點就是具備了實景提示功能,以彈出窗口的形式在屏幕的左上角相當形象地提示前進的方向,對于駕駛者來說有較大的參考作用。

    編輯點評:E路航E800車載GPS導航儀自帶高清正版Papago導航軟件,帶有電視功能,高清屏幕,6英寸導航是時下一款比較新穎的導航產品,特別是目前還帶有2年的免費升級服務,相當超值。

    推薦產品:ACCO A600

    ACCO A600在外形方面有了較大的突破,在設計風格上面,與A系列風格迥異。ACCO正面采用寬屏窄邊設計,在外觀細節方面,ACCO A600花了相當大的心思,機器正面左右兩邊與背面采用拉絲面板,除了除滑效果明顯外,視覺效果也相當震撼。

    ACCO A600是當之無愧的6寸全能王。采用主流的A4平臺,SiRF A4 CPU,ARM11內核,500MHz主頻,128MB DDR,內置4GB,支持三年免費CMMB數字電視,支持移動測速預警和固定測速預警功能。支持無線倒車后視,支持RMVB等主流視頻格式。功能方面相當完善。ACCO A600預裝YFMAP精英版2.0。YFmap(實景地圖)是通過衛星實拍圖片,通過真實衛星照片,再現持機者的所處的環境,建筑、景觀、綠地、道路等各種信息都是一種真實再現,具有感同身受、身臨其境的特點,而且信息量、直觀度是普通模擬電子地圖無法比擬的。

    這是遠峰國際新近推出的一款內嵌于GPS系統固件的電子狗程序和雷達控制軟件,具有界面美觀實用、功能強大、升級簡單等諸多特點。預警系統設置界面也是非常的簡單實用,用戶可以根據所在城市的狀況,選擇預警的設置,避免無謂的打擾。

    編輯點評:作為ACCO首款6寸機器,功能上相當全面。流動測速,無線后視,固定電子狗,YFearth,三年免費CMMB,支持RMVB,ACCO A600將滿足絕大部份人的需求。

    本期總結:車載GPS加上CMMB功能無疑讓導航儀本身的實用高性價比大大增強,本次推薦的帶有CMMB功能的導航儀涵蓋了多種產品,用戶選擇是還是需要根據自身出發。

    E路航E800所配備的PAPAGO!趴趴走的導航系統,該導航系統具有3D建筑物和實景導航功能,并且操作簡便,UI界面亮麗。該系統利用成熟的虛擬現實技術,真實呈現三維建筑物及復雜路口實景圖,寬闊立體的視覺效果,令行車導航更直觀、快捷、安全。動態三維實景導航不但能將整個真實場景立體化,還能在復雜路段進行放大動態顯示,標注箭頭,進行直觀的方向指示,同時避免了用戶因長期注視線條和色塊所造成的視覺疲勞問題,真正實現體驗式導航,可謂處處彰顯人性化。

    上章節講了Nand flash驅動的編寫與移植,本章節主要講在 U-BOOT 對 Nand Flash 的支持,學linux的建議收藏,以后工作中會遇到。

    說明:
    本人作為一名工作多年的程序員,給大家都是精心挑選的資料,希望對大家的學習有幫助。

    本章主要內容如下:

    3 在 U-BOOT 對 Nand Flash 的支持

    3.1 U-BOOT 對從 Nand Flash 啟動的支持

    3.1.1 從 Nand Flash 啟動 U-BOOT 的基本原理

    3.1.2 支持 Nand Flash 啟動代碼說明

    3.2 U-BOOT 對 Nand Flash 命令的支持

    3.2.1 主要數據結構介紹

    3.2.2 支持的命令函數說明

    4 在 Linux 對 Nand Flash 的支持

    4.1 Linux 下 Nand Flash 調用關系

    4.1.1 Nand Flash 設備添加時數據結構包含關系

    4.1.2 Nand Flash 設備注冊時數據結構包含關系

    4.2 Linux 下 Nand Flash 驅動主要數據結構說明

    4.2.1 s3c2410 專有數據結構

    4.2.2 Linux 通用數據結構說明

    4.3.1 注冊 driver_register

    4.3.2 探測設備 probe

    4.3.3 初始化 Nand Flash 控制器

    4.3.4 移除設備

    4.3.5 Nand Flash 芯片初始化

    4.3.6 讀 Nand Flash

    4.3.7 寫 Nand Flash



    3.1 U-BOOT 對從 Nand Flash 啟動的支持

    3.1.1 從 Nand Flash 啟動 U-BOOT 的基本原理

    1. 前 4K 的問題

    如果 S3C2410 被配置成從 Nand Flash 啟動(配置由硬件工程師在電路板設置), S3C2410 的 Nand Flash 控制器

    有一個特殊的功能, 在 S3C2410 上電后, Nand Flash 控制器會自動的把 Nand Flash 上的前 4K 數據搬移到 4K 內部

    RAM 中, 并把 0x00000000 設置內部 RAM 的起始地址, CPU 從內部 RAM 的 0x00000000 位置開始啟動。這個過

    程不需要程序干涉。

    程序員需要完成的工作,是把最核心的啟動程序放在 Nand Flash 的前 4K 中。

    2. 啟動程序的安排

    由于 Nand Flash 控制器從 Nand Flash 中搬移到內部 RAM 的代碼是有限的,所以, 在啟動代碼的前 4K 里,我

    們必須完成 S3C2410 的核心配置以及把啟動代碼(UBOOT)剩余部分搬到 RAM 中運行。以 UBOOT 為例, 前 4K

    完成的主要工作, 見第四部分的 2.2 節。

    3.1.2 支持 Nand Flash 啟動代碼說明

    首先在 include/configs/crane2410.h 中加入 CONFIG_S3C2410_NAND_BOOT, 如下:

    #define CONFIG_S3C2410_NAND_BOOT 1

    支持從 Nand Flash 中啟動.

    1. 執行 Nand Flash 初始化

    下面代碼在 cpu/arm920t/start.S 中

    #ifdef CONFIG_S3C2410_NAND_BOOT

    copy_myself:

    mov r10, lr

    ldr sp, DW_STACK_START @安裝棧的起始地址

    mov fp, #0 @初始化幀指針寄存器

    bl nand_reset @跳到復位 C 函數去執行

    ...

    DW_STACK_START:

    .word STACK_BASE+STACK_SIZE-4

    2. nand_reset C 代碼

    下面代碼被加在/board/crane2410/crane2410.c 中

    void nand_reset(void)

    {

    int i;

    /* 設置 Nand Flash 控制器 */

    rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

    /* 給 Nand Flash 芯片發送復位命令 */

    NF_nFCE_L();

    NF_CMD(0xFF);

    for(i=0; i<10; i++);

    NF_WAITRB(); NF_nFCE_H();

    }

    3. 從 Nand Flash 中把 UBOOT 拷貝到 RAM

    @read U-BOOT from Nand Flash to RAM

    ldr r0,=UBOOT_RAM_BASE @ 設置第 1 個參數: UBOOT 在 RAM 中的起始地址

    mov r1, #0x0 @ 設置第 2 個參數:Nand Flash 的起始地址

    mov r2, #0x20000 @ 設置第 3 個參數: UBOOT 的長度(128KB)

    bl nand_read_whole @ 調用 nand_read_whole(), 該函數在 board/crane2410/crane2410.c 中

    tst r0, #0x0 @ 如果函數的返回值為 0,表示執行成功.

    beq ok_nand_read @ 執行內存比較

    4. 從 Nand Flash 中把數據讀入到 RAM 中

    int nand_read_whole(unsigned char *buf, unsigned long start_addr, int size)

    {

    int i, j;

    /* 如果起始地址和長度不是 512 字節(1 頁)的倍數, 則返回錯誤代碼 */

    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {

    return -1;

    }

    /* 激活 Nand Flash */

    NF_nFCE_L();

    for(i=0; i<10; i++);

    i=start_addr;

    while(i < start_addr + size) {

    /* 讀 A 區 */

    rNFCMD=0;

    /* 寫入讀取地址 */

    rNFADDR=i & 0xff;

    rNFADDR=(i >> 9) & 0xff;

    rNFADDR=(i >> 17) & 0xff;

    rNFADDR=(i >> 25) & 0xff;

    NF_WAITRB();

    /* 讀出一頁(512 字節) */

    for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {

    *buf=(rNFDATA & 0xff);

    buf++;

    }

    }

    /* 停止驅動 Nand Flash */

    NF_nFCE_H();

    return 0;

    }5. 校查搬移后的數據

    把 RAM 中的前 4K 與內部中前 4K 進行比較, 如果完全相同, 則表示搬移成功.

    ok_nand_read:

    mov r0, #0x00000000 @內部 RAM 的起始地址

    ldr r1,=UBOOT_RAM_BASE @UBOOT 在 RAM 中的起始地址

    mov r2, #0x400 @比較 1024 次, 每次 4 字節, 4 bytes * 1024=4K-bytes

    go_next: @ 比較 1024 次, 每次 4 個字節

    ldr r3, [r0], #4

    ldr r4, [r1], #4

    teq r3, r4

    bne notmatch

    subs r2, r2, #4

    beq done_nand_read

    bne go_next

    notmatch:

    1:b 1b

    done_nand_read:

    mov pc, r10

    3.2 U-BOOT 對 Nand Flash 命令的支持

    在 U-BOOT 下對 Nand Flash 的支持主要是在命令行下實現對 nand flash 的操作。對 nand flash 實現的命令

    為:nand info、nand device、nand read、nand write、nand erease、nand bad。

    用到的主要數據結構有:struct nand_flash_dev、struct nand_chip。前者包括主要的芯片型號、存儲容量、

    設備 ID、I/O 總線寬度等信息;后者是具體對 nand flash 進行操作時用到的信息。

    3.2.1 主要數據結構介紹

    1. struct nand_flash_dev 數據結構

    該數據結構在 include/linux/mtd/nand.h 中定義,在 include/linux/mtd/nand_ids.h 中賦初值。

    struct nand_flash_dev {

    char *name;

    /* 芯片名稱 */

    int manufacture_id; /* 廠商 ID */

    int model_id; /* 模式 ID */

    int chipshift; /* Nand Flash 地址位數 */

    char page256; /* 表明是否時 256 字節一頁。1:是;0:否。*/

    char pageadrlen; /* 完成一次地址傳送需要往 NFADDR 中傳送幾次。*/

    unsigned long erasesize; /* 一次塊擦除可以擦除多少字節 */

    int bus16; /* 地址線是否是 16 位,1:是;0:否 */

    };

    2. struct nand_chip 數據結構

    該數據結構在 include/linux/mtd/nand.h 中定義. 該結構體定義出一個 Nand Flash 設備數組:

    struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];

    該數組在 nand_probe()中對其進行初始化.

    struct nand_chip {

    int

    page_shift; /* Page 地址位數 */

    u_char *data_buf; /* 本次讀出的一頁數據 */

    u_char *data_cache; /* 讀出的一頁數據 */

    int cache_page; /* 上次操作的頁號 */u_char ecc_code_buf[6]; /* ECC 校驗碼 */

    u_char reserved[2];

    char ChipID;

    /* 芯片 ID 號 */

    struct Nand *chips; /* Nand Flash 芯片列表, 表示支持幾個芯片為一個設備*/

    int chipshift;

    char* chips_name; /* Nand Flash 芯片名稱 */

    unsigned long erasesize; /* 塊擦寫的大小 */

    unsigned long mfr; /* 廠商 ID */

    unsigned long id; /* 模式 ID */

    char* name; /* 設備名稱 */

    int numchips; /* 有幾塊 Nand Flash 芯片 */

    char page256; /* 一頁是 256 字節, 還是 512 字節 */

    char pageadrlen; /* 頁地址的長度 */

    unsigned long IO_ADDR; /* 用于對 nand flash 進行尋址的地址值存放處 */

    unsigned long totlen; /* Nand Flash 總共大小 */

    uint oobblock; /* 一頁的大小。本款 nand flash 為 512 */

    uint oobsize;

    /* spare array 大小。本款 nand flash 為 16 */

    uint eccsize; /* ECC 大小 */

    int bus16; /* 地址線是否是 16 位,1:是;0:否 */

    };

    3.2.2 支持的命令函數說明

    1. nand info/nand device

    功能:顯示當前 nand flash 芯片信息。

    函數調用關系如下(按先后順序):

    static void nand_print(struct nand_chip *nand) ;

    2. nand erase

    功能:擦除指定塊上的數據。

    函數調用關系如下(按先后順序):

    int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean);

    3. nand bad

    功能:顯示壞塊。

    函數調用關系如下(按先后順序):

    static void nand_print_bad(struct nand_chip* nand);

    int check_block (struct nand_chip *nand, unsigned long pos);

    4. nand read

    功能:讀取 nand flash 信息到 SDRAM。

    函數調用關系如下(按先后順序):

    int nand_rw (struct nand_chip* nand, int cmd,size_t start, size_t len, size_t * retlen, u_char * buf);

    static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,

    size_t * retlen, u_char *buf, u_char *ecc_code);

    static void NanD_ReadBuf (struct nand_chip *nand, u_char * data_buf, int cntr);

    READ_NAND(adr);

    5. nand write

    功能:從 SDRAM 寫數據到 nand flash 中。

    函數調用關系如下(按先后順序):int nand_rw (struct nand_chip* nand, int cmd,size_t start, size_t len, size_t * retlen, u_char * buf);

    static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,

    size_t * retlen, const u_char * buf, u_char * ecc_code);

    static int nand_write_page (struct nand_chip *nand, int page, int col, int last, u_char * ecc_code);

    WRITE_NAND(d , adr);

    3.2.3 U-BOOT 支持 Nand Flash 命令移植說明

    1. 設置配置選項

    在 CONFIG_COMMANDS 中, 打開 CFG_CMD_NAND 選項.

    #define CONFIG_COMMANDS \

    (CONFIG_CMD_DFL

    | \

    CFG_CMD_CACHE

    | \

    CFG_CMD_NAND

    | \

    /*CFG_CMD_EEPROM |*/ \

    /*CFG_CMD_I2C

    |*/ \

    /*CFG_CMD_USB

    |*/ \

    CFG_CMD_PING | \

    CFG_CMD_REGINFO | \

    CFG_CMD_DATE

    | \

    CFG_CMD_ELF)

    #if (CONFIG_COMMANDS & CFG_CMD_NAND)

    #define CFG_NAND_BASE 0x4E000000 /* Nand Flash 控制器在 SFR 區中起始寄存器地址 */

    #define CFG_MAX_NAND_DEVICE 1 /* 支持的最在 Nand Flash 數據 */

    #define SECTORSIZE 512 /* 1 頁的大小 */

    #define NAND_SECTOR_SIZE SECTORSIZE

    #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE – 1) /* 頁掩碼 */

    #define ADDR_COLUMN 1 /* 一個字節的 Column 地址 */

    #define ADDR_PAGE 3 /* 3 字節的頁塊地址, A9-A25*/

    #define ADDR_COLUMN_PAGE 4 /* 總共 4 字節的頁塊地址 */

    #define NAND_ChipID_UNKNOWN 0x00 /* 未知芯片的 ID 號 */

    #define NAND_MAX_FLOORS 1

    #define NAND_MAX_CHIPS 1

    /* Nand Flash 命令層底層接口函數 */

    #define WRITE_NAND_COMMAND(d, adr) do {rNFCMD=d;} while(0)

    #define WRITE_NAND_ADDRESS(d, adr) do {rNFADDR=d;} while(0)

    #define WRITE_NAND(d, adr) do {rNFDATA=d;} while(0)

    #define READ_NAND(adr) (rNFDATA)

    #define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));}

    #define NAND_DISABLE_CE(nand) {rNFCONF |=(1<<11);}

    #define NAND_ENABLE_CE(nand) {rNFCONF &=~(1<<11);}

    /* 下面一組操作對 Nand Flash 無效 */

    #define NAND_CTL_CLRALE(nandptr)

    #define NAND_CTL_SETALE(nandptr)

    #define NAND_CTL_CLRCLE(nandptr)

    #define NAND_CTL_SETCLE(nandptr)/* 允許 Nand Flash 寫校驗 */

    #define CONFIG_MTD_NAND_VERIFY_WRITE 1

    #endif /* CONFIG_COMMANDS & CFG_CMD_NAND*/

    2. 加入自己的 Nand Flash 芯片型號

    在 include/linux/mtd/ nand_ids.h 中的對如下結構體賦值進行修改:

    static struct nand_flash_dev nand_flash_ids[]={

    ......

    {"Samsung K9F1208U0B", NAND_MFR_SAMSUNG, 0x76, 26, 0, 4, 0x4000, 0},

    .......

    }

    這樣對于該款 Nand Flash 芯片的操作才能正確執行。

    3. 編寫自己的 Nand Flash 初始化函數

    在 board/crane2410/crane2410.c 中加入 nand_init()函數.

    void nand_init(void)

    {

    /* 初始化 Nand Flash 控制器, 以及 Nand Flash 芯片 */

    nand_reset();

    /* 調用 nand_probe()來檢測芯片類型 */

    printf ("%4lu MB\n", nand_probe(CFG_NAND_BASE) >> 20);

    }

    該函數在啟動時被 start_armboot()調用.

    4 在 Linux 對 Nand Flash 的支持

    4.1 Linux 下 Nand Flash 調用關系

    4.1.1 Nand Flash 設備添加時數據結構包含關系

    struct mtd_partition partition_info[]

    --> struct s3c2410_nand_set nandset

    --> struct s3c2410_platform_nand superlpplatfrom

    --> struct platform_device s3c_device_nand

    在該數據結構的 name字段的初始化值"s3c2410-nand",必須與 Nand Flash設備驅動注冊時

    struct device_driver結構中的 name字段相同,因為 platfrom bus 是依靠名字來匹配的.

    --> struct platform_device *smdk2410_devices[]

    4.1.2 Nand Flash 設備注冊時數據結構包含關系

    struct device_driver s3c2410_nand_driver

    -->struct device *dev

    該數據構由系統分配.

    -->struct platform_device *pdev

    -->struct s3c2410_platform_nand *plat

    -->struct s3c2410_nand_set nset

    -->struct mtd_partition

    4.1.3 當發生系統調用時數據結構調用關系

    struct mtd_info它的*priv指向 chip

    -->struct nand_chip

    它的*priv指向 nmtd

    -->struct s3c2410_nand_mtd

    它是 s3c2410_nand_info 的一個字段

    -->s3c2410_nand_info

    它被設為 Nand Flash設備驅動的私有數據結構,在 Nand Flash設備驅動注冊時分配空間.

    -->struct device

    4.2 Linux 下 Nand Flash 驅動主要數據結構說明

    4.2.1 s3c2410 專有數據結構

    1. s3c2410_nand_set

    struct s3c2410_nand_set {

    int nr_chips; /* 芯片的數目 */

    int nr_partitions; /* 分區的數目 */

    char *name; /* 集合名稱 */

    int nr_map; /* 可選, 底層邏輯到物理的芯片數目 */

    struct mtd_partition partitions; /* 分區列表 */

    };

    2. s3c2410_platform_and

    struct s3c2410_platform_nand {

    /* timing information for controller, all times in nanoseconds */

    int tacls; /* 從 CLE/ALE有效到 nWE/nOE 的時間 */

    int twrph0; /* nWE/nOE 的有效時間 */

    int twrph1; /* 從釋放 CLE/ALE到 nWE/nOE 不活動的時間 */

    int nr_sets; /* 集合數目 */

    struct s3c2410_nand_set sets; /* 集合列表 */

    /* 根據芯片編號選擇有效集合 */

    void (*select_chip)(struct s3c2410_nand_set , int chip);

    };

    3. s3c2410_nand_mtd

    在 drivers/mtd/nand/s3c2410.c 中,

    struct s3c2410_nand_mtd {

    struct mtd_info mtd; /* MTD 信息 */

    struct nand_chip chip; /* nand flash 芯片信息 */

    struct s3c2410_nand_set set; /* nand flash 集合 */

    struct s3c2410_nand_info *info; /* nand flash 信息 */

    int scan_res;

    };

    4. s3c2410_nand_info

    struct s3c2410_nand_info {

    /* mtd info */

    struct nand_hw_control controller; /* 硬件控制器 */

    struct s3c2410_nand_mtd *mtds; /* MTD 設備表 */

    struct s3c2410_platform_nand platform; /* Nand 設備的平臺 */ /* device info */

    struct device *device; /* 設備指針 */

    struct resource *area; /* 資源指針 */

    struct clk *clk; /* Nand Flash 時鐘 */

    void __iomem *regs; /* 寄存器基地址(map后的邏輯地址) */

    int mtd_count; /* MTD的數目 */

    unsigned char is_s3c2440;

    };

    5. struct clk

    在 arch/arm/mach-s3c2410/clock.h 中

    struct clk {

    struct list_head list; /* clock 列表結點 */

    struct module *owner; /* 所屬模塊 */

    struct clk *parent; /* 父結點 */

    const char *name; /* 名稱 */

    int id; /* 編號 */

    atomic_t used; /* 使用者計數 */

    unsigned long rate; /* 時鐘速率 */

    unsigned long ctrlbit; /* 控制位 */

    int (*enable)(struct clk *, int enable); /* Clock 打開方法 */

    };

    4.2.2 Linux 通用數據結構說明

    1. device_driver

    include/linux/device.h

    struct device_driver {

    const char * name; /* 驅動名稱 */

    struct bus_type * bus; /* 總線類型 */

    struct completion unloaded; /* 卸載事件通知機制 */

    struct kobject kobj; /* sys中的對象 */

    struct klist klist_devices; /* 設備列表 */

    struct klist_node knode_bus; /* 總線結點列表 */

    struct module * owner;/* 所有者 */

    /* 設備驅動通用方法 */

    int (*probe) (struct device * dev); /* 探測設備 */

    int (*remove) (struct device * dev); /* 移除設備 */

    void (*shutdown) (struct device * dev); /* 關閉設備 */

    /* 掛起設備 */

    int (*suspend) (struct device * dev, pm_message_t state, u32 level);

    int (*resume) (struct device * dev, u32 level); /* 恢復 */

    };

    2. platform_device

    include/linux/device.h

    struct platform_device {

    const char * name; /* 名稱 */

    u32 id; /* 設備編號, -1表示不支持同類多個設備 */

    struct device dev; /* 設備 */

    u32 num_resources; /* 資源數 */

    struct resource * resource; /* 資源列表 */};

    3. resource

    struct resource {

    const char name; /* 資源名稱 */

    unsigned long start, end; /* 開始位置和結束位置 */

    unsigned long flags; /* 資源類型 */

    /* 資源在資源樹中的父親,兄弟和孩子 */

    struct resource *parent, *sibling, *child;

    };

    4. device

    include/linux/device.h

    struct device {

    struct klist klist_children; /* 在設備列表中的孩子列表 */

    struct klist_node knode_parent; /* 兄弟結點 */

    struct klist_node knode_driver; /* 驅動結點 */

    struct klist_node knode_bus; /* 總線結點 */

    struct device parent; /* 父親 */

    struct kobject kobj; /* sys結點 */

    char bus_id[BUS_ID_SIZE];

    struct semaphore sem; /* 同步驅動的信號量 */

    struct bus_type * bus; /* 總線類型 */

    struct device_driver *driver; /* 設備驅動 */

    void *driver_data; /* 驅動的私有數據 */

    void *platform_data; /* 平臺指定的數據,為 device核心驅動保留 */

    void *firmware_data; /* 固件指定的數據,為 device核心驅動保留 */

    struct dev_pm_info power; /* 設備電源管理信息 */

    u64 *dma_mask; /* DMA掩碼 */

    u64 coherent_dma_mask;

    struct list_head dma_pools; /* DMA緩沖池 */

    struct dma_coherent_mem *dma_mem; /* 連續 DMA 內存的起始位置 */

    void (*release)(struct device * dev); /* 釋放設置方法 */

    };

    5. nand_hw_control

    include/linux/mtd/nand.h

    struct nand_hw_control {

    spinlock_t lock; /* 自旋鎖,用于硬件控制 */

    struct nand_chip *active; /* 正在處理 MTD 設備 */

    wait_queue_head_t wq; /* 等待隊列 */

    };

    6. nand_chip

    include/linux/mtd/nand.h

    struct nand_chip {

    void __iomem *IO_ADDR_R; /* 讀地址 */

    void __iomem *IO_ADDR_W; /* 寫地址 */ /* 字節操作 */

    u_char (*read_byte)(struct mtd_info *mtd); /* 讀一個字節 */

    void (*write_byte)(struct mtd_info *mtd, u_char byte); /* 寫一個字節 */

    /* 雙字節操作 */

    u16 (*read_word)(struct mtd_info mtd); /* 讀一個字 */

    void (*write_word)(struct mtd_info *mtd, u16 word); /* 寫一個字 */

    /* buffer操作 */

    void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);

    void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);

    int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);

    /* 選擇一個操作芯片 */

    void (*select_chip)(struct mtd_info *mtd, int chip);

    /* 壞塊檢查操作 */

    int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);

    /* 壞塊標記操作 */

    int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);

    /* 硬件控制操作 */

    void (*hwcontrol)(struct mtd_info *mtd, int cmd);

    /* 設備準備操作 */

    int (*dev_ready)(struct mtd_info *mtd);

    /* 命令發送操作 */

    void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int

    page_addr);

    /* 等待命令完成 */

    int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);

    /* 計算 ECC 碼操作 */

    int (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char

    *ecc_code);

    /* 數據糾錯操作 */

    int (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc,

    u_char *calc_ecc);

    /* 開啟硬件 ECC */

    void (*enable_hwecc)(struct mtd_info *mtd, int mode);

    /* 擦除操作 */

    void (*erase_cmd)(struct mtd_info *mtd, int page);

    /* 檢查壞塊表 */

    int (*scan_bbt)(struct mtd_info *mtd);

    int eccmode; /* ECC 模式 */

    int eccsize; /* ECC 計算時使用的字節數 */

    int eccbytes; /* ECC 碼的字節數 */

    int eccsteps; /* ECC 碼計算的步驟數 */

    int chip_delay; /* 芯片的延遲時間 */

    spinlock_t chip_lock; /* 芯片訪問的自旋鎖 */

    wait_queue_head_t wq; /* 芯片訪問的等待隊列 */

    nand_state_t state; /* Nand Flash狀態 */

    int page_shift; /* 頁右移的位數,即 column地址位數 */

    int phys_erase_shift; /* 塊右移的位數, 即 column和頁一共的地址位數 */

    int bbt_erase_shift; /* 壞塊頁表的位數 */

    int chip_shift; /* 該芯片總共的地址位數 */

    u_char *data_buf; /* 數據緩沖區 */

    u_char *oob_buf; /* oob 緩沖區 */

    int oobdirty; /* oob 緩沖區是否需要重新初始化 */

    u_char *data_poi; /* 數據緩沖區指針 */

    unsigned int options; /* 芯片專有選項 */

    int badblockpos;/* 壞塊標示字節在 OOB 中的位置 */

    int numchips; /* 芯片的個數 */ unsigned long chipsize; /* 在多個芯片組中, 一個芯片的大小 */

    int pagemask; /* 每個芯片頁數的屏蔽字, 通過它取出每個芯片包含多少個頁 */

    int pagebuf; /* 在頁緩沖區中的頁號 */

    struct nand_oobinfo *autooob; /* oob 信息 */

    uint8_t *bbt; /* 壞塊頁表 */

    struct nand_bbt_descr *bbt_td; /* 壞塊表描述 */

    struct nand_bbt_descr *bbt_md; /* 壞塊表鏡像描述 */

    struct nand_bbt_descr *badblock_pattern; /* 壞塊檢測模板 */

    struct nand_hw_control *controller; /* 硬件控制 */

    void *priv; /* 私有數據結構 */

    /* 進行附加錯誤檢查 */

    int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int

    status, int page);

    };

    7. mtd_info

    include/linux/mtd/mtd.h

    struct mtd_info {

    u_char type; /* 設備類型 */

    u_int32_t flags; /* 設備標志位組 */

    u_int32_t size; /* 總共設備的大小 */

    u_int32_t erasesize; /* 擦除塊的大小 */

    u_int32_t oobblock; /* OOB塊的大小,如:512 個字節有一個 OOB */

    u_int32_t oobsize; /* OOB數據的大小,如:一個 OOB 塊有 16 個字節 */

    u_int32_t ecctype; /* ECC 校驗的類型 */

    u_int32_t eccsize; /* ECC 碼的大小 */

    char *name; /* 設備名稱 */

    int index; /* 設備編號 */

    /* oobinfo 信息,它可以通過 MEMSETOOBINFO ioctl 命令來設置 */

    struct nand_oobinfo oobinfo;

    u_int32_t oobavail; /* OOB區的有效字節數,為文件系統提供 */

    /* 數據擦除邊界信息 */

    int numeraseregions;

    struct mtd_erase_region_info *eraseregions;

    u_int32_t bank_size; /* 保留 */

    /* 擦除操作 */

    int (*erase) (struct mtd_info *mtd, struct erase_info *instr);

    /* 指向某個執行代碼位置 */

    int (*point) (struct mtd_info *mtd, loff_t from,

    size_t len, size_t *retlen, u_char **mtdbuf);

    /* 取消指向 */

    void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);

    /* 讀/寫操作 */

    int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);

    int (*write) (struct mtd_info *mtd, loff_t to, size_t len,

    size_t *retlen, const u_char *buf);

    /* 帶 ECC 碼的讀/寫操作 */

    int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,

    u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);

    int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,

    const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); /* 帶 OOB 碼的讀/寫操作 */

    int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,

    u_char *buf);

    int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,

    const u_char *buf);

    /* 提供訪問保護寄存器區的方法 */

    int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);

    int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len,

    size_t *retlen, u_char *buf);

    int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);

    int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len,

    size_t *retlen, u_char *buf);

    int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len,

    size_t *retlen, u_char *buf);

    int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);

    /* 提供 readv和 writev 方法 */

    int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count,

    loff_t from, size_t *retlen);

    int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count,

    loff_t from, size_t *retlen, u_char *eccbuf,

    struct nand_oobinfo *oobsel);

    int (*writev) (struct mtd_info *mtd, const struct kvec *vecs,

    unsigned long count, loff_t to, size_t *retlen);

    int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs,

    unsigned long count, loff_t to, size_t *retlen,

    u_char *eccbuf, struct nand_oobinfo *oobsel);

    /* 同步操作 */

    void (*sync) (struct mtd_info *mtd);

    /* 芯片級支持的加/解鎖操作 */

    int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);

    int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);

    /* 電源管理操作 */

    int (*suspend) (struct mtd_info *mtd);

    void (*resume) (struct mtd_info *mtd);

    /* 壞塊管理操作 */

    int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);

    int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);

    /* 重啟前的通知事件 */

    struct notifier_block reboot_notifier;

    void *priv; /* 私有數據結構 */

    struct module *owner; /* 模塊所有者 */

    int usecount; /* 使用次數 */

    };

    4.3 Linux 下 Nand Flash 驅動說明4.3.1 注冊 driver_register

    通過 module_init(s3c2410_nand_init);注冊 Nand Flash 驅動. 在 s3c2410_nand_init ()中通過 driver_register()注冊

    s3c2410_nand_driver驅動程序,如下所示:

    static struct device_driver s3c2410_nand_driver={

    .name="s3c2410-nand",

    .bus=&platform_bus_type, /* 在 drivers/base/platform.c中定義 */

    .probe=s3c2410_nand_probe,

    .remove=s3c2410_nand_remove,

    };

    4.3.2 探測設備 probe

    在注冊的 Nand Flash驅動程序中, probe 方法為 s3c2410_nand_probe(). s3c2410_nand_probe()再調用

    s3c24xx_nand_probe(). 在該函數中, 把*info 作為 Nand Flash 驅動的私有數據結構, 并通過 dev_set_drvdata(dev,

    info)把*info 保存在*device 的*driver_data 字段中.然后通過 clk_get(dev, "nand")獲取 Nand Flash的時鐘資

    源, clk_use(info->clk)增加時鐘資源的使用計數, clk_enable(info->clk)開啟資源.填寫*info 的其它字段,

    其中包括:

    1. 通過 request_mem_region()為 Nand Flash 寄存器區申請 I/O 內存地址空間區,并通過 ioremap()把它映射到虛

    擬地址空間.

    2. 調用 s3c2410_nand_inithw()初始化 Nand Flash 控制器.

    3. 為 mtd 設備分配設備信息的存儲空間.

    4. 對當前 mtd 設備,調用 s3c2410_nand_init_chip()進行初始化.

    5. 對當前 mtd 設備, 調用 nand_scan()檢測 Nand Flash 芯片, nand_scan()函數在 drivers/mtd/nand/nand_base.c 中

    定義.該函數的作用是初始化 struct nand_chip 中一些方法, 并從 Nand Flash 中讀取芯片 ID, 并初始化 struct

    mtd_info 中的方法.

    6. 對當前 mtd 設備,加入其分區信息.

    7. 如果還有更多 mtd 設備,到 4 執行.

    4.3.3 初始化 Nand Flash 控制器

    s3c2410_nand_inithw()函數會初始化 Nand Flash 控制器, 通過設置 Nand Flash 控制寄存器(S3C2410_NFCONF)來

    完成, 這里最重要的是根據 S3C2410 的 PCLK 計算出 tacls, twrph0 以及 twrph1 值.

    4.3.4 移除設備

    s3c2410_nand_remove()當設備被移除時,被 device 核心驅動調用.它完成的主要工作如下:

    1. 把*device 的*driver_data 字段置空.

    2. 釋放 mtd 設備信息.

    3. 釋放 clk 資源.

    4. 通過 iounmap()取消映地址空間.

    5. 釋放申請的 I/O 內存資源.

    6. 釋放設備私有數據*info 的空間.

    4.3.5 Nand Flash 芯片初始化

    s3c2410_nand_init_chip()初始化 struct nand_chip 中的一些主要字段以及方法.其中主要包括的方法有:

    1. s3c2410_nand_hwcontrol(); 硬件控制

    2. s3c2410_nand_devready(); 設備是否準備好

    3. s3c2410_nand_write_buf(); 寫一個 buffer 到 nand flash

    4. s3c2410_nand_read_buf(); 讀一個 buffer 到 nand flash

    5. s3c2410_nand_select_chip(); 選擇操作芯片

    如果支持 ECC 硬件校驗,還設置如下方法: 1. s3c2410_nand_correct_data(); 通過 ECC 碼校正數據

    2. s3c2410_nand_enable_hwecc(); 開啟硬件 ECC 檢查

    3. s3c2410_nand_calculate_ecc(); 計算 ECC 碼

    4.3.6 讀 Nand Flash

    當對 nand flash 的設備文件(nand flash 在/dev 下對應的文件)執行系統調用 read(),或在某個文件系統中對該

    設備進行讀操作時. 會調用 struct mtd_info 中的 read方法,他們缺省調用函數為 nand_read(),在

    drivers/mtd/nand/nand_base.c中定義.nand_read()調用 nand_do_read_ecc(),執行讀操作. 在

    nand_do_read_ecc()函數中,主要完成如下幾項工作:

    1. 會調用在 nand flash驅動中對 struct nand_chip 重載的 select_chip 方法,即

    s3c2410_nand_select_chip()選擇要操作的 MTD 芯片.

    2. 會調用在 struct nand_chip 中系統缺省的方法 cmdfunc 發送讀命令到 nand flash.

    3. 會調用在 nand flash驅動中對 struct nand_chip 重載的 read_buf(),即 s3c2410_nand_read_buf()

    從 Nand Flash的控制器的數據寄存器中讀出數據.

    4. 如果有必要的話,會調用在 nand flash驅動中對 struct nand_chip 重載的

    enable_hwecc,correct_data 以及 calculate_ecc方法,進行數據 ECC 校驗。

    4.3.7 寫 Nand Flash

    當對 nand flash 的設備文件(nand flash 在/dev 下對應的文件)執行系統調用 write(),或在某個文件系統中對該設備

    進行讀操作時, 會調用 struct mtd_info 中 write 方法,他們缺省調用函數為 nand_write(),這兩個函數在

    drivers/mtd/nand/nand_base.c中定義. nand_write()調用 nand_write_ecc(),執行寫操作.在

    nand_do_write_ecc()函數中,主要完成如下幾項工作:

    1. 會調用在 nand flash驅動中對 struct nand_chip 重載的 select_chip 方法,即

    s3c2410_nand_select_chip()選擇要操作的 MTD 芯片.

    2. 調用 nand_write_page()寫一個頁.

    3. 在 nand_write_page()中,會調用在 struct nand_chip 中系統缺省的方法 cmdfunc 發送寫命令

    到 nand flash.

    4. 在 nand_write_page()中,會調用在 nand flash驅動中對 struct nand_chip 重載的

    write_buf(),即 s3c2410_nand_write_buf()從 Nand Flash的控制器的數據寄存器中寫入數據.

    5. 在 nand_write_page()中,會調用在 nand flash驅動中對 struct nand_chip 重載 waitfunc 方法,

    該方法調用系統缺省函數 nand_wait(),該方法獲取操作狀態,并等待 nand flash操作完成.等

    待操作完成,是調用 nand flash驅動中對 struct nand_chip 中重載的 dev_ready方法,即

    s3c2410_nand_devready()函數.

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有