NAND FLASH驅(qū)動(dòng)程序
#include "linux/module.h"
#include "linux/types.h"
#include "linux/init.h"
#include "linux/kernel.h"
#include "linux/string.h"
#include "linux/ioport.h"
#include "linux/platform_device.h
#include "linux/delay.h"
#include "linux/err.h"
#include "linux/slab.h"
#include "linux/clk.h"
#include "linux/mtd/mtd.h"
#include "linux/mtd/nand.h"
#include "linux/mtd/nand_ecc.h"
#include "linux/mtd/partitions.h"
#include "asm/io.h"
#include "asm/arch/regs-nand.h"
#include "asm/arch/nand.h"
struct s3c_nand_regs {
};
static struct nand_chip *s3c_nand;
static struct mtd_info *s3c_mtd;
static struct s3c_nand_regs *s3c_nand_regs;
static struct mtd_partition s3c_nand_parts[] = {
};
static void s3c2440_select_chip(struct mtd_info *mtd, int chipnr)
{
}
static void s3c2440_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
}
static int s3c2440_dev_ready(struct mtd_info *mtd)
{
}
static int s3c_nand_init(void)
{
/ 設(shè)置nand_chip是給nand_scan函數(shù)使用的, 如果不知道怎么設(shè)置, 先看nand_scan怎么使用
/ 它應(yīng)該提供:選中,發(fā)命令,發(fā)地址,發(fā)數(shù)據(jù),讀數(shù)據(jù),判斷狀態(tài)的功能
// 使能NAND FLASH控制器的時(shí)鐘
* TACLS: 發(fā)出CLE/ALE之后多長(zhǎng)時(shí)間才發(fā)出nWE信號(hào), 從NAND手冊(cè)可知CLE/ALE與nWE可以同時(shí)發(fā)出,所以TACLS=0
* TWRPH0: nWE的脈沖寬度, HCLK x ( TWRPH0 + 1 ), 從NAND手冊(cè)可知它要>=12ns, 所以TWRPH0>=1
* TWRPH1: nWE變?yōu)楦唠娖胶蠖嚅L(zhǎng)時(shí)間CLE/ALE才能變?yōu)榈碗娖? 從NAND手冊(cè)可知它要>=5ns, 所以TWRPH1>=0
//
#define TACLS 0
#define TWRPH0 1
#define TWRPH1 0
* BIT1-設(shè)為1, 取消片選
* BIT0-設(shè)為1, 使能NAND FLASH控制器
//
}
static void s3c_nand_exit(void)
{
}
module_init(s3c_nand_init);
module_exit(s3c_nand_exit);
MODULE_LICENSE("GPL");
=================================================================
NAND FLASH是一個(gè)存儲(chǔ)芯片
那么: 這樣的操作很合理"讀地址A的數(shù)據(jù),把數(shù)據(jù)B寫到地址A"
問1. 原理圖上NAND FLASH和S3C2440之間只有數(shù)據(jù)線,
答1.在DATA0~DATA7上既傳輸數(shù)據(jù),又傳輸?shù)刂?/div> 當(dāng)ALE為高電平時(shí)傳輸?shù)氖堑刂罚?/div> 怎么傳入命令?
問2. 從NAND FLASH芯片手冊(cè)可知,要操作NAND FLASH需要先發(fā)出命令
答2.在DATA0~DATA7上既傳輸數(shù)據(jù),又傳輸?shù)刂罚矀鬏斆?/div> 當(dāng)ALE為高電平時(shí)傳輸?shù)氖堑刂罚?/div> 當(dāng)CLE為高電平時(shí)傳輸?shù)氖敲?/div> 當(dāng)ALE和CLE都為低電平時(shí)傳輸?shù)氖菙?shù)據(jù) 那么怎么避免干擾? 沒有選中的芯片不會(huì)工作,相當(dāng)于沒接一樣 NAND FLASH肯定不可能瞬間完成燒寫的, 怎么判斷燒寫完成? 發(fā)出命令 發(fā)出地址 發(fā)出數(shù)據(jù)/讀數(shù)據(jù) NAND FLASH S3C2440 CLE設(shè)為高電平 NFCMMD=命令值 在DATA0~DATA7上輸出命令值 發(fā)出一個(gè)寫脈沖 ALE設(shè)為高電平 在DATA0~DATA7上輸出地址值 發(fā)出一個(gè)寫脈沖 ALE,CLE設(shè)為低電平 在DATA0~DATA7上輸出數(shù)據(jù)值 發(fā)出一個(gè)寫脈沖 發(fā)出讀脈沖 讀DATA0~DATA7的數(shù)據(jù) S3C2440 u-boot 0xda 17 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 S3C2440 u-boot nand_scan_ident nand_set_defaults 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; add_mtd_partitions add_mtd_device list_for_each(this, &mtd_notifiers) { // 問. mtd_notifiers在哪設(shè)置 // 答. drivers/mtd/mtdchar.c,mtd_blkdev.c調(diào)用register_mtd_user struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list); not->add(mtd); // mtd_notify_add 和 blktrans_notify_add 先看字符設(shè)備的mtd_notify_add class_device_create class_device_create 再看塊設(shè)備的blktrans_notify_add list_for_each(this, &blktrans_majors) { // 問. blktrans_majors在哪設(shè)置 // 答. driversmtdmdblock.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 (driversmtdmdblock.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 -> Memory Technology Device (MTD) support -> NAND Device Support < > NAND Flash support for S3C2410/S3C2440 SoC 使用新內(nèi)核啟動(dòng), 并且使用NFS作為根文件系統(tǒng),因?yàn)橹案募到y(tǒng)在nand flash上面,現(xiàn)在內(nèi)核去除了nand flash的驅(qū)動(dòng),內(nèi)核就無法訪問根文件系統(tǒng)了。 flash_eraseall /dev/mtd3 //擦除后本身就格式化成 yaffs文件系統(tǒng),所以不用再格式化了 mount -t yaffs /dev/mtdblock3 /mnt flash_erase :只擦除一個(gè)扇區(qū) flash_eraseall :整個(gè)分區(qū)都擦除掉
問3. 數(shù)據(jù)線既接到NAND FLASH,也接到NOR FLASH,還接到SDRAM、DM9000等等
答3. 這些設(shè)備,要訪問之必須"選中",
問4. 假設(shè)燒寫NAND FLASH,把命令、地址、數(shù)據(jù)發(fā)給它之后,
答4. 通過狀態(tài)引腳RnB來判斷:它為高電平表示就緒,它為低電平表示正忙
問5. 怎么操作NAND FLASH呢?
答5. 根據(jù)NAND FLASH的芯片手冊(cè),一般的過程是:
發(fā)命令 選中芯片
發(fā)地址 選中芯片 NFADDR=地址值
發(fā)數(shù)據(jù) 選中芯片 NFDATA=數(shù)據(jù)值
讀數(shù)據(jù) 選中芯片 val=NFDATA
用UBOOT來體驗(yàn)NAND FLASH的操作:
1. 讀ID
選中 NFCONT的bit1設(shè)為0 md.l 0x4E000004 1; mw.l 0x4E000004 1
發(fā)出命令0x90 NFCMMD=0x90 mw.b 0x4E000008 0x90
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
讀數(shù)據(jù)得到0xEC val=NFDATA md.b 0x4E000010 1
讀數(shù)據(jù)得到device code val=NFDATA md.b 0x4E000010 1
退出讀ID的狀態(tài) NFCMMD=0xff mw.b 0x4E000008 0xff
2. 讀內(nèi)容: 讀0地址的數(shù)據(jù)
使用UBOOT命令:
nand dump 0
Page 00000000 dump:
選中 NFCONT的bit1設(shè)為0 md.l 0x4E000004 1; mw.l 0x4E000004 1
發(fā)出命令0x00 NFCMMD=0x00 mw.b 0x4E000008 0x00
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
發(fā)出命令0x30 NFCMMD=0x30 mw.b 0x4E000008 0x30
讀數(shù)據(jù)得到0x17 val=NFDATA md.b 0x4E000010 1
讀數(shù)據(jù)得到0x00 val=NFDATA md.b 0x4E000010 1
讀數(shù)據(jù)得到0x00 val=NFDATA md.b 0x4E000010 1
讀數(shù)據(jù)得到0xea val=NFDATA md.b 0x4E000010 1
退出讀狀態(tài) NFCMMD=0xff mw.b 0x4E000008 0xff
NAND FLASH驅(qū)動(dòng)程序層次
看內(nèi)核啟動(dòng)信息
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c2440-nand s3c2440-nand: Tacls=3, 30ns Twrph0=7 70ns, Twrph1=3 30ns
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
Scanning device for bad blocks
Bad eraseblock 256 at 0x02000000
Bad eraseblock 257 at 0x02020000
Bad eraseblock 319 at 0x027e0000
Bad eraseblock 606 at 0x04bc0000
Bad eraseblock 608 at 0x04c00000
Creating 4 MTD partitions on "NAND 256MiB 3,3V 8-bit":
0x00000000-0x00040000 : "bootloader"
0x00040000-0x00060000 : "params"
0x00060000-0x00260000 : "kernel"
0x00260000-0x10000000 : "root"
搜"S3C24XX NAND Driver"
S3c2410.c (driversmtdnand)
s3c2410_nand_inithw
s3c2410_nand_init_chip
nand_scan // drivers/mtd/nand/nand_base.c 根據(jù)nand_chip的底層操作函數(shù)識(shí)別NAND FLASH,構(gòu)造mtd_info
if (!chip->select_chip)
chip->select_chip = nand_select_chip; // 默認(rèn)值不適用
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
s3c2410_nand_add_partition
測(cè)試4th:
1. make menuconfig去掉內(nèi)核自帶的NAND FLASH驅(qū)動(dòng)
-> Device Drivers
2. make uImage
3. insmod s3c_nand.ko
4. 格式化 (參考下面編譯工具)
5. 掛接
6. 在/mnt目錄下建文件
編譯工具:
1. tar xjf mtd-utils-05.07.23.tar.bz2
2. cd mtd-utils-05.07.23/util
修改Makefile:
#CROSS=arm-linux-
改為
CROSS=arm-linux-
3. make
4. cp flash_erase flash_eraseall /work/nfs_root/first_fs/bin/
關(guān)鍵詞:
NANDFLASH驅(qū)動(dòng)程
相關(guān)推薦
技術(shù)專區(qū)
- FPGA
- DSP
- MCU
- 示波器
- 步進(jìn)電機(jī)
- Zigbee
- LabVIEW
- Arduino
- RFID
- NFC
- STM32
- Protel
- GPS
- MSP430
- Multisim
- 濾波器
- CAN總線
- 開關(guān)電源
- 單片機(jī)
- PCB
- USB
- ARM
- CPLD
- 連接器
- MEMS
- CMOS
- MIPS
- EMC
- EDA
- ROM
- 陀螺儀
- VHDL
- 比較器
- Verilog
- 穩(wěn)壓電源
- RAM
- AVR
- 傳感器
- 可控硅
- IGBT
- 嵌入式開發(fā)
- 逆變器
- Quartus
- RS-232
- Cyclone
- 電位器
- 電機(jī)控制
- 藍(lán)牙
- PLC
- PWM
- 汽車電子
- 轉(zhuǎn)換器
- 電源管理
- 信號(hào)放大器
評(píng)論