MTD源代码分析(三)

Linux MTD层的研究(Nandflash) 花了点时间学习Linux MTD层,下面简单总结一下! 以下是MTD层的结构图       MTD层实现了文件系统与Flash之间的桥梁,下面就粗略说明字符型MTD驱动与下层驱动的关系。 分析对象:/drivers/mtdchar.c 字符型mtd设备 字符设备中定义了mtd_fops字符类的文件指针操作函数,完成字符设备读写与打开等功能。 1. static int mtd 阅读详情
 
mtdchar.c

MTD字符设备的文件

notifier

MTD字符设备的notifier

static struct mtd_notifier notifier = {          

       add: mtd_notify_add,

       remove:   mtd_notify_remove,

};

 

mtd_lseek

格式:

       static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)

注释:

       无

功能:

       置MTD字符设备的指针

说明:

       无

参数:

       file:MTD字符设备文件

       offset:偏移

       orig:设置方式

返回:

       成功:返回当前指针位置

       设置方式无效:返回-EINVAL

调用:

       无

被调用:

       注册进mtd_fops结构

源代码:

{

       struct mtd_info *mtd=(struct mtd_info *)file->private_data;

 

       switch (orig) {

       case 0:

              /* SEEK_SET */

              file->f_pos = offset;

              break;

       case 1:

              /* SEEK_CUR */

              file->f_pos += offset;

              break;

       case 2:

              /* SEEK_END */

              file->f_pos =mtd->size + offset;

              break;

       default:

              return -EINVAL;

       }

 

       if (file->f_pos < 0)

              file->f_pos = 0;

       else if (file->f_pos >= mtd->size)

              file->f_pos = mtd->size - 1;

 

       return file->f_pos;

}

 

 

mtd_open

格式:

       static int mtd_open(struct inode *inode, struct file *file)

注释:

       无

功能:

       打开一个MTD字符设备

说明:

       devnum=minor>>2(参看Documentations/devices.txt),

       进行安全性检查,

       调用get_mtd_device获取MTD设备,并将file->private_data指向它

参数:

       inode:FIXME

       file:是系统提供给MTD字符设备用于传递参数的file结构,此函数中它的private_data

成员被指向原始设备层的MTD设备

返回:

       成功:返回0

       失败:返回错误码

调用:

       get_mtd_device()获得原始设备层的MTD设备

被调用:

       注册进mtd_fops结构

源代码:

{

       int minor = MINOR(inode->i_rdev);

       int devnum = minor >> 1;

       struct mtd_info *mtd;

 

       DEBUG(MTD_DEBUG_LEVEL0, "MTD_open/n");

 

       if (devnum >= MAX_MTD_DEVICES)

              return -ENODEV;

 

       /* You can't open the RO devices RW */

       if ((file->f_mode & 2) && (minor & 1))

              return -EACCES;

 

       mtd = get_mtd_device(NULL, devnum);

      

       if (!mtd)

              return -ENODEV;

      

       if (MTD_ABSENT == mtd->type) {

              put_mtd_device(mtd);

              return -ENODEV;

       }

 

       file->private_data = mtd;

             

       /* You can't open it RW if it's not a writeable device */

       if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) {

              put_mtd_device(mtd);

              return -EACCES;

       }

             

       return 0;

} /* mtd_open */

 

 

 

 

mtd_close

格式:

       static int mtd_close(struct inode *inode, struct file *file)

注释:

       无

功能:

       关闭一个MTD字符设备

说明:

       调用mtd_info->sync()同步MTD设备,

       调用put_mtd_device()返还MTD设备

参数:

       inode:FIXME

       file:无用

返回:

       返回0

调用:

       mtd_info->sync()同步MTD设备

put_mtd_device()返还MTD设备

被调用:

       被注册进mtd_fops结构

源代码:

{

       struct mtd_info *mtd;

 

       DEBUG(MTD_DEBUG_LEVEL0, "MTD_close/n");

 

       mtd = (struct mtd_info *)file->private_data;

      

       if (mtd->sync)

              mtd->sync(mtd);

      

       put_mtd_device(mtd);

 

       return 0;

} /* mtd_close */

 

MAX_KMALLOC_SIZE

/* FIXME: This _really_ needs to die. In 2.5, we should lock the

   userspace buffer down and use it directly with readv/writev.

*/

