六、(正点原子)pinctrl子系统和gpio子系统

        前面我们使用设备树来驱动LED灯,其实就是将LED寄存器地址写入到设备树的属性reg中,通过OF函数 ,读取到LED灯的寄存器信息,从而操作寄存器来控制LED灯。在操作LED灯时候,我们使用到GPIO这个引脚,通过对这个GPIO的控制来实现LED灯的控制。

一、pinctrl子系统

        pinctrl子系统,用来设置pin(引脚)的复用功能和配置这个pin的电气属性。主要体现:

  • 获取设备树中pin信息。
  • 根据获取到的pin信息来设备pin的复用功能。
  • 根据获取到的pin信息来设备pin的电气属性,比如上/下拉、速度、驱动能力等。

        对于我们来说,只需要在设备树里面设置好某个pin的相关属性,其他的初始化工作pinctrl子系统来完成,pinctrl子系统源码目录为drivers/pinctrl

        pin配置信息详解

        要使用 pinctrl 子系统,我们需要在设备树里面设置 PIN 的配置信息,毕竟 pinctrl 子系统要
根据你提供的信息来配置 PIN 功能,一般会在设备树里面创建一个节点来描述 PIN 的配置信
息。在imx6ull.dtsi中有者三个节点表示imx6ullpin引脚

iomuxc: iomuxc@020e0000 {
	compatible = "fsl,imx6ul-iomuxc";
	reg = <0x020e0000 0x4000>;
};


gpr: iomuxc-gpr@020e4000 {
	compatible = "fsl,imx6ul-iomuxc-gpr",
	"fsl,imx6q-iomuxc-gpr", "syscon";
	reg = <0x020e4000 0x4000>;
};

iomuxc_snvs: iomuxc-snvs@02290000 {
	compatible = "fsl,imx6ull-iomuxc-snvs";
	reg = <0x02290000 0x10000>;
};

 imx6ull的参考手册

        在imx6ull-alientek-emmc.dts中,对pin进行追加信息比如:

 不同的外设使用的 PIN 不同、其配置也不同,因此一个萝卜一个坑,将某个外设所使用的所有 PIN 都组织在一个子节点里面。其中,在iomux节点下有个imx6ul-evk的子结点,这个节点就是用来描述evk这个开发板外设所使用到的pin。简单来说就是在这个节点来表示出来evk开发板的各个功能使用到哪些引脚和引脚是哪一个。比如:hoggrp-1这个evk节点下面的子结点,表示热插拔功能所需要的引脚。

        关于MX6UL_PAD_UART1_RTS_B__GPIO1_IO19       0x17059 含义:

这是一个宏定义,定义在文件arch/arm/boot/dts/imx6ul-pinfunc.h 中, imx6ull.dtsi 会引用 imx6ull-pinfunc.h 这个头文件,而imx6ull-pinfunc.h 又会引用 imx6ul-pinfunc.h 这个头文件,

        在imx6ull参考手册中我们可以看出来MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 这个宏就是表示UART1_RTS_B这个引脚复用为GPIO1_IO19功能 。

<mux_reg   conf_reg    input_reg      mux_mode    input_val>
 0x0090    0x031C      0x0000         0x5         0x0

         0x0090mux_reg寄存器偏移地址,复用功能寄存器地址。

        0x031C conf_reg 寄存器偏移地址,表示IOMUXC_SW_PAD_CTL_PAD_UART1_RTS_B寄存器的地址。

        0x0000 input_reg 寄存器偏移地址,有些外设有 input_reg 寄存器,有 input_reg 寄存器的
外设需要配置 input_reg 寄存器。没有的话就不需要设置, UART1_RTS_B 这个 PIN 用做
GPIO1_IO19 的时候是没有 input_reg 寄存器,因此这里 intput_reg 是无效的。

        0x5mux_reg 寄 存 器 值,相 当 于 设 置IOMUXC_SW_MUX_CTL_PAD_UART1_RTS_B 寄存器为 0x5,也即是设置 UART1_RTS_B 这个 PIN 复用为 GPIO1_IO19

        0x0input_reg 寄存器值,应为这个引脚没有input_reg寄存器,所以无法向里面写入值。

