02day led灯03_IOREAD
#include <linux/module.h> //MODULE_LICENSE("GPL");
#include <linux/init.h> //module_init module_exit
#include <linux/kernel.h> //printk
#include <linux/io.h> //ioremap iounremap
#include <linux/ioport.h> //request_mem_region
#define LED_REG_BASE 0x110002e0
#define DEVNAME "my_led"
static u32 led_reg;
// #define GPM4CON (*(volatile u32 *)led_reg)
// #define GPM4DAT (*(volatile u32 *)(led_reg + 4))
static int test_init(void)
{
int ret = 0;
printk("%s:%s:%d init\n", __FILE__, __FUNCTION__, __LINE__);
//向Linux内核中申请一段地址空间,如果之前已经有了其他的模块对该地址进行了申请,那么本次申请会失败.
//注册成功之后,那么可以在/proc/iomem 看到注册信息
//
if(!request_mem_region(LED_REG_BASE, 8 , DEVNAME)) {
printk("request_mem_region failed\n");
ret = -1;
goto err_request_mem_region;
}
led_reg = (u32)ioremap(LED_REG_BASE, 8);
//初始化
//*(volatile u32 *)led_reg
//把GPM4_0~3 设置成gpio 输出
// GPM4CON = (GPM4CON & ~0xffff) | 0x1111;
// GPM4DAT = (GPM4DAT & ~0xffff) | 0b1001;
/*
linux内核中 提供了一系列的IO操作,修改寄存器可以遵循
读 ---改---- 写
在asm/io.h中 有一些的接口操作,
ioread8
ioread16
ioread32
iowrite8
iowrite16
iowrite32(值, 地址)
*/
//一定是映射之后的地址,不能传入物理地址
u32 value = ioread32(led_reg); //读
value = (value & ~0xffff) | 0x1111; //改
iowrite32(value, led_reg);
//只读取8位
u8 stat = ioread8(led_reg + 4);
stat = (stat & ~0xf) | 0b0110;
iowrite8(stat, led_reg+4);
return 0;
err_request_mem_region:
return ret;
}
//卸载
static void test_exit(void)
{
printk("%s:%s:%d init\n", __FILE__, __FUNCTION__, __LINE__);
//释放映射的虚拟地址
iounmap((void *)led_reg);
release_mem_region(LED_REG_BASE, 8);
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL"); //加入GPL许可