RT-Thread PIN设备

RT-Thread PIN设备

  • RT-Thread PIN设备驱动框架
    • RT-Thread PIN设备驱动层次图
    • RT-Thread PIN设备注册
      • RT-Thread PIN设备注册函数
    • RT-Thread PIN设备操作函数
      • pin_get
      • pin_mode
      • pin_write
      • pin_read
      • pin_attach_irq
      • pin_detach_irq
      • pin_irq_enable

PIN设备又叫GPIO设备,是MCU输入输出的一种设备,RT-Thread将GPIO抽象成PIN设备,以实现对GPIO的基本操作。
在这里插入图片描述
在这里插入图片描述

比如上面两个GPIO设备,其中一个作为输出控制LED灯的亮灭,一个作为输入判断按键的高低电平。
对于GPIO的操作都有以下几点:

  • 设置GPIO的方向,是作为输入还是输出
  • 设置GPIO的属性,是上拉,下拉,还是推挽、开漏等
  • 设置GPIO的高低电平或者读取GPIO的电平
  • 如果需要中断,还需要设置GPIO的中断
  • 有些GPIO能复用成其他外设功能,比如ADC、UART等

RT-Thread的PIN设备框架就需要实现上面的GPIO基本功能。

RT-Thread PIN设备驱动框架

RT-Thread PIN设备驱动层次图

在这里插入图片描述

RT-Thread PIN设备注册

RT-Thread PIN设备注册函数

int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data)
{_hw_pin.parent.type         = RT_Device_Class_Miscellaneous;_hw_pin.parent.rx_indicate  = RT_NULL;_hw_pin.parent.tx_complete  = RT_NULL;#ifdef RT_USING_DEVICE_OPS_hw_pin.parent.ops          = &pin_ops; 
#else_hw_pin.parent.init         = RT_NULL;_hw_pin.parent.open         = RT_NULL;_hw_pin.parent.close        = RT_NULL;_hw_pin.parent.read         = _pin_read;_hw_pin.parent.write        = _pin_write;_hw_pin.parent.control      = _pin_control;
#endif_hw_pin.ops                 = ops; // PIN设备 操作函数_hw_pin.parent.user_data    = user_data;/* register a character device */rt_device_register(&_hw_pin.parent, name, RT_DEVICE_FLAG_RDWR); // 注册PIN设备return 0;
}

PIN设备的关键是用户的OPS操作函数

RT-Thread PIN设备操作函数

struct rt_pin_ops
{void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_base_t mode);void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_base_t value);int (*pin_read)(struct rt_device *device, rt_base_t pin);rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_int32_t pin,rt_uint32_t mode, void (*hdr)(void *args), void *args);rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_int32_t pin);rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled);rt_base_t (*pin_get)(const char *name);
};
  • pin_mode:设置GPIO的模式,比如上拉下拉。
  • pin_write:设置GPIO的电平状态。
  • pin_read:读取GPIO的电平。
  • pin_attach_irq:绑定GPIO中断。
  • pin_detach_irq:脱离GPIO中断。
  • pin_irq_enable:GPIO中断使能。
  • pin_get:获取GPIO编号。

注意事项:引脚编号
对于MCU厂商来说,会给自家MCU的GPIO进行一个分类,比如STM32的MCU就会以PAX、PBX等名称进行分类,而像NXP的就会以GPIO1_IOX、GPIO2_IOX等名称进行分类。RT-Thread的PIN设备框架为了能做到通用,统一使用了引脚编号这个属性,不管MCU的引脚怎么命名,在RT-Thread里面都是以0、1、2、3等数字进行操作。

pin_get

pin_get函数的作用是获取MCU的引脚编号。下面以STM32为例进行说明