MX6UL_PAD_UART1_RTS_B__GPIO1_IO19       0x17059中的0x17059其实就是conf_reg寄存器的值,这个值由我们子设备,相当于配置这个引脚的电气属性。

         设备树中添加pinctrl节点模板

         关 于 I.MX 系 列 SOC 的 pinctrl 设 备 树 绑 定 信 息 可 以 参 考 文 档
Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt

二、gpio子系统

         前面pinctrl子系统主要是设置引脚的复用功能和电气属性,如果 pinctrl 子系统将一个 PIN 复用为 GPIO 的话,那么接下来就要用到 gpio 子系统了。 gpio 子系统顾名思义,就是用于初始化 GPIO 并且提供相应的 API 函数,比如设置 GPIO为输入输出,读取 GPIO 的值等。 gpio 子系统的主要目的就是方便驱动开发者使用 gpio,驱动开发者在设备树中添加 gpio 相关信息,然后就可以在驱动程序中使用 gpio 子系统提供的 API函数来操作 GPIO, Linux 内核向驱动开发者屏蔽掉了 GPIO 的设置过程,极大的方便了驱动开发者使用 GPIO

        设备树中的gpio信息

        比如我们在imx6ull-alientek-emmc.dts,有usdhc1这样一个节点:

         pinctrl-name:用来表示设备的状态,这里有2个,分别为默认状态(default)和休眠状态(sleep)还可以自定义状态,比如state_100mhz:表示这个gpio运行为100mhz状态。

        pinctrl-0:表示第0个状态对应于"default"状态,对应的引脚在pinctrl-0里面定义。

        pinctrl-1:表示第1个状态对应于"state_100mhz"状态,对应的引脚在pinctrl-1里面定义。

        cd-gpios:描述usdhc1使用到的IO引脚“&gpio1”表示 引脚所使用的 IO 属于 GPIO1 组,“19”表示 GPIO1 组的第 19 号 IO,“GPIO_ACTIVE_LOW”表示低电平有效,如果改为“GPIO_ACTIVE_HIGH”就表示高电平有效。
 

        gpio子系统API函数 

        1、gpio_request函数

        用于申请一个 GPIO 管脚,在使用一个 GPIO 之前一定要使用 gpio_request进行申请,定义在linux/gpio.h中函数原型如下:

static inline int gpio_request(unsigned gpio, const char *label)

        gpio:要申请的gpio标号,使用 of_get_named_gpio 函数从设备树获取指定 GPIO 属性信
息,此函数会返回这个 GPIO 的标号。

        label:gpio 设置个名字。

        返回值:0,申请成功;其他值,申请失败。

        2、gpio_free函数

        如果不使用某个 GPIO 了,那么就可以调用 gpio_free 函数进行释放。函数原型如下:

static inline void gpio_free(unsigned gpio)

        gpio: 要释放的 gpio 标号。

        3、gpio_direction_input、gpio_direction_output函数 

        设置某个 GPIO 为输入输出,函数原型如下所示:

static inline int gpio_direction_input(unsigned gpio)

static inline int gpio_direction_output(unsigned gpio, int value)

        gpio: 要设置的 GPIO 标号。

        value:设置为输出时,GPIO 默认输出值。

        返回值:0,设置成功;负值,设置失败。

        4、gpio_get_value、gpio_set_value函数

        用于获取和设置某个 GPIO 的值(0 或 1),定义所示:

static inline int gpio_get_value(unsigned gpio)

static inline void gpio_set_value(unsigned gpio, int value)

       gpio: 要设置的 GPIO 标号。

       value: 要设置的值。

       返回值:负值,获取失败,否者得到的GPIO值。

        与gpio相关的OF函数

        1、of_gpio_named_count函数

        获取设备树某个属性里面定义了几个 GPIO 信息,要注意的是空的 GPIO 信息也会被统计到,比如:

gpios = <0
         &gpio1 1 2
         0
         &gpio2 3 4>;

        上述代码的“gpios”节点一共定义了 4 个 GPIO,但是有 2 个是空的,没有实际的含义。
通过 of_gpio_named_count 函数统计出来的 GPIO 数量就是 4 个,定义在linux/of_gpio.h里面,此函数原型如下:

