[linux 驱动]regmap子系统详解与实战

news2024/9/26 14:54:08

目录

 

1 描述

2 结构体

2.1 regmap

2.2 regmap_bus

2.3 regmap_config

3 regmap 操作函数

3.1 regmap 申请与初始化

3.1.1 regmap_init_i2c

3.1.2 regmap_init_spi

3.1.3 regmap_exit

3.2 regmap 设备访问 API 函数

3.2.1 regmap_read

3.2.2 regmap_write

4 示例


 

1 描述

        Linux 内核引入了 regmap 模型,regmap 将寄存器访问的共同逻辑抽象出来,驱动开发人员不需要再去纠结使用 SPI 或者 I2C 接口 API 函数,统一使用 regmapAPI 函数。这样的好处就是统一使用 regmap,降低了代码冗余,提高了驱动的可以移植性。regmap 模型的重点在于:

        通过 regmap 模型提供的统一接口函数来访问器件的寄存器,SOC 内部的寄存器也可以使用 regmap 接口函数来访问。

        regmap 是 Linux 内核为了减少慢速 I/O 在驱动上的冗余开销,提供了一种通用的接口来操作硬件寄存器。另外,regmap 在驱动和硬件之间添加了 cache,降低了低速 I/O 的操作次数,提高了访问效率,缺点是实时性会降低。

        regmap 框架结构如下图所示。

 

9272d96ec03618c44a209d495c1657fa.png

2 结构体

2.1 regmap

 52 struct regmap {
 53         union {
 54                 struct mutex mutex;
 55                 struct {
 56                         spinlock_t spinlock;
 57                         unsigned long spinlock_flags;
 58                 };
 59         };
 60         regmap_lock lock;
 61         regmap_unlock unlock;
 62         void *lock_arg; /* This is passed to lock/unlock functions */
 63         gfp_t alloc_flags;
 64 
 65         struct device *dev; /* Device we do I/O on */
 66         void *work_buf;     /* Scratch buffer used to format I/O */
 67         struct regmap_format format;  /* Buffer format */
 68         const struct regmap_bus *bus;
 69         void *bus_context;
 70         const char *name;
 71 
 72         bool async;
 73         spinlock_t async_lock;
 74         wait_queue_head_t async_waitq;
 75         struct list_head async_list;
 76         struct list_head async_free;
 77         int async_ret;
 78 
 79 #ifdef CONFIG_DEBUG_FS
 80         bool debugfs_disable;
 81         struct dentry *debugfs;
 82         const char *debugfs_name;
 83 
 84         unsigned int debugfs_reg_len;
 85         unsigned int debugfs_val_len;
 86         unsigned int debugfs_tot_len;
 87 
 88         struct list_head debugfs_off_cache;
 89         struct mutex cache_lock;
 90 #endif
 91 
 92         unsigned int max_register;
 93         bool (*writeable_reg)(struct device *dev, unsigned int reg);
 94         bool (*readable_reg)(struct device *dev, unsigned int reg);
 95         bool (*volatile_reg)(struct device *dev, unsigned int reg);
 96         bool (*precious_reg)(struct device *dev, unsigned int reg);
 97         bool (*readable_noinc_reg)(struct device *dev, unsigned int reg);
 98         const struct regmap_access_table *wr_table;
 99         const struct regmap_access_table *rd_table;
100         const struct regmap_access_table *volatile_table;
101         const struct regmap_access_table *precious_table;
102         const struct regmap_access_table *rd_noinc_table;
103 
104         int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
105         int (*reg_write)(void *context, unsigned int reg, unsigned int val);
106         int (*reg_update_bits)(void *context, unsigned int reg,
107                                unsigned int mask, unsigned int val);
108 
109         bool defer_caching;
110 
111         unsigned long read_flag_mask;
112         unsigned long write_flag_mask;
113 
114         /* number of bits to (left) shift the reg value when formatting*/
115         int reg_shift;
116         int reg_stride;
117         int reg_stride_order;
118 
119         /* regcache specific members */
120         const struct regcache_ops *cache_ops;
121         enum regcache_type cache_type;
122 
123         /* number of bytes in reg_defaults_raw */
124         unsigned int cache_size_raw;
125         /* number of bytes per word in reg_defaults_raw */
126         unsigned int cache_word_size;
127         /* number of entries in reg_defaults */
128         unsigned int num_reg_defaults;
129         /* number of entries in reg_defaults_raw */
130         unsigned int num_reg_defaults_raw;
131 
132         /* if set, only the cache is modified not the HW */
133         bool cache_only;
134         /* if set, only the HW is modified not the cache */
135         bool cache_bypass;
136         /* if set, remember to free reg_defaults_raw */
137         bool cache_free;
138 
139         struct reg_default *reg_defaults;
140         const void *reg_defaults_raw;
141         void *cache;
142         /* if set, the cache contains newer data than the HW */
143         bool cache_dirty;
144         /* if set, the HW registers are known to match map->reg_defaults */
145         bool no_sync_defaults;
146 
147         struct reg_sequence *patch;
148         int patch_regs;
149 
150         /* if set, converts bulk read to single read */
151         bool use_single_read;
152         /* if set, converts bulk read to single read */
153         bool use_single_write;
154         /* if set, the device supports multi write mode */
155         bool can_multi_write;
156 
157         /* if set, raw reads/writes are limited to this size */
158         size_t max_raw_read;
159         size_t max_raw_write;
160 
161         struct rb_root range_tree;
162         void *selector_work_buf;        /* Scratch buffer used for selector */
163 
164         struct hwspinlock *hwlock;
165 };

