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

【ASOC全解析(三)】machine原理和实战

【ASOC全解析(三)】machine原理和实战

  • 一、machine概述与原理
    • 1.1 machine的主要职责
    • 1.2 本文的主要内容
  • 二、machine程序示例
    • 完整的machine驱动代码示例
    • 扩展知识:SND_SOC_DAILINK_DEFS
      • 使用方法说明
      • 总结与其它说明

/*****************************************************************************************************************/

声明: 本博客内容均由https://blog.csdn.net/weixin_47702410原创,转载or引用请注明出处,谢谢!

创作不易,如果文章对你有帮助,麻烦点赞 收藏支持~感谢

/*****************************************************************************************************************/

一、machine概述与原理

在ASOC中,Machine层,也称为“机器层”或“板级层”,是ASoC架构中负责将Codec和Platform层连接起来的部分。它是ASoC中与硬件平台相关的部分,通常包含了特定于机器(如开发板或产品)的音频路由和控制逻辑。

1.1 machine的主要职责

Machine层的主要职责包括:

  • 定义音频路径:Machine层定义了音频数据在系统中的流动路径。这包括输入(如麦克风)和输出(如扬声器)设备的连接方式,以及它们如何与Codec设备进行交互。

  • 控制音频接口:Machine层负责管理和配置音频接口,例如I2S、PCM、AC97等,这些接口用于在Codec和SoC之间传输音频数据。

  • 音频路由和混音:Machine层定义了音频信号的路由,例如将哪个音频输入路由到哪个输出,以及如何混合不同的音频源。

  • DAPM(Dynamic Audio Power Management)配置:Machine层配置DAPM策略,以便在不使用某些音频组件时关闭它们的电源,从而节省能源。

  • 板级初始化代码:Machine层包含了特定于机器的初始化代码,这些代码在系统启动时执行,用于初始化音频硬件和ASoC组件。

  • 提供用户空间接口:Machine层通过ALSA提供了用户空间接口,允许应用程序控制音频硬件,例如调整音量、改变音频路由等。

Machine层通常是由设备制造商或社区开发者针对特定硬件平台编写的,因为它需要详细了解硬件的音频架构和功能。在Linux内核源代码中,Machine层的代码通常位于sound/soc/目录下的与特定板相关的子目录中。

Machine层的实现通常涉及到编写一个Machine驱动,这个驱动会注册一个snd_soc_card结构,该结构描述了音频卡的各种属性,包括DAI(Digital Audio Interface)链接、Codec信息、平台信息以及DAPM路由等。这个驱动还会处理与音频相关的平台特定事件,比如耳机插入检测或按钮控制等。

1.2 本文的主要内容

本文针对DAI的连接为主,进行相关的实践。即将所有组件驱动程序(例如Codec端、platform端和 DAI)粘合在一起的代码。

其它功能会关联ALSA Core层或者DAPM或者指定硬件相关的知识,后续有时间再另作文章介绍。

二、machine程序示例

针对DAI的连接,主要是有三个步骤:

  • 1、定义DAI_Link连接codec和platform
  • 2、定义声卡,需要定义snd_soc_card
  • 3、注册声卡

上面的这三点,主要是调用API函数snd_soc_register_card完成(这个函数很重要,但内容较多,后续有时间再出一版文章详细说明)

