驅動09.nand flash

来源:http://www.cnblogs.com/Lwd-linux/archive/2017/01/13/6283263.html
-Advertisement-
Play Games

1 nand flash的操作 目的:讀地址A的數據,把數據B寫到地址A。 問1. 原理圖上NAND FLASH和S3C2440之間只有數據線,怎麼傳輸地址?答1.在DATA0~DATA7上既傳輸數據,又傳輸地址,當ALE為高電平時傳輸的是地址。 問2. 從NAND FLASH晶元手冊可知,要操作N ...


1 nand flash的操作

目的:讀地址A的數據,把數據B寫到地址A。

問1. 原理圖上NAND FLASH和S3C2440之間只有數據線,怎麼傳輸地址?
答1.在DATA0~DATA7上既傳輸數據,又傳輸地址,當ALE為高電平時傳輸的是地址。

問2. 從NAND FLASH晶元手冊可知,要操作NAND FLASH需要先發出命令
     怎麼傳入命令?
答2.在DATA0~DATA7上既傳輸數據,又傳輸地址,也傳輸命令
     當ALE為高電平時傳輸的是地址,
     當CLE為高電平時傳輸的是命令
     當ALE和CLE都為低電平時傳輸的是數據
問3. 數據線既接到NAND FLASH,也接到NOR FLASH,還接到SDRAM、DM9000等等,那麼怎麼避免干擾?
答3. 這些設備,要訪問之必須"選中",沒有選中的晶元不會工作,相當於沒接一樣。(記憶體控制器
問4. 假設燒寫NAND FLASH,把命令、地址、數據發給它之後,
     NAND FLASH肯定不可能瞬間完成燒寫的,怎麼判斷燒寫完成?
答4. 通過狀態引腳RnB來判斷:它為高電平表示就緒,它為低電平表示正忙

問5. 怎麼操作NAND FLASH呢?
答5. 根據NAND FLASH的晶元手冊,一般的過程是:
     發出命令
     發出地址
     發出數據/讀數據

2 分析nand flash的啟動過程

搜"S3C24XX NAND Driver"
S3c2410.c (drivers\mtd\nand)

s3c2410_nand_inithw
s3c2410_nand_init_chip
nand_scan  // 根據nand_chip的底層操作函數識別NAND FLASH,構造mtd_info
    nand_scan_ident
        nand_set_defaults
            if (!chip->select_chip)
                chip->select_chip = nand_select_chip; // 預設值不適用

            if (chip->cmdfunc == NULL)
                chip->cmdfunc = nand_command;
                                    chip->cmd_ctrl(mtd, command, ctrl);
            if (!chip->read_byte)
                chip->read_byte = nand_read_byte;
                                    readb(chip->IO_ADDR_R);
            if (chip->waitfunc == NULL)
                chip->waitfunc = nand_wait;
                                    chip->dev_ready
        
        
        nand_get_flash_type
            chip->select_chip(mtd, 0);
            chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
            *maf_id = chip->read_byte(mtd);
            dev_id = chip->read_byte(mtd);
    nand_scan_tail
            mtd->erase = nand_erase;
            mtd->read = nand_read;
            mtd->write = nand_write;
s3c2410_nand_add_partition
    add_mtd_partitions
        add_mtd_device
            list_for_each(this, &mtd_notifiers) { // 問. mtd_notifiers在哪設置
                                                  // 答. drivers/mtd/mtdchar.c,mtd_blkdev.c調用register_mtd_user
                struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
                not->add(mtd);
                // mtd_notify_add  和 blktrans_notify_add
                先看字元設備的mtd_notify_add
                        class_device_create
                        class_device_create
                再看塊設備的blktrans_notify_add
                    list_for_each(this, &blktrans_majors) { // 問. blktrans_majors在哪設置
                                                            // 答. drivers\mtd\mdblock.c或mtdblock_ro.c   register_mtd_blktrans
                        struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);              
                        tr->add_mtd(tr, mtd);
                                mtdblock_add_mtd (drivers\mtd\mdblock.c)
                                    add_mtd_blktrans_dev
                                        alloc_disk
                                        gd->queue = tr->blkcore_priv->rq; // tr->blkcore_priv->rq = blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue_lock);
                                        add_disk            

3 nand flash驅動程式框架

(1)分配一個nand_chip/mtd_info結構體

(2)設置

(3)硬體相關的操作

(4)使用nand_scan/add_mtd_partitions

4 寫代碼

參考drivers\mtd\nand\s3c2410.c

  1 /*參考drivers\mtd\nand\at91_nand.c*/
  2 
  3 
  4 #include <linux/module.h>
  5 #include <linux/types.h>
  6 #include <linux/init.h>
  7 #include <linux/kernel.h>
  8 #include <linux/string.h>
  9 #include <linux/ioport.h>
 10 #include <linux/platform_device.h>
 11 #include <linux/delay.h>
 12 #include <linux/err.h>
 13 #include <linux/slab.h>
 14 #include <linux/clk.h>
 15 
 16 #include <linux/mtd/mtd.h>
 17 #include <linux/mtd/nand.h>
 18 #include <linux/mtd/nand_ecc.h>
 19 #include <linux/mtd/partitions.h>
 20 
 21 #include <asm/io.h>
 22 
 23 #include <asm/arch/regs-nand.h>
 24 #include <asm/arch/nand.h>
 25 
 26 
 27 struct s3c_nand_regs {
 28     unsigned long nfconf  ;
 29     unsigned long nfcont  ;
 30     unsigned long nfcmd   ;
 31     unsigned long nfaddr  ;
 32     unsigned long nfdata  ;
 33     unsigned long nfeccd0 ;
 34     unsigned long nfeccd1 ;
 35     unsigned long nfeccd  ;
 36     unsigned long nfstat  ;
 37     unsigned long nfestat0;
 38     unsigned long nfestat1;
 39     unsigned long nfmecc0 ;
 40     unsigned long nfmecc1 ;
 41     unsigned long nfsecc  ;
 42     unsigned long nfsblk  ;
 43     unsigned long nfeblk  ;
 44 };
 45 
 46 static struct mtd_info *s3c_mtd;
 47 static struct nand_chip *s3c_nand;
 48 
 49 
 50 static struct mtd_partition s3c_nand_parts[] = {
 51     [0] = {
 52         .name   = "bootloader",
 53         .size   = 0x00040000,
 54         .offset    = 0,
 55     },
 56     [1] = {
 57         .name   = "params",
 58         .offset = MTDPART_OFS_APPEND,
 59         .size   = 0x00020000,
 60     },
 61     [2] = {
 62         .name   = "kernel",
 63         .offset = MTDPART_OFS_APPEND,
 64         .size   = 0x00200000,
 65     },
 66     [3] = {
 67         .name   = "root",
 68         .offset = MTDPART_OFS_APPEND,
 69         .size   = MTDPART_SIZ_FULL,
 70     }
 71 };
 72 
 73 static void s3c2440_select_chip(struct mtd_info *mtd, int chipnr)
 74 {
 75     if (chipnr == -1)
 76     {
 77         /* 取消選中: NFCONT[1]設為1 */
 78         s3c_nand_regs->nfcont |= (1<<1);        
 79     }
 80     else
 81     {
 82         /* 選中: NFCONT[1]設為0 */
 83         s3c_nand_regs->nfcont &= ~(1<<1);
 84     }
 85 }
 86 
 87 static void s3c2440_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
 88 {
 89     if (ctrl & NAND_CLE)
 90     {
 91         /* 發命令: NFCMMD=dat */
 92         s3c_nand_regs->nfcmd = dat;
 93     }
 94     else
 95     {
 96         /* 發地址: NFADDR=dat */
 97         s3c_nand_regs->nfaddr = dat;
 98     }
 99 }
100 
101 static int s3c2440_dev_ready(struct mtd_info *mtd)
102 {
103     return (s3c_nand_regs->nfstat & (1<<0));
104 }
105 
106 
107 static int s3c_nand_init(void)
108 {
109     struct clk *clk;
110     s3c_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
111 
112     s3c_nand_regs = ioremap(0x4E000000, sizeof(struct s3c_nand_regs));
113 
114     s3c_nand->select_chip = s3c2440_select_chip;
115     s3c_nand->cmd_ctrl = s3c2440_cmd_ctrl;
116     s3c_nand->IO_ADDR_R = &s3c_nand_regs->nfdata;
117     s3c_nand->IO_ADDR_W = &s3c_nand_regs->nfdata;
118     s3c_nand->dev_ready   = s3c2440_dev_ready;
119     s3c_nand->ecc.mode    = NAND_ECC_SOFT;//enable ECC
120     
121     clk = clk_get(NULL, "nand");
122     clk_enable(clk);              
123 
124 #define TACLS    0
125 #define TWRPH0   1
126 #define TWRPH1   0
127     s3c_nand_regs->nfconf = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
128     s3c_nand_regs->nfcont = (1<<1) | (1<<0);
129     
130     s3c_mtd = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
131     s3c_mtd->owner = THIS_MODULE;
132     s3c_mtd->priv = s3c_nand;
133     nand_scan(s3c_mtd, 1);//識別nand falsh,構造mtd_info
134 
135     add_mtd_partitions(s3c_mtd, s3c_nand_parts,4);
136 
137     return 0;
138 }
139 
140 
141 static void s3c_nand_exit(void)
142 {
143     del_mtd_partitions(s3c_mtd);
144     kfree(s3c_mtd);
145     iounmap(s3c_nand_regs);
146     kfree(s3c_nand);
147 }
148 
149 module_init(s3c_nand_init);
150 module_exit(s3c_nand_exit);
151 
152 MODULE_LICENSE("GPL");
s3c_nand.c

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 配置環境: 操作系統:Windows Server 2003 sp2企業版 Web伺服器:系統自帶的IIS6.0 所需工具: PHP:php-5.2.12-Win32.zip(官方網址:http://www.php.net) 資料庫:mysql-5.0.22-win32.zip(官方網址:http: ...
  • 用MSI安裝包安裝 根據自己的操作系統下載對應的32位或64位安裝包。按如下步驟操作: MySQL資料庫官網的下載地址http://dev.mysql.com/downloads/mysql,第一步: 安裝許可 雙擊安裝文件,在如下圖所示界面中勾選“I accept the license term ...
  • 這篇文章將對linux下udp socket編程重要知識點進行總結,無論是開發人員應知應會的,還是說udp socket的一些偏僻知識點,本文都會講到。儘可能做到,讀了一篇文章之後,大家對udp socket有一個比較全面的認識。本文分為兩個專題,第一個是常用的upd socket框架,第二個是一些 ...
  • redhat 的更新包只對註冊的用戶生效,所以我們需要自己手動更改成CentOS 的更新包,CentOS幾乎和redhat是一樣的,所以無需擔心軟體包是否可安裝,安裝之後是否有問題。 ...
  • linux教學輔助訓練(第二階段) 標簽(空格分隔):Linux輔助訓練 [更多資料點我查看][1] 提示 :本階段性練習題是對《實戰教學筆記》相應章節知識的歸納與擴展部分,必須要會,是面試前必須重溫的一套基礎練習。(第一階段即為實戰教學筆記第四節 Linux命令基礎)。 一,問答考試 1.1 解釋 ...
  • 第十節 正則表達式 標簽(空格分隔):Linux實戰教學筆記 [更多資料點我查看][1] 第1章 什麼是正則表達式 1. 正則表達式就是為了處理大量的文本|字元串而定義的一套規則和方法 2. 通過定義的這些特殊符號的輔助,系統管理員就可以快速過濾,替換或輸出需要的字元串。Linux正則表達式一般以行 ...
  • 這裡說的“後門”並不是教你做壞事,而是讓你做好事,搭建自己的調試工具更好地進行調試開發。我們都知道,當程式發生異常錯誤時,我們需要定位到錯誤,有時我們還想,我們在不修改程式的前提下,就能通過log來定位錯誤呢?有人會說,我在我的程式裡加多點列印就好了,程式每做一步我就加一行列印,到時一查log就知道 ...
  • 1 比較nor/nand flash NOR NAND介面: RAM-Like,引腳多 引腳少,復用容量: 小 1M 2M 3M 大:128M 256M G讀: 簡單 複雜寫: 發出特定命令 慢 發出特定命令 快價格: 貴 便宜特點: 無位反轉、壞塊 位反轉、壞塊 關鍵重要的程式 大數據、容忍可以出 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...