#define MAX_KMALLOC_SIZE 0x20000

 

 

mtd_read

格式:

       static ssize_t mtd_read(struct file *file, char *buf, size_t count,loff_t *ppos)

注释:

       无

功能:

       MTD字符设备的写操作

说明:

       当count>0时{

              裁减本次操作大小len至min(MAX_KMALLOC_SIZE,count),

              申请一块大小为MAX_KMALLOC_SIZE的内核空间kbuf,

              调用mtd_info->read将MTD设备中的数据读入kbuf,

              将kbuf中的数据拷贝到用户空间buf,

              count自减

              释放kbuf

       }

参数:

file:系统给MTD字符设备驱动程序用于传递参数的file结构,此函数通过file得到下

层的MTD设备

       buf:用户空间的指针,用于存放读取的数据

       count:被读数据的长度

       ppos:被读数据在MTD设备中的位置

返回:

       成功:返回实际读取数据的长度

       失败:返回错误码

调用:

       mtd_info->read()用于从MTD设备中读取数据

被调用:

       被注册进mtd_fops结构

源代码:

{

       struct mtd_info *mtd = (struct mtd_info *)file->private_data;

       size_t retlen=0;

       size_t total_retlen=0;

       int ret=0;

       int len;

       char *kbuf;

      

       DEBUG(MTD_DEBUG_LEVEL0,"MTD_read/n");

 

       if (*ppos + count > mtd->size)

              count = mtd->size - *ppos;

 

       if (!count)

              return 0;

      

       /* FIXME: Use kiovec in 2.5 to lock down the user's buffers

          and pass them directly to the MTD functions */

       while (count) {

              if (count > MAX_KMALLOC_SIZE)

                     len = MAX_KMALLOC_SIZE;

              else

                     len = count;

 

              kbuf=kmalloc(len,GFP_KERNEL);

              if (!kbuf)

                     return -ENOMEM;

             

              ret = MTD_READ(mtd, *ppos, len, &retlen, kbuf);

              if (!ret) {

                     *ppos += retlen;

                     if (copy_to_user(buf, kbuf, retlen)) {

                             kfree(kbuf);

                            return -EFAULT;

                     }

                     else

                            total_retlen += retlen;

 

                     count -= retlen;

                     buf += retlen;

              }

              else {

                     kfree(kbuf);

                     return ret;

              }

             

              kfree(kbuf);

       }

      

       return total_retlen;

} /* mtd_read */

 

 

 

mtd_write

格式:

       static ssize_t mtd_write(struct file *file, const char *buf, size_t count,loff_t *ppos)

注释:

       无

功能:

       对MTD字符设备的写操作

说明:

       当count>0时{

              裁减本次操作大小len至min(MAX_KMALLOC_SIZE,count),

              申请一块大小为MAX_KMALLOC_SIZE的内核空间kbuf,

              将用户空间buf中的数据拷贝到kbuf,

              调用mtd_info->write将kbuf中的数据读入MTD设备,

              count自减

              释放kbuf

       }

参数:

file:系统给MTD字符设备驱动程序用于传递参数的file结构,此函数通过file得到下

层的MTD设备

       buf:用户空间的指针,用于存放将要写入的数据

       count:被写数据的长度

       ppos:数据被写入MTD设备中的位置

返回:

       成功:返回实际读取数据的长度

       失败:返回错误码

调用:

       mtd_info->write用于写入MTD设备

被调用:

       被注册进mtd_fops结构

源代码:

{

       struct mtd_info *mtd = (struct mtd_info *)file->private_data;

       char *kbuf;

       size_t retlen;

       size_t total_retlen=0;

       int ret=0;

       int len;

 

       DEBUG(MTD_DEBUG_LEVEL0,"MTD_write/n");

      

       if (*ppos == mtd->size)

              return -ENOSPC;

      

       if (*ppos + count > mtd->size)

              count = mtd->size - *ppos;

 

       if (!count)

              return 0;

 

       while (count) {

              if (count > MAX_KMALLOC_SIZE)

                     len = MAX_KMALLOC_SIZE;

              else

                     len = count;

 

              kbuf=kmalloc(len,GFP_KERNEL);

              if (!kbuf) {

                     printk("kmalloc is null/n");

                     return -ENOMEM;

              }

 

              if (copy_from_user(kbuf, buf, len)) {

                     kfree(kbuf);

                     return -EFAULT;

              }

             

               ret = (*(mtd->write))(mtd, *ppos, len, &retlen, kbuf);

              if (!ret) {

                     *ppos += retlen;

                     total_retlen += retlen;

                     count -= retlen;

                     buf += retlen;

              }

              else {

                     kfree(kbuf);

                     return ret;

              }

             

              kfree(kbuf);

       }

 

       return total_retlen;

} /* mtd_write */

 

 

