Linux下SRAM的读写

时间:2022-09-04 19:36:13
 

项目中需要用ARM与FPGA进行通信,通信方式是通过FPGA生成的SRAM作为数据的交换区,ARM9芯片为ATMEL的AT91SAM9260,采用Linux 2.6.19的内核,今天搞了一天,总算是读写成功,下面简要的说明一下。

       ARM中只有I/O内存的没有I/O端口,ARM9运行后默认是开启MMU的,Linux采用虚拟存储管理内存,具体的内存管理方式本文不作展开。所以要使用Linux访问外设必须要先进行内存映射。这里主要涉及两个函数:

Ø         Request_mem_region:该函数检查所需要转换的内存是否被占用,进行合法性检查,有些驱动中没有,个人认为安全性起见还是使用为妙。

Ø         Ioremap:该函数完成物理地址到虚拟地址的映射,映射后的地址才能被Linux内核使用。

下面给出代码:

驱动程序:

#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/gpio.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <asm/arch/hardware.h>
#include <asm/arch/gpio.h>
#include <asm/uaccess.h>
#include <linux/slab.h> /*for Kmalloc*/
#include <asm/io.h>/*for virt_to_phys*/
#include <asm/hardware.h>
#include <asm/arch/at91_pio.h>
#include <asm/arch/at91rm9200.h>/*for sram address and size*/

#define SRAM0_PHYADDR 0x300000
#define SRAM0_SIZE 0x1000 /*4K*/


int sram_major = 242;

int sram_open(struct inode *inode,struct file *filp);
int sram_release(struct inode *inode,struct file *filp);
int sram_release(struct inode *inode,struct file *filp);
ssize_t sram_read(struct file *filp , char __user *buf ,size_t count,loff_t *f_pos);
ssize_t sram_write(struct file *filp , char __user *buf ,size_t count,loff_t *f_pos);
//int sram_mmap(struct file *filp, struct vm_area_struct *vma );
//static void sram_setup_cdev(struct sram_dev *dev,int index);
int sram_init(void);
void sram_cleanup(void);


MODULE_AUTHOR("Cun Tian Rui");
MODULE_LICENSE("Dual BSD/GPL");


struct sram_dev
{
struct cdev cdev;
unsigned long startAddr;
unsigned long size;
char *mapPtr;
}sram_dev;

struct sram_dev *sramdevp;

struct file_operations sram_fops =
{
.owner = THIS_MODULE,
// .ioctl = sram_ioctl,
.open = sram_open,
.release = sram_release,
.read = sram_read,
.write = sram_write,
// .mmap = sram_mmap
};



int sram_open(struct inode *inode,struct file *filp)
{
struct sram_dev *devp;
devp = container_of(inode->i_cdev,struct sram_dev,cdev);
filp->private_data = devp;

return 0;
}

int sram_release(struct inode *inode,struct file *filp)
{
return 0;
}

ssize_t sram_read(struct file *filp , char __user *buf ,size_t count,loff_t *f_pos)
{

unsigned long p = *f_pos;
struct sram_dev *devp = filp->private_data;
printk("Driver read function running\n");
printk("p is %d\n",p);
if (p >= devp->size)
return -EINVAL;
if (count > devp->size-p)
count = devp->size-p;
printk("count is %d\n",count);
if (copy_to_user(buf, devp->mapPtr+p,count))
return -EFAULT;
*f_pos+= count;
return count;
}