2.2 regmap_bus

        regmap_bus 的结构体,它用于描述一种与寄存器映射(regmap)交互的硬件总线或接口的属性和功能。在嵌入式系统或硬件驱动开发中,寄存器映射是一种常见的技术,用于通过内存地址空间访问硬件设备的寄存器。这种方式使得软件可以像操作内存一样来读写硬件的寄存器,从而控制硬件设备。

        regmap_bus结构定义了读写函数默认的寄存器地址寄存器值的大小端

492 struct regmap_bus {             
 493         bool fast_io;
 494         regmap_hw_write write; 
 495         regmap_hw_gather_write gather_write;
 496         regmap_hw_async_write async_write;
 497         regmap_hw_reg_write reg_write;
 498         regmap_hw_reg_update_bits reg_update_bits;
 499         regmap_hw_read read;
 500         regmap_hw_reg_read reg_read;
 501         regmap_hw_free_context free_context;
 502         regmap_hw_async_alloc async_alloc;
 503         u8 read_flag_mask;
 504         enum regmap_endian reg_format_endian_default;
 505         enum regmap_endian val_format_endian_default;
 506         size_t max_raw_read;         
 507         size_t max_raw_write;        
 508 };

bool fast_io;:一个布尔值,指示是否使用快速I/O模式。这可能会影响读写操作的性能和方式。

regmap_hw_write write;:一个指向函数的指针,该函数用于执行硬件写操作。这个函数的具体实现取决于特定的硬件和总线。

regmap_hw_gather_write gather_write;:一个指向函数的指针,用于执行聚集写操作。这通常用于一次写入多个数据到硬件寄存器,以提高效率。

regmap_hw_async_write async_write;:一个指向函数的指针,用于执行异步写操作。这允许写操作在后台进行,而不阻塞当前线程。

regmap_hw_reg_write reg_write;:一个指向函数的指针,专门用于单个寄存器的写操作。

regmap_hw_reg_update_bits reg_update_bits;:一个指向函数的指针,用于更新寄存器的特定位而不改变其他位。

regmap_hw_read read;:一个指向函数的指针,用于执行硬件读操作。

regmap_hw_reg_read reg_read;:一个指向函数的指针,专门用于读取单个寄存器的值。

regmap_hw_free_context free_context;:一个指向函数的指针,用于释放与硬件交互时可能分配的资源或上下文。

regmap_hw_async_alloc async_alloc;:一个指向函数的指针,用于分配异步操作所需的资源。

u8 read_flag_mask;:一个无符号8位整数,用作读操作时的标志掩码,可能用于控制读操作的某些方面。

enum regmap_endian reg_format_endian_default;:一个枚举类型,表示寄存器格式(即寄存器在硬件中的存储方式)的默认字节序(大端或小端)。

enum regmap_endian val_format_endian_default;:一个枚举类型,表示值格式(即写入或读取到寄存器的值的存储方式)的默认字节序。

size_t max_raw_read; 和 size_t max_raw_write;:分别表示在一次操作中能够读取或写入的最大原始数据量(以字节为单位)。这对于了解硬件的限制和优化数据传输效率很重要。