mtd_erase_callback

格式:

       static void mtd_erase_callback (struct erase_info *instr)

注释:

       无

功能:

       唤醒进程

说明:

       在擦除进行完后被调用

参数:

       instr:进行的擦除的erase_info结构

返回:

       无

调用:

       wake_up()

被调用:

       在mtd_ioctl中被赋给erase_info->callback

源代码:

{

       wake_up((wait_queue_head_t *)instr->priv);

}

 

 

mtd_ioctl

格式:

       static int mtd_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)

注释:

       无

功能:

       MTD字符设备的IO控制

说明:

       根据cmd分别处理

参数:

       inode:FIXME

       file:传递参数的结构

       cmd:IO控制的命令

       arg:IO控制的参数

返回:

       成功:返回0

       失败:返回错误码

调用:

       无

被调用:

       注册进mtd_fops结构

源代码:

{

       struct mtd_info *mtd = (struct mtd_info *)file->private_data;

       int ret = 0;

       u_long size;

      

       DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl/n");

 

       size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;

       if (cmd & IOC_IN) {

              ret = verify_area(VERIFY_READ, (char *)arg, size);

              if (ret) return ret;

       }

       if (cmd & IOC_OUT) {

              ret = verify_area(VERIFY_WRITE, (char *)arg, size);

              if (ret) return ret;

       }

      

       switch (cmd) {

       case MEMGETREGIONCOUNT:

              if (copy_to_user((int *) arg, &(mtd->numeraseregions), sizeof(int)))

                     return -EFAULT;

              break;

 

       case MEMGETREGIONINFO:

       {

              struct region_info_user ur;

 

              if (copy_from_user(      &ur,

                                   (struct region_info_user *)arg,

                                   sizeof(struct region_info_user))) {

                     return -EFAULT;

              }

 

              if (ur.regionindex >= mtd->numeraseregions)

                     return -EINVAL;

              if (copy_to_user((struct mtd_erase_region_info *) arg,

                            &(mtd->eraseregions[ur.regionindex]),

                            sizeof(struct mtd_erase_region_info)))

                     return -EFAULT;

              break;

       }

 

       case MEMGETINFO:

              if (copy_to_user((struct mtd_info *)arg, mtd,

                             sizeof(struct mtd_info_user)))

                     return -EFAULT;

              break;

 

       case MEMERASE:

       {

              struct erase_info *erase=kmalloc(sizeof(struct erase_info),GFP_KERNEL);

              if (!erase)

                     ret = -ENOMEM;

              else {

                     wait_queue_head_t waitq;

                     DECLARE_WAITQUEUE(wait, current);

 

                     init_waitqueue_head(&waitq);

 

                     memset (erase,0,sizeof(struct erase_info));

                     if (copy_from_user(&erase->addr, (u_long *)arg,

                                      2 * sizeof(u_long))) {

                            kfree(erase);

                            return -EFAULT;

                     }

                     erase->mtd = mtd;

                     erase->callback = mtd_erase_callback;

                     erase->priv = (unsigned long)&waitq;

                    

                     /*

                       FIXME: Allow INTERRUPTIBLE. Which means

                       not having the wait_queue head on the stack.

                      

                       If the wq_head is on the stack, and we

                       leave because we got interrupted, then the

                       wq_head is no longer there when the

                       callback routine tries to wake us up.

                     */

                     ret = mtd->erase(mtd, erase);

                     if (!ret) {

                            set_current_state(TASK_UNINTERRUPTIBLE);

                            add_wait_queue(&waitq, &wait);

                            if (erase->state != MTD_ERASE_DONE &&

                                erase->state != MTD_ERASE_FAILED)

                                   schedule();

                            remove_wait_queue(&waitq, &wait);

                            set_current_state(TASK_RUNNING);

 

                            ret = (erase->state == MTD_ERASE_FAILED)?-EIO:0;

                     }

                     kfree(erase);

              }

              break;

       }

 

       case MEMWRITEOOB:

       {

              struct mtd_oob_buf buf;

              void *databuf;

              ssize_t retlen;

             

              if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)))

                     return -EFAULT;

             

              if (buf.length > 0x4096)

                     return -EINVAL;

 

              if (!mtd->write_oob)

                     ret = -EOPNOTSUPP;

              else

                     ret = verify_area(VERIFY_READ, (char *)buf.ptr, buf.length);

 

              if (ret)

                     return ret;

 

              databuf = kmalloc(buf.length, GFP_KERNEL);

              if (!databuf)

                     return -ENOMEM;

             

              if (copy_from_user(databuf, buf.ptr, buf.length)) {

                     kfree(databuf);

                     return -EFAULT;

              }

 

              ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf);

 

              if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t)))

                     ret = -EFAULT;

 

              kfree(databuf);

              break;

 

       }

 

       case MEMREADOOB:

       {

              struct mtd_oob_buf buf;

              void *databuf;

              ssize_t retlen;

 

              if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)))

                     return -EFAULT;

             

              if (buf.length > 0x4096)

                     return -EINVAL;

 

              if (!mtd->read_oob)

                     ret = -EOPNOTSUPP;

              else

                     ret = verify_area(VERIFY_WRITE, (char *)buf.ptr, buf.length);

 

              if (ret)

                     return ret;

 

              databuf = kmalloc(buf.length, GFP_KERNEL);

              if (!databuf)

                     return -ENOMEM;

             

              ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf);

 

              if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t)))

                     ret = -EFAULT;

              else if (retlen && copy_to_user(buf.ptr, databuf, retlen))

                     ret = -EFAULT;

             

              kfree(databuf);

              break;

       }

 

       case MEMLOCK:

       {

              unsigned long adrs[2];

 

              if (copy_from_user(adrs ,(void *)arg, 2* sizeof(unsigned long)))

                     return -EFAULT;

 

              if (!mtd->lock)

                     ret = -EOPNOTSUPP;

              else

                     ret = mtd->lock(mtd, adrs[0], adrs[1]);

              break;

       }

 

       case MEMUNLOCK:

       {

              unsigned long adrs[2];

 

              if (copy_from_user(adrs, (void *)arg, 2* sizeof(unsigned long)))

                     return -EFAULT;

 

              if (!mtd->unlock)

                     ret = -EOPNOTSUPP;

              else

                     ret = mtd->unlock(mtd, adrs[0], adrs[1]);

              break;

       }

 

             

       default:

              DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %x)/n", cmd, MEMGETINFO);

              ret = -ENOTTY;

       }

 

       return ret;

} /* memory_ioctl */

 

 

 