static inline int of_gpio_named_count(struct device_node *np, const char* propname)

        np:设备节点。

        propname:要统计的GPIO属性名字。

        返回值:正值,统计到的 GPIO 数量;负值,失败。

        2、of_gpio_count函数

        和 of_gpio_named_count 函数一样,但是不同的地方在于,此函数统计的是“gpios”这个属
性的 GPIO 数量,而 of_gpio_named_count 函数可以统计任意属性的 GPIO 信息,函数原型如下所示:

static inline int of_gpio_count(struct device_node *np)

        np:设备节点。

        返回值:正值,统计到的 GPIO 数量;负值,失败。 

        3、of_get_named_gpio函数

        获取 GPIO 编号,因为 Linux 内核中关于 GPIO 的 API 函数都要使用 GPIO 编号,
此函数会将设备树中类似<&gpio5 7 GPIO_ACTIVE_LOW>的属性信息转换为对应的 GPIO
号,此函数在驱动中使用很频繁!函数原型如下:

static inline int of_get_named_gpio(struct device_node *np,
                                    const char *propname, 
                                    int index)

         np:设备节点。

        propname:要统计的GPIO属性名字。

        index:GPIO 索引,因为一个属性里面可能包含多个 GPIO,此参数指定要获取哪个 GPIO
的编号,如果只有一个 GPIO 信息的话此参数为 0。

        返回值:正值,获取到的 GPIO 编号;负值,失败。
 

三、使用pinctrl子系统和gpio子系统

        我们以正点原子阿尔法开发板为例,在设备树中添加LED灯的信息,通过pinctrl子系统和gpio子系统来配置LED的引脚,从而控制LED灯的开关。

        1、修改设备树文件

        ①、添加pinctrl子结点

        在原理图中,LED灯连接到了GPIO1_IO03这个引脚,所以我们的将这个引脚复用为GPIO1_IO03功能,并配置引脚的电气属性。

        打开imx6ull-alientekemmc.dts,在 iomuxc 节点的 imx6ul-evk 子节点下创建一个名为“pinctrl_led”的子节点:

        ②、添加 LED 设备节点

        在根节点“/”下创建 LED 灯节点,节点名为“gpioled”

        ③、检查引脚是否被使用 

        我们所使用的设备树基本都是在半导体厂商提供的设备树文件基础上修改而来的,而半导体厂商提供的设备树是根据自己官方开发板编写的,很多 PIN 的配置和我们所使用的开发板不一样。检查 PIN 有没有被其他外设使用包括两个方面:

  • 检查 pinctrl 设置。
  • 如果这个 PIN 配置为 GPIO 的话,检查这个 GPIO 有没有被别的外设使用。

        编译设备树,使用新编译的设备树文件,查看/proc/device-tree/是否存在我们添加的节点:

        2、LED灯驱动程序编写 

        参考:五、(正点原子)设备树下的LED驱动-CSDN博客

         当我们驱动框架搭建好以后,需要使用OF函数,获取设备树中LED节点的属性信息。

        在LED控制函数中,我们就可以直接使用gpio子系统的API函数来对GPIO进行读写操作:

 最终的gpioled.c驱动文件:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ide.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/err.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>

#define GPIOLED_CNT      1
#define GPIOLED_NAME     "gpioled"

#define LED_ON      1
#define LED_OFF     0



/* gpioled设备结构体 */
typedef struct gpioled_dev{
    dev_t devid;                    /* 设备号   */
    int major;                      /* 主设备号 */
    int minor;                      /* 次设备号 */
    struct cdev cdev;               /* 字符设备 */
    struct class *class;            /* 类      */
    struct device *device;          /* 类的设备 */
    struct device_node *nd;         /* 节点 */
    int led_gpio;                   /* LED的gpio编号 */
}gpioled_dev;
gpioled_dev gpioled;



/* LED等控制函数 */
static int Led_Switch(unsigned char Led_Status)
{

    if(Led_Status == LED_ON){
        gpio_set_value(gpioled.led_gpio,0);
    }else if(Led_Status == LED_OFF){
        gpio_set_value(gpioled.led_gpio,1);
    }else{
        return -1;
    }
    return 0;
}