#define PIN_NUM(port, no) (((((port)&0xFu) << 4) | ((no)&0xFu)))
/* e.g. PE.7 */
static rt_base_t stm32_pin_get(const char *name)
{rt_base_t pin = 0;int hw_port_num, hw_pin_num = 0;int i, name_len;name_len = rt_strlen(name);if ((name_len < 4) || (name_len >= 6)) // 判断传入的引脚名字长度是否非法{goto out;}if ((name[0] != 'P') || (name[2] != '.')) // 判断传入的引脚名字的第0和第2位是否非法{goto out;}if ((name[1] >= 'A') && (name[1] <= 'Z')) // 判断传入的引脚范围是否非法{hw_port_num = (int)(name[1] - 'A');}else{goto out;}for (i = 3; i < name_len; i++) // 计算引脚编号{hw_pin_num *= 10;hw_pin_num += name[i] - '0';}pin = PIN_NUM(hw_port_num, hw_pin_num); // 返回引脚编号return pin;out:rt_kprintf("Px.y  x:A~Z  y:0-15, e.g. PA.0\n");return -RT_EINVAL;
}

比如传入的引脚名字为PB.0,那么通过计算可以得到PB.0的引脚编号为16。不同的MCU计算方法可能会不一样,但是道理都是一样的,就是将引脚名称全部转化为引脚编号

pin_mode

pin_mode作用是设置GPIO引脚的模式

/*
device :设备句柄
pin    :引脚编号
mode   :引脚模式
*/void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_base_t mode);

RT-Thread提供以下几种GPIO的引脚模式

模式说明
PIN_MODE_OUTPUT输出模式
PIN_MODE_INPUT输入模式
PIN_MODE_INPUT_PULLUP输入上拉
PIN_MODE_INPUT_PULLDOWN输入下拉
PIN_MODE_OUTPUT_OD开漏输出
下面以STM32为例进行说明

static void stm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
{GPIO_InitTypeDef GPIO_InitStruct;if (PIN_PORT(pin) >= PIN_STPORT_MAX) // 判断输入的引脚编号是否非法{return;}/* Configure GPIO_InitStructure */GPIO_InitStruct.Pin = PIN_STPIN(pin);GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;if (mode == PIN_MODE_OUTPUT) // 配置引脚为输出模式{/* output setting */GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;}else if (mode == PIN_MODE_INPUT) // 配置引脚为输入模式{/* input setting: not pull. */GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;}else if (mode == PIN_MODE_INPUT_PULLUP) // 配置引脚为上拉输入模式{/* input setting: pull up. */GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;}else if (mode == PIN_MODE_INPUT_PULLDOWN) // 配置引脚为下拉输入模式{/* input setting: pull down. */GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLDOWN;}else if (mode == PIN_MODE_OUTPUT_OD) // 配置引脚为开漏输出模式{/* output setting: od. */GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;}HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct); // 配置GPIO
}

如果MCU还有其他的模式配置可以自行添加

pin_write

pin_write作用是设置GPIO引脚的电平状态

/*
device :设备句柄
pin    :引脚编号
value  :输出电平
*/void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_base_t value);

RT-Thread提供以下的电平

电平状态说明
PIN_LOW低电平
PIN_HIGH高电平
下面以STM32为例进行说明
static void stm32_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
{GPIO_TypeDef *gpio_port;uint16_t gpio_pin;if (PIN_PORT(pin) < PIN_STPORT_MAX) // 判断输入的引脚编号是否非法{gpio_port = PIN_STPORT(pin);gpio_pin = PIN_STPIN(pin);HAL_GPIO_WritePin(gpio_port, gpio_pin, (GPIO_PinState)value); // 设置GPIO电平}
}

pin_read

pin_read作用是读取GPIO引脚的电平状态

/*
device :设备句柄
pin    :引脚编号
返回值: GPIO电平
*/int (*pin_read)(struct rt_device *device, rt_base_t pin);
电平状态说明
PIN_LOW低电平
PIN_HIGH高电平
下面以STM32为例进行说明
static rt_ssize_t stm32_pin_read(rt_device_t dev, rt_base_t pin)
{GPIO_TypeDef *gpio_port;uint16_t gpio_pin;GPIO_PinState state = GPIO_PIN_RESET;if (PIN_PORT(pin) < PIN_STPORT_MAX) // 判断输入的引脚编号是否非法{gpio_port = PIN_STPORT(pin);gpio_pin = PIN_STPIN(pin);state = HAL_GPIO_ReadPin(gpio_port, gpio_pin); // 读取GPIO电平}else{return -RT_EINVAL;}return (state == GPIO_PIN_RESET) ? PIN_LOW : PIN_HIGH; // 返回高或低
}