完整的machine驱动代码示例

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>SND_SOC_DAILINK_DEFS(mycodec,DAILINK_COMP_ARRAY(COMP_CPU("myplat.0")),DAILINK_COMP_ARRAY(COMP_CODEC("my_codec.0", "my_codec_dai")),DAILINK_COMP_ARRAY(COMP_PLATFORM("myplat.0")));static int my_card_init(struct snd_soc_pcm_runtime *rtd)
{printk("%s,line:%d\n",__func__,__LINE__);return 0;
}static int my_card_hw_params(struct snd_pcm_substream *substream,struct snd_pcm_hw_params *params) {struct snd_soc_pcm_runtime *rtd = substream->private_data;//struct snd_soc_dai *codec_dai = rtd->codec_dai;struct snd_soc_card *card = rtd->card;unsigned int freq;//int ret;int stream_flag;printk("%s,line:%d\n",__func__,__LINE__);switch (params_rate(params)) {case    8000:case    12000:case    16000:case    24000:case    32000:case    48000:case    96000:case    192000:freq = 24576000;break;case    11025:case    22050:case    44100:freq = 22579200;break;default:dev_err(card->dev, "invalid rate setting\n");return -EINVAL;}/* the substream type: 0->playback, 1->capture */stream_flag = substream->stream;return 0;
}static struct snd_soc_ops my_card_ops = {.hw_params = my_card_hw_params,
};static struct snd_soc_dai_link my_card_dai_link[] = {{.name       = "my-codec",.stream_name    = "MY-CODEC",SND_SOC_DAILINK_REG(mycodec),
/*SND_SOC_DAILINK_REG(mycodec)等效于.codec_name = "my_codec.0",.codec_dai_name = "my_codec_dai",.cpu_dai_name   = "myplat.0",.platform_name  = "myplat.0",
*/.init       = my_card_init,.ops        = &my_card_ops,},
};static struct snd_soc_card snd_soc_my_card = {.name           = "my-codec",.owner          = THIS_MODULE,.dai_link       = my_card_dai_link,.num_links      = ARRAY_SIZE(my_card_dai_link),
};static int mymachine_probe(struct platform_device *pdev) {int ret = 0;struct snd_soc_card *card = &snd_soc_my_card;printk("-----%s----\n",__func__);/* register the soc card */card->dev = &pdev->dev;ret = snd_soc_register_card(card);if (ret < 0) {dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret);return -1;}return ret;
}static int mymachine_remove(struct platform_device *pdev){printk("-----%s----\n",__func__);return 0;
}static void mymachine_pdev_release(struct device *dev){printk("-----%s----\n",__func__);
}static struct platform_device mymachine_pdev = {.name           = "mymachine",.dev.release    = mymachine_pdev_release,
};static struct platform_driver mymachine_pdrv = {.probe      = mymachine_probe,.remove     = mymachine_remove,.driver     = {.name   = "mymachine",},
};static int __init mymachine_init(void)
{int ret;ret = platform_device_register(&mymachine_pdev);if (ret)return ret;ret = platform_driver_register(&mymachine_pdrv);if (ret)platform_device_unregister(&mymachine_pdev);return ret;
}static void __exit mymachine_exit(void)
{platform_driver_unregister(&mymachine_pdrv);platform_device_unregister(&mymachine_pdev);
}module_init(mymachine_init);
module_exit(mymachine_exit);
MODULE_LICENSE("GPL");

扩展知识:SND_SOC_DAILINK_DEFS

从Linux 5.x开始,Linux使用宏SND_SOC_DAILINK_REG快捷定义DAI_LINK中的有关codec和platform连接关系。

其本质和5.x之前的版本并无实质的变化,仅是在形式上采用了一种更加便捷的定义方法。相关源码主要参考“linux/v5.10.177/source/include/sound/soc.h“

本小节主要扩展解释一下下面的语句:

SND_SOC_DAILINK_DEFS(mycodec,DAILINK_COMP_ARRAY(COMP_CPU("myplat.0")),DAILINK_COMP_ARRAY(COMP_CODEC("my_codec.0", "my_codec_dai")),DAILINK_COMP_ARRAY(COMP_PLATFORM("myplat.0")));SND_SOC_DAILINK_REG(mycodec),

SND_SOC_DAILINK_DEFS的定义如下:

#define SND_SOC_DAILINK_DEFS(name, cpu, codec, platform...) \SND_SOC_DAILINK_DEF(name##_cpus, cpu);          \SND_SOC_DAILINK_DEF(name##_codecs, codec);      \SND_SOC_DAILINK_DEF(name##_platforms, platform)

代入得到:

