在以前的文章中,有一篇
基于ARM-contexA9-Linux驱动开发:如何获取板子上独有的ID号
在那篇文章中,具体可以参考。那时候我使用了简单的字符设备驱动框架,最终的ID号通过read方法可将ID读取出来,但是,这样做就太麻烦啦,有没有更简单的方法呢?其实有,这种方法称作IO地址的映射,而今天我们要说的是IO地址的动态映射方法,静态映射就太简单了,直接调用相应的接口,配置相应的寄存器,设置状态就可以实现。接下来看看驱动代码:
#if 0
. io地址:
. 静态映射:
//这个头文件与平台相关,不同平台对应不同的gpio.h,也就是有不同的配置信息
arch/arm/mach-exynos/include/mach/gpio.h
gpio ==> S3C64XX_GPx(n)
EXYNOS4X12_GPM0()
EXYNOS4_GPD0()
int gpio_request(gpio, "name"); 申请;
void gpio_free(gpio); 撤销;
int gpio_direction_output(gpio, dat); 配置为输出, 输出1/0;
int gpio_direction_input(gpio); 配置为输入, 输入1/0;
int s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(con)); 配置为con;
void gpio_set_value(gpio, dat); 输出1/0;
int gpio_get_value(gpio); 输入1/0;
irqnum = gpio_to_irq(gpio); gpio <==> irqnum
MACH_TYPE_TINY4412
/* Initial IO mappings */
static struct map_desc exynos_iodesc[] __initdata = {
{
.virtual = (unsigned long)S5P_VA_CHIPID,
.pfn = __phys_to_pfn(EXYNOS_PA_CHIPID),
.length = SZ_4K,
.type = MT_DEVICE,
},
};
. 动态映射:
virt = ioremap(phys, size); //vmalloc_area
iounmap(virt);
//将虚拟地址转化为32位整型数
ioread32(virt);
iowrite32(val, virt);
//将虚拟地址转化为16位整型数
ioread16();
iowrite16();
//将虚拟地址转化为8位整型数
ioread8();
iowrite8();
#endif
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/atomic.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/slab.h>
//和IO相关的头文件
#include <linux/io.h>
//板子ID的物理地址 0x10000000 -----> 通过4412的手册查询到
#define CHIP_ID 0x10000000
int test_init(void)
{
int ret;
unsigned int *virt = NULL;
printk("test init\n");
//将CHIP_ID的物理地址映射成虚拟地址,分配4个字节的大小给它
virt = ioremap(CHIP_ID, 4);
//如果映射完成之后,virt指针为空,返回错误码
if(IS_ERR_OR_NULL(virt))
{
ret = -EIO;
goto ERROR_map;
}
//打印虚拟地址
printk("virt = %p\n", virt);
//打印物理地址
printk("CHIP_ID = %x\n", CHIP_ID);
//将虚拟地址转化为32位整型数
printk("*virt = %x\n", ioread32(virt));
//解除地址映射
iounmap(virt);
return 0;
ERROR_map:
return ret;
}
void test_exit(void)
{
printk("test exit\n");
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("yangyx");
MODULE_VERSION("1.1");