2.3 regmap_config

        在regmap_config,定义了寄存器的各种信息,比如寄存器地址长度寄存器值的长度读写寄存器的地址范围的信息,寄存器地址和值的大小端以及缓冲方式。

343 struct regmap_config {
 344         const char *name;
 345 
 346         int reg_bits;
 347         int reg_stride;
 348         int pad_bits;
 349         int val_bits;
 350 
 351         bool (*writeable_reg)(struct device *dev, unsigned int reg);
 352         bool (*readable_reg)(struct device *dev, unsigned int reg);
 353         bool (*volatile_reg)(struct device *dev, unsigned int reg);
 354         bool (*precious_reg)(struct device *dev, unsigned int reg);
 355         bool (*readable_noinc_reg)(struct device *dev, unsigned int reg);
 356 
 357         bool disable_locking;
 358         regmap_lock lock;
 359         regmap_unlock unlock;
 360         void *lock_arg;
 361 
 362         int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
 363         int (*reg_write)(void *context, unsigned int reg, unsigned int val);
 364 
 365         bool fast_io;
 366 
 367         unsigned int max_register;
 368         const struct regmap_access_table *wr_table;
 369         const struct regmap_access_table *rd_table;
 370         const struct regmap_access_table *volatile_table;
 371         const struct regmap_access_table *precious_table;
 372         const struct regmap_access_table *rd_noinc_table;
 373         const struct reg_default *reg_defaults;
 374         unsigned int num_reg_defaults;
 375         enum regcache_type cache_type;
 376         const void *reg_defaults_raw;
 377         unsigned int num_reg_defaults_raw;
 378 
 379         unsigned long read_flag_mask;
 380         unsigned long write_flag_mask;
 381         bool zero_flag_mask;
 382 
 383         bool use_single_rw;
 384         bool can_multi_write;
 385 
 386         enum regmap_endian reg_format_endian;
 387         enum regmap_endian val_format_endian;
 388 
 389         const struct regmap_range_cfg *ranges;
 390         unsigned int num_ranges;
 391 
 392         bool use_hwlock;
 393         unsigned int hwlock_id;
 394         unsigned int hwlock_mode;
 395 };

3 regmap 操作函数

3.1 regmap 申请与初始化

3.1.1 regmap_init_i2c

函数原型

#define regmap_init_i2c(i2c, config) \

__regmap_lockdep_wrapper(__regmap_init_i2c, #config, \

i2c, config)

参数

struct i2c_client *i2c

这是指向 I2C 设备的指针,通常是一个 struct i2c_client 类型。

struct regmap_config *config

这是一个配置结构体,包含有关寄存器映射的配置信息,比如寄存器地址、数据格式等。

返回值

 

 

功能

用于初始化 I2C 设备的寄存器映射

        当设备驱动配置好config以后,调用对应的regmap_init_i2c

281 struct regmap *__regmap_init_i2c(struct i2c_client *i2c,
282                                  const struct regmap_config *config,
283                                  struct lock_class_key *lock_key,
284                                  const char *lock_name)
285 {                        
286         const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
287 
288         if (IS_ERR(bus))
289                 return ERR_CAST(bus);
290 
291         return __regmap_init(&i2c->dev, bus, &i2c->dev, config,
292                              lock_key, lock_name);
293 }             
662 #define regmap_init_i2c(i2c, config)                                    \
 663         __regmap_lockdep_wrapper(__regmap_init_i2c, #config,            \
 664                                 i2c, config)
620 #ifdef CONFIG_LOCKDEP
 621 #define __regmap_lockdep_wrapper(fn, name, ...)                         \
 622 (                                                                       \
 623         ({                                                              \
 624                 static struct lock_class_key _key;                      \
 625                 fn(__VA_ARGS__, &_key,                                  \
 626                         KBUILD_BASENAME ":"                             \
 627                         __stringify(__LINE__) ":"                       \
 628                         "(" name ")->lock");                            \
 629         })                                                              \
 630 )
 631 #else
 632 #define __regmap_lockdep_wrapper(fn, name, ...) fn(__VA_ARGS__, NULL, NULL)
 633 #endif
281 struct regmap *__regmap_init_i2c(struct i2c_client *i2c,
282                                  const struct regmap_config *config,
283                                  struct lock_class_key *lock_key,
284                                  const char *lock_name)
285 {
286         const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
287 
288         if (IS_ERR(bus))
289                 return ERR_CAST(bus);
290 
291         return __regmap_init(&i2c->dev, bus, &i2c->dev, config,
292                              lock_key, lock_name);
293 }

 

