返回信息流在编写GPIO驱动程序mini2440_gpios.c中,想控制GPF IO的模式(input&output)和读其接口的数据,利用如下语句:
#define GPGCON (*(volatile unsigned long *)0x56000060)
#define GPGDAT (*(volatile unsigned long *)0x56000064)
【(地址是查的S3C2440的芯片手册,如下图)
】
……
GPGCON = 0;(根据数据手册定义是将GPF口全部设置为input模式)
……
驱动程序调试通过,没有错误。
然后写了一个简单的测试程序gpios_test.c,编译后运行,在执行到GPGCON = 0 ;这个语句就过不去,
系统提示:
Unable to handle kernel paging request at virtual address 56000060
pgd = c33f0000
[56000060] *pgd=00000000
Internal error:Oops:5 [#1]
Modules linked in mini2440_gpios mini2440_backlight
CPU : 0
PC is at mini2440_gpios_open+0x14/0x3c [mini2440_gpios]
……
我实在是搞不明白,只能用内部接口函数s3c2410_gpio_cfgpin()进行端口配置,但是一次只能配置一位,十分不方便,恳请高手赐教!!!不甚感谢!!
[ema41]
这是一条镜像帖。来源:北邮人论坛 / embedded-system / #10499同步于 2011/4/21
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Embedded_System机器人发帖
【又一问题】ARM mini2440板子寄存器读写问题
jay1
2011/4/21镜像同步12 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
对地址不能这样读
用IOADDRESS()或者p2v()转化一下那个地址
这两个宏在头文件里都可以找得到
【 在 jay1 (黑色幽默) 的大作中提到: 】
: 在编写GPIO驱动程序mini2440_gpios.c中,想控制GPF IO的模式(input&output)和读其接口的数据,利用如下语句:
: #define GPGCON (*(volatile unsigned long *)0x56000060)
: #define GPGDAT (*(volatile unsigned long *)0x56000064)
: ...................
这两个函数我百度了下好像没有什么资料。。。。这个函数具体是在哪个头文件?我调用的是以下几个。。。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
我刚开始学。。。实在很菜。。。能不能说具体一点?拜托了!
【 在 ArmStrong 的大作中提到: 】
: 对地址不能这样读
: 用IOADDRESS()或者p2v()转化一下那个地址
: 这两个宏在头文件里都可以找得到
: ...................
我查找了我调用的几个头文件里,没有找到IOADDRESS()。。。
【 在 ArmStrong 的大作中提到: 】
: 对地址不能这样读
: 用IOADDRESS()或者p2v()转化一下那个地址
: 这两个宏在头文件里都可以找得到
: ...................
就是说不能直接对物理地址进行读写,要转化成虚拟地址,具体怎么转化可以参考内核里的其它代码,肯定会有很多这样的操作的
【 在 jay1 (黑色幽默) 的大作中提到: 】
: 我查找了我调用的几个头文件里,没有找到IOADDRESS()。。。
我找到了!!是ioremap函数,在ADC的驱动中有
static void __iomem *base_addr;
base_addr=ioremap(S3C2410_PA_ADC,0x20);
if (base_addr == NULL) {
printk(KERN_ERR "Failed to remap register block\n");
return -ENOMEM;
}
太感谢你了!!!!!
【 在 ArmStrong 的大作中提到: 】
: 就是说不能直接对物理地址进行读写,要转化成虚拟地址,具体怎么转化可以参考内核里的其它代码,肯定会有很多这样的操作的
: 【 在 jay1 (黑色幽默) 的大作中提到: 】
: : 我查找了我调用的几个头文件里,没有找到IOADDRESS()。。。
: ...................
这里还有一个问题,ADC驱动中有如下代码
static void __iomem *base_addr;
#define ADCCON (*(volatile unsigned long *)(base_addr + S3C2410_ADCCON)) //ADC control
#define ADCTSC (*(volatile unsigned long *)(base_addr + S3C2410_ADCTSC)) //ADC touch screen control
#define ADCDLY (*(volatile unsigned long *)(base_addr + S3C2410_ADCDLY)) //ADC start or Interval Delay
#define ADCDAT0 (*(volatile unsigned long *)(base_addr + S3C2410_ADCDAT0)) //ADC conversion data 0
#define ADCDAT1 (*(volatile unsigned long *)(base_addr + S3C2410_ADCDAT1)) //ADC conversion data 1
#define ADCUPDN (*(volatile unsigned long *)(base_addr + 0x14)) //Stylus Up/Down interrupt status
但是我在GPIO中用
#define GPIODAT (*(volatile unsigned long *)(base_addr + S3C2410_GPGDAT))
在编译驱动程序时会报错
error:invalid operands to binary +
然后无法直接对寄存器操作,只能通过ioread32(base_addr)来读。。。
求解释!先谢过了!!
PS;我还以为少添加了头文件,我把ADC驱动的所有头文件都添加进来,结果还是报错。。无奈了。。
【 在 ArmStrong 的大作中提到: 】
: 就是说不能直接对物理地址进行读写,要转化成虚拟地址,具体怎么转化可以参考内核里的其它代码,肯定会有很多这样的操作的
: 【 在 jay1 (黑色幽默) 的大作中提到: 】
: : 我查找了我调用的几个头文件里,没有找到IOADDRESS()。。。
: ...................
可以把每个你想操作的物理端口地址都ioremap一次试试....
对寄存器进行读操作用ioread(),写操作要用iowrite(),直接对寄存器进行操作是什么意思呢
在你的文件里没有S3C2410_GPGDAT的定义吧
【 在 jay1 (黑色幽默) 的大作中提到: 】
: 这里还有一个问题,ADC驱动中有如下代码
: static void __iomem *base_addr;
: #define ADCCON (*(volatile unsigned long *)(base_addr + S3C2410_ADCCON)) //ADC control
: ...................
调用ioread和iowrite不是比较慢吗?是希望说像一个变量一样,直接可以进行读写赋值。
【 在 susanbear 的大作中提到: 】
: 可以把每个你想操作的物理端口地址都ioremap一次试试....
: 对寄存器进行读操作用ioread(),写操作要用iowrite(),直接对寄存器进行操作是什么意思呢
: --
: ...................