1. 如何編寫linux下的 Nand flash驅動
Bare NAND chips:裸片,單獨的nand 晶元 SmartMediaCards: =裸片+一層薄塑料,常用於數碼相機和MP3播放器中。之所以稱smart,是由於其軟體smart,而不是硬體本身有啥smart之處。^_^ DiskOnChip:裸片+glue logic,glue logic=硬體ECC產生器+用於靜態的nand 晶元控制的寄存器+直接訪問一小片地址窗口,那塊地址中包含了引導代碼的stub樁,其可以從nand flash中拷貝真正的引導代碼。 Nand flash的操作,和其他一些常見的設備,如硬碟等,不同,其有自己特殊的方式。 其特殊就在於: Nand flash的最小單位是頁page,而不是其他很多設備所說的位bit。 寫入數據之前必須先進行擦除erase操作 寫的時候,最小單位是頁page,對也進行寫操作,也稱作「頁編程」,page programming 擦除的最小單位是塊block 由於物理特性,容易出錯,所以無論是讀還是寫,都要採取檢測和校驗,即EDC。 nand flash出廠時候,就有一定壞的塊block,成為換塊,並且做了一定標記。 nand flash中有個額外的空間,叫做spare area/oob!
2. linux nor flash驅動如何載入為什麼系統中沒有mtdcore.c文件
這個文件在內核源碼driver/mtd目錄下面,要考慮到你的調試內核是否有編譯mtd驅動,或者以模塊方式編譯的mtdcore而沒有載入。
你是用insmod方式載入ko並不能解決模塊依賴問題的。
3. 如何編寫Linux下Nand Flash驅動
1.硬體方面:
【Flash的種類】
Flash主要分nand flash和nor flash
除了網上最流行的這個解釋之外:
NAND和NOR的比較
我再多說幾句,nor的成本相對高,比較適合應用於存儲少量的代碼。
Nand flash相對成本低,因此可以用來存儲大量的數據,其在嵌入式系統中的作用,相當於PC上的硬碟,用於存儲大量數據。
Nor flash,有類似於dram之類的地址匯流排,因此可以直接和CPU相連,CPU可以直接通過地址匯流排對nor flash進行訪問,而nand flash沒有這類的匯流排,只有IO介面,只能通過IO介面發送命令和地址,對nand flash內部數據進行訪問。相比之下,nor flash就像是並行訪問,nand flash就是串列訪問,所以相對來說,前者的速度更快些。
2.軟體方面:
Linux驅動原理
具體內部很多實現,已經包含在drivers/mtd/nand/nand_base.c中了
【nand flash驅動載入識別nand類型過程】
在驅動載入的時候,會去調用:
nand_get_flash_type()
其中,就會對nand的類型和其他相關參數進行檢查。
1) 選中對應設備,如果此時只有一個nand 晶元,則此步可以省略
/* Select the device */
chip->select_chip(mtd, 0);
x
2) 發讀命令,去讀取設備類型代碼
/* Send the command for reading device ID */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
3) 判斷是哪個廠商的,哪個類型的flash
/* Read manufacturer and device IDs */
*maf_id = chip->read_byte(mtd);
dev_id = chip->read_byte(mtd);
4) 在事先已經定義好的nand flash類型中查找屬於何種廠商和型號
/* Lookup the flash id */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
if (dev_id == nand_flash_ids[i].id) {
type = &nand_flash_ids[i];
break;
}
}
5) 繼續判斷具體nand flash的各個參數,包括
晶元信息,Pagesize頁大小,oobsize即oob的大小,blocksize塊大小,buswidth匯流排寬度是8位還是16位。
如果頁大小不是之前老的nand的512B,而是新的nand的2K或更大,則後面對應的發送給nand flash命令的的時候,調用的函數就由nand_command()變成nand_command_lp()了。
後者主要比前者多一發個命令:
chip->cmd_ctrl(mtd, column >> 8, ctrl);
即,多發一個列地址命令。
因為大頁面(>2KB)的定址需要2次column,而小頁面(512B)只需要1次的列地址。
具體可以參考nand flash的datasheet。
6) 接著會做一些其他初始化操作,包括最後調用nand_set_defaults()去實現的默認函數的掛載,如果你的nand flash驅動沒有實現的話,就是掛載默認的了。
【模塊載入原理】
這個內容太大,此處只是簡單說說。
驅動載入的功能主要是probe函數實現的,主要去識別設備的類型和各個參數,並且為設備的使用進行正常的初始化。
對應卸載時候執行的remove函數,施放對應的,之前申請的一些資源。
【MTD設備】
在Linux下,將nand Flash等設備歸屬到MTD設備下進行統一管理。
Mtd,即memory technology deveice,即將nand看出是存儲設備來管理。
之所以會這么說和這么做,是因為前面提高的nand flash和普通硬碟等設備的特殊性:
IO介面,最小單位是頁,寫前需擦除等,導致了,不能像平常對待硬碟等操作一樣去操作nand flash,只能採取一些特殊方法,這就誕生了mtd設備的統一抽象層,將nand flash,nor flash和其他類型的flash等設備,統一抽象成mtd設備來管理,根據這些設備的特點,上層實現了常見的操作函數封裝,底層具體的內部實現,就需要驅動設計者自己來實現了。
4. 如何編寫linux下nand flash驅動
Linux驅動原理
具體內部很多實現,已經包含在drivers/mtd/nand/nand_base.c中了
【nand flash驅動載入識別nand類型過程】
在驅動載入的時候,會去調用:
nand_get_flash_type()
其中,就會對nand的類型和其他相關參數進行檢查。
1) 選中對應設備,如果此時只有一個nand 晶元,則此步可以省略
/* Select the device */
chip->select_chip(mtd, 0);
x
2) 發讀命令,去讀取設備類型代碼
/* Send the command for reading device ID */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
3) 判斷是哪個廠商的,哪個類型的flash
/* Read manufacturer and device IDs */
*maf_id = chip->read_byte(mtd);
dev_id = chip->read_byte(mtd);
4) 在事先已經定義好的nand flash類型中查找屬於何種廠商和型號
/* Lookup the flash id */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
if (dev_id == nand_flash_ids[i].id) {
type = &nand_flash_ids[i];
break;
}
}
5) 繼續判斷具體nand flash的各個參數,包括
晶元信息,Pagesize頁大小,oobsize即oob的大小,blocksize塊大小,buswidth匯流排寬度是8位還是16位。
如果頁大小不是之前老的nand的512B,而是新的nand的2K或更大,則後面對應的發送給nand flash命令的的時候,調用的函數就由nand_command()變成nand_command_lp()了。
後者主要比前者多一發個命令:
chip->cmd_ctrl(mtd, column >> 8, ctrl);
即,多發一個列地址命令。
因為大頁面(>2KB)的定址需要2次column,而小頁面(512B)只需要1次的列地址。
具體可以參考nand flash的datasheet。
6) 接著會做一些其他初始化操作,包括最後調用nand_set_defaults()去實現的默認函數的掛載,如果你的nand flash驅動沒有實現的話,就是掛載默認的了。
【模塊載入原理】
這個內容太大,此處只是簡單說說。
驅動載入的功能主要是probe函數實現的,主要去識別設備的類型和各個參數,並且為設備的使用進行正常的初始化。
對應卸載時候執行的remove函數,施放對應的,之前申請的一些資源。
【MTD設備】
在Linux下,將nand Flash等設備歸屬到MTD設備下進行統一管理。
Mtd,即memory technology deveice,即將nand看出是存儲設備來管理。
之所以會這么說和這么做,是因為前面提高的nand flash和普通硬碟等設備的特殊性:
IO介面,最小單位是頁,寫前需擦除等,導致了,不能像平常對待硬碟等操作一樣去操作nand flash,只能採取一些特殊方法,這就誕生了mtd設備的統一抽象層,將nand flash,nor flash和其他類型的flash等設備,統一抽象成mtd設備來管理,根據這些設備的特點,上層實現了常見的操作函數封裝,底層具體的內部實現,就需要驅動設計者自己來實現了。
1. 了解硬體的nand flash的各個參數和工作原理
具體參考nand flash的datasheet,主要包括,自己nand flash的廠商,型號等。
Nand flash的頁大小,oob大小,塊大小,位寬8bit還是16bit。
工作原理,上面已經做了一定描述,不清楚的,可以參考datasheet,多看看,就會明白很多。
2. 按照linux下驅動編寫規范編寫nand flash驅動,
可以參考其他已經有的驅動,比如內核源碼中已經有的
drivers/mtd/nand/s3c2410.c
就是個很好的例子。
自己以其為模板,實現自己板子的nand flash驅動。
其實主要工作就是,實現
static struct platform_driver s3c2410_nand_driver = {
.probe = s3c2410_nand_probe,
.remove = s3c2410_nand_remove,
.suspend = s3c24xx_nand_suspend,
.resume = s3c24xx_nand_resume,
.driver = {
.name = "s3c2410-nand",
.owner = THIS_MODULE,
},
};
中的
XXX_nand_probe函數
XXX_nand_remove函數
XXX_nand_enable_hwecc,如果支持硬體ecc的話。
對nand flash的讀寫,這兩個函數,實現了對nand的具體操作。
【Linux下Nand Flash驅動編寫簡單步驟】
軟體和硬體知識,都已經了解的話,由於上層的linux的 mtd框架中,已經完全封裝好了,對nand flash的write page,write oob等相關函數的實現,那麼剩下的只是相對來說已經是很少量的,關於nand 驅動具體內部操作方面的工作:
1.初始化
先是在nand 晶元初始化的時候,對其
XXX_nand_init_chip()
給對應的晶元chip賦給對應的
XXX_nand_read_buf和XXX_nand_write_buf等函數:
chip->cmd_ctrl = XXX_nand_hwcontrol;
chip->dev_ready = XXX_nand_devready;
chip->read_buf = XXX_nand_read_buf;
chip->write_buf = XXX_nand_write_buf;
以實現後續的對nand晶元的操作。
然後根據ecc類型,賦給對應的ecc的校驗與糾錯函數:
chip->ecc.hwctl = XXX_nand_enable_hwecc;
chip->ecc.calculate = XXX _nand_calculate_ecc;
3. 實現上面提到的對應的各個函數,關於如何實現,參考一下其他nand驅動,就會理解很多了。
4. 驅動測試,參考具體的 ldd3(Linux Device Driver version 3)的測試相關部分內容。
轉載僅供參考,版權屬於原作者。祝你愉快,滿意請採納哦
5. 求問linux nor flash驅動編程過程中add_mtd_partitions和del_mtd_partitions怎麼用
add_mtd_partitions函數,add_mtd_partitions()會對每一個新建分區建立一個新的mtd_part 結構體,將其加入mtd_
partitions中,並調用add_mtd_device()將此分區作為MTD設備加入mtd_table。成功時返回0,如果分配mtd_part時內存不足,則返回-ENOMEM。
1、在說這個函數前,先說下,與這有關的結構體struct mtd_part和struct
mtd_partition結構體,如下所示:
mtd_part結構體用於描述分區,其mtd_info結構體成員用於描述本分區
/* Our partition node structure */
struct
mtd_part {
struct mtd_info mtd;
分區的信息(大部分由其master決定
struct mtd_info
*master; 該分區的主分區
u_int32_t offset;
該分區的偏移地址
int index; 分區號
struct list_head list;
int registered;
};
struct mtd_partition {
char *name; /* identifier string */ 標識字元串
u_int32_t size;/* partition size */ 分區大小
u_int32_t offset;/* offset within the master MTD
space */ 主MTD空間內的偏移
u_int32_t
mask_flags;/* master MTD flags to mask out
for this partition */
struct
nand_ecclayout *ecclayout;/* out of band
layout for this partition (NAND only)*/
struct mtd_info **mtdp;/* pointer to store the MTD object
*/
};
為了更明白我們以6410中的定義:
struct mtd_partition s3c_partition_info[] =
{
{
.name =
"Bootloader",
.offset =
0,
.size =
(256*SZ_1K),
.mask_flags = MTD_CAP_NANDFLASH,
},
{
.name = "Kernel",
.offset = (256*SZ_1K),
.size = (4*SZ_1M) - (256*SZ_1K),
.mask_flags =
MTD_CAP_NANDFLASH,
},
#if
defined(CONFIG_SPLIT_ROOT_FILESYSTEM)
{
.name = "Rootfs",
.offset = (4*SZ_1M),
//
.size = (512*SZ_1M),//(48*SZ_1M),
.size =
(80*SZ_1M),//(48*SZ_1M),
},
#endif
{
.name = "File System",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
}
};
struct s3c_nand_mtd_info s3c_nand_mtd_part_info = {
.chip_nr = 1,
.mtd_part_nr =
ARRAY_SIZE(s3c_partition_info),
.partition
= s3c_partition_info,
};
2、下面來看add_mtd_partitions函數,源碼如下:
/*
* This function, given a master MTD object and a
partition table, creates
* and registers slave MTD objects which are bound
to the master according to
* the partition definitions.
* (Q:
should we register the master MTD object as well?)
*/
int
add_mtd_partitions(struct mtd_info *master,
const struct
mtd_partition *parts,
int
nbparts)
{
struct mtd_part
*slave;
u_int32_t cur_offset = 0;
int i;
printk(KERN_NOTICE "Creating
%d MTD partitions on \"%s\":\n", nbparts, master->name);
for (i = 0; i
< nbparts; i++) { 主要就是這個循環體,應該是分別添加每個struct
mtd_partition結構
slave =
add_one_partition(master, parts + i, i, cur_offset);
if (!slave)
return -ENOMEM;
cur_offset = slave->offset
+ slave->mtd.size;
}
return
0;
}
6. 如何編寫Linux下Nand Flash驅動
摘錄的別人心得
【Linux下nand flash驅動編寫步驟簡介】
1. 了解硬體的nand
flash的各個參數和工作原理
具體參考nand flash的datasheet,主要包括,自己nand
flash的廠商,型號等。
Nand flash的頁大小,oob大小,塊大小,位寬8bit還是16bit。
工作原理,上面已經做了一定描述,不清楚的,可以參考datasheet,多看看,就會明白很多。
2. 按照linux下驅動編寫規范編寫nand
flash驅動,
可以參考其他已經有的驅動,比如內核源碼中已經有的
drivers/mtd/nand/s3c2410.c
就是個很好的例子。
自己以其為模板,實現自己板子的nand flash驅動。
其實主要工作就是,實現
static struct platform_driver s3c2410_nand_driver =
{
.probe =
s3c2410_nand_probe,
.remove =
s3c2410_nand_remove,
.suspend =
s3c24xx_nand_suspend,
.resume =
s3c24xx_nand_resume,
.driver = {
.name =
"s3c2410-nand",
.owner =
THIS_MODULE,
},
};
中的
XXX_nand_probe函數
XXX_nand_remove函數
XXX_nand_enable_hwecc,如果支持硬體ecc的話。
對nand flash的讀寫,這兩個函數,實現了對nand的具體操作。
【Linux下Nand Flash驅動編寫簡單步驟】
軟體和硬體知識,都已經了解的話,由於上層的linux的 mtd框架中,已經完全封裝好了,對nand
flash的write page,write oob等相關函數的實現,那麼剩下的只是相對來說已經是很少量的,關於nand
驅動具體內部操作方面的工作:
初始化
先是在nand 晶元初始化的時候,對其
XXX_nand_init_chip()
給對應的晶元chip賦給對應的
XXX_nand_read_buf和XXX_nand_write_buf等函數:
chip->cmd_ctrl =
XXX_nand_hwcontrol;
chip->dev_ready =
XXX_nand_devready;
chip->read_buf =
XXX_nand_read_buf;
chip->write_buf =
XXX_nand_write_buf;
以實現後續的對nand晶元的操作。
然後根據ecc類型,賦給對應的ecc的校驗與糾錯函數:
chip->ecc.hwctl =
XXX_nand_enable_hwecc;
chip->ecc.calculate = XXX
_nand_calculate_ecc;
3. 實現上面提到的對應的各個函數,關於如何實現,參考一下其他nand驅動,就會理解很多了。
4. 驅動測試,參考具體的 ldd3(Linux
Device Driver version 3)的測試相關部分內容。