NORFlash协议层

1、CFI mode:
①、注册 cfi_chipdrv :

static int __init cfi_probe_init(void)
{
    register_mtd_chip_driver(&cfi_chipdrv);
    return 0;
}
/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

在cfi_probe_init函数中调用register_mtd_chip_driver函数,将cfi_chipdrv 添加到chip_drvs_list中去:

void register_mtd_chip_driver(struct mtd_chip_driver *drv)
{
    spin_lock(&chip_drvs_lock);
    list_add(&drv->list, &chip_drvs_list);
    spin_unlock(&chip_drvs_lock);
}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

其中,cfi_chipdrv 结构体变量定义如下:

static struct mtd_chip_driver cfi_chipdrv = {
    .probe      = cfi_probe,
    .name       = "cfi_probe",
    .module     = THIS_MODULE
};
/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

②、do_map_probe执行过程:
在do_map_probe函数中调用get_mtd_chip_driver函数 :

struct mtd_info *do_map_probe(const char *name, struct map_info *map)
{
    struct mtd_chip_driver *drv;
    struct mtd_info *ret;

    drv = get_mtd_chip_driver(name);

    ...

}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

依次列举chip_drvs_list中的mtd_chip_driver 项,将每一项的成员name和传入参数name做比较,返回name相同的mtd_chip_driver 项,返回值ret = &cfi_chipdrv给do_map_probe函数中的drv:

static struct mtd_chip_driver *get_mtd_chip_driver (const char *name)
{
    struct list_head *pos;
    struct mtd_chip_driver *ret = NULL, *this;

    spin_lock(&chip_drvs_lock);

    list_for_each(pos, &chip_drvs_list) {
        this = list_entry(pos, typeof(*this), list);

        if (!strcmp(this->name, name)) {
            ret = this;
            break;
        }
    }
    if (ret && !try_module_get(ret->module))
        ret = NULL;

    spin_unlock(&chip_drvs_lock);

    return ret; //ret = &cfi_chipdrv
}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

再由mtd_chip_driver返回do_map_probe执行drv->probe(map):

struct mtd_info *do_map_probe(const char *name, struct map_info *map)
{
    struct mtd_chip_driver *drv;
    struct mtd_info *ret;

    ...

    ret = drv->probe(map); //drv = &cfi_chipdrv

    ...

    return ret;
}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

由于drv = &cfi_chipdrv,执行执行drv->probe即相当于执行cfi_chipdrv.probe = cfi_probe:

struct mtd_info *cfi_probe(struct map_info *map)
{
    /*
     * Just use the generic probe stuff to call our CFI-specific
     * chip_probe routine in all the possible permutations, etc.
     */
    return mtd_do_chip_probe(map, &cfi_chip_probe);
}
/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

其中,cfi_chip_probe如下定义:

static struct chip_probe cfi_chip_probe = {
    .name       = "CFI",
    .probe_chip = cfi_probe_chip
};
/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

cfi_probe ->mtd_do_chip_probe:

struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
{
    struct mtd_info *mtd = NULL;
    struct cfi_private *cfi;

    /* First probe the map to see if we have CFI stuff there. */
    cfi = genprobe_ident_chips(map, cp); //cp = &cfi_chip_probe 

    ...

}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

mtd_do_chip_probe->genprobe_ident_chips:

static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)
{
    struct cfi_private cfi;
    struct cfi_private *retcfi;
    unsigned long *chip_map;
    int i, j, mapsize;
    int max_chips;

    memset(&cfi, 0, sizeof(cfi));

    /* Call the probetype-specific code with all permutations of
       interleave and device type, etc. */
    if (!genprobe_new_chip(map, cp, &cfi)) {
        /* The probe didn't like it */
        pr_debug("%s: Found no %s device at location zero\n",
             cp->name, map->name);
        return NULL;
    }

    ...

}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

genprobe_ident_chips->genprobe_new_chip执行cp->probe_chip:

static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
                 struct cfi_private *cfi)
{
    int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */
    int max_chips = map_bankwidth(map); /* And minimum 1 */
    int nr_chips, type;

    for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) {

        ...

        for (; type <= CFI_DEVICETYPE_X32; type<<=1) {

            ...

            if (cp->probe_chip(map, 0, NULL, cfi))
                return 1;
        }
    }
    return 0;
}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

由于cp = &cfi_chip_probe 所以执行执行cp->probe_chip相当于执行cfi_chip_probe.probe_chip = cfi_probe_chip。
2、JEDEC mode:
①、注册jedec_chipdrv :

static int __init jedec_probe_init(void)
{
    register_mtd_chip_driver(&jedec_chipdrv);
    return 0;
}

在jedec_probe_init函数中调用register_mtd_chip_driver函数,将jedec_chipdrv 添加到chip_drvs_list中去:

void register_mtd_chip_driver(struct mtd_chip_driver *drv)
{
    spin_lock(&chip_drvs_lock);
    list_add(&drv->list, &chip_drvs_list);
    spin_unlock(&chip_drvs_lock);
}

其中,jedec_chipdrv 定义如下:

static struct mtd_chip_driver jedec_chipdrv = {
    .probe  = jedec_probe,
    .name   = "jedec_probe",
    .module = THIS_MODULE
};

②、do_map_probe执行过程:
在do_map_probe函数中调用get_mtd_chip_driver函数 :

