nor flash驱动框架 分析
右下角放大
协议层已经做好,需要配置的是硬件相关的设置,基地址和位宽。
字符设备就找字符设备驱动程序,
普通文件就找文件系统 找到块设备驱动,文件系统把对文件的读写转换成对块设备的读写。RAMblock,硬盘,MTD(nand(jedec cfi) nor)。
nor 和 nand 的差异最小到基地址和位宽,所以可以通过配置使得通用,在drivers\mtd\maps\physmap.c
中,
入口函数
注册平台驱动 平台设备 设置了
static int __init physmap_init(void)
{
err = platform_driver_register(&physmap_flash_driver);
platform_device_register(&physmap_flash);
}
平台设备中有resource ,
.resource = &physmap_flash_resource,
resource包括了,
static struct resource physmap_flash_resource = {
.start = CONFIG_MTD_PHYSMAP_START, // 起始地址 长度
.end = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1,
.flags = IORESOURCE_MEM,
};
设置位宽
static struct physmap_flash_data physmap_flash_data = {
.width = CONFIG_MTD_PHYSMAP_BANKWIDTH,
};
平台设备驱动 platform_driver_register 找probe physmap_flash_probe
static int physmap_flash_probe(struct platform_device *dev)
{
info->map.name = dev->dev.bus_id; // 设置map_info结构体
info->map.phys = dev->resource->start; // 物理地址 起始地址 长度
info->map.size = dev->resource->end - dev->resource->start + 1;
info->map.bankwidth = physmap_data->width; // 位宽
info->map.set_vpp = physmap_data->set_vpp;
info->map.virt = ioremap(info->map.phys, info->map.size); // 物理地址映射
// 由MTD的协议层提供
info->mtd = do_map_probe(*probe_type, &info->map); // 返回mtd_info结构体
add_mtd_partitions(info->mtd, physmap_data->parts, // 添加分区
physmap_data->nr_parts);
}
// 参数一 name 根据nor的规范才能获取nor的属性 大小等
// static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
struct mtd_info *do_map_probe(const char *name, struct map_info *map)
最后分析出我们配置硬件相关需要做:
- 分配map_info结构体
- 设置 物理基地址(phys)、大小(size)、位宽(bankwidth) 虚拟基地址(virt)等。
内核看到的不同开发板最小的差别就是这些了 - 使用 调用nor flash的协议层函数来识别
- 添加分区,不是必须。add_mtd_partitions
配置内核支持nor flash
内核已经做好,自己配置内核生成.ko模块测试就行,
make menuconfig
物理起始地址改为0,
长度16M 0x1000000,长度需要大于nor的真实长度,因为需要ioremap,
位宽 2字节make modules
生成了模块
拷贝过去,
- 启动开发板,插入模块
insmod physmap.ko
这里没有分区,整个nor就是一个分区,大小2M,擦除大小64k