253 static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
254                                         const struct regmap_config *config)
255 {
256         if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C))
257                 return &regmap_i2c;
258         else if (config->val_bits == 8 && config->reg_bits == 8 &&
259                  i2c_check_functionality(i2c->adapter,
260                                          I2C_FUNC_SMBUS_I2C_BLOCK))
261                 return &regmap_i2c_smbus_i2c_block;
262         else if (config->val_bits == 16 && config->reg_bits == 8 &&
263                  i2c_check_functionality(i2c->adapter,
264                                          I2C_FUNC_SMBUS_WORD_DATA))
265                 switch (regmap_get_val_endian(&i2c->dev, NULL, config)) {
266                 case REGMAP_ENDIAN_LITTLE:
267                         return &regmap_smbus_word;
268                 case REGMAP_ENDIAN_BIG:
269                         return &regmap_smbus_word_swapped;
270                 default:                /* everything else is not supported */
271                         break;
272                 }
273         else if (config->val_bits == 8 && config->reg_bits == 8 &&
274                  i2c_check_functionality(i2c->adapter,
275                                          I2C_FUNC_SMBUS_BYTE_DATA))
276                 return &regmap_smbus_byte;
277 
278         return ERR_PTR(-ENOTSUPP);
279 }

3.1.2 regmap_init_spi

701 #define regmap_init_spi(dev, config)                                    \
 702         __regmap_lockdep_wrapper(__regmap_init_spi, #config,            \
 703                                 dev, config)

3.1.3 regmap_exit

        不管是什么接口,全部使用 regmap_exit 这个函数来释放 regmap。

1310 void regmap_exit(struct regmap *map)
1311 {
1312         struct regmap_async *async;
1313 
1314         regcache_exit(map);
1315         regmap_debugfs_exit(map);
1316         regmap_range_exit(map);
1317         if (map->bus && map->bus->free_context)
1318                 map->bus->free_context(map->bus_context);
1319         kfree(map->work_buf);
1320         while (!list_empty(&map->async_free)) {
1321                 async = list_first_entry_or_null(&map->async_free,
1322                                                  struct regmap_async,
1323                                                  list);
1324                 list_del(&async->list);
1325                 kfree(async->work_buf);
1326                 kfree(async);
1327         }
1328         if (map->hwlock)
1329                 hwspin_lock_free(map->hwlock);
1330         kfree_const(map->name);
1331         kfree(map->patch);
1332         kfree(map);
1333 }

3.2 regmap 设备访问 API 函数

        不管是 I2C 还是 SPI 等接口,还是 SOC 内部的寄存器,对于寄存器的操作就两种:读和写。regmap 提供了最核心的两个读写操作:regmap_read 和 regmap_write。这两个函数分别用来读/写寄存器。

3.2.1 regmap_read

函数原型

int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)

参数

struct regmap *map

regmap结构体指针

unsigned int reg

读取的寄存器地址

unsigned int *val

存储读取的数据的指针

返回值

int

成功:0 失败:负数

功能

从设备的寄存器中读取数据。regmap框架提供了一种统一的方式来访问设备的寄存器,无论这些寄存器是通过i2c、spi、内存映射还是其他方式访问的

2472 int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
2473 {      
2474         int ret;
2475        
2476         if (!IS_ALIGNED(reg, map->reg_stride))
2477                 return -EINVAL;
2478        
2479         map->lock(map->lock_arg);
2480 
2481         ret = _regmap_read(map, reg, val);
2482 
2483         map->unlock(map->lock_arg);
2484 
2485         return ret;
2486 }
2428 static int _regmap_read(struct regmap *map, unsigned int reg,
2429                         unsigned int *val)
2430 {
2431         int ret;
2432         void *context = _regmap_map_get_context(map);
2433 
2434         if (!map->cache_bypass) {
2435                 ret = regcache_read(map, reg, val);
2436                 if (ret == 0)
2437                         return 0;
2438         }
2439 
2440         if (map->cache_only)
2441                 return -EBUSY;
2442 
2443         if (!regmap_readable(map, reg))
2444                 return -EIO;
2445 
2446         ret = map->reg_read(context, reg, val);
2447         if (ret == 0) {
2448 #ifdef LOG_DEVICE
2449                 if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0)
2450                         dev_info(map->dev, "%x => %x\n", reg, *val);
2451 #endif
2452 
2453                 trace_regmap_reg_read(map, reg, *val);
2454 
2455                 if (!map->cache_bypass)
2456                         regcache_write(map, reg, *val);
2457         }
2458 
2459         return ret;
2460 }