mtd_fops

MTD字符设备的操作函数结构

static struct file_operations mtd_fops = {                  

       owner:           THIS_MODULE,

       llseek:             mtd_lseek,         /* lseek */

       read:              mtd_read,       /* read */

       write:            mtd_write,     /* write */

       ioctl:              mtd_ioctl,       /* ioctl */

       open:              mtd_open,      /* open */

       release:    mtd_close,      /* release */

};

 

 

 

init_mtdchar

格式:

       static int __init init_mtdchar(void)

注释:

       无

功能:

       初始化一个MTD字符设备(设备层)

说明:

       如果定义了CONFIG_DEVFS_FS{

调用devfs_register_chrdev()注册MTD字符设备

调用register_mtd_user()将设备层MTD字符设备的notifier注册进原始设备层

       }

       否则调用register_chrdev()注册MTD字符设备

参数:

       无

返回:

       成功:返回0

       注册失败:返回-EAGAIN

调用:

       devfs_register_chrdev()或register_chrdev()注册字符设备

被调用:

       __init

       module_init

源代码:

{

#ifdef CONFIG_DEVFS_FS

       if (devfs_register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops))

       {

              printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices./n",

                     MTD_CHAR_MAJOR);

              return -EAGAIN;

       }

 

       devfs_dir_handle = devfs_mk_dir(NULL, "mtd", NULL);

 

       register_mtd_user(&notifier);

