UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Contributor
Contributor
374 Views
Registered: ‎11-23-2017

Writing to DDR fails

Hi all,

In my application , it needs to allocate physical memory and copying data from one location to another, i wrote a kernel module and allocated memory region and accessed it via virtual address returned by ioremap_nocache(); and writing to virtual address results in kernel freeze , Linux Hangs stucks and reboot is required. does anyone know why is this so?

here is my kernel module code i wrote:

#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>



#define DEVICE_NAME   "dma_kernel"

#define CLASS_NAME    "axi_dma"


MODULE_LICENSE("GPL");              
MODULE_AUTHOR("Harry");      
MODULE_DESCRIPTION("A simple Linux driver for the AXI DMA."); 
MODULE_VERSION("1.0");

//static void __iomem *dma_virt_addr;
static void __iomem *virt_source_buf_address;
//static void __iomem *virt_destination_buf_address;
//static unsigned int* p;
//static volatile unsigned int* dma_virt_addr;

static int    majorNumber;                             
static struct class*  axidmaclass  = NULL;
		
static int     axi_dma_open(struct inode *, struct file *);
static int     axi_dma_release(struct inode *, struct file *);

static int axi_dma_open(struct inode *inodep, struct file *filep){
  
   printk(KERN_INFO "AXI DMA: Device has been opened time(s)\n");
   return 0;
}

static int axi_dma_release(struct inode *inodep, struct file *filep){
   printk(KERN_INFO "AXI DMA: Device successfully closed\n");
   return 0;
}
static struct file_operations axi_dma={

.owner=THIS_MODULE,
.open=axi_dma_open,
.release=axi_dma_release,
};

static int __init axi_dma_init(void){
// Try to dynamically allocate a major number for the device -- more difficult but worth it
   majorNumber = register_chrdev(0, DEVICE_NAME, &axi_dma);
   if (majorNumber<0){
      printk(KERN_ALERT "axidma failed to register a major number\n");
      return majorNumber;
   }
   printk(KERN_INFO "axidma: registered correctly with major number %d\n", majorNumber);


   // Register the device class
   axidmaclass = class_create(THIS_MODULE, CLASS_NAME);
   if (IS_ERR(axidmaclass)){                // Check for error and clean up if there is
      unregister_chrdev(majorNumber, DEVICE_NAME);
      printk(KERN_ALERT "Failed to register device class\n");
      return PTR_ERR(axidmaclass);          // Correct way to return an error on a pointer
   }
   printk(KERN_INFO "axidma: device class registered correctly\n");

//request memory region

if(request_mem_region(0x80001400,256*2048,"axi_dma_mmeory")==NULL){
printk("failed to request memory region\n");
}

   printk(KERN_INFO "AXI DMA Initialized");

	u32  *src_buffer;
	u32  *dest_buffer;
	u32  *p; 
	src_buffer = kmalloc(1024, GFP_KERNEL);
	dest_buffer = kzalloc(1024, GFP_KERNEL);
int i;

if (!src_buffer || !dest_buffer) {
		printk(KERN_ERR "Allocating memory failed\n");
		return -1;
	}

		for (i = 0; i < 1024/4; i++)
		src_buffer[i] = i;


	virt_source_buf_address = ioremap_nocache(0x80001400, 256*1024);
        if (!virt_source_buf_address ) {
                printk("Could not map physical memory to virtual\n");
                return -1;
        }
	printk("virt_source_buf_address: %08X\n", (unsigned int)virt_source_buf_address);
	p = virt_source_buf_address;

		for (i = 0; i < 1024/4; i++){
		__raw_writel(src_buffer[i], p++);
			printk("data \n%d\n",*p);
			*p++;
}

		p = virt_source_buf_address;
	
		for (i = 0; i < 1024/4; i++)
		dest_buffer[i] = __raw_readl(p++);


		for (i = 0; i < 1024/4; i++) {
		if (dest_buffer[i] != src_buffer[i]) { 
			printk("index = %d, src=%02X, dest = %02X\n", i, src_buffer[i], dest_buffer[i]);
		}
	}

return 0;

}


static void __exit axi_dma_exit(void){
	device_destroy(axidmaclass, MKDEV(majorNumber, 0));     // remove the device
   	class_unregister(axidmaclass);                          // unregister the device class
   	class_destroy(axidmaclass);                             // remove the device class
   	unregister_chrdev(majorNumber, DEVICE_NAME);             // unregister the major num
	release_mem_region(0x80001300 ,256*1024*256);
        printk(KERN_INFO "AXI DMA Exit\n");
}
module_init(axi_dma_init);
module_exit(axi_dma_exit);


and here is the result when i insert the module and it stuck the Linux as shown below:

reult.png

0 Kudos
1 Reply
Visitor ceejliu
Visitor
155 Views
Registered: ‎08-05-2017

回复: Writing to DDR fails

Hello,

Did you solve this problem?

I have the same situation.

0 Kudos