3.2.2 regmap_write

函数原型

int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)

参数

struct regmap *map

regmap结构体指针

unsigned int reg

写的寄存器地址

unsigned int val

写寄存器的值

返回值

int

成功:0 失败:负数

功能

从设备的寄存器中写数据。regmap框架提供了一种统一的方式来访问设备的寄存器,无论这些寄存器是通过i2c、spi、内存映射还是其他方式访问的

1773 int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
1774 {
1775         int ret;
1776 
1777         if (!IS_ALIGNED(reg, map->reg_stride))
1778                 return -EINVAL;
1779 
1780         map->lock(map->lock_arg);
1781 
1782         ret = _regmap_write(map, reg, val);
1783 
1784         map->unlock(map->lock_arg);
1785 
1786         return ret;
1787 }
1734 int _regmap_write(struct regmap *map, unsigned int reg,
1735                   unsigned int val)
1736 {
1737         int ret;
1738         void *context = _regmap_map_get_context(map);
1739 
1740         if (!regmap_writeable(map, reg))
1741                 return -EIO;
1742 
1743         if (!map->cache_bypass && !map->defer_caching) {
1744                 ret = regcache_write(map, reg, val);
1745                 if (ret != 0)
1746                         return ret;
1747                 if (map->cache_only) {
1748                         map->cache_dirty = true;
1749                         return 0;
1750                 }
1751         }
1752 
1753 #ifdef LOG_DEVICE
1754         if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0)
1755                 dev_info(map->dev, "%x <= %x\n", reg, val);
1756 #endif
1757 
1758         trace_regmap_reg_write(map, reg, val);
1759 
1760         return map->reg_write(context, reg, val);
1761 }

4 示例

40 enum regcache_type {
  41         REGCACHE_NONE,
  42         REGCACHE_RBTREE,
  43         REGCACHE_COMPRESSED,
  44         REGCACHE_FLAT, 
  45 };     
#define MCU_REG_MAX									100

static bool mcu_is_volatile_reg(struct device *dev, unsigned int reg)
{       
        switch (reg) {
        case MCU_VID:
        case MCU_PID:
        case MCU_VERSION_MAJOR:
        case MCU_VERSION_MINOR:
        case MCU_POWER_LOSS:
        case MCU_RTC_WAKE:
        case MCU_WOL_WAKE:
        case MCU_WDT_TIMOUT:
        case MCU_WDT_CONTROL:
             return true;
        }
        
        return false;
}

static const struct regmap_config mcu_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
        .max_register = MCU_REG_MAX,
        .cache_type = REGCACHE_NONE,
        .volatile_reg = mcu_is_volatile_reg,
};

static int  spirit_mcu_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	int ret = 0;
	struct spirit_mcu *spirit_mcu;
	struct device_node *np = client->dev.of_node;

	spirit_mcu = devm_kzalloc(&client->dev, sizeof(struct spirit_mcu), GFP_KERNEL);
	if (!spirit_mcu)
		return -ENOMEM;


    spirit_mcu->regmap = devm_regmap_init_i2c(client, &mcu_regmap_config);
    if (IS_ERR(spirit_mcu->regmap)) {
            dev_err(&client->dev, "regmap initialization failed\n");
            return PTR_ERR(spirit_mcu->regmap);
    }
	spirit_mcu->userfeed = 0;
	i2c_set_clientdata(client, spirit_mcu);
	spirit_mcu->i2c = client;
	spirit_mcu->np = np;
	mcu_i2c_client = client;


	ret = regmap_read(spirit_mcu->regmap, MCU_VID, &spirit_mcu->deviceInfo.vid);
	if (ret) {
		dev_err(&client->dev, "read 0x%x failed\n", MCU_VID);
		//return ret;
	}
    
    return 0;
}


static const struct i2c_device_id spirit_mcu_id[] = {
	{ "spirit_mcu", 0 },
	{ }
};

static struct i2c_driver spirit_mcu_driver = {
	.driver		= {
		.name	= "spirit_mcu",
		.owner	= THIS_MODULE,
	},
	.probe		= spirit_mcu_probe,
 	.id_table	= spirit_mcu_id,
};

