文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>VIVI中MTD驱动的实现(1)

VIVI中MTD驱动的实现(1)

时间:2010-05-17  来源:charming2440

在vivi中使用的flash有nor和nand,而mtd的作用就是提供一个中间层的驱动,实现接口函数的统一管理,这里首先介绍nand flash在mtd中的实现。

在vivi bootloader中,第6步的时候就是实现mtd中间驱动的实现,MTD驱动的函数调用关系如下:

mtd_dev_init()---->mtd_init()---->smc_init()在这里需要说明,mtd_init()函数可以按照配置调用不同的函数,包括cfi_init(),smc_init(),amd_init(),这里不同的函数对应不同的flash设备的初始化。

其中cfi_init()是intel发起的nor flash的接口标准。

    smc_init()是smc只能卡接口,我们使用的nand flash使用的就是这个接口

    amd_init()是AMD flash接口


在完成上面初始化以后则是增加flash命令,这部分于后面的增加命令相似(有待研究)

              ---->add_command(&flash_command)


下面来具体看看函数的实现,首先我们要注意到的是两个数据结构,分别是mtd_info(mtd_info是表示MTD设备的结构,每个分区也被表示为一个mtd_info,如果有两个MTD设备,每个设备有三个分区,那么在系统中就一共有6个mtd_info结构),一下是vivi中mtd_info结构

struct mtd_info {
    u_char type;
    u_int32_t flags;
    u_int32_t size;  // Total size of the MTD

    /* "Major" erase size for the device. Naïve users may take this
     * to be the only erase size available, or may use the more detailed
     * information below if they desire
     */
    u_int32_t erasesize;

    u_int32_t oobblock;  // Size of OOB blocks (e.g. 512)
    u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
    u_int32_t ecctype;
    u_int32_t eccsize;

    // Kernel-only stuff starts here.
    char *name;
    int index;

    /* Data for variable erase regions. If numeraseregions is zero,
     * it means that the whole device has erasesize as given above.
     */
    int numeraseregions;
    struct mtd_erase_region_info *eraseregions;

    /* This really shouldn't be here. It can go away in 2.5 */
    u_int32_t bank_size;

    struct module *module;
    int (*erase) (struct mtd_info *mtd, struct erase_info *instr);

    /* This stuff for eXecute-In-Place */
    int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);

    /* We probably shouldn't allow XIP if the unpoint isn't a NULL */
    void (*unpoint) (struct mtd_info *mtd, u_char * addr);
    int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
    int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);

    int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf);
    int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf);

    int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
    int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);

    /*
     * Methods to access the protection register area, present in some
     * flash devices. The user data is one time programmable but the
     * factory data is read only.
     */
    int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);

    int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);

    /* This function is not yet implemented */
    int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);


    /* Chip-supported device locking */
    int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
    int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);

    void *priv;
};
还有一个重要的结构nand_chip,这个结构中包含了nand flash所有的信息

/*
 * NAND Private Flash Chip Data
 *
 * Structure overview:
 *
 *  IO_ADDR_R - address to read the 8 I/O lines of the flash device
 *
 *  IO_ADDR_W - address to write the 8 I/O lines of the flash device
 *
 *  hwcontrol - hardwarespecific function for accesing control-lines
 *
 *  dev_ready - hardwarespecific function for accesing device ready/busy line
 *
 *  chip_lock - spinlock used to protect access to this structure
 *
 *  wq - wait queue to sleep on if a NAND operation is in progress
 *
 *  state - give the current state of the NAND device
 *
 *  page_shift - number of address bits in a page (column address bits)
 *
 *  data_buf - data buffer passed to/from MTD user modules
 *
 *  data_cache - data cache for redundant page access and shadow for
 *       ECC failure
 *
 *  ecc_code_buf - used only for holding calculated or read ECCs for
 *                 a page read or written when ECC is in use
 *
 *  reserved - padding to make structure fall on word boundary if
 *             when ECC is in use
 */
struct nand_chip {
#ifdef CONFIG_MTD_NANDY
    void (*hwcontrol)(int cmd);
    void (*write_cmd)(u_char val);
    void (*write_addr)(u_char val);
    u_char (*read_data)(void);
    void (*write_data)(u_char val);
    void (*wait_for_ready)(void);
    /*spinlock_t chip_lock;*/
    /*wait_queue_head_t wq;*/
    /*nand_state_t state;*/
    int page_shift;
    u_char *data_buf;
    u_char *data_cache;
    int cache_page;
    struct nand_smc_dev *dev;
    u_char spare[SMC_OOB_SIZE];
#else   /* CONFIG_MTD_NANDY */
    unsigned long IO_ADDR_R;
    unsigned long IO_ADDR_W;
    void (*hwcontrol)(int cmd);
    int (*dev_ready)(void);
    int chip_delay;
    /*spinlock_t chip_lock;*/
    /*wait_queue_head_t wq;*/
    /*nand_state_t state;*/
    int page_shift;
    u_char *data_buf;
    u_char *data_cache;
    int cache_page;
#ifdef CONFIG_MTD_NAND_ECC
    u_char ecc_code_buf[6];
    u_char reserved[2];
#endif
#endif  /* CONFIG_MTD_NANDY */
};


