【驱动】第9课、NOR驱动之学习笔记

主   机:VMWare--Ubuntu-16.04.2-x64-100ask

开发板:Mini2440--256M NandFlash,   2M NorFlash,   64M SDRAM,   LCD-TD35;
    bootlorder:u-boot1.16,        Kernel:2.6.22.6;
编译器:arm-linux-gcc-3.4.5


 

【课堂笔记】

使用UBOOT体验NOR FLASH的操作(开发板设为NOR启动,进入UBOOT)
先使用OpenJTAG烧写UBOOT到NOR FLASH

1. 读数据
md.b 0

2. 读ID
NOR手册上:
往地址555H写AAH
往地址2AAH写55H
往地址555H写90H
读0地址得到厂家ID: C2H
读1地址得到设备ID: 22DAH或225BH
退出读ID状态: 给任意地址写F0H

2440的A1接到NOR的A0,所以2440发出(555h<<1), NOR才能收到555h这个地址
UBOOT怎么操作?

往地址AAAH写AAH                mw.w aaa aa
往地址554写55H                  mw.w 554 55
往地址AAAH写90H              mw.w aaa 90
读0地址得到厂家ID: C2H               md.w 0 1
读2地址得到设备ID: 22DAH或225BH      md.w 2 1
退出读ID状态:                mw.w 0 f0

3. NOR有两种规范, jedec, cfi(common flash interface)
读取CFI信息

NOR手册:
进入CFI模式 往55H写入98H
读数据: 读10H得到0051
读11H得到0052
读12H得到0059
读27H得到容量

2440的A1接到NOR的A0,所以2440发出(555h<<1), NOR才能收到555h这个地址
UBOOT怎么操作?
进入CFI模式 往AAH写入98H          mw.w aa 98
读数据: 读20H得到0051            md.w 20 1
读22H得到0052                md.w 22 1
读24H得到0059                md.w 24 1
读4EH得到容量                md.w 4e 1
退出CFI模式                  mw.w 0 f0

4. 写数据: 在地址0x100000写入0x1234
    md.w 100000 1 // 得到ffff
    mw.w 100000 1234
    md.w 100000 1 // 还是ffff

NOR手册:
往地址555H写AAH
往地址2AAH写55H
往地址555H写A0H
往地址PA写PD

2440的A1接到NOR的A0,所以2440发出(555h<<1), NOR才能收到555h这个地址
UBOOT怎么操作?
往地址AAAH写AAH       mw.w aaa aa
往地址554H写55H        mw.w 554 55
往地址AAAH写A0H        mw.w aaa a0
往地址0x100000写1234h      mw.w 100000 1234

 


NOR FLASH驱动程序框架


测试1:通过配置内核支持NOR FLASH
1. make menuconfig
-> Device Drivers
  -> Memory Technology Device (MTD) support
    -> Mapping drivers for chip access
      <M> CFI Flash device in physical memory map
      (0x0) Physical start address of flash mapping // 物理基地址
      (0x1000000) Physical length of flash mapping // 长度
      (2) Bank width in octets (NEW) // 位宽

2. make modules
  cp drivers/mtd/maps/physmap.ko /work/nfs_root/first_fs
3. 启动开发板
  ls /dev/mtd*
  insmod physmap.ko
  ls /dev/mtd*
  cat /proc/mtd

测试2: 使用自己写的驱动程序:

1. ls /dev/mtd*
2. insmod s3c_nor.ko
3. ls /dev/mtd*
4. 格式化: flash_eraseall -j /dev/mtd1
5. mount -t jffs2 /dev/mtdblock1 /mnt
在/mnt目录下操作文件


NOR FLASH识别过程:
do_map_probe("cfi_probe", s3c_nor_map);
  drv = get_mtd_chip_driver(name)
  ret = drv->probe(map); // cfi_probe.c
    cfi_probe
      mtd_do_chip_probe(map, &cfi_chip_probe);
        cfi = genprobe_ident_chips(map, cp);
          genprobe_new_chip(map, cp, &cfi)
            cp->probe_chip(map, 0, NULL, cfi)
              cfi_probe_chip
                // 进入CFI模式
                cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
                // 看是否能读出"QRY"
                qry_present(map,base,cfi)
      .....

do_map_probe("jedec_probe", s3c_nor_map);
  drv = get_mtd_chip_driver(name)
  ret = drv->probe(map); // jedec_probe
    jedec_probe
      mtd_do_chip_probe(map, &jedec_chip_probe);
        genprobe_ident_chips(map, cp);
          genprobe_new_chip(map, cp, &cfi)
            cp->probe_chip(map, 0, NULL, cfi)
              jedec_probe_chip
                // 解锁
                cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
                cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);

                // 读ID命令
                cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);

                // 得到厂家ID,设备ID
                cfi->mfr = jedec_read_mfr(map, base, cfi);
                cfi->id = jedec_read_id(map, base, cfi);

                // 和数组比较
                jedec_table


【编程】

一、搭建nor驱动框架
1. 分配map_info结构体
  s3c_nor_map = kzalloc(sizeof(struct map_info), GFP_KERNEL);; //kfree(s3c_nor_map);

