為什么要把cpu的地址ADDR1連接到nor的A0上面
cpu讀取時認(rèn)為一個地址對應(yīng)一個字節(jié),而nor flash一個地址對應(yīng)兩字節(jié)雁社,如果直連的話就會存在一個問題置济,cpu讀0,nor返回0地址兩字節(jié)的低字節(jié)谆扎,cpu讀1時挂捅,nor返回1地址兩字節(jié)的低字節(jié),這樣顯然是有問題的
但是按照原理圖就沒有問題了
cpu讀0燕酷,nor返回0地址兩字節(jié)的低字節(jié)籍凝,cpu讀1時,nor返回0地址兩字節(jié)的高字節(jié)苗缩,因為00饵蒂,01,addr1都是0酱讶,同樣10退盯,11都對應(yīng)nor的1地址,因為addr0不接泻肯,怎么變都無所謂這樣就相當(dāng)于cpu連續(xù)兩個地址對應(yīng)nor的一個地址渊迁。
?由于這樣的特性,cpu如果發(fā)出地址0xa0灶挟,10100000琉朽,addr0沒有接,對應(yīng)nor flash地址1010000稚铣,hex:0x50.
nor有兩種規(guī)范jedec箱叁,cfi
通用的
1.進(jìn)入cfi模式
2.查找進(jìn)入cfi模式后的后續(xù)操作
讀取廠家ID
1.555寫入aa mw.w 0xaaa 0xaa
2.2aa寫入55 mw.w 0x554 0x55
3.555寫入90 mw.w 0xaaa 0x90
4.讀取x00得到0xc2.廠家id,注意這里是兩個字節(jié)為一個device id,高位在高地址
進(jìn)入cfi模式
1.55寫入98 mw.w aa 0x98
2.讀取10
程序源碼do_map_probe函數(shù)是識別nor flash的函數(shù)惕医,廠家id耕漱,設(shè)備id,容量等信息
/*
* 參考 drivers\mtd\maps\physmap.c
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
static struct mtd_info *nor_mtd = NULL;
static struct map_info *my_map_info = NULL;
static struct mtd_partition my_partions[] = {
[0] = {
.name = "bootloader",
.size = 0x80000,
.offset = 0,
},
[1] = {
.name = "root",
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND,
},
};
static int s3c_nor_init(void)
{
int err = 0;
/*
1.分配一個map_info結(jié)構(gòu)體抬伺,設(shè)置
*/
my_map_info = kzalloc(sizeof(struct map_info), GFP_KERNEL);
if (!my_map_info) {
printk("error alloc my_map_info\n");
return -ENOMEM;
}
my_map_info->name = "my_nor";
my_map_info->phys = 0x0;
my_map_info->size = 0x100000;
my_map_info->bankwidth = 2;
//映射地址空間螟够,大小需要比nor flash大一點
my_map_info->virt = ioremap(my_map_info->phys,my_map_info->size);
if (!(my_map_info->virt)) {
printk("Error ioremap\n");
iounmap(my_map_info->virt);
return -ENOMEM;
}
simple_map_init(my_map_info);
//分配一個mtd_info結(jié)構(gòu)體
nor_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
if (!nor_mtd) {
printk("error alloc nor_mtd\n");
iounmap(my_map_info->virt);
return -ENOMEM;
}
nor_mtd = do_map_probe("cfi_probe", my_map_info);
if (!nor_mtd) {
printk("error do_map_probe\n");
iounmap(my_map_info->virt);
kfree(my_map_info);
kfree(nor_mtd);
return -ENOMEM;
}
err = add_mtd_partitions(nor_mtd, my_partions, 2);
if (err) {
printk("func:%s, line:%d\n",
__func__, __LINE__);
return -1;
}
return 0;
}
static void s3c_nor_exit(void)
{
int err = 0;
iounmap(my_map_info->virt);
kfree(my_map_info);
kfree(nor_mtd);
err = del_mtd_partitions(nor_mtd);
if (!err) {
printk("func:%s, line:%d, del mtd failed!\n",
__func__, __LINE__);
}
}
module_init(s3c_nor_init);
module_exit(s3c_nor_exit);
MODULE_LICENSE("GPL");