pin_attach_irq

pin_attach_irq作用是绑定GPIO引脚中断

/*
device :设备句柄
pin    :引脚编号
mode   :引脚中断类型
hdr    :引脚中断函数
args   :中断函数参数
返回值:错误代码
*/rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_int32_t pin,rt_uint32_t mode, void (*hdr)(void *args), void *args);

RT-Thread提供以下的引脚触发类型

触发类型说明
PIN_IRQ_MODE_RISING上升沿触发
PIN_IRQ_MODE_FALLING下升沿触发
PIN_IRQ_MODE_RISING_FALLING双边沿触发
PIN_IRQ_MODE_HIGH_LEVEL高电平触发
PIN_IRQ_MODE_LOW_LEVEL低电平触发

引脚的中断绑定函数需要在程序中进行保存,所以可以建一张中断表保存引脚的中断函数,当中断来临的时候,再通过查表的方式进行调用。下面以STM32为例进行说明

// 引脚的中断表
static struct rt_pin_irq_hdr pin_irq_hdr_tab[] =
{{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},{-1, 0, RT_NULL, RT_NULL},
};static rt_err_t stm32_pin_attach_irq(struct rt_device *device, rt_base_t pin,rt_uint8_t mode, void (*hdr)(void *args), void *args)
{rt_base_t level;rt_int32_t irqindex = -1;if (PIN_PORT(pin) >= PIN_STPORT_MAX) // 判断引脚编号是否非法{return -RT_ENOSYS;}irqindex = bit2bitno(PIN_STPIN(pin)); // 通过引脚编号反推得到中断号if (irqindex < 0 || irqindex >= (rt_int32_t)ITEM_NUM(pin_irq_map)) // 判断中断号是否非法{return -RT_ENOSYS;}level = rt_hw_interrupt_disable(); // 关闭中断if (pin_irq_hdr_tab[irqindex].pin == pin &&pin_irq_hdr_tab[irqindex].hdr == hdr &&pin_irq_hdr_tab[irqindex].mode == mode &&pin_irq_hdr_tab[irqindex].args == args) // 是否重复注册引脚中断{rt_hw_interrupt_enable(level);return RT_EOK;}if (pin_irq_hdr_tab[irqindex].pin != -1) // 中断号是否已经被注册{rt_hw_interrupt_enable(level);return -RT_EBUSY;}// 更新中断表pin_irq_hdr_tab[irqindex].pin = pin; pin_irq_hdr_tab[irqindex].hdr = hdr;pin_irq_hdr_tab[irqindex].mode = mode;pin_irq_hdr_tab[irqindex].args = args;rt_hw_interrupt_enable(level); // 开启中断return RT_EOK;
}
rt_inline void pin_irq_hdr(int irqno) 
{if (pin_irq_hdr_tab[irqno].hdr) // 通过查表执行中断函数{pin_irq_hdr_tab[irqno].hdr(pin_irq_hdr_tab[irqno].args);}
}

上面的函数通过引脚编号得到相应的引脚中断号,然后将引脚的中断函数注册进中断表,当中断来临的时候通过pin_irq_hdr函数在中断表找到相应的中断函数然执行。

pin_detach_irq

pin_detach_irq作用是解绑GPIO引脚中断

/*
device :设备句柄
pin    :引脚编号
返回值: 错误代码
*/rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_int32_t pin);

下面以STM32为例进行说明