2. 设置: 物理基地址(phys), 大小(size), 位宽(bankwidth), 虚拟基地址(virt)

  s3c_nor_map->name = "s3c_nor";
  s3c_nor_map->phys = 0;
  s3c_nor_map->size = 0x1000000; /* >= NOR的真正大小 */
  s3c_nor_map->bankwidth = 2;
  s3c_nor_map->virt = ioremap(s3c_nor_map->phys, s3c_nor_map->size); //iounmap(info->map.virt);
  simple_map_init(s3c_nor_map);

3. 使用: 调用NOR FLASH协议层提供的函数来识别
  s3c_nor_mtd = do_map_probe("cfi_probe", s3c_nor_map); 或者
  s3c_nor_mtd = do_map_probe("jedec_probe", s3c_nor_map); //回滚函数:map_destroy(info->mtd);

4. 注册mtd分区表
  add_mtd_partitions(s3c_nor_mtd, s3c_nor_parts, 2); //回滚函数:del_mtd_device(info->mtd);
  del_mtd_partitions(info->mtd);
【测试】
如上。

【问题】
问1:关于NOR'A0-A21对应-S3C2440'A1-A22,关于此部分地址的转换没有在硬件相关的驱动程序s3c_nor.c中出现,它会在(内核)哪里被设置呢?
答1:不知。

【源码】

 1 /*
 2  * 2019-01-16
 3  * 目的: Norflash硬件相关层驱动程序;
 4  */
 5 #include <linux/module.h>
 6 #include <linux/types.h>
 7 #include <linux/kernel.h>
 8 #include <linux/init.h>
 9 #include <linux/slab.h>
10 #include <linux/device.h>
11 #include <linux/platform_device.h>
12 #include <linux/mtd/mtd.h>
13 #include <linux/mtd/map.h>
14 #include <linux/mtd/partitions.h>
15 #include <linux/mtd/physmap.h>
16 #include <asm/io.h>
17 MODULE_LICENSE("GPL");
18 
19 static struct map_info *s3c_nor_map;
20 static struct mtd_info *s3c_nor_mtd;
21 
22 static struct mtd_partition s3c_nor_parts[] = {
23     [0] = {
24         .name   = "bootloader_nor",
25         .size   = 0x00040000,
26         .offset    = 0,
27     },
28     [1] = {
29         .name   = "root_nor",
30         .offset = MTDPART_OFS_APPEND,
31         .size   = MTDPART_SIZ_FULL,
32     }
33 };
34 
35 static int s3c_nor_init(void)
36 {
37     int err;
38     /* 1.分配一个map_info结构体 */
39     s3c_nor_map = kzalloc(sizeof(struct map_info ), GFP_KERNEL);
40     if(!s3c_nor_map)
41     {
42         printk(KERN_ERR "Failed to allocate s3c_nor_map map_info structure!\n");
43         err = -ENOMEM;
44         goto err_fail1;
45     }
46     /* 2.设置该结构体 */
47     s3c_nor_map->name = "s3c_nor";        /* 名字 */
48     s3c_nor_map->phys = 0;                /* 物理基地址 */
49     s3c_nor_map->size = 0x1000000;        /* 16M大小 */
50     s3c_nor_map->bankwidth = 2;            /* 位宽: 2x8位 */
51     s3c_nor_map->virt = ioremap(s3c_nor_map->phys, s3c_nor_map->size);    /* 虚拟基地址 */
52     if(!s3c_nor_map->virt)
53     {
54         printk(KERN_ERR "Failed to ioremap s3c_nor_map->virt regions!\n");
55         err = -ENOMEM;
56         goto err_fail2;
57     }
58     simple_map_init(s3c_nor_map);
59     /* 3.使用: 调用Norflash协议层提供的函数来识别 */
60     printk("use cfi_probe\n");
61     s3c_nor_mtd = do_map_probe("cfi_probe", s3c_nor_map);
62     if(!s3c_nor_mtd)
63     {
64         printk("use jedec_probe\n");
65         s3c_nor_mtd = do_map_probe("jedec_probe", s3c_nor_map);
66     }
67     if(!s3c_nor_mtd)
68     {
69         printk("map_probe failed!\n");
70         err = -ENXIO;
71         goto err_fail3;
72     }
73     s3c_nor_mtd->owner = THIS_MODULE;
74     /* 4.注册mtd分区表 */
75     add_mtd_partitions(s3c_nor_mtd, s3c_nor_parts, 2);
76     return 0;
77  err_fail3:
78      map_destroy(s3c_nor_mtd);
79  err_fail2:
80      iounmap(s3c_nor_map->virt);
81  err_fail1:
82      kfree(s3c_nor_map);
83      return err;
84 }
85 static void s3c_nor_exit(void)
86 {
87     del_mtd_device(s3c_nor_mtd);
88     del_mtd_partitions(s3c_nor_mtd);
89     map_destroy(s3c_nor_mtd);
90      iounmap(s3c_nor_map->virt);
91      kfree(s3c_nor_map);
92 }
93 
94 module_init(s3c_nor_init);
95 module_exit(s3c_nor_exit);

 

posted @ 2019-01-16 21:16  大秦长剑  阅读(309)  评论(0编辑  收藏  举报