之前讲过映射硬件,可以看一下: 现在用动态的映射
动态映射操作LED
1、建立动态映射
首先使用request_mem_region()函数向内核申请需要映射的内存资源。
然后使用ioremap()函数来实现映射,传给它一个物理地址,返回一个虚拟地址。
也就是说,要先申请(不一定申请成功),然后再映射,然后再使用。
2、销毁动态映射
首先使用iounmap()函数解除映射,然后使用release_mem_region()函数释放申请。
也就是说,使用完要解除映射时,先解除映射,然后再释放申请。
原来的:
static int __init chrdev_init(void)
{
.....
.....
.....
if (!request_mem_region(GPJ0CON_PA, 4, "GPJ0CON"))
return -EINVAL;
if (!request_mem_region(GPJ0DAT_PA, 4, "GPJ0CON"))
return -EINVAL;
pGPJ0CON = ioremap(GPJ0CON_PA, 4);
pGPJ0DAT = ioremap(GPJ0DAT_PA, 4);
*pGPJ0CON = 0x11111111;
*pGPJ0DAT = ((0<<3) | (0<<4) | (0<<5)); // 亮
....
....
}
static void __exit chrdev_exit(void)
{
printk(KERN_INFO "chrdev_exit helloworld exit\n");
*pGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));
// 解除映射
iounmap(pGPJ0CON);
iounmap(pGPJ0DAT);
release_mem_region(GPJ0CON_PA, 4);
release_mem_region(GPJ0DAT_PA, 4);
// 使用新的接口来注销字符设备驱动
// 第一步真正注销字符设备驱动用cdev_del
cdev_del(&test_cdev);
// 第二步去注销申请的主次设备号
unregister_chrdev_region(mydev, MYCNT);
}
动态映射结构体方式:(最好用这种方式)
static int __init chrdev_init(void)
{
...
...
...
// 2步完成了映射
if (!request_mem_region(GPJ0_REGBASE, sizeof(gpj0_reg_t), "GPJ0REG"))
return -EINVAL;
pGPJ0REG = ioremap(GPJ0_REGBASE, sizeof(gpj0_reg_t));
// 映射之后用指向结构体的指针来进行操作
// 指针使用->结构体内元素的方式来操作各个寄存器
pGPJ0REG->gpj0con = 0x11111111;
pGPJ0REG->gpj0dat = ((0 << 3) | (0 << 4) | (0 << 5)); // 亮
return 0;
}
static void __exit chrdev_exit(void)
{
printk(KERN_INFO "chrdev_exit helloworld exit\n");
// *pGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));
pGPJ0REG->gpj0dat = ((1 << 3) | (1 << 4) | (1 << 5));
// 解除映射
/* 原来的
iounmap(pGPJ0CON);
iounmap(pGPJ0DAT);
release_mem_region(GPJ0CON_PA, 4);
release_mem_region(GPJ0DAT_PA, 4);
*/ 动态映射方式
iounmap(pGPJ0REG);
release_mem_region(GPJ0_REGBASE, sizeof(gpj0_reg_t));
// 在module_exit宏调用的函数中去注销字符设备驱动
unregister_chrdev(mymajor, MYNAME);
}
内核提供的读写寄存器接口
为了增加可移植性,内核提供的寄存器读写接口:
(1)writel和readl
(2)iowrite32和ioread32
(1)和(2)没有什么本质上的差异
writel:
功能:writel() 函数往内存映射的 I/O 空间上写入32位(4字节)数据。
参数:
data:要写入的一个字节的数据.
addr:32位I/O 地址。
readl
功能:readl() 函数从内存映射的 I/O 空间读取32位(4字节)数据。
参数
addr :I/O 地址。
返回值 : 从 I/O 空间读取的数值。