/* 打开驱动文件 */
static int gpioled_open (struct inode *Inode, struct file *File)
{
    File->private_data = &gpioled;   /* 设置私有数据 */
    return 0;
}
/* 关闭驱动文件 */
static int gpioled_release (struct inode *Inode, struct file *File)
{

    return 0;
}
/* 对驱动文件进行写操作 */
static ssize_t gpioled_write (struct file *File, const char __user *buf,
                            size_t Count, loff_t *Loff)
{
    int ret = 0;
    unsigned char databuf[1];

    ret = copy_from_user(databuf,buf,Count);
    if(ret < 0){
        return ret;
    }

    Led_Switch(databuf[0]);
    return 0;
}

/* 字符设备的文件操作集合 */
static const struct file_operations gpioled_opts = {
    .owner = THIS_MODULE,
    .open = gpioled_open,
    .release = gpioled_release,
    .write = gpioled_write,
};

/* 模块入口 */
static int __init gpioled_init(void)
{
    int ret = 0;

    /* 获取设备节点:gpioled */
    gpioled.nd = of_find_node_by_path("/gpioled");
    if(gpioled.nd == NULL){
        ret = -EINVAL;
        goto fail_nd;
    }
    /* 获取设备树中的gpio属性,得到LED所使用的GPIO编号 */
    gpioled.led_gpio = of_get_named_gpio(gpioled.nd,"led-gpio", 0);
    if(gpioled.led_gpio < 0){
        ret = -EINVAL;
        goto fail_nd;
    }
    printk("led-gpio num = %d\r\n",gpioled.led_gpio);

    /* 申请GPIO */
    ret = gpio_request(gpioled.led_gpio, "led-gpio");
    if(ret){
        goto fail_nd;
    }

    /* 将LED的GPIO设置为输出,默认关闭LED灯(低电平点亮) */
    ret = gpio_direction_output(gpioled.led_gpio, 0);
    if(ret < 0){
        goto fail_gpio;
    }

    /* 注册字符设备 */
    /* 1、注册设备号 */
    gpioled.major = 0;
    if(gpioled.major){               /* 指定了设备号 */
        gpioled.devid = MKDEV(gpioled.major,0);
        ret = register_chrdev_region(gpioled.devid, GPIOLED_CNT, GPIOLED_NAME);
    }else{                          /* 没有指定设备号 */
        ret = alloc_chrdev_region(&gpioled.devid, 0, GPIOLED_CNT, GPIOLED_NAME);
        gpioled.major = MAJOR(gpioled.devid);
        gpioled.minor = MINOR(gpioled.devid);
        
    }
    if(ret < 0){                    /* 注册设备号失败 */
        goto fail_devid;
    }
    printk("major=%d,minor=%d\r\n",gpioled.major,gpioled.minor);

    /* 2、注册字符设备 */
    gpioled.cdev.owner = THIS_MODULE;
    cdev_init(&gpioled.cdev, &gpioled_opts);               /* 初始化 */
    ret = cdev_add(&gpioled.cdev, gpioled.devid, GPIOLED_CNT);
    if(ret < 0){
        goto fail_cdev;
    }

    /* 自动添加节点 */
    /* 1、添加类 */
    gpioled.class = class_create(THIS_MODULE,GPIOLED_NAME);
    if(IS_ERR(gpioled.class)){
        ret = PTR_ERR(gpioled.class);
        goto fail_class;
    }
    /* 2、添加类的设备 */
    gpioled.device = device_create(gpioled.class, NULL,gpioled.devid, NULL, GPIOLED_NAME);
    if(IS_ERR(gpioled.device)){
        ret = PTR_ERR(gpioled.device);
        goto fail_device;
    }


    return 0;

fail_device:
    class_destroy(gpioled.class);
fail_class:
    cdev_del(&gpioled.cdev);
fail_cdev:
    unregister_chrdev_region(gpioled.devid,GPIOLED_CNT);
fail_devid:
fail_gpio:
    gpio_free(gpioled.led_gpio);
fail_nd:
    return ret;
}

