我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android Qcom Audio入门学习

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android Qcom Audio入门学习

总结: Android Audio不简单呀,一个人摸索入门不容易的,研究了一段时间,感觉还不是很懂,但以下的知识对入门还是有帮助的。

FE(Front End)

提供pcm的设备信息,将数据从用户空间传输到音频后端,以及从音频后端捕获录制等
vendor/qcom/opensource/audio-hal/primary-hal/msm8974/platform.c
platform_init中根据声卡的名称"bengal-qrd-snd-card"获取得知配置platform_info对应的文件
PLATFORM_INFO_XML_PATH_QRD_NAME,audio_platform_info_qrd.xml,那这个文件是用来干嘛的呢?

其一就是包含pcm_ids,pcm就是我们这里提到的音频前端FE,访问pcm设备时需要知道设备的id(/dev/snd/pcmC0D3P /dev/snd/pcmC0D17c\ C0: card0 D3/D17: device id c:capture p:playbac),不同的平台上可能出现差异,所以Framework就通过usecase来指定pcm设备,pcm_device_table用于管理usecase与pcm_ids的map关系,最终通过配置文件来修改以实现map关系的管理

pcm_device_table   [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,        //PCM_PLAYBACK               LOWLATENCY_PCM_DEVICE},    //PCM_CAPTURE<pcm_ids>   <usecase name="USECASE_AUDIO_PLAYBACK_LOW_LATENCY" type="out" id="9"/>

vendor/qcom/opensource/audio-hal/primary-hal/hal/audio_hw.c中包含use_case_table,
常见的就是low_latency(按键音等低延时)、deep_buffer(音乐等)、compress_offload(mp3、flac、acc等不需要软件解码,送入ADSP进行解码)、record(录音)、voice_call(语音通话)、voip_call(网络通话)等等

BE(Back End)

执行音频路由任务,连接Audio Device(Mic Speaker Codec等),ADSP 处于音频前端和音频后端之间
audio_platform_info_qrd.xml中包含的其二backend_names,audio device与interface的对应关系,使用QCAT Tool显示RX Devices,需要做如下修改,因为并非使用高通的WSA

- <device name="SND_DEVICE_OUT_SPEAKER" interface="WSA_CDC_DMA_RX_0"/>+ <device name="SND_DEVICE_OUT_SPEAKER" interface="SEC_MI2S_RX"/>

ACDB(Audio Calibration Database)

audio_platform_info_qrd.xml中包含的其三acdb_ids,用于给每个音频设备在DSP 路径上的配置,或者可以说是DSP的配置文件

APR(Asynchronous Packet Router)

APR是基于SMD(Share memory Driver,提供通道让不同设备数据交互)和SMMU(System Memory Management Unit, 如果外部设备有一段可以访问的内存,那么可以直接通过smmu把这段内存映射给cpu,cpu可以直接去访问这段内存)的一种IPC 通信方式,用于Ap与QDSP通信
ADSP.VT.5.4.1/adsp_proc/apr - vendor/qcom/opensource/audio-kernel/ipc/apr.c
在这里插入图片描述

DAI(Digital Audio Interface)

一个machine当然要包含自己内部的音频控制接口单元–cpu_dai和外部音频设备通信协议转换接口单元–codec_dai

I2S(Inter-IC Sound)

SCLK串行时钟、WS声道选择线、Tx用于传输音频数据、Rx用于接收音频数据

PCM(Pulse Code Modulation)

BCLK位时钟,依据采样率变化、SYNC同步信号、Tx传输音频数据、Rx接受音频数据

SWR(SoundWire)

SWR由MIPI联盟推出的音频接口,有主从的两线制(clock,data)总线,Mipi SoundWire Spec 学习笔记

SLIM (Serial Low Power Interchip Media Bus)

SLIM由MIPI联盟开发的音频接口,同SWR类似,但支持多个Data线,可用于与aux(不适用dai) codec通信

ALSA(Advanced Linux Sound Architecture)

在这里插入图片描述
图片来自于ALSA 架构,推荐博客高通音频架构(三),ASOC(ALSA Systen on chip)主要提供一套独立的嵌入式系统设备管理框架。
(1) ALSA Library : 应用通过ALSA Library于内核空间进行交互,Android中使用tinyalsa,支持PCM和Control接口
(2) ALSA Layer: 处于内核空间,向上提供接口,如PCM、Control、Mixer,向下驱动硬件设备 I2S、Codec、Machine
(3) ASOC Machine:作为Codec和Platform的载体,将硬件设备关联起来,连接codec_dai与cpu_dai,构成硬件通路
(4) ASOC Platform: 可以简单理解为就是Soc平台,负责Soc侧的音频传输,音频接口配置与控制等
(5) ASOC Codec: 控制音频解码,完成音频采集和播放过程中模拟与数字间的转换,aux代表未使用dai的codec,
(6) DAPM: Dynamic Audio Power Management 在任何时候都能工作在最小功耗下,控制内部widget通路上下点

高通子系统subsystem基础知识

kernel/msm-4.19/drivers/soc/qcom/subsys-pil-tz.c (generic peripheral image loader (PIL) driver)
在devictree中可以发现有 qcom,firmware-name = adsp cdsp venus modem ipa_fws slpi
其实在PIL驱动并没有发生image加载过程,真正的加载有对应的子模块处理中,adsp就是在adsp-loader.c中

vendor/qcom/opensource/audio-kernel/dsp/adsp-loader.c
通过init.qcom.rc启动时 write /sys/kernel/boot_adsp/boot 1 ,之后就会subsystem_get(“adsp”)获取并加载;
其他例如slpi, 要看高通不同的平台子模块的组成,有些PIL是没有load slpi模块,sensor也是adsp中,
所以启动的节点会出现/sys/kernel/boot_adsp/ 以及 /sys/kernle/boot_slpi/两种情况
kernel/msm-4.19/drivers/sensors/sensors_ssc.c subsystem_get_with_fwname(“slpi”)获取并加载,如果有slpi的话

子系统的通信方式有三种(1)smen (2)spss(Secure-Processor-SubSystem) (3)spi,之前分析过adsp与glink以及ssc的通信都是基于smem
之前分析的博客  Android Qcom USB Driver学习(九)        Android Qcom Sensor架构学习

AMSS contents.xml和build.py可以得知各子系统的镜像 common/build/ufs/bin/asic/pil_split_bins中打包成NON-HLOS.bin或者是SDA.bin
PILDxe会去解析uefipil.cfg,其中就包含modem镜像的组成adsp slpi cdsp modem spss等几个子系统

Android推动GKI,能有更多的可动态加载的内核模块 (DLKM),老点的Android版本audio也一直在执行DLKM的,以adsp-loader为例
vendor/qcom/opensource/audio-kernel/dsp/Kbuild Android.mk 将adsp-loader.c 模块化为audio_adsp_loader.ko
在out目录下有/dlkm/lib/modules/audio_adsp_loader.ko 和 /vendor/lib/modules/audio_adsp_loader.ko (Android Kernel ko)

vendor/lib/modules # modinfo audio_adsp_loader.ko         filename:       audio_adsp_loader.kolicense:        GPL v2              description:    ADSP Loader module  alias:          of:N*T*Cqcom,adsp-loader                        alias:          of:N*T*Cqcom,adsp-loaderC*                      depends:name:           adsp_loader_dlkm    vermagic:       4.19.157+ SMP preempt mod_unload modversions aarch64uart boot log:subsys-pil-tz ab00000.qcom,lpass: Falling back to syfs fallback for: adsp.mdtsubsys-pil-tz ab00000.qcom,lpass: Falling back to syfs fallback for: adsp.b02subsys-pil-tz ab00000.qcom,lpass: Subsystem error monitoring/handling services are upadsprpc: fastrpc_restart_notifier_cb: adsp subsystem is upadsprpc: fastrpc_rpmsg_probe: opened rpmsg channel for adsp

之前遇到过Google服务器导致ADSP中的SSC编译有问题,因为SSC用到了谷歌的Protocol,ADSP子系统启动有问题会开不了机,
看编译出的镜像size变小也可以得知有问题,暂时还没遇到过不加载导致Audio功能有问题的情况。
那高通的ADSP当作为audio究竟是如何工作?高通msm8996平台的ASOC音频路径分析
在这里插入图片描述
高通平台上fe dai link是链接cpu和adsp的,并非使用的i2s等硬件接口,而是使用共享内存的方式,在数据传输过程中没有实际的操作,platform直接将音频数据最终写入adsp,它描述的并非一个物理设备,这段是从博主那边看来的,自己还需看代码体会一下,挖坑。

[Linux Audio Driver] 高通平台MI2S总线配置
可见devicetree中的asoc-cpu asoc-platform包含了所有的dai接口,这里使用的MI2S1对应Secondary
硬件接口:LPI_MI2S1_CLK LPI_MI2S1_WS LPI_MI2S1_DATA0 LPI_MI2S1_DATA1
注意这里的gpio与lpg gpio的对应关系,硬件上的gpio102-gpio105对应lpg goui10-13
在这里插入图片描述

qcom,mi2s-audio-intf = <1>;qcom,sec-mi2s-gpios = <&cdc_sec_mi2s_gpios>; &q6core {        cdc_sec_mi2s_gpios: msm_cdc_pinctrl_sec {                compatible = "qcom,msm-cdc-pinctrl";                pinctrl-names = "aud_active", "aud_sleep";                pinctrl-0 = <&lpi_i2s2_sck_active &lpi_i2s2_ws_active                        &lpi_i2s2_sd0_active &lpi_i2s2_sd1_active>;                pinctrl-1 = <&lpi_i2s2_sck_sleep &lpi_i2s2_ws_sleep                        &lpi_i2s2_sd0_sleep &lpi_i2s2_sd1_sleep>;                qcom,lpi-gpios;        };};

耳机检测相关 0:NC(normally-closed) 1:NO(normally-open),高通音频MBHC耳机系统软件相关配置归纳
根据硬件原理图,确认HS-DET和HPG-L引脚的连接状态,未插入时断开的则时NO,未插入时连接的则是NC

qcom,msm-mbhc-hphl-swh = <1>; qcom,msm-mbhc-gnd-swh = <1>;

DMIC0 DCMI1数字Mic输入接口对应硬件DMIC1_CLK DMIC1_DATA DMIC2_CLK DMIC2_DATA, micbias麦克风工作电压

qcom,cdc-dmic01-gpios = <&cdc_dmic01_gpios>;qcom,cdc-dmic23-gpios = <&cdc_dmic23_gpios>;qcom,cdc-micbias1-mv = <1800>qcom,cdc-micbias2-mv = <1800>qcom,cdc-micbias3-mv = <1800>

如果是dai的codec则添加在这里asoc-codec和asoc-codec-names,vendor/qcom/opensource/audio-kernel/asoc/bengal.cpopulate_snd_card_dailinks将所有的snd_soc_dai_link保持在snd_soc_card中,在msm_populate_dai_link_component_of_node, 通过上面记录的num_links,逐个通过platform_name去找platform_of_node,对应devicetree中的asoc-platform-namesasoc-platform,通过cpu_dai_name去找cpu_of_node对应devicetree中的asoc-cpu-namesasoc-cpu,codec同理对应asoc-codecasoc-codec-names,上述的内容都包含在sns_soc_dai_link中,硬件上我们得知使用的Secondary MI2S接的PA(PA也当作codec来看),所以需要配置dai_link,在max98390 snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98390, max98390_dai, ARRAY_SIZE(max98390_dai));
分别传入snd_soc_codec_driver以及snd_soc_dai_driverdevm_snd_soc_register_card中调用soc_probe_link_dais来probe codec,当然这里并非作为i2c器件的i2c_driver的max98390_i2c_probe,而是作为alsa component的snd_soc_component_driver或者snd_soc_codec_driver(这两种其实都是抽象component示例最终挂在到全局链表component_list)的max98390_probe