#else

       if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops))

       {

              printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices./n",

                     MTD_CHAR_MAJOR);

              return -EAGAIN;

       }

#endif

 

       return 0;

}

 

cleanup_mtdchar

格式:

       static void __exit cleanup_mtdchar(void)

注释:

       无

功能:

       清除MTD字符设备

说明:

       如果定义了CONFIG_DEVFS_FS{

              调用unregister_mtd_user()注销MTD字符设备的notifier,

              调用devfs_unregister_chrdev()注销MTD字符设备

}

否则调用unregister_chrdev()注销MTD字符设备

参数:

       无

返回:

       无

调用:

       unregister_chrdev()或devfs_unregister_chrdev()注销字符设备

被调用:

       __exit

       module_exit

源代码:

{

#ifdef CONFIG_DEVFS_FS

       unregister_mtd_user(&notifier);

       devfs_unregister(devfs_dir_handle);

       devfs_unregister_chrdev(MTD_CHAR_MAJOR, "mtd");

#else

       unregister_chrdev(MTD_CHAR_MAJOR, "mtd");

#endif

}


详细图解MTD驱动分析 存储器技术设备(英语:Memory Technology Device,缩写为 MTD),是Linux系统中设备文件系统的一个类型,主要用于闪存类驱动,是一种闪存转换层(Flash Translation Layer,FTL)。 创造MTD子系统的主要目的是提供一个介于闪存硬件驱动程序与高级应用程序之间的抽象层,使新的memory设备的驱动更加简单。MTD的所有源代码在/drivers/mtd子 阅读详情

相关推荐

Linux下读写FLASH驱动——MTD设备分析

最近在学习驱动读写flash的代码部分。经历了可笑的过程:开始我知道flash用通过spi口来读写。所以就到了driver/spi 下面看相关代码。发现有个spidev.c里面有read/write/ioctl等函数。而且还有一个davinci_spi_master.以为调用spi驱动的时候会首先调用到这里,于是就想怎么在上层应用里将spidev.c里open调用到就可以了。最后修改了一些地方就在

lishaochun1983的专栏 1649

通过mtd读写flash_mtd_debug:linux下直接读写flash扇区 及 交叉编译mtd_utils | 学步园

mtd_debug是一个linux下直接读写flash扇区的工具,是mtd-utils的一个部件。具体用法如下:./mtd_debug read ./mtd_debug write [len]./mtd_debug erase 具体使用举例:./mtd_debug erase/dev/mtd/1 0x0 0xc00000 :表示擦写了0x34300000 ~ 0x34f00000共12...

weixin_39996134的博客 1228

深入分析Linux MTD源代码:管理非易失性存储的关键机制

Linux Memory Technology Device(MTD)是一种专门用于嵌入式系统的内存设备驱动框架。其主要目的是为非易失性存储设备,如闪存(Flash),提供一个标准化的接口和管理策略。MTD的主要作用是在系统中创建一个抽象层,允许更高效、更灵活地管理底层存储介质。

weixin_34885746的博客 1237

通过mtd读写flash_mtd_debuglinux下直接读写flash扇区及交叉编译mtd_utils

mtd_debuglinux下直接读写flash扇区及交叉编译mtd_utilsmtd_debug是一个linux下直接读写flash扇区的工具,是mtd-utils的一个部件。具体用法如下:./mtd_debugread<device><offset><dest-filename><len>./mtd_debugwrite<devic...

weixin_39583222的博客 651

Openwrt:mtd/mtd_write烧写固件

【查看当前系统分区信息】  cat /proc/mtd  显示:  dev: size erasesize name  mtd0: 00050000 00010000 “u-boot”  mtd1: 00020000 00010000 “u-boot-env”  mtd2: 00f80000 00010000 “firmware”  mtd3: 00107440 00010000 “kerne...

ysh1042436059的专栏 6597

深入分析Linux MTD源代码及其机制

