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 &#61; 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&#43;0x0/0xc0 [DIGIO]) from [] (sys_init_module&#43;0)
r6 &#61; C026F434 r5 &#61; BF030520 r4 &#61; C026F44C
[] (sys_init_module&#43;0x0/0x314) from [] (ret_fast_syscall&#43;0x)
r7 &#61; 00000080 r6 &#61; 00000000 r5 &#61; 00000000 r4 &#61; 00000004
Code: aa000002 eb403843 e1a00004 e91ba870 (e59c3000)
Segmentation fault
并行接口原理图.jpg (164.89 KB, 下载次数: 0)
并行接口原理图
2012-11-29 14:57 上传
并行接口原理图
附上驱动程序代码&#xff1a;
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include//包含可装载模块需要的大量符号和函数的定义
#include#include//定义了LINUX内核的版本&#xff0c;用于版本检查
#include#include//指定初始化和清除函数
#include//#include
//
//#include//LINUX内核编译时的配置文件&#xff0c;文件里面指向另一个由make menuconfig自动生成的文件autoconfig.h
#include#include//最重要的头文件之一。该文件包含驱动程序使用的大部分内核API的定义&#xff0c;包含睡眠函数以及各种变量声明。
#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)&#61;ioremap(0x0800b800,0x2); //映射74HC574,16位
buffer&#61;*(volatile unsigned short *)(digital_in); //读数字输入
copy_to_user(buffer,&dio_value,sizeof(dio_value));//数据送入用户空间
}
static void dig_io_write()
{
(void *)(digital_out)&#61;ioremap(0x10000000,0x2); //映射74HC574,16位
copy_form_user(&dio_value,buffer,sizeof(dio_value));//数据送入内核空间
*(volatile unsigned short *)&#61;buffer; //写数字输出
}
*/
static ssize_t dig_io_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) //读函数
{
unsigned char val;
val&#61;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&#61;{
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&#61;{
owner:THIS_MODULE,
ioctl:digio_ioctl,
};
*/
static int __init digio_init(void) //设备驱动初始化函数
{
int ret;
int i;
ret&#61;register_chrdev(DIGIO_MAJOR,DEVICE_NAME,&digio_fops);
if(ret<0)
{
printk(DEVICE_NAME"can&#39;t regsiter major number");
return ret;
}
// devfs_handle&#61;devfs_register(NULL,DEVICE_NAME,DEVFS_FL_DEFAULT,DIGIO_MAJOR,S_IFCHR|S_IRUSR|S_IWUSR,&digio_fops,NULL);
// EXTERNAL_BaseAddr_IO&#61;ioremap(pEXTERNAL_IO_Addr,1);
rGPACON&#61;rGPACON&0x7effff;
rGPADAT&#61;rGPADAT&0xefff;
rGPBCON&#61;rGPBCON&0x3ffffc|0x000001;
rGPBDAT&#61;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");