ssize_t sram_write(struct file *filp , char __user *buf ,size_t count,loff_t *f_pos)
{

unsigned long p = *f_pos;
printk("Driver write function running\n");
printk("p is %d\n",p);
struct sram_dev *devp = filp->private_data;
if (p >= devp->size)
return -EINVAL;
if (count > devp->size-p)
count = devp->size-p;
printk("count is %d\n",count);
if (copy_from_user( devp->mapPtr+p,buf,count))
return -EFAULT;
*f_pos += count;
return count;

}
/*
int sram_mmap(struct file *filp, struct vm_area_struct *vma )
{
unsigned long offset = vma->vm_pgoff<<PAGE_SHIFT;
unsigned long size = vma->vm_end - vma->vm_start;

if ( size > SRAM0_SIZE )
{
printk("size too big\n");
return(-ENXIO);
}

offset = offset + SRAM0_PHYADDR;

vma->vm_flags |= VM_LOCKED;
if ( remap_pfn_range(vma,vma->vm_start,offset,size,PAGE_SHARED))
{
printk("remap page range failed\n");
return -ENXIO;
}

return(0);

}
*/

int sram_init(void)
{
int result;
int err,ret;
int devno = MKDEV(sram_major,0);

dev_t dev = MKDEV(sram_major,0);
if(sram_major)
{

result = register_chrdev_region(dev,1,"SRAM0");
}

if(result < 0)
{
return result;
}

sramdevp = kmalloc(sizeof(struct sram_dev),GFP_KERNEL);
if(!sramdevp)
{
result = - ENOMEM;
goto fail_malloc;
}

memset(sramdevp,0,sizeof(struct sram_dev));
//sram_setup_cdev(sramdevp,0);


sramdevp->startAddr = SRAM0_PHYADDR;
sramdevp->size = SRAM0_SIZE;
ret = request_mem_region(SRAM0_PHYADDR, SRAM0_SIZE, "SRAM0 Region");
if(ret==NULL)
{
printk("Request Memory Region Failed!\n");
return -1;
}
sramdevp->mapPtr = ioremap(SRAM0_PHYADDR,SRAM0_SIZE);
cdev_init(&sramdevp->cdev,&sram_fops);
sramdevp->cdev.owner = THIS_MODULE;
sramdevp->cdev.ops = &sram_fops;
err = cdev_add(&sramdevp->cdev,devno,1);

if(err)
{
printk(KERN_NOTICE "Error %d adding SRAM%d",err,0);
}

printk( "SRAM0_virt_addr = 0x%lx\n", (unsigned long)sramdevp->mapPtr );
return 0;

fail_malloc:
unregister_chrdev_region(dev,sramdevp);
kfree(sramdevp);
return result;

}

void sram_cleanup(void)
{
cdev_del(&sramdevp->cdev);
iounmap(sramdevp->mapPtr);
kfree(sramdevp);
unregister_chrdev_region(MKDEV(sram_major,0),1);
}




module_init(sram_init);
module_exit(sram_cleanup);


 

写SRAM:

#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<stdio.h>#include<linux/fs.h>#include<stdlib.h>#include<unistd.h>#define SRAM_DEV "/dev/SRAM0"int main(){  int fd;   char * data="ctrboss";   fd=open(SRAM_DEV,O_WRONLY);if(fd<0){  printf("Unable to open sram device %s\n",SRAM_DEV);  return 0;}  write(fd,data,sizeof(data));  close(fd);  return 1;} 

读SRAM:

#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<stdio.h>#include<linux/fs.h>#include<stdlib.h>#include<unistd.h>#define SRAM_DEV "/dev/SRAM0"int main(){  int i,fd;  char data[6];  fd=open(SRAM_DEV,O_RDONLY);  if(fd<0)  {   printf("Unable to open sram device %s\n",SRAM_DEV);   return 0;  }  read(fd,data,sizeof(data));  printf("data is %x\n",data[0]);  printf("data is %x\n",data[1]);  printf("data is %x\n",data[2]);  printf("data is %x\n",data[3]);  printf("data is %x\n",data[4]);  printf("data is %x\n",data[5]);    printf("data is %c\n",data[0]);  printf("data is %c\n",data[1]);  printf("data is %c\n",data[2]);  printf("data is %c\n",data[3]);  printf("data is %c\n",data[4]);  printf("data is %c\n",data[5]);	  close(fd);  return 1;}