#define SND_SOC_DAILINK_DEFS(mycodec, COMP_CPU("myplat.0"), COMP_CODEC("my_codec.0", "my_codec_dai"), COMP_PLATFORM("myplat.0"))    \
//...

再展开上面的三个宏可以得到:

#define SND_SOC_DAILINK_DEFS(mycodec, { .dai_name = "myplat.0", }, { .name = "my_codec.0", .dai_name = "my_codec_dai", }, { .name = "myplat.0" })   \
//...

将上面的结果完整代入SND_SOC_DAILINK_DEF,即可以得到完整的SND_SOC_DAILINK_DEFS展开结果:

    SND_SOC_DAILINK_DEF(mycodec_cpus,  { .dai_name = "myplat.0", });            \SND_SOC_DAILINK_DEF(mycodec_codecs, { .name = "my_codec.0", .dai_name = "my_codec_dai", });     \SND_SOC_DAILINK_DEF(mycodec_platforms, { .name = "myplat.0" })

进一步代入SND_SOC_DAILINK_DEF可以得到:

static struct snd_soc_dai_link_component mycodec_cpus[] = { .dai_name = "myplat.0", };static struct snd_soc_dai_link_component mycodec_codecs[]   = {.name = "my_codec.0", .dai_name = "my_codec_dai", };static struct snd_soc_dai_link_component mycodec_platforms[]    = {.name = "myplat.0" };

使用方法说明

使用方法

SND_SOC_DAILINK_REG(name),

这个宏展开后如下:

    .cpus           = mycodec_cpus,.num_cpus       = ARRAY_SIZE(mycoded_cpus),.codecs         = mycodec_codecs,.num_codecs     = ARRAY_SIZE(mycodec_codecs),.platforms      = mycodec_platforms,.num_platforms  = ARRAY_SIZE(mycodec_platforms),

总结与其它说明

SND_SOC_DAILINK_DEFS(mycodec,DAILINK_COMP_ARRAY(COMP_CPU("myplat.0")),DAILINK_COMP_ARRAY(COMP_CODEC("my_codec.0", "my_codec_dai")),DAILINK_COMP_ARRAY(COMP_PLATFORM("myplat.0")));static struct snd_soc_dai_link my_card_dai_link[] = {{.name       = "my-codec",.stream_name    = "MY-CODEC",SND_SOC_DAILINK_REG(mycodec),.init       = my_card_init,.ops        = &my_card_ops,},
};//***************************************************************
//最终展开是:
static struct snd_soc_dai_link_component mycodec_cpus[] = { .dai_name = "myplat.0", 
};static struct snd_soc_dai_link_component mycodec_codecs[]   = {.name = "my_codec.0", .dai_name = "my_codec_dai", 
};static struct snd_soc_dai_link_component mycodec_platforms[]    = {.name = "myplat.0" 
};static struct snd_soc_dai_link my_card_dai_link[] = {{.name       = "my-codec",.stream_name    = "MY-CODEC",.cpus           = mycodec_cpus,.num_cpus       = ARRAY_SIZE(mycodec_cpus),.codecs         = mycodec_codecs,.num_codecs     = ARRAY_SIZE(mycodec_codecs),.platforms      = mycodec_platforms,.num_platforms  = ARRAY_SIZE(mycodec_platforms),.init       = my_card_init,.ops        = &my_card_ops,},
};

其它说明
Linux源码中也另外提供了三种DAI_Link的定义方式,下面直接分析其内容的含义,先看Linux官方的说明:

