本帖最后由 沐唐 于 2022-1-22 16:09 编辑
1、 编写内核驱动
- #include<linux/kernel.h>#include <linux/init.h>
- #include <linux/fs.h>
- #include <asm/io.h>
- #include <linux/uaccess.h>
- #include <linux/cdev.h>
- #include <linux/module.h>
- #include <linux/slab.h>
- static unsigned long *gpm4con;
- static unsigned long *gpm4dat;
- static struct cdev *pcdev;
- static dev_t dev_no;
- <p style="text-indent: 2em;">static int mycdev_open(structinode *inodp, struct file *filp){</p><p style="text-indent: 2em;"> printk("Hello ,This is a open !\n");</p> //led的初始化
- //申请空间 0xB8003000+0x140
- <p style="text-indent: 2em;"> gpm4con =ioremap(0xB8003000+0x140,8);</p> gpm4dat = gpm4con+1;
- //配置端口为输出 PF10 13 14
- <p style="text-indent: 2em;"> *gpm4con |=1<<10|1<<13|1<<14;</p> return 0;
- }
- <p style="text-indent: 2em;">static ssize_t mycdev_write (struct file *filp, const char __user*buffer, size_t t, loff_t *offset){</p><p style="text-indent: 2em;"> unsigned char buf[20]={0};</p><p style="text-indent: 2em;"> copy_from_user(buf,buffer,t);</p><p style="text-indent: 2em;"> printk("Hello ,This is a write !\n");</p><p style="text-indent: 2em;"> if(!strncmp(buf,"ledon",strlen(buf))){</p><p style="text-indent: 2em;"> *gpm4dat&= ~(1<<10|1<<13|1<<14);</p> }
- <p style="text-indent: 2em;"> else if(!strncmp(buf,"ledoff",strlen(buf)))</p><p style="text-indent: 2em;"> *gpm4dat |=1<<10|1<<13|1<<14;</p> return 0;
- }
- <p style="text-indent: 2em;">static ssize_t mycdev_read (struct file *filp, char __user *buffer,size_t t, loff_t *offset){</p><p style="text-indent: 2em;"> printk("Hello ,This is a read !\n");</p><p style="text-indent: 2em;"> //copy_to_user(buffer,form, n);</p> return 0;
- }
- static int mycdev_close(struct inode *inodp, struct file *filp){
- <p style="text-indent: 2em;"> printk("Hello ,This is a close !\n");</p>
- iounmap(gpm4con);
- return 0;
- }
- static struct file_operations myops={
- .owner = THIS_MODULE,
- .open = mycdev_open,
- .read = mycdev_read,
- .write = mycdev_write,
- .release = mycdev_close,
- };
- static int __init mycedev_init(void){
- //分配cdev空间
- pcdev = cdev_alloc();
- //分配设备号,次设备从0开始,分配2个
- <p style="text-indent: 2em;"> alloc_chrdev_region(&dev_no,0,2,"mycdev");</p> //初始化结构体
- cdev_init(pcdev,&myops);
- //设备注册
- cdev_add(pcdev,dev_no,2);
- //直接打印主设备号,方便注册
- <p style="text-indent: 2em;"> //major =MAJOR(dev_no);</p><p style="text-indent: 2em;"> printk("major =%d \n", MAJOR(dev_no));</p>
- return 0;
- }
- static void __exit mycedev_exit(void){
- //取消设备注册
- cdev_del(pcdev);
- unregister_chrdev_region(dev_no,2);
- kfree(pcdev);
- <p style="text-indent: 2em;"> printk("mycdev isexit \n"); </p>}
- module_init(mycedev_init);
- module_exit(mycedev_exit);
- MODULE_LICENSE("GPL");
复制代码
2、编写app
#include<fcntl.h>#include <string.h>
#include <stdio.h>
#define LEDON "ledon"
#define LEDOFF "ledoff"
int main(){
int fd =open("/dev/mycdev", O_RDWR); if(fd < 0){
printf("openleds device is failed !\r\n"); return -1;
}
while(1)
{
write(fd,LEDON, strlen(LEDON)+1); sleep(1);
write(fd,LEDOFF, strlen(LEDON)+1); sleep(1);
}
close(fd);
return 0;
}
3、编写makefile- <p style="text-indent: 2em;">obj-m:= mycdev.o</p>
- KDIR := /tjk/tjk/nuc970bsp/linux-3.10.x
- all :
- <p style="text-indent: 2em;"> make -C $(KDIR)M=$(PWD) modules</p><p style="text-indent: 2em;"> rm -rf *.cmd *.o*.symvers *.order *.mod.* *.unsigned</p> app :
- <p style="text-indent: 2em;"> arm-linux-gcc ledapp.c-o ledapp</p>
复制代码
注意:1、 MAJOR(dev_no)返回主设备号
2、 Mknod /dev/mycdev c 253 0 创建设备文件
Cat /proc/devices 查看主设备号
|