asoc-codec  = <&stub_codec>, <&bolero>; asoc-codec-names = "msm-stub-codec.1", "bolero_codec";static struct snd_soc_dai_link msm_mi2s_be_dai_links[MI2S_DAI_LINK_MAX] = {{.name = LPASS_BE_SEC_MI2S_RX,.stream_name = "Secondary MI2S Playback",.cpu_dai_name = "msm-dai-q6-mi2s.1",.platform_name = "msm-pcm-routing",-.codec_name = "msm-stub-codec.1",-.codec_dai_name = "msm-stub-rx",+ .codec_name     = "max98390.0-0038",  +.codec_dai_name = "max98390-aif1",   .no_pcm = 1,.dpcm_playback = 1,.id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,.be_hw_params_fixup = msm_be_hw_params_fixup,.ops = &msm_mi2s_be_ops,.ignore_suspend = 1,.ignore_pmdown_time = 1,},static struct snd_soc_dai_driver max98390_dai[] = {   {                .name = "max98390-aif1",                .playback = {                        .stream_name = "HiFi Playback",                        .channels_min = 1,                        .channels_max = 2,                        .rates = MAX98390_RATES,                        .formats = MAX98390_FORMATS,                },                .capture = {                        .stream_name = "HiFi Capture",                        .channels_min = 1,                        .channels_max = 2,                        .rates = MAX98390_RATES,                        .formats = MAX98390_FORMATS,                },                .ops = &max98390_dai_ops,   }};

高通各平台之间也是差异的,snd_soc_dai_link结构体中仅codecs为snd_soc_dai_link_component,有些是cpu codecs platforms都是,所以在snd_soc_dai_link中使用了SND_SOC_DAILINK_REG,对应到SND_SOC_DAILINK_DEF/SND_SOC_DAILINK_DEFS定义的dai links kernel/msm-5.4/techpack/audio/asoc/msm-dailink.h

SND_SOC_DAILINK_DEFS(sec_mi2s_rx,DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-mi2s.2")),-DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),+   DAILINK_COMP_ARRAY(COMP_CODEC("max98390.1-0038", "max98390-aif1")),DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));static struct snd_soc_dai_link msm_mi2s_be_dai_links[]{                .name = LPASS_BE_SEC_MI2S_RX,                .stream_name = "Secondary MI2S Playback",                .no_pcm = 1,                .dpcm_playback = 1,                .id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,                .be_hw_params_fixup = msm_be_hw_params_fixup,                .ops = &msm_mi2s_be_ops,                .ignore_suspend = 1,                .ignore_pmdown_time = 1,                SND_SOC_DAILINK_REG(sec_mi2s_rx),},

高通的PA相关的属性,0:没使用WSA PA, 1: 单声道 2:双声道,项目上没有用到置为0就不研究了

qcom,wsa-max-devs = <0>;  qcom,wsa-devs = <0>;qcom,wsa-aux-dev-prefix = "SpkrMono";

硬件接口 SWR_TX_CLK SWR_TX_DATA0 SWR_TX_DATA1 SWR_RX_CLK SWR_RX_DATA0 SWR_TX_DATA1 对应LPI_GPIO 0-5

qcom,codec-max-aux-devs = <1>;qcom,codec-aux-devs = <&wcd937x_codec>;

snd_soc_of_parse_audio_routing解析存入of_dapm_routes:snd_soc_dapm_route,上述devicetree对应routes.sink routes.source(kcontrol为空是dirct直连),通过snd_soc_dapm_add_routes完成音频路径的注册,作用是将系统中注册的各种wideget:snd_soc_dapm_widget连接在一起

qcom,audio-routing =                      "TX DMIC0", "MIC BIAS1",              "MIC BIAS1", "Digital Mic0",

widget是通过snd_soc_dapm_new_controls注册的,四种widget的定义在include/sound/soc-dapm.h
(1)platform domain:SND_SOC_DAPM_MIC        (2)path domain:SND_SOC_DAPM_MICBIAS_E
(3)Codec domain:SND_SOC_DAPM_VMID        (4)stream domain:SND_SOC_DAPM_ADC_E
项目中使用wcd937x没有DMIC输入,提供MICBIAS,DMIC来自bolero

bolero_codec/hon4290-android12-vendor/vendor/qcom/opensource/audio-kernel/asoc/bengal.cstatic const struct snd_soc_dapm_widget msm_int_dapm_widgets[] = {    SND_SOC_DAPM_MIC("Digital Mic0", msm_dmic_event),    SND_SOC_DAPM_MIC("Digital Mic1", msm_dmic_event),}; vendor/qcom/opensource/audio-kernel/asoc/codecs/bolero/tx-macro.cstatic const struct snd_soc_dapm_widget tx_macro_dapm_widgets_common[]    SND_SOC_DAPM_ADC_E("TX DMIC0", NULL, SND_SOC_NOPM, 0, 0,  tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), wcd937x_codecvendor/qcom/opensource/audio-kernel/asoc/codecs/wcd937x/wcd937x.cstatic const struct snd_soc_dapm_widget wcd937x_dapm_widgets[] =        SND_SOC_DAPM_MIXER_E("ADC1_MIXER", SND_SOC_NOPM, 0, 0, adc1_switch, ARRAY_SIZE(adc1_switch), wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),        SND_SOC_DAPM_MICBIAS_E("MIC BIAS1", SND_SOC_NOPM, 0, 0, wcd937x_codec_enable_micbias,  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),

我们知道widget也是分起点终点的,不同的kernel版本会带来变化,SND_SOC_DAPM_MICBIAS_E(不能定义在route的起点和重点)变为SND_SOC_DAPM_SUPPLY录音时mic bias 无法自动打开问题,所以audio-routing的配置需要修改为

qcom,audio-routing ="TX DMIC0", "Digital Mic0","TX DMIC0", "MIC BIAS1",SND_SOC_DAPM_SUPPLY("MIC BIAS1", SND_SOC_NOPM, 0, 0, wcd938x_codec_enable_micbias,  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),

高通hal还有route相关的配置configs/bengal/mixer_paths_qrd.xml,在 bring up的时候,先使用tinymix/tinycap/tinyplay验证通路,再进行修改

tinymix "SEC_MI2S_RX Audio Mixer MultiMedia1" "1"tinymix "SEC_MI2S_RX SampleRate" "KHZ_48"tinymix "SEC_MI2S_RX Format" "S16_LE"tinymix "SEC_MI2S_RX Channels" "Two"tinyplay /data/test.wavtinymix "MultiMedia1 Mixer TX_CDC_DMA_TX_3" "1"tinymix "TX_CDC_DMA_TX_3 Channels" "One"tinymix "TX_AIF1_CAP Mixer DEC0" "1"tinymix "TX DMIC MUX0" "DMIC0"tinycap /data/test.wav 
<path name="deep-buffer-playback">-   <ctl name="RX_CDC_DMA_RX_1 Audio Mixer MultiMedia1" value="1" />+   <ctl name="SEC_MI2S_RX Audio Mixer MultiMedia1" value="1" /></path><path name="speaker">-   <ctl name="RX_CDC_DMA_RX_1 Channels" value="One" />-   <ctl name="RX_MACRO RX2 MUX" value="AIF2_PB" />-   <ctl name="RX INT2_1 MIX1 INP0" value="RX2" />-   <ctl name="AUX_RDAC Switch" value="1" />-   <ctl name="SpkrMono WSA_RDAC" value="Switch" />+   <ctl name="SEC_MI2S_RX SampleRate" value="KHZ_48"/>+   <ctl name="SEC_MI2S_RX Format" value="S16_LE" />+   <ctl name="SEC_MI2S_RX Channels" value="Two" /></path><path name="dmic1">    <ctl name="TX_CDC_DMA_TX_3 Channels" value="One" />    <ctl name="TX_AIF1_CAP Mixer DEC0" value="1" />    <ctl name="TX DMIC MUX0" value="DMIC0" /></path>static const struct snd_kcontrol_new msm_mi2s_snd_controls[] = {    SOC_ENUM_EXT("SEC_MI2S_RX SampleRate", sec_mi2s_rx_sample_rate,          mi2s_rx_sample_rate_get, mi2s_rx_sample_rate_put),    SOC_ENUM_EXT("SEC_MI2S_RX Format", mi2s_rx_format,  msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),    SOC_ENUM_EXT("SEC_MI2S_RX Channels", sec_mi2s_rx_chs,   msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),static struct dev_config mi2s_rx_cfg[] = {    [SEC_MI2S]  = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},};

最后再通过 tinymix “SEC_MI2S_RX Audio Mixer MultiMedia1” “1”理解一下playback的route

PCM->MultiMedia1 Playback->MM_DL1 -> MultiMedia1 ⊕ SEC_MI2S_RX Audio Mixer->SEC_MI2S_RX->Secondary MI2S Playback

MM_DL1:SND_SOC_DAPM_AIF_IN对应一个数字音频输入接口, SEC_MI2S_RX:SND_SOC_DAPM_AIF_OUT对应一个数字音频输出接口;dai widget和stream widget是通过stream name来匹配的,通过aif_name来指定,MultiMedia1 Playback(stream_name)连接FE DAI, Secondary MI2S Playback(stream_name)连接BE DAI;SEC_MI2S_RX Audio Mixer:SND_SOC_DAPM_MIXER是个mixer(可用于多个MultiMediax混合),MultiMedia1作为kcontrol,连接Source和Sink

来源地址:https://blog.csdn.net/qq_40405527/article/details/128385982

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android Qcom Audio入门学习

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android Qcom Audio入门学习

总结: Android Audio不简单呀,一个人摸索入门不容易的,研究了一段时间,感觉还不是很懂,但以下的知识对入门还是有帮助的。 Audio架构中的名词 FE(Front End) 提供pcm的设备信息,将数据从用户空间传输到音频后端,
2023-08-24

Android学习之Flux架构入门

Flux 架构介绍 Flux 架构 被Facebook使用来构建他们的客户端web应用。跟Clean Architecture一样,它不是为移动应用设计的,但是它的特性和简单可以让我们很好的在安卓项目中采用。Flux模式最大的特点是单向的数
2022-06-06

Android --Room入门分析与学习

Room Room 持久性库在 SQLite 的基础上提供了一个抽象层,让用户能够在充分利用 SQLite 的强大功能的同时,获享更强健的数据库访问机制Android数据持久层直接使用SQLite很麻烦,Google官方推出了Room, G
2022-06-06

Android DataBinding 基础入门(学习记录)

目录 一、DataBinding简介二、findViewById 和 DataBinding 原理及优缺点1. findViewById的优缺点2. DataBinding的优缺点 三、Android mvvm 之 data
2023-08-30

MySQL入门学习

数据库的好处 1.持久存到本地 2.可以实现结构化查询,方便管理 数据库相关概念 1.DB:数据库,保存一组有组织的数据的融通器 2.DBMS:数据库管理系统,又称数据库软件(产品),用于管理DB中的数据 3.
MySQL入门学习
2015-02-25

python入门学习

首先在官网下载好python3.6及以上的版本,根据自己的系统选择:没有显示64位的就是32位的安装包,选择蓝线的能够直接打开在控制台输入python,配置成功的图片如下:从IDLE打开python输入指令 print("I love py
2023-01-31

Node.js学习入门

开始之前,安利一本正在看的书《站在两个世界的边缘》,作者程浩,上帝丢给他太多理想,却忘了给他完成理想的时间。OK,有兴趣的可以看一看。 node.js如标题一样,我也是刚开始接触,大家一起学习,有不当的地方望指正。node.js是做什么的,
2022-06-04

Android的HTTP类库Volley入门学习教程

1. 什么是Volley 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据。Android系统中主要提供了两种方式来进行HTTP通信,HttpURLConnec
2022-06-06

Oracle入门学习四

上一篇:Oracle入门学习三学习视频:https://www.bilibili.com/video/BV1tJ411r7EC?p=35Oracle表连接:内连接、外连接。外连接分左连接、右连接。多表查询时,如果表之间没有条件关联,则会把所有匹配的结果查找出来
Oracle入门学习四
2017-05-24

Oracle入门学习五

学习视频: https://www.bilibili.com/video/BV1tJ411r7EC?p=35数据的完整性:保证插入表格的数据必须正确。包括实体完整性、区域完整性、引用完整性、自定义完整性。约束:约束的作用是为了保证数据的完整性,类型包括主键约束
Oracle入门学习五
2022-04-01

Oracle入门学习一

oracle的安装,用户授权,表格操作,数据类型,ddl表格,dml数据。下一篇:Oracle入门学习二学习视频:https://www.bilibili.com/video/BV1tJ411r7EC?p=15安装教程附带百度云安装包:https://blog
Oracle入门学习一
2018-09-30

Oracle入门学习二

上一篇:Oracle入门学习一学习视频:https://www.bilibili.com/video/BV1tJ411r7EC?p=15算术运算符:+ - * /逻辑运算符:and or not比较运算符:“=”、“”、“=”、“”、“!=”。注意“=”是等于
Oracle入门学习二
2014-07-13

Oracle入门学习三

上一篇:Oracle入门学习二学习视频:https://www.bilibili.com/video/BV1tJ411r7EC?p=26字符串函数:length、upper、lower、initcap、 concat、instr、replace。-- dual
Oracle入门学习三
2021-08-20

Python入门学习(六)

在熟悉了Python中常用的一些内置函数, 那接下来我们定义一个自己的函数吧def add(x, y): return x + y函数函数语法def functonname(parameters): ... return
2023-01-31

Django 入门学习(3)

在例4的基础上,我希望直接保存数据到数据库中。 Django自带了一个sqlite的数据库,已经配置好了 可以直接使用。使用方式和sqlalchemy类似,相当于一个内置的ORM框架。settings.py 默认已经绑定了sqlite3DA
2023-01-31

Oracle入门学习六

事务:把一组操作看做一个工作单元,要么都执行,要么都不执行。dml操作才有事务,查询没有事务。开始事务:从上一次的事务结束之后,从第一次dml操作,就自动开启了事务提交事务:commit回滚事务:rollbackcreate table bank(id num
Oracle入门学习六
2021-12-10

Android app开发中的Fragment入门学习教程

在Android3.0上开始引入了一个新概念叫Fragment。它有自己的布局文件,可以作为组件排布,也可以相互组合去实现不同的布局显示。使用Fragment可以重复利用代码,并且可以满足不同设备尺寸的需求。Fragment不能单独存在,只
2022-06-06

MNIST机器学习入门

当我们开始学习编程的时候,第一件事往往是学习打印"Hello World"。就好比编程入门有Hello World,机器学习入门有MNIST。MNIST是一个入门级的计算机视觉数据集,它包含各种手写数字图片。它也包含每一张图片对应的标签,告
2023-01-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录