当前位置: 首页 > news >正文

云南网站建设快速优化做模式网站

云南网站建设快速优化,做模式网站,阿里巴巴网站建设的功能定位,网站建设明细报价表使用新字符设备驱动的一般模板#xff0c;以及设备树#xff0c;驱动LED。 1、添加“stm32mp1_led”节点 打开虚拟机上“VSCode”#xff0c;点击“文件”#xff0c;点击“打开文件夹”#xff0c;点击“zgq”#xff0c;点击“linux”#xff0c;点击“atk-mp1”以及设备树驱动LED。 1、添加“stm32mp1_led”节点 打开虚拟机上“VSCode”点击“文件”点击“打开文件夹”点击“zgq”点击“linux”点击“atk-mp1”点击“linux”点击“my_linux”点击“stm32mp157d-atk.dts”。 stm32mp157d-atk.dts文件如下 /dts-v1/; #include stm32mp157.dtsi #include stm32mp15xd.dtsi #include stm32mp15-pinctrl.dtsi #include stm32mp15xxaa-pinctrl.dtsi #include stm32mp157-m4-srm.dtsi #include stm32mp157-m4-srm-pinctrl.dtsi #include stm32mp157d-atk.dtsi / { model STMicroelectronics STM32MP157D eval daughter; compatible st,stm32mp157d-ed1, st,stm32mp157; chosen { stdout-path serial0:115200n8; }; aliases { serial0 uart4; }; reserved-memory { gpu_reserved: gpuf6000000 { reg 0xf6000000 0x8000000; no-map; }; optee_memory: opteefe000000 { reg 0xfe000000 0x02000000; no-map; }; }; }; cpu1{ cpu-supply vddcore; }; gpu { contiguous-area gpu_reserved; status okay; }; optee { status okay; }; 修改后的stm32mp157d-atk.dts文件如下 /dts-v1/; #include stm32mp157.dtsi #include stm32mp15xd.dtsi #include stm32mp15-pinctrl.dtsi #include stm32mp15xxaa-pinctrl.dtsi #include stm32mp157-m4-srm.dtsi #include stm32mp157-m4-srm-pinctrl.dtsi #include stm32mp157d-atk.dtsi / { model STMicroelectronics STM32MP157D eval daughter; compatible st,stm32mp157d-ed1, st,stm32mp157; chosen { stdout-path serial0:115200n8; }; aliases { serial0 uart4; }; reserved-memory { gpu_reserved: gpuf6000000 { reg 0xf6000000 0x8000000; no-map; }; optee_memory: opteefe000000 { reg 0xfe000000 0x02000000; no-map; }; }; stm32mp1_led { compatible atkstm32mp1-led; status okay; reg 0X50000A28 0X04 /* RCC_MP_AHB4ENSETR */ 0X5000A000 0X04 /* GPIOI_MODER */ 0X5000A004 0X04 /* GPIOI_OTYPER */ 0X5000A008 0X04 /* GPIOI_OSPEEDR */ 0X5000A00C 0X04 /* GPIOI_PUPDR */ 0X5000A018 0X04 ; /* GPIOI_BSRR */ }; }; cpu1{ cpu-supply vddcore; }; gpu { contiguous-area gpu_reserved; status okay; }; optee { status okay; }; 见下图 2、编译设备树 1)、在VSCode终端输入“make dtbs回车”执行编译设备树 2)、输入“ls arch/arm/boot/uImage -l” 查看是否生成了新的“uImage”文件 3)、输入“ls arch/arm/boot/dts/stm32mp157d-atk.dtb -l” 查看是否生成了新的“stm32mp157d-atk.dtb”文件 拷贝输出的文件 4)、输入“cp arch/arm/boot/uImage /home/zgq/linux/atk-mp1/linux/bootfs/ -f回车”执行文件拷贝准备烧录到EMMC 5)、输入“cp arch/arm/boot/dts/stm32mp157d-atk.dtb /home/zgq/linux/atk-mp1/linux/bootfs/ -f回车”执行文件拷贝准备烧录到EMMC 6)、输入“cp arch/arm/boot/uImage /home/zgq/linux/tftpboot/ -f回车”执行文件拷贝准备从tftp下载 7)、输入“cp arch/arm/boot/dts/stm32mp157d-atk.dtb /home/zgq/linux/tftpboot/ -f回车”执行文件拷贝准备从tftp下载 8)、输入“ls -l /home/zgq/linux/atk-mp1/linux/bootfs/回车”查看“/home/zgq/linux/atk-mp1/linux/bootfs/”目录下的所有文件和文件夹 9)、输入“ls -l /home/zgq/linux/tftpboot/回车”查看“/home/zgq/linux/tftpboot/”目录下的所有文件和文件夹 输入“chmod 777 /home/zgq/linux/tftpboot/stm32mp157d-atk.dtb回车” 给“stm32mp157d-atk.dtb”文件赋予可执行权限 输入“chmod 777 /home/zgq/linux/tftpboot/uImage回车” ,给“uImage”文件赋予可执行权限 输入“ls /home/zgq/linux/tftpboot/回车”查看“/home/zgq/linux/tftpboot/”目录下的所有文件和文件夹 3、查看“stm32mp1_led”节点 启动开发板从网络下载程序 输入“root” 输入“cd /proc/device-tree/回车” 切换到“/sys/firmware/devicetree/base”目录 输入“ls”查看“stm32mp1_led”是否存在 输入“cd stm32mp1_led/回车” 输入“ls”查看“/sys/firmware/devicetree/base/stm32mp1_led”目录下的文件和文件夹 输入“cat compatible回车” 输入“cat name回车” 输入“cat status回车” 4、创建MyDtsLED目录 输入“cd /home/zgq/linux/Linux_Drivers/回车” 切换到“/home/zgq/linux/Linux_Drivers/” 输入“ls回车”查看“/home/zgq/linux/Linux_Drivers/” 输入“mkdir MyDtsLED回车”创建“MyDtsLED”目录 输入“ls回车”查看“/home/zgq/linux/Linux_Drivers/” 5、LED.c文件如下 #include LED.h #include linux/of_address.h //使能of_iomap() struct MyDtsLED_dev strMyDtsLED; /* 映射后的寄存器虚拟地址指针 */ static void __iomem *MPU_AHB4_PERIPH_RCC_PI; /*RCC_MP_AHB4ENSETR寄存器*/ static void __iomem *GPIOI_MODER_PI; /*GPIOx_MODER寄存器xA to K, Z*/ static void __iomem *GPIOI_OTYPER_PI;/*GPIOx_OTYPERxA to K,Z*/ static void __iomem *GPIOI_OSPEEDR_PI;/*GPIOx_OSPEEDRxA to K, Z*/ static void __iomem *GPIOI_PUPDR_PI; /*GPIOx_PUPDRxA to K, Z*/ static void __iomem *GPIOI_BSRR_PI;/*GPIOx_BSRRxA to K, Z*/ int led_ioremap(void); void led_iounmap(void); void led_Pin_Init(void); void led_switch(u8 sta); /* 寄存器地址映射 */ int led_ioremap(void) { int ret; u32 regdata[12]; const char *str; struct property *proper; /* 获取设备树中的属性数据 */ /* 1、获取设备节点stm32mp1_led */ strMyDtsLED.nd of_find_node_by_path(/stm32mp1_led); //通过全路径“/stm32mp1_led”来查找stm32mp1_led节点 //path/stm32mp1_led,“/stm32mp1_led”就是stm32mp1_led这个节点的全路径。 //返回值:返回找到的节点如果为NULL表示查找失败。 if(strMyDtsLED.nd NULL) { printk(stm32mp1_led node nost find!\r\n); return -EINVAL; } else { printk(stm32mp1_lcd node find!\r\n); } /* 2、获取compatible属性内容 */ proper of_find_property(strMyDtsLED.nd, compatible, NULL); //查找指定的属性compatible //npstrMyDtsLED.nd指定设备节点 //name“compatible“指定属性名字。 //lenpNULL不指定属性值的字节数 //返回值:返回找到的属性。 if(proper NULL) { printk(compatible property find failed\r\n); } else { printk(compatible %s\r\n, (char*)proper-value); } /* 3、获取status属性内容 */ ret of_property_read_string(strMyDtsLED.nd, status, str); //读取指定属性status的值 //npstrMyDtsLED.nd指定设备节点 //proname“status“指定属性的名字 //out_stringstr返回读到的属性值 //返回值:0读取成功负值读取失败。 if(ret 0){ printk(status read failed!\r\n); } else { printk(status %s\r\n,str); } /* 4、获取reg属性内容 */ ret of_property_read_u32_array(strMyDtsLED.nd, reg, regdata, 12); //读取指定设备节点的属性值保存到regdata[]中 //npstrMyDtsLED.nd指定设备节点 //pronamereg指定属性的名字 //out_valueregdata[]用来返回属性值数据类型为u32 //sz12表示要读取的数组元素数量为12个 //返回值:0读取成功负值读取失败其中-EINVAL表示属性不存在-ENODATA表示没有要读取的数据-EOVERFLOW 表示属性值列表太小。 if(ret 0) { printk(reg property read failed!\r\n); } else { u8 i 0; printk(reg data:\r\n); for(i 0; i 12; i) printk(%#X , regdata[i]); printk(\r\n); } MPU_AHB4_PERIPH_RCC_PI of_iomap(strMyDtsLED.nd, 0); //将“reg属性的第(01)段地址信息”转换为“虚拟地址” //npstrMyDtsLED.nd指定设备节点 //index0表示读取reg属性的第(01)段 //返回值:经过内存映射后的虚拟内存首地址如果为NULL的话则表示内存映射失败 GPIOI_MODER_PI of_iomap(strMyDtsLED.nd, 1); //将“reg属性的第(11)段地址信息”转换为“虚拟地址” //npstrMyDtsLED.nd指定设备节点 //index1表示读取reg属性的第(11)段 //返回值:经过内存映射后的虚拟内存首地址如果为NULL的话则表示内存映射失败 GPIOI_OTYPER_PI of_iomap(strMyDtsLED.nd, 2); //将“reg属性的第(21)段地址信息”转换为“虚拟地址” //npstrMyDtsLED.nd指定设备节点 //index2表示读取reg属性的第(21)段 //返回值:经过内存映射后的虚拟内存首地址如果为NULL的话则表示内存映射失败 GPIOI_OSPEEDR_PI of_iomap(strMyDtsLED.nd, 3); //将“reg属性的第(31)段地址信息”转换为“虚拟地址” //npstrMyDtsLED.nd指定设备节点 //index3表示读取reg属性的第(31)段 //返回值:经过内存映射后的虚拟内存首地址如果为NULL的话则表示内存映射失败 GPIOI_PUPDR_PI of_iomap(strMyDtsLED.nd, 4); //将“reg属性的第(41)段地址信息”转换为“虚拟地址” //npstrMyDtsLED.nd指定设备节点 //index4表示读取reg属性的第(41)段 //返回值:经过内存映射后的虚拟内存首地址如果为NULL的话则表示内存映射失败 GPIOI_BSRR_PI of_iomap(strMyDtsLED.nd, 5); //将“reg属性的第(51)段地址信息”转换为“虚拟地址” //npstrMyDtsLED.nd指定设备节点 //index5表示读取reg属性的第(51)段 //返回值:经过内存映射后的虚拟内存首地址如果为NULL的话则表示内存映射失败 return 0; } /*取消“寄存器地址映射”*/ void led_iounmap(void) { iounmap(MPU_AHB4_PERIPH_RCC_PI); iounmap(GPIOI_MODER_PI); iounmap(GPIOI_OTYPER_PI); iounmap(GPIOI_OSPEEDR_PI); iounmap(GPIOI_PUPDR_PI); iounmap(GPIOI_BSRR_PI); } void led_Pin_Init(void) { u32 val 0; /* 2、使能RCC时钟 */ val readl(MPU_AHB4_PERIPH_RCC_PI);/* 读RCC_MP_AHB4ENSETR寄存器 */ val ~(0X1 8);/* 清除以前的bit8设置 */ val | (0X1 8); /* 设置新的bit8值 */ writel(val, MPU_AHB4_PERIPH_RCC_PI); /* 将val的值写入RCC_MP_AHB4ENSETR寄存器 */ /* 3、将PI0输出引脚。*/ val readl(GPIOI_MODER_PI);/*读GPIOI_MODER寄存器*/ val ~(0X3 0); /* bit0:1清零 */ val | (0X1 0); /* bit0:1设置01配置为输出模式 */ writel(val, GPIOI_MODER_PI); /* 将val的值写入GPIOI_MODER寄存器 */ /* 4、设置PI0为推挽模式 */ val readl(GPIOI_OTYPER_PI);/*读GPIOI_OTYPER寄存器*/ val ~(0X1 0); /* bit0清零设置为上拉*/ writel(val, GPIOI_OTYPER_PI); /* 将val的值写入GPIOI_OTYPER寄存器 */ /* 5、设置PI0为极高速 */ val readl(GPIOI_OSPEEDR_PI);/*读GPIOI_OSPEEDR寄存器*/ val ~(0X3 0); /* bit0:1 清零 */ val | (0x3 0); /* bit0:1 设置为11极高速*/ writel(val, GPIOI_OSPEEDR_PI); /* 将val的值写入GPIOI_OSPEEDR寄存器 */ /* 6、设置PI0为上拉。*/ val readl(GPIOI_PUPDR_PI);/*读GPIOI_PUPDR寄存器*/ val ~(0X3 0); /* bit0:1 清零*/ val | (0x1 0); /*bit0:1 设置为01配置为上拉*/ writel(val,GPIOI_PUPDR_PI); /* 将val的值写入GPIOI_PUPDR寄存器 */ /* 6、默认打开LEDPI00 */ val readl(GPIOI_BSRR_PI);/*读GPIOI_BSRR寄存器*/ val ~(0X1 16); /* bit16 清零*/ val | (0x1 16); /*bit16 设置为1令PI0输出低电平*/ writel(val, GPIOI_BSRR_PI); /* 将val的值写入GPIOI_BSRR寄存器 */ /* 6、默认关闭LEDPI01 */ val readl(GPIOI_BSRR_PI);/*读GPIOI_BSRR寄存器*/ val ~(0X1 0); /* bit0 清零*/ val | (0x1 0);/*bit0 设置为1令PI0输出高电平*/ writel(val, GPIOI_BSRR_PI); /* 将val的值写入GPIOI_BSRR寄存器 */ } void led_switch(u8 sta) { u32 val 0; if(sta LEDON) { val readl(GPIOI_BSRR_PI);/*读GPIOI_BSRR寄存器*/ val ~(0X1 16); /* bit16 清零*/ val | (0x1 16); /*bit16 设置为1令PI0输出低电平*/ writel(val, GPIOI_BSRR_PI); /* 将val的值写入GPIOI_BSRR寄存器 */ } else if(sta LEDOFF) { val readl(GPIOI_BSRR_PI);/*读GPIOI_BSRR寄存器*/ val ~(0X1 0); /* bit0 清零*/ val | (0x1 0);/*bit0 设置为1令PI0输出高电平*/ writel(val, GPIOI_BSRR_PI); /* 将val的值写入GPIOI_BSRR寄存器 */ } } 6、LED.h程序如下 #ifndef __LED_H #define __LED_H #include linux/types.h /* 数据类型重命名 使能bool,u8,u16,u32,u64, uint8_t, uint16_t, uint32_t, uint64_t 使能s8,s16,s32,s64,int8_t,int16_t,int32_t,int64_t */ #include linux/cdev.h //使能cdev结构 #include linux/device.h//使能class结构和device结构 #include linux/of.h    //使能device_node结构 #define LEDOFF 0 /* 关灯 */ #define LEDON 1 /* 开灯 */ struct MyDtsLED_dev{ dev_t devid; /*声明32位变量devid用来给保存设备号 */ int major; /* 主设备号 */ int minor; /* 次设备号 */ struct cdev  cdev; /*字符设备结构变量cdev */ struct class *class; /* 类 */ struct device *device;/*设备*/ struct device_node *nd;/* 设备节点 */ }; extern struct MyDtsLED_dev strMyDtsLED; extern int led_ioremap(void); extern void led_iounmap(void); extern void led_Pin_Init(void); extern void led_switch(u8 sta); #endif 7、LEDInterface.c程序如下 #include LED.h #include linux/types.h //数据类型重命名 //使能bool,u8,u16,u32,u64, uint8_t, uint16_t, uint32_t, uint64_t //使能s8,s16,s32,s64,int8_t,int16_t,int32_t,int64_t #include linux/kernel.h #include linux/delay.h #include linux/ide.h #include linux/init.h #include linux/module.h #include linux/string.h #include linux/cdev.h //使用字符设备结构 #include linux/mdev.h #define MyDtsLED_CNT    1   //定义设备数量为1 #define MyDtsLED_NAME  MyDtsLEDName//定义设备的名字 /* 打开设备 */ static int MyDtsLED_open(struct inode *inode, struct file *filp) { filp-private_data strMyDtsLED; /* 设置私有数据 */ printk(MyDtsLED_open!\r\n); return 0; } /* 从设备读取数据保存到首地址为buf的数据块中长度为cnt个字节 */ //file结构指针变量flip表示要打开的设备文件 //buf表示用户数据块的首地址 //cnt表示用户数据的长度单位为字节 //loff_t结构指针变量offt表示“相对于文件首地址的偏移” static ssize_t MyDtsLED_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) { return 0; } /* 向设备写数据将数据块首地址为buf的数据长度为cnt个字节发送给用户 */ //file结构指针变量flip表示要打开的设备文件 //buf表示用户数据块的首地址 //cnt表示用户数据的长度单位为字节 //loff_t结构指针变量offt表示“相对于文件首地址的偏移” static ssize_t MyDtsLED_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt) { int ret 0; unsigned char databuf[1]; unsigned char ledstat; ret copy_from_user(databuf, buf, cnt); if(ret 0){ printk(kernel write failed!\r\n); ret -EFAULT; } ledstat databuf[0];/*获取到应用传递进来的开关灯状态*/ led_switch(ledstat);/*执行开灯或执行关灯*/ return ret; } /* 关闭/释放设备 */ static int MyDtsLED_release(struct inode *inode, struct file *filp) { /* 用户实现具体功能 */ printk(MyDtsLED_release!\r\n); return 0; } /*声明file_operations结构变量MyCharDevice_fops*/ /*它是指向设备的操作函数集合变量*/ const struct file_operations MyDtsLED_fops { .owner THIS_MODULE, .open MyDtsLED_open, .read MyDtsLED_read, .write MyDtsLED_write, .release MyDtsLED_release, }; /*驱动入口函数 */ static int  __init MyDtsLED_init(void) { int ret; /* 1、寄存器地址映射 */ led_ioremap();//寄存器地址映射 led_Pin_Init();//LED灯引脚初始化 /*2、申请设备号*/ strMyDtsLED.major0; if(strMyDtsLED.major)/*如果指定了主设备号*/ { strMyDtsLED.devid MKDEV(strMyDtsLED.major, 0); //输入参数strMyDtsLED.major为“主设备号” //输入参数0为“次设备号”大部分驱动次设备号都选择0 //将strMyDtsLED.major左移20位再与0相或就得到“Linux设备号” retregister_chrdev_region(strMyDtsLED.devid, MyDtsLED_CNT, MyDtsLED_NAME); //strMyDtsLED.devid表示起始设备号 //MyDtsLED_CNT表示次设备号的数量 //MyDtsLED_NAME表示设备名 if(ret 0) goto fail_map; } else { /* 没有定义设备号 */ retalloc_chrdev_region(strMyDtsLED.devid, 0, MyDtsLED_CNT,MyDtsLED_NAME); /* 申请设备号 */ //strMyDtsLED.devid保存申请到的设备号 //0次设备号的起始地址 //MyDtsLED_CNT要申请的次设备号数量 //MyDtsLED_NAME表示“设备名字” if(ret 0) goto fail_map; strMyDtsLED.major MAJOR(strMyDtsLED.devid); /* 获取分配号的主设备号 */ //输入参数strMyDtsLED.devid为“Linux设备号” //将strMyDtsLED.devid右移20位得到“主设备号” strMyDtsLED.minor MINOR(strMyDtsLED.devid); /* 获取分配号的次设备号 */ //输入参数strMyDtsLED.devid为“Linux设备号” //将strMyDtsLED.devid与0xFFFFF相与后得到“次设备号” } /*3、注册字符设备*/ strMyDtsLED.cdev.owner THIS_MODULE; //使用THIS_MODULE将owner指针指向当前这个模块 cdev_init(strMyDtsLED.cdev,MyDtsLED_fops); //注册字符设备初始化“字符设备结构变量strMyDtsLED.cdev” //strMyDtsLED.cdev是等待初始化的结构体变量 //MyDtsLED_fops就是字符设备文件操作函数集合 /*4、添加字符设备*/ retcdev_add(strMyDtsLED.cdev,strMyDtsLED.devid,MyDtsLED_CNT); //添加字符设备 /*strMyDtsLED.cdev表示指向要添加的字符设备即字符设备结构strMyDtsLED.cdev变量*/ //strMyDtsLED.devid表示设备号 //MyDtsLED_CNT表示需要添加的设备数量 if(ret 0 ) //添加字符设备失败 goto del_register; printk(dev id major %d,minor %d\r\n, strMyDtsLED.major, strMyDtsLED.minor); printk(MyDtsLED_init is ok!!!\r\n); /*5、自动创建设备节点 */ strMyDtsLED.class class_create(THIS_MODULE, MyDtsLED_NAME); if (IS_ERR(strMyDtsLED.class)){ goto del_cdev; } /*6、创建设备 */ strMyDtsLED.device device_create(strMyDtsLED.class, NULL, strMyDtsLED.devid, NULL, MyDtsLED_NAME); //创建设备 //设备要创建在strMyDtsLED.class类下面 //NULL表示没有父设备 //strMyDtsLED.devid是设备号; //参数drvdataNULL设备没有使用数据 //MyDtsLED_NAME是设备名字 //如果设置fmtMyDtsLED_NAME 的话就会生成/dev/MyDtsLED_NAME设备文件。 //返回值就是创建好的设备。 if (IS_ERR(strMyDtsLED.device)){ goto destroy_class; } return 0; destroy_class: class_destroy(strMyDtsLED.class); //删除类 //strMyDtsLED.class就是要删除的类 del_cdev: cdev_del(strMyDtsLED.cdev); //删除字符设备 //strMyDtsLED.cdev表示指向需要删除的字符设备即字符设备结构strMyDtsLED.cdev变量 del_register: unregister_chrdev_region(strMyDtsLED.devid, MyDtsLED_CNT); /* 释放设备号 */ //strMyDtsLED.devid需要释放的起始设备号 //MyDtsLED_CNT需要释放的次设备号数量 fail_map://申请设备号失败 /*若有释放的内存则释放内存*/ led_iounmap(); return -EIO; } /*驱动出口函数 */ static void __exit MyDtsLED_exit(void) { /*1、释放内存*/ led_iounmap(); /*2、 释放设备号 */ unregister_chrdev_region(strMyDtsLED.devid, MyDtsLED_CNT); /*释放设备号 */ //strMyDtsLED.devid需要释放的起始设备号 //MyDtsLED_CNT需要释放的次设备号数; /*3、删除字符设备*/ cdev_del(strMyDtsLED.cdev); /*删除字符设备*/ /*strMyDtsLED.cdev表示指向需要删除的字符设备即字符设备结构strMyDtsLED.cdev变量*/ /*4、 删除设备 */ device_destroy(strMyDtsLED.class, strMyDtsLED.devid); //删除创建的设备 //newchrled.class是要删除的设备所处的类 //newchrled.devid是要删除的设备号 /*5、删除类*/ class_destroy(strMyDtsLED.class); //删除类 //strMyDtsLED.class就是要删除的类 } module_init(MyDtsLED_init); //指定MyDtsLED_init()为驱动入口函数 module_exit(MyDtsLED_exit); //指定MyDtsLED_exit()为驱动出口函数 MODULE_AUTHOR(Zhanggong);//添加作者名字 MODULE_LICENSE(GPL);//LICENSE采用“GPL协议” MODULE_INFO(intree,Y); //去除显示“loading out-of-tree module taints kernel.” 8、LED_APP.c文件如下 #include stdio.h #include unistd.h #include sys/types.h #include sys/stat.h #include fcntl.h #include stdlib.h #include string.h //APP运行命令:./LED_APP filename 1|0如果是1表示打开LED如果是0表示关闭LED #define LEDOFF 0 /* 关灯 */ #define LEDON 1 /* 开灯 */ /* 参数argc: argv[]数组元素个数 参数argv[]:是一个指针数组 返回值: 0 成功;其他 失败 */ int main(int argc, char *argv[]) { int fd, retvalue; char *filename; unsigned char databuf[1]; if(argc ! 3) { printf(Error Usage!\r\n); return -1; } //argv[]是指向输入参数“./LED_App” “/dev/LMyNewLEDName” “1” filename argv[1]; //argv[1]指向字符串“/dev/MyNewLEDName” fd open(filename, O_RDWR); //如果打开“/dev/MyNewLEDName”文件成功则fd为“文件描述符” //fd0表示关灯 fd1表示开灯 if(fd 0) { printf(Cant open file %s\r\n, filename); return -1; } databuf[0] atoi(argv[2]); /* 写入的数据是数字的表示打开或关闭 */ retvalue write(fd, databuf, 1); //将databuf[]中前1个字节发送给用户 //返回值大于0表示写入的字节数 //返回值等于0表示没有写入任何数据 //返回值小于0表示写入失败 if(retvalue 0) { printf(write file %s failed!\r\n, filename); close(fd); //fd表示要关闭的“文件描述符” //返回值等于0表示关闭成功 //返回值小于0表示关闭失败 return -1; } /* 关闭设备 */ retvalue close(fd); //fd表示要关闭的“文件描述符” //返回值等于0表示关闭成功 //返回值小于0表示关闭失败 if(retvalue 0) { printf(Cant close file %s\r\n, filename); return -1; } return 0; } 9、Makefile文件如下 KERNELDIR : /home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31 #使用“:”将其后面的字符串赋值给KERNELDIR CURRENT_PATH : $(shell pwd) #采用“shell pwd”获取当前打开的路径 #使用“$(变量名)”引用“变量的值” MyAPP : LED_APP MyNewLED_Module-objs LEDInterface.o LED.o obj-m : MyNewLED_Module.o CC : arm-none-linux-gnueabihf-gcc drv: $(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) modules app: $(CC)  $(MyAPP).c  -o $(MyAPP) clean: $(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) clean rm $(MyAPP) install: sudo cp *.ko $(MyAPP) /home/zgq/linux/nfs/rootfs/lib/modules/5.4.31/ -f 10、添加“c_cpp_properties.json” 按下“CtrlShiftP”,打开VSCode控制台然后输入“C/C:Edit Configurations(JSON)”,打开以后会自动在“.vscode ”目录下生成一个名为“c_cpp_properties.json” 的文件。 修改c_cpp_properties.json内容如下所示: { configurations: [ { name: Linux, includePath: [ ${workspaceFolder}/**, /home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31, /home/zgq/linux/Linux_Drivers/MyDtsLED, /home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31/arch/arm/include, /home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31/include, /home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31/arch/arm/include/generated ], defines: [], compilerPath: /usr/bin/gcc, cStandard: gnu11, cppStandard: gnu14, intelliSenseMode: gcc-x64 } ], version: 4 } 11、编译 输入“make clean回车” 输入“make drv回车” 输入“make app回车” 输入“make install回车” 输入“ls /home/zgq/linux/nfs/rootfs/lib/modules/5.4.31/ -l回车”产看是存在“LED_APP和MyDtsLED_Module.ko” 12、测试 启动开发板从网络下载程序 输入“root” 输入“cd /lib/modules/5.4.31/回车” 切换到“/lib/modules/5.4.31/”目录 注意“lib/modules/5.4.31/”在虚拟机中是位于“/home/zgq/linux/nfs/rootfs/”目录下但在开发板中却是位于根目录中。 输入“ls -l”查看“MyDtsLED_Module.ko和LED_APP”是否存在 输入“depmod”,驱动在第一次执行时需要运行“depmod” 输入“modprobe MyDtsLED_Module.ko”加载“MyDtsLED_Module.ko”模块 输入“lsmod”查看有哪些驱动在工作 输入“ls /dev/MyDtsLEDName -l回车”发现节点文件“/dev/MyDtsLEDName” 输入“./LED_APP /dev/MyDtsLEDName 1回车”执行开灯 输入“./LED_APP /dev/MyDtsLEDName 0回车”执行关灯 输入“rmmod MyDtsLED_Module.ko”卸载“MyDtsLED_Module.ko”模块 注意:输入“rmmod MyDtsLED_Module”也可以卸载“MyDtsLED_Module.ko”模块 输入“lsmod”查看有哪些驱动在工作。 输入“ls /dev/MyDtsLEDName -l回车”查询节点文件“/dev/MyDtsLEDName”是否存在
http://www.pierceye.com/news/65660/

