分类: LINUX
2008-10-29 18:17:07
2.4中的gpio要把内核数据放在proc下面,方法比较麻烦。看2.6的驱动,里面采用ctl_table结构来做,
而且是可读写的,使用和实现起来非常方便,统一放在proc/sys下面。
static ctl_table gpio_table[] = {
{
.ctl_name = 3,
.procname = "gpio2",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &gpio_sysctl_op,
},
{
.ctl_name = 2,
.procname = "gpio1",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &gpio_sysctl_op,
},
{
.ctl_name = 1,
.procname = "gpio0",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &gpio_sysctl_op,
},
{ .ctl_name = 0 }
};
在写gpio_sysctl_op实现时遇到一些麻烦,比如说cat /proc/sys/gpio/gpio0 会不停的输出,后来看了
下别人的代码,加了一段程序就可以了
static int gpio_sysctl_op(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
if (*ppos > 0) {
*lenp = 0;
return 0;
}
在driver/cdrom/cdrom.c里面它是这样加的
if (!*lenp || (*ppos && !write)) {
*lenp = 0;
return 0;
}
此外你要使cat /proc/sys/gpio0 能正确显示,送到用户空间的必须是字符串,所以读出来的十六进制数要转换一下的。
整个函数如下,对其中的lenp和ppos还是搞得不是很清楚。
static int gpio_sysctl_op(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int i;
unsigned int port_data = 0;
unsigned char str_data[24] = {0};
if (!*lenp || (*ppos && !write)) {
*lenp = 0;
return 0;
}
if (!write){
/*read*/
/*
if (*ppos > 0) {
*lenp = 0;
return 0;
}*/
port_data = ar7100_reg_rd(AR7100_GPIO_IN);
for ( i = 0 ; i < 22 ; i++){
int bit_i = (port_data & (1< str_data[21-i] = bit_i ? '1':'0';
}
str_data[22] = '\n';
str_data[23] = '\0';
copy_to_user(buffer,&str_data,24);
*ppos = *ppos + 24;
*lenp = 24;
return *lenp;
}
return *lenp;
}
AR9132的gpio寄存器设计的很复杂,竟然rx和tx都能使能在gpio口上,要控制它要用到
GPIO_OE 方向设定
GPIO_IN 读数据
GPIO_OUT 写数据
GPIO_IN读数据不用设置GPIO_OE,但是要写数据到GPIO_OUT一定要先设置GPIO_OE,对应位置
1为输出。
5vt 131X的CPU的GPIO设置感觉很方便,它是分组的A,B,C每组都有
GPIO_DIR
GPIO_DATA
寄存器
设了方向后,就可以在GPIO_DATA上读数据或写数据到GPIO口上