/*
 * NAND Flash Device ID Structure
 *
 * Structure overview:
 *
 *  name - Complete name of device
 *
 *  manufacture_id - manufacturer ID code of device.
 *
 *  model_id - model ID code of device.
 *
 *  chipshift - total number of address bits for the device which
 *              is used to calculate address offsets and the total
 *              number of bytes the device is capable of.
 *
 *  page256 - denotes if flash device has 256 byte pages or not.
 *
 *  pageadrlen - number of bytes minus one needed to hold the
 *               complete address into the flash array. Keep in
 *               mind that when a read or write is done to a
 *               specific address, the address is input serially
 *               8 bits at a time. This structure member is used
 *               by the read/write routines as a loop index for
 *               shifting the address out 8 bits at a time.
 *
 *  erasesize - size of an erase block in the flash device.
 */
struct nand_flash_dev {
    char * name;
    int manufacture_id;
    int model_id;
    int chipshift;
    char page256;
    char pageadrlen;
    unsigned long erasesize;
};

首先看看上面三个结构,了解结构中包含的信息

在回来继续分析smc_init()函数,首先函数需要申请一个地址空间用来存放struct mtd_info和struct nand_chip,返回地址给mymtd

mymtd = mmalloc(sizeof(struct mtd_info) + sizeof(struct  nand_chip));

定一个nand_chip结构的变量this; struct nand_chip *this

this = (struct nand_chip *)(&mymtd[1])这个地方有必要解释一下:

其中,mymtd是指向struct mtd_info的指针,那么mymtd[1]实际上是等效于*(mymtd + 1)的数学计算模式,注意mymtd并非数组,这里仅仅利用了编译器翻译的特点。对于指针而言,加1实际上增加的指针对应类型的值,在这里地址实际上增加了sizeof(struct mtd_info),因为前面分配了两块连续的地址空间,所以&(*(mymtd + 1))实际上就是mtd_info数据结构结束的下一个地址,然后实现强制转换,于是this就成为了nand_chip的入口指针了。但是,这里必须要把握好,因为这个地方是不会进行内存的检查的,也就是说,如果你使用了mymtd[2],那么仍然按照上述公式解析,虽然可以运算,可是就是明显的指针泄漏了,可能会出现意料不到的结果。写了一个测试程序,对这点进行了探讨,要小心内存问题。(参考了CalmArrow的解释)

紧接着就是初始两个结构

memset((char *)mymtd, 0, sizeof(struct mtd_info));

memset((char *)this, 0, sizeof(struct nand_chip));

使得mymtd->priv指向this结构。也就是使得这两部分联系起来

设置nand flash的寄存器

NFCONT |= ((1<<0) & (1 << 4) & (1 << 5));

由于nand_chip是直接于nanf flash挂钩的,应此在此定义一些函数直接对nand flash进行操作

先看整理,再对每个细节进行分析:

this->hwcontrol = smc_hwcontrol;

this->write_cmd = write_cmd;

this->write_addr = write_addr;

this->read_data = read_data;

this->write_data = write_data;

this->wait_for_ready = wait_for_ready;

我们首先来看smc_hwcontrol函数,也就是nand flash的硬件控制,实现很简单,根据vivi中定义的情况之处理3中情况(1,2,10,其他的命令只是简单的退出)

static void smc_hwcontrol(int cmd)

{

    swith (cmd)

        {

            //enable chip select NFCONT &= ~(1 << 1)

            case NAND_CTL_SETNCE:

                    NFCONT &= NFCONT_nFCE_HIGH;

                    break;

           //disable chip select NFCONT |= (1 << 1)

             case NAND_CTL_CLRNCE:

                     NFCONT |= NFCONT_nFCE_HIGH;

                     break;

              // RnB is detected! NFSTAT |= (1 << 2)

              case NAND_CTL_CLRRnB:

                      NFSTAR |= NFSTAT_RnB;

                      break;

        }

}

写命令,

static void write_cmd(u_char val)

{

      NFCMD = (u_char)val;

}

写地址

static void write_addr(u_char val)

{

      NFADDR = (u_char)val;

}

读数据:

static u_char read_data(void)

{

      return (u_char)NFDATA;

}

写数据:

static void write_data(u_char val)

{

      NFDATA = (u_char)val;

}

等待准备好:

static void wait_for_ready(void)

{

//NFSTAT bit[2]为0的时候则表示没准备好,当Bit[2]等于1的时候,则准备好

       while (!(NFSTAT & (1 << 2)))

            ;//do nothing

}

排行榜 更多 +
斗虫公园手机版下载

斗虫公园手机版下载

休闲益智 下载
武林外传之同福奇缘手机版下载

武林外传之同福奇缘手机版下载

角色扮演 下载
无畏契约源能行动小米服手游下载

无畏契约源能行动小米服手游下载

飞行射击 下载