相关文章:

  • 做简历网站 知乎上海公司做网站
  • 做盗版网站违法吗网页设置安全站点
  • 龙华网站建设的基本步骤wordpress怎么实现社交
  • 沈阳网站备案查询网站建设与管理实训课程
  • 网站设计 分辨率上海工作网站
  • 宁德市城乡建设网站做外汇看的网站
  • 网站名怎么写做衣服网站的实验感想
  • 三明住房建设局网站物业公司网站设计
  • 企业创建网站的途径都有啥建筑业招聘网站
  • 优化推广网站淄博如何加强校园网站建设
  • 瑞安机械网站建设邵阳市中高风险地区
  • 将自己做的网站发布到网上做株洲网站需要多少钱
  • 家居行业网站建设产品故事软文案例
  • 网站首页备案号链接秦皇岛建设局招标网
  • 免费网站app源码免费咨询法律律师电话号码
  • wordpress+论坛+注册seo百度seo排名优化软件
  • 网站建设用什么程序wordpress迁移器
  • 下陆区建设局网站400元做网站送网推
  • 营销型网站核心要素有哪些优秀集团网站案例
  • 青岛建站模板厂家做公众号商城原型的网站
  • 免费公司介绍网站怎么做网站在线交谈
  • 做图的网站网站的首页面设计
  • 长沙专业个人做网站哪家好wordpress 邮件服务
  • 网站建设中页面下载湘潭网站公司
  • 重庆市建设工程造价信息网官方网站改版影响seo吗
  • 哪个做网站公司河南省十大互联网企业
  • 南通网站网店怎么开视频教程
  • 2网站建设公司做网站商城多少钱
  • 杭州下城网站建设网页设计摘要内容
  • 怎么给企业做网站上海公司注册一站式企业服务