1、裸机LED灯实验就是操作6ULL的寄存器
2、Linux驱动开发也可以操作寄存器。Linux下不能直接对寄存器的物理地址进行读写操作,比如寄存器A物理地址为0x01010101。裸机可以直接对0x01010101的物理地址进行操作,但是在Linux下不行。因为linux会使能MMU。
在Linux里面操作的都是虚拟地址,所以需要先得到0x01010101这个物理地址所对应的虚拟地址
MMU:
①、完成虚拟内存到物理内存的映射
②、内存保护,设置存储器的访问权限
Ⅰ、ioremap函数
用于获取指定物理地址空间对应的虚拟地址
#define ioremap (cookie,size)
cookie:物理地址的起始地址
size :要转换的字节数量
例如:0x01010101开始10个地址进行转换
va = ioremap(0x01010101, 10)
Ⅱ、iounmap函数
卸载驱动时,获取的虚拟地址进行释放
#define iounmap (va)
二、LED灯字符设备驱动框架搭建#include三、应用APP搭建#include #include #include #include #include #define LED_MAJOR 200 #define LED_NAME "led" #define CCM_CCGR1_BASE (0x020C406C) #define SW_MUX_GPIO1_IO03_BASE (0x020E0068) #define SW_PAD_GPIO1_IO03_BASE (0x020E02F4) #define GPIO1_GDIR_BASE (0x0209C004) #define GPIO1_DR_BASE (0x0209C000) static void __iomem *IMX6ULL_CCM_CCGR1; static void __iomem *SW_MUX_GPIO1_IO03; static void __iomem *SW_PAD_GPIO1_IO03; static void __iomem *GPIO1_GDIR; static void __iomem *GPIO1_DR; #define LEDOFF 0 #define LEDON 1 void led_switch(u8 sta) { u32 val = 0; if(sta == LEDOFF) { val = readl(GPIO1_DR); val |= (1 << 3); writel(val, GPIO1_DR); } else if(sta == LEDON) { val = readl(GPIO1_DR); val &= ~(1 << 3); writel(val, GPIO1_DR); } } static int led_open(struct inode *inode, struct file *filp) { return 0; } static int led_release(struct inode *inode, struct file *filp) { return 0; } static ssize_t led_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { int ret; unsigned char databuf[1]; ret = copy_from_user(databuf, buf, count); if(ret < 0) { printk("kernel wirte failed"); return -EFAULT; } led_switch(databuf[0]); return 0; } static const struct file_operations led_fops = { .owner = THIS_MODULE, .write = led_write, .open = led_open, .release= led_release, }; static int __init led_init(void) { int ret = 0; int val = 0; IMX6ULL_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4); SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4); SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4); GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4); GPIO1_DR = ioremap(GPIO1_DR_BASE, 4); val = readl(IMX6ULL_CCM_CCGR1); val &= ~(3 << 26); val |= 3 << 26; writel(val, IMX6ULL_CCM_CCGR1); writel(0x5, SW_MUX_GPIO1_IO03); writel(0x10B0, SW_PAD_GPIO1_IO03); val = readl(GPIO1_GDIR); val |= 1 << 3; writel(val, GPIO1_GDIR); val = readl(GPIO1_DR); val &= ~(1 << 3); writel(val, GPIO1_DR); ret = register_chrdev(LED_MAJOR, LED_NAME, &led_fops); if(ret < 0) { printk("register chrdev failedrn"); return -EIO; } printk("len_init rn"); return 0; } static void __exit led_exit(void) { int val = 0; val = readl(GPIO1_DR); val |= (1 << 3); writel(val, GPIO1_DR); iounmap(IMX6ULL_CCM_CCGR1); iounmap(SW_MUX_GPIO1_IO03); iounmap(SW_PAD_GPIO1_IO03); iounmap(GPIO1_GDIR); iounmap(GPIO1_DR); unregister_chrdev(LED_MAJOR, LED_NAME); printk("led_exit rn"); } module_init(led_init); module_exit(led_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("zhang");
#include#include #include #include #include #include #define LEDOFF 0 #define LEDON 1 int main(int argc, char *argv[]) { int fd, ret; char *filename; filename = argv[1]; unsigned char databuf[1]; if(argc != 3) { printf("Error Usage!rn"); return -1; } fd = open(filename, O_RDWR); if(fd < 0) { printf("open failedrn"); return -1; } databuf[0] = atoi(argv[2]); ret = write(fd, databuf, sizeof(databuf)); close(fd); return 0; }



