⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash.c

📁 基于linux嵌入式系统的flash驱动以及测试程序和Makefile文件
💻 C
字号:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/modversions.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/param.h>
#include <linux/fs.h>
#include <linux/config.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <linux/malloc.h>
#include <linux/sched.h>
#include <linux/ioport.h>
#include <asm/page.h>
#include <asm/mmu.h>
#include <linux/init.h>

#define DEVICE_NAME  "/dev/flash"
 
static short Major;
static int p;
static int rp;
unsigned long baseaddr;

int flash_erase()
{
  volatile unsigned short *addr=(volatile unsigned short *)baseaddr;
  unsigned long start;

  *(addr+0x555)=0xaa; 
  *(addr+0x2aa)=0x55;
  *(addr+0x555)=0x80;
  *(addr+0x555)=0xaa;
  *(addr+0x2aa)=0x55;  
  addr=(volatile unsigned short *)baseaddr;
  *(addr)=0x30;
  
  for(addr=(volatile unsigned short *)baseaddr;addr<(volatile unsigned short *)baseaddr+0x10000;addr++){
    start=jiffies;
    while(*addr!=0xffff){if((jiffies-start)>500 )return -1;}
  }
  addr=(volatile unsigned short *)baseaddr;
  *addr=0xf0; 
  return 0;
}

int flash_write_word(volatile unsigned short * dest, unsigned short data)
{
  volatile unsigned short *addr=(volatile unsigned short *)baseaddr;
  unsigned long start;

  if((*((volatile unsigned short*)dest) &data)!=data){return 2;}

  *(addr+0x555)=0xaa; 
  *(addr+0x2aa)=0x55;
  *(addr+0x555)=0xa0;

  *((volatile unsigned short *)dest)=data;

  start=jiffies;

  while((*((volatile unsigned short *)dest) & 0x0080) != (data & 0x0080)){
    if((jiffies-start)>500 )return -1;
  }
  return 0;
}

static ssize_t aaa_read(struct file *file, char *buf,size_t len, loff_t *off)
{
  int err;
  int readlen;
  unsigned short filesize=*(volatile unsigned short *)(baseaddr+0x10000-2);
  char *cp=(volatile unsigned char *)(baseaddr+rp);

  if(rp+len>filesize)readlen=filesize-rp;
  else readlen=len;

 err=copy_to_user((void *)buf,(void *)(cp),readlen);
 if(err)
   return -1;
 else{
   rp+=readlen;
   return readlen;
 }
}

static ssize_t aaa_write(struct file *file, const char *buf,size_t len, loff_t *off)
{
  static int b=0;   //First write
  int i;
  int err;
  static char *cp;       //buffer of 64K
 
  if(b==0){
    cp=kmalloc(64*1024,GFP_KERNEL);
    if(cp==NULL){
      printk("Memory Alloc Fails\n");
      return -1;
    }
    b=1;
  }

  err=copy_from_user((void *)&cp[p],buf,len);
  if(err){
    printk("Copy from user fails\n");
    kfree(cp);
    return -1;
  }

  p+=len;

  if(cp[p-1]==0xFF && cp[p-2]==0xFF && cp[p-3]==0xFF && cp[p-4]==0xFF){

    unsigned short *sp=(unsigned short *)cp;

    flash_erase();
    for(i=0;i<p/2;i++){
      flash_write_word((volatile unsigned short *)(baseaddr+i*2),sp[i]);   
  }
    if((p%2)==1)flash_write_word((volatile unsigned short *)(baseaddr+p-1),0xffff);


    flash_write_word((volatile unsigned short *)(baseaddr+0x10000-2),p-4);

    p=0;
    b=0;
    kfree(cp);
  }  
  return 0;
}

static int aaa_ioctl(struct inode *inodp,struct file *filp,unsigned int command,unsigned long arg)
{
  baseaddr=0xe0600000+command*0x10000;
  if(command==30)baseaddr=0xe00f0000;
  return 0;	
}


static int aaa_open(struct inode * inodp,struct file* fp)
{        
  p=0;
  rp=0;
  return 0;
}

static int aaa_release(struct inode * inodp,struct file *filp)
{
  return 0;
}
/**************************KERNEL RELATIVE************************/
static struct file_operations aaa_fops ={
  NULL,
  NULL,//llseek
  aaa_read,
  aaa_write,
  NULL,//readdir
  NULL,//poll
  aaa_ioctl,
  NULL,//mmap,
  aaa_open,
  NULL,//flush,
  aaa_release,
  NULL,// fsync
  NULL,//fasync
  NULL,//lock
  NULL,//readv
  NULL,//writev
  NULL,//sendpage
  NULL//get_unmapped_area
};

int init_module(void)
{
  Major=register_chrdev(0,DEVICE_NAME,&aaa_fops);
  if(Major<0)
    {
      printk("<1>sorry,cannot open device %s,your device number is %d\n",DEVICE_NAME,Major);
      return Major;
    }
  printk("<1>succed in allocating a device number,which is %d\n",Major);  

  return 0;
}

void cleanup_module(void)
{
  int ret;
  ret=unregister_chrdev(Major,DEVICE_NAME);
  ret<0 ? printk("Error in unregistering %s\n",DEVICE_NAME):printk("Success in unregistering %s\n",DEVICE_NAME);
}






⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -