近来二周由于工作原因,需要修改驱动程序的工作,尽管一直想做这方面的工作,总觉得这方面的工作挺有挑战性的,可是地直都处于一个理论状态,直到最近二周。
现在我就介绍一下我的成功经验和在开发过程中遇到的问题。
一、对读某一GPIO引脚的Linux系统驱动的开发背景:
1、MCU芯片:FIC8120 (基于ARM9的内核);
2、操作系统:Linux (2.4内核版本);
二、程序源码:
1、驱动源码:
引用:#define GPIO_read 0x1110
static int gpio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
// add codes by zhiyin 2008-7-25 11:34:42
case GPIO_read:
put_user( *(volatile unsigned int *) (CPE_GPIO_VA_BASE + 0x4), (unsigned long *)arg);
// 1、put_user:把内核空间的数据拷贝到用户空间;
// 2、CPE_GPIO_VA_BASE + 0x4: GpioDataIn寄存器地址;
// 3、arg:用户应用程序传过来的地址参数;
// 4、从上面的解析中不难理解,驱动的功能是把 GpioDataIn寄存器的内容拷贝到arg地址
// 所对应的用户空间
break;
}
}
2、应用程序:
引用:#include
#include
#include
#include
#include
#define DEVICE_GPIOTEST "/dev/gpio"
#define GPIO_read 0x1110
void read_gpio()
{
int fd;
unsigned long pin = 0;
// open device for gpio
if((fd=open(DEVICE_GPIOTEST,O_NONBLOCK))<0)
{
perror("can not open device");
exit(1);
}
ioctl(fd, GPIO_read, &pin);
// 如果某一引脚输入的是高电平哪么相应的位的值应该为"1",否则为"0";
// 如返回结果的值的二进制形式为:100000 说明GPIO5为高电平;
printf("zhiyin: pin= %d\n", pin);
// close device for gpio
if(close(fd) < 0)
{
perror("close");
exit(1);
}
}
三、后记
看了之后你是否觉得简单呀!但是这可是花了我近二周的时间哦!呵呵,万事开头难呀,尽管结果很简单但是在做的时候你需要真正理解代码的每一个细节,并且要有一个较大的知识圈比如:
1、精通Linux系统各个层面的操作和对驱动程序的理解;
2、万用表、波器的熟练使用;
3、能看懂相应的电路图;
4、最后一点也是最重要的一点就是一定要坚持下去,可能你做了很多的“无用功”,但是或许成功就是这样一点一滴的“无用功”积累起来的!