//include/sound/soc.h
/** Sample 1 : Single CPU/Codec/Platform** SND_SOC_DAILINK_DEFS(test,*  DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai")),*  DAILINK_COMP_ARRAY(COMP_CODEC("codec", "codec_dai")),*  DAILINK_COMP_ARRAY(COMP_PLATFORM("platform")));** struct snd_soc_dai_link link = {*  ...*  SND_SOC_DAILINK_REG(test),* };** Sample 2 : Multi CPU/Codec, no Platform** SND_SOC_DAILINK_DEFS(test,*  DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai1"),*             COMP_CPU("cpu_dai2")),*  DAILINK_COMP_ARRAY(COMP_CODEC("codec1", "codec_dai1"),*             COMP_CODEC("codec2", "codec_dai2")));** struct snd_soc_dai_link link = {*  ...*  SND_SOC_DAILINK_REG(test),* };** Sample 3 : Define each CPU/Codec/Platform manually** SND_SOC_DAILINK_DEF(test_cpu,*      DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai1"),*                 COMP_CPU("cpu_dai2")));* SND_SOC_DAILINK_DEF(test_codec,*      DAILINK_COMP_ARRAY(COMP_CODEC("codec1", "codec_dai1"),*                 COMP_CODEC("codec2", "codec_dai2")));* SND_SOC_DAILINK_DEF(test_platform,*      DAILINK_COMP_ARRAY(COMP_PLATFORM("platform")));** struct snd_soc_dai_link link = {*  ...*  SND_SOC_DAILINK_REG(test_cpu,*              test_codec,*              test_platform),* };** Sample 4 : Sample3 without platform** struct snd_soc_dai_link link = {*  ...*  SND_SOC_DAILINK_REG(test_cpu,*              test_codec);* };*/

这段注释提供了几个示例来说明如何使用SND_SOC_DAILINK_DEFS和SND_SOC_DAILINK_REG宏来定义和注册SoC音频dailink。一个dailink通常包含一个CPU(DMA引擎),一个或多个编解码器,以及一个平台(音频控制器硬件)。

下面是每个示例的解释:

  • 示例 1:单个CPU/Codec/Platform