static int __init spirit_mcu_init(void)
{
	return i2c_add_driver(&spirit_mcu_driver);
}

static void __exit spirit_mcu_exit(void)
{
	unregister_reboot_notifier(&mcu_reboot_notifier);
	i2c_del_driver(&spirit_mcu_driver);
}

MODULE_AUTHOR("neilnee@jwele.com.cn");
MODULE_DESCRIPTION("spirit mcu driver");
MODULE_LICENSE("GPL");

late_initcall(spirit_mcu_init);
module_exit(spirit_mcu_exit);

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在NXP源码基础上适配ELF 1开发板的UART功能

UART即通用异步收发器&#xff0c;是一种支持全双工串行通信协议的接口。在i.MX6ULL处理器平台上&#xff0c;该处理器原生支持多达8路的UART接口&#xff0c;提供了丰富的串行通信能力。 针对ELF 1开发板&#xff0c;实际引出了4路UART接口供开发者使用&#xff0c;具体包括U…

艾默生电源维修ASTEC电源模块MP4-2Q-1E-4EE-0N

Emerson/ASTEC电源模块维修-艾默生/雅达电源维修MP1,MP4,MP6,MP8系列型号。 电源维修中&#xff0c;许多电源采用UC38系列8脚PWM组件&#xff0c;大多数电源不能工作都是因为电源启动电阻损坏&#xff0c;或芯片性能下降。当R断路后无VC&#xff0c;PWM组件无法工作&#xff0…

实现领域驱动设计(DDD)系列详解:集成限界上下文

一个项目中通常存在着多个限界上下文&#xff0c;并且我们需要在它们之间进行集成。 在上下文映射图中存在两种主要形式&#xff1a;一种是通过绘制一些简单的框图来展示它们之间的集成关系&#xff1b;另一种则是通过代码来实现这些集成关系。 到了具体的技术实现&#xff0…

重学SpringBoot3-自定义starter

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-自定义starter 1. 什么是 Spring Boot Starter&#xff1f;Starter 的优势 2. Spring Boot 3 中的改进3. 常见的 Starter 示例3.1. 使用 Web Starter 构…

华硕主板开启TPM 2.0

安装Windows11系统&#xff0c;需要打开TPM 安装 Windows 11 的方法 电脑健康状况检查应用验证最低系统要求 在电脑上启用 TPM 2.0 查看主板型号 winr msinfo32 查看 tpm 进入Advanced Mode&#xff08;F7&#xff09; 选择Security&#xff0c;进入Secure Boot&#xff0c;我…

echarts横向柱状图让Y轴的名字和数量在柱状图上方展示

效果图 let vm thisvm.chart2 echarts.init(this.$refs.chart2)let xDatas this.registerProjectType.map((item) > {let found data.find((countItem) > countItem.projectType item.label)return found ? found.count : 0})// 翻转数据让其他项目在最下面let xDa…

现场扫码实时投票打分显示最新现场大屏微信现场投票实时显示

现场投票“神器”超级好玩儿||现场参与者通过手机扫码进入投票系统&#xff0c;大屏幕实时显示投票排名&#xff0c;增加紧张和刺激感。可以随时截止投票&#xff0c;方便便捷&#xff0c;可设置 单票&#xff0c;多票&#xff0c;自由票&#xff0c;结合现场互动&#xff0c;增…

SEO全自动发布外链工具增加权重的网站工具源码系统 带源代码包以及搭建部署教程

系统概述 传统的手动发布外链方式不仅费时费力&#xff0c;而且效率低下。因此&#xff0c;开发一款能够全自动发布外链的工具成为了迫切的需求。SEO 全自动发布外链工具增加权重的网站工具源码系统正是在这样的背景下诞生的。它旨在为网站管理员提供一种便捷、高效的方式来增…

图论系列(dfs)9.25

一、主题空间 场地由若干主题空间与走廊组成&#xff0c;场地的地图记作由一维字符串型数组 grid&#xff0c;字符串中仅包含 "0"&#xff5e;"5" 这 6 个字符。地图上每一个字符代表面积为 1 的区域&#xff0c;其中 "0" 表示走廊&#xff0…

B站批量删除动态—Python

B站协议批量删除动态实现 b站登录协议请看点方蓝色字体 b站扫码登录协议 文章结尾附Python代码 一、抓包 1.1删除动态包 POST请求 https://api.bilibili.com/x/dynamic/feed/operate/remove?platformweb&csrf3bdb2bda73e3d6f75ea991167fb39389 请求表单数据{&quo…

基于python+django+vue的电影数据分析及可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

exebios提取工具通用exebios分离工具exe转编程器bios文件软件bios文件解密提取工具exe原厂bios提取烧录器bios芯片文件工具

好多电脑官网下载的BIOS文件是exe格式的特别是笔记本电脑&#xff0c;自己把电脑bios刷坏了黑屏不开机&#xff0c;需要用编程器刷BIOS&#xff0c;自然需要编程器版本的BIOS文件 需要把exe格式的BIOS文件转换成bin格式的编程器版本BIOS文件&#xff0c;转换需要用到一个小工具…

RAG技术全面解析:Langchain4j如何实现智能问答的跨越式进化?

LLM 的知识仅限于其训练数据。如希望使 LLM 了解特定领域的知识或专有数据&#xff0c;可&#xff1a; 使用本节介绍的 RAG 使用你的数据对 LLM 进行微调 结合使用 RAG 和微调 1 啥是 RAG&#xff1f; RAG 是一种在将提示词发送给 LLM 之前&#xff0c;从你的数据中找到并…

企业图纸文档管理系统推荐 三大企业图纸文档管理软件详细介绍

在现代企业的设计和生产过程中&#xff0c;图纸文档的管理是至关重要的一环。 无论是建筑、制造业&#xff0c;还是技术研发领域&#xff0c;图纸文档的正确存储、分享与管理能够极大提升工作效率&#xff0c;避免误操作或信息丢失。 接下来&#xff0c;小编将为大家推荐三款优…

8606 二叉树的构建及遍历操作

### 伪代码 1. **CreateBiTree**: - 读取一个字符 ch。 - 如果 ch 是 #&#xff0c;则当前节点为空。 - 否则&#xff0c;创建一个新节点 T&#xff0c;将 ch 赋值给 T 的数据域。 - 递归创建 T 的左子树。 - 递归创建 T 的右子树。 2. **PreOrderTraverse**: …

15 Midjourney从零到商用·实战篇:建筑设计与室内设计

以前设计师生成一张效果图需要先画草稿&#xff0c;导入三维软件搭建场景后&#xff0c;再用渲染器渲染&#xff0c;而现在只需要有客户的意向图或者自己想法&#xff0c;在MidJourney中就能一键生成惊艳的效果图。 “给我一个prompt我能撬动整个设计界”。设计师在AI绘画面前似…

安卓系统常见问题如native crash,卡顿卡死定位工具命令技巧-android framework实战开发

背景&#xff1a; 有学员朋友近来有问到一些安卓系统开发过程中的一些核心小技能小技巧等&#xff0c;比如native crash在企业里面该如何准确定位具体代码函数&#xff0c;程序卡住&#xff0c;或者长时间没反应&#xff0c;想要看看卡在代码的哪里。针对以上的一些问题&#…

中电金信:源启智能视觉分析系统~助力各行业破局升级,释放新质生产力

作为人工智能与计算机视觉的交叉范畴&#xff0c;智能视觉模仿人类视觉机能&#xff0c;来对各种形式的视觉输入予以处理、理解以及决策。当下&#xff0c;智能视觉已然发展为应用广泛、市场覆盖面大且形式多元的产业方向&#xff0c;获得了国家政策的强力支持。数字化时代搭台…

开源模型应用落地-qwen2.5-7b-instruct-LoRA微调-LLaMA-Factory-单机单卡-V100(十八)

一、前言 本篇文章将使用LLaMA-Factory去高效微调(命令和界面方式)QWen2.5系列模型,通过阅读本文,您将能够更好地掌握这些关键技术,理解其中的关键技术要点,并应用于自己的项目中。 QWen2系列模型微调: 开源模型应用落地-qwen2-7b-instruct-LoRA微调-LLaMA-Factory-单机单…

MySQL Mail服务器集成:如何配置发送邮件?

MySQL Mail插件使用指南&#xff1f;怎么优化 MySQL发邮件性能&#xff1f; MySQL Mail服务器的集成&#xff0c;使得数据库可以直接触发邮件发送&#xff0c;极大地简化了应用架构。AokSend将详细介绍如何配置MySQL Mail服务器&#xff0c;以实现邮件发送功能。 MySQL Mail&…