static rt_err_t stm32_pin_dettach_irq(struct rt_device *device, rt_base_t pin)
{rt_base_t level;rt_int32_t irqindex = -1;if (PIN_PORT(pin) >= PIN_STPORT_MAX) // 判断引脚编号是否非法{return -RT_ENOSYS;}irqindex = bit2bitno(PIN_STPIN(pin));if (irqindex < 0 || irqindex >= (rt_int32_t)ITEM_NUM(pin_irq_map)) // 判断中断号是否非法{return -RT_ENOSYS;}level = rt_hw_interrupt_disable(); // 关闭中断if (pin_irq_hdr_tab[irqindex].pin == -1) // GPIO引脚中断没有中断{rt_hw_interrupt_enable(level);return RT_EOK;}// 将GPIO中断号对应的中断表索引属性清空pin_irq_hdr_tab[irqindex].pin = -1;pin_irq_hdr_tab[irqindex].hdr = RT_NULL;pin_irq_hdr_tab[irqindex].mode = 0;pin_irq_hdr_tab[irqindex].args = RT_NULL;rt_hw_interrupt_enable(level);return RT_EOK;
}

pin_irq_enable

pin_irq_enable作用是使能GPIO引脚中断

/*
device :设备句柄
pin    :引脚编号
enabled: 使能
返回值: 错误代码
*/
rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled);

以下以STM32为例


static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,rt_uint8_t enabled)
{const struct pin_irq_map *irqmap;rt_base_t level;rt_int32_t irqindex = -1;GPIO_InitTypeDef GPIO_InitStruct;if (PIN_PORT(pin) >= PIN_STPORT_MAX) // 判断引脚编号是否非法{return -RT_ENOSYS;}if (enabled == PIN_IRQ_ENABLE) // 如果引脚中断使能{irqindex = bit2bitno(PIN_STPIN(pin));if (irqindex < 0 || irqindex >= (rt_int32_t)ITEM_NUM(pin_irq_map))  // 判断中断号是否非法{return -RT_ENOSYS;}level = rt_hw_interrupt_disable(); // 关中断if (pin_irq_hdr_tab[irqindex].pin == -1) // 如果中断号没有注册{rt_hw_interrupt_enable(level);return -RT_ENOSYS;}irqmap = &pin_irq_map[irqindex];/* Configure GPIO_InitStructure */GPIO_InitStruct.Pin = PIN_STPIN(pin);GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;switch (pin_irq_hdr_tab[irqindex].mode)  // 设置GPIO中断模式{case PIN_IRQ_MODE_RISING:GPIO_InitStruct.Pull = GPIO_PULLDOWN;GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; // 上升沿触发break;case PIN_IRQ_MODE_FALLING:GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;  // 下升沿触发break;case PIN_IRQ_MODE_RISING_FALLING:GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;  // 双边沿触发break;}HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct);// 使能GPIO中断HAL_NVIC_SetPriority(irqmap->irqno, 5, 0);HAL_NVIC_EnableIRQ(irqmap->irqno);pin_irq_enable_mask |= irqmap->pinbit;rt_hw_interrupt_enable(level);}else if (enabled == PIN_IRQ_DISABLE) // 引脚中断不使能{irqmap = get_pin_irq_map(PIN_STPIN(pin));if (irqmap == RT_NULL){return -RT_ENOSYS;}level = rt_hw_interrupt_disable();HAL_GPIO_DeInit(PIN_STPORT(pin), PIN_STPIN(pin));pin_irq_enable_mask &= ~irqmap->pinbit;
#if defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0)if ((irqmap->pinbit >= GPIO_PIN_0) && (irqmap->pinbit <= GPIO_PIN_1)){if (!(pin_irq_enable_mask & (GPIO_PIN_0 | GPIO_PIN_1))){HAL_NVIC_DisableIRQ(irqmap->irqno);}}else if ((irqmap->pinbit >= GPIO_PIN_2) && (irqmap->pinbit <= GPIO_PIN_3)){if (!(pin_irq_enable_mask & (GPIO_PIN_2 | GPIO_PIN_3))){HAL_NVIC_DisableIRQ(irqmap->irqno);}}else if ((irqmap->pinbit >= GPIO_PIN_4) && (irqmap->pinbit <= GPIO_PIN_15)){if (!(pin_irq_enable_mask & (GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 |GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15))){HAL_NVIC_DisableIRQ(irqmap->irqno);}}else{HAL_NVIC_DisableIRQ(irqmap->irqno);}
#elseif ((irqmap->pinbit >= GPIO_PIN_5) && (irqmap->pinbit <= GPIO_PIN_9)){if (!(pin_irq_enable_mask & (GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9))){HAL_NVIC_DisableIRQ(irqmap->irqno);}}else if ((irqmap->pinbit >= GPIO_PIN_10) && (irqmap->pinbit <= GPIO_PIN_15)){if (!(pin_irq_enable_mask & (GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15))){HAL_NVIC_DisableIRQ(irqmap->irqno);}}else{HAL_NVIC_DisableIRQ(irqmap->irqno);}
#endifrt_hw_interrupt_enable(level);}else{return -RT_ENOSYS;}return RT_EOK;
}

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

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

