ioremap内存映射 始终不能访问内存 求解
ioremap内存映射,修改了数次,还是不能正常访问寄存器,基本问题是可以加载模块,但是只要lsmod就会出现段错误
unable to handle kernel paging request at virtual address 7fXXXXXX
望高手指教!!!
- C/C++ code
#include <asm/io.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/irq.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <linux/device.h>#include <linux/gpio.h>static int led_major;static void *base;#define LED_CONTROLLER_BASE 0x56000050#define led_all_off 0#define led_all_on 1#define DEVICE_NAME "zx_led"#define LED_CON (*(volatile u32*)(LED_CONTROLLER_BASE))#define LED_DAT (*(volatile u32*)(LED_CONTROLLER_BASE + 4))#define LED_UP (*(volatile u32*)(LED_CONTROLLER_BASE + 8))#define LED_MEM_LEN 0x0cstatic int led_open(struct inode *inode,struct file *file){ printk("the led driver is open\n"); return 0;}static int led_close(struct inode *inode,struct file *file){ printk("the led driver is close\n"); return 0;}static int led_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg){ switch(cmd) { case led_all_off: //iowrite16(0x00,base + 0x04); iowrite16((ioread16(base + 0x04)&0xff)|0x0,base + 0x04); break; case led_all_on: iowrite16(0x0f00,base + 0x04); iowrite16((ioread16(base + 0x04)&0xff)|0xff00,base + 0x04); break; default: return -EINVAL; } return 0;}static struct file_operations led_fops ={ .owner = THIS_MODULE, .open = led_open, .ioctl = led_ioctl, .release= led_close,};static struct class *led_class;static int led_init(void){ printk("led initialize\n"); led_major = register_chrdev(0, DEVICE_NAME, &led_fops); if(led_major < 0) { printk("can't creat led_major\n"); return led_major; } printk("register zhengxu_led Driver OK! Major = %d\n", led_major); led_class = class_create(THIS_MODULE,DEVICE_NAME); if(IS_ERR(led_class)) { printk("led_class create is failed\n"); return -1; } printk("class_create is ok\n"); device_create(led_class, NULL, MKDEV(led_major, 0), NULL, DEVICE_NAME); printk("initialize is sucessful\n"); request_mem_region(LED_CONTROLLER_BASE,LED_MEM_LEN,"zx_led"); base=ioremap_nocache(LED_CONTROLLER_BASE,LED_MEM_LEN); printk("%lx\n",base); printk("ioremap is sucessful\n"); if(base < 0) { printk("ioremap is failed\n"); }// iowrite16(0xff00,base); iowrite16((ioread16(base)&0xff00)|0x00ff,base);// iowrite16(0xff00,base + 0x08); iowrite16((ioread16(base + 0x08)&0xff)|0xff00,base + 0x08); return 0;}void led_exit(void){ unregister_chrdev(led_major,DEVICE_NAME); device_destroy(led_class,MKDEV(led_major,0)); class_destroy(led_class); iounmap(base); release_mem_region(LED_CONTROLLER_BASE,LED_MEM_LEN);}module_init(led_init);module_exit(led_exit);MODULE_AUTHOR("zhengxu");MODULE_LICENSE("GPL");[解决办法]
是可以用ioremap去映射物理内存的,不过base的类型好像是 void __iomem *啊!还有啊,最好多用printk打印程序执行到哪儿出问题了,我一般直接用ioremap。
可以这样定义后就可以直接读值和写值,就把它当做一个变量就可以了。不过你也可以直接搞成结构体类型也成。
#define ADCCON(*(volatile unsigned long *)(base_addr + 0x00))