/* 模块出口 */
static void __exit gpioled_exit(void)
{
    /* 关灯 */
    Led_Switch(LED_OFF);
    
    /* gpio释放 */
    gpio_free(gpioled.led_gpio);

    /* 删除设备 */
    cdev_del(&gpioled.cdev);
    /* 注销设备号 */
    unregister_chrdev_region(gpioled.devid,GPIOLED_CNT);
    printk("gpioled_exit\r\n");

    /* 销毁类的设备 */
    device_destroy(gpioled.class,gpioled.devid);
    /* 销毁类 */
    class_destroy(gpioled.class);

}

/* 注册模块入口和出口函数 */
module_init(gpioled_init);
module_exit(gpioled_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZhangXueGuo");

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ实践——最大长度队列

大纲 抛弃消息创建最大长度队列绑定实验 转存死信创建死信队列创建可重写Routing key的最大长度队列创建绑定关系实验 在一些业务场景中&#xff0c;我们只需要保存最近的若干条消息&#xff0c;这个时候我们就可以使用“最大长度队列”来满足这个需求。该队列在收到消息后&…

leetCode40组合总和(回溯)

题目 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次示例 : 输入: candidates [2,5,2,1,2], target 5, 输出: [ [1,2,2], [5] ]回溯一般模…

3.XSS-DOM型(基础和进阶)

DOM XSS&#xff08;基础&#xff09; 不与后台服务器产生数据交互,通过前端的dom节点形成的XSS漏洞。 进行测试一下&#xff0c;输入111&#xff0c;会显示what do you see 查看元素代码&#xff0c;看到What do you see 根据前端页面语句进行编写弹窗攻击代码 <a hr…

# 消息中间件 RocketMQ 高级功能和源码分析(十)

消息中间件 RocketMQ 高级功能和源码分析&#xff08;十&#xff09; 一、消息中间件 RocketMQ 源码分析&#xff1a; 消息消费概述 1、集群模式和广播模式 消息消费以组的模式开展&#xff0c;一个消费组内可以包含多个消费者&#xff0c;每一个消费者组可订阅多个主题&…

萨科微slkor宋仕强论道华强北假货之六

萨科微slkor宋仕强论道华强北假货之六&#xff0c;华强北的假货这么多&#xff0c;搞得客户害怕、同行焦虑&#xff0c;话说“在华强北没有被坑过的&#xff0c;就不是华强北人”。我们金航标Kinghelm&#xff08;www.kinghelm.com.cn&#xff09;公司以前有一个贸易部&#xf…

【单片机】MSP430G2553单片机 Could not find MSP-FET430UIF on specified COM port 解决方案

文章目录 MSP430G2553开发板基础知识解决办法如何实施解决办法4步骤一步骤二步骤三 MSP430G2553开发板基础知识 MSP430G2553开发板如下图&#xff0c;上半部分就是UIF程序下载调试区域的硬件。个人觉得MSP430G2553开发板的这个部分没有做好硬件设计&#xff0c;导致很多系统兼…

三相光伏逆变并网电流电压双闭环仿真

三相并网发电系统的拓扑结构图展示了系统的基本构成和连接方式。图中&#xff0c;&#x1d456;&#x1d451;&#x1d450;1为直流输入电源&#xff0c;&#x1d436;1为输入直流母线滤波电容&#xff0c;&#x1d447;1~&#x1d447;6为三相逆变桥的6个IGBT开关管。这些开关…

MyBatis系列六: 映射关系多对一

动态SQL语句-更复杂的查询业务需求 官方文档基本介绍映射方式配置Mapper.xml的方式-应用实例注解的方式实现-应用实例课后练习 官方文档 文档地址: https://mybatis.org/mybatis-3/zh_CN/sqlmap-xml.html 基本介绍 ●基本介绍 1.项目中多对1的关系是一个基本的映射关系, 也可…

搜索python包的说明

当我发现bug时&#xff0c;就怀疑是sns包的版本问题了&#xff08;原代码是原作者以前成功运行的代码&#xff09;&#xff0c;于是直接到网上搜&#xff0c;找到对应的说明文档 根据该示例代码进行改写&#xff1a; 达成目的。

Harbor本地仓库搭建003_Harbor常见错误解决_以及各功能使用介绍_镜像推送和拉取---分布式云原生部署架构搭建003

首先我们去登录一下harbor,但是可以看到,用户名密码没有错,但是登录不上去 是因为,我们用了负债均衡,nginx会把,负载均衡进行,随机分配,访问的 是harbora,还是harborb机器. loadbalancer中 解决方案,去loadbalance那个机器中,然后 这里就是25机器,我们登录25机器 然后去配置…

【尚庭公寓SpringBoot + Vue 项目实战】预约看房与租约管理(完结)

【尚庭公寓SpringBoot Vue 项目实战】预约看房与租约管理&#xff08;完结&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】预约看房与租约管理&#xff08;完结&#xff09;1、业务说明2、接口开发2.1、预约看房管理2.1.1.保存或更新看房预约2.1.2. 查询个人预约…

首个AI高考全卷评测结果出分,大模型“考生”表现如何?

内容提要 大部分大模型“考生”语文、英语科目表现良好&#xff0c;但在数学方面还有待加强。阅卷老师点评&#xff0c;在语文科目上&#xff0c;对于语言中的一些“潜台词”&#xff0c;大模型尚无法完全理解。在数学科目上&#xff0c;大模型的主观题回答相对凌乱&#xff0…

2005年上半年软件设计师【下午题】试题及答案

文章目录 2005年上半年软件设计师下午题--试题2005年上半年软件设计师下午题--答案2005年上半年软件设计师下午题–试题

力扣每日一题 6/22 字符串/贪心

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 2663.字典序最小的美丽字符串【困难】 题目&#xff1a; 如果一个字符串满…

NLP大语言模型的缩放定律

一、简述 ​论文《神经语言模型的缩放定律》包含对交叉熵损失的语言模型性能的经验缩放定律的研究&#xff0c;重点关注Transformer架构。 https://arxiv.org/pdf/2001.08361.pdfhttps://arxiv.org/pdf/2001.08361.pdf 实验表明&#xff0c;测试损失与模型大小、数据集…

基于STM8系列单片机驱动74HC595驱动两个3位一体的数码管

1&#xff09;单片机/ARM硬件设计小知识&#xff0c;分享给将要学习或者正在学习单片机/ARM开发的同学。 2&#xff09;内容属于原创&#xff0c;若转载&#xff0c;请说明出处。 3&#xff09;提供相关问题有偿答疑和支持。 为了节省单片机MCU的IO口资源驱动6个数码管&…

STM32单片机USART串口打印和收发数据

文章目录 1. 串口通信 1.1 串口初始化 1.2 库函数 2. 串口打印 2.1 Serial.c 2.2 Serial.h 2.3 main.c 3. 串口收发数据 3.1 Serial.c 3.2 Serial.h 3.3 main.c 1. 串口通信 对于串口通信的详细解析可以看下面这篇文章 STM32单片机USART串口详解-CSDN博客 STM32单片…

基于java+springboot+vue实现的智慧生活商城系统(文末源码+Lw)244

摘 要 计算机网络发展到现在已经好几十年了&#xff0c;在理论上面已经有了很丰富的基础&#xff0c;并且在现实生活中也到处都在使用&#xff0c;可以说&#xff0c;经过几十年的发展&#xff0c;互联网技术已经把地域信息的隔阂给消除了&#xff0c;让整个世界都可以即时通…

数据中心:AI范式下的内存挑战与机遇

在过去的十年里&#xff0c;数据中心和服务器行业经历了前所未有的扩张&#xff0c;这一进程伴随着CPU核心数量、内存带宽(BW)&#xff0c;以及存储容量的显著增长。这种超大规模数据中心的扩张不仅带来了对计算能力的急剧需求&#xff0c;也带来了前所未有的内存功率密度挑战&…

BigDataCloud 反向地理编码

在当今数字化飞速发展的时代&#xff0c;地理信息的精确获取和游戏数据的深入分析成为众多领域的关键需求。2024 年的今天&#xff0c;技术的创新为我们带来了更为出色的 API 服务。BigDataCloud 反向地理编码服务&#xff0c;能够将经纬度迅速而准确地转换为详细位置信息&…