相关文章

SpringSecurity-入门代码

创建SpringBoot项目 参考文章&#xff1a; 【环境搭建】使用IDEA创建SpringBoot项目详细步骤_idea创建spring boot项目-CSDN博客 编写helloworld代码 RestController public class HelloController {GetMapping("/hello")public String hello(){return "hel…

深入了解SD-WAN:企业广域网的未来

在讨论SD-WAN之前&#xff0c;我们先来了解一下WAN的基本概念。WAN&#xff08;广域网&#xff09;是一个连接多个地理位置分散的局域网的通信网络。在企业中&#xff0c;WAN通常连接总部、分支机构、托管设施和云服务等多个网络节点。广域网允许用户共享各种应用和服务&#x…

【AI绘画】新手小白看这篇就够啦!国产PS AI插件超好入门!

随着人工智能技术的飞速发展&#xff0c;Photoshop作为设计师们不可或缺的工具&#xff0c;也在不断地融入AI技术&#xff0c;以提升设计效率和效果。最近米兔用了一款AI绘画软件StartAI&#xff0c;被其强大的功能和易用性经验到了&#xff0c;下面跟大家详细分享一下这款ps插…

ViNT: A Foundation Model for Visual Navigation

介绍 现存的问题&#xff1a;预训练的方式在很多领域取得了成功&#xff0c;但是由于环境、平台和应用程序的绝对多样性&#xff0c;因此很难应用在机器人领域。 那么想要做移动机器人的基础模型需要什么&#xff1f; 本文定义了一个机器人领域的基础模型&#xff0c;可以实…

文字炫酷祝福 含魔法代码

效果下图&#xff1a;&#xff08;可自定义显示内容&#xff09; 代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initi…

移动机器人程序节点崩溃的处理

对于一些特殊情况例如程序节点崩溃&#xff0c;可能需要一些特殊的处理方法。处理目的是为了保证程序出现特殊异常情况导致崩溃也能在每人干预的情况下正常运行并完成某些初始化状态。常见处理工程化方法如下。 针对节点崩溃问题&#xff0c;可以设置守护进程或脚本来监控程序运…

TS中的内置工具

在TypeScript&#xff08;TS&#xff09;中&#xff0c;有多种内置的工具和类型工具&#xff0c;它们帮助开发者更有效地编写和维护类型安全的代码。以下是一些主要的内置工具及其功能概述&#xff1a; 类型别名&#xff08;Type Aliases&#xff09;&#xff1a; 类型别名是一…

代码随想录算法训练营第42天 [1049. 最后一块石头的重量 II 494. 目标和 474.一和零]

代码随想录算法训练营第42天 [1049. 最后一块石头的重量 II 494. 目标和 474.一和零] **一、1049. 最后一块石头的重量 II ** 链接: 代码随想录. 思路&#xff1a;石头相撞重量最小&#xff0c;最小的情况就是刚好分为两组大小相同的&#xff0c;这样相撞后重量就为0 所以转化为…

【RK3588/算能/Nvidia智能盒子】AI“值守”,规范新能源汽车充电站停车、烟火及充电乱象

近年来&#xff0c;中国新能源汽车高速发展&#xff0c;产量连续8年位居全球第一。根据中国充电联盟数据&#xff0c;截至2023年6月&#xff0c;新能源汽车保有量1620万辆&#xff0c;全国充电基础设施累计数量为665.2万台&#xff0c;车桩比约2.5:1。 虽然新能源汽车与充电桩供…

mysql--安装跳过验证修改密码安全加固

