嵌入式Linux驱动开发:蜂鸣器驱动

1. 引言

本文档详细记录了基于i.MX6ULL处理器的蜂鸣器驱动开发过程。内容涵盖驱动的理论基础、代码实现、设备树配置以及用户空间应用程序的编写。本文档严格遵循用户提供的代码和文档,确保理论与实践的紧密结合。本文档旨在为嵌入式Linux驱动开发者提供一份详尽的参考,帮助理解平台驱动模型、设备树的使用以及字符设备驱动的实现。

2. 理论基础

2.1 Linux驱动模型

Linux内核提供了多种驱动模型,以适应不同的硬件设备。其中,平台驱动模型(Platform Driver Model)是针对SoC(System on Chip)内部集成的外设而设计的。这些外设通常与CPU紧密耦合,其资源(如内存映射、中断)在系统启动时就已经确定。

平台驱动模型的核心思想是将设备和驱动分离,通过设备树(Device Tree)来描述硬件信息。设备树在系统启动时被加载,内核根据设备树中的节点信息来创建平台设备(platform_device),然后平台总线(platform_bus)负责匹配设备和驱动。

2.2 平台驱动模型

平台驱动模型由三个主要部分组成:平台设备(platform_device)、平台驱动(platform_driver)和平台总线(platform_bus)。

  • 平台设备(platform_device:代表一个物理设备。它包含了设备的资源信息,如内存地址、中断号等。在旧的内核版本中,这些信息通常在内核启动时静态注册。在现代内核中,这些信息通常由设备树提供。
  • 平台驱动(platform_driver:代表一个驱动程序。它包含了驱动的初始化、卸载、探测(probe)和移除(remove)等函数。驱动通过platform_driver_register函数注册到平台总线上。
  • 平台总线(platform_bus:负责匹配设备和驱动。当一个平台设备被注册时,平台总线会遍历所有已注册的平台驱动,通过of_match_tablename字段进行匹配。如果匹配成功,则调用驱动的probe函数。

2.3 设备树(Device Tree)

设备树是一种描述硬件的文本文件,它使用一种树形结构来组织信息。设备树文件(.dts)在编译时被转换为设备树二进制文件(.dtb),并在系统启动时被加载到内存中。

设备树的主要优点是:

  • 硬件描述与驱动代码分离:驱动代码不再需要硬编码硬件信息,使得驱动更具可移植性。
  • 动态配置:可以通过修改设备树文件来改变硬件配置,而无需重新编译内核。

在设备树中,每个节点代表一个设备或子系统。节点的属性(properties)描述了设备的特性。例如,compatible属性用于匹配驱动,reg属性描述了设备的内存映射地址,interrupts属性描述了设备的中断号。

2.4 字符设备驱动

字符设备是Linux中最基本的设备类型之一,它以字节流的形式进行数据传输。字符设备驱动的核心是file_operations结构体,它定义了驱动支持的操作,如openreadwriterelease等。

在Linux内核中,每个字符设备都有一个主设备号和一个次设备号。主设备号标识设备类型,次设备号标识具体的设备实例。设备文件通常位于/dev目录下。

2.5 杂项设备(Miscellaneous Device)

杂项设备是一种特殊的字符设备,它使用一个固定的主设备号(10),次设备号范围为0到255。杂项设备的目的是简化字符设备的注册过程。通过使用misc_register函数,驱动可以避免手动分配设备号和创建设备文件。

3. 代码实现

3.1 平台设备(leddevice.c

leddevice.c文件定义了一个平台设备,该设备用于模拟一个LED。虽然文件名为leddevice.c,但其内容实际上与蜂鸣器驱动相关。该文件的主要作用是向内核注册一个平台设备,该设备描述了蜂鸣器所需的硬件资源。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/ide.h>
#include <linux/platform_device.h>/* 寄存器物理地址 */
#define CCM_CCGR1_BASE (0X020C406C)
#define SW_MUX_GPIO1_IO03_BASE (0X020E0068)
#define SW_PAD_GPIO1_IO03_BASE (0X020E02F4)
#define GPIO1_DR_BASE (0X0209C000)
#define GPIO1_GDIR_BASE (0X0209C004)#define REGISTER_LNE 4
  • 寄存器物理地址:这些宏定义了i.MX6ULL处理器中与GPIO相关的寄存器的物理地址。CCM_CCGR1_BASE是时钟控制模块的寄存器,用于使能GPIO1的时钟。SW_MUX_GPIO1_IO03_BASESW_PAD_GPIO1_IO03_BASE分别是复用和电气特性的配置寄存器。GPIO1_DR_BASEGPIO1_GDIR_BASE分别是GPIO数据寄存器和方向寄存器。
void leddevice_realease(struct device *dev)
{printk("Device: leddevice_realease!\r\n");
}
  • 设备释放函数:当平台设备被注销时,内核会调用此函数。这是一个空函数,仅用于打印一条调试信息。
static struct resource led_resources[] = {[0] = {.start = CCM_CCGR1_BASE,.end = CCM_CCGR1_BASE + REGISTER_LNE - 1,.flags = IORESOURCE_MEM,},[1] = {.start = SW_MUX_GPIO1_IO03_BASE,.end = SW_MUX_GPIO1_IO03_BASE + REGISTER_LNE - 1,.flags = IORESOURCE_MEM,},[2] = {.start = SW_PAD_GPIO1_IO03_BASE,.end = SW_PAD_GPIO1_IO03_BASE + REGISTER_LNE - 1,.flags = IORESOURCE_MEM,},[3] = {.start = GPIO1_DR_BASE,.end = GPIO1_DR_BASE + REGISTER_LNE - 1,.flags = IORESOURCE_MEM,},[4] = {.start = GPIO1_GDIR_BASE,.end = GPIO1_GDIR_BASE + REGISTER_LNE - 1,.flags = IORESOURCE_MEM,},
};
  • 资源数组led_resources数组定义了平台设备所需的资源。每个资源结构体包含起始地址、结束地址和标志。IORESOURCE_MEM标志表示这是一个内存资源。这些资源在驱动的probe函数中被映射到虚拟地址空间。
static struct platform_device leddevice = {.name = "imx6ull-led",.id = -1,.dev = {.release = leddevice_realease,},.num_resources = ARRAY_SIZE(led_resources),.resource = led_resources,
};
  • 平台设备结构体leddevice结构体定义了一个平台设备。.name字段必须与驱动中的.name字段匹配,以便平台总线能够正确匹配设备和驱动。.id字段设置为-1,表示这是唯一的设备实例。.dev.release字段指定了设备释放函数。.num_resources.resource字段指定了设备的资源。
static int __init
leddevice_init(void)
{platform_device_register(&leddevice);return 0;
}static void __exit leddevice_exit(void)
{platform_device_unregister(&leddevice);
}module_init(leddevice_init);
module_exit(leddevice_exit);MODULE_LICENSE("GPL");
  • 模块初始化和退出leddevice_init函数在模块加载时被调用,它注册平台设备。leddevice_exit函数在模块卸载时被调用,它注销平台设备。module_initmodule_exit宏用于指定初始化和退出函数。

3.2 蜂鸣器驱动(miscbeep.c

miscbeep.c文件实现了蜂鸣器的驱动程序。该驱动使用平台驱动模型和杂项设备框架。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/string.h>
#include <linux/ide.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>#define MISCBEEP_NAME "miscbeep"
#define MISCBEEP_MINOR 144
#define BEEP_OFF 0
#define BEEP_ON 1
  • 宏定义MISCBEEP_NAME定义了杂项设备的名称,该名称将出现在/dev目录下。MISCBEEP_MINOR定义了次设备号。BEEP_OFFBEEP_ON定义了蜂鸣器的状态。
struct miscbeep_dev
{int beep_gpio;struct device_node *nd;
};
struct miscbeep_dev miscbeep;
  • 设备结构体miscbeep_dev结构体用于保存驱动的状态信息。beep_gpio字段保存了蜂鸣器GPIO的编号。nd字段保存了设备树节点的指针,用于在probe函数中获取设备信息。
static int miscbeep_open(struct inode *inode, struct file *filp)
{filp->private_data = &miscbeep;return 0;
}
  • open函数:当用户空间程序打开设备文件时,内核调用此函数。该函数将设备结构体的指针保存在filp->private_data中,以便在后续的readwrite等操作中使用。
static ssize_t miscbeep_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *ppos)
{int retvalue;unsigned char databuf[1];unsigned char beepstat;struct miscbeep_dev *dev = filp->private_data;retvalue = copy_from_user(databuf, buf, cnt);if (retvalue < 0){printk("kernel write failed!\r\n");return -EFAULT;}beepstat = databuf[0]; /* 获取状态值 */if (beepstat == BEEP_ON){gpio_set_value(dev->beep_gpio, 0); /* 打开蜂鸣器 */}else if (beepstat == BEEP_OFF){gpio_set_value(dev->beep_gpio, 1); /* 关闭蜂鸣器 */}return 0;
}
  • write函数:当用户空间程序向设备文件写入数据时,内核调用此函数。该函数首先使用copy_from_user函数将用户空间的数据复制到内核空间。然后,根据写入的数据(0或1)来控制蜂鸣器的开关。gpio_set_value函数用于设置GPIO的电平。注意,蜂鸣器的控制逻辑是低电平有效,因此写入0表示打开,写入1表示关闭。
static int miscbeep_release(struct inode *inode, struct file *filep)
{return 0;
}
  • release函数:当用户空间程序关闭设备文件时,内核调用此函数。该函数目前为空,但在实际应用中,可以用于释放资源或执行清理操作。
struct file_operations miscbeep_fops = {.owner = THIS_MODULE,.open = miscbeep_open,.write = miscbeep_write,.release = miscbeep_release,
};
  • 文件操作结构体miscbeep_fops结构体定义了驱动支持的操作。.owner字段设置为THIS_MODULE,表示该结构体属于当前模块。.open.write.release字段分别指向相应的函数。
struct miscdevice beep_miscdev = {.minor = MISCBEEP_MINOR,.name = MISCBEEP_NAME,.fops = &miscbeep_fops,
};
  • 杂项设备结构体beep_miscdev结构体定义了杂项设备。.minor字段指定了次设备号。.name字段指定了设备名称。.fops字段指向文件操作结构体。
static int miscbeep_probe(struct platform_device *dev)
{int ret = 0;miscbeep.nd = dev->dev.of_node;miscbeep.beep_gpio = of_get_named_gpio(miscbeep.nd, "beep-gpios", 0);if (miscbeep.beep_gpio < 0){ret = -EINVAL;goto fail_get_gpio;}ret = gpio_request(miscbeep.beep_gpio, "beep-gpio");if (ret){ret = -EINVAL;goto fail_req;}ret = gpio_direction_output(miscbeep.beep_gpio, 1);if (ret < 0){ret = -EINVAL;goto fail_gpio_dir;}ret = misc_register(&beep_miscdev);if (ret){ret = -EINVAL;goto fail_misc_reg;}return 0;
fail_misc_reg:printk("Driver: fail_misc_reg\r\n");
fail_gpio_dir:gpio_free(miscbeep.beep_gpio);printk("Driver: fail_gpio_dir\r\n");
fail_req:printk("Driver: fail_req\r\n");
fail_get_gpio:printk("Driver: fail_get_gpio\r\n");return ret;
}
  • probe函数:当平台总线匹配到设备和驱动时,内核调用此函数。该函数执行以下操作:
    1. 获取设备树节点指针。
    2. 使用of_get_named_gpio函数从设备树中获取蜂鸣器GPIO的编号。
    3. 使用gpio_request函数申请GPIO。
    4. 使用gpio_direction_output函数将GPIO设置为输出模式,并初始化为高电平(关闭蜂鸣器)。
    5. 使用misc_register函数注册杂项设备。
      如果任何一步失败,函数将跳转到相应的错误处理标签,释放已申请的资源。
static int miscbeep_remove(struct platform_device *dev)
{misc_deregister(&beep_miscdev);gpio_set_value(miscbeep.beep_gpio, 1);gpio_free(miscbeep.beep_gpio);return 0;
}
  • remove函数:当平台设备被注销时,内核调用此函数。该函数执行以下操作:
    1. 使用misc_deregister函数注销杂项设备。
    2. 将GPIO设置为高电平,关闭蜂鸣器。
    3. 使用gpio_free函数释放GPIO。
static struct of_device_id beep_of_match[] = {{.compatible = "alientek,beep"},{/* sentinel */},
};
  • 设备树匹配表beep_of_match数组定义了驱动支持的设备。.compatible字段必须与设备树中的compatible属性匹配。平台总线使用此表来匹配设备和驱动。
struct platform_driver miscbeep_driver = {.driver = {.name = "imx6ul-beep",.of_match_table = beep_of_match,},.remove = miscbeep_remove,.probe = miscbeep_probe,
};
  • 平台驱动结构体miscbeep_driver结构体定义了平台驱动。.driver.name字段必须与平台设备的.name字段匹配。.of_match_table字段指向设备树匹配表。.probe.remove字段分别指向proberemove函数。
static int __init
miscbeep_init(void)
{return platform_driver_register(&miscbeep_driver);
}static void __exit miscbeep_exit(void)
{platform_driver_unregister(&miscbeep_driver);
}module_init(miscbeep_init);
module_exit(miscbeep_exit);MODULE_LICENSE("GPL");
  • 模块初始化和退出miscbeep_init函数在模块加载时被调用,它注册平台驱动。miscbeep_exit函数在模块卸载时被调用,它注销平台驱动。

3.3 Makefile

KERNERDIR := /home/ubuntu2004/linux/IMX6ULL/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga
CURRENTDIR := $(shell pwd)obj-m := miscbeep.o
build : kernel_moduleskernel_modules:$(MAKE) -C $(KERNERDIR) M=$(CURRENTDIR) modulesclean:$(MAKE) -C $(KERNERDIR) M=$(CURRENTDIR) clean
  • Makefile:该Makefile用于编译驱动模块。KERNERDIR变量指定了内核源码的路径。CURRENTDIR变量指定了当前目录的路径。obj-m变量指定了要编译的模块文件。kernel_modules目标调用内核的Makefile来编译模块。clean目标用于清理编译生成的文件。

3.4 用户空间应用程序(miscbeepAPP.c

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"#define LEDOFF 0
#define LEDON 1/** @description		: main主程序* @param - argc 	: argv数组元素个数* @param - argv 	: 具体参数* @return 			: 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;}filename = argv[1];/* 打开led驱动 */fd = open(filename, O_RDWR);if (fd < 0){printf("file %s open failed!\r\n", argv[1]);return -1;}databuf[0] = atoi(argv[2]); /* 要执行的操作:打开或关闭 *//* 向/dev/led文件写入数据 */retvalue = write(fd, databuf, sizeof(databuf));if (retvalue < 0){printf("LED Control Failed!\r\n");close(fd);return -1;}retvalue = close(fd); /* 关闭文件 */if (retvalue < 0){printf("file %s close failed!\r\n", argv[1]);return -1;}return 0;
}
  • 用户空间应用程序:该程序用于控制蜂鸣器。它接受两个命令行参数:设备文件路径和操作(0或1)。程序首先打开设备文件,然后向设备文件写入操作数据,最后关闭设备文件。

4. 设备树配置

4.1 设备树节点

imx6ull-alientek-emmc.dts文件中,定义了蜂鸣器的设备树节点:

beep{compatible = "alientek,beep";pinctrl-names = "default";pinctrl-0 = <&pinctrl_beep>;states = "okay";beep-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
};
  • compatible:该属性的值必须与驱动中的of_device_id表中的.compatible字段匹配。
  • pinctrl-namespinctrl-0:这些属性指定了引脚控制配置。pinctrl-0指向pinctrl_beep节点,该节点定义了GPIO5_IO01引脚的复用和电气特性。
  • beep-gpios:该属性指定了蜂鸣器使用的GPIO。<&gpio5 1 GPIO_ACTIVE_HIGH>表示使用GPIO5的第1个引脚,高电平有效。

4.2 引脚控制配置

iomuxc节点中,定义了pinctrl_beep节点:

pinctrl_beep: beepgrp {fsl,pins = <MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01	0x10b0>;
};
  • MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01:该宏将SNVS_TAMPER1引脚复用为GPIO5_IO01。
  • 0x10b0:该值配置了引脚的电气特性,如驱动强度、上拉/下拉电阻等。

5. 编译和测试

5.1 编译驱动

  1. miscbeep.cMakefileleddevice.c文件复制到开发板的内核源码目录。
  2. miscbeep目录下执行make命令,编译驱动模块。
  3. 使用scp命令将生成的miscbeep.ko文件复制到开发板。

5.2 加载驱动

  1. 在开发板上,使用insmod命令加载leddevice.ko模块:
    insmod leddevice.ko
    
  2. 加载miscbeep.ko模块:
    insmod miscbeep.ko
    

5.3 测试驱动

  1. 编译用户空间应用程序:
    gcc -o miscbeepAPP miscbeepAPP.c
    
  2. 运行应用程序,打开蜂鸣器:
    ./miscbeepAPP /dev/miscbeep 1
    
  3. 运行应用程序,关闭蜂鸣器:
    ./miscbeepAPP /dev/miscbeep 0
    

8. 源码仓库

https://gitee.com/dream-cometrue/linux_driver_imx6ull

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97455.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97455.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/97455.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt中的锁和条件变量和信号量

Qt中的锁和条件变量和信号量 C11中引入智能指针用来解决锁忘记释放的问题 代码如下&#xff1a; void Thread::run() {for(int i0;i<50000;i){QMutexLocker locker(&mutex);//mutex.lock();num;//mutex.unlock();} }大括号结束的时候&#xff0c;生命周期踩结束&#xf…

智能电视MaxHub恢复系统

公司的MaxHub智能电视又出故障了。 去年硬件故障返厂&#xff0c;花了8600多元。 这次看上去是软件故障。开机后蓝屏报错。 按回车键&#xff0c;电视重启。 反复折腾几次&#xff0c;自行修复执行完毕&#xff0c;终于可以进入系统了。 只不过进入windows10后&#xff0c;图…

TensorFlow 面试题及详细答案 120道(71-80)-- 性能优化与调试

《前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。 前后端面试题-专栏总目录 文章目录 一、本文面试题目录 71. 如何优化TensorFlow模…

数据结构 第三轮

以看严蔚敏老师的教材为主&#xff0c;辅以其他辅导书&#xff1a;王道&#xff0c;新编数据结构&#xff0c;学校讲义 线性结构&#xff1a;线性表、串、队列、栈、数组和广义表 树形结构、网状结构&#xff1a;图 查找、排序 动态内存管理和文件 绪论 8-29 数据&#xf…

[新启航]新启航激光频率梳 “光量子透视”:2μm 精度破除遮挡,完成 130mm 深孔 3D 建模

摘要&#xff1a;本文介绍新启航激光频率梳的 “光量子透视” 技术&#xff0c;该技术凭借独特的光量子特性与测量原理&#xff0c;以 2μm 精度破除深孔遮挡&#xff0c;成功完成 130mm 深孔的 3D 建模&#xff0c;为深孔三维形态的精确获取提供了创新解决方案&#xff0c;推动…

MongoDB /redis/mysql 界面化的数据查看页面App

MongoDB、Redis 和 MySQL 都有界面化的数据查看工具&#xff0c;以下是相关介绍&#xff1a; MongoDB 输入MongoDB的账号密码即可读取数据&#xff0c;可访问数据。 MongoDB Compass&#xff1a;这是 MongoDB 官方提供的 GUI 管理工具&#xff0c;支持 Windows、Mac 和 Linux 等…

Spring Boot 实战:接入 DeepSeek API 实现问卷文本优化

本文结合 Spring Boot 项目&#xff0c;介绍如何接入 DeepSeek API&#xff0c;自动优化问卷文本&#xff0c;并给出完整示例代码及详细注释。一、项目目标 目标是实现一个 REST 接口&#xff0c;将原始问卷文本提交给 DeepSeek API&#xff0c;然后返回优化后的文本给前端。 接…

opencv实现轮廓绘制和选择

前面学习了opencv中图像的一些处理&#xff0c;但对于opencv我们更多的还是对图像做出一些判断和识别&#xff0c;所以下面开始学习图像的识别。 原图&#xff1a; 一 图像轮廓的识别 import cv2 pencv2.imread(pen.png,0) ret,new_pencv2.threshold(pen,120,255,cv2.THRESH_…

【Linux】Docker洞察:掌握docker inspect命令与Go模板技巧

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;CSDN博客专家   &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01…

知料觅得-新一代AI搜索引擎

本文转载自&#xff1a;知料觅得-新一代AI搜索引擎 - Hello123工具导航 ** 一、&#x1f50d; 初识知料觅得&#xff1a;你的 AI 搜索新伙伴 知料觅得是一款融合了前沿人工智能技术的智能搜索引擎&#xff0c;它旨在彻底改变我们获取信息的方式。不同于传统搜索引擎只给你一堆…

高性能网络转发中的哈希表技术选型与实践

引言 在现代网络编程中,处理大量并发连接是一个常见而重要的挑战。特别是在中间件、代理服务器和负载均衡器等场景中,如何高效地管理数万个并发连接并实现数据转发,对系统性能有着至关重要的影响。本文将围绕一个具体的网络转发场景,深入探讨三种不同的哈希表实现(hsearc…

【CF】Day136——Codeforces Round 1046 (Div. 2) CD (动态规划 | 数学)

C. Against the Difference题目&#xff1a;思路&#xff1a;简单DP不难发现我们贪心是没法贪的&#xff0c;因此考虑DP我们令 dp[i] 为 前 i 个元素能构造出的最长整齐子序列的长度&#xff0c;不难发现一个很简单的转移&#xff0c;即直接继承 dp[i] dp[i-1]&#xff0c;那么…

如何评价 Kimi 开源的推理平台 Mooncake?对行业有什么影响?

2月26日&#xff0c;Mooncake的论文获得「计算机存储顶会 FAST 2025」Best Paper&#xff0c;这也是国内连续第三年拿到FAST Best Paper。同时&#xff0c;Mooncake 团队宣布和 vLLM 团队已经合作制定了一个多阶段路线图。这次整合将为 vLLM 引入 P/D&#xff08;Prefill/Decod…

Java中不太常见的语法-总结

简介 读源码时&#xff0c;或者看同事写的代码&#xff0c;经常看到一些不太常见的语法&#xff0c;这里做一个总结 不太常见的语法 成员变量的默认值 案例&#xff1a; public class Person2 {private String name "张三";private Integer age;public String getNa…

Easytier异地组网与移动光猫GS220-s

Easytier异地组网与Nginx反向代理_--relay-network-whitelis easytier-CSDN博客 上一篇文章介绍了Easytier实现异地组网&#xff0c;基于Windows应用&#xff0c;本篇将探讨如何将Easytier写入光猫GS220-s中&#xff0c;实现更方便的家庭组网。 一、Telnet移动光猫GS220-s 1…

卫星信号和无线信号的设备厂商

以下是一些与卫星信号相关的公司&#xff1a;中国卫通集团股份有限公司&#xff1a;中国航天科技集团有限公司从事卫星运营服务业的核心专业子公司&#xff0c;是中国唯一拥有通信卫星资源且自主可控的卫星通信运营企业。运营管理着多颗在轨民商用通信广播卫星&#xff0c;覆盖…

HyperPlonk 的硬件友好性

1. 引言 在工业界广泛使用的 Plonk SNARK 协议高度依赖 NTT 来完成计算。HyperPlonk 是 Plonk 的一个变种&#xff0c;它试图通过用 Sumcheck 替代 NTT&#xff08;以及其它改进&#xff09;来提升并行性。Ingonyama团队认为&#xff1a; Sumcheck 在 HyperPlonk 中所谓的并行…

Visual Studio内置环境变量有哪些

在 Visual Studio 中&#xff0c;内置变量&#xff08;也称为宏&#xff09;可以用于在项目配置中指定特定的路径、环境变量或其他值。这些变量可以在项目的属性页面中使用&#xff0c;也可以在代码中使用。以下是一些常用的内置变量及其用途&#xff1a; 常用内置变量 $(Solut…

大模型入门学习微调实战:基于PyTorch和Hugging Face电影评价情感分析模型微调全流程(附完整代码)手把手教你做

深入浅出&#xff1a;如何训练一个属于你的大模型&#xff1f; “一个强大的大模型&#xff0c;究竟是如何训练出来的&#xff1f;” 本文将基于行业共识&#xff0c;为您详细拆解大模型的完整训练流程&#xff0c;并提供一个基于开源模型和数据集的实战代码示例&#xff0c;…

零、2025 年软件设计师考试大纲

一、考试说明 1.考试目标 通过本考试的合格人员能根据软件开发项目管理和软件工程的要求&#xff0c;按照系统总体设计规格说明书进行软件设计&#xff0c;编写程序设计规格说明书等相应的文档&#xff0c;组织和指导程序员编写、调试程序&#xff0c;并对软件进行优化和集成…