2410并行接口驱动,虚拟地址和实际地址映射问题。
[复制链接]
使用S3C2410的DATA0~DATA15,扩展2个并行接口,原理图如下所示。 通过一个CPLD扩展I/O驱动修改成驱动程序,编译没有出错,但是在板子上insmod时出现段错误。 怀疑是使用的物理地址和虚拟地址不对。
#define pEXTERNAL_IO_Addr 0x080000c0 #define EXTERNAL_BaseAddr_IO (*(volatile unsigned char*)(0xd02000c0)) 加载模块时出错信息: [root@(none) tmp]# insmod DIGIO2.ko Using DIGIO2.ko Unable to handle kernel paging request at virtual address 56000000 pgd = c2604000 [56000000] *pgd=00000000 Internal error: Oops: 5 [#1] Modules linked in: DIGIO ov511 usbvideo usb_storage sd_mod CPU: 0 PC is at digio_init+0x50/0xc0 [DIGIO] LR is at 0x56000004 pc : [] lr : [<56000004>] Not tainted sp : c2e55f6c ip : 56000000 fp : c2e55f84 r10: 00000000 r9 : c2e54000 r8 : c002c5c4 r7 : 00000000 r6 : 56000014 r5 : 56000010 r4 : 00000000 r3 : c0270284 r2 : 0000efff r1 : 000007fe r0 : bf03010c Flags: nZCv IRQs on FIQs on Mode SVC_32 Segment user Control: C000717F Table: 32604000 DAC: 00000015 Process insmod (pid: 337, stack limit = 0xc2e54190) Stack: (0xc2e55f6c to 0xc2e56000) 5f60: c026f44c bf030520 c026f434 c2e55fa4 c2e55f88 5f80: c0055fbc bf032010 00000004 00000000 00000000 00000080 00000000 c2e55fa8 5fa0: c002c440 c0055e20 00000000 00000000 00900080 40015000 00000b79 001cb028 5fc0: 00000004 00000000 00000000 befffd74 001cb018 001cb008 00000000 00000000 5fe0: beffd8c4 beffd8b8 000444e0 40199ac0 60000010 00900080 e586000c e596201c Backtrace: [] (digio_init+0x0/0xc0 [DIGIO]) from [] (sys_init_module+0) r6 = C026F434 r5 = BF030520 r4 = C026F44C [] (sys_init_module+0x0/0x314) from [] (ret_fast_syscall+0x) r7 = 00000080 r6 = 00000000 r5 = 00000000 r4 = 00000004 Code: aa000002 eb403843 e1a00004 e91ba870 (e59c3000) Segmentation fault
并行接口原理图
附上驱动程序代码:
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include //包含可装载模块需要的大量符号和函数的定义
#include
#include //定义了LINUX内核的版本,用于版本检查
#include
#include //指定初始化和清除函数
#include
//#include //
//#include //LINUX内核编译时的配置文件,文件里面指向另一个由make menuconfig自动生成的文件autoconfig.h
#include
#include //最重要的头文件之一。该文件包含驱动程序使用的大部分内核API的定义,包含睡眠函数以及各种变量声明。
#include
#include
#include
#include
//#include
#include
#include
// #define DEVICE_NAME "digio" //设备名
#define DIGIO_MAJOR 232 //主设备号 //unsigned short buffer,dio_value;
#define pEXTERNAL_IO_Addr 0x080000c0
#define EXTERNAL_BaseAddr_IO (*(volatile unsigned char*)(0xd02000c0))
/*
static void dig_io_read()
{
(void *)(digital_in)=ioremap(0x0800b800,0x2); //映射74HC574,16位
buffer=*(volatile unsigned short *)(digital_in); //读数字输入
copy_to_user(buffer,&dio_value,sizeof(dio_value));//数据送入用户空间
} static void dig_io_write()
{
(void *)(digital_out)=ioremap(0x10000000,0x2); //映射74HC574,16位
copy_form_user(&dio_value,buffer,sizeof(dio_value));//数据送入内核空间
*(volatile unsigned short *)=buffer; //写数字输出
}
*/
static ssize_t dig_io_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) //读函数
{
unsigned char val;
val=inb(EXTERNAL_BaseAddr_IO); //读取数据
copy_to_user(buf,&val,1); //数据送入用户空间
return 1;
} static ssize_t dig_io_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{
unsigned char val;
copy_from_user(&val,buf,1); //数据送入内核空间
outb(val,EXTERNAL_BaseAddr_IO); //写数据
return 1;
} static struct file_operations digio_fops={
owner:THIS_MODULE,
write:dig_io_write,
read:dig_io_read,
}; //static devfs_handle_t devfs_handle; /*
static int digio_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg)
{
switch(cmd)
{
case 0:dig_io_read();
case 1:dig_io_write();
default:
return -EINVAL;
}
} static struct file_operations digio_fops={
owner:THIS_MODULE,
ioctl:digio_ioctl,
};
*/ static int __init digio_init(void) //设备驱动初始化函数
{
int ret;
int i;
ret=register_chrdev(DIGIO_MAJOR,DEVICE_NAME,&digio_fops);
if(ret<0)
{
printk(DEVICE_NAME"can't regsiter major number");
return ret;
}
// devfs_handle=devfs_register(NULL,DEVICE_NAME,DEVFS_FL_DEFAULT,DIGIO_MAJOR,S_IFCHR|S_IRUSR|S_IWUSR,&digio_fops,NULL);
// EXTERNAL_BaseAddr_IO=ioremap(pEXTERNAL_IO_Addr,1);
rGPACON=rGPACON&0x7effff;
rGPADAT=rGPADAT&0xefff;
rGPBCON=rGPBCON&0x3ffffc|0x000001;
rGPBDAT=rGPBDAT&0x7fe;
printk(DEVICE_NAME"initialized\n");
return 0;
} static void __exit digio_exit(void) //模块退出函数
{
// iounmap(EXTERNAL_BaseAddr_IO);
// devfs_unregister(devfs_handle);
unregister_chrdev(DIGIO_MAJOR,DEVICE_NAME);
} module_init(digio_init);
module_exit(digio_exit);
MODULE_LICENSE("GPL");
|