安装mysql 配置mysql的yum源 [rootVM-0-14-rockylinux ~]# tee /etc/yum.repos.d/mysql.repo << EOF > [MYSQL] > namemysql > baseurlhttps://mirrors.tuna.tsinghua.edu.cn/mysql/yum/mysql-5.7-community-el7-x86_64 > gpgcheck0 > EOF yum安装mysq…

Playwright工作原理

执行test时&#xff0c;有哪些关键步骤 当我们用Playwright编写一段简单的test script&#xff0c;代码如下所示&#xff1a;在test case中第一段代码就是await page.goto(xxxxx) import { test, expect } from playwright/test;test(test, async ({ page }) > {await page…

浅谈LavelDB

简介 LevelDB 是一个开源的轻量级键值存储库&#xff0c;由 Google 开发&#xff0c;用于提供快速的键值存储和支持读写大量数据。LevelDB 具有高性能、快速的读取和写入速度以及支持原子操作的特点&#xff0c;适合用于需要高效存储和检索键值数据的场景。 LevelDB 主要特点…

NVIDIA新模型Nemotron-4:98%的训练数据是合成生成的,你敢信?

获取本文论文原文PDF&#xff0c;请公众号 AI论文解读 留言&#xff1a;论文解读 标题&#xff1a;Nemotron-4 340B Technical Report 模型概述&#xff1a;Nemotron-4 340B系列模型的基本构成 Nemotron-4 340B系列模型包括三个主要版本&#xff1a;Nemotron-4-340B-Base、…

77道经典的软件测试面试题(答案+文档)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、问&#xff1a;你在测试中发现了一个bug&#xff0c;但是开发经理认为这不是一个bug&#xf…

【ARM-Linux篇】POSIX消息队列

System V消息队列POSIX 消息队列主 要 函 数#include <sys/msg.h> int msgget(key_t key, int oflag) int msgsnd(int msqid, const void * ptr, size_t length, int flag) ssize_t msgrcv (int msqid, void *ptr, size_t length, long type, int flag) int msgctl(int m…

Lua迭代器详解(附加红点功能实例)

Lua迭代器详解与用法 1. 什么是迭代器2. 为什么需要理解迭代器的原理3. 迭代器的实现0. 闭包1. 有状态迭代器2. 无状态迭代器 4. 红点树系统基础 1. 什么是迭代器 迭代器是一种能让我们遍历一个集合中的所有元素的代码结构。比如常用ipairs()和pairs()。 2. 为什么需要理解迭代…

SSH生成SSH密钥(公钥和私钥)

在设置SSH服务时&#xff0c;生成SSH密钥&#xff08;公钥和私钥&#xff09;是一个常见的任务。这些密钥用于安全地进行身份验证&#xff0c;无需输入密码。以下是如何生成SSH密钥的步骤&#xff1a; 1. 生成SSH密钥对 首先&#xff0c;您需要在客户端机器上生成一个SSH密钥…

算法设计与分析期末复习题

一&#xff1a;程序阅读分析题&#xff08;共40分&#xff09; 1.&#xff08;8分&#xff09;阅读“算法1”&#xff0c;分析算法1的功能、时间复杂度。 答案&#xff1a;经典的汉诺塔问题&#xff0c;其目标是将 n 个不同大小的盘子从柱子 A 移动到柱子 C&#xff0c;借助柱…

单例设计模式双重检查的作用

先看双重校验锁的写法 public class Singleton {/*volatile 修饰&#xff0c;singleton new Singleton() 可以拆解为3步&#xff1a;1、分配对象内存(给singleton分配内存)2、调用构造器方法&#xff0c;执行初始化&#xff08;调用 Singleton 的构造函数来初始化成员变量&am…

停车场控制机系统哪家好?捷顺捷曜分体式车场控制机有哪些功能亮点?

停车场控制机为现代城市提供了许多便利和好处。首先&#xff0c;它能够自动记录车辆进出的时间&#xff0c;便于车主和管理人员进行费用计算。其次&#xff0c;通过车牌识别技术&#xff0c;提高了车辆进出的效率&#xff0c;减少了排队等待时间。此外&#xff0c;控制机还可以…