为什么要把cpu的地址ADDR1连接到nor的A0上面
cpu读取时认为一个地址对应一个字节,而nor flash一个地址对应两字节,如果直连的话就会存在一个问题,cpu读0,nor返回0地址两字节的低字节,cpu读1时,nor返回1地址两字节的低字节,这样显然是有问题的
但是按照原理图就没有问题了
cpu读0,nor返回0地址两字节的低字节,cpu读1时,nor返回0地址两字节的高字节,因为00,01,addr1都是0,同样10,11都对应nor的1地址,因为addr0不接,怎么变都无所谓这样就相当于cpu连续两个地址对应nor的一个地址。
由于这样的特性,cpu如果发出地址0xa0,10100000,addr0没有接,对应nor flash地址1010000,hex:0x50.
nor有两种规范jedec,cfi
通用的
1.进入cfi模式
2.查找进入cfi模式后的后续操作
读取厂家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,注意这里是两个字节为一个device id,高位在高地址
进入cfi模式
1.55写入98 mw.w aa 0x98
2.读取10
程序源码do_map_probe函数是识别nor flash的函数,厂家id,设备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结构体,设置
*/
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结构体
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");