Linux MTD,即Memory Technology Device,是针对基于闪存的存储设备的一套内核子系统。它提供了一套通用的接口,使得不同的非易失性存储设备可以被Linux内核统一管理和访问。MTD的主要作用是抽象存储设备的硬件细节,允许用户程序通过统一的API来访问这些设备,无论是NAND还是Nor Flash,都可以使用相同的API进行操作。MTD的核心设计哲学是简化嵌入式系统的存储管理,使得开发者能够更加专注于上层应用的开发,而无需深入了解底层硬件的复杂性。

weixin_26850469的博客 679

linux MTD FALSH管理设计

由于loader升级需要使用flash来保存数据,但在android系统上又没有合适的接口使用,因此 对MTD接口设计研究了一下并移植了flash管理代码,有些心得记录一下。专有名词: 1. MTD:Memory Technology Device,内存技术设备, 2. JEDEC:Joint Electron Device Engineering Council,电子电器设备联合会 3....

dowhathowtodo 274

Windows 10下三菱PLC控件安装报错Error Number:-119的终极解决方案(附详细步骤)

本文针对Windows 10系统安装三菱PLC控件时常见的Error Number:-119报错,提供了深度分析与终极解决方案。文章剖析了该错误源于oleaut32.dll文件版本冲突,并详细介绍了通过设置兼容性模式、手动注册DLL、直接安装MX Component以及高级系统修复等多种方法,帮助用户彻底解决此安装难题,顺利搭建PLC开发环境。

weixin_29289821的博客 286

Linux MTD 源代码分析

Linux MTD 源代码分析http://blogimg.chinaunix.net/blog/upfile/070511172139.pdf MTD原始设备与FLASH硬件驱动的对话MTD原始设备与FLASH硬件驱动的对话-续  mtd.h重要

pottichu的专栏 5427

Linux MTD架构下的nand flash驱动详解

转载自:http://blog.csdn.net/wang_zheng_kai/article/details/18988521 有了前面的基础(Nandflash详解:https://blog.csdn.net/Golden_Chen/article/details/89470673),我们就可以研究MTD下的nand驱动了,我这里用的是jz4780grus开发板,我将以下面几个部分做一个介绍...

Golden_Chen的专栏 1万+

@transactional滥用导致数据源连接池耗尽问题

@transactional滥用导致数据源连接池耗尽问题

qq_43205267的博客 1175

MTD系列 - 关于linux MTD的一些理解

<br /> <!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 680460288 22 0 262145 0;}

zgolee的专栏 2万+

NX二次开发编译时dll自动数字签名及拷贝

在UG5.0开始,所有基于UG二次开发的DLL都要“签名”后才能被客户端上正版的NX调用。

菜鸟爱飞不飞的博客 2654

MTD源码分析