SND_SOC_DAILINK_DEFS(test,DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai")),DAILINK_COMP_ARRAY(COMP_CODEC("codec", "codec_dai")),DAILINK_COMP_ARRAY(COMP_PLATFORM("platform")));

这个示例展示了如何定义一个包含单个CPU、Codec和Platform的dailink。SND_SOC_DAILINK_DEFS宏用于创建三个数组:test_cpus、test_codecs和test_platforms,每个数组包含一个组件。

struct snd_soc_dai_link link = {...SND_SOC_DAILINK_REG(test),
};

然后,SND_SOC_DAILINK_REG宏用于在snd_soc_dai_link结构体中注册这些组件。

  • 示例 2:多个CPU/Codec,没有Platform
SND_SOC_DAILINK_DEFS(test,DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai1"),COMP_CPU("cpu_dai2")),DAILINK_COMP_ARRAY(COMP_CODEC("codec1", "codec_dai1"),COMP_CODEC("codec2", "codec_dai2")));

这个示例展示了如何定义一个包含多个CPU和Codec,但没有Platform的dailink。SND_SOC_DAILINK_DEFS宏创建了两个数组:test_cpus和test_codecs,每个数组包含两个组件。

struct snd_soc_dai_link link = {...SND_SOC_DAILINK_REG(test),
};

SND_SOC_DAILINK_REG宏在这里假定Platform是空的,并在snd_soc_dai_link结构体中注册CPU和Codec组件。

  • 示例 3:手动定义每个CPU/Codec/Platform
SND_SOC_DAILINK_DEF(test_cpu,DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai1"),COMP_CPU("cpu_dai2")));
SND_SOC_DAILINK_DEF(test_codec,DAILINK_COMP_ARRAY(COMP_CODEC("codec1", "codec_dai1"),COMP_CODEC("codec2", "codec_dai2")));
SND_SOC_DAILINK_DEF(test_platform,DAILINK_COMP_ARRAY(COMP_PLATFORM("platform")));

这个示例展示了如何手动定义每个CPU、Codec和Platform组件。SND_SOC_DAILINK_DEF宏用于创建三个独立的数组。

struct snd_soc_dai_link link = {...SND_SOC_DAILINK_REG(test_cpu,test_codec,test_platform),
};

然后,SND_SOC_DAILINK_REG宏用于在snd_soc_dai_link结构体中注册这些组件。

  • 示例 4:没有Platform的示例3
struct snd_soc_dai_link link = {...SND_SOC_DAILINK_REG(test_cpu,test_codec);
};

这个示例与示例3类似,但它省略了Platform组件。SND_SOC_DAILINK_REG宏在这里只注册CPU和Codec组件。

这些示例展示了如何灵活地使用宏来定义和注册不同配置的dailinks,这对于SoC音频驱动的开发非常重要。

相关文章:

【ASOC全解析(三)】machine原理和实战

【ASOC全解析&#xff08;三&#xff09;】machine原理和实战 一、machine概述与原理1.1 machine的主要职责1.2 本文的主要内容 二、machine程序示例完整的machine驱动代码示例扩展知识&#xff1a;SND_SOC_DAILINK_DEFS使用方法说明总结与其它说明 /*************************…...

matlab appdesigner系列-常用15-滑块、微调器

滑块&#xff0c;以左右拖动的方式在一定范围内改变数值 此示例&#xff0c;滑块显示微调器的数值&#xff0c;微调器也可以显示滑块的数值 操作步骤为&#xff1a; 1&#xff09;将滑块和微调器拖拽到画布上 2&#xff09;分别设置这两个组件的回调函数 回调函数有两个选项…...

google翻译相机报错 请安装最新的Google应用,以便使用相机翻译功能

修复&#xff1a;google翻译相机报错 背景&#xff1a;解决方法 背景&#xff1a; 国内手机使用google翻译的相机时报错&#xff1a; 请安装最新的Google应用&#xff0c;以便使用相机翻译功能点击报错的“确定”后转到了国内空白的软件商店页面 解决方法 Google Play搜索 …...

openssl3.2/test/certs - 015 - Primary intermediate ca: ca-cert

文章目录 openssl3.2/test/certs - 015 - Primary intermediate ca: ca-cert概述笔记END openssl3.2/test/certs - 015 - Primary intermediate ca: ca-cert 概述 openssl3.2 - 官方demo学习 - test - certs 笔记 这个例子有不同的地方, 发证书时, 指定了CA. 看实验注释, 是…...

linux中用户及用户组信息

1&#xff0c;linux通过用户名和口令来验证用户的身份。 2&#xff0c;几个用户可以组成一个用户组。 3&#xff0c;useradd工具添加用户&#xff0c;groupadd命令添加用户组。 4&#xff0c;history 命令查看用户在Shell中执行命令的历史记录。 5&#xff0c;userdel命令删…...

用Go plan9汇编实现斐波那契数列计算

斐波那契数列是一个满足递推关系的数列&#xff0c;如&#xff1a;1 1 2 3 5 8 ... 其前两项为1&#xff0c;第3项开始&#xff0c;每一项都是其前两项之和。 用Go实现一个简单的斐波那契计算逻辑 func fib(n int) int {if n 1 || n 2 {return 1}return fib(n-1) fib(n-2) …...

Message queue 消息队列--RabbitMQ 【基础入门】

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是平顶山大师&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《Message queue 消息队列--RabbitMQ 【基础入门…...

【汇编】 13.3 对int iret和栈的深入理解

书中示例 assume cs:codecode segment start:mov ax,csmov ds,axmov si,offset lpmov ax,0mov es,axmov di,200hmov cx,offset end0-offset lpcldrep movsb ;lp到end0的指令传送到0:200处mov ax,0mov es,axmov word ptr es:[7ch*4],200hmov word ptr es:[7ch*42],0 ;设置7c表项…...

Git提交大文件报错“remote: Please remove the file from history and try again. ”

如在使用Git过程中不小心将较大的二进制文件加入仓库&#xff0c;那么仓库大小很快就会超过规定的配额&#xff0c;在Push的时候会报下面的错误&#xff1a; remote: Powered by GITEE.COM [GNK-6.4] remote: error: File: c91e5de4f55bedd0669db01036fc131ea8e516ce 130.66 MB…...

接口测试 03 -- 接口自动化思维 Requests库应用

1. 接口自动化思维梳理 1.1接口自动化的优点 接口测试自动化&#xff0c;简单来讲就是功能测试用例脚本化然后执行脚本&#xff0c;产生一份可视化测试报告。不管什么样的测试方式&#xff0c;都是为了验证功能与发现 BUG。那为什么要做接口测试自动化呢&#xff1f;一句话概括…...

SpringBoot:Bean生命周期自定义初始化和销毁

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java项目分享》 《RabbitMQ》《Spring》《SpringMVC》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 前言一、Bean注解指…...

Git--基本操作介绍(2)

Git 常用的是以下 6 个命令&#xff1a;git clone、git push、git add 、git commit、git checkout、git pull. 说明&#xff1a; workspace&#xff1a;工作区staging area&#xff1a;暂存区/缓存区local repository&#xff1a;版本库或本地仓库remote repository&#xf…...

第08章_面向对象编程(高级)(static,单例设计模式,理解mian方法,代码块,final,抽象类与抽象方法,接口,内部类,枚举类,注解,包装类)

文章目录 第08章_面向对象编程(高级)本章专题与脉络1. 关键字&#xff1a;static1.1 类属性、类方法的设计思想1.2 static关键字1.3 静态变量1.3.1 语法格式1.3.2 静态变量的特点1.3.3 举例1.3.4 内存解析 1.4 静态方法1.4.1 语法格式1.4.2 静态方法的特点1.4.3 举例 1.5 练习 …...

Java中Map接口常用的方法

java.util.Map接口中常用的方法&#xff1a; 1.Map和Collection没有继承关系 2.Map集合以key和value的方式存储数据&#xff1a;键值对 key和value都是引用数据类型 key和value都是存储对象的内存地址 key起到主导的地位&#xff0c;value是key的一个附属品 3.Map接口中常用的方…...

Linux软件包管理器yum

文章目录 前言概述Linux下载软件的三种方式源代码安装rpm安装yum安装 关于yum的相关操作查看软件包软件安装卸载软件 yum源问题 前言 在Windows系统中&#xff0c;如果我们要去下载软件&#xff0c;我们可以在该软件的官网中进行下载&#xff0c;或者在微软的额软件商店进行下…...

Linux中NFS服务器的搭建和安装

1.介绍&#xff1a; 网络文件系统即将本地系统放在网络上某一个位置的系统&#xff0c;基于UDP/IP使用nfs能够在不同计算机之间通过网络进行文件共享&#xff0c;能使使用者访问网络上其他计算机中的文件就像在访问自己的计算机一样&#xff0c;也就是说放在一个开发板上&#…...

c递归算法模型

使用递归算法模型可以较为自然地解决许多问题&#xff0c;尤其是对于那些数据结构层次比较清晰的问题&#xff0c;递归算法模型往往能够提供一种简单清晰的解法。 递归算法模型的核心思想是将一个大问题通过递归的方式拆分为若干个较小的问题&#xff0c;并不断递归下去直到问…...

力扣740. 删除并获得点数

动态规划 思路&#xff1a; 选择元素 x&#xff0c;获得其点数&#xff0c;删除 x 1 和 x - 1&#xff0c;则其他的 x 的点数也会被获得&#xff1b;可以将数组转换成一个有序 map&#xff0c;key 为 x&#xff0c; value 为对应所有 x 的和&#xff1b;则问题转换成了不能同…...

spring和springboot的区别

在当今的软件开发领域&#xff0c;Spring和Spring Boot无疑是Java开发者最常用的框架之一。尽管它们都源于Spring项目&#xff0c;但它们在设计和使用上有很大的不同。本文将深入探讨Spring和Spring Boot之间的主要区别&#xff0c;以及为什么有时候选择其中一个而不是另一个是…...

imgaug库图像增强指南(35):【iaa.Fog】——轻松创建自然雾气场景

引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应运而生&#xff0c;成为了解决这一问题的…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...