网站开发的结构图做网站的图片一般放哪

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

网站开发的结构图,做网站的图片一般放哪,网站推广策划方案3000字,网站效果图用什么做使用原子操作来实现“互斥访问”LED灯设备#xff0c;目的是每次只允许一个应用程序使用LED灯。 1、创建MyAtomicLED目录 输入“cd /home/zgq/linux/Linux_Drivers/回车” 切换到“/home/zgq/linux/Linux_Drivers/”目录 输入“mkdir MyAtomicLED回车”#xff0c;创建MyA…使用原子操作来实现“互斥访问”LED灯设备目的是每次只允许一个应用程序使用LED灯。 1、创建MyAtomicLED目录 输入“cd /home/zgq/linux/Linux_Drivers/回车” 切换到“/home/zgq/linux/Linux_Drivers/”目录 输入“mkdir MyAtomicLED回车”创建MyAtomicLED目录 输入“ls回车”查看“/home/zgq/linux/Linux_Drivers/”目录下的文件和文件夹 2、添加gpio_led节点 若在stm32mp157d-atk.dts文件中的根节点下没有gpio_led节点则添加gpio_led节点 3、编译设备树 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/”目录下的所有文件和文件夹 4、创建LED.c #include LED.h #include linux/gpio.h //使能gpio_request(),gpio_free(),gpio_direction_input(), //使能gpio_direction_output(),gpio_get_value(),gpio_set_value() #include linux/of_gpio.h //使能of_gpio_named_count(),of_gpio_count(),of_get_named_gpio() struct MyAtomicLED_dev  strMyAtomicLED; int Get_gpio_num(void); int led_GPIO_request(void); void led_switch(u8 sta,struct MyAtomicLED_dev *dev); int Get_gpio_num(void) { int ret 0; const char str; / 设置LED所使用的GPIO / / 1、获取设备节点strMyAtomicLED / strMyAtomicLED.nd of_find_node_by_path(/gpio_led); //path/gpio_led使用“全路径的节点名“在“stm32mp157d-atk.dts“中查找节点“gpio_led” //返回值:返回找到的节点如果为NULL表示查找失败。 if(strMyAtomicLED.nd NULL) { printk(gpio_led node not find!\r\n); return -EINVAL; } / 2.读取status属性 / ret of_property_read_string(strMyAtomicLED.nd, status, str); //在gpio_led节点中status okay; //指定的设备节点strMyAtomicLED.nd //pronamestatus给定要读取的属性名字 //out_stringstr:返回读取到的属性值 //返回值:0读取成功负值读取失败。 if(ret 0) return -EINVAL; if (strcmp(str, okay)) return -EINVAL; //strcmp(s1,s2),当s1s2时返回值为负数 //strcmp(s1,s2),当s12时返回值为正数 //strcmp(s1,s2),当s1s2时返回值为0 / 3、获取compatible属性值并进行匹配 / ret of_property_read_string(strMyAtomicLED.nd, compatible, str); //在gpio_led节点中compatible zgq,led; //指定的设备节点strMyAtomicLED.nd //pronamecompatible给定要读取的属性名字 //out_stringstr:返回读取到的属性值 //返回值:0读取成功负值读取失败。 if(ret 0) { printk(gpio_led node: Failed to get compatible property\n); return -EINVAL; } if (strcmp(str, zgq,led)) { printk(gpio_led node: Compatible match failed\n); return -EINVAL; } / 4、 根据设备树中的led-gpio属性得到LED所使用的LED编号 */ strMyAtomicLED.led_gpio of_get_named_gpio(strMyAtomicLED.nd, led-gpio, 0); //在gpio_led节点中led-gpio gpioi 0 GPIO_ACTIVE_LOW //npstrMyAtomicLED.nd,指定的“设备节点” //propnameled-gpio给定要读取的属性名字 //Index0,给定的GPIO索引为0 //返回值正值获取到的GPIO编号负值失败。 if(strMyAtomicLED.led_gpio 0) { printk(cant get led-gpio); return -EINVAL; } printk(led-gpio num %d\r\n, strMyAtomicLED.led_gpio); //打印结果为“led-gpio num 128“ //因为GPIO编号是从0开始的GPIOI端口的序号是8每个端口有16个IO口因此GPIOI0的编号为816128 return 0; } int led_GPIO_request(void) { int ret 0; / 5.向gpio子系统申请使用“gpio编号” / ret gpio_request(strMyAtomicLED.led_gpio, LED-GPIO); //gpiostrMyAtomicLED.led_gpio指定要申请的“gpio编号” //IabelLED-GPIO给这个gpio引脚设置个名字为LED-GPIO //返回值0申请“gpio编号”成功;其他值申请“gpio编号”失败 if (ret) { printk(KERN_ERR strMyAtomicLED: Failed to request led-gpio\n); return ret; } / 6、设置PI0为输出并且输出高电平默认关闭LED灯 */ ret gpio_direction_output(strMyAtomicLED.led_gpio, 1); //gpiostrMyAtomicLED.led_gpio,指定的“gpio编号”这里是128对应的是GI0引脚 //value1设置引脚输出高电平 //返回值0设置“引脚输出为vakued的值”成功;负值设置“引脚输出为vakued的值”失败。 if(ret 0) { printk(cant set gpio!\r\n); } return 0; } void led_switch(u8 sta,struct MyAtomicLED_dev dev) { if(sta LEDON) { gpio_set_value(dev-led_gpio, 0); / 打开LED灯 / } else if(sta LEDOFF) { gpio_set_value(dev-led_gpio, 1); / 关闭LED灯 / } } 5、创建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/cdev.h //使能class结构和device结构 #include linux/of.h   //使能device_node结构 #define LEDOFF 0 / 关灯 / #define LEDON 1 / 开灯 */ struct MyAtomicLED_dev{ dev_t devid; /声明32位变量devid用来给保存设备号/ int major;   /主设备号/ int minor;   /次设备号/ struct cdev  cdev; /*字符设备结构变量cdev */ struct class *class;     // struct device *device;  /设备/ struct device_node *nd; /设备节点/ int led_gpio;   /led所使用的GPIO编号/ atomic_t lock;  /原子变量/ }; extern struct MyAtomicLED_dev strMyAtomicLED; extern int Get_gpio_num(void); extern int led_GPIO_request(void); extern void led_switch(u8 sta,struct MyAtomicLED_dev dev); #endif 6、创建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/ide.h //使能copy_from_user(),copy_to_user() #include linux/module.h //使能MyAtomicLED_init(),MyAtomicLED_exit() #include linux/gpio.h //使能gpio_request(),gpio_free(),gpio_direction_input(), //gpio_direction_output(),gpio_get_value(),gpio_set_value() #define MyAtomicLED_CNT    1   //定义设备数量为1 #define MyAtomicLED_NAME  MyAtomicLEDName  //定义设备的名字 / 打开设备 */ static int MyAtomicLED_open(struct inode *inode, struct file *filp) { /通过判断原子变量的值来检查LED有没有被别的应用使用/ if (!atomic_dec_and_test(strMyAtomicLED.lock)) { //当strMyAtomicLED.lock.counter1时atomic_dec_and_test()返回1 //从strMyAtomicLED.lock.counter减1如果结果为0就返回1否则返回0; atomic_inc(strMyAtomicLED.lock);/小于0的话就加1,使其原子变量等于0/ return -EBUSY; /* LED被使用返回忙*/ } filp-private_data strMyAtomicLED; /设置私有数据/ printk(MyAtomicLED_open!\r\n); return 0; } /* 从设备读取数据保存到首地址为buf的数据块中长度为cnt个字节 */ //file结构指针变量flip表示要打开的设备文件 //buf表示用户数据块的首地址 //cnt表示用户数据的长度单位为字节 //loff_t结构指针变量offt表示“相对于文件首地址的偏移” static ssize_t MyAtomicLED_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 MyAtomicLED_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); //将buf[]中的前cnt个字节拷贝到databuf[]中 if(ret 0){ printk(kernel write failed!\r\n); ret -EFAULT; } ledstat databuf[0];/获取到应用传递进来的开关灯状态/ led_switch(ledstat,filp-private_data);/执行开灯或执行关灯/ return ret; } /* 关闭/释放设备 */ static int MyAtomicLED_release(struct inode *inode, struct file *filp) { struct MyAtomicLED_dev *dev filp-private_data; atomic_inc(dev-lock); /关闭驱动文件的时候释放原子变量便于其它线程使用/ printk(MyAtomicLED_release!\r\n); return 0; } /声明file_operations结构变量MyCharDevice_fops/ /它是指向设备的操作函数集合变量/ const struct file_operations MyAtomicLED_fops { .owner THIS_MODULE, .open MyAtomicLED_open, .read MyAtomicLED_read, .write MyAtomicLED_write, .release MyAtomicLED_release, }; /*驱动入口函数 */ static int  __init MyAtomicLED_init(void) { int ret; strMyAtomicLED.lock (atomic_t)ATOMIC_INIT(0); /初始化原子变量/ atomic_set(strMyAtomicLED.lock, 1); /原子变量初始值strMyAtomicLED.lock.counter1/ retGet_gpio_num();//读引脚编号 if(ret 0) return ret; /* 1、申请“gpio编号”*/ retled_GPIO_request();//申请“gpio编号”  if(ret 0) return ret;//向gpio子系统申请使用“gpio编号” 失败 /2、申请设备号/ strMyAtomicLED.major0; if(strMyAtomicLED.major)/如果指定了主设备号/ { strMyAtomicLED.devid MKDEV(strMyAtomicLED.major, 0); //输入参数strMyAtomicLED.major为“主设备号” //输入参数0为“次设备号”大部分驱动次设备号都选择0 //将strMyAtomicLED.major左移20位再与0相或就得到“Linux设备号” retregister_chrdev_region( strMyAtomicLED.devid,\ MyAtomicLED_CNT, \ MyAtomicLED_NAME ); //strMyAtomicLED.devid表示起始设备号 //MyAtomicLED_CNT表示次设备号的数量 //MyAtomicLED_NAME表示设备名 if(ret 0) goto free_gpio; } else { /* 没有定义设备号 / retalloc_chrdev_region( strMyAtomicLED.devid,\ 0, \ MyAtomicLED_CNT,\ MyAtomicLED_NAME); / 申请设备号 / //strMyAtomicLED.devid保存申请到的设备号 //0次设备号的起始地址 //MyAtomicLED_CNT要申请的次设备号数量 //MyAtomicLED_NAME表示“设备名字” if(ret 0) goto free_gpio; strMyAtomicLED.major MAJOR(strMyAtomicLED.devid); / 获取分配号的主设备号 / //输入参数strMyAtomicLED.devid为“Linux设备号” //将strMyAtomicLED.devid右移20位得到“主设备号” strMyAtomicLED.minor MINOR(strMyAtomicLED.devid); / 获取分配号的次设备号 */ //输入参数strMyAtomicLED.devid为“Linux设备号” //将strMyAtomicLED.devid与0xFFFFF相与后得到“次设备号” } /3、注册字符设备/ strMyAtomicLED.cdev.owner THIS_MODULE; //使用THIS_MODULE将owner指针指向当前这个模块 cdev_init(strMyAtomicLED.cdev,MyAtomicLED_fops); //注册字符设备初始化“字符设备结构变量strMyAtomicLED.cdev” //strMyAtomicLED.cdev是等待初始化的结构体变量 //MyAtomicLED_fops就是字符设备文件操作函数集合 /4、添加字符设备/ retcdev_add(strMyAtomicLED.cdev,strMyAtomicLED.devid,MyAtomicLED_CNT); //添加字符设备 /strMyAtomicLED.cdev表示指向要添加的字符设备即字符设备结构strMyAtomicLED.cdev变量/ //strMyAtomicLED.devid表示设备号 //MyAtomicLED_CNT表示需要添加的设备数量 if(ret 0 ) //添加字符设备失败 goto del_register; printk(dev id major %d,minor %d\r\n, strMyAtomicLED.major, strMyAtomicLED.minor); printk(MyAtomicLED_init is ok!!!\r\n); /*5、自动创建设备节点 */ strMyAtomicLED.class class_create(THIS_MODULE, MyAtomicLED_NAME); if (IS_ERR(strMyAtomicLED.class)){ goto del_cdev; } /*6、创建设备 / strMyAtomicLED.device device_create(strMyAtomicLED.class, NULL, strMyAtomicLED.devid, NULL, MyAtomicLED_NAME); //创建设备 //设备要创建在strMyAtomicLED.class类下面 //NULL表示没有父设备 //strMyAtomicLED.devid是设备号; //参数drvdataNULL设备没有使用数据 //MyAtomicLED_NAME是设备名字 //如果设置fmtMyAtomicLED_NAME 的话就会生成/dev/MyAtomicLED_NAME设备文件。 //返回值就是创建好的设备。 if (IS_ERR(strMyAtomicLED.device)){ goto destroy_class; } return 0; destroy_class: class_destroy(strMyAtomicLED.class); //删除类 //strMyAtomicLED.class就是要删除的类 del_cdev: cdev_del(strMyAtomicLED.cdev); //删除字符设备 //strMyAtomicLED.cdev表示指向需要删除的字符设备即字符设备结构strMyAtomicLED.cdev变量 del_register: unregister_chrdev_region(strMyAtomicLED.devid, MyAtomicLED_CNT); / 释放设备号 */ //strMyAtomicLED.devid需要释放的起始设备号 //MyAtomicLED_CNT需要释放的次设备号数量 free_gpio://申请设备号失败 /释放gpio编号/ gpio_free(strMyAtomicLED.led_gpio); return -EIO; } /*驱动出口函数 */ static void __exit MyAtomicLED_exit(void) { /1、删除字符设备/ cdev_del(strMyAtomicLED.cdev); /删除字符设备/ /strMyAtomicLED.cdev表示指向需要删除的字符设备即字符设备结构strMyAtomicLED.cdev变量/ /*2、 释放设备号 */ unregister_chrdev_region(strMyAtomicLED.devid, MyAtomicLED_CNT); /*释放设备号 */ //strMyAtomicLED.devid需要释放的起始设备号 //MyAtomicLED_CNT需要释放的次设备号数; /*3、 删除设备 */ device_destroy(strMyAtomicLED.class, strMyAtomicLED.devid); //删除创建的设备 //strMyAtomicLED.class是要删除的设备所处的类 //strMyAtomicLED.devid是要删除的设备号 /4、删除类/ class_destroy(strMyAtomicLED.class); //删除类 //strMyAtomicLED.class就是要删除的类 /5、释放gpio编号/ gpio_free(strMyAtomicLED.led_gpio); } module_init(MyAtomicLED_init); //指定MyAtomicLED_init()为驱动入口函数 module_exit(MyAtomicLED_exit); //指定MyAtomicLED_exit()为驱动出口函数 MODULE_AUTHOR(Zhanggong);//添加作者名字 MODULE_LICENSE(GPL);//LICENSE采用“GPL协议” MODULE_INFO(intree,Y); //去除显示“loading out-of-tree module taints kernel.” 7、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]; unsigned char cnt 0; if(argc ! 3) { printf(Error Usage!\r\n); return -1; } //argv[]是指向输入参数“./LED_App” “/dev/LED” “1” filename argv[1]; //argv[1]指向字符串“/dev/LED” fd open(filename, O_RDWR); //如果打开“/dev/LED”文件成功则fd为“文件描述符” //fd0表示标准输入流 fd1表示标准输出流fd2表示错误输出流 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表示关闭失败 printf(close file %s\r\n, filename); return -1; } / 模拟占用10S LED / //添加延时程序导致关闭文件推迟为了是演示互斥访问共享资源的效果 while(1) { sleep(5); cnt; printf(App running times:%d\r\n, cnt); if(cnt 2) break; } / 关闭设备 */ retvalue close(fd); //fd表示要关闭的“文件描述符” //返回值等于0表示关闭成功 //返回值小于0表示关闭失败 if(retvalue 0) { printf(Cant close file %s\r\n, filename); return -1; } else printf(close file %s\r\n, filename); return 0; } 8、创建Makefile KERNELDIR : /home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31 #使用“:”将其后面的字符串赋值给KERNELDIR CURRENT_PATH : \((shell pwd) #采用“shell pwd”获取当前打开的路径 #使用“\)(变量名)”引用“变量的值” MyAPP : LED_APP MyAtomicLED_Module-objs LEDInterface.o LED.o obj-m : MyAtomicLED_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 9、添加“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/MyAtomicLED, /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 } 10、编译 输入“make clean回车” 输入“make drv回车” 输入“make app回车” 输入“make install回车” 输入“ls /home/zgq/linux/nfs/rootfs/lib/modules/5.4.31/ -l回车”产看是存在“LED_APP和MyAtomicLED_Module.ko” 11、测试 启动开发板从网络下载程序 输入“root” 输入“cd /lib/modules/5.4.31/回车” 切换到“/lib/modules/5.4.31/”目录 注意“lib/modules/5.4.31/”在虚拟机中是位于“/home/zgq/linux/nfs/rootfs/”目录下但在开发板中却是位于根目录中。 输入“ls -l”查看“MyAtomicLED_Module.ko和LED_APP”是否存在 输入“depmod”,驱动在第一次执行时需要运行“depmod” 输入“modprobe MyAtomicLED_Module.ko”加载“MyAtomicLED_Module.ko”模块 输入“lsmod”查看有哪些驱动在工作 输入“ls /dev/MyAtomicLEDName -l回车”发现节点文件“/dev/MyAtomicLEDName” 输入“./LED_APP /dev/MyAtomicLEDName 1回车”执行开灯 注意“ ”表示在后台运行LED_APP这个软件。 等待出现“close file /dev/MyAtomicLEDName”按下“回车键”。 注意如果没有出现“close file /dev/MyAtomicLEDName”就急着输入“./LED_APP /dev/MyAtomicLEDName 0回车”就会提示“Cant open file /dev/MyAtomicLEDName”这就避免线程竞争访问贡献资源。 输入“./LED_APP /dev/MyAtomicLEDName 0回车”执行关灯 输入“rmmod MyAtomicLED_Module.ko”卸载“MyAtomicLED_Module.ko”模块 注意:输入“rmmod MyAtomicLED_Module”也可以卸载“MyAtomicLED_Module.ko”模块 输入“lsmod”查看有哪些驱动在工作。 输入“ls /dev/MyAtomicLEDName -l回车”查询节点文件“/dev/MyAtomicLEDName”是否存在