struct mtd_info *do_map_probe(const char *name, struct map_info *map)
{
    struct mtd_chip_driver *drv;
    struct mtd_info *ret;

    drv = get_mtd_chip_driver(name);

    ...

}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

依次列举chip_drvs_list中的mtd_chip_driver 项,将每一项的成员name和传入参数name做比较,返回name相同的mtd_chip_driver 项,返回值ret = &jedec_chipdrv 给do_map_probe函数中的drv:

static struct mtd_chip_driver *get_mtd_chip_driver (const char *name)
{
    struct list_head *pos;
    struct mtd_chip_driver *ret = NULL, *this;

    spin_lock(&chip_drvs_lock);

    list_for_each(pos, &chip_drvs_list) {
        this = list_entry(pos, typeof(*this), list);

        if (!strcmp(this->name, name)) {
            ret = this;
            break;
        }
    }
    if (ret && !try_module_get(ret->module))
        ret = NULL;

    spin_unlock(&chip_drvs_lock);

    return ret; //ret = &jedec_chipdrv 
}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

再由mtd_chip_driver返回do_map_probe执行drv->probe(map):

struct mtd_info *do_map_probe(const char *name, struct map_info *map)
{
    struct mtd_chip_driver *drv;
    struct mtd_info *ret;

    ...

    ret = drv->probe(map); //drv = &jedec_chipdrv 

    ...

    return ret;
}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

由于drv = &jedec_chipdrv ,执行执行drv->probe即相当于执行jedec_chipdrv .probe = jedec_probe:

static struct mtd_info *jedec_probe(struct map_info *map)
{
    /*
     * Just use the generic probe stuff to call our CFI-specific
     * chip_probe routine in all the possible permutations, etc.
     */
    return mtd_do_chip_probe(map, &jedec_chip_probe);
}
/* linux-3.4.2\drivers\mtd\chips\jedec_probe.c */

其中,jedec_chip_probe 定义如下:

static struct chip_probe jedec_chip_probe = {
    .name = "JEDEC",
    .probe_chip = jedec_probe_chip
};
/* linux-3.4.2\drivers\mtd\chips\jedec_probe.c */

jedec_probe->mtd_do_chip_probe:

struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
{
    struct mtd_info *mtd = NULL;
    struct cfi_private *cfi;

    /* First probe the map to see if we have CFI stuff there. */
    cfi = genprobe_ident_chips(map, cp); //cp = &cfi_chip_probe 

    ...

}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

mtd_do_chip_probe->genprobe_ident_chips:

static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)
{
    struct cfi_private cfi;
    struct cfi_private *retcfi;
    unsigned long *chip_map;
    int i, j, mapsize;
    int max_chips;

    memset(&cfi, 0, sizeof(cfi));

    /* Call the probetype-specific code with all permutations of
       interleave and device type, etc. */
    if (!genprobe_new_chip(map, cp, &cfi)) {
        /* The probe didn't like it */
        pr_debug("%s: Found no %s device at location zero\n",
             cp->name, map->name);
        return NULL;
    }

    ...

}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

genprobe_ident_chips->genprobe_new_chip执行cp->probe_chip:

static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
                 struct cfi_private *cfi)
{
    int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */
    int max_chips = map_bankwidth(map); /* And minimum 1 */
    int nr_chips, type;

    for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) {

        ...

        for (; type <= CFI_DEVICETYPE_X32; type<<=1) {

            ...

            if (cp->probe_chip(map, 0, NULL, cfi))
                return 1;
        }
    }
    return 0;
}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

由于cp = &jedec_chip_probe,所以执行执行cp->probe_chip相当于执行jedec_chip_probe.probe_chip =jedec_probe_chip 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Nor Flash代码是一种非易失性存储器的编程语言。Nor Flash是一种常见的闪存技术,用于存储固件、操作系统和其他固化数据。Nor Flash代码使用类似于C语言的语法,它可以用来编写存储在Nor Flash芯片中的程序和数据。以下是一个简单的Nor Flash代码示例: ```c #include <flash.h> // 定义存储位置和大小 #define FIRMWARE_START_ADDRESS 0x100000 #define FIRMWARE_SIZE 0x8000 // 定义固件数据 const uint8_t firmware_data[FIRMWARE_SIZE] = { 0x00, 0x01, 0x02, 0x03, // 在这里添加实际的固件数据 }; // 主程序入口 int main() { // 初始化Nor Flash硬件 flash_init(); // 擦除存储区域 flash_erase(FIRMWARE_START_ADDRESS, FIRMWARE_SIZE); // 写入固件数据 flash_write(FIRMWARE_START_ADDRESS, firmware_data, FIRMWARE_SIZE); // 退出程序 return 0; } ``` 以上是一个简单的Nor Flash代码示例,它首先包含了flash头文件,然后定义了固件在Nor Flash中的存储位置和大小。接着,定义了固件数据的数组,这里只是一个简单的示例,实际情况下应该包含实际的固件数据。然后,在主程序入口函数中,通过flash_init()函数初始化Nor Flash硬件,然后使用flash_erase()函数擦除存储区域,最后使用flash_write()函数写入固件数据。最后,返回0表示程序正常退出。 这只是一个简单的示例,实际应用中可能涉及更复杂的代码和功能。Nor Flash代码可以根据具体需求进行编写和调整,以实现相应的应用功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值