免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1917 | 回复: 3
打印 上一主题 下一主题

IO控制驱动程序开发 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-05-16 10:25 |只看该作者 |倒序浏览
开发板:扬创s3c2440,
内核:utulinux2.6.24

本人写了一个控制IO口的驱动,功能是控制IO口的高低电平输出,用了PORTC的GPC15,GPC14,GPC13,GPC12这四个管脚(查了下芯片手册这四个管脚均可以配置成输入和输出管脚,并且开发板将这四个管脚通过排针引出了,感觉测试时比较容易控制)。
其中:
PORTC的控制寄存器地址GPCCON地址为0x56000020
PORTC的数据寄存器地址GPCDAT地址为0x56000024
驱动程序如下所示:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/cdev.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-irq.h>
MODULE_LICENSE("GPL");
#define DEVNAME  "IOPORT"
#define IOPORTSIZE      4
#define IOPORTREG       0x56000020
#define IOPORTADDR      0x56000024
static volatile unsigned long* IoRegBase;
static volatile unsigned long* IoPortBase;
static int io_major_no = 0;
static int IOPORT_Remap()
{
        int io_err;
        io_err = check_region( IOPORTREG,IOPORTSIZE );
        if( io_err < 0 )
        {
                printk( "io register check error!" );
                return 1;
        }
        io_err = check_region( IOPORTADDR,IOPORTSIZE );
        if( io_err < 0 )
        {
                printk( "io base address check error!" );
                return 1;
        }
        request_region( IOPORTREG,IOPORTSIZE * 2, DEVNAME );
        IoRegBase = ioremap( IOPORTREG,IOPORTSIZE );
        IoPortBase = ioremap( IOPORTADDR,IOPORTSIZE );
        return 0;
}
static int io_open( struct inode* inode,struct file* flip );
static int io_release( struct inode* inode,struct file* flip );
static ssize_t io_write( struct file* ,const char*,size_t,loff_t* );
static ssize_t io_read( struct file*,const char*,size_t,loff_t* );
struct file_operations io_fops =
{
.open = io_open,
.release = io_release,
.write = io_write,
.read = io_read,
};
static int io_open( struct inode* inode,struct file* flip )
{
int i;
for( i = 0; i < 4; i++ )
{
  *( IoRegBase + i ) = 0x00;
}
*( IoRegBase + 3 ) = 0x55;
*( IoPortBase ) = 0x0000;
return 0;
}
static int io_release( struct inode* inode,struct file* flip )
{
int i;
for( i = 0; i < 4; i++ )
{
  *( IoRegBase + i ) = 0x00;
}
return 0;
}
static ssize_t io_write( struct file* flip,const char* buffer,size_t len,loff_t* off )
{
char *buf,t;
buf = buffer;
t = buf[0];
switch( t )
{
  case 'a': *( IoPortBase ) = 0xf000;break;
  case 'b': *( IoPortBase ) = 0x7000;break;
  case 'c': *( IoPortBase ) = 0xb000;break;
  default : printk( "error" );
}
return 0;
}
static ssize_t io_read( struct file* flip,const char* buffer,size_t len,loff_t* off )
{
return 0;
}
static int __init io_module_init( void )
{
int result;
result = register_chrdev( 212,DEVNAME,&io_fops );
io_major_no = 212;
}
static void __exit io_module_release( void )
{
iounmap( IoRegBase );
iounmap( IoPortBase );
release_region( IOPORTREG,IOPORTSIZE );
release_region( IOPORTADDR,IOPORTSIZE );
unregister_chrdev( io_major_no,DEVNAME );
}
module_init( io_module_init );
module_exit( io_module_release );

测试程序:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#define DEVICE_FILENAME "/dev/IOPORT"
int main()
{
        int fileHandle,i;
        char buff[10] = "bcd";
        fileHandle = open( DEVICE_FILENAME,O_RDWR|O_NDELAY);
        if ( fileHandle >= 0 )
        {
                printf( "the device added already" );
        }
        for( i = 0; i < 10000; i++ )
        write (fileHandle,buff,1);

}




编译可以动过加载也没有问题但是当用如上测试程序测试时就出现了一大堆的oop错误不知什么原因希望大家能够给予一些指点。。。

论坛徽章:
0
2 [报告]
发表于 2009-05-16 18:56 |只看该作者
不能直接对指针操作, 要使用 readl ,writel  操作

论坛徽章:
0
3 [报告]
发表于 2009-05-17 17:08 |只看该作者
>>*( IoRegBase + i ) = 0x00;
>>*( IoRegBase + 3 ) = 0x55;
>>*( IoPortBase ) = 0x0000;
改为
*(char *)(IoRegBase + i ) = 0x00;
*(char *)( IoRegBase + 3 ) = 0x55;
*(unsign int *)( IoPortBase ) = 0x0000;
其他类似的操作也要修改

Ps:代码贴好一点吧,看得非常累

论坛徽章:
0
4 [报告]
发表于 2009-05-17 17:16 |只看该作者
另:
>>static volatile unsigned long* IoRegBase;
>>static volatile unsigned long* IoPortBase;
改为:
static volatile unsigned char* IoRegBase;
static volatile unsigned char* IoPortBase;

提个建议,你当务之急应该是好好学习一下c语言的指针

i = (unsigned long)IoRegBase + 1;
i = (unsigned long *)IoRegBase + 1;
这两行,i的值是完全不同的,从中可以好好考虑一下为什么你程序会内存越界

[ 本帖最后由 sep 于 2009-5-17 17:18 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP