cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Contributor
Contributor
534 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
Observer
Observer
315 Views
Registered: ‎08-05-2017

回复: Writing to DDR fails

Hello,

Did you solve this problem?

I have the same situation.

0 Kudos