引:这一段时间一直很忙,同时看着几份不同的项目代码,有bootloader启动画面的添加修改、图形界面的优化和配合中间件小组的开发。中间件移植有一个地方是涉及到MTD分区操作的,花了一两天的时间终于将这部分的来龙去脉弄清楚了。在这里声明:MTD驱动代码我只看过大概,大体上知道流程是怎样走,具体的分析只局限于Flash硬件驱动层(具体flash芯片)和MTD设备层(file operation系列函

laiqun_ai的专栏 2022

mtd子系统

目录 linux的mtd概述 简介 mtd的字符设备和块设备的命名规则 mtd工具 分层注册函数 字符节点分层调用流程 open 擦除 读 写 控制器驱动probe流程 代码流程 结构体关系图 核心层流程 字符设备 块设备 /sys/class/mtd的相关成员 常用函数 内核版本:linux-4.9.37 linux的mtd...

IT利刃出鞘的博客 2630

STM32异常与中断过程详解

1. 异常与中断概念引入 异常主要是指来自CPU内部的意外事件,比如执行了未定义指令、算术溢出、除零运算等发生在CPU内部的意外事件,这些异常的发生,会引起CPU运行相应的异常处理程序;中断一般来自硬件(如片上外设、外部I/O输入等)发生的事件,当这些硬件产生中断信号时,CPU会暂停当前运行的程序,转而去处理相关硬件的中断服务程序。但无论是异常还是中断,都会引起程序执行偏离正常的流程,转而去执行异常/中断的处理函数。 下面对异常和中断的介绍,如果中断信号的产生原因来自CPU内部,则称之为异常;如果中断信号来

luobeihai的博客 1万+

mtd层次分析

关于mtd的层次分析,网上一大堆,先看看网上怎么说的. MTD(memory technology device内存技术设备)是用于访问memory设备(ROM、flash)的Linux的子系统。MTD的主要目的是为了使新的memory设备的驱 动更加简单,为此它在硬件和上层之间提供了一个抽象的接口。MTD的所有源代码在/drivers/mtd子目录下。我将CFI接口的MTD设备分为四层 (

1637

PLC为西门子的S7-1200,舵机为 DS3218,PLC控制舵机旋转程序实现?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 968

mtd nandflash 分析

一、MTD 的概念和层次 MTD(memory technology device 存储 技术设备 ) 是用于访问 memory 设备( ROM 、 flash )的 Linux 的子系统。 MTD 的主要目的是为了使新的 memory 设备的驱动更加简单,为此它在硬件和上层之间提供了一个抽象的接口。 MTD 的所有源代码在 /drivers/mtd 子目录下 。[1] 传统上, UNIX 只

bugouyonggan的专栏 3845

MTD源代码分析(二)

源码分析下面具体介绍每个文件的内容和作用:  头文件分析 mtd.hMTD_CHAR_MAJOR#define MTD_CHAR_MAJOR 90         MTD字符设备的主设备号MTD_BLOCK_MAJOR#define MTD_BLOCK_MAJOR 31       MTD块设备的主设备号MAX_MTD_DEVICES#define

abc的专栏 2479

避坑指南!YOLO26模型导出/推理常见问题,99%的开发者都踩过

版本锁定:Ultralytics=8.4.2、OpenVINO=2024.0.0、Python=3.10,版本不一致是80%问题的根源;参数对齐:训练/导出/推理的imgsz、归一化、坐标映射必须完全一致,差一步就出错;算子统一:避免自定义算子,优先用YOLO26原生算子(C3k2/PSABlock),确保推理引擎兼容;分步验证:导出后先校验ONNX/IR模型→单图片推理→RTSP流推理→72小时稳定性测试,一步过易踩坑;工业级测试。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 497

MTD源代码分析(一)

看了下MTD源代码 ,发现以前有好多看不懂的现在基本上有点眉目了,下面这篇MTD源代码分析的资料帮了我很大的忙。我现在把他贴出来。linux源代码分析by jim zeusvision 0.1If you got any Problem, Suggestion, Advice or Question ,Please mail to: jimzeus@sina.com.cnAny corre

abc的专栏 2532

最全教改、课程思政、教学成果、一流学科申报书范本(内附清单)(全新整理)

1、资源内容地址:https://blog.csdn.net/2301_79696294/article/details/1404047002、代码特点:今年全新,手工精心整理,放心引用,数据来自权威,相对于其他人的控制变量数据准确很多,适合写论文做实证用 ,不会出现数据造假问题3、适用对象:大学生,本科生,研究生小白可用,容易上手!!!3、课程引用: 经济学,地理学,城市规划与城市研究,公共政策与管理,社会学,商业与管理## 数据指标说明为全面深化高等院校教育教学改革,落实立德树人根本任务,创新人才培养模式,提升人才培养质量,教学改革项目越来越受各个高校重视,作为一名青椒,特别是非主流的青椒,不能一口气吃成胖子,申请国自然、国社科太难了,须知蚊子腿也是肉。比如说,一个省级教改项目也有两万的科研经费,这点蚊子腿也可以做不少事情,当然大牛们肯定看不上,所以我们才有机会。今天,给大家收集了一份:最全教改、课程思政、教学成果、一流学科申报书范本,助力大家中标各类教改课题。

通过mtd读写flash_Linux下读写FLASH驱动——MTD设备分析

最近在学习驱动读写flash的代码部分。经历了可笑的过程:开始我知道flash用通过spi口来读写。所以就到了driver/spi 下面看相关代码。发现有个spidev.c里面有read/write/ioctl等函数。而且还有一个davinci_spi_master.以为调用spi驱动的时候会首先调用到这里,于是就想怎么在上层应用里将spidev.c里open调用到就可以了。最后修改了一些地方就在...

weixin_39662228的博客 613
上一篇: MTD源代码分析(二)
下一篇: 虚拟机redhat下samba服务器安装总结
abc19842008
博客等级 码龄22年 74粉丝 69原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值